//+------------------------------------------------------------------+
//| RSI Scalping EA with Flexible Exit Strategy & Custom Timeframe |
//| By ChatGPT - Improved Version |
//+------------------------------------------------------------------+
#property strict
#include <Trade\Trade.mqh>
CTrade trade;
// --- Input Parameters ---
input ENUM_TIMEFRAMES RSI_Timeframe = PERIOD_M5; // 🔥 Pilih timeframe RSI
input int RSI_Period = 14;
input int RSI_Overbought = 70;
input int RSI_Overbought_2 = 80;
input int RSI_Oversold = 30;
input int RSI_Oversold_2 = 20;
input int RSI_ExitLevel = 50;
input bool Close_On_Touch = true; // 🔥 Close saat RSI menyentuh netral tanpa
tunggu candle close
input double Fixed_Lot = 0.1;
input double LotMultiplier = 2.0;
input int Max_Positions = 3;
// --- Global Variables ---
int RSI_Handle;
double RSI_Value[];
datetime lastCandleTime = 0;
//+------------------------------------------------------------------+
//| OnInit - Initialize RSI Indicator |
//+------------------------------------------------------------------+
int OnInit() {
RSI_Handle = iRSI(_Symbol, RSI_Timeframe, RSI_Period, PRICE_CLOSE); // 🔥 Custom
TF
if (RSI_Handle == INVALID_HANDLE) {
Print("❌ ERROR: RSI Handle tidak bisa dibuat!");
return INIT_FAILED;
}
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| OnTick - Main Trading Logic (Entry + Layering) |
//+------------------------------------------------------------------+
void OnTick() {
datetime currentCandleTime = iTime(_Symbol, RSI_Timeframe, 0);
// 🔥 Kalau mode candle close, tunggu sampai candle baru
if (!Close_On_Touch && currentCandleTime == lastCandleTime) return;
lastCandleTime = currentCandleTime;
if (CopyBuffer(RSI_Handle, 0, (Close_On_Touch ? 0 : 1), 1, RSI_Value) <= 0) {
Print("❌ ERROR: Gagal mengambil data RSI!");
return;
}
double rsi = RSI_Value[0];
Print("📊 RSI: ", rsi, " | TF: ", RSI_Timeframe, " | Mode Close: ",
Close_On_Touch ? "On Touch" : "On Candle Close");
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
int openPositions = GetOpenPositions();
// **BUY ENTRY: RSI Oversold**
if (rsi < RSI_Oversold && openPositions < Max_Positions) {
double lot = Fixed_Lot;
trade.Buy(lot, _Symbol, ask, 0, 0, "RSI Buy");
Print("✅ BUY order pertama dibuka! RSI: ", rsi, ", Lot: ", lot);
}
else if (rsi < RSI_Oversold_2 && openPositions < Max_Positions) {
double lot = Fixed_Lot * LotMultiplier;
trade.Buy(lot, _Symbol, ask, 0, 0, "RSI Buy Layer 2");
Print("✅ BUY order kedua dibuka! RSI: ", rsi, ", Lot: ", lot);
}
// **SELL ENTRY: RSI Overbought**
if (rsi > RSI_Overbought && openPositions < Max_Positions) {
double lot = Fixed_Lot;
trade.Sell(lot, _Symbol, bid, 0, 0, "RSI Sell");
Print("✅ SELL order pertama dibuka! RSI: ", rsi, ", Lot: ", lot);
}
else if (rsi > RSI_Overbought_2 && openPositions < Max_Positions) {
double lot = Fixed_Lot * LotMultiplier;
trade.Sell(lot, _Symbol, bid, 0, 0, "RSI Sell Layer 2");
Print("✅ SELL order kedua dibuka! RSI: ", rsi, ", Lot: ", lot);
}
// 🔥 **Close posisi jika RSI mencapai level netral**
ClosePositions(rsi);
}
//+------------------------------------------------------------------+
//| Close positions based on RSI Exit Level |
//+------------------------------------------------------------------+
void ClosePositions(double rsi) {
for (int i = PositionsTotal() - 1; i >= 0; i--) {
ulong ticket = PositionGetTicket(i);
if (ticket > 0 && PositionSelectByTicket(ticket)) {
ENUM_POSITION_TYPE type =
(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
string posType = (type == POSITION_TYPE_BUY) ? "BUY" : "SELL";
// **BUY CLOSE LOGIC**
if (type == POSITION_TYPE_BUY && rsi >= RSI_ExitLevel) {
Print("✅ Closing BUY Position: Ticket=", ticket);
if (trade.PositionClose(ticket)) {
Print("✅ BUY Closed! RSI: ", rsi);
} else {
Print("❌ ERROR Closing BUY! Error: ", GetLastError());
}
}
// **SELL CLOSE LOGIC**
if (type == POSITION_TYPE_SELL && rsi <= RSI_ExitLevel) {
Print("✅ Closing SELL Position: Ticket=", ticket);
if (trade.PositionClose(ticket)) {
Print("✅ SELL Closed! RSI: ", rsi);
} else {
Print("❌ ERROR Closing SELL! Error: ", GetLastError());
}
}
}
}
}
//+------------------------------------------------------------------+
//| Fungsi untuk cek jumlah posisi terbuka |
//+------------------------------------------------------------------+
int GetOpenPositions() {
int count = 0;
for (int i = 0; i < PositionsTotal(); i++) {
if (PositionGetSymbol(i) == _Symbol) count++;
}
return count;
}
//+------------------------------------------------------------------+
//| OnDeinit - Cleanup RSI Handle |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
IndicatorRelease(RSI_Handle);
}