PineScript中函数如何作用于数据?WPNR指标转换疑问
加权百分位近秩(WPNR)指标:PineScript转Python的核心疑问解析
我正尝试将以下PineScript的加权百分位近秩(WPNR)指标转换为Python,但无法理解函数如何作用于
src。wpnr函数返回单个值,我认为这是每根K线的指标值,但为何每次传入相同的src却能返回不同值?
//@version=4 study('Weighted percentile nearest rank', 'WPNR', true, resolution='', resolution_gaps=true) //by gorx1 & wallneradam multisort(base_array, second_array, reverse) => //[ n = array.size(base_array) index_array = array.new_int(n) if n > 0 for i = 0 to n - 1 array.set(index_array, i, i) n -= 1 for i = 0 to n > 0 ? n - 1 : na for j = 0 to n - i - 1 t = array.get(base_array, j) t1 = array.get(base_array, j + 1) if (reverse ? t < t1 : t > t1) array.set(base_array, j, t1) array.set(base_array, j + 1, t) _t = array.get(second_array, j) array.set(second_array, j, array.get(second_array, j + 1)) array.set(second_array, j + 1, _t) _ti = array.get(index_array, j) array.set(index_array, j, array.get(index_array, j + 1)) array.set(index_array, j + 1, _ti) index_array //] wpnr(src, len, n) => //[ data = array.new_float() weights = array.new_float() for i = 0 to len - 1 array.push(data , src[i] ) array.push(weights, len - i) //the actual linear weights // array.push(weights, 1 ) //unit weights, if u wanna do a raincheck multisort(data, weights, false) sum = 0.0 weights_cum = array.new_float() for i = 0 to len - 1 sum := sum + array.get(weights, i) array.push(weights_cum, sum) wpnr = 0.0 thres = array.sum(weights) / 100 * n for i = 0 to len - 1 if array.get(weights_cum, i) >= thres wpnr := array.get(data, i) break wpnr //] src = input(close, 'Source') len = input(50 , 'Length') n = input(50 , '%' ) out = wpnr(src, len, n) plot(out, 'WPNR', color.rgb(255, 255, 255))
核心原因:PineScript的src是动态序列变量
- 在PineScript中,
src(比如示例里的close)不是固定不变的数组,而是随K线推进的滚动序列。每生成一根新K线,src会自动更新为包含最新len周期内的数据,最旧的周期数据会被挤出窗口。 - 调用
wpnr(src, len, n)时,src[i]取的是当前K线往前数第i根的数据源值:src[0]是当前K线的收盘价,src[1]是前一根K线的收盘价,直到src[len-1]是往前第len-1根K线的收盘价。每根K线计算时,这个滚动窗口的内容都不同,所以wpnr的返回值自然会变化。
wpnr函数执行逻辑拆解
- 构建加权数据窗口
- 循环
0到len-1,将当前滚动窗口内的src值存入data数组,同时生成线性权重:越新的K线权重越高(当前K线权重为len,最旧的为1)。
- 循环
- 双数组同步排序
- 调用
multisort对data数组进行升序排序,同时同步调整weights数组的顺序,确保每个数据值对应正确的权重。
- 调用
- 计算累计权重
- 遍历排序后的
weights数组,生成累计权重数组weights_cum,记录到每个位置为止的总权重。
- 遍历排序后的
- 定位百分位对应值
- 计算阈值
thres = 总权重 * n%,找到第一个累计权重≥阈值的data值,该值即为当前K线的WPNR结果。
- 计算阈值
Python转换实现示例
def multisort(base_array, second_array, reverse): n = len(base_array) index_array = list(range(n)) if n > 0: n -= 1 # 冒泡排序,同步调整三个数组 for i in range(n if n > 0 else 0): for j in range(n - i): t = base_array[j] t1 = base_array[j + 1] # 根据reverse参数判断交换条件 if (reverse and t < t1) or (not reverse and t > t1): # 交换base数组元素 base_array[j], base_array[j+1] = base_array[j+1], base_array[j] # 交换权重数组元素 second_array[j], second_array[j+1] = second_array[j+1], second_array[j] # 交换索引数组元素 index_array[j], index_array[j+1] = index_array[j+1], index_array[j] return index_array def wpnr(src_window, n_percent): len_window = len(src_window) data = src_window.copy() # 生成线性权重:越新的数据权重越高 weights = [len_window - i for i in range(len_window)] # 对数据和权重同步排序 multisort(data, weights, reverse=False) # 计算累计权重 weights_cum = [] total_weight = 0.0 for w in weights: total_weight += w weights_cum.append(total_weight) # 计算百分位阈值 threshold = total_weight * (n_percent / 100) wpnr_value = 0.0 # 找到第一个累计权重≥阈值的数据值 for i in range(len_window): if weights_cum[i] >= threshold: wpnr_value = data[i] break return wpnr_value # 使用示例:假设你有一个收盘价序列close_prices(列表格式) length = 50 percent = 50 wpnr_results = [] # 滚动计算每根K线的WPNR值 for i in range(length - 1, len(close_prices)): # 截取当前K线往前length个数据的窗口 current_window = close_prices[i - length + 1 : i + 1] current_wpnr = wpnr(current_window, percent) wpnr_results.append(current_wpnr)
内容的提问来源于stack exchange,提问作者JayK23
相关产品推荐
相关产品推荐

