Saturday, August 23, 2025

//+------------------------------------------------------------------+
//| Expert Advisor: EA_RR1to2_FixedSL.mq5 |
//| Risk 1%, Fixed SL, RR 1:2, Max 2 posisi |
//+------------------------------------------------------------------+
#property strict
#include <Trade/Trade.mqh>
CTrade trade;

//---------------- Input Parameter ----------------
input double RiskPercent = 1.0; // Risiko per trade (% balance)
input int FastEMA = 9; // EMA cepat
input int SlowEMA = 21; // EMA lambat
input int StopLossPips = 30; // Fixed SL (pips)
input double RR = 2.0; // Risk Reward Ratio (1:2)

//---------------- Global Variabel ----------------
int handleFastEMA, handleSlowEMA;

//---------------- Hitung Lot Berdasarkan Risk ----------------
double CalculateLot(double stopLossPips)
{
   double balance = AccountInfoDouble(ACCOUNT_BALANCE);
   double riskMoney = balance * RiskPercent / 100.0;

   double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);

   // nilai 1 pip per lot
   double pipValuePerLot = tickValue / tickSize * _Point;

   // Estimasi kerugian per lot
   double lossPerLot = stopLossPips * pipValuePerLot;

   if(lossPerLot <= 0) return 0.01;

   double lot = riskMoney / lossPerLot;

   // Sesuaikan dengan batas broker
   double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   double stepLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);

   lot = MathMax(minLot, MathMin(maxLot, lot));
   lot = MathFloor(lot/stepLot) * stepLot;

   return lot;
}

//---------------- Hitung Posisi Terbuka ----------------
int OpenPositionsCount()
{
   int total = 0;
   for(int i=0; i<PositionsTotal(); i++)
   {
      if(PositionGetSymbol(i) && PositionGetString(POSITION_SYMBOL) == _Symbol)
         total++;
   }
   return total;
}

//---------------- OnInit ----------------
int OnInit()
{
   handleFastEMA = iMA(_Symbol, PERIOD_CURRENT, FastEMA, 0, MODE_EMA, PRICE_CLOSE);
   handleSlowEMA = iMA(_Symbol, PERIOD_CURRENT, SlowEMA, 0, MODE_EMA, PRICE_CLOSE);
   return(INIT_SUCCEEDED);
}

//---------------- OnTick ----------------
void OnTick()
{
   // Batasi max 2 posisi
   if(OpenPositionsCount() >= 2) return;

   // Buffer EMA
   double emaFast[2], emaSlow[2];
   if(CopyBuffer(handleFastEMA, 0, 0, 2, emaFast) <= 0) return;
   if(CopyBuffer(handleSlowEMA, 0, 0, 2, emaSlow) <= 0) return;

   double emaFastCurr = emaFast[0];
   double emaFastPrev = emaFast[1];
   double emaSlowCurr = emaSlow[0];
   double emaSlowPrev = emaSlow[1];

   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double lot = CalculateLot(StopLossPips);

   // Kondisi BUY (EMA cepat cross ke atas EMA lambat)
   if(emaFastPrev < emaSlowPrev && emaFastCurr > emaSlowCurr)
   {
      double sl = bid - StopLossPips * _Point;
      double tp = bid + StopLossPips * RR * _Point;
      trade.Buy(lot, _Symbol, ask, sl, tp);
   }

   // Kondisi SELL (EMA cepat cross ke bawah EMA lambat)
   if(emaFastPrev > emaSlowPrev && emaFastCurr < emaSlowCurr)
   {
      double sl = ask + StopLossPips * _Point;
      double tp = ask - StopLossPips * RR * _Point;
      trade.Sell(lot, _Symbol, bid, sl, tp);
   }
}

0 comments:

Post a Comment

Related Posts Plugin for WordPress, Blogger...