设为首页 收藏本站 切换语言

MT5編碼請求幫忙!!

| 发表于 5 天前 | 显示全部楼层 |复制链接
最近正在學習寫EA,東拼西湊了一些內容
可是總是出現Compile總是出現錯誤,主要是跟「POSITION」函數有關

想請各位高手指導!!


EA的邏輯是雙均線+RSI過濾+MACD過濾

1.進場條件:

  (1)多單:
      當前無多單
      均線黃金交叉
      RSI 小於設定值
      MACD 黃金交叉
  (2)空單:
      當前無空單
      均線死亡交叉
      RSI 大於設定值
      MACD 死亡交叉
2.出場條件

      均線反向交叉 + MACD 反向交叉
      或虧損達到設定值
      或移動停利
3.手數手動設定


----------------------------------------------------------------------------------------------------------------
//+------------------------------------------------------------------+
//|                 MA_RSI_MACD_Strategy.mq5                         |
//+------------------------------------------------------------------+
#property strict

input double TradeLot        = 0.1;      // 固定手數
input int FastMAPeriod       = 12;
input int SlowMAPeriod       = 26;
input ENUM_MA_METHOD MaMethod = MODE_SMA;
input ENUM_APPLIED_PRICE MaPrice = PRICE_CLOSE;

input int RsiPeriod          = 14;
input double RsiBuyLevel     = 30.0;
input double RsiSellLevel    = 70.0;

input int MacdFast           = 12;
input int MacdSlow           = 26;
input int MacdSignal         = 9;

input double StopLoss        = 100;      // 點數
input double TrailingStop    = 80;       // 移動停利點數

input ENUM_TIMEFRAMES TF     = PERIOD_H1;

datetime lastTradeTime = 0;

//+------------------------------------------------------------------+
//| 取得指標值                                                      |
//+------------------------------------------------------------------+
bool IsGoldenCross()
{
   double fastPrev = iMA(_Symbol, TF, FastMAPeriod, 0, MaMethod, MaPrice, 1);
   double slowPrev = iMA(_Symbol, TF, SlowMAPeriod, 0, MaMethod, MaPrice, 1);
   double fastCurr = iMA(_Symbol, TF, FastMAPeriod, 0, MaMethod, MaPrice, 0);
   double slowCurr = iMA(_Symbol, TF, SlowMAPeriod, 0, MaMethod, MaPrice, 0);
   return (fastPrev < slowPrev && fastCurr > slowCurr);
}

bool IsDeathCross()
{
   double fastPrev = iMA(_Symbol, TF, FastMAPeriod, 0, MaMethod, MaPrice, 1);
   double slowPrev = iMA(_Symbol, TF, SlowMAPeriod, 0, MaMethod, MaPrice, 1);
   double fastCurr = iMA(_Symbol, TF, FastMAPeriod, 0, MaMethod, MaPrice, 0);
   double slowCurr = iMA(_Symbol, TF, SlowMAPeriod, 0, MaMethod, MaPrice, 0);
   return (fastPrev > slowPrev && fastCurr < slowCurr);
}

bool IsMACDGoldenCross()
{
   double macdPrev, signalPrev, macdCurr, signalCurr;
   iMACD(_Symbol, TF, MacdFast, MacdSlow, MacdSignal, PRICE_CLOSE, macdPrev, signalPrev, 1);
   iMACD(_Symbol, TF, MacdFast, MacdSlow, MacdSignal, PRICE_CLOSE, macdCurr, signalCurr, 0);
   return (macdPrev < signalPrev && macdCurr > signalCurr);
}

bool IsMACDDeathCross()
{
   double macdPrev, signalPrev, macdCurr, signalCurr;
   iMACD(_Symbol, TF, MacdFast, MacdSlow, MacdSignal, PRICE_CLOSE, macdPrev, signalPrev, 1);
   iMACD(_Symbol, TF, MacdFast, MacdSlow, MacdSignal, PRICE_CLOSE, macdCurr, signalCurr, 0);
   return (macdPrev > signalPrev && macdCurr < signalCurr);
}

double GetRSI()
{
   return iRSI(_Symbol, TF, RsiPeriod, PRICE_CLOSE, 0);
}

