数据科学与机器学习(第 07 部分):多项式回归(基础篇)
📘

数据科学与机器学习(第 07 部分):多项式回归(基础篇)

第 1/3 篇

◍ 用多项式拟合非线性价格轨迹

在 MT5 里做价格建模,线性拟合经常兜不住震荡段和拐点密集的走势。把自变量做成 x、x²、x³ 这样的高阶项,就是多项式回归的思路,它能把一条弯弯曲曲的残差带压得更贴盘面。 原文给出的系列开篇目录里列了 31 一月 2023 发布的第 07 部分,当时页面阅读量是 1 437,说明这类非线性拟合在量化交易者里并非冷门玩具。 阶数选太低会欠拟合,选太高又会在样本外乱抖。后续会落到贝叶斯信息准则(BIC)来挑阶数,以及特征缩放避免高阶项数值爆炸——这两点在 MT5 的 Python/R 桥或纯 MQL5 矩阵运算里都得自己写。

从线性退一步看多项式回归

先不急着把整套回归模型铺开,回到更底层的视角。基础线性回归其实是大量机器学习模型的骨架,而多项式回归只是它的一个变体,核心仍是拟合自变量与因变量的关系,只是把特征做了幂次扩展。 在 MT5 的行情建模里,这类参数化方法值得留意:像多项式回归、支持向量机都属于带显式参数的路子,通用性较强。它们处理简单样本时能给出近乎直线的边界,遇到复杂分布又可以通过高阶项画出非线性分界面,这对价格行为里的拐点识别有参考意义。 外汇与贵金属杠杆高、跳空频繁,任何回归边界都只是历史样本的概率拟合,实盘使用前建议在策略测试器里用不同品种回测验证。

「多项式不是非得写满每一项」

多项式本质是把已有数据 x 做升幂,再乘上不同系数做缩放。比如一个三次式里,常数 5 对应 a0,-7 对应 a1,4 对应 a2,11.3 对应 a3,每个系数只决定对应幂次项的权重。 实际建模时,你不一定非要把 x 的每一项都写进方程。有些幂次项对拟合贡献极小,留空反而更干净,也降低过拟合概率。 看 MT5 里的多项式回归实现,重点在系数数组和幂次循环,而不是数学式子长得多完整。

◍ 多项式回归里的阶数怎么定

做回归拟合时,多项式的阶(用 n 表示)指的是表达式里 x 的最高次幂,而不是变量的个数。比如一条曲线写成 y = a0 + a1·x + a2·x² + a3·x³,不管前面挂了几个系数,只要最高次是 x³,它就是三阶多项式回归。 很多人会被表象带偏:有的方程里 x 的一次、二次、三次项系数齐全,排列像是 1、2、3;有的方程只显式写了两项,但其中一项是 x³。这时候别数项数,直接看最大的那个指数——它决定阶数。 在 MT5 里用多项式拟合汇率序列时,阶数选太高容易过拟合历史 K 线,选太低又抓不到拐点。外汇与贵金属波动高、跳空频繁,高阶拟合在历史样本上 R² 再高也只代表过去,实盘仍属高风险,参数要自己回测验证。

把线性回归升到 k 阶

多项式回归本质是一族可升阶的线性模型。最基础的一阶形式就是普通线性回归 y = β₀ + β₁x,它并无特殊,只是多项式阶数为 1 的特例。 当我们把自变量升到二次,得到 y = β₀ + β₁x + β₂x²,这就是二阶多项式回归。继续往上推,k 阶形式为 y = β₀ + β₁x + … + βₖxᵏ。 这里容易混淆:式子出现了 x²、xᵏ 这类非线性项,模型还算线性吗?答案是算。线性度约束的是系数 β,而不是自变量。β 之间仍是一次相加,x 升到多少幂都只是数据变换,拟合时依然走最小二乘的线性求解。 在 MT5 里验证这一点很简单:用 iCustom 或自行算 x 的各阶幂序列,再丢进线性回归函数,看残差结构即可。外汇与贵金属波动高、过拟合风险大,阶数越高越要警惕样本外失效。

