You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在K线(OHLC)序列中寻找最高复利增长率?

如何在K线(OHLC)序列中寻找最高复利增长率?

嘿,这个问题戳中了很多量化交易新手的盲区——简单找“每个低点后的第一个高点”往往会错过更优的复利组合,就像你举的例子里那样,直接跳步拿最末端的高点反而收益更高。咱们一步步拆解这个问题:

先明确你的测试案例问题

首先把你给的测试数据理清楚(按时间从旧到新排序):

// (时间, open, high, low, close)
[ 0,    0,    0,    1,    0 ]  // 最旧的K线,低点=1
[ 1,    0,    1.1,  0,    0 ]  // 高点=1.1
[ 2,    0,    0,    1.8,  0 ]  // 低点=1.8
[ 3,    0,    2,    0,    0 ]  // 最新的K线,高点=2

你之前用的findFirst()逻辑,会匹配“1→1.1”和“1.8→2”,算出来的复利是(1.1/1)*(2/1.8)≈1.22,但显然最优解是直接从1拿到2,复利=2/1=2,收益差了一倍多!

问题出在哪?

简单的“找第一个更高点”逻辑是贪心策略,它只看眼前的第一个收益,没考虑“跳过中间次优节点,直接拿后面更大收益”的可能性。要找到全局最优的复利,我们需要用动态规划的思路,从后往前计算每个节点能获得的最大收益。

具体实现思路

核心想法是:从序列的最后一个节点往前推,记录每个节点开始到末尾的最大复利。定义maxRate[i]为第i个节点开始能拿到的最大复利,步骤如下:

  • 初始化maxRate[n] = 1(序列结束后没有操作,复利为1)
  • 从后往前遍历每个节点i:
    1. 先默认不操作当前节点,所以maxRate[i] = maxRate[i+1](继承后面节点的最大收益)
    2. 如果当前节点有可买入的低点,就遍历所有时间在i之后的节点j:
      • 如果j有可卖出的高点且高于i的低点,计算(j.high / i.low) * maxRate[j+1](i买j卖,加上j之后的最大收益)
      • 把这个值和当前的maxRate[i]比较,取更大的那个更新maxRate[i]

用Java代码实现(贴合你的场景)

// 假设你已经有OHLC类,包含getTime(), getLow(), getHigh()方法
List<OHLC> ohlcs = ...; // 你的K线序列,按时间从旧到新排序
int n = ohlcs.size();
double[] maxRate = new double[n + 1];
maxRate[n] = 1.0; // 序列末尾无操作,复利为1

// 从后往前遍历计算
for (int i = n - 1; i >= 0; i--) {
    OHLC currentOhlc = ohlcs.get(i);
    // 初始值:不操作当前节点,继承后面的最大复利
    maxRate[i] = maxRate[i + 1];
    
    // 仅处理有有效低点的节点(对应你案例中的非零值)
    if (currentOhlc.getLow() > 0) {
        // 遍历所有后续节点,寻找最优卖出点
        for (int j = i + 1; j < n; j++) {
            OHLC nextOhlc = ohlcs.get(j);
            // 仅处理有有效高点且高于当前低点的节点
            if (nextOhlc.getHigh() > 0 && nextOhlc.getHigh() > currentOhlc.getLow()) {
                double candidateRate = (nextOhlc.getHigh() / currentOhlc.getLow()) * maxRate[j + 1];
                // 更新当前节点的最大复利
                if (candidateRate > maxRate[i]) {
                    maxRate[i] = candidateRate;
                }
            }
        }
    }
}

// 最终的最大复利增长率就是maxRate[0]
System.out.println("最大复利增长率:" + maxRate[0]);

在你的测试案例中,这段代码会返回2.0,正好是最优解。

额外说明

  • 时间复杂度是O(n²),如果你的K线序列特别长(比如上万条),可以考虑用单调栈预处理每个节点后的最高高点来优化,但一般场景下O(n²)完全够用。
  • 实际场景中你可能需要调整“有效低点/高点”的判断逻辑(比如不用零值,而是用价格的合理性筛选)。

备注:内容来源于stack exchange,提问作者Paul

火山引擎 最新活动