//+------------------------------------------------------------------+
//| 主邏輯:OnTick                                                   |
//+------------------------------------------------------------------+
void OnTick()
{
   // 檢查是否已經有單
   bool hasBuy = PositionSelect(_Symbol) && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY;
   bool hasSell = PositionSelect(_Symbol) && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL;

   double rsi = GetRSI();
   double sl = StopLoss * _Point;
   double tp = 0;

   // 進多單條件
   if (!hasBuy && IsGoldenCross() && rsi < RsiBuyLevel && IsMACDGoldenCross())
   {
      if (OrderSend(_Symbol, OP_BUY, TradeLot, Ask, 10, Ask - sl, tp, "Buy Order", 0, 0, clrBlue) > 0)
         lastTradeTime = TimeCurrent();
   }

   // 進空單條件
   if (!hasSell && IsDeathCross() && rsi > RsiSellLevel && IsMACDDeathCross())
   {
      if (OrderSend(_Symbol, OP_SELL, TradeLot, Bid, 10, Bid + sl, tp, "Sell Order", 0, 0, clrRed) > 0)
         lastTradeTime = TimeCurrent();
   }

   // 出場邏輯(包含反向交叉、移動停利)
   if (PositionSelect(_Symbol))
   {
      ulong ticket = PositionGetInteger(POSITION_TICKET);
      double entryPrice = PositionGetDouble(POSITION_PRICE_OPEN);
      double stopLoss = PositionGetDouble(POSITION_SL);
      double currentPrice = SymbolInfoDouble(_Symbol, PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY ? SYMBOL_BID : SYMBOL_ASK);
      double profit = PositionGetDouble(POSITION_PROFIT);

      // 出場條件
      bool exitBuy = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY &&
                      (IsDeathCross() && IsMACDDeathCross()));

      bool exitSell = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL &&
                       (IsGoldenCross() && IsMACDGoldenCross()));

      if (exitBuy || exitSell)
         PositionClose(ticket);
      
      // 移動停利
      if (TrailingStop > 0)
      {
         double trail = TrailingStop * _Point;
         double newSL;
         if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
         {
            newSL = currentPrice - trail;
            if (newSL > stopLoss)
               PositionModify(ticket, newSL, 0);
         }
         else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
         {
            newSL = currentPrice + trail;
            if (newSL < stopLoss)
               PositionModify(ticket, newSL, 0);
         }
      }
   }
}

举报

评论 使用道具

精彩评论3

qiwen
C
| 发表于 5 天前 | 显示全部楼层
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
input double TradeLot        = 0.1;      // 固定手數
input int FastMAPeriod       = 12;
input int SlowMAPeriod       = 26;
input ENUM_MA_METHOD MaMethod = MODE_SMA;
input ENUM_APPLIED_PRICE MaPrice = PRICE_CLOSE;

input int RsiPeriod          = 14;
input double RsiBuyLevel     = 30.0;
input double RsiSellLevel    = 70.0;

input int MacdFast           = 12;
input int MacdSlow           = 26;
input int MacdSignal         = 9;

input double StopLoss        = 100;      // 點數
input double TakeProfit      = 200;      // 固定止盈
input double TrailingStop    = 80;       // 移動停利點數
input int MinTradeGap        = 3600;     // 最小交易間隔(秒)

input ENUM_TIMEFRAMES TF     = PERIOD_H1;

datetime lastTradeTime = 0;

//+------------------------------------------------------------------+
//| 指標計算(修正 MQL5 語法)                                      |
//+------------------------------------------------------------------+
bool IsGoldenCross()
{
   double fastPrev[], slowPrev[], fastCurr[], slowCurr[];
   ArraySetAsSeries(fastPrev, true);
   ArraySetAsSeries(slowPrev, true);
   ArraySetAsSeries(fastCurr, true);
   ArraySetAsSeries(slowCurr, true);
   
   int fastMaHandle = iMA(_Symbol, TF, FastMAPeriod, 0, MaMethod, MaPrice);
   int slowMaHandle = iMA(_Symbol, TF, SlowMAPeriod, 0, MaMethod, MaPrice);
   
   CopyBuffer(fastMaHandle, 0, 1, 1, fastPrev);
   CopyBuffer(slowMaHandle, 0, 1, 1, slowPrev);
   CopyBuffer(fastMaHandle, 0, 0, 1, fastCurr);
   CopyBuffer(slowMaHandle, 0, 0, 1, slowCurr);
   
   return (fastPrev[0] < slowPrev[0] && fastCurr[0] > slowCurr[0]);
}

