数据科学与机器学习(第四十部分):斐波那契回调位在机器学习中的应用·综合运用
📐

数据科学与机器学习(第四十部分):斐波那契回调位在机器学习中的应用·综合运用

(3/3)·前面铺垫了数列本源与特征工程,这一篇直接上策略测试器看模型到底能不能跑出概率优势

含代码示例实战向 第 3/3 篇
很多人把斐波那契回调线画完就手动猜反转,却从没验证过这些价位在统计上是否真有边缘。用机器学习把回调位转成目标变量再回测,才发现肉眼觉得的“支撑”可能只是幸存者偏差。

把随机森林塞进EA跑样本外验证

做这类斐波那契+机器学习的EA,第一步是把训练好的ONNX模型当资源挂进来,分类器和回归器各一份,再引一个随机森林库去加载它们。训练时用过的lookahead_window和lookback_window必须原样搬进EA,这两个值直接决定持仓用几根K线平掉。 分类器模型在当前周期走过lookahead_window根K线后平仓,回归器则走lookback_window根K线平仓,逻辑和Python里造目标变量时一致。原文训练数据取自2005-01-01至2023-01-01,样本外测试用的是2023全年,回归模型在样本外胜率达到57.42%,表现相对更稳。 人工画斐波那契常凭感觉定高低点区间,没有清晰规则,容易自我误导。机器学习版强制用回溯/前瞻窗口把规律固化,假设模型已在指定窗口上学到了价格回撤规律,EA直接开仓并按K线数持有即可,不必等趋势确认信号——那往往已到末端。 为了实用,我把回归模型连续输出转成了二元信号,避开手动交易滞后开仓的坑。想深挖斐波那契在ML目标构建里的有效性,重点就是优化前瞻与回溯窗口这两个参数。

MQL5 / C++
class="macro">#resource "\Files\EURUSD.PERIOD_H4.Fibonnacitarg-RFC.onnx" as class="type">uchar rfc_onnx[]
class="macro">#resource "\Files\EURUSD.PERIOD_H4.Fibonnacitarg-RFR.onnx" as class="type">uchar rfr_onnx[]
class="macro">#include <Random Forest.mqh>
CRandomForestClassifier rfc;
CRandomForestRegressor rfr;
input group "Models configs";
input target_var_type fib_target = CLASSIFIER; class=class="str">"cmt">//Model type
input class="type">int lookahead_window = class="num">5;
input class="type">int lookback_window = class="num">10;
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert initialization function                                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
  {
class=class="str">"cmt">//--- Setting the symbol and timeframe

   if (!MQLInfoInteger(MQL_TESTER) && !MQLInfoInteger(MQL_DEBUG))
   if (!ChartSetSymbolPeriod(class="num">0, symbol_, timeframe_))
     {
       printf("%s failed to set symbol %s and timeframe %s",__FUNCTION__,symbol_,EnumToString(timeframe_));
       class="kw">return INIT_FAILED;
     }
class=class="str">"cmt">//---
   m_trade.SetExpertMagicNumber(magic_number);
   m_trade.SetDeviationInPoints(slippage);
   m_trade.SetMarginMode();
   m_trade.SetTypeFillingBySymbol(Symbol());

class=class="str">"cmt">//---

   class="kw">switch(fib_target)
     {
      case  REGRESSOR:

         if (!rfr.Init(rfr_onnx))
          {
            printf("%s failed to initialize the random forest regressor",__FUNCTION__);
            class="kw">return INIT_FAILED;
          }

         break;
      case CLASSIFIER:

         if (!rfc.Init(rfc_onnx))
          {
            printf("%s failed to initialize the random forest classifier",__FUNCTION__);
            class="kw">return INIT_FAILED;
          }

         break;
     }
class=class="str">"cmt">//---
   class="kw">return(INIT_SUCCEEDED);
   }

「把模型信号接进 OnTick 实盘逻辑」

EA 的核心调度落在 OnTick:先用 isNewBar 拦掉旧柱的重复触发,只在每根 K 线开盘后跑一次推理,避免同一根 bar 内反复开仓刷手续费。 特征向量 x 取前一根完结 bar 的 O/H/L/C 四个值,用 iOpen/iHigh/iLow/iClose 带参数 1 拉取。这个输入维度很轻,适合在 MT5 实盘里低延迟跑随机森林类模型。 fib_target 切换两种模式:REGRESSOR 下用 rfr.predict 出斐波那契预测值,若预测值大于当前收盘价(参数 0)则 signal=1 偏多,否则 signal=0 偏空;CLASSIFIER 则直接取 rfc.predict(x).cls 的类别做信号。外汇与贵金属波动剧烈,信号仅代表概率倾向,不等于方向必现。 下单前用 SymbolInfoTick 取实时 ask/bid,volume_ 取 SYMBOL_VOLUME_MIN 做最小手数。signal==1 且无双向持仓时 m_trade.Buy 市价多;signal==0 同理 m_trade.Sell。CloseTradeAfterTime 按训练周期换算秒数平仓:分类器用 lookahead_window,回归器用 lookback_window,这是把样本外偏移锁死在可控时间窗里的关键。

