Selamat Pagi / Siang / Malam teman2, Saya sedang belajar dan mengembangkan EA MT4 berbasis trend following menggunakan kombinasi Parabolic SAR, Moving Average (MA), dan ADX. EA ini sudah saya lengkapi dengan validasi broker-safe dan source code MQL4 saya sertakan agar bisa direview.
Dan Mohon bantuannya untuk di backtest pada M15 dan M30, saya coba backtest terkendala,makasih
Ringkasan logika EA:
EA ini masih dalam tahap pembelajaran dan pengembangan, jadi segala saran, kritik, atau referensi tambahan akan sangat saya hargai.
Silakan dicek source code-nya dan mohon koreksinya jika ada bagian yang kurang tepat atau bisa dioptimalkan.
Source Code :
Dan Mohon bantuannya untuk di backtest pada M15 dan M30, saya coba backtest terkendala,makasih
Ringkasan logika EA:
- Entry hanya ketika ADX > 25 (indikasi trend kuat)
- BUY: harga di atas MA & Parabolic SAR berada di bawah harga
- SELL: harga di bawah MA & Parabolic SAR berada di atas harga
- Entry dilakukan saat candle close
- Maksimal 1 posisi per pair
Code:
OnTick
├─ Candle baru?
│ └─ Tidak → Stop
├─ Ada posisi?
│ └─ Ya → Stop
├─ Hitung indikator
├─ ADX > 25?
│ └─ Tidak → Stop
├─ Harga > MA & SAR bawah?
│ └─ BUY
└─ Harga < MA & SAR atas?
└─ SELL
EA ini masih dalam tahap pembelajaran dan pengembangan, jadi segala saran, kritik, atau referensi tambahan akan sangat saya hargai.
Silakan dicek source code-nya dan mohon koreksinya jika ada bagian yang kurang tepat atau bisa dioptimalkan.
Source Code :
Code:
//+------------------------------------------------------------------+
//| EA SAR + MA + ADX (Broker Safe Version) |
//+------------------------------------------------------------------+
#property strict
//================ INPUT ==================
input double LotSize = 0.01;
input int MagicNumber = 777;
input int MAPeriod = 50;
input int MAMethod = MODE_EMA;
input int MAPrice = PRICE_CLOSE;
input int ADXPeriod = 14;
input double ADXLevel = 25.0;
input double SARStep = 0.02;
input double SARMax = 0.2;
input int StopLoss = 100; // points
input int TakeProfit = 10; // points
//================ GLOBAL =================
datetime lastCandleTime = 0;
//+------------------------------------------------------------------+
//| Expert initialization |
//+------------------------------------------------------------------+
int OnInit()
{
lastCandleTime = 0;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick |
//+------------------------------------------------------------------+
void OnTick()
{
// Entry hanya pada candle baru
if(Time[0] == lastCandleTime) return;
lastCandleTime = Time[0];
// Hanya 1 posisi per symbol
if(CountOpenOrders() > 0) return;
//================ INDIKATOR =================
double ma = iMA(NULL, 0, MAPeriod, 0, MAMethod, MAPrice, 1);
double sar = iSAR(NULL, 0, SARStep, SARMax, 1);
double adx = iADX(NULL, 0, ADXPeriod, PRICE_CLOSE, MODE_MAIN, 1);
double closePrice = Close[1];
// Filter trend kuat
if(adx <= ADXLevel) return;
//================ LOGIKA ENTRY =================
if(closePrice > ma && sar < closePrice)
OpenBuy();
if(closePrice < ma && sar > closePrice)
OpenSell();
}
//+------------------------------------------------------------------+
//| OPEN BUY |
//+------------------------------------------------------------------+
void OpenBuy()
{
RefreshRates();
double lot = FixLot(LotSize);
double price = NormalizeDouble(Ask, Digits);
double sl = 0, tp = 0;
if(StopLoss > 0)
sl = NormalizeDouble(price - StopLoss * Point, Digits);
if(TakeProfit > 0)
tp = NormalizeDouble(price + TakeProfit * Point, Digits);
if(!CheckStopLevel(price, sl, tp)) return;
int ticket = OrderSend(
Symbol(), OP_BUY, lot, price, 3,
sl, tp, "BUY SAR MA ADX", MagicNumber, 0, clrBlue
);
if(ticket < 0)
Print("BUY Error: ", GetLastError());
else
Print("BUY Opened. Ticket: ", ticket);
}
//+------------------------------------------------------------------+
//| OPEN SELL |
//+------------------------------------------------------------------+
void OpenSell()
{
RefreshRates();
double lot = FixLot(LotSize);
double price = NormalizeDouble(Bid, Digits);
double sl = 0, tp = 0;
if(StopLoss > 0)
sl = NormalizeDouble(price + StopLoss * Point, Digits);
if(TakeProfit > 0)
tp = NormalizeDouble(price - TakeProfit * Point, Digits);
if(!CheckStopLevel(price, sl, tp)) return;
int ticket = OrderSend(
Symbol(), OP_SELL, lot, price, 3,
sl, tp, "SELL SAR MA ADX", MagicNumber, 0, clrRed
);
if(ticket < 0)
Print("SELL Error: ", GetLastError());
else
Print("SELL Opened. Ticket: ", ticket);
}
//+------------------------------------------------------------------+
//| LOT VALIDATION |
//+------------------------------------------------------------------+
double FixLot(double lot)
{
double minLot = MarketInfo(Symbol(), MODE_MINLOT);
double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
double stepLot = MarketInfo(Symbol(), MODE_LOTSTEP);
lot = MathMax(minLot, MathMin(lot, maxLot));
lot = NormalizeDouble(lot / stepLot, 0) * stepLot;
return NormalizeDouble(lot, 2);
}
//+------------------------------------------------------------------+
//| STOPLEVEL CHECK |
//+------------------------------------------------------------------+
bool CheckStopLevel(double price, double sl, double tp)
{
double stopLevel = MarketInfo(Symbol(), MODE_STOPLEVEL);
double minDist = stopLevel * Point;
if(sl != 0 && MathAbs(price - sl) < minDist)
{
Print("SL too close");
return false;
}
if(tp != 0 && MathAbs(price - tp) < minDist)
{
Print("TP too close");
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| COUNT OPEN ORDERS |
//+------------------------------------------------------------------+
int CountOpenOrders()
{
int total = 0;
for(int i = 0; i < OrdersTotal(); i++)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderMagicNumber() == MagicNumber &&
OrderSymbol() == Symbol())
{
total++;
}
}
}
return total;
}
//+------------------------------------------------------------------+
Attachments
Last edited:
