[英]Improving Pandas iteration performance
我有以下代码,它获取单个资产的历史价格并计算预测,并计算如果您真的根据预测投资您的资金,您将如何公平。 用金融术语来说,这是一个回溯测试。
主要问题是它非常慢,我不确定改进它的正确策略是什么。 我需要运行数千次,因此需要一个数量级的加速。
我应该从哪里开始寻找?
class accountCurve():
def __init__(self, forecasts, prices):
self.curve = pd.DataFrame(columns=['Capital','Holding','Cash','Trade', 'Position'], dtype=float)
forecasts.dropna(inplace=True)
self.curve['Forecast'] = forecasts
self.curve['Price'] = prices
self.curve.loc[self.curve.index[0],['Capital', 'Holding', 'Cash', 'Trade', 'Position']] = [10000, 0, 10000, 0, 0]
for date, forecast in forecasts.iteritems():
x=self.curve.loc[date]
previous = self.curve.shift(1).loc[date]
if previous.isnull()['Cash']==False:
x['Cash'] = previous['Cash'] - previous['Trade'] * x['Price']
x['Position'] = previous['Position'] + previous['Trade']
x['Holding'] = x['Position'] * x['Price']
x['Capital'] = x['Cash'] + x['Holding']
x['Trade'] = np.fix(x['Capital']/x['Price'] * x['Forecast']/20) - x['Position']
编辑:
要求的数据集:
价格:
import quandl
corn = quandl.get('CHRIS/CME_C2')
prices = corn['Open']
预测:
def ewmac(d):
columns = pd.Series([2, 4, 8, 16, 32, 64])
g = lambda x: d.ewm(span = x, min_periods = x*4).mean() - d.ewm(span = x*4, min_periods=x*4).mean()
f = columns.apply(g).transpose()
f = f*10/f.abs().mean()
f.columns = columns
return f.clip(-20,20)
forecasts=ewmac(prices)
我建议在for
循环中使用 numpy 数组而不是数据框。 它通常会显着提升速度。
所以代码可能如下所示:
class accountCurve():
def __init__(self, forecasts, prices):
self.curve = pd.DataFrame(columns=['Capital','Holding','Cash','Trade', 'Position'], dtype=float)
# forecasts.dropna(inplace=True)
self.curve['Forecast'] = forecasts.dropna()
self.curve['Price'] = prices
# helper np.array:
self.arr = np.array(self.curve)
self.arr[0,:5] = [10000, 0, 10000, 0, 0]
for i in range(1, self.arr.shape[0]):
this = self.arr[i]
prev = self.arr[i-1]
cash = prev[2] - prev[3] * this[6]
position = ...
holding = ...
capital = ...
trade = ...
this[:5] = [capital, holding, cash, trade, position]
# back to data frame:
self.curve[['Capital','Holding','Cash','Trade', 'Position']] = self.arr[:,:5]
# or maybe this would be faster:
# self.curve[:] = self.arr
我不太明白if previous.isnull()['Cash']==False:
。 看起来好像previous['Cash']
从来没有为空,除了第一行 - 但你更早设置了第一行。
此外,您可以考虑在课堂之外执行forecasts.dropna(inplace=True)
。 如果它最初是一个数据框,您将运行它一次,而不是为每一列重复它。 (我是否正确理解您将单列forecasts
输入到课程中?)
我建议的下一步是使用一些行分析器来查看您的代码大部分时间花在哪里,并尝试优化这些瓶颈。 如果您使用 ipython,那么您可以尝试运行%prun
或%lprun
。 例如
%lprun -f accountCurve.__init__ A = accountCurve(...)
将为您的__init__
每一行生成统计信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.