将 MQL5 与数据处理包集成(第 4 部分):大数据处理·综合运用
「把多指标塞进特征数组交给模型」
EA 在 OnTick 里先把技术面量化为数值,再统一丢给预测函数。下面这段 MT5 代码就是典型的「指标采集 → 特征组装 → 信号分发」骨架,直接挂 EURUSD 或 XAUUSD 的 M5 周期就能跑通逻辑。 代码先取了 MA20、MA50 两条均线(SMA、收盘价),RSI 周期固定 14,MACD 用 12/26/9 经典参数。注意 MACD 必须通过 iMACD 拿句柄,再用 CopyBuffer 分别拷主图、信号线、柱线三个缓冲区,任何一次拷贝返回 ≤0 都会在日志里报警,但不会中断后续执行。 五个特征按固定顺序进数组:features[0]~[4] 分别是 MA20、MA50、RSI、MACD、SignalLine。GetPrediction 返回 1 触发 MBuy(),返回 -1 触发 MSell(),中间值不动作。外汇与贵金属杠杆高,这类信号仅代表模型当时的概率倾向,实盘前务必在策略测试器用至少 3 个月 tick 数据回验。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Expert tick function | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnTick(){ class=class="str">"cmt">// Calculate indicators class="type">class="kw">double MA20 = iMA(_Symbol, PERIOD_CURRENT, class="num">20, class="num">0, MODE_SMA, PRICE_CLOSE); class="type">class="kw">double MA50 = iMA(_Symbol, PERIOD_CURRENT, class="num">50, class="num">0, MODE_SMA, PRICE_CLOSE); class="type">class="kw">double RSI = iRSI(_Symbol, PERIOD_CURRENT, class="num">14, PRICE_CLOSE); class=class="str">"cmt">// Declare arrays to hold MACD data class="type">class="kw">double MACD_Buffer[class="num">1], SignalLine_Buffer[class="num">1], Hist_Buffer[class="num">1]; class=class="str">"cmt">// Get MACD handle class="type">int macd_handle = iMACD(NULL, class="num">0, class="num">12, class="num">26, class="num">9, PRICE_CLOSE); if (macd_handle != INVALID_HANDLE) { class=class="str">"cmt">// Copy the most recent MACD values into buffers if (CopyBuffer(macd_handle, class="num">0, class="num">0, class="num">1, MACD_Buffer) <= class="num">0) Print("Failed to copy MACD"); if (CopyBuffer(macd_handle, class="num">1, class="num">0, class="num">1, SignalLine_Buffer) <= class="num">0) Print("Failed to copy Signal Line"); if (CopyBuffer(macd_handle, class="num">2, class="num">0, class="num">1, Hist_Buffer) <= class="num">0) Print("Failed to copy Histogram"); } class=class="str">"cmt">// Assign the values from the buffers class="type">class="kw">double MACD = MACD_Buffer[class="num">0]; class="type">class="kw">double SignalLine = SignalLine_Buffer[class="num">0]; class=class="str">"cmt">// Assign features class="type">class="kw">double features[class="num">5]; features[class="num">0] = MA20; features[class="num">1] = MA50; features[class="num">2] = RSI; features[class="num">3] = MACD; features[class="num">4] = SignalLine; class=class="str">"cmt">// Get prediction class="type">class="kw">double signal = GetPrediction(features); if (signal == class="num">1){ MBuy(); class=class="str">"cmt">// Adjust lot size } else if (signal == -class="num">1){ MSell(); } }
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Expert tick function | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void OnTick(){ class=class="str">"cmt">// Calculate indicators class="type">class="kw">double MA20 = iMA(_Symbol, PERIOD_CURRENT, class="num">20, class="num">0, MODE_SMA, PRICE_CLOSE); class="type">class="kw">double MA50 = iMA(_Symbol, PERIOD_CURRENT, class="num">50, class="num">0, MODE_SMA, PRICE_CLOSE); class="type">class="kw">double RSI = iRSI(_Symbol, PERIOD_CURRENT, class="num">14, PRICE_CLOSE); class=class="str">"cmt">// Declare arrays to hold MACD data class="type">class="kw">double MACD_Buffer[class="num">1], SignalLine_Buffer[class="num">1], Hist_Buffer[class="num">1]; class=class="str">"cmt">// Get MACD handle class="type">int macd_handle = iMACD(NULL, class="num">0, class="num">12, class="num">26, class="num">9, PRICE_CLOSE); if (macd_handle != INVALID_HANDLE) { class=class="str">"cmt">// Copy the most recent MACD values into buffers if (CopyBuffer(macd_handle, class="num">0, class="num">0, class="num">1, MACD_Buffer) <= class="num">0) Print("Failed to copy MACD"); if (CopyBuffer(macd_handle, class="num">1, class="num">0, class="num">1, SignalLine_Buffer) <= class="num">0) Print("Failed to copy Signal Line"); if (CopyBuffer(macd_handle, class="num">2, class="num">0, class="num">1, Hist_Buffer) <= class="num">0) Print("Failed to copy Histogram"); } class=class="str">"cmt">// Assign the values from the buffers class="type">class="kw">double MACD = MACD_Buffer[class="num">0]; class="type">class="kw">double SignalLine = SignalLine_Buffer[class="num">0]; class=class="str">"cmt">// Assign features class="type">class="kw">double features[class="num">5]; features[class="num">0] = MA20; features[class="num">1] = MA50; features[class="num">2] = RSI; features[class="num">3] = MACD; features[class="num">4] = SignalLine; class=class="str">"cmt">// Get prediction class="type">class="kw">double signal = GetPrediction(features); if (signal == class="num">1){ MBuy(); class=class="str">"cmt">// Adjust lot size } else if (signal == -class="num">1){ MSell(); } }
◍ 用 Flask 把 BTC 模型预测挂成接口
想把离线训好的机器学习模型用进 BTC 决策,不一定非要嵌进 MT5。起一个轻量 web API,让盯盘工具 POST 一段行情特征就能拿回预测,是更灵活的接法。 下面这段 Python 用了 Flask 框架,加载一个名为 btc_trading_model.pkl 的 joblib 模型文件,在本地 5000 端口暴露 /predict 接口,只接受 POST 的 JSON 行情数据并返回预测列表。
from flask class="kw">import Flask, request, jsonify class="kw">import joblib class="kw">import pandas as pd # Load the model model = joblib.load(&class="macro">#x27;btc_trading_model.pkl&class="macro">#x27;) app = Flask(__name__) @app.route(&class="macro">#x27;/predict&class="macro">#x27;, methods=[&class="macro">#x27;POST&class="macro">#x27;]) def predict(): data = request.json df = pd.DataFrame(data) prediction = model.predict(df) class="kw">return jsonify(prediction.tolist()) app.run(port=class="num">5000)
from flask class="kw">import Flask, request, jsonify class="kw">import joblib class="kw">import pandas as pd # Load the model model = joblib.load(&class="macro">#x27;btc_trading_model.pkl&class="macro">#x27;) app = Flask(__name__) @app.route(&class="macro">#x27;/predict&class="macro">#x27;, methods=[&class="macro">#x27;POST&class="macro">#x27;]) def predict(): data = request.json df = pd.DataFrame(data) prediction = model.predict(df) class="kw">return jsonify(prediction.tolist()) app.run(port=class="num">5000)
一点提醒
把历史 BTC/USD 的 H1 数据清洗后抽出的 MA、RSI、MACD 特征喂给模型,训出的信号预测器通过 Flask API 对外服务,MT5 里的 EA 只负责抓实时指标、发请求、按回包下单——这条链路在 5.08 KB 的 BTC-Big-DataH.mq5 里已经跑通。 对外汇与贵金属来说,这类 ML+指标混合方案只是把人工判断换成概率输出,市场突变时模型滞后不可避免,杠杆品种爆仓风险始终存在。 真要落地,先拿原文附的 162.02 KB BTCUSD_H1.csv 在本地复现 notebook,再只开模拟账户接 EA,别一上来就实盘扛单。