💻 Cluster MQL5

Expert Advisor IA MT5 Deriv — Tutoriel MQL5

Par Dan Machado · 10 min de lecture · Niveau intermédiaire

Si Deriv Bot Builder est trop limité et Python trop complexe, MQL5 sur MT5 est le compromis idéal. Cet Expert Advisor RSI complet vous donne une base solide pour automation sur MetaTrader 5 Deriv. Code commenté, compile sans erreur, déployable sur VPS Afrique.

🎯 Ce Que Vous Construirez

Un EA MQL5 qui :
✓ Calcule RSI(14) sur V75 ou tout symbole forex
✓ Détecte croisements oversold/overbought
✓ Place ordres BUY/SELL avec SL et TP
✓ Position sizing 2% du balance automatique
✓ Limite trades par jour (8 max)
✓ Cooldown 60min après 3 pertes consécutives
✓ Logging vers fichier CSV

Prérequis

  • Compte Deriv avec MT5 activé (créer compte)
  • MetaTrader 5 téléchargé via Deriv
  • Connexion compte MT5 démo configurée
  • Familiarité basique avec MetaEditor

Code Complet EA — RSI V75 Mean Reversion

▸ MQL5 · RSI_Mean_Reversion_EA.mq5
//+------------------------------------------------------------------+
//| RSI_Mean_Reversion_EA.mq5 - IA Trader Pro                       |
//| Stratégie: V75 RSI mean reversion avec risk management          |
//+------------------------------------------------------------------+
#property copyright "Dan Machado / IA Trader Pro"
#property version   "1.00"
#property strict

#include <Trade\Trade.mqh>
CTrade trade;

// === INPUTS ===
input int    RSI_Period      = 14;     // Période RSI
input int    Oversold        = 30;     // Seuil oversold
input int    Overbought      = 70;     // Seuil overbought
input double RiskPercent     = 2.0;    // % balance par trade
input double DailyLossLimit  = 5.0;    // Limite perte journalière %
input int    MaxTradesPerDay = 8;      // Max trades / jour
input int    StopLossPoints  = 1000;   // SL en points
input int    TakeProfitPoints= 2000;   // TP en points (ratio 1:2)
input int    MagicNumber     = 75001;  // ID unique de cet EA

// === GLOBAL VARS ===
int rsiHandle;
double rsi[];
double startDayBalance;
int tradesToday = 0;
int consecLosses = 0;
datetime lastTradeDate = 0;
datetime cooldownUntil = 0;

//+------------------------------------------------------------------+
//| Initialization                                                    |
//+------------------------------------------------------------------+
int OnInit() {
    rsiHandle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, PRICE_CLOSE);
    if(rsiHandle == INVALID_HANDLE) {
        Print("Erreur création RSI handle");
        return INIT_FAILED;
    }
    ArraySetAsSeries(rsi, true);
    startDayBalance = AccountInfoDouble(ACCOUNT_BALANCE);
    Print("EA RSI Mean Reversion démarré sur ", _Symbol);
    return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Deinitialization                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
    IndicatorRelease(rsiHandle);
    Print("EA arrêté");
}

//+------------------------------------------------------------------+
//| Main tick handler                                                 |
//+------------------------------------------------------------------+
void OnTick() {
    // Reset daily counters at midnight
    MqlDateTime dt;
    TimeToStruct(TimeCurrent(), dt);
    static int lastDay = -1;
    if(dt.day != lastDay) {
        tradesToday = 0;
        startDayBalance = AccountInfoDouble(ACCOUNT_BALANCE);
        lastDay = dt.day;
    }
    
    // Skip if cooldown active
    if(cooldownUntil > 0 && TimeCurrent() < cooldownUntil) return;
    if(cooldownUntil > 0 && TimeCurrent() >= cooldownUntil) {
        cooldownUntil = 0;
        consecLosses = 0;
    }
    
    // Check daily loss limit
    double currentBalance = AccountInfoDouble(ACCOUNT_BALANCE);
    double lossPct = ((startDayBalance - currentBalance) / startDayBalance) * 100;
    if(lossPct >= DailyLossLimit) {
        return; // Stop trading for today
    }
    
    // Check max trades
    if(tradesToday >= MaxTradesPerDay) return;
    
    // Skip if already in position
    if(PositionsTotalForMagic(MagicNumber) > 0) return;
    
    // Update RSI
    if(CopyBuffer(rsiHandle, 0, 0, 3, rsi) < 3) return;
    
    // Detect signals (crossover logic)
    double rsi_current = rsi[0];
    double rsi_prev = rsi[1];
    
    bool buySignal = (rsi_prev < Oversold && rsi_current >= Oversold);
    bool sellSignal = (rsi_prev > Overbought && rsi_current <= Overbought);
    
    if(buySignal) PlaceTrade(ORDER_TYPE_BUY);
    else if(sellSignal) PlaceTrade(ORDER_TYPE_SELL);
}