「多项式阶数该怎么定」

线性模型在拟合非线性关系时经常失灵。以苹果股价与纳斯达克指数为例,前者是后者最大的权重成分之一,但二者同轴散点图明显不是一条直线,直接套用线性回归得到的信任度很低,据此做预测决策风险偏大。 解决思路是上多项式回归:把一个自变量升到任意次幂来逼近弯曲的轨迹。问题随之而来——阶数取几?阶太低欠拟合,阶太高又容易过拟合,尤其在外汇和贵金属这种高噪声市场,过拟合模型实盘大概率失效。 判断阶数前先认识贝叶斯信息准则(BIC)。它惩罚模型复杂度,BIC 值越小,模型在有限样本下的解释力越可信。逐阶跑多项式、比 BIC,是比肉眼瞅散点更硬的办法。 下面这段 MT5 函数用 CGraphics 在终端直接画散点图,把两个品种的向量塞进去就能看同轴分布。注意图形区域建在 0 号图表、左上偏移 (30,70)、宽高 440×320,点径设 10、填充开启。 别把正态当圣经 散点看着弯不代表多项式一定胜出,BIC 对比完若 2 阶与 3 阶差不到 2 点,优先选低阶,贵金属隔夜跳空会让高阶项变成噪声放大器。

MQL5 / C++
class="type">bool ScatterPlot(
                      class="type">class="kw">string obj_name,
                      vector &x,
                      vector &y,
                      class="type">class="kw">string legend,
                      class="type">class="kw">string x_axis_label = "x-axis",
                      class="type">class="kw">string y_axis_label = "y-axis", 
                      class="type">class="kw">color  clr = clrDodgerBlue,
                      class="type">bool   points_fill = true                       
                      )
 { 
   if (!graph.Create(class="num">0,obj_name,class="num">0,class="num">30,class="num">70,class="num">440,class="num">320))
    {
      printf("Failed to Create graphical object on the Main chart Err = %d",GetLastError());
      class="kw">return(class="kw">false);
    }
  
   ChartSetInteger(class="num">0,CHART_SHOW,ChartShow);
  
   class="type">class="kw">double x_arr[], y_arr[]; 
  
   pol_reg.vectortoArray(x,x_arr);
   pol_reg.vectortoArray(y,y_arr);
  
   CCurve *curve = graph.CurveAdd(x_arr,y_arr,clr,CURVE_POINTS);
   curve.PointsSize(class="num">10);
   curve.PointsFill(points_fill); 
   curve.Name(legend);
   graph.XAxis().Name(x_axis_label);
   graph.XAxis().NameSize(class="num">10);
   graph.YAxis().Name(y_axis_label);
   graph.YAxis().NameSize(class="num">10);
   graph.FontSet("Lucida Console",class="num">10);
   graph.CurvePlotAll();
   graph.Update();
 
   class="kw">delete(curve);
  
   class="kw">return(true);
 }
   class="type">class="kw">string plot_name = "x vs y"; 
  
   ObjectDelete(class="num">0,plot_name);    
   ScatterPlot(plot_name,x_v,y_v,X_symbol,X_symbol,Y_symol,clrOrange);

常见问题

试试多项式回归,用二次或三次项捕捉曲线,比纯线性拟合更贴近非线性轨迹。
不必,低阶项系数若接近零可直接省略,只保留显著项能让模型更干净、过拟合风险更低。
可以,小布能基于历史K线自动跑多项式拟合并标出推荐阶数,你直接看结果省去手调。
阶数过高会死磕噪声,回测漂亮实盘拉胯,建议从2阶起逐步加并用样本外数据验证。
把原始价格列扩展成 x、x²…xᵏ 多列再喂给同一套回归,本质还是最小二乘只是特征升维了。