B2BIndicators/B2BIndicator.mq5

208 lines
11 KiB
MQL5
Raw Permalink Normal View History

2026-06-12 00:15:53 +00:00
//+------------------------------------------------------------------+
//| B2BIndicator.mq5 |
//| Copyright 2026, Delawa xyz |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026"
#property indicator_chart_window
#property indicator_plots 0
//--- INPUT PARAMETERS
input group "=== Risk Settings ==="
input double InpATR_Multiplier_SL = 2.0;
input double InpATR_Multiplier_TP = 3.0;
input group "=== Indicator Settings ==="
input int InpBB1_Period = 200;
input double InpBB1_Deviation = 1.3;
input int InpBB2_Period = 20;
input double InpBB2_Deviation = 2.3;
input int InpEMA8_Period = 8;
input int InpSMA21_Period = 21;
input int InpEMA50_Period = 50;
input double InpPSAR_Step = 0.02;
input double InpPSAR_Maximum = 0.2;
input int InpRSI_Period = 14; // Periode standar RSI
input int InpADX_Period = 14; // Periode standar ADX
//--- GLOBAL HANDLES
int handle_bb1, handle_bb2, handle_ema8, handle_sma21, handle_ema50, handle_psar, handle_atr, handle_rsi, handle_adx;
datetime time_last_bar;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
time_last_bar = 0;
// Inisialisasi Indikator Bawaan
handle_bb1 = iBands(_Symbol, _Period, InpBB1_Period, 0, InpBB1_Deviation, PRICE_CLOSE);
handle_bb2 = iBands(_Symbol, _Period, InpBB2_Period, 0, InpBB2_Deviation, PRICE_CLOSE);
handle_ema8 = iMA(_Symbol, _Period, InpEMA8_Period, 0, MODE_EMA, PRICE_CLOSE);
handle_sma21 = iMA(_Symbol, _Period, InpSMA21_Period, 0, MODE_SMA, PRICE_CLOSE);
handle_ema50 = iMA(_Symbol, _Period, InpEMA50_Period, 0, MODE_EMA, PRICE_CLOSE);
handle_psar = iSAR(_Symbol, _Period, InpPSAR_Step, InpPSAR_Maximum);
handle_atr = iATR(_Symbol, _Period, 14);
handle_rsi = iRSI(_Symbol, _Period, InpRSI_Period, PRICE_CLOSE);
handle_adx = iADX(_Symbol, _Period, InpADX_Period);
if(handle_bb1 == INVALID_HANDLE || handle_bb2 == INVALID_HANDLE || handle_ema8 == INVALID_HANDLE ||
handle_sma21 == INVALID_HANDLE || handle_ema50 == INVALID_HANDLE || handle_psar == INVALID_HANDLE ||
handle_atr == INVALID_HANDLE || handle_rsi == INVALID_HANDLE || handle_adx == INVALID_HANDLE)
{
return(INIT_FAILED);
}
// --- MEMBUAT OBJEK LAYOUT BARU ---
CreateLabel("DB_Title", 20, 20, "=== M1 HYBRID MONITOR PANEL ===", 11, clrWhite);
CreateLabel("DB_Status", 20, 45, "STATUS: LOADING...", 12, clrYellow);
CreateLabel("DB_BB1", 20, 75, "BB1 (200): Upper: - | Mid: - | Lower: -", 9, clrCyan);
CreateLabel("DB_BB2", 20, 95, "BB2 (20): Upper: - | Mid: - | Lower: -", 9, clrCyan);
CreateLabel("DB_EMA8", 20, 115, "EMA 8: -", 9, clrLightPink);
CreateLabel("DB_SMA21", 20, 135, "SMA 21: -", 9, clrLightSkyBlue);
CreateLabel("DB_EMA50", 20, 155, "EMA 50: -", 9, clrDarkGray); // clrLightBlack diganti clrDarkGray (Aman dari error)
// Tambahan Info Baru Sesuai Request Anda
CreateLabel("DB_Targets", 20, 180, "Proyeksi Jarak SL Manual: - | Jarak TP: -", 9, clrLightGray);
CreateLabel("DB_DailyOpen", 20, 200, "Daily Open: -", 9, clrWhite);
CreateLabel("DB_OpenPip", 20, 220, "Open Pip: -", 9, clrKhaki);
CreateLabel("DB_Time", 20, 240, "Time (Sisa Candle M1): - detik", 9, clrOrange);
CreateLabel("DB_RSI", 20, 260, "RSI: -", 9, clrSpringGreen);
CreateLabel("DB_ADX", 20, 280, "ADX: -", 9, clrGold);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, "DB_");
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
// Array buffers
double bb1_upper[2], bb1_mid[2], bb1_lower[2];
double bb2_upper[2], bb2_mid[2], bb2_lower[2];
double ema8[2], sma21[2], ema50[2], psar[2], atr[2], rsi[2], adx[2], close_price[2], low_p[2], high_p[2];
if(CopyBuffer(handle_bb1, 1, 0, 2, bb1_upper) < 0 || CopyBuffer(handle_bb1, 0, 0, 2, bb1_mid) < 0 || CopyBuffer(handle_bb1, 2, 0, 2, bb1_lower) < 0 ||
CopyBuffer(handle_bb2, 1, 0, 2, bb2_upper) < 0 || CopyBuffer(handle_bb2, 0, 0, 2, bb2_mid) < 0 || CopyBuffer(handle_bb2, 2, 0, 2, bb2_lower) < 0 ||
CopyBuffer(handle_ema8, 0, 0, 2, ema8) < 0 || CopyBuffer(handle_sma21, 0, 0, 2, sma21) < 0 || CopyBuffer(handle_ema50, 0, 0, 2, ema50) < 0 ||
CopyBuffer(handle_psar, 0, 0, 2, psar) < 0 || CopyBuffer(handle_atr, 0, 0, 2, atr) < 0 ||
CopyBuffer(handle_rsi, 0, 0, 2, rsi) < 0 || CopyBuffer(handle_adx, 0, 0, 2, adx) < 0 ||
CopyClose(_Symbol, _Period, 0, 2, close_price) < 0 || CopyLow(_Symbol, _Period, 0, 2, low_p) < 0 || CopyHigh(_Symbol, _Period, 0, 2, high_p) < 0)
{
return(rates_total);
}
// --- DATA HITUNGAN BARU ---
// 1. Mengambil Harga Daily Open (Harga pembukaan lilin harian/D1)
MqlRates daily_rates[];
ArraySetAsSeries(daily_rates, true);
if(CopyRates(_Symbol, PERIOD_D1, 0, 1, daily_rates) > 0)
{
double daily_open = daily_rates[0].open;
ObjectSetString(0, "DB_DailyOpen", OBJPROP_TEXT, "Daily Open : " + DoubleToString(daily_open, _Digits));
// 2. Hitung Open Pip (Selisih Running Price Saat Ini terhadap Daily Open)
double current_price = close_price[0]; // Harga tick saat ini
double diff_pips = (current_price - daily_open) / (_Point * 10);
if(_Digits == 3 || _Digits == 5) diff_pips = (current_price - daily_open) / (_Point * 10); // Menyesuaikan broker 3/5 digit
else diff_pips = (current_price - daily_open) / _Point;
ObjectSetString(0, "DB_OpenPip", OBJPROP_TEXT, StringFormat("Open Pip : %.1f pips", diff_pips));
}
// 3. Hitung Waktu Sisa Candle (Countdown dalam detik)
datetime current_time = TimeCurrent();
datetime candle_open_time = iTime(_Symbol, _Period, 0);
int period_seconds = PeriodSeconds(_Period); // Jika M1, ini bernilai 60 detik
int time_left = (int)(candle_open_time + period_seconds - current_time);
if(time_left < 0) time_left = 0;
ObjectSetString(0, "DB_Time", OBJPROP_TEXT, StringFormat("Time : %d detik menuju bar baru", time_left));
// 4. Update Teks Indikator Standar & Baru
ObjectSetString(0, "DB_BB1", OBJPROP_TEXT, StringFormat("BB1 (200) : Upper: %s | Mid: %s | Lower: %s", DoubleToString(bb1_upper[1], _Digits), DoubleToString(bb1_mid[1], _Digits), DoubleToString(bb1_lower[1], _Digits)));
ObjectSetString(0, "DB_BB2", OBJPROP_TEXT, StringFormat("BB2 (20) : Upper: %s | Mid: %s | Lower: %s", DoubleToString(bb2_upper[1], _Digits), DoubleToString(bb2_mid[1], _Digits), DoubleToString(bb2_lower[1], _Digits)));
ObjectSetString(0, "DB_EMA8", OBJPROP_TEXT, "EMA 8 : " + DoubleToString(ema8[1], _Digits));
ObjectSetString(0, "DB_SMA21", OBJPROP_TEXT, "SMA 21 : " + DoubleToString(sma21[1], _Digits));
ObjectSetString(0, "DB_EMA50", OBJPROP_TEXT, "EMA 50 : " + DoubleToString(ema50[1], _Digits));
ObjectSetString(0, "DB_RSI", OBJPROP_TEXT, StringFormat("RSI : %.2f", rsi[1]));
ObjectSetString(0, "DB_ADX", OBJPROP_TEXT, StringFormat("ADX : %.2f", adx[1]));
// --- EVALUASI LOGIKA ALARM ---
double vwap_sim = bb1_mid[1];
double bb1_u_cross[3], bb1_m_cross[3], bb1_l_cross[3], bb2_m_cross[3];
CopyBuffer(handle_bb1, 1, 0, 3, bb1_u_cross);
CopyBuffer(handle_bb1, 0, 0, 3, bb1_m_cross);
CopyBuffer(handle_bb1, 2, 0, 3, bb1_l_cross);
CopyBuffer(handle_bb2, 0, 0, 3, bb2_m_cross);
bool L1_Buy = (bb2_m_cross[1] > bb1_u_cross[1] && bb2_m_cross[2] <= bb1_u_cross[2]) || (bb2_m_cross[1] > bb1_m_cross[1] && bb2_m_cross[2] <= bb1_m_cross[2]) || (bb2_m_cross[1] > bb1_l_cross[1] && bb2_m_cross[2] <= bb1_l_cross[2]);
bool L1_Sell = (bb2_m_cross[1] < bb1_u_cross[1] && bb2_m_cross[2] >= bb1_u_cross[2]) || (bb2_m_cross[1] < bb1_m_cross[1] && bb2_m_cross[2] >= bb1_m_cross[2]) || (bb2_m_cross[1] < bb1_l_cross[1] && bb2_m_cross[2] >= bb1_l_cross[2]);
bool L2_Buy = (ema8[1] > sma21[1]) && (close_price[1] > ema50[1]);
bool L2_Sell = (ema8[1] < sma21[1]) && (close_price[1] < ema50[1]);
bool L3_Buy = (psar[1] < low_p[1]);
bool L3_Sell = (psar[1] > high_p[1]);
bool L4_Buy = (close_price[1] > vwap_sim);
bool L4_Sell = (close_price[1] < vwap_sim);
// Ganti warna status rekomendasi utama
datetime current_bar_time = iTime(_Symbol, _Period, 0);
if(L1_Buy && L2_Buy && L3_Buy && L4_Buy)
{
ObjectSetString(0, "DB_Status", OBJPROP_TEXT, "STATUS: REKOMENDASI >>> BUY SIGNAL VALID <<<");
ObjectSetInteger(0, "DB_Status", OBJPROP_COLOR, clrLime);
if(current_bar_time != time_last_bar) { Alert(_Symbol+" M1 - BUY VALID!"); time_last_bar = current_bar_time; }
}
else if(L1_Sell && L2_Sell && L3_Sell && L4_Sell)
{
ObjectSetString(0, "DB_Status", OBJPROP_TEXT, "STATUS: REKOMENDASI >>> SELL SIGNAL VALID <<<");
ObjectSetInteger(0, "DB_Status", OBJPROP_COLOR, clrRed);
if(current_bar_time != time_last_bar) { Alert(_Symbol+" M1 - SELL VALID!"); time_last_bar = current_bar_time; }
}
else
{
ObjectSetString(0, "DB_Status", OBJPROP_TEXT, "STATUS: REKOMENDASI >>> WAIT (WAITING SIGNAL) <<<");
ObjectSetInteger(0, "DB_Status", OBJPROP_COLOR, clrYellow);
}
// Update Jarak Target ATR
double sl_dist = NormalizeDouble(atr[1] * InpATR_Multiplier_SL, _Digits);
double tp_dist = NormalizeDouble(atr[1] * InpATR_Multiplier_TP, _Digits);
ObjectSetString(0, "DB_Targets", OBJPROP_TEXT, StringFormat("Proyeksi Jarak SL Manual: %s | Jarak TP: %s", DoubleToString(sl_dist, _Digits), DoubleToString(tp_dist, _Digits)));
return(rates_total);
}
//+------------------------------------------------------------------+
//| Fungsi Pembantu Membuat Label Teks |
//+------------------------------------------------------------------+
void CreateLabel(string name, int x, int y, string text, int size, color col)
{
ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, size);
ObjectSetString(0, name, OBJPROP_FONT, "Consolas"); // Menggunakan font berspasi seragam agar sejajar rapi
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_COLOR, col);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
}