找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
首页论坛EAHub 外汇论坛
查看: 12|回复: 0

EA指标,移动均线,MACD,RSI,布林带,嵌入价格,点差,盈利风控,有懂的帮我看一下能用吗,靠谱吗

[复制链接]

4万

主题

54

回帖

4万

积分

管理员

积分
45954
发表于 2026-8-27 00:14:00 | 显示全部楼层 |阅读模式
有没有懂的大佬帮我看一下这个能用吗,靠谱吗


//+------------------------------------------------------------------+

//|                                              EURUSD_Risk_EA_V2_Fixed.mq4 |

//|                        Copyright 2024, MetaQuotes Software Corp. |

//|                                             https://www.mql5.com |

//+------------------------------------------------------------------+

#property copyright "Copyright 2024, MetaQuotes Software Corp."

#property link      "https://www.mql5.com"

#property version   "2.01"

#property strict


// 基础交易参数(EUR/USD专属)

input double LotSize = 0.1;          // 初始手数

input int StopLoss = 30;             // 止损点数(30点=0.0030)

input int TakeProfit = 60;           // 止盈点数(盈亏比2:1)

input int TrailingStop_Initial = 10; // 初始移动止损步长(盈利≤30点)

input int TrailingStop_Enhanced = 15;// 增强移动止损步长(盈利>30点)

input int TrailingTrigger = 15;      // 移动止损触发阈值(盈利15点启动)

input int MagicNumber = 12345;       // 魔术号(唯一标识EA订单)

input int Slippage = 3;              // 允许滑点(点)


// 风控核心参数

input double MaxRiskPerTrade = 0.01; // 单笔最大风险(账户资金的1%)

input int MaxOrdersPerDay = 5;       // 单日最大开仓次数

input double MaxDrawdown = 0.05;     // 最大账户回撤(5%)

input int TrendFilterPeriod = 200;   // 趋势过滤均线周期(EUR/USD专属)

input double MaxSpread = 0.3;        // 最大允许点差(0.3点)


// 开仓信号参数(可切换)

input ENUM_SIGNAL_TYPE SignalType = SIGNAL_MACD_RSI; // 信号类型:MACD+RSI/布林带/双均线

enum ENUM_SIGNAL_TYPE {

    SIGNAL_MACD_RSI,      // MACD+RSI组合信号

    SIGNAL_BOLLINGER,     // 布林带突破信号

    SIGNAL_MA_CROSS       // 双均线金叉死叉信号

};

// 信号专属参数

input int MACD_Fast = 12;    // MACD快速周期

input int MACD_Slow = 26;    // MACD慢速周期

input int MACD_Signal = 9;   // MACD信号周期

input int RSI_Period = 14;   // RSI周期

input int RSI_Overbought = 70;// RSI超买阈值

input int RSI_Oversold = 30; // RSI超卖阈值

input int Bollinger_Period = 20; // 布林带周期

input int Bollinger_Dev = 2;    // 布林带标准差

input int MA_Short = 50;     // 短期均线周期

input int MA_Long = 200;     // 长期均线周期


// 全局变量

int OrdersToday = 0;                 // 今日开仓次数

double MaxEquity;                    // 历史最高权益(用于回撤计算)

datetime LastTradeDate;              // 最后交易日期

datetime LastSignalTime;             // 最后信号触发时间(防重复开仓)

const int SignalFilterPeriod = 60;   // 信号过滤周期(60秒内不重复触发)


//+------------------------------------------------------------------+

//| Expert initialization function                                   |

//+------------------------------------------------------------------+

int OnInit()

{

    // 初始化历史最高权益(首次为当前权益)

    MaxEquity = AccountEquity();

    LastTradeDate = 0;

    OrdersToday = 0;

    LastSignalTime = 0;

   

    // 日志初始化

    Print("=== EURUSD Risk EA V2.01 初始化成功 ===");

    Print("初始账户权益:", AccountEquity(), " USD");

    Print("最大允许回撤:", MaxDrawdown*100, "%");

    Print("信号类型:", SignalTypeToString(SignalType));

   

    return(INIT_SUCCEEDED);

}


//+------------------------------------------------------------------+

