📝

Draft article

This draft is visible to admins and superusers only. Sign in with an authorized account.

← 返回文章列表
July 7, 2026
5 分钟阅读

GPU 何时才划算:参数扫描的屋顶线,一个 167x 头条其实是 27x 算法 × 6.2x 硬件

GPU 何时才划算:参数扫描的屋顶线,一个 167x 头条其实是 27x 算法 × 6.2x 硬件
#算法交易
#回测
#性能
#gpu
#屋顶线
#优化
Part 9 of 10 · Collection
High-Performance Backtest Engines

"回测无幻觉"系列文章。

速度阶梯一文刻意收在了一个不太令人满意的地方。我们把一个 80 组合的参数扫描,在一台笔记本 CPU 上从 pandas 的 69.9 秒压到并行 numba 的 0.23 秒——实测 298x——然后论证说 GPU 并不是那块缺失的拼图。评论区没有平静地接受这个结论,而它也理应不接受。"不是缺失的拼图"是一个关于某一种工作负载、某一个规模的断言。它不是自然规律。所以这篇文章做了件诚实的事:把 GPU 摆上试验台。

结论不是一个判决,而是一条曲线。GPU 相对 CPU 的领先幅度不是一个你能印在幻灯片上的单一数字;它是你每次调用交给它多少工作量的函数。在我们的多时间框架指标预计算上,GPU 相对 CPU 引擎的加速比,从**每次只要它算一个参数组合时的 54.5x,一路升到一次要它算 61 个时的 359.6x。**同一个内核、同一份数据、同一套硬件——唯一改变的只是批量。一个只报告其中一个数字、隐去另一个的基准测试,测的不是 GPU,而是在挑选一个头条。

而且即便是 359.6x,也不是它看上去的样子。把它剥开,一个 **167x 的多时间框架大头条会分解为 27x 的算法——一次同样让 CPU 快 27x 的改写——乘以 6.2x 的真实硬件。**那 27x 不是 GPU 做的,是数学做的。这篇文章讲的就是把这两者区分开来,因为把它们混为一谈,正是一块 $2,000 的显卡被卖出去、去解决一个 git commit 本可以免费解决的问题的方式。

数据来源:下文所有数字都在一台 Apple M2 Max 上实测,通过 MLX 在 Metal GPU 上跑 fp32,对比在十二个 CPU 线程上跑 fp64 的 numba,来自我们的 engine_multitf_gpu.pybench_param_sweep.py 基准脚本,每一项都由一道等价性校验把关,确认 GPU 路径与 CPU 路径产出相同的交易。这一篇没有公开的配套论文——脚本本身就是记录。

这是一个屋顶线问题,不是一次基准测试

一张屋顶线图:右侧是一条平坦的计算天花板,左侧是一道陡峭的内存带宽斜坡,一个代表批量的圆点正从被开销主导的角落沿斜坡向脊点攀爬

"GPU 到底快多少"之所以没有单一答案,原因就在于屋顶线模型(Williams、Waterman 与 Patterson,2009)。一个处理器可达到的性能同时被两条天花板封顶:一条平坦的,由峰值算力(FLOP/s)决定;一条倾斜的,由内存带宽乘以算术强度——你每搬运一字节数据所做的有用运算次数——决定。每字节廉价的工作待在倾斜天花板之下,受带宽限制;每字节丰厚的工作够到平坦天花板,属于计算密集型。GPU 的平坦天花板高高凌驾于 CPU 之上,但它那条倾斜天花板,以及至关重要的每次调用的固定成本,却没有那么优雅地随之降下来。

对一次参数扫描来说,还有第三个项主导着图表的左侧:**启动与传输开销。**每一次 GPU 调用都要付出一个大致固定的代价——分发内核,把输入搬过(在 Apple Silicon 上是统一的、但并非免费的)内存边界,再把结果搬回来。把一批 BB 个组合的墙钟时间建模为

Tgpu(B)=O+bB,Tcpu(B)=aBT_{\text{gpu}}(B) = O + b\,B, \qquad T_{\text{cpu}}(B) = a\,B

其中 OO 是那个固定开销,bb 是 GPU 每个组合的边际成本,aa 是 CPU 的。于是加速比为

S(B)=aBO+bB  B  ab.S(B) = \frac{a\,B}{O + b\,B} \;\xrightarrow{B \to \infty}\; \frac{a}{b}.