bool IsDeathCross()
{
   double fastPrev[], slowPrev[], fastCurr[], slowCurr[];
   ArraySetAsSeries(fastPrev, true);
   ArraySetAsSeries(slowPrev, true);
   ArraySetAsSeries(fastCurr, true);
   ArraySetAsSeries(slowCurr, true);
   
   int fastMaHandle = iMA(_Symbol, TF, FastMAPeriod, 0, MaMethod, MaPrice);
   int slowMaHandle = iMA(_Symbol, TF, SlowMAPeriod, 0, MaMethod, MaPrice);
   
   CopyBuffer(fastMaHandle, 0, 1, 1, fastPrev);
   CopyBuffer(slowMaHandle, 0, 1, 1, slowPrev);
   CopyBuffer(fastMaHandle, 0, 0, 1, fastCurr);
   CopyBuffer(slowMaHandle, 0, 0, 1, slowCurr);
   
   return (fastPrev[0] > slowPrev[0] && fastCurr[0] < slowCurr[0]);
}

bool IsMACDGoldenCross()
{
   double macdPrev[], signalPrev[];
   ArraySetAsSeries(macdPrev, true);
   ArraySetAsSeries(signalPrev, true);
   int macdHandle = iMACD(_Symbol, TF, MacdFast, MacdSlow, MacdSignal, PRICE_CLOSE);
   CopyBuffer(macdHandle, 0, 0, 2, macdPrev);
   CopyBuffer(macdHandle, 1, 0, 2, signalPrev);
   return (macdPrev[1] < signalPrev[1] && macdPrev[0] > signalPrev[0]);
}

bool IsMACDDeathCross()
{
   double macdPrev[], signalPrev[];
   ArraySetAsSeries(macdPrev, true);
   ArraySetAsSeries(signalPrev, true);
   int macdHandle = iMACD(_Symbol, TF, MacdFast, MacdSlow, MacdSignal, PRICE_CLOSE);
   CopyBuffer(macdHandle, 0, 0, 2, macdPrev);
   CopyBuffer(macdHandle, 1, 0, 2, signalPrev);
   return (macdPrev[1] > signalPrev[1] && macdPrev[0] < signalPrev[0]);
}

double GetRSI()
{
   double rsi[];
   ArraySetAsSeries(rsi, true);
   int rsiHandle = iRSI(_Symbol, TF, RsiPeriod, PRICE_CLOSE);
   CopyBuffer(rsiHandle, 0, 0, 1, rsi);
   return rsi[0];
}