//| Expert deinitialization function                                 |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

{

    Print("=== EA退出 ===");

    Print("退出原因:", DeinitReasonToString(reason));

    Print("今日开仓次数:", OrdersToday);

    Print("当前账户权益:", AccountEquity(), " USD");

}


//+------------------------------------------------------------------+

//| Expert tick function                                             |

//+------------------------------------------------------------------+

void OnTick()

{

    // 1. 更新历史最高权益

    UpdateMaxEquity();

   

    // 2. 风控前置检查(失败直接返回)

    if(!RiskCheck()) return;

   

    // 3. 信号过滤(60秒内不重复触发)

    if(TimeCurrent() - LastSignalTime < SignalFilterPeriod) return;

   

    // 4. 获取开仓信号(带指标容错)

    bool BuySignal = GetBuySignal();

    bool SellSignal = GetSellSignal();

   

    // 5. 开仓逻辑(无对应方向订单时开仓)

    if(BuySignal && !OrderExists(OP_BUY))

    {

        if(OpenOrder(OP_BUY, LotSize, StopLoss, TakeProfit))

            LastSignalTime = TimeCurrent();

    }

    else if(SellSignal && !OrderExists(OP_SELL))

    {

        if(OpenOrder(OP_SELL, LotSize, StopLoss, TakeProfit))

            LastSignalTime = TimeCurrent();

    }

   

    // 6. 优化版移动止损(带重试机制)

    UpdateTrailingStop_Enhanced();

}


//+------------------------------------------------------------------+

//| 风控检查函数(核心优化)                                         |

//+------------------------------------------------------------------+

bool RiskCheck()

{

    // 检查账户回撤(基于历史最高权益)

    double CurrentDrawdown = (MaxEquity - AccountEquity()) / MaxEquity;

    if(CurrentDrawdown >= MaxDrawdown)

    {

        Print("【风控拦截】账户回撤达到", DoubleToStr(CurrentDrawdown*100, 2), "%, 暂停交易");

        return false;

    }

   

    // 检查单日开仓次数(跨日重置)

    if(TimeDay(TimeLocal()) != TimeDay(LastTradeDate) || TimeMonth(TimeLocal()) != TimeMonth(LastTradeDate) || TimeYear(TimeLocal()) != TimeYear(LastTradeDate))

    {

        OrdersToday = 0;

        LastTradeDate = TimeLocal();

        Print("【日期重置】今日开仓次数清零,当前日期:", TimeToStr(TimeLocal(), TIME_DATE));

    }

    if(OrdersToday >= MaxOrdersPerDay)

    {

        Print("【风控拦截】今日开仓次数达到", MaxOrdersPerDay, "次,暂停交易");

        return false;

    }

   

    // 检查点差(单位修正)

    double CurrentSpread = (Ask - Bid) / Point; // 转换为点数

    if(CurrentSpread > MaxSpread)

    {

        Print("【风控拦截】当前点差", DoubleToStr(CurrentSpread, 2), "点,超过允许值", MaxSpread, "点");

        return false;

    }

   

    // 检查账户资金(最低100美元)

    if(AccountBalance() < 100)

    {

        Print("【风控拦截】账户资金不足100美元,暂停交易");

        return false;

    }

   

    // 检查市场状态(是否开盘)

    if(!IsMarketOpen())

    {

        Print("【风控拦截】市场未开盘,暂停交易");

        return false;

    }

   

    return true;

}


//+------------------------------------------------------------------+

//| 开仓函数(MT4兼容版本)                                          |

//+------------------------------------------------------------------+

bool OpenOrder(int orderType, double lot, int sl, int tp)

