如何使用python更快地计算指数移动平均值?
我正忙于构建回溯测试软件,但我在创建指数移动平均线时遇到了麻烦。我使用for循环成功地创建了它,但每个要测试的符号运行大约需要20秒(太长) 如果有人有任何建议,我正试图找到一个更快的解决方案 我当前的代码看起来像这样,但它不会产生正确的结果如何使用python更快地计算指数移动平均值?,python,pandas,numpy,finance,quantitative-finance,Python,Pandas,Numpy,Finance,Quantitative Finance,我正忙于构建回溯测试软件,但我在创建指数移动平均线时遇到了麻烦。我使用for循环成功地创建了它,但每个要测试的符号运行大约需要20秒(太长) 如果有人有任何建议,我正试图找到一个更快的解决方案 我当前的代码看起来像这样,但它不会产生正确的结果 def exponential_moving_average(df, period): # Create a copy of original dataframe to work with. dataframe = df.copy()
def exponential_moving_average(df, period):
# Create a copy of original dataframe to work with.
dataframe = df.copy()
dataframe['EMA'] = dataframe['Close'].ewm( span = period,
adjust = False,
min_periods = period,
ignore_na = True
).mean()
return dataframe['EMA']
此方法位于Indicators类中,输入采用以下内容
是每天的df
和开盘价、高价、低价
以及任何其他用于回溯测试和预测的指标收盘价
是必须计算指数移动平均数的“窗口”或天数period
df
值的代码段:
symbol Open High Low Close ATR slow_ma
Date
2010-01-03 EURUSD 1.43075 1.43369 1.43065 1.43247 NaN NaN
2010-01-04 EURUSD 1.43020 1.44560 1.42570 1.44120 NaN NaN
2010-01-05 EURUSD 1.44130 1.44840 1.43460 1.43650 NaN NaN
2010-01-06 EURUSD 1.43660 1.44350 1.42820 1.44060 NaN NaN
2010-01-07 EURUSD 1.44070 1.44470 1.42990 1.43070 NaN NaN
2010-01-08 EURUSD 1.43080 1.44380 1.42630 1.44160 NaN NaN
2010-01-10 EURUSD 1.44245 1.44252 1.44074 1.44110 NaN NaN
2010-01-11 EURUSD 1.44280 1.45560 1.44080 1.45120 NaN NaN
2010-01-12 EURUSD 1.45120 1.45450 1.44530 1.44840 NaN NaN
2010-01-13 EURUSD 1.44850 1.45790 1.44570 1.45100 NaN 1.442916
2010-01-14 EURUSD 1.45090 1.45550 1.44460 1.44990 NaN 1.444186
2010-01-15 EURUSD 1.45000 1.45110 1.43360 1.43790 NaN 1.443043
2010-01-17 EURUSD 1.43597 1.43655 1.43445 1.43480 NaN 1.441544
2010-01-18 EURUSD 1.43550 1.44000 1.43340 1.43830 NaN 1.440954
2010-01-19 EURUSD 1.43820 1.44130 1.42520 1.42870 NaN 1.438726
以下是slow\u ma
(10天期间)的预期结果
我更改了第一个数据帧的值,以便它显示用于计算
slow\u ma
值的数字
这是我在Stackoverflow上的第一篇文章,所以问问是否有什么不清楚的地方
如何更快地使用python计算指数移动平均数?
在旧的2.6[GHz]i5设备上,在<50[us]
下为您的大小数据/周期提供的速度可实现
第0步:使结果(流程)通过质量保证 拥有快速但错误的数据具有负附加值,对吗 如果您使用的是“硬连线”
.ewm()
方法,如果可以使用不同的dataframe['Close']
列处理模式,则只能重新读取其参数化选项
作为快速检查:
aPV = [ 1.43247, # borrowed from dataframe['Close']
1.44120,
1.43650,
1.44060, 1.43070, 1.44160, 1.44110, 1.45120, 1.44840,
1.45100, 1.44990, 1.43790, 1.43480, 1.43830, 1.42870,
]
|>>> QuantFX.numba_EMA_fromPrice2( N_period = 10,
aPriceVECTOR = QuantFX.np.array( aPV )
)
array([
1.43247 ,
1.43405727,
1.4345014 ,
1.43561024,
1.43471747,
1.43596884,
1.43690178,
1.43950145,
1.44111937,
1.44291585,
1.44418569,
1.44304284,
1.44154414,
1.4409543 ,
1.43872624
]
)
与上面第一个表中的值(即低于LSD的2个数量级)相比,存在一些数值表示差异
第1步:调整(QA确认)处理以提高速度
在这个阶段,很大程度上取决于使用的外部环境
从cythonize()可以预期最佳结果,但评测可能会在运行中显示一些惊喜
无需将处理移到cython代码中,您就可以在全球使用float64
-s而不是float32
-s(在类似EMA深度上被削掉了一些110~200[us]
),矢量化就地分配(约2倍加速,从~100[us]
到~50[us]
在更好地结合矢量内存分配(结果矢量及其矢量化值处理)和最佳情况下,如果数学重新公式化可以帮助跳过一些纯粹的“机械”操作
然而,所有的加速技巧都依赖于使用的工具——如果是纯的
,或者numpy+numba
(这可能会对EMA这类毫无疑问的琐碎处理产生负面影响——对“杰克逊博士”来说,没有多少数学上的肉)或者是cython的优化解决方案,因此如果要获得最佳结果,必须在目标CPU环境中进行评测
正在尝试找到更快的解决方案 在给定的
[SPACE]
-域数据规模(window==10
,aPriceVECTOR.shape[0]~15
)上,更新您的帖子,说明您的预期目标加速比,或者更好地说明所述问题的[TIME]
-域中的每次呼叫处理成本,如果目标代码执行平台有一些硬件/CPU/缓存层次结构组合约束或没有,因为构建backtester平台实际上非常强调任何和所有代码设计+代码执行效率低下
鉴于EMA相当有效,工具可能会获得约4倍的加速 QuantFX的故事已经从
~42000[美国]
下降到~21000[美国]
,没有numba
/JIT工具,只需重新制定和优化内存向量处理(使用人工大小的工作负载,处理aPV[:10000]块)
接下来,运行时间下降到~10600[us]
,使用原样的Cpython代码库,只要有自动Cythonise的权限,就可以使用pyximport导入-ed代码:
pass; import pyximport
pass; pyximport.install( pyimport = True )
from QuantFX import numba_EMA_fromPrice2
...
因此,可以获得速度
~45~47[美国]
在普通2.6[GHz]i5设备上,针对您的大小数据aPV[:15]
,周期=10
如果坚持使用pandas
数据框架工具和方法,您的表现主要掌握在pandas团队手中,在设计折衷方面没有太多需要做,这必须在速度和普遍性之间的两难境地中完成。你能分享一个结果错误的数据帧片段吗(也不确定输入中的span=period
是否有意义)根据我的理解,span是公式α=2/(span+1),它是加权均线的乘数,span是我想要计算的时段。例如,它也可以写为(2/(选定时间段+1))=(2/(10+1))=0.1818(18.18%)。对于您提供的样本,slow\u ma
的值是多少您在期间使用的值是多少?我已经更改了第一个数据帧的值,以显示用于计算慢速的值,第二个数据帧包含预期结果。我用来缩短数据帧的时间是10天
|>>> ( QuantFX.numba_EMA_fromPrice2( 10,
QuantFX.np.array( aPV )
)
- QuantFX.np.array( slow_EMA_1 )# values borrowed from Table 1 above
)
array([ nan,
nan,
nan,
nan,
nan,
nan,
nan,
nan,
nan,
-1.50656152e-07,
-3.05082306e-07,
-1.58703705e-07,
1.42878787e-07,
2.98719007e-07,
2.44406460e-07
]
)
pass; import pyximport
pass; pyximport.install( pyimport = True )
from QuantFX import numba_EMA_fromPrice2
...