Pine Script技术问询:如何保存触发条件时特定K线的多组数据并实现与当前K线的距离计算
嘿,这个需求在量化交易策略开发里挺常见的,我来给你拆解成数据存储和距离计算两部分讲,保证清晰实用:
一、数据存储方案
1. 二维数组实现(直接满足你的需求)
如果就想用二维数组,逻辑非常直观:每一行对应一条触发条件的K线,每行包含5个浮点值,顺序固定为 [开盘价, 最高价, 最低价, 收盘价, 自定义值]。
举个Python的实操例子:
# 初始化空的二维数组,用来存所有触发条件的K线数据 triggered_krecords = [] # 当触发条件满足时,调用这个函数保存数据 def save_triggered_kline(open_p, high_p, low_p, close_p, custom_val): triggered_krecords.append([open_p, high_p, low_p, close_p, custom_val])
要是用Java的话,写法也类似:
// 用ArrayList存储二维数组,灵活扩容 ArrayList<Double[]> triggeredKRecords = new ArrayList<>(); // 保存触发的K线数据 public void saveTriggeredKline(double open, double high, double low, double close, double customVal) { triggeredKRecords.add(new Double[]{open, high, low, close, customVal}); }
2. 结构化存储(更推荐,可读性拉满)
二维数组虽然能用,但时间久了你很容易忘哪个索引对应哪个字段(比如索引3是收盘价还是最低价?)。更推荐用数据类/结构体封装这些字段,代码维护起来轻松太多。
比如Python用dataclasses(Python 3.7+支持):
from dataclasses import dataclass # 定义一个专门的类来存储触发K线的所有数据 @dataclass class TriggeredKline: open: float high: float low: float close: float custom_value: float # 存储列表,用来存所有触发的K线实例 triggered_krecords = [] # 保存数据的时候直接实例化类就行 triggered_krecords.append(TriggeredKline(open=12.3, high=13.1, low=12.0, close=12.7, custom_value=0.6))
后续访问数据时,直接写kline.close、kline.custom_value,比记数组索引靠谱多了。
二、点位距离计算
这里的“距离”得先明确需求:是算单个点位的差值,还是多个点位的综合差异?我两种情况都给你讲:
1. 单个点位的距离计算
如果只需要对比某一个特定点位(比如当前收盘价和触发K线的收盘价的距离),直接做差值就行,要区分方向就保留正负,要绝对值距离就套个abs():
用结构化存储的例子:
# 假设当前K线的收盘价是current_close current_close = 13.5 # 取最近一条触发的K线(或者根据业务逻辑取特定的某一条) latest_triggered = triggered_krecords[-1] # 带方向的距离(正表示当前收盘价更高,负表示更低) close_distance = current_close - latest_triggered.close # 无方向的绝对值距离 abs_close_distance = abs(current_close - latest_triggered.close)
如果用二维数组,就是把latest_triggered.close换成triggered_krecords[-1][3](因为索引3对应收盘价)。
2. 多点位的综合距离计算
如果要同时考虑所有5个点位的差异,推荐用欧几里得距离——把每个点位的差值当作多维空间的坐标差,计算空间距离。公式是:
总距离 = √[(当前开盘-触发开盘)² + (当前最高-触发最高)² + (当前最低-触发最低)² + (当前收盘-触发收盘)² + (当前自定义值-触发自定义值)²]
Python实现代码(兼容结构化存储和二维数组):
import math def calculate_total_distance(current_data, triggered_data): # 先计算每个点位的差值 if isinstance(current_data, TriggeredKline): # 结构化数据的情况 diffs = [ current_data.open - triggered_data.open, current_data.high - triggered_data.high, current_data.low - triggered_data.low, current_data.close - triggered_data.close, current_data.custom_value - triggered_data.custom_value ] else: # 二维数组的情况 diffs = [current_data[i] - triggered_data[i] for i in range(5)] # 计算平方和后开根号 squared_sum = sum(d ** 2 for d in diffs) return math.sqrt(squared_sum)
3. 自定义加权距离(适配策略需求)
如果你的策略里某些点位更重要(比如收盘价权重更高),可以给不同点位设置权重,计算加权后的综合距离:
def calculate_weighted_distance(current_data, triggered_data): # 自定义权重,比如收盘价占40%,其他三个价格各15%,自定义值占10% weights = [0.15, 0.15, 0.15, 0.4, 0.1] if isinstance(current_data, TriggeredKline): diffs = [ current_data.open - triggered_data.open, current_data.high - triggered_data.high, current_data.low - triggered_data.low, current_data.close - triggered_data.close, current_data.custom_value - triggered_data.custom_value ] else: diffs = [current_data[i] - triggered_data[i] for i in range(5)] # 计算加权平方和后开根号 weighted_squared_sum = sum((d * w) ** 2 for d, w in zip(diffs, weights)) return math.sqrt(weighted_squared_sum)
这样就完全适配你的需求了,不管是存储还是计算都能搞定。
内容的提问来源于stack exchange,提问作者aref razavi




