15117583565 发表于 2026-5-13 22:53:15

求EA源码

求这款EA源码,EA名字是名单网格EA

179469489 发表于 2026-6-6 16:54:59


#property copyright "Copyright 2026"
#property link      "https://www.mql5.com"
#property version   "3.2"
#property strict

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

input group"======= 【EA 启动开关】======="
input bool   启动开关    = true;

// 移动平均线参数
input group"======= 【移动平均线参数】======="
input int                  移动周期         = 10;
input ENUM_MA_METHOD         移动方法         = MODE_SMA;
input ENUM_APPLIED_PRICE   移动应用价格   = PRICE_CLOSE;

// 多单设置
input int                   多单加仓间隔               = 120;             // 多单加仓间隔(点数)
input double                多单加仓倍数               = 1.3;             // 多单加仓倍数
input double                多单初始开仓仓位             = 0.01;            // 多单初始开仓仓位
input double                多单仓位止盈点数             = 50.0;            // 多单仓位止盈点数
input int                   多单加仓次数               = 19;            // 多单加仓次数
input int                   多单加仓间隔2                = 120;             // 多单加仓间隔【2】(点数)
input double                多单加仓倍数2                = 1.3;             // 多单加仓倍数【2】
input double                多单仓位止盈点数2            = 50.0;            // 多单仓位止盈点数【2】
input int                   多单加仓次数2                = 1;               // 多单加仓次数【2】

// 空单设置
input int                   空单加仓间隔               = 120;             // 空单加仓间隔(点数)
input double                空单加仓倍数               = 1.3;             // 空单加仓倍数
input double                空单初始开仓仓位             = 0.01;            // 空单初始开仓仓位
input double                空单仓位止盈点数             = 50.0;            // 空单仓位止盈点数
input int                   空单加仓次数               = 19;            // 空单加仓次数
input int                   空单加仓间隔2                = 120;             // 空单加仓间隔【2】(点数)
input double                空单加仓倍数2                = 1.3;             // 空单加仓倍数【2】
input double                空单仓位止盈点数2            = 50.0;            // 空单仓位止盈点数【2】
input int                   空单加仓次数2                = 1;               // 空单加仓次数【2】

// 风控设置
input double                整体盈利全平               = 0.0;             // 整体盈利全平(美元)
input double                整体亏损全平               = 0.0;             // 整体亏损全平(美元)
input int                   最大浮点数                   = 10;            // 最大浮点数(备用)
input double                盈利多少后今天停止         = 9999.0;          // 盈利多少后今天停止(美元)
input double                亏损多少后今天停止         = 9999999.0;       // 亏损多少后今天停止(美元)
input int                   字体大小                     = 12;            // 字体大小

// 辅助参数(非图片参数)
input int                   交易滑点                     = 10;            // 交易滑点
input int                   加仓冷却秒                   = 5;               // 加仓冷却秒

//+------------------------------------------------------------------+
//| 全局变量                                                         |
//+------------------------------------------------------------------+
double                     g_point          = 0.0;
int                        g_digits         = 0;
bool                         g_activated      = false;
string                     g_auth_tip       = "未启动";
bool                         g_is_tester      = false;

int                        ma_handle      = -1;
int                        trend_dir      = 0;            // 1:上涨 -1:下跌 0:震荡

datetime                     g_last_buy_time= 0;
datetime                     g_last_sell_time = 0;

double                     g_today_start_balance = 0.0;
bool                         g_today_stop            = false;
datetime                     g_last_day_check       = 0;

// 合并后的最大加仓次数
int                        max_buy_additions;
int                        max_sell_additions;
double                     buy_add_spacing;
double                     sell_add_spacing;
double                     buy_add_mult;
double                     sell_add_mult;

// 按钮名称
#define BUTTON_CLOSE_ALL   "Btn_CloseAll"
#define BUTTON_CLOSE_BUY   "Btn_CloseBuy"
#define BUTTON_CLOSE_SELL"Btn_CloseSell"

