Pine Script机器学习代码正确性验证及优化方向咨询
TradingView kNN指标代码验证与技术路径分析
问题背景
我基于lastguru的Trading View代码修改了脚本,目前已有预测结果,但效果未达预期。想确认代码是否正确,以及当前技术路径是否合理,寻求专业指导。
指标运行截图

现有代码
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © subikshababu //@version=5 indicator("ema ML",overlay = false) em1=ta.ema(ta.ema(hlc3,2),3) em2=ta.ema(ta.ema(hlc3,5),8) em3=ta.ema(ta.ema(hlc3,8),13) em4=ta.ema(ta.ema(hlc3,13),21) plot(em1,color = color.red,linewidth = 2) plot(em2,color = color.green,linewidth = 2) plot(em3,color = color.blue,linewidth = 2) arrsma=array.from(em1,em2,em3) avgem=array.avg(arrsma) plot(avgem,color=color.black,linewidth = 3) src=close>open?1 : close<open?-1:0 ///////// // kNN // ///////// SRC=avgem // Define storage arrays for: parameter 1, parameter 2, price, result (up = 1; down = -1) var knn1 = array.new_float(1, 0) var knn2 = array.new_float(1, 0) var knnp = array.new_float(1, 0) var knnr = array.new_float(1, 0) // Store the previous trade; buffer the current one until results are in _knnStore(p1, p2) => var prevp1 = 0.0 var prevp2 = 0.0 var prevsrc = 0.0 array.push(knn1, prevp1) array.push(knn2, prevp2) array.push(knnp, prevsrc) array.push(knnr, src >= src[1] ? 1 : -1) prevp1 := p1 prevp2 := p2 prevsrc := src prevsrc // Get neighbours by getting k smallest distances from the distance array, and then getting all results with these distances _knnGet(arr1, arr2, k) => sarr = array.copy(arr1) array.sort(sarr) ss = array.slice(sarr, 0, math.min(k, array.size(sarr))) m = array.max(ss) out = array.new_float(0) for i = 0 to array.size(arr1) - 1 by 1 if array.get(arr1, i) <= m array.push(out, array.get(arr2, i)) out // Create a distance array from the two given parameters _knnDistance(p1, p2) => dist = array.new_float(0) n = array.size(knn1) - 1 for i = 0 to n by 1 d = math.sqrt(math.pow(p1 - array.get(knn1, i), 2) + math.pow(p2 - array.get(knn2, i), 2)) array.push(dist, d) dist // Make a prediction, finding k nearest neighbours _knn(p1, p2, k) => slice = _knnGet(_knnDistance(p1, p2), array.copy(knnr), k) knn = array.sum(slice) knn //////////// // Inputs // //////////// // When DIST is 0, KNN default was 23 KNN = input(title='kNN nearest neighbors (k)', defval=1) float DIST = input(title='kNN minimum difference', defval=.5) BACKGROUND = input(title='Draw background', defval=false) //////// // MA // //////// buysell(x,y)=> _knnStore(x, y) filter = _knn(x, y, KNN) buy= (( filter >= DIST))?1 : 0 sell= ((filter <= -DIST))?1:0 [buy,sell] [buy,sell]=buysell(em1,em2) [buy1,sell1]=buysell(em1,em3) //[buy2,sell2]=buysell(em1,em4) buycum=buy+buy1 sellcum=sell+sell1 buysig=buycum>sellcum sellsig=sellcum>buycum plotshape(buysig,style = shape.circle,location = location.top,color = color.green) plotshape(sellsig,style = shape.circle,location = location.top,color = color.red)
代码正确性问题
1. 训练数据污染
多次调用buysell函数(如em1&em2、em1&em3)共享同一组knn1/knn2/knnp/knnr数组,导致不同特征对的训练数据混杂,kNN无法学习到对应特征的有效模式。
2. 无效初始数据
数组初始化时默认存入0值,这部分无效数据会参与距离计算,干扰真实样本的匹配结果。
3. 标签与预测目标不匹配
knnr存储的是src >= src[1] ? 1 : -1(当日涨跌方向是否强于前一日),但脚本最终要输出的是涨跌交易信号,标签定义和预测目标不一致,导致模型学习方向错误。
4. 参数逻辑不兼容
当KNN值大于1时,_knn返回的是邻居结果总和,范围随K值变化,但DIST是固定阈值,比如K=3时总和范围为-3到3,固定0.5的阈值会导致信号触发逻辑混乱。
技术路径合理性分析
用kNN构建交易信号的思路可行,但当前路径存在核心缺陷:
- 特征冗余:em1/em2/em3均为双重EMA的hlc3,特征高度相关,kNN的距离计算会被冗余特征主导,无法有效区分市场状态。
- 特征维度单一:仅用均线类特征,缺少波动率(ATR)、成交量、震荡指标(RSI/MACD)等维度信息,特征空间不足以刻画复杂市场变化。
- 数据管理混乱:共享训练数组、初始无效数据等问题,导致模型学习到的是混乱噪声模式,而非有效规律。
优化建议
- 隔离训练数据:为每一组特征对单独创建训练数组,避免不同特征的样本混杂。
- 修正标签定义:将标签改为下一日涨跌结果,比如
knnr存储close[1] > close[2] ? 1 : -1,让模型学习“当前特征对应下一日涨跌”的规律。 - 丰富特征维度:加入ATR、RSI、成交量变化率、MACD等不同类型特征,降低特征相关性,拓展特征空间。
- 归一化特征:kNN对数据尺度敏感,将所有特征归一化到0-1区间,避免数值大的特征主导距离计算。
- 动态阈值调整:将
_knn返回值改为平均投票结果(总和/K),再和阈值比较,比如avg_vote = array.sum(slice)/k,用avg_vote >= 0.3作为做多条件,适配不同K值。 - 清理初始数据:初始化数组时不存入默认0值,待有真实数据后再开始存储样本。
- 回测验证:优化后用多品种、多周期回测,统计胜率、盈亏比、最大回撤等指标,验证信号有效性。
内容的提问来源于stack exchange,提问作者Babu Ramasamy
相关产品推荐
相关产品推荐

