MetaTrader 5 和 R 进行算法交易新手指南·进阶篇
◍ MT5R 怎么打通 R 和 MT5
要让 R 里的统计模型直接驱动 MT5 下单,核心不是写一堆 DLL,而是建一条常驻的双工通道。MT5R 在 RStudio 与 MetaTrader 5 终端之间用 WebSocket 拉起全双工通信,指令和行情可以同向并发,不像老式 HTTP 轮询那样卡节奏。 通道要活起来,MT5 终端必须监听一个固定端口,RStudio 会话也得在同一端口上收发。MT5R 自带一个用 MQL5 写的 EA 专门干监听的活,源码开放,你想加逻辑直接改。 我们随文给的定制版 EA 在开源基础上塞进了自动追踪止损和自动获利了结,省得你在 R 侧反复发平仓指令。外汇和贵金属杠杆高、滑点突兀,这套自动退出逻辑也只是降低手动延误,不保证不回撤。
把 MT5R 接进 R 画图流水线
EA 放进终端后,先按文件→打开数据文件夹,进 .\MQL5\experts\ 把 MT5R 丢进 Experts 目录,挂到图表上并放行网络权限,R 那边才能读到行情。回到 RStudio,依次载入 mt5R、xts、quantmod 三个包,用 MT5.Ping() 探一下通道,返回 TRUE 才说明 EA 和终端握上手。 MT5R 不碰账号登录,只解决行情抓取。GetSymbol 要填品种名、分钟级周期(日线给 1440)和行数,数据上来是旧数据在顶、现价在底;把 xts 设成 TRUE,直接转成时间序列对象,日期轴和后续加指标都省事。 示例里抓的是 Volatility 75 Index,周期参数 iTF=1(即 1 分钟),iRows=5000,也就是最近 5000 根分钟棒。lineChart 出裸线图,addRSI(n=60) 把 60 周期 RSI 叠上去——这类高波动指数品种,RSI 阈值区可能和常规外汇对错位,上机前自己核一遍。 下面这段是可直抄的 R 代码,逐行对应上面动作:加载三个库、Ping 探活、设品种变量、抓 5000 行 1 分钟数据、画线、叠 RSI。
class="macro">#Import the MT5R Library library(mt5R) class="macro">#Import xts to help us plot library(xts) class="macro">#Import quantmod to help us plot library(quantmod) class="macro">#Check if our connection is established MT5.Ping() class="macro">#Global variables MARKET_SYMBOL <- "Volatility class="num">75 Index" class="macro">#Request historical price data price_data <- MT5.GetSymbol(MARKET_SYMBOL, iTF = class="num">1, iRows=class="num">5000,xts = TRUE) class="macro">#Plotting a line chart lineChart(price_data, name = MARKET_SYMBOL) class="macro">#We can also add technical indicators to the plot addRSI(n=class="num">60)
「特征拼接与按时间切分训练集」
把指标真正写进数据表,和只在图上画出来是两回事。这里用 quantmod 把 20 周期 SMA、RSI、ATR 算出来并挂到原表列上:SMA 吃收盘价,RSI 吃收盘价,ATR 必须喂 High/Low/Close 三列。挂完先 na.omit 把前 19 行算不全的缺失值整行删掉,否则后面模型会报维度错。 目标列靠下一根收盘价做判定:Next_Close 用 lag(Close,-1) 取错位,ifelse(Next_Close > Close,1,0) 标成上涨类 1、否则 0。这步决定了你后面训的是「下一根是否收更高」的二分类,而不是回归预测点位。 时间序列最忌随机洗牌。原文用前 4000 行做训练、4001–4980 行做测试,共 980 行外样本,严格按时间顺序切,避免未来信息漏进训练集造成虚高胜率。外汇与贵金属波动受消息驱动,这种泄漏会让回测漂亮、实盘亏损,属高风险陷阱。 模型选了 MASS 包里的 QDA,调用 qda(Target ~ Open+High+Low+Close, data=train_set)。输出里两类先验几乎对半(0.49925 / 0.50075),组均值显示标签 1 的 OHLC 整体比标签 0 低约 300 点,说明样本期内「收更低」的那类开盘结构偏弱势。 别把正态当圣经 QDA 假设各类协方差不同,不要求特征联合正态,但实战里若某类样本极少,组内散度矩阵会估歪,MT5 导出的 tick 数据重采样后建议先 table(Target) 看平衡度再跑。
class="macro">#Add moving average price_data$SMA_20 <- SMA(price_data$Close,n = class="num">20) class="macro">#Add RSI to the dataframe price_data$RSI_20 <- RSI(price_data$Close,n=class="num">20) class="macro">#Add ATR to the dataframe price_data$ATR_20 <- ATR(price_data[,c("High","Low","Close")], n=class="num">20) class="macro">#Drop missing values price_data <- na.omit(price_data) class="macro">#Next close price price_data$Next_Close <- lag(price_data$Close,-class="num">1) class="macro">#Setting up our target price_data$Target <- ifelse( ( (price_data$Next_Close) > price_data$Close) , class="num">1 , class="num">0) class="macro">#Train test split train_set <- price_data[class="num">1:class="num">4000,] train_y <- price_data[class="num">1:class="num">4000,c("Target")] test_set <- price_data[class="num">4001:class="num">4980,] test_y <- price_data[class="num">4001:class="num">4980,c("Target")] class="macro">#Fitting models library(MASS) class="macro">#Quadratic Discriminant Analysis class="macro">#Using OHLC Data qda <- qda(Target ~ Open+High+Low+Close,data = train_set) qda
◍ 涨势识别比跌势更准
把测试集丢进自定义二次判别分析(QDA)模型后,用混淆矩阵对比预测类别与真实标签,能直接看出模型对上涨走势的命中率高于下跌走势。这种偏科在外汇与贵金属短线分类里很常见,样本里上行波动结构往往更规整,下行常伴随跳空与流动性断裂,导致特征边界模糊。 下面这段 R 代码就是产出混淆矩阵的最小闭环:先对测试集做 predict,提取 class 向量,再用 table 横竖对齐预测值与 test_y。注意它跑在 R 环境而非 MT5,但矩阵结论可以拿来反推你 MT5 里信号过滤器的阈值——比如对模型易误判的下跌信号,手动加一层波动率过滤。外汇与贵金属杠杆高,模型偏科不代表实盘胜率,需用 MT5 历史回测交叉验证。 [CODE] #Evaluating model performance #Custom Quadratic Discriminant Analysis qda_predictionts <- predict(qda,test_set) qda_predictionts <- qda_predictionts$class #Confusion matrix table(qda_predictionts,test_y) [/CODE] 逐行拆解:第 1~2 行是注释,标明在做模型评估与自定义 QDA;第 3 行对 test_set 生成预测对象;第 4 行从预测对象里抠出类别标签向量;第 5~6 行用 table 把预测类别和真实 test_y 交叉成矩阵,行列表头即混淆矩阵。打开 RStudio 粘进去就能复现图 9 的结论。
class="macro">#Evaluating model performance class="macro">#Custom Quadratic Discriminant Analysis qda_predictionts <- predict(qda,test_set) qda_predictionts <- qda_predictionts$class class="macro">#Confusion matrix table(qda_predictionts,test_y)
把预测信号接进 MT5 的持仓开关
要让模型真正下单,先得有个状态位记住上一笔方向。这里用 last_trade 存最近一次动作:1 代表买、0 代表卖、-1 代表空仓,后面判断「行情是否反转」就靠它跟新预测比对。外汇与贵金属杠杆高,实盘跑这套逻辑前务必在策略测试器用历史数据验证信号胜率,切勿直接上真实账户。 主流程是一个死循环 while(TRUE),里面先抓当前品种 M1 的两根 K 线、取最新一根丢给 QDA 模型出 class(1 或 0)。接着用 MT5$positions_total() 看有没有仓:没仓就按预测方向开最小手数,并把 last_trade 写成对应值;有仓且预测值不等于 last_trade,说明模型倾向反向波动,立刻 MT5$Close 平掉并重置状态位。 循环尾巴的 Sys.sleep(60) 是关键节奏阀——它把检查频率锁在每根一分钟柱一次,避免在同一根 K 线内反复刷单。你在 R 里用 reticulate 调 MT5 包时,若发现成交延迟,先确认这个 sleep 是否因系统负载被拉长,而非模型本身失效。 别把正态当圣经 QDA 假设各类别协方差不同,但行情突变时分布会漂移,last_trade 的比对只能过滤同根柱内的反向噪音,跨周期拐点仍可能漏判,建议叠加 ATR 过滤再上实盘。
class="macro">#Keeping track of the last trade last_trade <- -class="num">1 while(TRUE){ class="macro">#Fetching current market data print("Fetching market information") data <- MT5.GetSymbol(MARKET_SYMBOL,iTF=class="num">1, iRows = class="num">2) data <- data[class="num">1,] class="macro">#Forecasting market move qda_forecast <- predict(qda,data) qda_forecast <- qda_forecast$class print("Model forecast: ") print(qda_forecast) class="macro">#Checking if we have no open positions current_positions <- MT5$positions_total() class="macro">#If we have no open positions, open a position following the model forecast if(current_positions == class="num">0){ print("We have no open positions. Opening a new position") class="macro">#A Forecast of class="num">1 means buy if(qda_forecast == class="num">1){ print("Opening Buy Position") MT5$Buy(MARKET_SYMBOL,symbol_info$volume_min) last_trade <- class="num">1 } class="macro">#A Forecast of class="num">0 means sell if (qda_forecast == class="num">0){ print("Opening Sell Position") MT5$Sell(MARKET_SYMBOL,symbol_info$volume_min) last_trade <- class="num">0 } } else{ class="macro">#Are we anticipating a move against our open position? if(last_trade != qda_forecast){ class="macro">#If we are, let&class="macro">#x27;s close our position print("Closing open position") MT5$Close(MARKET_SYMBOL) class="macro">#Reset last trade last_trade <- -class="num">1 } else{ class="macro">#Otherwise everything is expected to be fine print("The current position is aligned with the market") info <- MT5$account_info() print("Current Profit") print(info$profit) } } class="macro">#Wait for a new candle to form Sys.sleep(class="num">60) }
「R 与 MT5 搭管道的落地边界」
把 R 和 MetaTrader 5 接起来跑实时算法,难点不在语法,而在依赖管理。原文给出的 MT5R EA 定制版(mq5 文件 151.33 KB)能自主挂止损止盈,初学者改几个参数就能跑,互补包把单包的短板补上了,整体依赖被压到最小。 但评论区有个真实坑:有用户在 MT4 里用同类 R 桥接库,R 一崩整个终端跟着崩。作者本人只在 MT5 做数据分析、不在实盘阶段走 R,所以没踩过。你要真拿去跑,建议先在 MT5 上隔离测试,别把分析进程和下单进程绑死。 外汇和贵金属杠杆高、滑点狠,这类桥接框架只是工具,不替你管风险。开 MT5 把附带的 mt5R_v0_1_5.mq5 拖进策略测试器,断网跑一遍历史数据,比看十篇软文都实在。