这一个分式就解释了整篇文章。在 BB 很小时,分母里的 OO 会把这个比值压垮——你花了代价把 GPU 唤醒,却几乎没用上它。随着 BB 增大,你把 OO 摊到更多组合上,加速比就朝着它的渐近线 a/ba/b(那个真实的硬件比值)攀升。半程点落在 B=O/bB = O/b 处:一个批量空间里的"脊点",它告诉你,你的扫描要宽到什么程度,GPU 才能发挥出哪怕一半的实力。一次几十个组合的扫描,远远坐在那个脊点的左边。一次数千个组合的扫描,则坐在平坦段上,GPU 终于挣得了它的天花板。

所以正确的问题从来不是"GPU 是不是更快"。而是"我的扫描是否在脊点的右边,以及我每个组合的工作是否足够计算密集,能在到达那里时够到平坦天花板"。两者都必须成立。本文余下的部分,就是去测量这些门槛究竟落在哪里。

单时间框架的裁决:GPU 只是勉强胜出

同一个 80 组合单时间框架扫描的两根柱子:十二核 CPU 池以每秒 246 个组合,紧挨着 GPU 的每秒 779 个,是一个不大的 3.2x 差距,而非一道鸿沟

先从速度阶梯用过的那个工作负载开始:一个单时间框架的 HMA/HMA3 扫描,150,000 根 K 线上的 80 个组合。我们给那把梯子加了第六级台阶——M5,通过 MLX 在 Apple GPU 上计算指标,交易仍在 CPU 上提取。预热完毕,取三次运行的最优,等价性关卡亮绿灯:

方法 墙钟时间 相对 pandas 组合/秒
M0 pandas + 循环 287.08s 1.0x 0.3
M2 numba(1 核) 2.02s 142x 39.7
M4 多进程 + numba(12 核) 0.33s 883x 245.9
M5 MLX GPU(fp32) 0.10s 2796x 779.2

对着朴素的串行基准,GPU 看上去像个英雄——2,796x。但这是任何诚实的人都不该做的对比:它让一个优秀的 GPU 实现,去对阵最差的那个 CPU 实现。把 GPU 摆到你真正会部署的那个 CPU 面前——同一个内核跑满全部十二个核心,也就是 M4——胜势就坍缩成了清醒的 3.2x(779 对 246 个组合每秒)。一整块显卡,跑完整个扫描,也只以三倍的优势胜过一个十二核 CPU 池。

3.2 倍不是什么都没有。但它也不是任何人买 GPU 的理由。而且它恰恰是屋顶线对一次这么窄的扫描所预言的结果:80 个组合位于脊点左侧。固定的启动与传输开销 OO 在一个 0.10 秒的作业里仍占据着可观的一块,所以我们从未触及渐近线 a/ba/b。更糟的是,每个组合成本里有一部分是那个 O(n) 的交易提取过程,我们刻意把它留在了 CPU 上——这是一个 GPU 根本无法加速的项(下一节详谈原因)。对一个这种规模的单时间框架研究循环,速度阶梯当初的裁决依然成立:**GPU 不是那块缺失的拼图。**并行 numba 早已把你送到了 0.23–0.33 秒,而把它再削到 0.10,并不是解开研究者困局的那把钥匙。扫描周围的编排才是。

那句裁决里有意思的词是这种规模。沿着批量轴向右移动,故事就变了。

成本究竟花在了哪里

在我们把批量放大之前,先看看我们实际上在为什么买单,因为屋顶线只有在昂贵的那部分是计算密集型时才会给你回报。对这次扫描做性能剖析,会发现它几乎全是一件事:**加权移动平均卷积。**一条 HMA 是三次 WMA,一条 HMA3 是四次;每个组合都要在整条序列上把它们重新算一遍。交易提取——走一遍那两条指标数组,找出 hma - hma3 的符号翻转,记录成交——是单独一趟廉价的 O(n) 过程。这次扫描是一个披着交易策略外衣的卷积工作负载。