MQL5 / C++
class="type">void OnTick()
  {
class=class="str">"cmt">//--- Getting signals from the model

   if (!isNewBar())
        class="kw">return;

        vector x = {
           iOpen(Symbol(), Period(), class="num">1),
           iHigh(Symbol(), Period(), class="num">1),
           iLow(Symbol(), Period(), class="num">1),
           iClose(Symbol(), Period(), class="num">1)
        };

        class="type">long signal = class="num">0;

        class="kw">switch(fib_target)
          {
           case  REGRESSOR:
             {
                  class="type">class="kw">double pred_fib = rfr.predict(x);
                  signal = pred_fib>iClose(Symbol(), Period(), class="num">0)?class="num">1:class="num">0; class=class="str">"cmt">//If the predicted fibonacci is greater than the current close price, thats bullish otherwise thats bearish signal
             }

             break;
           case CLASSIFIER:

             signal = rfc.predict(x).cls;

             break;
          }
class=class="str">"cmt">//--- Trading based on the signals received from the model

   class="type">MqlTick ticks;
   if (!SymbolInfoTick(Symbol(), ticks))
          {
             printf("Failed to obtain ticks information, Error = %d",GetLastError());
             class="kw">return;
          }

   class="type">class="kw">double volume_ = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MIN);

   if (signal == class="num">1)
     {             
            if (!PosExists(POSITION_TYPE_BUY) && !PosExists(POSITION_TYPE_SELL)) 
                m_trade.Buy(volume_, Symbol(), ticks.ask);
     }

   if (signal == class="num">0)
     {             
            if (!PosExists(POSITION_TYPE_SELL) && !PosExists(POSITION_TYPE_BUY)) 
             m_trade.Sell(volume_, Symbol(), ticks.bid);
     }
class=class="str">"cmt">//--- Closing trades 

   class="kw">switch(fib_target)
     {
      case CLASSIFIER:

        CloseTradeAfterTime((Timeframe2Minutes(Period())*lookahead_window)*class="num">60); class=class="str">"cmt">//Close the trade after a certain lookahead and according the the trained timeframe  

        break;

      case REGRESSOR:

        CloseTradeAfterTime((Timeframe2Minutes(Period())*lookback_window)*class="num">60); class=class="str">"cmt">//Close the trade after a certain lookahead and according the the trained timeframe

◍ 预测斐波那契与现价交叉判定信号

这段逻辑收口在一个条件赋值上:把前面循环算出的预测斐波那契值 pred_fib 和当前 K 线收盘价做比较。若 pred_fib 大于 iClose(Symbol(), Period(), 0) 返回的即时收盘价,signal 置 1,视为偏多信号;否则置 0,视为偏空信号。 外汇与贵金属市场受杠杆与跳空影响,这类基于历史回看窗口的线性外推信号只在趋势连续时概率占优,震荡段假信号会明显增多,实盘前务必在 MT5 策略测试器用至少 3 个月 tick 数据回测。 下方代码就是该判定的原文实现,循环 break 后直接一句话完成多空标记,没有额外平滑处理。

MQL5 / C++
      break;
   }
}
signal = pred_fib>iClose(Symbol(), Period(), class="num">0)?class="num">1:class="num">0; class=class="str">"cmt">//If the predicted Fibonacci is greater than the current close price, that&class="macro">#x27;s bullish otherwise that&class="macro">#x27;s bearish signal

画得少,看得清

回归测试里,只用 OHLC 四个原始字段喂给随机森林,模型在斐波那契水平上的判别表现明显甩开随机猜测,这说明简单输入也能榨出结构信息。 当前这套框架还没吃满特征维度,把指标数值和策略确认信号补进训练集,或换一组斐波那契位做实验,才可能抓到更复杂的走势。 股票与指数市场在长牛里的规律回调、日线这种低噪音周期,都是更值得拿 ONNX 模型去验的场子;外汇和贵金属波动更野,直接上实盘前先在 MT5 用 Experts\Fibonacci AI based.mq5 跑一遍回测。 附件里的 Random Forest.mqh 和 Python 脚本已经把训练到部署的链路铺好了,改两个 csv 就能复现,剩下的只是调特征和周期。

让小布替你跑这套回测诊断
这些把斐波那契水平转成标签、喂给分类与回归模型的做法,小布盯盘的 AIGC 已内置模板,打开对应品种页就能一键生成训练集与测试报告,你只管看概率分布做决策。

常见问题

常见泄漏来自用未来高低点反推斐波那契区间后又当作当期特征,必须按时间切分训练集与测试集,目标变量也只能用当时已出现的极值构建。
分类适合判断价格是否触及某回调位,回归适合预测触及后的回调幅度;前者标签清晰、后者受滑点影响大,实盘前倾向先用分类筛信号。
大概率不通用,贵金属与交叉盘的波动结构不同,模型参数与回调阈值需要按品种重训,外汇贵金属本身高风险,过拟合历史会放大回撤。
可以,知识库里的 AIGC 模块已封装了从画线到特征提取的脚本,绑定品种后自动产出训练与测试日志,省去自己写 MQL5 的重复劳动。
测试器默认点差与成交假设偏理想,且斐波那契价位在极端行情会连续失效,样本外表现倾向衰减,需做多周期压力测试再上资金。