//+------------------------------------------------------------------+
//| Calculate lot size (2% risk)                                      |
//+------------------------------------------------------------------+
double CalculateLotSize() {
    double balance = AccountInfoDouble(ACCOUNT_BALANCE);
    double risk_amount = balance * (RiskPercent / 100);
    double point_value = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
    double lot = risk_amount / (StopLossPoints * point_value);
    
    // Round to broker requirements
    double min_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
    double lot_step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
    lot = MathFloor(lot / lot_step) * lot_step;
    lot = MathMax(lot, min_lot);
    
    return lot;
}

//+------------------------------------------------------------------+
//| Place trade with SL/TP                                            |
//+------------------------------------------------------------------+
void PlaceTrade(ENUM_ORDER_TYPE type) {
    double price = (type == ORDER_TYPE_BUY) ?
                   SymbolInfoDouble(_Symbol, SYMBOL_ASK) :
                   SymbolInfoDouble(_Symbol, SYMBOL_BID);
    
    double sl = (type == ORDER_TYPE_BUY) ?
                price - StopLossPoints * _Point :
                price + StopLossPoints * _Point;
    
    double tp = (type == ORDER_TYPE_BUY) ?
                price + TakeProfitPoints * _Point :
                price - TakeProfitPoints * _Point;
    
    double lot = CalculateLotSize();
    
    trade.SetExpertMagicNumber(MagicNumber);
    
    bool success = false;
    if(type == ORDER_TYPE_BUY) {
        success = trade.Buy(lot, _Symbol, price, sl, tp, "RSI Bull");
    } else {
        success = trade.Sell(lot, _Symbol, price, sl, tp, "RSI Bear");
    }
    
    if(success) {
        tradesToday++;
        Print("Trade placé: ", EnumToString(type), " ", lot, " @ ", price);
        LogTrade(type, price, lot);
    }
}

//+------------------------------------------------------------------+
//| Count open positions for this EA                                  |
//+------------------------------------------------------------------+
int PositionsTotalForMagic(int magic) {
    int count = 0;
    for(int i = 0; i < PositionsTotal(); i++) {
        ulong ticket = PositionGetTicket(i);
        if(PositionSelectByTicket(ticket)) {
            if(PositionGetInteger(POSITION_MAGIC) == magic &&
               PositionGetString(POSITION_SYMBOL) == _Symbol) {
                count++;
            }
        }
    }
    return count;
}

//+------------------------------------------------------------------+
//| Log trade to CSV                                                  |
//+------------------------------------------------------------------+
void LogTrade(ENUM_ORDER_TYPE type, double price, double lot) {
    int handle = FileOpen("RSI_EA_Trades.csv",
                         FILE_WRITE|FILE_READ|FILE_CSV|FILE_ANSI, ',');
    if(handle == INVALID_HANDLE) return;
    
    FileSeek(handle, 0, SEEK_END);
    FileWrite(handle,
              TimeToString(TimeCurrent()),
              _Symbol,
              (type == ORDER_TYPE_BUY ? "BUY" : "SELL"),
              DoubleToString(price, _Digits),
              DoubleToString(lot, 2),
              DoubleToString(AccountInfoDouble(ACCOUNT_BALANCE), 2)
    );
    FileClose(handle);
}