//+------------------------------------------------------------------+
//| 交易邏輯(修正 MQL5 交易函數)                                 |
//+------------------------------------------------------------------+
void OnTick()
{
   // 檢查交易間隔
   if (TimeCurrent() - lastTradeTime < MinTradeGap)
      return;

   // 檢查持倉
   bool hasBuy = PositionSelect(_Symbol) && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY;
   bool hasSell = PositionSelect(_Symbol) && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL;

   double rsi = GetRSI();
   double sl = StopLoss * _Point;
   double tp = TakeProfit * _Point;

   // 進多單條件
   if (!hasBuy && IsGoldenCross() && rsi < RsiBuyLevel && IsMACDGoldenCross())
   {
      MqlTradeRequest request = {};
      MqlTradeResult result = {};
      request.action = TRADE_ACTION_DEAL;
      request.symbol = _Symbol;
      request.volume = TradeLot;
      request.type = ORDER_TYPE_BUY;
      request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      request.sl = request.price - sl;
      request.tp = request.price + tp;
      request.deviation = 10;
      request.comment = "Buy Order";
      request.magic = 0;
      
      if(!OrderSend(request, result))
         Print("Buy Order failed, error code: ", GetLastError());
      else
         lastTradeTime = TimeCurrent();
   }

   // 進空單條件
   if (!hasSell && IsDeathCross() && rsi > RsiSellLevel && IsMACDDeathCross())
   {
      MqlTradeRequest request = {};
      MqlTradeResult result = {};
      request.action = TRADE_ACTION_DEAL;
      request.symbol = _Symbol;
      request.volume = TradeLot;
      request.type = ORDER_TYPE_SELL;
      request.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      request.sl = request.price + sl;
      request.tp = request.price - tp;
      request.deviation = 10;
      request.comment = "Sell Order";
      request.magic = 0;
      
      if(!OrderSend(request, result))
         Print("Sell Order failed, error code: ", GetLastError());
      else
         lastTradeTime = TimeCurrent();
   }

   // 移動停利與出場邏輯
   if (PositionSelect(_Symbol))
   {
      ulong ticket = PositionGetInteger(POSITION_TICKET);
      double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);
      double stopLoss = PositionGetDouble(POSITION_SL);
      double profit = PositionGetDouble(POSITION_PROFIT);

      // 移動停利(僅向有利方向移動)
      if (TrailingStop > 0)
      {
         double trail = TrailingStop * _Point;
         double newSL;
         if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
         {
            newSL = currentPrice - trail;
            if (newSL > stopLoss && newSL > PositionGetDouble(POSITION_PRICE_OPEN) - sl)
            {
               MqlTradeRequest request = {};
               MqlTradeResult result = {};
               request.action = TRADE_ACTION_SLTP;
               request.position = ticket;
               request.sl = newSL;
               request.tp = PositionGetDouble(POSITION_TP);
               if(!OrderSend(request, result))
                  Print("Modify SL failed, error code: ", GetLastError());
            }
         }
         else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
         {
            newSL = currentPrice + trail;
            if (newSL < stopLoss && newSL < PositionGetDouble(POSITION_PRICE_OPEN) + sl)
            {
               MqlTradeRequest request = {};
               MqlTradeResult result = {};
               request.action = TRADE_ACTION_SLTP;
               request.position = ticket;
               request.sl = newSL;
               request.tp = PositionGetDouble(POSITION_TP);
               if(!OrderSend(request, result))
                  Print("Modify SL failed, error code: ", GetLastError());
            }
         }
      }

      // 強制平倉條件
      bool exitBuy = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY &&
                     (IsDeathCross() && profit > 0));

      bool exitSell = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL &&
                      (IsGoldenCross() && profit > 0));

      if (exitBuy || exitSell)
      {
         MqlTradeRequest request = {};
         MqlTradeResult result = {};
         request.action = TRADE_ACTION_DEAL;
         request.symbol = _Symbol;
         request.volume = PositionGetDouble(POSITION_VOLUME);
         request.type = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
         request.price = (request.type == ORDER_TYPE_SELL) ? SymbolInfoDouble(_Symbol, SYMBOL_BID) : SymbolInfoDouble(_Symbol, SYMBOL_ASK);
         request.position = ticket;
         request.deviation = 10;
         if(!OrderSend(request, result))
            Print("Close position failed, error code: ", GetLastError());
      }
   }
}
举报

点赞 评论 使用道具

qiwen
C
| 发表于 5 天前 | 显示全部楼层
MQL5 使用 MqlTradeRequest 和 MqlTradeResult 结构体,而非直接传参。

iMACD 和 iRSI 需使用 CopyBuffer 获取数据。
移动止损 (TrailingStop):使用 TRADE_ACTION_SLTP 修改持仓的止损/止盈。
平仓逻辑:通过 TRADE_ACTION_DEAL 反向交易平仓。
关于 iMA() 函数的参数数量不正确,以及 OrderSend() 的返回值没有被检查
iMA() 函数调用修正:
现在使用 CopyBuffer 获取移动平均线数据,而不是直接调用 iMA() 获取值
创建指标句柄后复制缓冲区数据
OrderSend() 返回值检查:
所有 OrderSend() 调用现在都检查返回值
如果失败,会打印错误代码
移动平均线交叉逻辑优化:
使用数组存储指标值
通过 CopyBuffer 获取前一根和当前K线的值
错误处理增强:
每个交易操作都添加了错误检查
使用 GetLastError() 获取错误代码
举报

点赞 1 评论 使用道具

bobochen0908
DD
 楼主 | 发表于 5 天前 | 显示全部楼层
qiwen 发表于 2025-4-12 11:17
MQL5 使用 MqlTradeRequest 和 MqlTradeResult 结构体,而非直接传参。

iMACD 和 iRSI 需使用 CopyBuffer  ...

太強了!!!  感謝大神教學!!!
慢慢消化中
举报

点赞 评论 使用道具

发新帖
EA交易
您需要登录后才可以评论 登录 | 立即注册

简体中文
繁體中文
English(英语)
日本語(日语)
Deutsch(德语)
Русский язык(俄语)
بالعربية(阿拉伯语)
Türkçe(土耳其语)
Português(葡萄牙语)
ภาษาไทย(泰国语)
한어(朝鲜语/韩语)
Français(法语)