基于MQL5的订单剥头皮交易系统(基础篇)
剥头皮系统的 MQL5 落地起点
在 MT5 上做订单剥头皮,核心是把入场、平仓、风控都交给 EA 在 tick 级响应,而不是靠手动盯盘抢那几毛点差。外汇与贵金属剥头皮属于高风险策略,滑点与流动性断裂都可能让胜率模型瞬间失效,实盘前务必在策略测试器里跑足样本。 这篇示例发布于 2025 年 5 月 19 日,原始公开数据里显示有 2836 次浏览、4 条讨论,说明基础剥头皮框架在社群里仍有稳定关注度。你可以直接开 MT5 新建 EA,把下文骨架抄进去验证编译是否通过。 真正能跑的剥头皮逻辑,往往先从最简的市价单 + 固定止损止盈开始,再逐步加订单修改与异步下单。先让小布替你跑这套编译,比一上来堆指标更不容易踩坑。
◍ 剥头皮订单流EA到底在做什么
这套面向 MT5 的 EA 走的是剥头皮订单流路线:盯着实时订单簿、成交量和价格行为,找订单流失衡的瞬间进场,持仓往往只有几分钟甚至几秒。它把订单流研究和成熟技术指标揉成一个混合策略,用来筛高概率的短打机会。 外汇和贵金属这类品种波动剧烈,剥头皮更是把风险压缩到极短时间窗里,所以系统内置了跟踪止损、部分平仓和动态仓位调整,还加了重大新闻禁交易与连续亏损上限。资本保护优先于抓单量。 EA 留了可调参数——成交量阈值、指标周期都能按你的风格改。但它不是“设完就扔”的机器:你得懂订单流基础和外挂的那几个指标,平时盯盘、随市况微调,否则策略衰减你很难察觉。
「剥头皮EA的骨架与可调参数」
这套跑在 MT5 上的订单流剥头皮系统,把均线和 ADX、ATR、RSI、布林带拧在一起做信号确认,再靠账户余额百分比与 ATR 波动率算动态仓位。OnInit() 里先抓交易权限和指标句柄,OnTick() 每来一个报价就重算订单流失衡与趋势强度,逻辑链不短但拆开能读。 风险管理这块给了两个硬闸:最大连续亏损次数默认设 1(MaxConsecutiveLosses=1),以及两笔单子之间至少隔 1 根 K 线(MinBarsBetweenTrades=1)。这种设定倾向把暴露压到极低,但也可能在震荡行情里频繁停手。外汇与贵金属杠杆高,实盘前务必在策略测试器里跑足够样本。 代码头部那批 input 参数就是你的调参面板:OrderFlowPeriod=30 代表抓近 30 根蜡烛的买卖量差,VolumeThreshold=35000 是判定失衡的量能门槛,RiskPercent=1.0 对应每笔最大回撤占比。直接改这几个数,就能在 M15 上验证不同敏感度。 高影响新闻过滤函数只是留了壳,原作者没填实,真要防突发波动得自己接日历事件。这部分空着不下单,比接错数据源更安全。
class="macro">#include <Trade\Trade.mqh> class="macro">#include <Trade\PositionInfo.mqh> class=class="str">"cmt">// Input parameters class="kw">input class="type">int VolumeThreshold = class="num">35000; class=class="str">"cmt">// Volume threshold to consider imbalance class="kw">input class="type">int OrderFlowPeriod = class="num">30; class=class="str">"cmt">// Number of candles to analyze order flow class="kw">input class="type">class="kw">double RiskPercent = class="num">1.0; class=class="str">"cmt">// Risk percentage per trade class="kw">input class="type">int ADXPeriod = class="num">14; class=class="str">"cmt">// ADX Period class="kw">input class="type">int ADXThreshold = class="num">25; class=class="str">"cmt">// ADX threshold for strong trend class="kw">input class="type">int MAPeriod = class="num">200; class=class="str">"cmt">// Moving Average Period class="kw">input ENUM_TIMEFRAMES Timeframe = PERIOD_M15; class=class="str">"cmt">// Timeframe for analysis class="kw">input class="type">class="kw">double MaxLotSize = class="num">0.1; class=class="str">"cmt">// Maximum allowed lot size class="kw">input class="type">int ATRPeriod = class="num">14; class=class="str">"cmt">// ATR Period class="kw">input class="type">class="kw">double ATRMultiplier = class="num">2.0; class=class="str">"cmt">// ATR Multiplier class="kw">input class="type">int RSIPeriod = class="num">14; class=class="str">"cmt">// RSI Period class="kw">input class="type">int RSIOverbought = class="num">70; class=class="str">"cmt">// RSI Overbought level class="kw">input class="type">int RSIOversold = class="num">30; class=class="str">"cmt">// RSI Oversold level class="kw">input class="type">int MAFastPeriod = class="num">10; class=class="str">"cmt">// Fast Moving Average Period class="kw">input class="type">int MASlowPeriod = class="num">30; class=class="str">"cmt">// Slow Moving Average Period class="kw">input class="type">int BollingerPeriod = class="num">20; class=class="str">"cmt">// Bollinger Bands Period class="kw">input class="type">class="kw">double BollingerDeviation = class="num">2.5; class=class="str">"cmt">// Bollinger Bands Standard Deviation class="kw">input class="type">int MaxConsecutiveLosses = class="num">1; class=class="str">"cmt">// Maximum number of consecutive losses before pausing class="kw">input class="type">int MinBarsBetweenTrades = class="num">1; class=class="str">"cmt">// Minimum number of bars between trades class=class="str">"cmt">// Global variables CTrade trade; CPositionInfo positionInfo; class="type">int maHandle, adxHandle, atrHandle, rsiHandle, maFastHandle, maSlowHandle, bollingerHandle; class="type">int consecutiveLosses = class="num">0; class="type">class="kw">datetime lastTradeTime = class="num">0; class="type">int barsSinceLastTrade = class="num">0; class=class="str">"cmt">// New global variables for statistics class="type">int totalTrades = class="num">0; class="type">int winningTrades = class="num">0; class="type">class="kw">double totalProfit = class="num">0; class="type">int OnInit() { class=class="str">"cmt">// Logging initialization Print("Starting Order Flow EA v13..."); class=class="str">"cmt">// Verify trading permissions if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) {
EA 初始化时的交易权限与指标句柄校验
在 MT5 的 EA 初始化阶段,先卡两道交易权限关:终端级自动交易开关和 EA 级交易许可。任一处未开启,直接 return INIT_FAILED,EA 不会进入 OnTick,避免无谓的错单尝试。 交易对象 CTrade 的预设也在这步落地:魔法号写死 123456,偏差容忍设 10 点(注释里标为 1 pip 容差),并用 SetTypeFillingBySymbol(_Symbol) 按品种适配成交模式。外汇与贵金属品种的开仓方式差异大,这一步漏掉可能在部分经纪商报出无效填充错误。 指标句柄一次性拉齐:SMA(MAPeriod)、ADX(ADXPeriod)、ATR(ATRPeriod)、RSI(RSIPeriod)、快/慢 EMA 及布林带(iBands,BollingerPeriod + BollingerDeviation)。只要任意一个返回 INVALID_HANDLE,就逐条 Print 具体哪个指标失效并终止初始化。 实盘里最常踩的坑是布林带句柄:BollingerDeviation 若传了非标准值(如 0 或负数),iBands 会静默返回无效句柄,EA 起不来却只在日志留一行 '- Invalid Bollinger Bands'。开 MT5 把这段粘进 OnInit 底部,跑一遍就能看见自己参数是否全绿。
if(!MQLInfoInteger(MQL_TRADE_ALLOWED)) { Print("Error: Automated trading is not allowed in the terminal."); class="kw">return INIT_FAILED; } if(!MQLInfoInteger(MQL_TRADE_ALLOWED)) { Print("Error: Automated trading is not allowed for this EA."); class="kw">return INIT_FAILED; } class=class="str">"cmt">// Initialize trading object trade.SetExpertMagicNumber(class="num">123456); trade.SetMarginMode(); trade.SetTypeFillingBySymbol(_Symbol); trade.SetDeviationInPoints(class="num">10); class=class="str">"cmt">// class="num">1 pip deviation allowed Print("Trading object initialized."); class=class="str">"cmt">// Initialize indicators maHandle = iMA(_Symbol, Timeframe, MAPeriod, class="num">0, MODE_SMA, PRICE_CLOSE); adxHandle = iADX(_Symbol, Timeframe, ADXPeriod); atrHandle = iATR(_Symbol, Timeframe, ATRPeriod); rsiHandle = iRSI(_Symbol, Timeframe, RSIPeriod, PRICE_CLOSE); maFastHandle = iMA(_Symbol, Timeframe, MAFastPeriod, class="num">0, MODE_EMA, PRICE_CLOSE); maSlowHandle = iMA(_Symbol, Timeframe, MASlowPeriod, class="num">0, MODE_EMA, PRICE_CLOSE); bollingerHandle = iBands(_Symbol, Timeframe, BollingerPeriod, class="num">0, BollingerDeviation, PRICE_CLOSE); class=class="str">"cmt">// Verify indicator initialization if(maHandle == INVALID_HANDLE || adxHandle == INVALID_HANDLE || atrHandle == INVALID_HANDLE || rsiHandle == INVALID_HANDLE || maFastHandle == INVALID_HANDLE || maSlowHandle == INVALID_HANDLE || bollingerHandle == INVALID_HANDLE) { Print("Error initializing indicators:"); if(maHandle == INVALID_HANDLE) Print("- Invalid MA"); if(adxHandle == INVALID_HANDLE) Print("- Invalid ADX"); if(atrHandle == INVALID_HANDLE) Print("- Invalid ATR"); if(rsiHandle == INVALID_HANDLE) Print("- Invalid RSI"); if(maFastHandle == INVALID_HANDLE) Print("- Invalid Fast MA"); if(maSlowHandle == INVALID_HANDLE) Print("- Invalid Slow MA"); if(bollingerHandle == INVALID_HANDLE) Print("- Invalid Bollinger Bands"); class="kw">return INIT_FAILED; } Print("All indicators initialized successfully."); class=class="str">"cmt">// Verify class="kw">input parameters