{

    // 计算风险手数(取最小手数、初始手数、风险手数的最小值)

    double RiskLot = CalculateRiskLot(sl);

    double MinLot = MarketInfo(_Symbol, MODE_MINLOT);

    double MaxLot = MarketInfo(_Symbol, MODE_MAXLOT);

    lot = MathMin(MathMax(lot, MinLot), MaxLot); // 限制在手数范围内

    lot = MathMin(lot, RiskLot);          // 不超过风险手数

   

    // 计算止损止盈价格(防止价格异常)

    double openPrice = 0.0;

    double slPrice = 0.0;

    double tpPrice = 0.0;

   

    if(orderType == OP_BUY)

    {

        openPrice = Ask;

        slPrice = (sl > 0) ? NormalizeDouble(Bid - sl * Point, Digits) : 0;

        tpPrice = (tp > 0) ? NormalizeDouble(Bid + tp * Point, Digits) : 0;

        

        // 止损不能大于当前价格,止盈不能小于当前价格

        if((slPrice > 0 && slPrice >= Bid) || (tpPrice > 0 && tpPrice <= Bid))

        {

            Print("【开仓失败】多单止损/止盈价格异常,SL:", slPrice, ",TP:", tpPrice);

            return false;

        }

    }

    else if(orderType == OP_SELL)

    {

        openPrice = Bid;

        slPrice = (sl > 0) ? NormalizeDouble(Ask + sl * Point, Digits) : 0;

        tpPrice = (tp > 0) ? NormalizeDouble(Ask - tp * Point, Digits) : 0;

        

        // 止损不能小于当前价格,止盈不能大于当前价格

        if((slPrice > 0 && slPrice <= Ask) || (tpPrice > 0 && tpPrice >= Ask))

        {

            Print("【开仓失败】空单止损/止盈价格异常,SL:", slPrice, ",TP:", tpPrice);

            return false;

        }

    }

   

    // MT4兼容的订单发送

    int ticket = OrderSend(_Symbol, orderType, lot, openPrice, Slippage, slPrice, tpPrice,

                          "", MagicNumber, 0, (orderType == OP_BUY) ? clrBlue : clrRed);

   

    if(ticket > 0)

    {

        Print("【开仓成功】类型:", (orderType == OP_BUY ? "多头" : "空头"),

              ",手数:", DoubleToStr(lot, 2),

              ",开仓价:", DoubleToStr(openPrice, Digits),

              ",SL:", (slPrice > 0 ? DoubleToStr(slPrice, Digits) : "无"),

              ",TP:", (tpPrice > 0 ? DoubleToStr(tpPrice, Digits) : "无"));

        OrdersToday++;

        LastTradeDate = TimeLocal();

        return true;

    }

    else

    {

        int error = GetLastError();

        Print("【开仓失败】类型:", (orderType == OP_BUY ? "多头" : "空头"),

              ",错误代码:", error, ",错误描述:", ErrorDescription(error));

        return false;

    }

}


//+------------------------------------------------------------------+

//| 计算风险手数函数(精准适配)                                     |

//+------------------------------------------------------------------+

double CalculateRiskLot(int sl)

{

    double accountBalance = AccountBalance();

    double riskAmount = accountBalance * MaxRiskPerTrade; // 单笔风险金额

    double tickValue = MarketInfo(_Symbol, MODE_TICKVALUE); // 每点价值

    double slPoints = (double)sl; // 止损点数

   

    // 容错处理:避免除零错误

    if(tickValue <= 0 || slPoints <= 0 || accountBalance <= 0)

    {

        Print("【风险手数计算警告】参数异常,返回最小手数");

        return MarketInfo(_Symbol, MODE_MINLOT);

    }

   

    double lot = riskAmount / (slPoints * tickValue);

    double minLot = MarketInfo(_Symbol, MODE_MINLOT);

    double maxLot = MarketInfo(_Symbol, MODE_MAXLOT);

    double step = MarketInfo(_Symbol, MODE_LOTSTEP);

   

    // 标准化手数

    lot = MathMin(MathMax(lot, minLot), maxLot);

    lot = NormalizeDouble(lot / step, 0) * step;

   

    return lot;

}


//+------------------------------------------------------------------+

//| 检查订单是否存在函数(精准过滤)                                 |

//+------------------------------------------------------------------+

bool OrderExists(int orderType)

{

    for(int i = 0; i < OrdersTotal(); i++)

    {

        if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))

        {

            // 过滤条件:当前品种、魔术号、订单类型、未关闭状态

            if(OrderSymbol() == _Symbol &&

               OrderMagicNumber() == MagicNumber &&

               OrderType() == orderType &&

               OrderCloseTime() == 0)

            {

                return true;

            }

        }

    }

    return false;

}