//+------------------------------------------------------------------+
//| 工具函数                                                         |
//+------------------------------------------------------------------+
int GetBuyCount() {
   int c = 0;
   for(int i = 0; i < PositionsTotal(); i++) {
      ulong t = PositionGetTicket(i);
      if(PositionSelectByTicket(t) && PositionGetInteger(POSITION_MAGIC) == 0 && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
         c++;
   }
   return c;
}

int GetSellCount() {
   int c = 0;
   for(int i = 0; i < PositionsTotal(); i++) {
      ulong t = PositionGetTicket(i);
      if(PositionSelectByTicket(t) && PositionGetInteger(POSITION_MAGIC) == 0 && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
         c++;
   }
   return c;
}

double GetTotalProfitUSD() {
   double p = 0;
   for(int i = 0; i < PositionsTotal(); i++) {
      ulong t = PositionGetTicket(i);
      if(!PositionSelectByTicket(t)) continue;
      if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
      if(PositionGetInteger(POSITION_MAGIC) != 0) continue;
      p += PositionGetDouble(POSITION_PROFIT);
   }
   return p;
}

double GetLastBuyPrice() {
   double p = 0;
   datetime t = 0;
   for(int i = 0; i < PositionsTotal(); i++) {
      ulong tk = PositionGetTicket(i);
      if(PositionSelectByTicket(tk) && PositionGetInteger(POSITION_MAGIC) == 0 && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
         datetime ot = (datetime)PositionGetInteger(POSITION_TIME);
         if(ot > t) {
            t = ot;
            p = PositionGetDouble(POSITION_PRICE_OPEN);
         }
      }
   }
   return p;
}

double GetLastSellPrice() {
   double p = 0;
   datetime t = 0;
   for(int i = 0; i < PositionsTotal(); i++) {
      ulong tk = PositionGetTicket(i);
      if(PositionSelectByTicket(tk) && PositionGetInteger(POSITION_MAGIC) == 0 && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
         datetime ot = (datetime)PositionGetInteger(POSITION_TIME);
         if(ot > t) {
            t = ot;
            p = PositionGetDouble(POSITION_PRICE_OPEN);
         }
      }
   }
   return p;
}

double CalcLot(int level, double init_lot, double mult) {
   double lot = init_lot;
   for(int i = 2; i <= level; i++) lot *= mult;
   double min_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double max_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   lot = MathMax(min_lot, MathMin(max_lot, lot));
   return NormalizeDouble(lot, 2);
}

//+------------------------------------------------------------------+
//| 移动平均线趋势                                                   |
//+------------------------------------------------------------------+
void AnalyzeTrend() {
   double ma;
   if(CopyBuffer(ma_handle, 0, 0, 3, ma) < 3) return;
   if(ma > ma && ma > ma)      trend_dir = 1;
   else if(ma < ma && ma < ma) trend_dir = -1;
   else                                     trend_dir = 0;
}

//+------------------------------------------------------------------+
//| 创建按钮                                                         |
//+------------------------------------------------------------------+
void CreateButton(string name, int x, int y, int width, int height, string text, color bgColor, color textColor, int fontSize) {
   if(ObjectFind(0, name) == -1) {
      ObjectCreate(0, name, OBJ_BUTTON, 0, 0, 0);
      ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
      ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
      ObjectSetInteger(0, name, OBJPROP_XSIZE, width);
      ObjectSetInteger(0, name, OBJPROP_YSIZE, height);
      ObjectSetString(0, name, OBJPROP_TEXT, text);
      ObjectSetInteger(0, name, OBJPROP_BGCOLOR, bgColor);
      ObjectSetInteger(0, name, OBJPROP_COLOR, textColor);
      ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize);
      ObjectSetInteger(0, name, OBJPROP_BORDER_COLOR, clrBlack);
      ObjectSetInteger(0, name, OBJPROP_STATE, false);
   }
}

//+------------------------------------------------------------------+
//| 面板显示(含按钮)                                                |
//+------------------------------------------------------------------+
void CreateLabel(long chartID, int x, int y, string text, color clr, int fontSize) {
   string labelName = "PANEL_" + IntegerToString(x) + "_" + IntegerToString(y);
   if(ObjectFind(chartID, labelName) != -1) ObjectDelete(chartID, labelName);
   ObjectCreate(chartID, labelName, OBJ_LABEL, 0, 0, 0);
   ObjectSetInteger(chartID, labelName, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(chartID, labelName, OBJPROP_YDISTANCE, y);
   ObjectSetString(chartID, labelName, OBJPROP_TEXT, text);
   ObjectSetInteger(chartID, labelName, OBJPROP_COLOR, clr);
   ObjectSetInteger(chartID, labelName, OBJPROP_FONTSIZE, fontSize);
   ObjectSetInteger(chartID, labelName, OBJPROP_BACK, true);
}

void DrawPanel() {
   int x = 140;
   int y = 70;
   int line = 18;
   CreateLabel(0, x, y, "", clrGold, 14);
   y += line + 5;
   CreateLabel(0, x, y, "运行状态 : " + g_auth_tip, clrLime, 字体大小);
   y += line;
   double profit = GetTotalProfitUSD();
   color pColor = (profit >= 0) ? clrGreen : clrRed;
   CreateLabel(0, x, y, "当前浮盈 : " + DoubleToString(profit, 2), pColor, 字体大小);
   y += line;
   int b = GetBuyCount(), s = GetSellCount();
   CreateLabel(0, x, y, "多单数量 : " + (string)b, clrBlue, 字体大小);
   y += line;
   CreateLabel(0, x, y, "空单数量 : " + (string)s, clrRed, 字体大小);
   y += line;
   CreateLabel(0, x, y, "多单加仓间隔 : " + DoubleToString(多单加仓间隔, 0) + "点", clrYellow, 字体大小);
   y += line;
   CreateLabel(0, x, y, "空单加仓间隔 : " + DoubleToString(空单加仓间隔, 0) + "点", clrYellow, 字体大小);
   y += line;
   string trend_str = trend_dir == 1 ? "上涨" : (trend_dir == -1 ? "下跌" : "震荡");
   CreateLabel(0, x, y, "当前趋势 : " + trend_str, clrCyan, 字体大小);
   y += line;
   double today_pnl = AccountInfoDouble(ACCOUNT_BALANCE) - g_today_start_balance;
   CreateLabel(0, x, y, "今日盈亏 : " + DoubleToString(today_pnl, 2), clrWhite, 字体大小);
   y += line + 8;
   
   // 创建三个按钮(位于面板下方)
   int btnWidth = 70, btnHeight = 25;
   CreateButton(BUTTON_CLOSE_BUY,x,               y, btnWidth, btnHeight, "多单全平", clrBlue, clrWhite, 10);
   CreateButton(BUTTON_CLOSE_SELL, x + btnWidth+5,y, btnWidth, btnHeight, "空单全平", clrRed, clrWhite, 10);
   CreateButton(BUTTON_CLOSE_ALL,x + 2*(btnWidth+5), y, btnWidth, btnHeight, "全平", clrDarkGray, clrWhite, 10);
}

//+------------------------------------------------------------------+
//| 平仓函数                                                         |
//+------------------------------------------------------------------+
void ClosePos(ulong tk) {
   if(!PositionSelectByTicket(tk)) return;
   MqlTradeRequest r;
   MqlTradeResult res;
   ZeroMemory(r);
   r.action = TRADE_ACTION_DEAL;
   r.symbol = _Symbol;
   r.position = tk;
   r.magic = 0;
   r.volume = PositionGetDouble(POSITION_VOLUME);
   r.type = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
   r.price = (r.type == ORDER_TYPE_SELL) ? SymbolInfoDouble(_Symbol, SYMBOL_BID) : SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   r.deviation = 交易滑点;
   Exec(r, res);
}

void CloseAll() {
   for(int i = PositionsTotal() - 1; i >= 0; i--) {
      ulong t = PositionGetTicket(i);
      if(PositionSelectByTicket(t) && PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == 0)
         ClosePos(t);
   }
}

void CloseBuyAll() {
   for(int i = PositionsTotal() - 1; i >= 0; i--) {
      ulong t = PositionGetTicket(i);
      if(PositionSelectByTicket(t) && PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == 0) {
         if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
            ClosePos(t);
      }
   }
}

void CloseSellAll() {
   for(int i = PositionsTotal() - 1; i >= 0; i--) {
      ulong t = PositionGetTicket(i);
      if(PositionSelectByTicket(t) && PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == 0) {
         if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
            ClosePos(t);
      }
   }
}

//+------------------------------------------------------------------+
//| 授权检查(取消账户限制)                                           |
//+------------------------------------------------------------------+
void CheckLicense() {
   g_is_tester = (bool)MQLInfoInteger(MQL_TESTER);
   if(g_is_tester) {
      g_activated = true;
      g_auth_tip = "回测模式";
      return;
   }
   if(!启动开关) {
      g_activated = false;
      g_auth_tip = "已停止";
      return;
   }
   // 无账户限制,直接激活
   g_activated = true;
   g_auth_tip = "正常运行";
}

//+------------------------------------------------------------------+
//| 交易执行                                                         |
//+------------------------------------------------------------------+
bool Exec(MqlTradeRequest &r, MqlTradeResult &res) {
   ZeroMemory(res);
   bool sent = OrderSend(r, res);
   if(!sent || res.retcode != TRADE_RETCODE_DONE) {
      Print("订单失败:", res.comment);
      return false;
   }
   return true;
}

bool OpenBuy(double lot) {
   if(!g_activated) return false;
   if(TimeCurrent() - g_last_buy_time < 加仓冷却秒) return false;
   MqlTradeRequest r;
   MqlTradeResult res;
   ZeroMemory(r);
   r.action = TRADE_ACTION_DEAL;
   r.symbol = _Symbol;
   r.volume = NormalizeDouble(lot, 2);
   r.type = ORDER_TYPE_BUY;
   r.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   r.deviation = 交易滑点;
   r.type_filling = ORDER_FILLING_IOC;
   r.magic = 0;
   bool ok = Exec(r, res);
   if(ok) g_last_buy_time = TimeCurrent();
   return ok;
}

bool OpenSell(double lot) {
   if(!g_activated) return false;
   if(TimeCurrent() - g_last_sell_time < 加仓冷却秒) return false;
   MqlTradeRequest r;
   MqlTradeResult res;
   ZeroMemory(r);
   r.action = TRADE_ACTION_DEAL;
   r.symbol = _Symbol;
   r.volume = NormalizeDouble(lot, 2);
   r.type = ORDER_TYPE_SELL;
   r.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   r.deviation = 交易滑点;
   r.type_filling = ORDER_FILLING_IOC;
   r.magic = 0;
   bool ok = Exec(r, res);
   if(ok) g_last_sell_time = TimeCurrent();
   return ok;
}

//+------------------------------------------------------------------+
//| 独立仓位止盈                                                   |
//+------------------------------------------------------------------+
void CheckSingleTP() {
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   for(int i = PositionsTotal() - 1; i >= 0; i--) {
      ulong ticket = PositionGetTicket(i);
      if(!PositionSelectByTicket(ticket)) continue;
      if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
      if(PositionGetInteger(POSITION_MAGIC) != 0) continue;
      double open_price = PositionGetDouble(POSITION_PRICE_OPEN);
      double points;
      double tp_points;
      if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
         points = (bid - open_price) / g_point;
         tp_points = 多单仓位止盈点数;
      } else {
         points = (open_price - ask) / g_point;
         tp_points = 空单仓位止盈点数;
      }
      if(points >= tp_points && tp_points > 0) {
         ClosePos(ticket);
         Print("独立止盈触发, 盈利点数: ", points);
      }
   }
}

//+------------------------------------------------------------------+
//| 整体盈利/亏损全平                                                 |
//+------------------------------------------------------------------+
void CheckGlobalPLClose() {
   double profit = GetTotalProfitUSD();
   if(整体盈利全平 > 0 && profit >= 整体盈利全平) {
      CloseAll();
      Print("整体盈利全平: ", profit);
   }
   if(整体亏损全平 > 0 && -profit >= 整体亏损全平) {
      CloseAll();
      Print("整体亏损全平: ", -profit);
   }
}

//+------------------------------------------------------------------+
//| 今日停止逻辑(修复日期比较)                                       |
//+------------------------------------------------------------------+
bool IsNewDay() {
   MqlDateTime tmNow, tmLast;
   datetime now = TimeCurrent();
   TimeToStruct(now, tmNow);
   TimeToStruct(g_last_day_check, tmLast);
   if(tmNow.year != tmLast.year || tmNow.mon != tmLast.mon || tmNow.day != tmLast.day) {
      g_last_day_check = now;
      return true;
   }
   return false;
}

void UpdateDailyStop() {
   if(IsNewDay()) {
      g_today_start_balance = AccountInfoDouble(ACCOUNT_BALANCE);
      g_today_stop = false;
   }
   if(g_today_stop) return;
   double today_pnl = AccountInfoDouble(ACCOUNT_BALANCE) - g_today_start_balance;
   if(盈利多少后今天停止 > 0 && today_pnl >= 盈利多少后今天停止) {
      g_today_stop = true;
      Print("今日盈利达标,停止交易。");
   }
   if(亏损多少后今天停止 > 0 && -today_pnl >= 亏损多少后今天停止) {
      g_today_stop = true;
      Print("今日亏损达标,停止交易。");
   }
}

//+------------------------------------------------------------------+
//| 首单开仓(依据趋势)                                              |
//+------------------------------------------------------------------+
void OpenFirstOrder() {
   if(GetBuyCount() > 0 || GetSellCount() > 0) return;
   if(trend_dir == 1) {
      OpenBuy(多单初始开仓仓位);
   } else if(trend_dir == -1) {
      OpenSell(空单初始开仓仓位);
   }
}

//+------------------------------------------------------------------+
//| 同向加仓                                                         |
//+------------------------------------------------------------------+
void AddPositionSameDirection() {
   int b = GetBuyCount();
   int s = GetSellCount();
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   
   if(trend_dir == 1 && s == 0 && b > 0 && b <= max_buy_additions) {
      double last = GetLastBuyPrice();
      if(last <= 0) return;
      double drop = (last - ask) / g_point;
      if(drop >= buy_add_spacing) {
         double lot = CalcLot(b + 1, 多单初始开仓仓位, buy_add_mult);
         if(OpenBuy(lot))
            Print("多单加仓第", b+1, "层");
      }
   }
   
   if(trend_dir == -1 && b == 0 && s > 0 && s <= max_sell_additions) {
      double last = GetLastSellPrice();
      if(last <= 0) return;
      double rise = (bid - last) / g_point;
      if(rise >= sell_add_spacing) {
         double lot = CalcLot(s + 1, 空单初始开仓仓位, sell_add_mult);
         if(OpenSell(lot))
            Print("空单加仓第", s+1, "层");
      }
   }
}

//+------------------------------------------------------------------+
//| 趋势反转处理                                                   |
//+------------------------------------------------------------------+
void HandleTrendReversal() {
   int b = GetBuyCount();
   int s = GetSellCount();
   if(trend_dir == 1 && s > 0) {
      CloseAll();
      if(GetBuyCount() == 0 && GetSellCount() == 0)
         OpenFirstOrder();
   }
   else if(trend_dir == -1 && b > 0) {
      CloseAll();
      if(GetBuyCount() == 0 && GetSellCount() == 0)
         OpenFirstOrder();
   }
   else if(trend_dir == 0 && (b > 0 || s > 0)) {
      CloseAll();
   }
}

//+------------------------------------------------------------------+
//| 主策略                                                         |
//+------------------------------------------------------------------+
void RunStrategy() {
   UpdateDailyStop();
   if(g_today_stop) return;
   
   CheckSingleTP();
   CheckGlobalPLClose();
   HandleTrendReversal();
   
   if(GetBuyCount() == 0 && GetSellCount() == 0)
      OpenFirstOrder();
   else
      AddPositionSameDirection();
}

//+------------------------------------------------------------------+
//| 图表事件处理(按钮点击)                                           |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) {
   if(id == CHARTEVENT_OBJECT_CLICK) {
      if(sparam == BUTTON_CLOSE_ALL) {
         CloseAll();
         Print("用户点击【全平】按钮");
      }
      else if(sparam == BUTTON_CLOSE_BUY) {
         CloseBuyAll();
         Print("用户点击【多单全平】按钮");
      }
      else if(sparam == BUTTON_CLOSE_SELL) {
         CloseSellAll();
         Print("用户点击【空单全平】按钮");
      }
   }
}