这种拆分,恰好对应屋顶线的两种区间:

  • **卷积是计算密集型的。**每个价格都会被读进许多重叠的窗口求和里,所以算术强度——每搬运一字节所做的运算次数——很高。这类工作够向平坦的计算天花板,而 GPU 的平坦天花板正是那条高耸的。更妙的是,这些窗口还组合地重叠:一条长度为 40 的 WMA 对几十个组合都有用,所以一次批量预计算把它共享一次,而不是每个组合各算一遍。批量不仅摊薄了启动开销;它还通过复用载入的数据抬高了算术强度。这就是该放到 GPU 上的那部分。
  • **交易提取受带宽限制、且充满分支。**一趟顺序遍历,每一次交叉处都有数据依赖的分支,基本没有复用。它的算术强度接近地板,控制流对一台 SIMD 设备充满敌意。把它推到 GPU 上收益甚微、代价高昂;它留在 CPU 上。这意味着它是阿姆达尔定律式拆分中的串行尾巴——一个 GPU 加速比永远无法穿透的固定地板,也是单时间框架数字为何在 3.2x 处饱和的部分原因。

这个内核的多时间框架版本里,还藏着第二条、更锋利的教训,它正是我们一直答应要解释的那个 27x 的来源。多时间框架引擎会把一条更高时间框架的 HMA 无前视地对齐到 1 分钟的基准索引上。按最直观的方式写,那是每根 K 线 O(length^1.5) 的工作量——在每一根基准 K 线上都重算一遍更高时间框架的移动平均线。但那条对齐后的 HMA,对于"最近几根已收盘的更高时间框架 K 线组成的短缓冲区加上运行中的收盘价"而言是线性的,所以整个逐根 K 线的计算就坍缩成了一个固定的权重向量:在已收盘 K 线序列上做一次 conv1d,后面跟一次 O(n) 的 gather。数以亿计的冗余运算,变成了一次在短得多的序列上的卷积。

这次坍缩是一个算法上的胜利,而不是硬件上的。它是一个更好的公式。它能在 GPU 上跑,也能在 CPU 上跑得一样好——np.correlate 加一次 gather,用 fp64。请牢牢记住这一点:多时间框架头条数字里最大的那个因子,是一次连一块 GPU 都不需要的机器就能用上的改写。当我们最终分解那个 167x 时,这就是那个 27x。

领先幅度随批量增大

一条 GPU 相对 CPU 加速比随批量大小上升的曲线,从一个组合时的 54.5x 一路扫过六十一个组合时的 359.6x,在三十二处有一个孤零零的凹陷,标注为分块边界造成的假象

现在做屋顶线让我们去做的那个测量。取那条昂贵的轴——在 1 分钟基准序列(我们拥有的最长 K 线流)上对齐的更高时间框架 HMA 预计算——然后每次调用喂给 GPU 数量递增的长度组合,B=1,2,4,,61B = 1, 2, 4, \dots, 61。这里的 CPU 基准是那个诚实的生产引擎:跨全部十二个核心、用 prange 的 numba。对每一个批量,我们都测量两者并取其比值。

批量 BB(组合/次调用) GPU 相对 12 核 CPU 引擎的加速比
1 54.5x
2 102.5x
4 129.5x
8 187.4x
16 267.4x
32 245.0x
61 359.6x

这就是 S(B)=aB/(O+bB)S(B) = aB/(O + bB) 用真实测量画出来的样子。在 B=1B = 1 时,GPU 就已经领先 54.5x——因为这个对比针对的是朴素的逐根 K 线引擎,所以哪怕只有一个组合,算法坍缩也已经烘焙在里面了——但它离自己的天花板还差得远:固定开销在一个单组合的调用里仍占主导。把批量翻倍,加速比就几乎翻倍到 102.5x;到 B=16B = 16 是 267.4x;到 B=61B = 61 是 359.6x,而且肉眼可见还在爬。**领先幅度随问题规模增大而增长。**这是关于 GPU 与参数扫描最重要的一句话,而它恰恰与 GPU 加速比通常被引用的方式相反——仿佛它们是芯片的某种恒定属性似的。

两点诚实的说明,因为这里是回测无幻觉系列,而一张干净单调的表格永远值得怀疑。

