Python如何高效识别OHLC数据集中的数值区间与支撑位
比特币OHLCV数据支撑区间统计优化方案
需求背景
我正在开发个人项目,需要在比特币历史价格OHLCV数据集中识别价格支撑区间,使用的pandas DataFrame数据格式如下:
startTime time open high low close volume date direction date 2022-04-08 21:00:00 2022-04-08T21:00:00+00:00 1.649452e+09 42802.0 42856.0 42439.0 42560.0 6.051324e+07 2022-04-08 21:00:00 down 2022-04-08 22:00:00 2022-04-08T22:00:00+00:00 1.649455e+09 42560.0 42664.0 42228.0 42297.0 1.318070e+08 2022-04-08 22:00:00 down 2022-04-08 23:00:00 2022-04-08T23:00:00+00:00 1.649459e+09 42297.0 42359.0 42101.0 42258.0 1.252274e+08 2022-04-08 23:00:00 down 2022-04-09 00:00:00 2022-04-09T00:00:00+00:00 1.649462e+09 42258.0 42457.0 42144.0 42435.0 8.506876e+07 2022-04-09 00:00:00 up 2022-04-09 01:00:00 2022-04-09T01:00:00+00:00 1.649466e+09 42435.0 42461.0 42284.0 42428.0 4.037635e+07 2022-04-09 01:00:00 down ... ... ... ... ... ... ... ... ... ... 2022-06-10 04:00:00 2022-06-10T04:00:00+00:00 1.654834e+09 30094.0 30126.0 30030.0 30069.0 3.618291e+07 2022-06-10 04:00:00 down 2022-06-10 05:00:00 2022-06-10T05:00:00+00:00 1.654837e+09 30069.0 30170.0 30061.0 30078.0 4.745932e+07 2022-06-10 05:00:00 up 2022-06-10 06:00:00 2022-06-10T06:00:00+00:00 1.654841e+09 30078.0 30212.0 30045.0 30076.0 6.220629e+07 2022-06-10 06:00:00 down 2022-06-10 07:00:00 2022-06-10T07:00:00+00:00 1.654844e+09 30076.0 30114.0 30030.0 30030.0 2.871507e+07 2022-06-10 07:00:00 down 2022-06-10 08:00:00 2022-06-10T08:00:00+00:00 1.654848e+09 30030.0 30092.0 29965.0 30005.0 5.683842e+07 2022-06-10 08:00:00 down
核心需求:
针对数据中每一个
low(最低价),计算其上下浮动0.5%的价格区间,统计该区间内包含的其他最低价的数量。

原有实现及问题
原有实现思路:
- 将所有
low列的价格归集到名为lows的列表中 - 遍历
lows列表:对每一个low值,计算其上下0.5%浮动的区间上下界 - 在第一层循环内再次遍历
lows列表,若元素值落在当前计算的区间内,就将其追加到对应结果列表中
原有完整代码:
import httpx import json import pandas as pd def get_ohlc(market): req = httpx.get(f'https://ftx.com/api/markets/{market}/candles?resolution=3600') data = req.json()['result'] ohlcv = pd.DataFrame(data) ohlcv['time'] = ohlcv['time'].astype('int64') ohlcv['time'] = ohlcv['time']/1000 ohlcv['date'] = pd.to_datetime(ohlcv['time'], unit='s') ohlcv = ohlcv.set_index(pd.DatetimeIndex(ohlcv['date'])) return ohlcv ohlcv = get_ohlc('BTC-PERP') supports = {} lows = ohlcv['low'].tolist() for low in lows: low_up = low + (low/100)*0.5 low_down = low - (low/100)*0.5 supports.update({low: []}) for sub_low in lows: if sub_low < low_up and sub_low > low_down: supports[low].append(sub_low) print(supports)
该实现采用双重循环,时间复杂度为O(n²),数据量增大后运行效率极低。
高效实现方案
方案1:排序+二分查找(无额外依赖,O(nlogn)复杂度)
不需要双重循环,先对最低价数组排序,再用二分查找快速定位每个区间的边界,计算区间内元素数量,内存占用低、运行速度快,适合10万条以上的大数据量场景:
import numpy as np lows_arr = ohlcv['low'].to_numpy() sorted_lows = np.sort(lows_arr) # 批量计算每个价格的上下0.5%边界 low_down = lows_arr * 0.995 low_up = lows_arr * 1.005 # 二分查找边界位置,差值即为区间内的最低价数量 left_pos = np.searchsorted(sorted_lows, low_down, side='left') right_pos = np.searchsorted(sorted_lows, low_up, side='right') ohlcv['support_touch_count'] = right_pos - left_pos
如果需要获取每个区间内的具体价格列表,只需要根据左右位置从排序后的数组中切片即可。
方案2:DBSCAN聚类直接识别支撑位
如果最终目标是识别有效支撑区间,而非逐点统计数量,可以直接用DBSCAN密度聚类算法,自动将0.5%偏差范围内的价格聚为一类,过滤掉触碰次数少的无效点位,输出结果更贴合交易分析场景:
from sklearn.cluster import DBSCAN lows_arr = ohlcv['low'].to_numpy().reshape(-1, 1) # 按平均价格的0.5%设置聚类距离阈值,min_samples为支撑位最少触碰次数 avg_price = lows_arr.mean() cluster_model = DBSCAN(eps=avg_price*0.005, min_samples=3) ohlcv['cluster_id'] = cluster_model.fit_predict(lows_arr) # 统计每个聚类的价格范围、触碰次数,即为支撑位信息 support_levels = ohlcv[ohlcv['cluster_id']!=-1].groupby('cluster_id')['low'].agg( touch_count='count', support_min='min', support_max='max', support_center='mean' ).sort_values('touch_count', ascending=False)
内容的提问来源于stack exchange,提问作者JayK23
相关产品推荐
相关产品推荐

