명시

//+------------------------------------------------------------------+
//| XAUUSD M5 TELEGRAM TRADING EA |
//| EMA 20/50/200 + RSI + ATR + Telegram |
//+------------------------------------------------------------------+
#property strict
#property version "1.00"
#property description "XAUUSD M5 EA with EMA, RSI, ATR and Telegram notifications"

#include <Trade/Trade.mqh>

CTrade trade;

//==================================================================
// PARAMETRES GENERAUX
//==================================================================

input group "=== TRADING ==="

input double Lots = 0.01;
input ulong MagicNumber = 26082601;
input int DeviationPoints = 30;

input bool EnableTrading = true;

input group "=== INDICATEURS ==="

input int EMA_Fast = 20;
input int EMA_Medium = 50;
input int EMA_Slow = 200;

input int RSI_Period = 14;
input int ATR_Period = 14;

input double ATR_SL_Multiplier = 1.5;
input double RiskReward = 2.0;

input double MinimumScore = 70.0;

input group "=== TELEGRAM ==="

input bool EnableTelegram = true;

input string TelegramToken = "TON_BOT_TOKEN";
input string TelegramChatID = "TON_CHAT_ID";

input int TelegramTimeout = 10000;

input bool SendStartupMessage = true;

//==================================================================
// HANDLES INDICATEURS
//==================================================================

int handleEMA20 = INVALID_HANDLE;
int handleEMA50 = INVALID_HANDLE;
int handleEMA200 = INVALID_HANDLE;
int handleRSI = INVALID_HANDLE;
int handleATR = INVALID_HANDLE;

//==================================================================
// VARIABLES
//==================================================================

datetime LastBarTime = 0;

//==================================================================
// INITIALISATION
//==================================================================

int OnInit()
{
   Print("======================================");
   Print("XAUUSD M5 TELEGRAM EA");
   Print("Initialisation...");
   Print("======================================");

   trade.SetExpertMagicNumber(MagicNumber);
   trade.SetDeviationInPoints(DeviationPoints);
   trade.SetTypeFillingBySymbol(_Symbol);

   // EMA 20
   handleEMA20 = iMA(
      _Symbol,
      PERIOD_M5,
      EMA_Fast,
      0,
      MODE_EMA,
      PRICE_CLOSE
   );

   // EMA 50
   handleEMA50 = iMA(
      _Symbol,
      PERIOD_M5,
      EMA_Medium,
      0,
      MODE_EMA,
      PRICE_CLOSE
   );

   // EMA 200
   handleEMA200 = iMA(
      _Symbol,
      PERIOD_M5,
      EMA_Slow,
      0,
      MODE_EMA,
      PRICE_CLOSE
   );

   // RSI
   handleRSI = iRSI(
      _Symbol,
      PERIOD_M5,
      RSI_Period,
      PRICE_CLOSE
   );

   // ATR
   handleATR = iATR(
      _Symbol,
      PERIOD_M5,
      ATR_Period
   );

   if(handleEMA20 == INVALID_HANDLE ||
      handleEMA50 == INVALID_HANDLE ||
      handleEMA200 == INVALID_HANDLE ||
      handleRSI == INVALID_HANDLE ||
      handleATR == INVALID_HANDLE)
   {
      Print("ERREUR : impossible de créer les indicateurs.");

      return INIT_FAILED;
   }

   if(EnableTelegram && SendStartupMessage)
   {
      string message =
         "🤖 XAUUSD M5 EA DEMARRE\n\n"
         "📊 Symbole : " + _Symbol + "\n"
         "⏱ Timeframe : M5\n"
         "💰 Lot : " + DoubleToString(Lots,2) + "\n"
         "📈 EMA : 20 / 50 / 200\n"
         "📊 RSI : " + IntegerToString(RSI_Period) + "\n"
         "📏 ATR : " + IntegerToString(ATR_Period) + "\n\n"
         "⚠️ Mode automatique : " +
         (EnableTrading ? "ACTIF" : "DESACTIVE");

      SendTelegram(message);
   }

   Print("EA initialise avec succes.");

   return INIT_SUCCEEDED;
}

