MQL5均线交易单无法正常平仓问题求助
MQL5 EA平仓问题的修复方案
以下是你的EA代码中导致无法正常平仓的核心问题及修复方法:
1. 静态全局变量未实时更新
你在全局作用域初始化了openCandle、closeCandle、EMA等变量,这些值只会在EA启动时计算一次,不会随新K线或tick更新,导致所有开平仓判断都基于过时数据。
修复: 将这些变量的计算移至OnTick()函数内,确保每次tick都获取最新数据,并通过参数传递给各业务函数。
2. 未选中对应仓位就读取属性
在平仓函数中,获取仓位方向前未调用PositionSelectByTicket(ticket)选中目标仓位,导致PositionGetInteger(POSITION_TYPE)返回的是最后选中仓位的方向,而非当前遍历的仓位。
修复: 在读取仓位属性前先选中目标仓位,确保获取的是当前遍历仓位的正确信息。
3. 平仓条件逻辑错误
当前平仓条件与开仓条件冲突:
buyOrderclose()的条件和sellOrder()的开仓条件完全一致,意味着只有当满足做空开仓条件时才会尝试平多单,但此时PositionsTotal()不为0,做空开仓不会触发,逻辑矛盾。sellOrderclose()同理,条件和buyOrder()开仓条件一致,无法正确触发平空单。
修复: 重新定义符合策略逻辑的平仓条件,示例中设置为:
- 平多单:出现看跌K线且收盘价站上EMA
- 平空单:出现看涨K线且收盘价跌破EMA
(可根据你的策略需求自行调整)
4. EMA变量类型错误
EMA被声明为int类型,但iMA()返回的是double类型数值,会导致小数部分截断,影响判断准确性。
修复: 将EMA的类型改为double。
完整修复后的代码
#include<Trade\Trade.mqh> CTrade trade; input double lots = 0.01; int period = 10; void OnTick() { // 实时获取最新K线与均线数据 double openCandle = iOpen(_Symbol, PERIOD_CURRENT, 0); double closeCandle = iClose(_Symbol, PERIOD_CURRENT, 0); double EMA = iMA(_Symbol, PERIOD_CURRENT, period, 0, MODE_EMA, 0); buyOrder(openCandle, closeCandle, EMA); sellOrder(openCandle, closeCandle, EMA); buyOrderclose(openCandle, closeCandle, EMA); sellOrderclose(openCandle, closeCandle, EMA); } void buyOrder(double openCandle, double closeCandle, double EMA) { if(openCandle < closeCandle && closeCandle < EMA && PositionsTotal() == 0) { double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits); if(trade.Buy(lots, _Symbol, Ask, NULL, NULL, NULL)) Print("BUY ORDER PLACED"); else Print("Buy failed: ", GetLastError()); } } void sellOrder(double openCandle, double closeCandle, double EMA) { if(openCandle > closeCandle && closeCandle < EMA && PositionsTotal() == 0) { double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits); if(trade.Sell(lots, _Symbol, Bid, NULL, NULL, NULL)) Print("SELL ORDER PLACED"); else Print("Sell failed: ", GetLastError()); } } void buyOrderclose(double openCandle, double closeCandle, double EMA) { // 平多单条件:看跌K线且收盘价站上EMA if(openCandle > closeCandle && closeCandle > EMA) { for(int i = PositionsTotal() - 1; i >= 0; i--) { int ticket = PositionGetTicket(i); if(PositionSelectByTicket(ticket)) { if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && PositionGetString(POSITION_SYMBOL) == _Symbol) { if(trade.PositionClose(ticket)) Print("BUY POSITION CLOSED, Ticket: ", ticket); else Print("Close buy failed: ", GetLastError()); } } } } } void sellOrderclose(double openCandle, double closeCandle, double EMA) { // 平空单条件:看涨K线且收盘价跌破EMA if(openCandle < closeCandle && closeCandle < EMA) { for(int i = PositionsTotal() - 1; i >= 0; i--) { int ticket = PositionGetTicket(i); if(PositionSelectByTicket(ticket)) { if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && PositionGetString(POSITION_SYMBOL) == _Symbol) { if(trade.PositionClose(ticket)) Print("SELL POSITION CLOSED, Ticket: ", ticket); else Print("Close sell failed: ", GetLastError()); } } } } }
内容的提问来源于stack exchange,提问作者Hari prasath
相关产品推荐
相关产品推荐

