//+------------------------------------------------------------------+ //| 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); }