第一,那个凹陷:B=32B = 32 读数为 245.0x,低于 B=16B = 16 时的 267.4x。这不是可以扫到地毯底下的噪声——它是一个分块边界造成的假象。我们的 conv1d 会把 32 个长度打包进一个内核分块,所以 B=32B = 32 恰好把一个分块塞满、没有余量,而 B=61B = 61 溢出到了第二个分块里,后者碰巧把设备喂得更饱。屋顶线关注的是趋势,而一台真实设备内部存在量化台阶;我们如实报告这点抖动,而不是绕开它去挑选数据。

第二,也更重要:**54.5x 和 359.6x 都是针对朴素 CPU 引擎的,两者都不是硬件收益。**这两个数字里仍然含着那个 27x 的算法坍缩。如果你把 CPU 基准换成在 CPU 上运行的那个坍缩后的算法——同一个公式、fp64、两边都经过优化——每一行都会大致缩小那么一个因子。而这正是下一节要精确算清的那个分解。

诚实的分解:27x 算法乘以 6.2x 硬件

一根 167x 的柱子分裂成两个叠起来的因子——一个大的 27x 标着算法、CPU 同样能享有,一个较小的 6.2x 标着硬件,是 GPU 真正贡献的唯一部分

要把算法和硅片分开,你得在同一个多时间框架网格上测量三条路径,而不是两条。所以基准测试运行了:

  1. cpu-engine——生产环境的 numba 引擎,跨全部核心的逐根 K 线对齐 HMA。这是朴素但并行的基准。
  2. cpu-collapsed——坍缩后的权重向量,np.correlate 加 gather,fp64,跑在 CPU 上。与(1)硬件相同,算法更优。
  3. gpu-mlx——把坍缩后的权重作为一次批量 conv1d 跑在 Metal GPU 上,fp32。与(2)算法相同,硬件不同。

把它们排在一起,完整的多时间框架头条数字就干净地因式分解了:

167×gpu vs naive CPU  =  27×cpu-collapsed vs cpu-engine  ×  6.2×gpu vs cpu-collapsed\underbrace{167\times}_{\text{gpu vs naive CPU}} \;=\; \underbrace{27\times}_{\text{cpu-collapsed vs cpu-engine}} \;\times\; \underbrace{6.2\times}_{\text{gpu vs cpu-collapsed}}

左边的因子,27x,是算法——上一节里那个从逐根 K 线到卷积的坍缩。它跟 GPU 毫无关系。用 numpy 把它实现出来,你的笔记本 CPU 在这个工作负载上就快了 27x,代价不过是一次重构。右边的因子,6.2x,是硬件——Metal GPU 相对十二个 CPU 核心上同一个优化过的算法那份诚实的、同类对同类的胜利。那 6.2x 才是你真正需要一块 GPU 才能拿到的唯一部分。

这就是整篇文章的寓意,用算术讲出来。当一份厂商基准、一个库的 README,或者一位兴奋的同事给你亮出"GPU 上 167x"时,你的条件反射应该是一个问题:*CPU 基准是什么?*如果基准是那个朴素实现——而它几乎总是,因为一个慢的基准能做出更漂亮的幻灯片——那么头条里的大部分都是一个 CPU 本也有权享有的算法收益,只有那点残差才是硬件。这里的残差是 6.2x。一句 167x 的说法,把硬件的贡献夸大了大约 27 倍。

再注意硬件这个因子本身是怎么随问题规模移动的。在那个小的单时间框架扫描上,GPU 相对最佳 CPU 的真实胜利是 3.2x。在那个更大的多时间框架预计算上,它是 6.2x——同样两块芯片,硬件优势却几乎翻倍,纯粹是因为更大的工作负载在 CPU 还跟得上之前,就把你往屋顶线上推得更高、更靠近 GPU 的平坦计算天花板。硬件领先也不是一个常数。它是同一条上升曲线上的一个点,而你在那条曲线上向右移动的方式,就是把批量做得更大、把每个组合的工作做得更丰厚。

一份决策指南:扫描到底要多宽?

一张简单的决策流程图:小规模扫描或单组合工作稀薄的走向 CPU,数千个计算密集组合的宽扫描走向 GPU,GPU 分支上还立着一道 fp32 一致性关卡