//==================================================================
// DEINITIALISATION
//==================================================================

void OnDeinit(const int reason)
{
   if(handleEMA20 != INVALID_HANDLE)
      IndicatorRelease(handleEMA20);

   if(handleEMA50 != INVALID_HANDLE)
      IndicatorRelease(handleEMA50);

   if(handleEMA200 != INVALID_HANDLE)
      IndicatorRelease(handleEMA200);

   if(handleRSI != INVALID_HANDLE)
      IndicatorRelease(handleRSI);

   if(handleATR != INVALID_HANDLE)
      IndicatorRelease(handleATR);

   Print("EA arrete.");
}

//==================================================================
// TICK PRINCIPAL
//==================================================================

void OnTick()
{
   // On travaille uniquement sur une nouvelle bougie M5
   if(!IsNewBar())
      return;

   // Une seule position sur le symbole
   if(PositionSelect(_Symbol))
   {
      Print("Position deja ouverte sur ", _Symbol);
      return;
   }

   AnalyzeMarket();
}

//==================================================================
// DETECTION NOUVELLE BOUGIE
//==================================================================

bool IsNewBar()
{
   datetime currentBar =
      iTime(_Symbol, PERIOD_M5, 0);

   if(currentBar == 0)
      return false;

   if(currentBar != LastBarTime)
   {
      LastBarTime = currentBar;
      return true;
   }

   return false;
}

//==================================================================
// ANALYSE DU MARCHE
//==================================================================

void AnalyzeMarket()
{
   double ema20[3];
   double ema50[3];
   double ema200[3];
   double rsi[3];
   double atr[3];

   ArraySetAsSeries(ema20,true);
   ArraySetAsSeries(ema50,true);
   ArraySetAsSeries(ema200,true);
   ArraySetAsSeries(rsi,true);
   ArraySetAsSeries(atr,true);

   if(CopyBuffer(handleEMA20,0,0,3,ema20) < 3)
      return;

   if(CopyBuffer(handleEMA50,0,0,3,ema50) < 3)
      return;

   if(CopyBuffer(handleEMA200,0,0,3,ema200) < 3)
      return;

   if(CopyBuffer(handleRSI,0,0,3,rsi) < 3)
      return;

   if(CopyBuffer(handleATR,0,0,3,atr) < 3)
      return;

   // Bougie clôturée
   double openPrice = iOpen(_Symbol,PERIOD_M5,1);
   double closePrice = iClose(_Symbol,PERIOD_M5,1);
   double highPrice = iHigh(_Symbol,PERIOD_M5,1);
   double lowPrice = iLow(_Symbol,PERIOD_M5,1);

   if(openPrice == 0 || closePrice == 0)
      return;

   // Valeurs de la dernière bougie clôturée
   double e20 = ema20[1];
   double e50 = ema50[1];
   double e200 = ema200[1];

   double rsiValue = rsi[1];
   double atrValue = atr[1];

   if(atrValue <= 0)
      return;

   double buyScore = 0;
   double sellScore = 0;

   string buyReasons = "";
   string sellReasons = "";

   //==============================================================
   // BUY
   //==============================================================

   // Prix > EMA200
   if(closePrice > e200)
   {
      buyScore += 25;
      buyReasons += "Prix > EMA200\n";
   }

   // EMA20 > EMA50
   if(e20 > e50)
   {
      buyScore += 20;
      buyReasons += "EMA20 > EMA50\n";
   }

   // Prix > EMA20
   if(closePrice > e20)
   {
      buyScore += 15;
      buyReasons += "Prix > EMA20\n";
   }

   // RSI haussier
   if(rsiValue > 50 && rsiValue < 70)
   {
      buyScore += 20;
      buyReasons += "RSI haussier\n";
   }

   // Bougie haussiere
   if(closePrice > openPrice)
   {
      buyScore += 20;
      buyReasons += "Bougie haussiere\n";
   }

   //==============================================================
   // SELL
   //==============================================================

   // Prix < EMA200
   if(closePrice < e200)
   {
      sellScore += 25;
      sellReasons += "Prix < EMA200\n";
   }

   // EMA20 < EMA50
   if(e20 < e50)
   {
      sellScore += 20;
      sellReasons += "EMA20 < EMA50\n";
   }

   // Prix < EMA20
   if(closePrice < e20)
   {
      sellScore += 15;
      sellReasons += "Prix < EMA20\n";
   }

   // RSI baissier
   if(rsiValue > 30 && rsiValue < 50)
   {
      sellScore += 20;
      sellReasons += "RSI baissier\n";
   }

   // Bougie baissiere
   if(closePrice < openPrice)
   {
      sellScore += 20;
      sellReasons += "Bougie baissiere\n";
   }

   //==============================================================
   // DECISION
   //==============================================================

   Print(
      "Analyse M5 | BUY=",
      DoubleToString(buyScore,0),
      "% | SELL=",
      DoubleToString(sellScore,0),
      "%"
   );

   // BUY
   if(buyScore >= MinimumScore &&
      buyScore > sellScore)
   {
      OpenBuy(
         buyScore,
         rsiValue,
         atrValue,
         buyReasons
      );

      return;
   }

   // SELL
   if(sellScore >= MinimumScore &&
      sellScore > buyScore)
   {
      OpenSell(
         sellScore,
         rsiValue,
         atrValue,
         sellReasons
      );

      return;
   }

   Print("Aucun signal valide.");
}

