如何在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:
- 先默认不操作当前节点,所以
maxRate[i] = maxRate[i+1](继承后面节点的最大收益) - 如果当前节点有可买入的低点,就遍历所有时间在i之后的节点j:
- 如果j有可卖出的高点且高于i的低点,计算
(j.high / i.low) * maxRate[j+1](i买j卖,加上j之后的最大收益) - 把这个值和当前的
maxRate[i]比较,取更大的那个更新maxRate[i]
- 如果j有可卖出的高点且高于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