把屋顶线折回成一个你能在花钱之前就做出的决定。当屋顶线的两个条件同时成立时,GPU 才划算:你的扫描在批量脊点的右边BO/bB \gg O/b,于是固定的启动与传输开销被摊薄了),并且你的每个组合的工作是计算密集型的(算术强度足够丰厚,能够到平坦天花板,而不是一趟稀薄的 O(n) 过程)。具体地,从我们测到的结果看:

  • **一个单时间框架策略的几十个组合:跳过 GPU。**你在脊点左侧;相对并行 numba,在一个本就只要十分之一秒的作业上,诚实的胜利是 ~3.2x。瓶颈不在内核,而在它周围的一切。
  • **数千个组合,或者一个真正多时间框架 / 多指标的预计算:GPU 挣得了它的位置。**开销被摊薄,共享的卷积抬高了算术强度,硬件胜利爬升到 6.2x,并随批量继续上升。这正是 GPU 能把一次通宵扫描变成一次咖啡时间的区间。
  • **先爬 CPU 阶梯——它更便宜,而且它排在前面。**那 CPU 上的 298x 和那个 27x 的算法坍缩都是免费或近乎免费的,而且它们是前提,不是替代品:GPU 的 6.2x 是叠加在坍缩后的算法之上的,而那个算法你本来就得写。把一块 GPU 硬拴到一条朴素流水线上,测出来的多半是那份朴素。

GPU 分支上还有一项与速度无关的税,你必须把它算进成本:**Apple 的 Metal GPU 根本没有 fp64。**一切都在 fp32 里跑,相对精度约 1.2e-7。这就扼杀了那个教科书式的快速移动平均技巧——O(n) 的前缀和 WMA——因为在 150k 根 K 线上、价格量级接近 30,000 时,那些累加和会达到 ~1e14,比 fp32 的安全整数范围高出七个数量级;我们实测到的相对误差高达 ~2e2(是两百倍,不是百分之二)。可用的表述方式是直接的窗口卷积,每个窗口求和都是有限个量级相当的项,fp32 能保持约 8e-7 的精度。即便如此,一个靠 hma - hma3 符号做决定的策略,偶尔仍会在两条曲线几乎相触的临界 K 线上翻转一次交叉,因为 fp32 的舍入会把一次近乎平局的情况推向一边。这就是为什么 GPU 路径随附一道衡量交易分歧了多少的等价性关卡——以基点计的 PnL 差值、交易笔数的相对偏移——而不是去断言一种它永远无法交付的逐位相同的输出。在我们这次运行里,那份分歧是 479,016 笔成交里有 90 笔发生了偏移(0.019%),稳稳在容差之内,但这份负担是真实的:**上 GPU 意味着你要背负一个数值一致性的故事,而不只是一个更快的时钟。**那份工程成本,同样是盈亏平衡的一部分。

数字是苹果形状的;曲线不是

上面每一个数字都出自一台 Apple M2 Max:一台统一内存设备,GPU 和 CPU 共享一个内存池,还有一块只有 fp32、没有双精度的 GPU。一块独立的 NVIDIA 或 AMD 显卡会改变这些常数,而且值得把每一个常数往哪个方向移动讲清楚,因为即便数字变了,论证的形状依然成立。

  • **传输开销 OO 会变得更糟,而不是更好。**一块独立显卡待在 PCIe 后面,所以输入和结果要跨总线做一次真实的拷贝,而这正是统一内存所避免的。这会把批量脊点 O/bO/b推——你需要一次更宽的扫描,独立 GPU 才能摊薄它的启动开销。在一台 PCIe 设备上,屋顶线的左边缘更陡,而不是更缓。
  • **平坦天花板 a/ba/b 会变得更高。**一块数据中心 GPU 拥有远比集成 GPU 更多的 FLOP/s 和带宽,所以在一次能把设备喂饱的扫描上,渐近的硬件胜利会比我们的 6.2x 更大。够到曲线右侧的回报增大了;坐在左侧的过路费也增大了。
  • **fp64 回来了,前缀和技巧也随之回来。**在一块拥有真正双精度的显卡上,O(n) 的前缀和 WMA 重新可行,一致性关卡也能收紧到逐位精确。我们付出的那份特定的 fp32 税——用直接卷积而非前缀和、用一道衡量分歧的关卡而非一个断言——是 Apple Silicon 的一个细节,不是一条定律。

这些都不改变论点。在任何设备上,S(B)=aB/(O+bB)S(B) = aB/(O + bB):一个你必须摊薄的固定开销,一条你只能从右侧逼近的渐近线。常数属于硬件;曲线属于算术。在你相信任何人的头条数字——包括我们的——之前,先用一段五行的批量扫描测出你自己的 OOaabb