//+------------------------------------------------------------------+
//| Trade event handler — track consecutive losses                    |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result) {
    if(trans.type == TRADE_TRANSACTION_DEAL_ADD) {
        HistoryDealSelect(trans.deal);
        if(HistoryDealGetInteger(trans.deal, DEAL_MAGIC) == MagicNumber) {
            double profit = HistoryDealGetDouble(trans.deal, DEAL_PROFIT);
            if(profit < 0) {
                consecLosses++;
                if(consecLosses >= 3) {
                    cooldownUntil = TimeCurrent() + 3600; // 60 min cooldown
                    Print("3 pertes consécutives. Cooldown 60min.");
                }
            } else if(profit > 0) {
                consecLosses = 0;
            }
        }
    }
}
//+------------------------------------------------------------------+

Comment Compiler et Lancer

  1. Ouvrez MetaEditor (F4 depuis MT5)
  2. File → New → Expert Advisor (template)
  3. Nom : RSI_Mean_Reversion_EA
  4. Remplacez tout le code par celui ci-dessus
  5. F7 pour compiler — doit dire « 0 errors, 0 warnings »
  6. Retournez dans MT5
  7. Navigateur → Expert Advisors → glissez RSI_Mean_Reversion_EA sur chart V75
  8. Activez « Algo Trading » (bouton vert en haut)
  9. L’EA tourne ! Vérifiez l’onglet « Experts » pour logs

⚠️ Important : Symboles V75 sur MT5 Deriv

Sur MetaTrader 5 Deriv, V75 apparaît sous différents noms selon la version :
• « Volatility 75 Index » (nom complet)
• « R_75 » (code court)
• « Volatility 75 (1s) Index » (version 1 seconde)

Utilisez la version « 1s » pour bots haute fréquence, version standard pour stratégies 5min+.

Backtester Avant Démo Live

  1. Dans MT5 : View → Strategy Tester (Ctrl+R)
  2. Expert : RSI_Mean_Reversion_EA
  3. Symbol : Volatility 75 Index
  4. Period : M5 ou H1
  5. Date : derniers 6 mois minimum
  6. Modeling : Every tick (plus précis)
  7. Cliquez Start
  8. Analysez : Profit Factor >1.5, Drawdown <25%, >30 trades

Déploiement VPS Africa Pour 24/7

🌍 VPS Recommandés (depuis Africa)

1. Vultr – Frankfurt : 6$/mo (~3,600 FCFA), latence ~150ms
2. Vultr – Lagos : best pour West Africa
3. Hetzner Cloud – Allemagne : 4€/mo (~2,600 FCFA)
4. OVH France : 5€/mo, support français

Tous acceptent paiement par carte (FCFA auto-converti). MT5 tourne nativement sur Windows VPS.

Setup VPS Quick

  1. Commandez VPS Windows Server 2019/2022
  2. RDP (Remote Desktop) depuis votre laptop
  3. Téléchargez MT5 Deriv sur VPS
  4. Login compte démo/réel
  5. Copiez votre EA (Files → Open Data Folder → MQL5/Experts)
  6. Lancez EA
  7. Déconnectez-vous, EA continue tourner 24/7

Optimisations Suggérées

  • Filtre EMA : ne trader que dans direction EMA(50)
  • Multi-timeframe : confirmer signal H1 sur signal M5
  • Volume filter : skip si volume anormalement bas
  • News filter : pause pendant news majeures (forex uniquement)
  • Trailing stop : protéger profits sur trades gagnants
  • Multiple symbols : V75 + V100 + R_50 en parallèle (un EA par symbole)

Erreurs Communes

🐛 Debug Tips

• « AutoTrading disabled » → cliquez bouton vert Algo Trading en haut MT5
• « Symbol not allowed » → ajoutez V75 au Market Watch (Ctrl+M, drag)
• « Invalid stops » → ajustez SL/TP : Deriv exige minimum distance
• « Not enough money » → trop de risque pour balance, baissez RiskPercent
• EA ne place pas d’ordres → vérifiez logs onglet Experts

🚀 Téléchargez MT5 Deriv et testez cet EA :

Ouvrir Compte Deriv + MT5 →

Lectures Connexes

DM

Dan Machado

Fondateur IA Trader Pro · Développeur MQL5 5+ ans

⚠️ Avertissement : Code MQL5 éducatif. Toujours backtester et démo-tester 30 jours minimum avant déploiement réel. Trading dérivés = risque élevé. Deriv régulé MFSA/Vanuatu. Contient des liens d’affiliation. Avertissement complet.