//==================================================================
// OUVERTURE BUY
//==================================================================

void OpenBuy(
   double score,
   double rsiValue,
   double atrValue,
   string reasons
)
{
   double ask =
      SymbolInfoDouble(
         _Symbol,
         SYMBOL_ASK
      );

   if(ask <= 0)
      return;

   int digits =
      (int)SymbolInfoInteger(
         _Symbol,
         SYMBOL_DIGITS
      );

   double sl =
      ask -
      (atrValue * ATR_SL_Multiplier);

   double risk =
      ask - sl;

   double tp =
      ask +
      (risk * RiskReward);

   sl = NormalizeDouble(sl,digits);
   tp = NormalizeDouble(tp,digits);

   Print(
      "Tentative BUY | Entry=",
      DoubleToString(ask,digits),
      " | SL=",
      DoubleToString(sl,digits),
      " | TP=",
      DoubleToString(tp,digits)
   );

   if(!EnableTrading)
   {
      string testMessage =
         "🟢 SIGNAL BUY\n\n"
         "📊 " + _Symbol + " M5\n"
         "📍 Entrée : " +
         DoubleToString(ask,digits) + "\n"
         "🛑 SL : " +
         DoubleToString(sl,digits) + "\n"
         "🎯 TP : " +
         DoubleToString(tp,digits) + "\n"
         "🔥 Score : " +
         DoubleToString(score,0) + "%\n"
         "📈 RSI : " +
         DoubleToString(rsiValue,2) + "\n\n"
         "⚠️ Trading automatique désactivé.";

      SendTelegram(testMessage);

      return;
   }

   bool result =
      trade.Buy(
         Lots,
         _Symbol,
         0.0,
         sl,
         tp,
         "XAUUSD_M5_BUY"
      );

   if(result)
   {
      Print("BUY envoye.");

      Sleep(300);

      SendTradeNotification(
         "BUY",
         score,
         rsiValue,
         atrValue,
         reasons
      );
   }
   else
   {
      Print(
         "Erreur BUY : ",
         trade.ResultRetcode(),
         " - ",
         trade.ResultRetcodeDescription()
      );
   }
}

//==================================================================
// OUVERTURE SELL
//==================================================================