这一切如何相连

这是一个关于回测速度究竟从何而来的小子系列里的第四次测量,而这些拼块拼成了一个关于在花钱之前该优化什么的统一论证:

  • 速度阶梯从 pandas 爬到并行 numba,单靠 CPU 就拿下 298x,并把 GPU 留作一个悬而未决的问题。这篇文章回答了它:GPU 是一个真实但有条件的第五级台阶,相对最顶端的 CPU 台阶值 3.2x–6.2x,而且只有在扫描宽到足以爬上屋顶线之后才作数。
  • IPC 税在另一个方向上做了同样的动作——测量离开进程要付出什么代价——并得出了同样形状的结论:边界(一个 socket、一次 GPU 启动)很便宜;税出在你跨越它的频率和健谈程度上。你批量处理 GPU 调用的理由,和你批量处理 IPC 的理由是同一个:摊薄一份固定的、每次跨越都要付的成本。
  • 聚合 parquet 缓存是 GPU 预计算所做之事的 CPU 侧版本——把共享的指标算一次,在每个组合之间复用它们。GPU 只是把那条复用加批量的原则搬到了硅片上。
  • 而那道 fp32 一致性关卡,是一个缩微版的回测-实盘一致性问题:一旦你的快路径算出了与参照略有不同的东西,你就欠下一份对这份分歧的量化交代,而不是挥挥手了事。

把这一切串起来的准则,和整个系列所推崇的是同一条:去测量你实际上被推销的那个东西。加速比是一个比值,而一个比值有分子和分母。大多数 GPU 带来的失望,源自一个被挑来奉承你的分母——CPU 基准;而大多数 GPU 的浪费,源自跑了一次太小、根本离不开屋顶线左边缘的扫描。

要点总结

  1. **GPU 加速比是一条曲线,不是一个数字。**在我们的多时间框架预计算上,相对 CPU 的领先幅度,从每次调用一个组合时的 54.5x 一路跑到六十一个时的 359.6x——同一块芯片,同一份数据。任何单一的数字都只是那条曲线上的一个点;要问它是在多大的批量下测出来的。
  2. **永远要盘问 CPU 基准。**那个 167x 的多时间框架头条数字,干净地因式分解为 27x 的算法(一次从逐根 K 线到卷积的坍缩,它让 CPU 同样提速)乘以 6.2x 的真实硬件。这里公平的 GPU 相对最佳 CPU 胜利,是单时间框架 3.2x、多时间框架 6.2x——而不是 167x。
  3. **领先幅度随问题规模增长,硬件因子也一样。**更大的批量和更丰厚的单组合工作会把你往屋顶线上推:诚实的硬件胜利本身,仅仅靠把工作负载做大,就从 3.2x 升到了 6.2x。小规模扫描坐在脊点左侧,几乎得不到什么好处。
  4. **先修好算法、先爬 CPU 阶梯——GPU 的胜利叠加在它们之上,而不是取而代之。**那 6.2x 是相对你本来就得写的那个坍缩后算法测出来的。把一块 GPU 硬拴到一条朴素流水线上,你测出来的多半是那份朴素,而不是硅片。
  5. **上 GPU 意味着你要背负一个数值一致性的故事。**Metal 上没有 fp64,前缀和 WMA 技巧在价格量级下失效(相对误差 ~2e2),而靠交叉符号做决定的策略会在临界 K 线上翻转。交付一道以基点量化分歧的等价性关卡;把那份工程成本算进你的盈亏平衡里。

当有人告诉你 GPU 让他们的回测快了一百倍时,他们几乎什么都没告诉你。问问他们批量大小和 CPU 基准,那个一百倍通常会化解成一个个位数的硬件胜利,外面裹着一个他们本可以免费得到的算法胜利——在一次足够大的扫描上,它值得拥有,理由恰如屋顶线所言,一个也不多。

免责声明:本文提供的信息仅用于教育和参考目的,不构成财务、投资或交易建议。加密货币交易涉及重大损失风险。

Authors

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

紧跟市场步伐

订阅我们的时事通讯,获取独家 AI 交易见解、市场分析和平台更新。

我们尊重您的隐私。您可以随时退订。