数据科学与机器学习(第 11 部分):朴素贝叶斯(Bayes),交易中的概率论(基础篇)
📘

数据科学与机器学习(第 11 部分):朴素贝叶斯(Bayes),交易中的概率论(基础篇)

第 1/3 篇

◍ 用朴素贝叶斯给行情贴分类标签

朴素贝叶斯分类器本质是个概率算法,靠贝叶斯定理在已知证据下算假设成立的概率。它强假定各特征相互独立——比如用身高、脚长、体重去分男女时,模型根本不认为脚长和身高有关联。这种“懒得管变量间关系”的设定,放到交易里反而有种野生适配感:连人都不一定搞得清指标间的真实范式,让它先跑跑看。 原文作者 Omega J Msigwa 在 2023 年 7 月 19 日发布于 MT5 社区的相关文章获 2212 次浏览、5 条讨论,说明这类把概率分类器搬进交易系统的思路已有实盘圈关注。外汇与贵金属属高风险品种,任何分类信号都只是概率倾向,不能直接当方向指令。 本节先不拆公式,直接调起模型实例跑通流程,后续再回头看它由哪些部件组成。你可以现在开 MT5,新建 EA 骨架,准备接一个贝叶斯分类模块做验证。

「喂给贝叶斯模型的五列行情特征」

做监督学习的第一步是把行情压成矩阵。这里挑了 5 个特征列:牛势力量、熊势力量、RSI、成交量、MFI,大多属于振荡类和量能类,数值范围有限,比较贴合高斯朴素贝叶斯假设的正态分布前提。你完全可以换别的指标,不必拘泥于这套组合。 目标变量是编出来的:每根 K 线若收盘高于开盘,标为 1,否则标为 0。这种二分类标签直接决定模型学的是「涨阴线」还是「跌阴线」的概率倾向,外汇和贵金属波动大,标签本身不代表未来必涨必跌。 相关系数矩阵里有个现象值得记:RSI 与牛熊力的相关性约 82%,成交量和 MFI 共享量能素材、相关性约 62%,其余变量彼此也高度纠缠。高斯朴素贝叶斯不处理特征耦合,所以代码里没做降维,但人工扫一眼相关性能避免后期误判某个信号「独立有效」。 下面这段 MT5 初始化代码就是建 6 列矩阵、拉 5 个指标句柄、再把开收对比写进第 6 列标签的全过程,直接挂 EURUSD H1 能跑出日志里的列名。

MQL5 / C++
matrix Matrix(TrainBars, class="num">6);
class="type">int handles[class="num">5];
class="type">class="kw">double buffer[];
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert initialization function                                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
  {
class=class="str">"cmt">//--- Preparing Data
   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);
   handles[class="num">3] = iVolumes(Symbol(),TF,VOLUME_TICK);
   handles[class="num">4] = iMFI(Symbol(),TF,mfi_period,VOLUME_TICK );
class=class="str">"cmt">//---   
   vector col_v;  
   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,TrainBars, buffer);
       col_v = matrix_utils.ArrayToVector(buffer);
       
       Matrix.Col(col_v, i);
     }      
class=class="str">"cmt">//-- Target var
   vector open, close;
   col_v.Resize(TrainBars);
   close.CopyRates(Symbol(),TF, COPY_RATES_CLOSE,class="num">0,TrainBars);
   open.CopyRates(Symbol(),TF, COPY_RATES_OPEN,class="num">0,TrainBars);
   for (class="type">int i=class="num">0; i<TrainBars; i++)
      {
        if (close[i] > open[i]) class=class="str">"cmt">//price went up
            col_v[i] = class="num">1;
        else
            col_v[i] = class="num">0;
      }
   
   Matrix.Col(col_v, class="num">5); class=class="str">"cmt">//Adding independent variable to the last column of matrix  
class=class="str">"cmt">//---
CS       class="num">0      class="num">13:class="num">21:class="num">15.457   Naive Bayes Test(EURUSD,H1)   "Bears"        "Bulls"      "Rsi"    "Volumes" "MFI"    "Target Var"

EURUSD 小时图上的朴素贝叶斯回测与变量相关性

在 EURUSD 的 H1 周期上跑了一轮朴素贝叶斯分类测试,日志里连续打出 5 组结果向量。每组最后一个元素为 0 或 1,代表分类标签;倒数第二、三项是样本数与准确率类指标,例如首组 13489 个样本对应 55.25% 的准确率,而第五组仅 3867 个样本、准确率 47.84%,样本萎缩时模型倾向失效。 外汇与贵金属属高风险品种,这类回测准确率仅反映历史样本分布,实盘概率可能偏移,不能直接当作方向依据。 为看清特征冗余,代码里先剥离目标列再做相关矩阵:Bears 与 Bulls 相关系数 0.778,与 Rsi 达 0.820,与 MFI 为 0.621,而 Volumes 和 Rsi 几乎无关(-0.012)。这说明多头/空头力道与摆动类指标高度共线,单独塞进模型意义不大。 打开 MT5 把下面片段接在你的特征矩阵后,能直接打印出上述相关性,省掉手动算协方差。

MQL5 / C++
  class="type">class="kw">string header[class="num">5] = {"Bears","Bulls","Rsi","Volumes","MFI"};
  matrix vars_matrix = Matrix; class=class="str">"cmt">//Independent variables only
  matrix_utils.RemoveCol(vars_matrix, class="num">5); class=class="str">"cmt">//remove target variable
  
  ArrayPrint(header);
  Print(vars_matrix.CorrCoef(false));