void OpenSell(
   double score,
   double rsiValue,
   double atrValue,
   string reasons
)
{
   double bid =
      SymbolInfoDouble(
         _Symbol,
         SYMBOL_BID
      );

   if(bid <= 0)
      return;

   int digits =
      (int)SymbolInfoInteger(
         _Symbol,
         SYMBOL_DIGITS
      );

   double sl =
      bid +
      (atrValue * ATR_SL_Multiplier);

   double risk =
      sl - bid;

   double tp =
      bid -
      (risk * RiskReward);

   sl = NormalizeDouble(sl,digits);
   tp = NormalizeDouble(tp,digits);

   Print(
      "Tentative SELL | Entry=",
      DoubleToString(bid,digits),
      " | SL=",
      DoubleToString(sl,digits),
      " | TP=",
      DoubleToString(tp,digits)
   );

   if(!EnableTrading)
   {
      string testMessage =
         "🔴 SIGNAL SELL\n\n"
         "📊 " + _Symbol + " M5\n"
         "📍 Entrée : " +
         DoubleToString(bid,digits) + "\n"
         "🛑 SL : " +
         DoubleToString(sl,digits) + "\n"
         "🎯 TP : " +
         DoubleToString(tp,digits) + "\n"
         "🔥 Score : " +
         DoubleToString(score,0) + "%\n"
         "📈 RSI : " +
         DoubleToString(rsiValue,2) + "\n\n"
         "⚠️ Trading automatique désactivé.";

      SendTelegram(testMessage);

      return;
   }

   bool result =
      trade.Sell(
         Lots,
         _Symbol,
         0.0,
         sl,
         tp,
         "XAUUSD_M5_SELL"
      );

   if(result)
   {
      Print("SELL envoye.");

      Sleep(300);

      SendTradeNotification(
         "SELL",
         score,
         rsiValue,
         atrValue,
         reasons
      );
   }
   else
   {
      Print(
         "Erreur SELL : ",
         trade.ResultRetcode(),
         " - ",
         trade.ResultRetcodeDescription()
      );
   }
}

//==================================================================
// NOTIFICATION TELEGRAM DU TRADE
//==================================================================

void SendTradeNotification(
   string direction,
   double score,
   double rsiValue,
   double atrValue,
   string reasons
)
{
   if(!EnableTelegram)
      return;

   if(!PositionSelect(_Symbol))
   {
      Print(
         "Position non trouvee apres ouverture."
      );

      return;
   }

   int digits =
      (int)SymbolInfoInteger(
         _Symbol,
         SYMBOL_DIGITS
      );

   double entry =
      PositionGetDouble(
         POSITION_PRICE_OPEN
      );

   double sl =
      PositionGetDouble(
         POSITION_SL
      );

   double tp =
      PositionGetDouble(
         POSITION_TP
      );

   double volume =
      PositionGetDouble(
         POSITION_VOLUME
      );

   ulong ticket =
      (ulong)PositionGetInteger(
         POSITION_TICKET
      );

   string emoji =
      direction == "BUY" ? "🟢" : "🔴";

   string message =
      emoji + " XAUUSD M5 — " +
      direction + "\n\n"

      "📊 Symbole : " + _Symbol + "\n"

      "💰 Lot : " +
      DoubleToString(volume,2) + "\n"

      "🎫 Ticket : " +
      IntegerToString((long)ticket) + "\n\n"

      "📍 Entrée : " +
      DoubleToString(entry,digits) + "\n"

      "🛑 SL : " +
      DoubleToString(sl,digits) + "\n"

      "🎯 TP : " +
      DoubleToString(tp,digits) + "\n\n"

      "🔥 Score : " +
      DoubleToString(score,0) + "%\n"

      "📈 RSI : " +
      DoubleToString(rsiValue,2) + "\n"

      "📏 ATR : " +
      DoubleToString(atrValue,digits) + "\n\n"

      "🔎 Conditions :\n" +
      reasons + "\n"

      "⚠️ Signal algorithmique — "
      "aucune garantie de gain.";

   SendTelegram(message);
}

//==================================================================
// TELEGRAM
//==================================================================