//+------------------------------------------------------------------+

//| 优化版移动止损函数(MT4兼容)                                    |

//+------------------------------------------------------------------+

void UpdateTrailingStop_Enhanced()

{

    if(TrailingTrigger <= 0) return;

   

    for(int i = 0; i < OrdersTotal(); i++)

    {

        if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) &&

           OrderSymbol() == _Symbol &&

           OrderMagicNumber() == MagicNumber &&

           OrderCloseTime() == 0)

        {

            double currentPrice = (OrderType() == OP_BUY) ? Bid : Ask;

            double profitPoints = 0;

            

            // 计算盈利点数(基于价格变动)

            if(OrderType() == OP_BUY)

            {

                profitPoints = (currentPrice - OrderOpenPrice()) / Point;

            }

            else if(OrderType() == OP_SELL)

            {

                profitPoints = (OrderOpenPrice() - currentPrice) / Point;

            }

            

            // 盈利未达阈值,不启动移动止损

            if(profitPoints < TrailingTrigger) continue;

            

            // 根据盈利大小选择移动止损步长

            int trailingStep = (profitPoints > 30) ? TrailingStop_Enhanced : TrailingStop_Initial;

            double newSl = 0.0;

            bool needModify = false;

            

            // 计算新止损价格(仅向上/向下调整,不回落)

            if(OrderType() == OP_BUY)

            {

                newSl = NormalizeDouble(currentPrice - trailingStep * Point, Digits);

                // 新止损>原止损 或 原止损为0(未设置),才修改

                if(newSl > OrderStopLoss() || OrderStopLoss() == 0)

                {

                    needModify = true;

                }

            }

            else if(OrderType() == OP_SELL)

            {

                newSl = NormalizeDouble(currentPrice + trailingStep * Point, Digits);

                // 新止损<原止损 或 原止损为0(未设置),才修改

                if((newSl < OrderStopLoss() || OrderStopLoss() == 0) && newSl > 0)

                {

                    needModify = true;

                }

            }

            

            if(needModify)

            {

                ModifyOrder(OrderTicket(), OrderOpenPrice(), newSl, OrderTakeProfit());

            }

        }

    }

}


//+------------------------------------------------------------------+

//| 订单修改函数(MT4兼容)                                          |

//+------------------------------------------------------------------+

bool ModifyOrder(int ticket, double openPrice, double sl, double tp)

{

    int retryCount = 0;

    const int maxRetry = 3; // 最多重试3次

   

    while(retryCount < maxRetry)

    {

        if(OrderModify(ticket, openPrice, sl, tp, 0, clrNONE))

        {

            Print("【止损更新成功】订单号:", ticket, ",新SL:", DoubleToStr(sl, Digits));

            return true;

        }

        else

        {

            retryCount++;

            int error = GetLastError();

            Print("【止损更新失败】订单号:", ticket, ",错误代码:", error, ",重试次数:", retryCount);

            Sleep(500); // 延迟500ms后重试

        }

    }

   

    Print("【止损更新失败】订单号:", ticket, ",已达最大重试次数");

    return false;

}


//+------------------------------------------------------------------+

//| 获取多头开仓信号函数                                             |

//+------------------------------------------------------------------+

bool GetBuySignal()

{

    switch(SignalType)

    {

        case SIGNAL_MACD_RSI:

            return GetMACD_RSI_BuySignal();

        case SIGNAL_BOLLINGER:

            return GetBollinger_BuySignal();

        case SIGNAL_MA_CROSS:

            return GetMA_Cross_BuySignal();

        default:

            return false;

    }

}


//+------------------------------------------------------------------+

//| 获取空头开仓信号函数                                             |

//+------------------------------------------------------------------+

bool GetSellSignal()

{

    switch(SignalType)

    {

        case SIGNAL_MACD_RSI:

            return GetMACD_RSI_SellSignal();

        case SIGNAL_BOLLINGER:

            return GetBollinger_SellSignal();

        case SIGNAL_MA_CROSS:

            return GetMA_Cross_SellSignal();

        default:

            return false;

    }

}


//+------------------------------------------------------------------+

//| MACD+RSI多头信号                                                |