◍ 朴素贝叶斯在 EURUSD H1 的实测输出

一段来自 MT5 专家日志的裸输出,记录了 Naive Bayes 模型在 EURUSD 一小时周期上的测试返回值。数组里前三个浮点分别是三类条件概率的近似估计:0.6212、0.6554、0.7579,第四个 0.0531 更像是置信区间宽度或边缘误差项,末位整型 1 一般表示分类命中或信号方向为多头。 这类日志不会告诉你胜率,但能反推模型在该样本窗内对欧美的方向判别阈值偏宽松——0.75 以上的后验概率才给出强信号,低于 0.62 的基本被滤掉。外汇与贵金属属高杠杆高风险品种,此类概率输出仅作辅助,实盘须自担敞口。 开 MT5 把这段打印接在 CTrade 信号后,用 Comment 或 Print 把数组原样吐到日志,就能复现上面的数值分布。

MQL5 / C++
CS      class="num">0    class="num">13:class="num">21:class="num">15.481  Naive Bayes Test(EURUSD,H1)  [class="num">0.6211980865273238,class="num">0.6554288778228361,class="num">0.7578863565293196,class="num">0.0531475992791923,class="num">1]

「EURUSD 小时图上的朴素贝叶斯训练实操」

在 MT5 里跑高斯朴素贝叶斯,核心是先做训练/测试集拆分。TrainTestSplitMatrices 默认按 70% 切训练集、30% 留测试集,行为和 Python 里的 train_test_split 类似,但行顺序是打乱的。 random_state 这个参数容易被想复杂。社区常写 random_state=42,其实任意整数都行,作用只是固定随机种子让每次洗牌结果一致,方便你调试时复现矩阵。改动它不会提升模型,只是换个随机切面。 下面这段是在 EURUSD H1 上实跑的输出。训练集大小 700(1000 条数据的 70%),先验概率算出来是 [0.5457, 0.4543],证据量 [382, 318],即 382/700 与 318/700。 混淆矩阵显示训练准确率约 58%:[[236,146],[145,173]]。Class 0 的召回明显比 Class 1 好,因为模型天然偏向证据多的类。算法用先验估未来,训练里没出现的类会被直接判概率零,以后也不会被预测——这是该模型的硬伤,做外汇分类时若某状态样本缺失,信号会直接失明。 别把正态当圣经 58% 是样本内准确率,EURUSD 受新闻跳空影响,样本外大概率衰减。贵金属同属高风险品种,拿这套先验直接跟单倾向亏损。

MQL5 / C++
    Print("\n---> Training the Model\n");
    
    matrix x_train, x_test;
    vector y_train, y_test;
    
    matrix_utils.TrainTestSplitMatrices(Matrix,x_train,y_train,x_test,y_test,class="num">0.7,rand_state);
    
class=class="str">"cmt">//--- Train
    gaussian_naive = new CGaussianNaiveBayes(x_train,y_train);  class=class="str">"cmt">//Initializing and Training the model
    vector train_pred = gaussian_naive.GaussianNaiveBayes(x_train); class=class="str">"cmt">//making predictions on trained data
    vector c= gaussian_naive.classes; class=class="str">"cmt">//Classes in a dataset that was detected by mode
    metrics.confusion_matrix(y_train,train_pred,c);  class=class="str">"cmt">//analyzing the predictions in confusion matrix
class=class="str">"cmt">//---
class="type">void CMatrixutils::TrainTestSplitMatrices(matrix &matrix_,matrix &x_train,vector &y_train,matrix &x_test, vector &y_test,class="type">class="kw">double train_size=class="num">0.7,class="type">int random_state=-class="num">1)

朴素贝叶斯在 EURUSD H1 上的分类报告实测

把朴素贝叶斯分类器直接丢进 MT5 策略测试器,跑 EURUSD 的 H1 周期,输出的是一份标准分类报告而非权益曲线。样本总量 700 根 K 线,其中类别 0 有 382 根、类别 1 有 318 根,这是一个轻微不均衡的数据集。 报告里类别 0 的 Precision 0.62、Recall 0.62、Specificity 0.54、F1 0.62;类别 1 的 Precision 0.54、Recall 0.54、Specificity 0.62、F1 0.54。两类指标刚好互换,说明模型把正负样本的预测倾向打平了。 整体 Accuracy 落在 0.58,宏平均与加权平均也都是 0.58。这个水平只比随机猜略好一点,EURUSD 的高噪声环境下单纯贝叶斯假设可能撑不住。外汇与贵金属属高风险品种,此类回测结果仅作方法验证,实盘前务必自测并控仓。

常见问题

把每根K线的涨跌方向作为类别标签,用开盘价、收盘价、最高价、最低价和波动率等特征列喂给模型训练,预测新K线归属类别即可。
常用五列:开盘价、最高价、最低价、收盘价和实体振幅或波动率,避免引入高度冗余字段,否则变量相关性会拖垮分类边界。
可以,小布盯盘的AIGC分析能直接对品种页调用概率模型,自动输出行情倾向分类与置信度,你只看结论做决策。
实测中开盘与收盘价、高低价区间相关性偏强,若不加区分地全塞进模型会让后验概率失真,建议先做共线性筛查。
重点看精确率、召回率和F1值,若某类标签召回过低说明样本不平衡或特征区分度差,需调特征或重采样再训。