You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化OHLC数据框判断后续价格先涨跌指定百分比的代码

OHLC阈值触发判断优化方案

原有代码问题

你现有的逐行apply方案时间复杂度为O(n²),每次遍历都要做切片、布尔索引操作,纯Python循环的执行效率极低,数据量超过1万行时卡顿会非常明显,且原代码存在函数名笔误(定义的函数名为check,调用时写的是find_threshold)。

最优实现方案(Numba JIT加速)

这是目前兼顾速度和内存开销的最佳方案,通过Numba将纯Python循环编译为机器码,执行速度比原方案提升100~1000倍,支持百万级OHLC数据正常运行:

依赖安装

如果没有装Numba可以先执行:pip install numba

代码实现

import numpy as np
import pandas as pd
from numba import jit

@jit(nopython=True)  # 开启nopython模式编译为机器码
def find_first_threshold(close_arr, high_arr, low_arr, threshold=0.01):
    n = len(close_arr)
    res = np.zeros(n, dtype=np.int8)  # 用int8节省内存
    for i in range(n):
        current_close = close_arr[i]
        up_thr = current_close * (1 + threshold)
        down_thr = current_close * (1 - threshold)
        first_up_idx = n  # 初始值设为数组长度,表示未找到
        first_down_idx = n
        # 从当前行的下一行开始遍历
        for j in range(i + 1, n):
            # 优先找最早触发的阈值
            if high_arr[j] >= up_thr and first_up_idx == n:
                first_up_idx = j
            if low_arr[j] <= down_thr and first_down_idx == n:
                first_down_idx = j
            # 两个阈值都找到就提前退出循环,减少无效计算
            if first_up_idx != n and first_down_idx != n:
                break
        # 赋值结果
        if first_up_idx < first_down_idx:
            res[i] = 1
        elif first_down_idx < first_up_idx:
            res[i] = -1
        else:
            res[i] = 0
    return res

# 调用函数直接生成结果列
ohlc['check'] = find_first_threshold(
    ohlc['close'].values,
    ohlc['high'].values,
    ohlc['low'].values
)

替代方案(无Numba纯Pandas向量化)

如果无法安装Numba,且数据量小于1万行,可以用广播向量化实现,避免逐行apply,但数据量过大时会出现内存溢出:

import numpy as np
import pandas as pd

close = ohlc['close'].values
high = ohlc['high'].values
low = ohlc['low'].values
n = len(close)

# 生成上穿、下穿阈值的布尔矩阵,上三角矩阵仅保留当前行之后的判断
up_mask = np.triu(high > (close * 1.01).reshape(-1, 1), k=1)
down_mask = np.triu(low < (close * 0.99).reshape(-1, 1), k=1)

# 找每行第一个触发阈值的位置
first_up = np.argmax(up_mask, axis=1)
first_down = np.argmax(down_mask, axis=1)

# 处理未触发的情况(argmax默认返回0,需要替换为超出数组长度的值)
first_up[~up_mask.any(axis=1)] = n
first_down[~down_mask.any(axis=1)] = n

# 生成结果列
ohlc['check'] = np.where(
    first_up < first_down, 1,
    np.where(first_down < first_up, -1, 0)
)

内容的提问来源于stack exchange,提问作者Sascha Galley

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 21:06:03