如何并行化基于机器学习模型的交易策略回测?
How to parallelize a backtesting for a trading strategy based on a machine learning model?
为了回测基于机器学习模型的交易策略,我想并行计算模型的再训练过程。
Now my question is:
是否有机会提高我的算法速度?
它是在 python 中使用 scikit-learn 实现的。回测流程定义如下:
- 在 900 个(前三年)数据点上训练模型
- 预测下一天 t+1
- 在下一个数据点 t+1 重新训练模型
- 再次用模型对第 t+2 天进行预测
- 重新训练模型....
- 做出预测...
简单地说,对下一个数据点进行预测并在该数据点上重新训练模型。然后这样做直到当天(最后一个数据点)。对于某些股票预测,这可能多达 5000 个数据点,这意味着通过使用在前 900 个数据点上训练的模型开始此回测过程,我需要重新训练和预测模型 4100 次。
为了并行化我正在使用多处理的过程。我有机会使用一台提供 40 CPU 内核的服务器。所以我正在做的是:
- 将数据点4100分成40份
- 在运行1部分程序的每个内核上启动一个进程
- 完成程序后,将结果写入磁盘
- 收集每个结果并将其放在一起
Python代码:
pool = Pool()
results = []
for i in range(len(parts)):
try:
result = pool.apply_async(classify_parts,[parts[i], parts[i+1]])
results.append(result)
except IndexError:
continue
for result in results:
result.get()
方法classify_parts,启动给定范围的过程。
例如,如果我有 500 个数据点并将通过在 100 个数据点上训练模型来开始整个回溯测试,我还有 400 个数据点(天)用于回溯测试,这意味着:
- 将 400 个数据点分成 40 个部分 [10,20,30,...,380,390,400]
- 在每个内核上启动一个进程:
classify_parts( 10, 20 )
, ..., classify_parts( 390, 400 )
- 从磁盘收集结果并将它们放在一起
希望我能清楚地说明我的概念。
So my biggest question is, if there is another more efficient way of doing backtesting with a machine learning model, that is retrained on every next data point ( day )? Because with this concept, one backtesting procedure for 5000 data points runs more than 10 minutes.
也许渐进/在线学习是正确的选择?
起初,这不是并行化进程调度。
如果有疑问,可以重新审视有关 SERIAL、PARALLEL 和 "just"-CONCURRENT[ 的理论细节=126=] 在进一步阅读之前进行进程调度。
使用简单的英语
事情可能会进入 SERIAL 操作模式(按原则(按意图)或某种资源限制)。如果要在键盘上键入单词“parallel
”,字母 p
,下一个a
,下一个r
...等必须连续触摸,一个接一个,否则输入过程无法提供保证的正确结果 - 即单词“parallel
" 在屏幕上(假设我们忘记了使用 Shift
键的机会,为了这个例子的清晰度)。
任何人都可以测试,如果一个人试图同时按下所有键,或者成对按下,或者当一只猫站在你的键盘前时,会产生什么……欢迎所有额外的想法-在实验中。
串行进程不能更快
在任何其他情况下,除了通过降低进程间传输延迟来获得更快的处理资源 and/or(或者如果存在一种新的、更智能的算法并且为程序员所熟知并且另外显示在可用资源上实施是可行的)。
什么是真正的并行进程?
另一方面,有些事情必须组织起来,以便恰好在光谱的另一端发生——如果所有事情都必须同时开始+发生+结束,否则结果来自过程被认为是错误的。可以举什么例子?
想象一些视觉上简单的“可读”示例 - 红箭的表演 - 一组 9 架喷气式飞机,显示高领航率的数字和演习
或 Frecce Tricolori
所有飞机同时以给定(相同)的方式移动,否则可爱的表演将失败。
想象一场必须举行的音乐会。这正是最终的 PARALLEL
过程,如果不是
,人们会立即意识到那将是多么具有破坏性
想象一个具有多个自由度的机器人控制系统,其中所有运动都必须执行,并且必须保持在闭环控制下 [actor - detector -执行器]子系统同步,协调所有几个编程控制的轴。系统必须将所有 NC 轴作为一个并行过程一起控制——否则机器人手臂将永远无法跟随黑线——the defined, curved, spatio-temporal trajectory in +4-D space ( best to view in real-time ).
机器人控制的例子表明,我们离特技飞行或交响乐的例子越远,我们有一些直接的经验(或者一个人的想象力可以提供一些理解),并行过程调度可能看起来更难感知或意识到,但交响乐似乎是最好的提醒,当质疑一个问题是否确实是一个真正的平行问题时。
问问你自己,如果只有一半的合奏在适当的时候以 19:00 的速度开始演奏会发生什么,或者如果一些小提琴以更快的速度演奏会发生什么。 .. 或者会发生什么,如果演奏者将开始按顺序只演奏一个音符并让 his/her 左侧邻居演奏 his/her 音符,等待演奏顺序回到同一位演奏者在音乐会中演奏 his/her 下一个音符。正确,那将是纯串行调度。 )
那么,40-CPU 核是否可以以某种方式加速我的问题?
问题还是要看处理。
如果学习方法(在未公开的 MCVE 中)具有内置依赖性,例如,如果 classify_parts( 20, 30 )
需要获得一些输入或一条信息,从“以前的" 一步 classify_parts( 10, 20 )
,那么答案是否定的。
如果学习方法是独立的,在上面定义的意义上,那么就有机会将过程安排为“公正”-CONCURRENT 并受益于有更多“自由”通道的事实高速公路允许汽车 运行 不仅在一条车道上,而且允许一辆汽车在从头到尾的路上超越另一辆较慢的汽车。橄榄球队可以“更快”地从城市 A 移动到城市 B,如果城市 A 体育场有 2 或 3 或更多 4 座汽车可用,而不是只有 1 辆并且必须来回移动成功将所有玩家转移到B市
接下来,即使有足够的车可以让所有玩家都搬到城市 B,如果从 A 到 B 只有一条车道,而对面的车流量很大,那么持续时间会很长从 B 到 A 的方向(不允许超车)和一辆拖拉机,也从 A 到 B,但速度为 1 英里/小时。
警告:(如果要搜索真正的快速处理,则越多越好)
尽管如此,即使存在上述 none 的“外部”障碍,也必须非常小心,不要失去“更大”的机器 + “更宽”的高速公路(更多可用资源)用于 “仅”-CONCURRENT 进程调度。
是的,这里的问题与编程工具有关。
Python 对快速原型制作有很大帮助,但要注意全局解释器锁 (GIL) 代码执行的影响。
在您的情况下,使用 40 个线程的 Pool()
可能看起来很有吸引力,但仍会等待 GIL-acquisition/release 并且所有工作都将完成再次变成 SERIAL
,只是因为没有注意到 Pool()
上 python 线程的已知 GIL 机制。
是的,还有其他更有前途的替代方案,例如 ThreadPool()
等,但不仅与代码相关的 GIL 步进正在破坏您加速的努力进程的速度以及共享数据结构是一个需要注意和避免的问题。此外,Pool()
天真复制的环境可能会超出一个人的系统 RAM 容量,交换机制将产生这种加速进程的尝试,完全无法使用。 什么都不分享,否则你加速处理的梦想将在共享机制上失败,你又回到了第一广场。
最好的方法是将代码设计为具有零共享、非阻塞(MEM、IO)操作的独立进程。
鉴于以上所有内容,40-CPU-核心可能有助于加速“恰好”-CONCURRENT 过程。
为了回测基于机器学习模型的交易策略,我想并行计算模型的再训练过程。
Now my question is:
是否有机会提高我的算法速度?
它是在 python 中使用 scikit-learn 实现的。回测流程定义如下:
- 在 900 个(前三年)数据点上训练模型
- 预测下一天 t+1
- 在下一个数据点 t+1 重新训练模型
- 再次用模型对第 t+2 天进行预测
- 重新训练模型....
- 做出预测...
简单地说,对下一个数据点进行预测并在该数据点上重新训练模型。然后这样做直到当天(最后一个数据点)。对于某些股票预测,这可能多达 5000 个数据点,这意味着通过使用在前 900 个数据点上训练的模型开始此回测过程,我需要重新训练和预测模型 4100 次。
为了并行化我正在使用多处理的过程。我有机会使用一台提供 40 CPU 内核的服务器。所以我正在做的是:
- 将数据点4100分成40份
- 在运行1部分程序的每个内核上启动一个进程
- 完成程序后,将结果写入磁盘
- 收集每个结果并将其放在一起
Python代码:
pool = Pool()
results = []
for i in range(len(parts)):
try:
result = pool.apply_async(classify_parts,[parts[i], parts[i+1]])
results.append(result)
except IndexError:
continue
for result in results:
result.get()
方法classify_parts,启动给定范围的过程。 例如,如果我有 500 个数据点并将通过在 100 个数据点上训练模型来开始整个回溯测试,我还有 400 个数据点(天)用于回溯测试,这意味着:
- 将 400 个数据点分成 40 个部分 [10,20,30,...,380,390,400]
- 在每个内核上启动一个进程:
classify_parts( 10, 20 )
, ...,classify_parts( 390, 400 )
- 从磁盘收集结果并将它们放在一起
希望我能清楚地说明我的概念。
So my biggest question is, if there is another more efficient way of doing backtesting with a machine learning model, that is retrained on every next data point ( day )? Because with this concept, one backtesting procedure for 5000 data points runs more than 10 minutes.
也许渐进/在线学习是正确的选择?
起初,这不是并行化进程调度。
如果有疑问,可以重新审视有关 SERIAL、PARALLEL 和 "just"-CONCURRENT[ 的理论细节=126=] 在进一步阅读之前进行进程调度。
使用简单的英语
事情可能会进入 SERIAL 操作模式(按原则(按意图)或某种资源限制)。如果要在键盘上键入单词“parallel
”,字母 p
,下一个a
,下一个r
...等必须连续触摸,一个接一个,否则输入过程无法提供保证的正确结果 - 即单词“parallel
" 在屏幕上(假设我们忘记了使用 Shift
键的机会,为了这个例子的清晰度)。
任何人都可以测试,如果一个人试图同时按下所有键,或者成对按下,或者当一只猫站在你的键盘前时,会产生什么……欢迎所有额外的想法-在实验中。
串行进程不能更快
在任何其他情况下,除了通过降低进程间传输延迟来获得更快的处理资源 and/or(或者如果存在一种新的、更智能的算法并且为程序员所熟知并且另外显示在可用资源上实施是可行的)。
什么是真正的并行进程?
另一方面,有些事情必须组织起来,以便恰好在光谱的另一端发生——如果所有事情都必须同时开始+发生+结束,否则结果来自过程被认为是错误的。可以举什么例子?
想象一些视觉上简单的“可读”示例 - 红箭的表演 - 一组 9 架喷气式飞机,显示高领航率的数字和演习
或 Frecce Tricolori
所有飞机同时以给定(相同)的方式移动,否则可爱的表演将失败。
想象一场必须举行的音乐会。这正是最终的
,人们会立即意识到那将是多么具有破坏性PARALLEL
过程,如果不是想象一个具有多个自由度的机器人控制系统,其中所有运动都必须执行,并且必须保持在闭环控制下 [actor - detector -执行器]子系统同步,协调所有几个编程控制的轴。系统必须将所有 NC 轴作为一个并行过程一起控制——否则机器人手臂将永远无法跟随黑线——the defined, curved, spatio-temporal trajectory in +4-D space ( best to view in real-time ).
机器人控制的例子表明,我们离特技飞行或交响乐的例子越远,我们有一些直接的经验(或者一个人的想象力可以提供一些理解),并行过程调度可能看起来更难感知或意识到,但交响乐似乎是最好的提醒,当质疑一个问题是否确实是一个真正的平行问题时。
问问你自己,如果只有一半的合奏在适当的时候以 19:00 的速度开始演奏会发生什么,或者如果一些小提琴以更快的速度演奏会发生什么。 .. 或者会发生什么,如果演奏者将开始按顺序只演奏一个音符并让 his/her 左侧邻居演奏 his/her 音符,等待演奏顺序回到同一位演奏者在音乐会中演奏 his/her 下一个音符。正确,那将是纯串行调度。 )
那么,40-CPU 核是否可以以某种方式加速我的问题?
问题还是要看处理。
如果学习方法(在未公开的 MCVE 中)具有内置依赖性,例如,如果 classify_parts( 20, 30 )
需要获得一些输入或一条信息,从“以前的" 一步 classify_parts( 10, 20 )
,那么答案是否定的。
如果学习方法是独立的,在上面定义的意义上,那么就有机会将过程安排为“公正”-CONCURRENT 并受益于有更多“自由”通道的事实高速公路允许汽车 运行 不仅在一条车道上,而且允许一辆汽车在从头到尾的路上超越另一辆较慢的汽车。橄榄球队可以“更快”地从城市 A 移动到城市 B,如果城市 A 体育场有 2 或 3 或更多 4 座汽车可用,而不是只有 1 辆并且必须来回移动成功将所有玩家转移到B市
接下来,即使有足够的车可以让所有玩家都搬到城市 B,如果从 A 到 B 只有一条车道,而对面的车流量很大,那么持续时间会很长从 B 到 A 的方向(不允许超车)和一辆拖拉机,也从 A 到 B,但速度为 1 英里/小时。
警告:(如果要搜索真正的快速处理,则越多越好)
尽管如此,即使存在上述 none 的“外部”障碍,也必须非常小心,不要失去“更大”的机器 + “更宽”的高速公路(更多可用资源)用于 “仅”-CONCURRENT 进程调度。
是的,这里的问题与编程工具有关。
Python 对快速原型制作有很大帮助,但要注意全局解释器锁 (GIL) 代码执行的影响。
在您的情况下,使用 40 个线程的 Pool()
可能看起来很有吸引力,但仍会等待 GIL-acquisition/release 并且所有工作都将完成再次变成 SERIAL
,只是因为没有注意到 Pool()
上 python 线程的已知 GIL 机制。
是的,还有其他更有前途的替代方案,例如 ThreadPool()
等,但不仅与代码相关的 GIL 步进正在破坏您加速的努力进程的速度以及共享数据结构是一个需要注意和避免的问题。此外,Pool()
天真复制的环境可能会超出一个人的系统 RAM 容量,交换机制将产生这种加速进程的尝试,完全无法使用。 什么都不分享,否则你加速处理的梦想将在共享机制上失败,你又回到了第一广场。
最好的方法是将代码设计为具有零共享、非阻塞(MEM、IO)操作的独立进程。