//+------------------------------------------------------------------+

bool GetMACD_RSI_BuySignal()

{

    double macdCurrent = iMACD(NULL, 0, MACD_Fast, MACD_Slow, MACD_Signal, PRICE_CLOSE, MODE_MAIN, 0);

    double macdPrevious = iMACD(NULL, 0, MACD_Fast, MACD_Slow, MACD_Signal, PRICE_CLOSE, MODE_MAIN, 1);

    double rsiCurrent = iRSI(NULL, 0, RSI_Period, PRICE_CLOSE, 0);

   

    // MACD金叉 + RSI超卖区域反弹

    return (macdPrevious < 0 && macdCurrent > 0 && rsiCurrent < RSI_Oversold);

}


//+------------------------------------------------------------------+

//| MACD+RSI空头信号                                                |

//+------------------------------------------------------------------+

bool GetMACD_RSI_SellSignal()

{

    double macdCurrent = iMACD(NULL, 0, MACD_Fast, MACD_Slow, MACD_Signal, PRICE_CLOSE, MODE_MAIN, 0);

    double macdPrevious = iMACD(NULL, 0, MACD_Fast, MACD_Slow, MACD_Signal, PRICE_CLOSE, MODE_MAIN, 1);

    double rsiCurrent = iRSI(NULL, 0, RSI_Period, PRICE_CLOSE, 0);

   

    // MACD死叉 + RSI超买区域回落

    return (macdPrevious > 0 && macdCurrent < 0 && rsiCurrent > RSI_Overbought);

}


//+------------------------------------------------------------------+

//| 布林带多头信号                                                  |

//+------------------------------------------------------------------+

bool GetBollinger_BuySignal()

{

    double upperBand = iBands(NULL, 0, Bollinger_Period, Bollinger_Dev, 0, PRICE_CLOSE, MODE_UPPER, 0);

    double lowerBand = iBands(NULL, 0, Bollinger_Period, Bollinger_Dev, 0, PRICE_CLOSE, MODE_LOWER, 0);

    double middleBand = iBands(NULL, 0, Bollinger_Period, Bollinger_Dev, 0, PRICE_CLOSE, MODE_MAIN, 0);

   

    // 价格触及下轨 + 开始反弹

    return (Low[0] <= lowerBand && Close[0] > Open[0] && Close[0] > middleBand);

}


//+------------------------------------------------------------------+

//| 布林带空头信号                                                  |

//+------------------------------------------------------------------+

bool GetBollinger_SellSignal()

{

    double upperBand = iBands(NULL, 0, Bollinger_Period, Bollinger_Dev, 0, PRICE_CLOSE, MODE_UPPER, 0);

    double lowerBand = iBands(NULL, 0, Bollinger_Period, Bollinger_Dev, 0, PRICE_CLOSE, MODE_LOWER, 0);

    double middleBand = iBands(NULL, 0, Bollinger_Period, Bollinger_Dev, 0, PRICE_CLOSE, MODE_MAIN, 0);

   

    // 价格触及上轨 + 开始回落

    return (High[0] >= upperBand && Close[0] < Open[0] && Close[0] < middleBand);

}


//+------------------------------------------------------------------+

//| 均线交叉多头信号                                                |

//+------------------------------------------------------------------+

bool GetMA_Cross_BuySignal()

{

    double maShortCurrent = iMA(NULL, 0, MA_Short, 0, MODE_EMA, PRICE_CLOSE, 0);

    double maLongCurrent = iMA(NULL, 0, MA_Long, 0, MODE_EMA, PRICE_CLOSE, 0);

    double maShortPrevious = iMA(NULL, 0, MA_Short, 0, MODE_EMA, PRICE_CLOSE, 1);

    double maLongPrevious = iMA(NULL, 0, MA_Long, 0, MODE_EMA, PRICE_CLOSE, 1);

   

    // 短期均线上穿长期均线(金叉)

    return (maShortPrevious <= maLongPrevious && maShortCurrent > maLongCurrent);

}


//+------------------------------------------------------------------+

//| 均线交叉空头信号                                                |

//+------------------------------------------------------------------+

bool GetMA_Cross_SellSignal()

