Pine Script函数局部变量_f[N]含义及MQL5移植差异问题
Pine Script函数历史值疑问及MQL5移植问题解答
问题
- Pine Script中
f_filt9x函数内的局部变量_f使用_f[1]、_f[2]等索引形式,_f[1]是否指函数上一次运行时的_f值? - 将该函数移植到MQL5时,把
_f改为全局缓冲区,运行结果与原脚本不一致,原因是什么?
原Pine Script代码
f_filt9x (_a, _s, _i) => int _m2 = 0, int _m3 = 0, int _m4 = 0, int _m5 = 0, int _m6 = 0, int _m7 = 0, int _m8 = 0, int _m9 = 0, float _f = .0, _x = (1 - _a) // Weights. // Initial weight _m1 is a pole number and equal to _i _m2 := _i == 9 ? 36 : _i == 8 ? 28 : _i == 7 ? 21 : _i == 6 ? 15 : _i == 5 ? 10 : _i == 4 ? 6 : _i == 3 ? 3 : _i == 2 ? 1 : 0 _m3 := _i == 9 ? 84 : _i == 8 ? 56 : _i == 7 ? 35 : _i == 6 ? 20 : _i == 5 ? 10 : _i == 4 ? 4 : _i == 3 ? 1 : 0 _m4 := _i == 9 ? 126 : _i == 8 ? 70 : _i == 7 ? 35 : _i == 6 ? 15 : _i == 5 ? 5 : _i == 4 ? 1 : 0 _m5 := _i == 9 ? 126 : _i == 8 ? 56 : _i == 7 ? 21 : _i == 6 ? 6 : _i == 5 ? 1 : 0 _m6 := _i == 9 ? 84 : _i == 8 ? 28 : _i == 7 ? 7 : _i == 6 ? 1 : 0 _m7 := _i == 9 ? 36 : _i == 8 ? 8 : _i == 7 ? 1 : 0 _m8 := _i == 9 ? 9 : _i == 8 ? 1 : 0 _m9 := _i == 9 ? 1 : 0 // filter _f := pow(_a, _i) * nz(_s) + _i * _x * nz(_f[1]) - (_i >= 2 ? _m2 * pow(_x, 2) * nz(_f[2]) : 0) + (_i >= 3 ? _m3 * pow(_x, 3) * nz(_f[3]) : 0) - (_i >= 4 ? _m4 * pow(_x, 4) * nz(_f[4]) : 0) + (_i >= 5 ? _m5 * pow(_x, 5) * nz(_f[5]) : 0) - (_i >= 6 ? _m6 * pow(_x, 6) * nz(_f[6]) : 0) + (_i >= 7 ? _m7 * pow(_x, 7) * nz(_f[7]) : 0) - (_i >= 8 ? _m8 * pow(_x, 8) * nz(_f[8]) : 0) + (_i == 9 ? _m9 * pow(_x, 9) * nz(_f[9]) : 0)
移植后的MQL5代码
//f_filt9x double f_filt9x(double _a, double _s, int _i, int i) { int _m2, _m3, _m4, _m5, _m6, _m7, _m8, _m9; _m2 = 0; _m3 = 0; _m4 = 0; _m5 = 0; _m6 = 0; _m7 = 0; _m8 = 0; _m9 = 0; double _x = (1.0 - _a); //Weights // Initial weight _m1 is a pole number and equal to _i _m2 = (_i==9) ? 36 : (_i==8) ? 28 : (_i==7) ? 21 : (_i==6) ? 15 : (_i==5) ? 10 : (_i==4) ? 6 : (_i==3) ? 3 : (_i==2) ? 1 : 0; _m3 = (_i==9) ? 84 : (_i==8) ? 56 : (_i==7) ? 35 : (_i==6) ? 20 : (_i==5) ? 10 : (_i==4) ? 4 : (_i==3) ? 1 : 0; _m4 = (_i==9) ? 126 : (_i==8) ? 70 : (_i==7) ? 35 : (_i==6) ? 15 : (_i==5) ? 5 : (_i==4) ? 1 : 0; _m5 = (_i==9) ? 126 : (_i==8) ? 56 : (_i==7) ? 21 : (_i==6) ? 6 : (_i==5) ? 1 : 0; _m6 = (_i==9) ? 84 : (_i==8) ? 28 : (_i==7) ? 7 : (_i==6) ? 1 : 0; _m7 = (_i==9) ? 36 : (_i==8) ? 8 : (_i==7) ? 1 : 0; _m8 = (_i==9) ? 9 : (_i==8) ? 1 : 0; _m9 = (_i==9) ? 1 : 0; //filter _f[i] = (MathPow(_a,_i) * _s) + _i * _x * _f[i-1] -( (_i>=2) ?_m2 * MathPow(_x,2)* _f[i-2] : 0) +( (_i>=3) ?_m3 * MathPow(_x,3)* _f[i-3] : 0) -( (_i>=4) ?_m4 * MathPow(_x,4)* _f[i-4] : 0) +( (_i>=5) ?_m5 * MathPow(_x,5)* _f[i-5] : 0) -( (_i>=6) ?_m6 * MathPow(_x,6)* _f[i-6] : 0) +( (_i>=7) ?_m7 * MathPow(_x,7)* _f[i-7] : 0) -( (_i>=8) ?_m8 * MathPow(_x,8)* _f[i-8] : 0) +( (_i==9) ?_m9 * MathPow(_x,9)* _f[i-9] : 0) ; return _f[i]; }
解答
一、Pine Script中_f[n]的含义
_f[1]不是函数上一次运行的结果,而是该变量在1根K线之前的历史值。Pine Script是逐K线执行的,每一根K线都会调用一次f_filt9x函数,_f作为函数内的变量,会自动保留每根K线的计算结果。_f[1]对应上一根K线中函数计算出的_f值,_f[2]对应前两根K线的结果,以此类推。nz()函数用于处理历史值为空的情况(比如前n根K线还未计算出_f值时),将空值替换为0,避免计算错误。
二、MQL5移植结果不一致的原因及修正
你的MQL5代码存在以下关键问题,导致结果偏差:
索引逻辑与边界处理缺失
Pine Script的_f[1]是上一根K线的历史值,而MQL5中直接使用_f[i-1]时,未处理i < n的情况(比如当前K线索引i=1时,i-2=-1会访问数组越界),导致读取未初始化的垃圾值,而Pine Script的nz()自动处理了这种情况。历史值存储逻辑差异
Pine Script会自动维护函数变量的全K线历史值,而MQL5的全局缓冲区需要手动确保每根K线的_f值被正确存储和读取。如果i参数传递的不是当前K线的正确索引,或者数组初始化不完整,会导致历史值混乱。浮点数类型与精度细节
Pine Script中_f是float类型,而MQL5中是double类型,虽然差异细微,但如果输入参数的类型转换不一致,也可能导致结果偏差。
修正后的MQL5代码
// 全局缓冲区,存储每根K线的_f计算结果 double _f[]; // 初始化缓冲区,在OnInitialize中调用 void InitFBuffer() { ArrayResize(_f, Bars); ArrayInitialize(_f, 0.0); } double f_filt9x(double _a, double _s, int _i, int currentBar) { int _m2 = 0, _m3 = 0, _m4 = 0, _m5 = 0, _m6 = 0, _m7 = 0, _m8 = 0, _m9 = 0; double _x = 1.0 - _a; // 权重计算,与原逻辑一致 _m2 = (_i==9) ? 36 : (_i==8) ? 28 : (_i==7) ? 21 : (_i==6) ? 15 : (_i==5) ? 10 : (_i==4) ? 6 : (_i==3) ? 3 : (_i==2) ? 1 : 0; _m3 = (_i==9) ? 84 : (_i==8) ? 56 : (_i==7) ? 35 : (_i==6) ? 20 : (_i==5) ? 10 : (_i==4) ? 4 : (_i==3) ? 1 : 0; _m4 = (_i==9) ? 126 : (_i==8) ? 70 : (_i==7) ? 35 : (_i==6) ? 15 : (_i==5) ? 5 : (_i==4) ? 1 : 0; _m5 = (_i==9) ? 126 : (_i==8) ? 56 : (_i==7) ? 21 : (_i==6) ? 6 : (_i==5) ? 1 : 0; _m6 = (_i==9) ? 84 : (_i==8) ? 28 : (_i==7) ? 7 : (_i==6) ? 1 : 0; _m7 = (_i==9) ? 36 : (_i==8) ? 8 : (_i==7) ? 1 : 0; _m8 = (_i==9) ? 9 : (_i==8) ? 1 : 0; _m9 = (_i==9) ? 1 : 0; // 模拟Pine Script的nz(),处理索引越界和未初始化情况 double f1 = (currentBar >= 1) ? _f[currentBar - 1] : 0.0; double f2 = (currentBar >= 2 && _i >= 2) ? _f[currentBar - 2] : 0.0; double f3 = (currentBar >= 3 && _i >= 3) ? _f[currentBar - 3] : 0.0; double f4 = (currentBar >= 4 && _i >= 4) ? _f[currentBar - 4] : 0.0; double f5 = (currentBar >= 5 && _i >= 5) ? _f[currentBar - 5] : 0.0; double f6 = (currentBar >= 6 && _i >= 6) ? _f[currentBar - 6] : 0.0; double f7 = (currentBar >= 7 && _i >= 7) ? _f[currentBar - 7] : 0.0; double f8 = (currentBar >= 8 && _i >= 8) ? _f[currentBar - 8] : 0.0; double f9 = (currentBar >= 9 && _i == 9) ? _f[currentBar - 9] : 0.0; // 计算当前K线的_f值 _f[currentBar] = MathPow(_a, _i) * _s + _i * _x * f1 - (_i >= 2 ? _m2 * MathPow(_x, 2) * f2 : 0.0) + (_i >= 3 ? _m3 * MathPow(_x, 3) * f3 : 0.0) - (_i >= 4 ? _m4 * MathPow(_x, 4) * f4 : 0.0) + (_i >= 5 ? _m5 * MathPow(_x, 5) * f5 : 0.0) - (_i >= 6 ? _m6 * MathPow(_x, 6) * f6 : 0.0) + (_i >= 7 ? _m7 * MathPow(_x, 7) * f7 : 0.0) - (_i >= 8 ? _m8 * MathPow(_x, 8) * f8 : 0.0) + (_i == 9 ? _m9 * MathPow(_x, 9) * f9 : 0.0); return _f[currentBar]; }
内容的提问来源于stack exchange,提问作者Mohsen Farghadani
相关产品推荐
相关产品推荐