bool SendTelegram(string message)
{
   if(!EnableTelegram)
      return false;

   if(TelegramToken == "" ||
      TelegramChatID == "" ||
      TelegramToken == "TON_BOT_TOKEN" ||
      TelegramChatID == "TON_CHAT_ID")
   {
      Print(
         "Telegram non configure."
      );

      return false;
   }

   string url =
      "https://api.telegram.org/bot" +
      TelegramToken +
      "/sendMessage";

   // Encoder le message pour application/x-www-form-urlencoded
   string encodedMessage =
      UrlEncode(message);

   string body =
      "chat_id=" +
      UrlEncode(TelegramChatID) +
      "&text=" +
      encodedMessage;

   char post[];
   char result[];

   string resultHeaders;

   int length =
      StringToCharArray(
         body,
         post,
         0,
         -1,
         CP_UTF8
      );

   if(length > 0)
      ArrayResize(post,length - 1);

   string headers =
      "Content-Type: application/x-www-form-urlencoded\r\n";

   ResetLastError();

   int response =
      WebRequest(
         "POST",
         url,
         headers,
         TelegramTimeout,
         post,
         result,
         resultHeaders
      );

   if(response == 200)
   {
      Print(
         "Telegram : message envoye."
      );

      return true;
   }

   Print(
      "Telegram WebRequest erreur = ",
      response,
      " | LastError = ",
      GetLastError()
   );

   Print(
      "Reponse Telegram : ",
      CharArrayToString(result)
   );

   return false;
}

//==================================================================
// URL ENCODE
//==================================================================

string UrlEncode(string text)
{
   uchar data[];

   StringToCharArray(
      text,
      data,
      0,
      WHOLE_ARRAY,
      CP_UTF8
   );

   string result = "";

   for(int i=0; i<ArraySize(data); i++)
   {
      uchar c = data[i];

      if(c == 0)
         break;

      bool safe =
         (c >= 'a' && c <= 'z') ||
         (c >= 'A' && c <= 'Z') ||
         (c >= '0' && c <= '9') ||
         c == '-' ||
         c == '_' ||
         c == '.' ||
         c == '~';

      if(safe)
      {
         result += CharToString(c);
      }
      else if(c == ' ')
      {
         result += "+";
      }
      else
      {
         result += "%";
         result += StringFormat(
            "%02X",
            c
         );
      }
   }

   return result;
}

//==================================================================
// NOTIFICATIONS DES FERMETURES
//==================================================================

void OnTradeTransaction(
   const MqlTradeTransaction &trans,
   const MqlTradeRequest &request,
   const MqlTradeResult &result
)
{
   if(!EnableTelegram)
      return;

   // Nous nous intéressons aux nouveaux deals
   if(trans.type != TRADE_TRANSACTION_DEAL_ADD)
      return;

   if(trans.deal == 0)
      return;

   // Sélectionner le deal dans l'historique
   if(!HistoryDealSelect(trans.deal))
      return;

   string symbol =
      HistoryDealGetString(
         trans.deal,
         DEAL_SYMBOL
      );

   if(symbol != _Symbol)
      return;

   long entryType =
      HistoryDealGetInteger(
         trans.deal,
         DEAL_ENTRY
      );

   // Notification fermeture
   if(entryType == DEAL_ENTRY_OUT ||
      entryType == DEAL_ENTRY_OUT_BY)
   {
      double volume =
         HistoryDealGetDouble(
            trans.deal,
            DEAL_VOLUME
         );

      double price =
         HistoryDealGetDouble(
            trans.deal,
            DEAL_PRICE
         );

      double profit =
         HistoryDealGetDouble(
            trans.deal,
            DEAL_PROFIT
         );

      ulong dealTicket =
         trans.deal;

      string emoji =
         profit >= 0 ? "✅" : "❌";

      string resultText =
         profit >= 0 ? "GAIN" : "PERTE";

      int digits =
         (int)SymbolInfoInteger(
            _Symbol,
            SYMBOL_DIGITS
         );

      string message =
         emoji + " TRADE FERME — " +
         resultText + "\n\n"

         "📊 Symbole : " +
         symbol + "\n"

         "💰 Volume : " +
         DoubleToString(volume,2) + "\n"

         "📍 Prix sortie : " +
         DoubleToString(price,digits) + "\n"

         "💵 Résultat : " +
         DoubleToString(profit,2) + "\n"

         "🎫 Deal : " +
         IntegerToString((long)dealTicket);

      SendTelegram(message);
   }
}
//+------------------------------------------------------------------+

프로젝트 정보

예산
30+ USD
기한
에서 10  25 일

고객

넣은 주문1
중재 수0