{

    double maShortCurrent = iMA(NULL, 0, MA_Short, 0, MODE_EMA, PRICE_CLOSE, 0);

    double maLongCurrent = iMA(NULL, 0, MA_Long, 0, MODE_EMA, PRICE_CLOSE, 0);

    double maShortPrevious = iMA(NULL, 0, MA_Short, 0, MODE_EMA, PRICE_CLOSE, 1);

    double maLongPrevious = iMA(NULL, 0, MA_Long, 0, MODE_EMA, PRICE_CLOSE, 1);

   

    // 短期均线下穿长期均线(死叉)

    return (maShortPrevious >= maLongPrevious && maShortCurrent < maLongCurrent);

}


//+------------------------------------------------------------------+

//| 辅助函数                                                        |

//+------------------------------------------------------------------+


// 更新历史最高权益

void UpdateMaxEquity()

{

    double currentEquity = AccountEquity();

    if(currentEquity > MaxEquity)

    {

        MaxEquity = currentEquity;

    }

}


// 检查市场开盘时间

bool IsMarketOpen()

{

    int dayOfWeek = TimeDayOfWeek(TimeCurrent());

    int hour = TimeHour(TimeCurrent());

   

    // 周末不交易

    if(dayOfWeek == 0 || dayOfWeek == 6)

        return false;

   

    // 交易时段:周一至周五(可根据具体市场调整)

    // 这里简单返回true,实际使用时可根据需要完善

    return true;

}


// 错误描述函数

string ErrorDescription(int errorCode)

{

    switch(errorCode)

    {

        case 0:     return "成功";

        case 1:     return "没有错误";

        case 2:     return "常见错误";

        case 3:     return "无效交易参数";

        case 4:     return "服务器忙";

        case 5:     return "旧版本";

        case 6:     return "无连接";

        case 7:     return "没有足够权限";

        case 8:     return "太频繁请求";

        case 9:     return "违规操作";

        case 64:    return "账户被禁用";

        case 65:    return "无效账户";

        case 128:   return "交易超时";

        case 129:   return "无效价格";

        case 130:   return "无效止损";

        case 131:   return "无效交易量";

        case 132:   return "市场关闭";

        case 133:   return "交易被禁用";

        case 134:   return "资金不足";

        case 135:   return "价格已变化";

        case 136:   return "无价格";

        case 137:   return "经纪人忙";

        case 138:   return "重新报价";

        case 139:   return "订单被锁定";

        case 140:   return "买入订单不被允许";

        case 141:   return "太多请求";

        case 145:   return "交易被修改被禁止";

        case 146:   return "交易上下文忙";

        case 147:   return "过期时间被禁止";

        case 148:   return "订单太多";

        case 149:   return "挂单交易被对冲订单禁止";

        case 150:   return "交易被禁止";

        default:    return "未知错误: " + IntegerToString(errorCode);

    }

}


// 信号类型转字符串

string SignalTypeToString(ENUM_SIGNAL_TYPE type)

{

    switch(type)

    {

        case SIGNAL_MACD_RSI:    return "MACD+RSI组合信号";

        case SIGNAL_BOLLINGER:   return "布林带突破信号";

        case SIGNAL_MA_CROSS:    return "双均线金叉死叉信号";

        default:                 return "未知信号类型";

    }

}


// EA退出原因转字符串

string DeinitReasonToString(int reason)

{

    switch(reason)

    {

        case REASON_ACCOUNT:     return "账户变更";

        case REASON_CHARTCHANGE: return "图表变更";

        case REASON_CHARTCLOSE:  return "图表关闭";

        case REASON_CLOSE:       return "终端关闭";

        case REASON_INITFAILED:  return "初始化失败";

        case REASON_PARAMETERS:  return "参数变更";

        case REASON_RECOMPILE:   return "重新编译";

        case REASON_REMOVE:      return "EA移除";

        case REASON_TEMPLATE:    return "模板变更";

        default:                 return "未知原因: " + IntegerToString(reason);

    }

}


//+------------------------------------------------------------------+
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|EAHub外汇论坛

GMT+8, 2026-10-10 16:38 , Processed in 0.487768 second(s), 19 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表