Python更新数据框的更快方法

时间:2020-03-25 01:10:13

标签: python pandas dataframe

我正在尝试测试三种不同股票的买卖。我创建了一个计划插入AI系统的类,并尝试找到一种策略。目前有效。您可以购买[symbol],出售[symbol],然后继续。有些功能花费的时间太长。我相信这是一种更快,更Python-y的方式。我的背景是JavaScript。

我正在使用一个数据框来存储交易。未平仓交易没有closeTimeStamp。利润是sell_price-平仓交易的buy_price或利润是sell_price-空头交易(空头)的current_quote利润是current_quote-多头空单交易的buy_price。更新了holdings_with_quotes之后,我可以对利润列求和,就可以得到未平仓和平仓交易的当前值。

    self.trades = pd.DataFrame(columns=['symbol', 'buy_price', 'sell_price', 'current_quote', 'openTimeStamp', 'closeTimeStamp', 'profit', 'multiplier'])

此功能需要花费大量时间。

  def update_holdings_with_quotes(self):
    start = time.time()
    if self.current_contracts > 0:
      quotes = self.quotes
      for symbol in ['/ES', '/NQ', '/YM']:
      # for symbol in self.trades['symbol']:
        current_price = self.quotes.loc[symbol]['lastPriceInDouble']
        multiplier = self.quotes.loc[symbol]['futureMultiplier']
        self.trades.loc[self.trades['closeTimeStamp'].isnull() & (self.trades['symbol'] == symbol), 'current_quote'] = current_price
        self.trades.loc[self.trades['closeTimeStamp'].isnull() & (self.trades['symbol'] == symbol) & (self.trades['action'] == Actions.BUY), 'profit'] =  (current_price - self.trades['buy_price']) * multiplier
        self.trades.loc[self.trades['closeTimeStamp'].isnull() & (self.trades['symbol'] == symbol) & (self.trades['action'] == Actions.SELL), 'profit'] =  (self.trades['sell_price'] - current_price)  * multiplier

      self.current_value = self.initial_value + self.trades['profit'].sum()
      self.current_gain = self.current_value - self.initial_value
    print("update_holdings_with_quotes time: {}".format(time.time() - start))

基本上,如果交易没有closeTimeStamp a.k.a,我将遍历三个引号并在数据框中设置值。我尝试使用静态符号数组,但这并没有加快速度。

我可以使用数据框以外的其他东西。我只是使用它,因为我认为这会有所帮助。

***我根据建议使用两个数据框而不是一个来编辑函数。一种用于开放交易,另一种用于封闭交易。那没有太大帮助。

  def update_holdings_with_quotes(self):
    start = time.time()
    if self.current_contracts > 0:
      quotes = self.quotes
      for symbol in ['/ES', '/NQ', '/YM']:
      # for symbol in self.trades['symbol']:
        current_price = self.quotes.loc[symbol]['lastPriceInDouble']
        multiplier = self.quotes.loc[symbol]['futureMultiplier']
        self.open_trades.loc[(self.open_trades['symbol'] == symbol), 'current_quote'] = current_price
        self.open_trades.loc[(self.open_trades['symbol'] == symbol) & (self.open_trades['action'] == Actions.BUY), 'profit'] =  (current_price - self.open_trades['buy_price']) * multiplier
        self.open_trades.loc[(self.open_trades['symbol'] == symbol) & (self.open_trades['action'] == Actions.SELL), 'profit'] =  (self.open_trades['sell_price'] - current_price)  * multiplier

      self.current_value = self.initial_value + self.open_trades['profit'].sum() + self.closed_trades['profit'].sum()
      self.current_gain = self.current_value - self.initial_value
      # self.logger.info('initial_value={} current_value={} current_contracts={}'.format(self.initial_value, self.current_value, self.current_contracts))
      self.check_status()
    print("update_holdings_with_quotes time: {}".format(time.time() - start))

1 个答案:

答案 0 :(得分:0)

这是它变慢的部分:

    self.trades.loc[self.trades['closeTimeStamp'].isnull() & (self.trades['symbol'] == symbol), 'current_quote'] = current_price
    self.trades.loc[self.trades['closeTimeStamp'].isnull() & (self.trades['symbol'] == symbol) & (self.trades['action'] == Actions.BUY), 'profit'] =  (current_price - self.trades['buy_price']) * multiplier
    self.trades.loc[self.trades['closeTimeStamp'].isnull() & (self.trades['symbol'] == symbol) & (self.trades['action'] == Actions.SELL), 'profit'] =  (self.trades['sell_price'] - current_price)  * multiplier

尤其是每个循环多次要求遍历整个“交易” DataFrame,以仅用于建立索引:

self.trades['closeTimeStamp'].isnull()
self.trades['symbol'] == symbol

一种前瞻性的解决方案是将DataFrame trades分为两个closed_tradesopen_trades。后者应随时间推移显着减小,并极大地加快查找速度。随着跟踪库存的增长,明智的做法是通过子类在符号之间进一步划分。

一种替代方法是跟踪数组中未平仓合约的索引。每次添加交易时,只需将maxIndex+1添加到数组中即可。如果您平仓,请从列表中删除该指数。只要确保不重新编制索引即可。

import numpy as np
ix_open = np.array([...])
ix_closed = np.array([...])

# after closing a few trades:
ix_open = np.setdiff1d(ix_open, ix_closed)