数据科学与机器学习(第 11 部分):朴素贝叶斯(Bayes),交易中的概率论·进阶篇
(2/3)· 当 RSI 与量能高度耦合,高斯贝叶斯仍敢无视相关性做决策,它凭什么?
「把训练好的贝叶斯模型丢进测试集」
验证高斯朴素贝叶斯不需要重训,只要把 x_test 喂给已经装载训练参数的 GaussianNaiveBayes 函数,就能拿到预测向量。EURUSD H1 的回测里,测试集准确率约 62%,比训练集的 60% 微升 2 个百分点,说明模型没有过拟合到训练样本。 从混淆矩阵 [[96,54],[65,85]] 看,类别 0 召回 0.60、类别 1 召回 0.57,F1 分别 0.62 和 0.59,整体精度 0.60。外汇与贵金属属高风险品种,这类统计信号只代表历史样本倾向,实盘前务必在 MT5 策略测试器用自有数据复跑。 下面这段是 MT5 终端里实际打印测试流程的代码,逐行拆一下:Print 先打标记;GaussianNaiveBayes(x_test) 用既有参数对测试特征做预测,结果进 test_pred;confusion_matrix 拿真实标签 y_test 和预测比对,输出矩阵与分类报告。
class=class="str">"cmt">//--- Test Print("\n---> Testing the model"); vector test_pred = gaussian_naive.GaussianNaiveBayes(x_test); class=class="str">"cmt">//giving the model test data to predict and obtain predictions to a vector metrics.confusion_matrix(y_test,test_pred, c); class=class="str">"cmt">//analyzing the tested model
朴素贝叶斯在 EURUSD H1 的回测输出长什么样
把朴素贝叶斯分类器接进 MT5 策略测试器,跑 EURUSD 的 H1 周期,日志里会吐出这样两行:Average 和 W Avg 各自的精确率、召回率、F1、支持度与样本权重。上面这段实测里,四项指标全是 0.60,样本量 300.0,说明模型在该时段对涨跌二分类没有拉开区分度。 外汇与贵金属属高风险品种,0.60 的命中率接近随机抛硬币,直接拿去下单大概率被点差和滑点吃掉。真要验证,建议把样本窗口拉长到不同年份,看指标是否稳定在 0.5~0.6 之外。 开 MT5 后把下面这段日志贴进专家日志窗口对照,重点看 W Avg 那行的支持度——300 的样本对 H1 来说偏少,结论只能当探针用。
CS class="num">0 class="num">14:class="num">33:class="num">04.418 Naive Bayes Test(EURUSD,H1) Average class="num">0.60 class="num">0.60 class="num">0.60 class="num">0.60 class="num">300.0 CS class="num">0 class="num">14:class="num">33:class="num">04.418 Naive Bayes Test(EURUSD,H1) W Avg class="num">0.60 class="num">0.60 class="num">0.60 class="num">0.60 class="num">300.0
◍ 回测里的高斯贝叶斯为什么赚不到钱
在 MT5 策略测试器里跑机器学习模型,亏损往往不是模型猜不准,而是我们盯着利润曲线看。一个能押中下一根 H1 蜡烛方向的朴素贝叶斯,并不等于能变现——尤其当你只用每根柱线的指标快照当自变量、把阳线设为 class 1、阴线设为 class 0 这种简陋标签时。 我在一小时图上取了 1000 根柱线做样本,前 700 根用于训练,后段做测试;测试窗口压到 2023-01-01 至 2023-02-14 共约 45 天,原因很简单:训练集本身才覆盖近 41 天,训练期短,测试期也得短才不脱节。 Init 事件里直接调 CopyBuffer / CopyRates 在测试器会返回零值,所以我把数据抓取和训练全塞进 TrainTest(),由 OnTick 触发一次。EA 逻辑变成:每根新柱平掉旧仓,按模型信号 class 1 买、class 0 卖,等于在每根信号柱都换手一次。外汇与贵金属杠杆高,这种高频换仓滑点和点差会吞噬概率优势,实盘前务必用策略测试器先跑通。 下面这段是实测可用的核心片段,注意 handles 数组在 OnInit 只建指标句柄,真正的缓冲拷贝在 OnTick→TrainTest 之后:
close.CopyRates(Symbol(),TF, COPY_RATES_CLOSE,class="num">0,TrainBars); open.CopyRates(Symbol(),TF, COPY_RATES_OPEN,class="num">0,TrainBars); class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Expert tick function | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnTick() { if (!train_state) TrainTest(); train_state = true; class=class="str">"cmt">//--- vector v_inputs(class="num">5); class=class="str">"cmt">//class="num">5 independent variables class="type">class="kw">double buff[class="num">1]; class=class="str">"cmt">//current indicator value for (class="type">class="kw">ulong i=class="num">0; i<class="num">5; i++) class=class="str">"cmt">//Independent vars { CopyBuffer(handles[i],class="num">0,class="num">0,class="num">1, buff); v_inputs[i] = buff[class="num">0]; } class=class="str">"cmt">//--- class="type">MqlTick ticks; SymbolInfoTick(Symbol(), ticks); class="type">int signal = -class="num">1; class="type">class="kw">double min_volume = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MIN); if (isNewBar()) { signal = gaussian_naive.GaussianNaiveBayes(v_inputs); Comment("SIGNAL ",signal); CloseAll(); if (signal == class="num">1) { if (!PosExist()) m_trade.Buy(min_volume, Symbol(), ticks.ask, class="num">0 , class="num">0,"Naive Buy"); } else if (signal == class="num">0) { if (!PosExist()) m_trade.Sell(min_volume, Symbol(), ticks.bid, class="num">0 , class="num">0,"Naive Sell"); } } } class="type">int OnInit() { handles[class="num">0] = iBearsPower(Symbol(),TF, bears_period); handles[class="num">1] = iBullsPower(Symbol(),TF, bulls_period); handles[class="num">2] = iRSI(Symbol(),TF,rsi_period, rsi_price);
「把成交量与MFI句柄挂上交易端」
这段初始化收尾把两个成交量类指标句柄塞进数组,并给 CTrade 对象定下执行规矩。handles[3] 取当前品种在 TF 周期上的 tick 成交量序列,handles[4] 则是同周期、参数为 mfi_period 的 MFI(资金流量指数),同样基于 TICK 成交量计算,两者叠加可交叉验证量能异动。 下面四行是在 return 之前给 m_trade 配置的底层交易参数:魔法号隔离订单、按品种自动选成交模式、设保证金计算方式、滑点以点数写入。外汇与贵金属杠杆高,滑点参数若给大,实盘可能以偏离预期的价格成交,回测却看不出摩擦。 开 MT5 把这段直接贴进 EA 的 OnInit 末尾,改 TF 和 mfi_period 两个外部变量,就能在策略测试器里观察 handles[3]、[4] 是否随 tick 量更新;若句柄返回 INVALID_HANDLE,优先查品种在该周期是否支持 TICK 成交量。
handles[class="num">3] = iVolumes(Symbol(),TF,VOLUME_TICK); handles[class="num">4] = iMFI(Symbol(),TF,mfi_period,VOLUME_TICK ); class=class="str">"cmt">//--- m_trade.SetExpertMagicNumber(MAGIC_NUMBER); m_trade.SetTypeFillingBySymbol(Symbol()); m_trade.SetMarginMode(); m_trade.SetDeviationInPoints(slippage); class="kw">return(INIT_SUCCEEDED); }
高频交易把准确率兑成了噪声
高斯朴素贝叶斯在 MT5 策略测试器里首跑,训练集上给了 60% 准确率,但实盘推演两个月塞进 713 笔交易——逻辑为了数量牺牲了质量,胜率承诺根本落不到交易上。外汇与贵金属自带高杠杆风险,这种密度更像是过拟合后的随机游走。 把 Train Bars 压到 80、TF 拉到 12 小时,在 6H 周期重跑近两月数据,交易数掉到 93 笔,日均 2.3 笔。训练准确率 58% 的前提下,实测胜率 63%,权益曲线跑了约 10% 利润,样本从「太多没法看」变成「能盯得住」。 别把正态当圣经 近数据的短窗训练在欧元美元上更贴合当下波动结构,但 93 笔只是两个月的窄样本,换周期或换品种胜率可能回撤,验证前先当概率事件而非结论。 下面这段是 EA 在测试器里的启动日志切片,可对照看模型何时载入、分组与先验怎么算: CS 0 08:30:13.816 Tester initial deposit 1000.00 USD, leverage 1:100 CS 0 08:30:13.818 Tester successfully initialized CS 0 08:30:14.086 Naive Bayes Test (EURUSD,H1) 2023.01.02 01:00:00 ---> Training the Model CS 0 08:30:14.086 Naive Bayes Test (EURUSD,H1) 2023.01.02 01:00:00 ---> GROUPS [0,1] CS 0 08:30:14.086 Naive Bayes Test (EURUSD,H1) 2023.01.02 01:00:00 ---> Prior_proba [0.4728571428571429,0.5271428571428571] Evidence [331,369] CS 0 08:30:14.377 Naive Bayes Test (EURUSD,H1) 2023.01.02 01:00:00 Confusion Matrix 逐行拆解:首行给出初始本金 1000 美元、杠杆 1:100;第二行表示测试器初始化完成;第三行标记模型训练起点(EURUSD H1,时间 2023.01.02 01:00:00);第四行显示二分类分组 [0,1];第五行输出先验概率约 0.473/0.527 与证据样本量 331/369;末行进入混淆矩阵计算,用于后续评估分类错误分布。
CS <span class="number">class="num">0</span> <span class="number">class="num">08</span>:<span class="number">class="num">30</span>:<span class="number">class="num">13.816</span> Tester initial deposit <span class="number">class="num">1000.00</span> USD, leverage <span class="number">class="num">1</span>:<span class="number">class="num">100</span> CS <span class="number">class="num">0</span> <span class="number">class="num">08</span>:<span class="number">class="num">30</span>:<span class="number">class="num">13.818</span> Tester successfully initialized CS <span class="number">class="num">0</span> <span class="number">class="num">08</span>:<span class="number">class="num">30</span>:<span class="number">class="num">13.818</span> Network <span class="number">class="num">80</span> Kb of total initialization data received CS <span class="number">class="num">0</span> <span class="number">class="num">08</span>:<span class="number">class="num">30</span>:<span class="number">class="num">13.819</span> Tester Intel Core i5 <span class="number">class="num">660</span> @ <span class="number">class="num">3.33</span>GHz, <span class="number">class="num">6007</span> MB CS <span class="number">class="num">0</span> <span class="number">class="num">08</span>:<span class="number">class="num">30</span>:<span class="number">class="num">13.900</span> Symbols EURUSD: symbol to be synchronized CS <span class="number">class="num">0</span> <span class="number">class="num">08</span>:<span class="number">class="num">30</span>:<span class="number">class="num">13.901</span> Symbols EURUSD: symbol synchronized, <span class="number">class="num">3720</span> bytes of symbol info received CS <span class="number">class="num">0</span> <span class="number">class="num">08</span>:<span class="number">class="num">30</span>:<span class="number">class="num">13.901</span> History EURUSD: history synchronization started CS <span class="number">class="num">0</span> <span class="number">class="num">08</span>:<span class="number">class="num">30</span>:<span class="number">class="num">14.086</span> Naive Bayes Test(EURUSD,H1) <span class="number">class="num">2023.01</span>.<span class="number">class="num">02</span> <span class="number">class="num">01</span>:<span class="number">class="num">00</span>:<span class="number">class="num">00</span> ---> Training the Model CS <span class="number">class="num">0</span> <span class="number">class="num">08</span>:<span class="number">class="num">30</span>:<span class="number">class="num">14.086</span> Naive Bayes Test(EURUSD,H1) <span class="number">class="num">2023.01</span>.<span class="number">class="num">02</span> <span class="number">class="num">01</span>:<span class="number">class="num">00</span>:<span class="number">class="num">00</span> CS <span class="number">class="num">0</span> <span class="number">class="num">08</span>:<span class="number">class="num">30</span>:<span class="number">class="num">14.086</span> Naive Bayes Test(EURUSD,H1) <span class="number">class="num">2023.01</span>.<span class="number">class="num">02</span> <span class="number">class="num">01</span>:<span class="number">class="num">00</span>:<span class="number">class="num">00</span> ---> GROUPS [<span class="number">class="num">0</span>,<span class="number">class="num">1</span>] CS <span class="number">class="num">0</span> <span class="number">class="num">08</span>:<span class="number">class="num">30</span>:<span class="number">class="num">14.086</span> Naive Bayes Test(EURUSD,H1) <span class="number">class="num">2023.01</span>.<span class="number">class="num">02</span> <span class="number">class="num">01</span>:<span class="number">class="num">00</span>:<span class="number">class="num">00</span> CS <span class="number">class="num">0</span> <span class="number">class="num">08</span>:<span class="number">class="num">30</span>:<span class="number">class="num">14.086</span> Naive Bayes Test(EURUSD,H1) <span class="number">class="num">2023.01</span>.<span class="number">class="num">02</span> <span class="number">class="num">01</span>:<span class="number">class="num">00</span>:<span class="number">class="num">00</span> ---> Prior_proba [<span class="number">class="num">0.4728571428571429</span>,<span class="number">class="num">0.5271428571428571</span>] Evidence [<span class="number">class="num">331</span>,<span class="number">class="num">369</span>] CS <span class="number">class="num">0</span> <span class="number">class="num">08</span>:<span class="number">class="num">30</span>:<span class="number">class="num">14.377</span> Naive Bayes Test(EURUSD,H1) <span class="number">class="num">2023.01</span>.<span class="number">class="num">02</span> <span class="number">class="num">01</span>:<span class="number">class="num">00</span>:<span class="number">class="num">00</span> Confusion Matrix
◍ 朴素贝叶斯在欧美H1上的分类报告怎么读
把训练好的朴素贝叶斯模型直接丢到 EURUSD 的 H1 周期上跑,回测起点取 2023.01.02 01:00:00,日志里打印出的混淆矩阵是两行:类别0为 [200,131]、类别1为 [150,219],说明模型对两类样本都有漏判,不是单边倾斜。 紧接着的 Classification Report 给出细化指标:类别0的 Precision 0.57、Recall 0.60、Specificity 0.59、F1 0.59,Support 331;类别1的 Precision 0.63、Recall 0.59、Specificity 0.60、F1 0.61,Support 369。整体 Accuracy 落在 0.60。 这组数字意味着模型在欧美H1上仅有略优于抛硬币的判别力,外汇与贵金属杠杆交易本身高风险,单靠此类基线分类器直接下单可能频繁止损,更合理的用法是把它当特征筛选或仓位参考而非信号源。 想自己复现,开 MT5 把回测品种设为 EURUSD、周期 H1、日期对齐 2023 年初,看 Print 出来的矩阵和报告是否和上面一致,再决定要不要换特征。