如何利用 MQL5 创建简单的多币种智能交易系统(第 6 部分):两条 RSI 指标相互交叉·进阶篇
◍ 移动止损触发条件的代码骨架
这段逻辑是自动改单函数的核心判断分支,只在满足特定价格关系时才动手调止损止盈。
| bool modsel = (price<modminsl && modselsl<modstart && (pos_stop==0.0 | modselsl<pos_stop)); 这一行先算一个布尔量:当前价低于模块最小止损线、候选止损小于初始止损、且持仓止损为空或候选止损更优。 |
|---|
if(modsel && netp>minprofit) 才是真正下单门槛——除了上面的价格条件,还必须保证净盈利大于最小利润阈值 minprofit,否则不碰仓位。 满足条件后只调一次 mc_trade.PositionModify(symbol,modselsl,modseltp),用候选止损和候选止盈改写持仓。外汇与贵金属杠杆高,这类自动改单在滑点行情中可能失效,建议在 MT5 策略测试器用 2023 年 XAUUSD 的 M15 数据跑一遍看触发频率。
class="type">bool modsel = (price<modminsl && modselsl<modstart && (pos_stop==class="num">0.0||modselsl<pos_stop)); class=class="str">"cmt">//-- if(modsel && netp>minprofit) { modist=mc_trade.PositionModify(symbol,modselsl,modseltp); } } } } class=class="str">"cmt">//-- class="kw">return(modist); class=class="str">"cmt">//--- } class=class="str">"cmt">//-end ModifySLTP() class=class="str">"cmt">//---------//
「多币种 RSI 交叉 EA 的程序骨架与开仓逻辑」
这套多币种智能系统的输入层先靠一堆枚举把交易边界框死:时区、分钟、10 个可选品种、资金管理模式、指标计算周期都被限定在 M5 到 D1 之间。若 Magic Number 留空,EA 会顺手接管图表上的手工单,这点写 EA 时容易忽略,却直接决定谁在控单。 品种名处理走 HandlingSymbolArrays() → SetSymbolNamePS() 的调用链,后者专门兼容带前缀/后缀的经纪商符号(比如 mEURUSDp)。拼写错或验证不过,EA 会弹警告并自删,不会静默跑废单。 OnInit() 里必调的 RSIxRSI_MCEA_Config() 负责把品种、周期、指标句柄一次性建好;OnTick() 则只做一件事——调 ExpertActionTrade(),开平、尾随、止盈全塞在这一个函数里。时段开关由 Trade_session() 逐层下钻到 Time_Zone() 控制,默认开自定义时段,起止时分由交易者填。 开仓信号来自 GetOpenPosition():它先抓两个 RSI(快线 ma_period=10、慢线 ma_period=30,均用 PRICE_WEIGHTED)和 PSAR(0.02,0.2) 做过滤。返回 1 调 OpenBuy(),-1 调 OpenSell(),0 表示信号未明。快/慢 RSI 句柄的缓冲区编号都是 0,复制时别抄错序号。 图表上 M/C/R 三个按钮是给手工干预留的后门:M 出平仓与统一 SL/TP 面板,C 一键切品种,R 直接卸 EA。外汇与贵金属杠杆高,这类自动系统在任何时段都可能因滑点放大亏损,上 MT5 前先用策略测试器跑历史段验证句柄逻辑。
class="macro">#include <Trade\Trade.mqh> class="macro">#include <Trade\PositionInfo.mqh> class="macro">#include <Trade\SymbolInfo.mqh> class="macro">#include <Trade\AccountInfo.mqh> CTrade mc_trade; CSymbolInfo mc_symbol; CPositionInfo mc_position; CAccountInfo mc_account; enum tm_zone { Cus_Session, class=class="str">"cmt">// Trading on Custom Session New_Zealand, class=class="str">"cmt">// Trading on New Zealand Session
把交易时段和品种拆成枚举开关
想在 MT5 里做分时段、分品种的策略,第一步是把『什么时候交易』和『交易什么』从硬编码里抽出来。下面这套枚举就是干这个的:用枚举把悉尼、东京、伦敦、纽约四个主流 session 列清楚,EA 只要读枚举值就知道当前该不该出手。 小时维度用了 hr_00 到 hr_23 共 24 个枚举项,分钟维度只取了 0/5/10…55 这 12 个整 5 分节点。实盘里如果你只在整 5 分去判断 session 边界,能少跑一大半 OnTick 逻辑,回测时也更容易对齐历史 K 线。 品种侧给了 All30、Usds、Eurs 到 Jpys 共 10 个选项,覆盖主要货币系。配合 YN 这个二值枚举(No=0, Yes=1),就能用输入参数组合出『伦敦时段 + 只做 EUR 系 + 开关打开』这类条件,不用改代码。 外汇和贵金属杠杆高、滑点跳空频繁,枚举只是把规则显式化,不等于过滤了风险;session 切换前后流动性断层仍可能让止损失效。
enum swsession { Australia, class=class="str">"cmt">// Trading on Autralia Sydney Session Asia_Tokyo, class=class="str">"cmt">// Trading on Asia Tokyo Session Europe_London, class=class="str">"cmt">// Trading on Europe London Session US_New_York class=class="str">"cmt">// Trading on US New York Session }; class=class="str">"cmt">//-- class=class="str">"cmt">//-- enum swhour { hr_00=class="num">0, class=class="str">"cmt">// class="num">00:class="num">00 hr_01=class="num">1, class=class="str">"cmt">// class="num">01:class="num">00 hr_02=class="num">2, class=class="str">"cmt">// class="num">02:class="num">00 hr_03=class="num">3, class=class="str">"cmt">// class="num">03:class="num">00 hr_04=class="num">4, class=class="str">"cmt">// class="num">04:class="num">00 hr_05=class="num">5, class=class="str">"cmt">// class="num">05:class="num">00 hr_06=class="num">6, class=class="str">"cmt">// class="num">06:class="num">00 hr_07=class="num">7, class=class="str">"cmt">// class="num">07:class="num">00 hr_08=class="num">8, class=class="str">"cmt">// class="num">08:class="num">00 hr_09=class="num">9, class=class="str">"cmt">// class="num">09:class="num">00 hr_10=class="num">10, class=class="str">"cmt">// class="num">10:class="num">00 hr_11=class="num">11, class=class="str">"cmt">// class="num">11:class="num">00 hr_12=class="num">12, class=class="str">"cmt">// class="num">12:class="num">00 hr_13=class="num">13, class=class="str">"cmt">// class="num">13:class="num">00 hr_14=class="num">14, class=class="str">"cmt">// class="num">14:class="num">00 hr_15=class="num">15, class=class="str">"cmt">// class="num">15:class="num">00 hr_16=class="num">16, class=class="str">"cmt">// class="num">16:class="num">00 hr_17=class="num">17, class=class="str">"cmt">// class="num">17:class="num">00 hr_18=class="num">18, class=class="str">"cmt">// class="num">18:class="num">00 hr_19=class="num">19, class=class="str">"cmt">// class="num">19:class="num">00 hr_20=class="num">20, class=class="str">"cmt">// class="num">20:class="num">00 hr_21=class="num">21, class=class="str">"cmt">// class="num">21:class="num">00 hr_22=class="num">22, class=class="str">"cmt">// class="num">22:class="num">00 hr_23=class="num">23 class=class="str">"cmt">// class="num">23:class="num">00 }; class=class="str">"cmt">//-- class=class="str">"cmt">//-- enum inmnt { mn_00=class="num">0, class=class="str">"cmt">// Minute class="num">0 mn_05=class="num">5, class=class="str">"cmt">// Minute class="num">5 mn_10=class="num">10, class=class="str">"cmt">// Minute class="num">10 mn_15=class="num">15, class=class="str">"cmt">// Minute class="num">15 mn_20=class="num">20, class=class="str">"cmt">// Minute class="num">20 mn_25=class="num">25, class=class="str">"cmt">// Minute class="num">25 mn_30=class="num">30, class=class="str">"cmt">// Minute class="num">30 mn_35=class="num">35, class=class="str">"cmt">// Minute class="num">35 mn_40=class="num">40, class=class="str">"cmt">// Minute class="num">40 mn_45=class="num">45, class=class="str">"cmt">// Minute class="num">45 mn_50=class="num">50, class=class="str">"cmt">// Minute class="num">50 mn_55=class="num">55 class=class="str">"cmt">// Minute class="num">55 }; class=class="str">"cmt">//-- class=class="str">"cmt">//-- enum PairsTrade { All30, class=class="str">"cmt">// All Forex class="num">30 Pairs TrdWi, class=class="str">"cmt">// Trader Wishes Pairs Usds, class=class="str">"cmt">// Forex USD Pairs Eurs, class=class="str">"cmt">// Forex EUR Pairs Gbps, class=class="str">"cmt">// Forex GBP Pairs Auds, class=class="str">"cmt">// Forex AUD Pairs Nzds, class=class="str">"cmt">// Forex NZD Pairs Cads, class=class="str">"cmt">// Forex CDD Pairs Chfs, class=class="str">"cmt">// Forex CHF Pairs Jpys class=class="str">"cmt">// Forex JPY Pairs }; class=class="str">"cmt">//-- class=class="str">"cmt">//-- enum YN { No, Yes };
◍ EA 参数枚举与手数风控的底层定义
在 MT5 写多品种 RSI 策略 EA 时,先把交易维度用枚举锁死,比后面满屏 if-else 要干净。下面这段代码把仓位模式、周期选择、 trailing 方式、单多品种模式全部枚举化,编译期就能排掉非法赋值。 enum mmt { FixedLot, DynamLot }; 定义固定手数与动态手数两种仓位模式;enum TFUSE 覆盖 M5 到 D1 共 11 个周期,默认指向 H4;enum TrType 区分按价格或按指标移动止损;enum MS 切单品种与多品种。 input 区直接暴露给 EA 属性面板。注意 rsidiff 默认 4.56,这是快慢 RSI 差值过滤阈值;Risk 输入 10.0 代表每笔最大回撤仓位占净值 10%,面板标注了 Min=1.0% / Max=10.0% 的硬边界。外汇与贵金属杠杆高,动态手数跑满 10% 风险可能在单根 H4 反转中吞掉可观净值,建议先按 1%~2% 在策略测试器跑。 把 usepairs 设成 All30 会一次性加载 30 个货币对,trademode 选 MP 时配合 traderwishes 字符串(如 "eurusd,usdchf")可缩窄到自选池。开 MT5 新建 EA,把这段枚举和 input 原样贴进头部,就能在属性框看到分组参数。
enum mmt { FixedLot, class=class="str">"cmt">// Fixed Lot Size DynamLot class=class="str">"cmt">// Dynamic Lot Size }; class=class="str">"cmt">//-- class=class="str">"cmt">//-- enum TFUSE { TFM5, class=class="str">"cmt">// 00_PERIOD_M5 TFM15, class=class="str">"cmt">// 01_PERIOD_M15 TFM30, class=class="str">"cmt">// 02_PERIOD_M30 TFH1, class=class="str">"cmt">// 03_PERIOD_H1 TFH2, class=class="str">"cmt">// 04_PERIOD_H2 TFH3, class=class="str">"cmt">// 05_PERIOD_H3 TFH4, class=class="str">"cmt">// 06_PERIOD_H4 TFH6, class=class="str">"cmt">// 07_PERIOD_H6 TFH8, class=class="str">"cmt">// 08_PERIOD_H8 TFH12, class=class="str">"cmt">// 09_PERIOD_H12 TFD1 class=class="str">"cmt">// 10_PERIOD_D1 }; class=class="str">"cmt">//-- class=class="str">"cmt">//-- enum TrType { byprice, class=class="str">"cmt">// Trailing Stop by Price byindi class=class="str">"cmt">// Trailing Stop by Indicator }; class=class="str">"cmt">//-- class=class="str">"cmt">//-- enum MS { SP, class=class="str">"cmt">// Single Pair MP class=class="str">"cmt">// Multi Pairs }; class=class="str">"cmt">//-- class=class="str">"cmt">//--- input group "=== Global Strategy EA Parameter ==="; class=class="str">"cmt">// Global Strategy EA Parameter input TFUSE tfinuse = TFH4; class=class="str">"cmt">// Select Expert TimeFrame, class="kw">default PERIOD_H4 input class="type">int rsifast = class="num">10; class=class="str">"cmt">// Input Period for Fast RSI input ENUM_APPLIED_PRICE frsiapp = PRICE_WEIGHTED; class=class="str">"cmt">// Select Fast RSI Applied Price input class="type">int rsislow = class="num">30; class=class="str">"cmt">// Input Period for Slow RSI input ENUM_APPLIED_PRICE srsiapp = PRICE_WEIGHTED; class=class="str">"cmt">// Select Slow RSI Applied Price input class="type">class="kw">double rsidiff = class="num">4.56; class=class="str">"cmt">// Input Differentiation between RSIs class=class="str">"cmt">//--- input group "=== Select Pairs to Trade ==="; class=class="str">"cmt">// Selected Pairs to trading input MS trademode = MP; class=class="str">"cmt">// Select Trading Pairs Mode(Multi or Single) input PairsTrade usepairs = All30; class=class="str">"cmt">// Select Pairs to Use input class="type">class="kw">string traderwishes = "eg. eurusd,usdchf"; class=class="str">"cmt">// If Use Trader Wishes Pairs, input pair name here, separate by comma class=class="str">"cmt">//-- input group "=== Money Management Lot Size Parameter ==="; class=class="str">"cmt">// Money Management Lot Size Parameter input mmt mmlot = DynamLot; class=class="str">"cmt">// Money Management Type input class="type">class="kw">double Risk = class="num">10.0; class=class="str">"cmt">// Percent Equity Risk per Trade(Min=class="num">1.0% / Max=class="num">10.0%)
「把交易时段和星期开关写进输入参数」
EA 的可控性首先体现在 input 区。下面这段声明把手数、交易时段、星期开关和止损逻辑全部暴露给 MT5 属性框,改参数不用动核心代码。 手数固定为 0.01,属于轻仓试单档位;外汇与贵金属杠杆高,0.01 手也可能在极端波动下出现超出预期的浮亏,参数只是起点不是安全阀。 时段分组用 input group 做视觉隔离:trd_time_zone 设为 Yes 时启用自定义会话,起始 hr_00 / mn_15 到 hr_23 / mn_55,等于几乎覆盖全交易日但留了首尾 15 分钟空档。星期开关里 ttd0(周日)和 ttd6(周六)为 No,ttd1~ttd5 为 Yes,也就是周末不交易。 订单管理里 use_sl = No 但 autosl = Yes,这组值看着矛盾:实际含义是“先不挂 SL,但保留自动测算 SL 的开关”,真要风控得把 use_sl 翻成 Yes 才会生效。复制下面代码到 MQ5 文件头部,编译后直接在属性面板验证分组和默认值。
input class="type">class="kw">double Lots = class="num">0.01; class=class="str">"cmt">// Input Manual Lot Size FixedLot class=class="str">"cmt">//--Trade on Specific Time input group "=== Trade on Specific Time ==="; class=class="str">"cmt">// Trade on Specific Time input YN trd_time_zone = Yes; class=class="str">"cmt">// Select If You Like to Trade on Specific Time Zone input tm_zone session = Cus_Session; class=class="str">"cmt">// Select Trading Time Zone input swhour stsescuh = hr_00; class=class="str">"cmt">// Time Hour to Start Trading Custom Session(class="num">0-class="num">23) input inmnt stsescum = mn_15; class=class="str">"cmt">// Time Minute to Start Trading Custom Session(class="num">0-class="num">55) input swhour clsescuh = hr_23; class=class="str">"cmt">// Time Hour to Stop Trading Custom Session(class="num">0-class="num">23) input inmnt clsescum = mn_55; class=class="str">"cmt">// Time Minute to Stop Trading Custom Session(class="num">0-class="num">55) class=class="str">"cmt">//--Day Trading On/Off input group "=== Day Trading On/Off ==="; class=class="str">"cmt">// Day Trading On/Off input YN ttd0 = No; class=class="str">"cmt">// Select Trading on Sunday(Yes) or(No) input YN ttd1 = Yes; class=class="str">"cmt">// Select Trading on Monday(Yes) or(No) input YN ttd2 = Yes; class=class="str">"cmt">// Select Trading on Tuesday(Yes) or(No) input YN ttd3 = Yes; class=class="str">"cmt">// Select Trading on Wednesday(Yes) or(No) input YN ttd4 = Yes; class=class="str">"cmt">// Select Trading on Thursday(Yes) or(No) input YN ttd5 = Yes; class=class="str">"cmt">// Select Trading on Friday(Yes) or(No) input YN ttd6 = No; class=class="str">"cmt">// Select Trading on Saturday(Yes) or(No) class=class="str">"cmt">//--Trade & Order management Parameter input group "=== Trade & Order management Parameter ==="; class=class="str">"cmt">// Trade & Order management Parameter input YN use_sl = No; class=class="str">"cmt">// Use Order Stop Loss(Yes) or(No) input YN autosl = Yes; class=class="str">"cmt">// Use Automatic Calculation Stop Loss(Yes) or(No)
EA 风控与多品种参数的落地写法
把止损止盈交给 EA 之前,先看清这组输入变量的分工。SLval 默认 30 点、TPval 默认 60 点,是在关闭自动测算时手动填的点数;autotp 设 Yes 后,TP 由指标逻辑推算,手填的 60 点就失效。 追踪止损那段最容易踩坑:TSmin=5 表示浮盈满 5 点才开始跟价,TSval=10 是回撤 10 点触发平仓线,TPmin=25 则限定追踪止盈至少吃掉 25 点才生效。外汇和贵金属杠杆高,这类参数在黄金上若照搬 30 点止损,遇数据行情可能瞬间扫掉,建议先上模拟盘跑一遍。 下面这段是品种数组的初始化入口,HandlingSymbolArrays 里先列了 8 个直盘。要加 XAUUSD 进去,直接往数组补字符串即可,MT5 编译后就能在多品种面板里看到它。 Close_by_Opps 与 SaveOnRev 管的是反向信号处置:前者遇反向信号清仓,后者弱信号时落袋。magicEA=20240111 用来隔离本 EA 订单,回测时若发现单子不归本程序管,先查这个数有没有撞车。
input class="type">class="kw">double SLval = class="num">30.0; class=class="str">"cmt">// If Not Use Automatic SL - Input SL value in Pips input YN use_tp = Yes; class=class="str">"cmt">// Use Order Take Profit(Yes) or(No) input YN autotp = Yes; class=class="str">"cmt">// Use Automatic Calculation Take Profit(Yes) or(No) input class="type">class="kw">double TPval = class="num">60.0; class=class="str">"cmt">// If Not Use Automatic TP - Input TP value in Pips input YN TrailingSLTP = Yes; class=class="str">"cmt">// Use Trailing SL/TP(Yes) or(No) input TrType trlby = byindi; class=class="str">"cmt">// Select Trailing Stop Type input class="type">class="kw">double TSval = class="num">10.0; class=class="str">"cmt">// If Use Trailing Stop by Price Input value in Pips input class="type">class="kw">double TSmin = class="num">5.0; class=class="str">"cmt">// Minimum Pips to start Trailing Stop input class="type">class="kw">double TPmin = class="num">25.0; class=class="str">"cmt">// Input Trailing Profit Value in Pips input YN Close_by_Opps = Yes; class=class="str">"cmt">// Close Trade By Opposite Signal(Yes) or(No) input YN SaveOnRev = Yes; class=class="str">"cmt">// Close Trade and Save profit due to weak signal(Yes) or(No) class=class="str">"cmt">//--Others Expert Advisor Parameter input group "=== Others Expert Advisor Parameter ===" ; class=class="str">"cmt">// Others EA Parameter input YN alerts = Yes; class=class="str">"cmt">// Display Alerts / Messages(Yes) or(No) input YN UseEmailAlert = No; class=class="str">"cmt">// Email Alert(Yes) or(No) input YN UseSendnotify = No; class=class="str">"cmt">// Send Notification(Yes) or(No) input YN trade_info_display = Yes; class=class="str">"cmt">// Select Display Trading Info on Chart(Yes) or(No) input class="type">ulong magicEA = class="num">20240111; class=class="str">"cmt">// Expert ID(Magic Number) class=class="str">"cmt">//--- class=class="str">"cmt">//---------// class="type">void MCEA::HandlingSymbolArrays(class="type">void) { class=class="str">"cmt">//--- class="type">class="kw">string All30[]={"EURUSD","GBPUSD","AUDUSD","NZDUSD","USDCAD","USDCHF","USDJPY","EURGBP",