//+------------------------------------------------------------------+
//| 初始化                                                         |
//+------------------------------------------------------------------+
int OnInit() {
   CheckLicense();
   g_point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   if(_Symbol == "XAUUSD" || _Symbol == "XAUUSDC") g_point = 0.00001;
   g_digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
   
   ma_handle = iMA(_Symbol, Period(), 移动周期, 0, 移动方法, 移动应用价格);
   if(ma_handle == INVALID_HANDLE) return INIT_FAILED;
   
   // 合并加仓次数
   max_buy_additions= 多单加仓次数 + 多单加仓次数2;
   max_sell_additions = 空单加仓次数 + 空单加仓次数2;
   buy_add_spacing   = 多单加仓间隔;
   sell_add_spacing= 空单加仓间隔;
   buy_add_mult      = 多单加仓倍数;
   sell_add_mult   = 空单加仓倍数;
   
   g_today_start_balance = AccountInfoDouble(ACCOUNT_BALANCE);
   g_today_stop = false;
   g_last_day_check = TimeCurrent();
   
   ObjectsDeleteAll(0);
   return INIT_SUCCEEDED;
}

void OnDeinit(const int reason) {
   ObjectsDeleteAll(0);
   if(ma_handle != -1) IndicatorRelease(ma_handle);
}

//+------------------------------------------------------------------+
//| 逐Tick运行                                                       |
//+------------------------------------------------------------------+
void OnTick() {
   CheckLicense();
   AnalyzeTrend();
   DrawPanel();
   if(!g_activated) return;
   RunStrategy();
}
//+------------------------------------------------------------------+

179469489 发表于 2026-6-6 16:55:49

OK 我这有可以来看看
页: [1]
查看完整版本: 求EA源码