//+------------------------------------------------------------------+ //| SNRC_OrderBlock_Indicator.mq5 | //| Telif Hakkı 2025, AYDIN SARIHAN (Geliştirildi) | //| https://www.mql5.com/en/users/aydinsarihan| //+------------------------------------------------------------------+ #property copyright "Copyright © 2025, AYDIN SARIHAN (Developed by AI)" #property link "https://www.mql5.com/en/users/aydinsarihan" #property version "1.00" #property strict #property indicator_chart_window #property description "SNRC QUASİDAMO ENGULF TRENDLINE metodolojisine göre Order Block'ları tespit eder." /// Değişiklik: Kod, sağlanan direktife ve SNRC kurallarına göre sıfırdan yapılandırıldı. /// Değişiklik: Çok zaman dilimli (MTF) analiz mantığı eklendi. /// Değişiklik: RBR ve DBD formasyon tespiti eklendi. /// Değişiklik: Nesne yönetimi ve mitigasyon kontrolü eklendi. //================================================================== // BÖLÜM 1: DAHİL EDİLENLER & KÜTÜPHANELER //================================================================== // Bu gösterge için ek kütüphane gerekmemektedir. //================================================================== // BÖLÜM 2: GİRİŞ PARAMETRELERİ (INPUTS) //================================================================== input group "Zaman Dilimi Ayarları (MTF)"; input ENUM_TIMEFRAMES HTF_Timeframe = PERIOD_H4; // Yüksek Zaman Dilimi (Engulfing tespiti için) input int HTF_Lookback_Bars = 100; // HTF'de taranacak mum sayısı input group "Formasyon Tanımlama Ayarları"; input double Base_Candle_Max_Body_Ratio = 0.3; // Bir mumun 'Base' sayılması için (Gövde/Toplam Boyut) oranı input int Max_Base_Candles = 5; // Bir Base bölgesindeki maksimum mum sayısı input group "Görsel Ayarlar"; input color Bullish_OB_Color = clrDodgerBlue; // Yükseliş (Bullish) Order Block rengi input color Bearish_OB_Color = clrTomato; // Düşüş (Bearish) Order Block rengi input color Mitigated_OB_Color = clrGray; // Mitige edilmiş (temas edilmiş) OB rengi input bool Fill_Order_Block = true; // Order Block içini doldur input bool Delete_Mitigated_OB = false; // Mitige edilmiş OB'leri sil //================================================================== // BÖLÜM 3: GLOBAL DEĞİŞKENLER & SABİTLER //================================================================== //--- Yapılar struct OrderBlock { double price_high; // OB üst sınırı double price_low; // OB alt sınırı datetime time_start; // OB başlangıç zamanı string name; // Grafik nesnesi adı bool is_bullish; // true: Bullish OB, false: Bearish OB bool is_mitigated; // Mitigasyon durumu }; //--- Global Değişklenler OrderBlock g_order_blocks[]; // Tespit edilen tüm order block'ları saklayan dizi datetime g_lastBarTime; // Yeni bar kontrolü için son bar zamanı // Sinyal enum (Direktif uyumlu) enum ENUM_SIGNAL { SIGNAL_BULLISH, SIGNAL_BEARISH, SIGNAL_NONE }; //================================================================== // BÖLÜM 4: ANA OLAY YÖNETİCİLERİ (MAIN EVENT HANDLERS) //================================================================== //+------------------------------------------------------------------+ //| Başlatma fonksiyonu | //+------------------------------------------------------------------+ int OnInit() { if(_Period >= HTF_Timeframe) { Print("Hata: Göstergenin zaman dilimi, HTF_Timeframe'den küçük olmalıdır."); return(INIT_PARAMETERS_INCORRECT); } ArrayResize(g_order_blocks, 0); g_lastBarTime = 0; Print("Başlatıldı: ", MQLInfoString(MQL_PROGRAM_NAME)); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Durdurma fonksiyonu | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { ObjectsDeleteAll(0, "SNRC_OB_"); Print("Durduruldu. Sebep: ", reason); } //+------------------------------------------------------------------+ //| Ana Döngü Fonksiyonu (Indicator) | //+------------------------------------------------------------------+ 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[]) { //--- Yeni bar kontrolü if(time[rates_total - 1] == g_lastBarTime) { CheckMitigation(rates_total, high, low); // Sadece mitigasyon kontrolü yap return(rates_total); } g_lastBarTime = time[rates_total - 1]; //--- Ana Mantık FindOrderBlocks(rates_total, time); CheckMitigation(rates_total, high, low); DrawOrderBlocks(); return(rates_total); } //================================================================== // BÖLÜM 5: STRATEJİ & HESAPLAMA MANTIĞI //================================================================== /// /// Ana fonksiyon: HTF'de Engulfing arar ve LTF'de OB tespiti için mantığı tetikler. /// void FindOrderBlocks(const int rates_total, const datetime &time[]) { MqlRates htf_rates[]; // HTF verilerini kopyala if(CopyRates(Symbol(), HTF_Timeframe, 0, HTF_Lookback_Bars, htf_rates) < HTF_Lookback_Bars) { Print("HTF verileri kopyalanamadı."); return; } ArraySetAsSeries(htf_rates, true); // HTF mumlarını tara for(int i = 0; i < HTF_Lookback_Bars - 2; i++) { ENUM_SIGNAL signal = Is_HTF_Engulfing(htf_rates, i); if(signal != SIGNAL_NONE) { // Engulfing bulundu, şimdi LTF'de ilgili aralıkta OB ara datetime htf_candle_start_time = htf_rates[i].time; datetime htf_candle_end_time = htf_rates[i].time + PeriodSeconds(HTF_Timeframe); // LTF (mevcut grafik) bar indekslerini bul int ltf_start_index = iBarShift(Symbol(), Period(), htf_candle_start_time); int ltf_end_index = iBarShift(Symbol(), Period(), htf_candle_end_time); if(ltf_end_index < 0) ltf_end_index = 0; // Henüz kapanmamış mum için Find_LTF_Pattern_And_Create_OB(signal, ltf_start_index, ltf_end_index); } } } /// /// Belirtilen HTF mumunun Engulfing olup olmadığını kontrol eder. /// /// HTF fiyat verileri. /// Kontrol edilecek mumun indeksi. /// SIGNAL_BULLISH, SIGNAL_BEARISH, veya SIGNAL_NONE. ENUM_SIGNAL Is_HTF_Engulfing(const MqlRates &htf_rates[], int index) { // Bullish Engulfing if(htf_rates[index].close > htf_rates[index].open && // Mevcut mum bullish htf_rates[index+1].close < htf_rates[index+1].open && // Önceki mum bearish htf_rates[index].close > htf_rates[index+1].open && // Mevcut kapanış, önceki açılışın üstünde htf_rates[index].open < htf_rates[index+1].close) // Mevcut açılış, önceki kapanışın altında { return SIGNAL_BULLISH; } // Bearish Engulfing if(htf_rates[index].close < htf_rates[index].open && // Mevcut mum bearish htf_rates[index+1].close > htf_rates[index+1].open && // Önceki mum bullish htf_rates[index].close < htf_rates[index+1].open && // Mevcut kapanış, önceki açılışın altında htf_rates[index].open > htf_rates[index+1].close) // Mevcut açılış, önceki kapanışın üstünde { return SIGNAL_BEARISH; } return SIGNAL_NONE; } /// /// LTF'de (mevcut grafik) RBR veya DBD formasyonu arar ve OB oluşturur. /// /// HTF Engulfing yönü (BULLISH/BEARISH). /// Aramanın başlayacağı bar indeksi. /// Aramanın biteceği bar indeksi. void Find_LTF_Pattern_And_Create_OB(ENUM_SIGNAL direction, int start_index, int end_index) { MqlRates ltf_rates[]; if(CopyRates(Symbol(), Period(), end_index, start_index - end_index + 1, ltf_rates) <= 0) return; ArraySetAsSeries(ltf_rates, false); // İndeksleme 0'dan başlasın // SNRC Kuralı: Bullish HTF Engulf -> LTF'de DBD ara if(direction == SIGNAL_BULLISH) { // Yükselişten (Rally) önceki son Base'i bul for(int i = ArraySize(ltf_rates) - 2; i > Max_Base_Candles; i--) { // Son mumun güçlü bir yükseliş olduğunu kontrol et (Rally) if(ltf_rates[i].close > ltf_rates[i].open && !IsBaseCandle(ltf_rates[i])) { int base_start_index = -1, base_end_index = -1; // Geriye doğru Base mumlarını ara for(int j = 1; j <= Max_Base_Candles; j++) { if(IsBaseCandle(ltf_rates[i-j])) { if(base_start_index == -1) base_start_index = i-j; base_end_index = i-j; } else break; // Base serisi bitti } // Eğer bir base bölgesi bulunduysa if(base_start_index != -1) { // Base'den önce bir düşüş (Drop) olduğunu onayla if(ltf_rates[base_end_index - 1].close < ltf_rates[base_end_index - 1].open) { // DBD bulundu, Order Block oluştur double ob_high = ltf_rates[base_end_index].high; double ob_low = ltf_rates[base_end_index].low; for(int k=base_end_index + 1; k <= base_start_index; k++) { ob_high = MathMax(ob_high, ltf_rates[k].high); ob_low = MathMin(ob_low, ltf_rates[k].low); } datetime ob_time = ltf_rates[base_end_index].time; AddOrderBlock(ob_high, ob_low, ob_time, true); return; // Bu HTF mumu için bir OB bulundu, aramayı bitir. } } } } } // SNRC Kuralı: Bearish HTF Engulf -> LTF'de RBR ara else if(direction == SIGNAL_BEARISH) { // Düşüşten (Drop) önceki son Base'i bul for(int i = ArraySize(ltf_rates) - 2; i > Max_Base_Candles; i--) { // Son mumun güçlü bir düşüş olduğunu kontrol et (Drop) if(ltf_rates[i].close < ltf_rates[i].open && !IsBaseCandle(ltf_rates[i])) { int base_start_index = -1, base_end_index = -1; // Geriye doğru Base mumlarını ara for(int j = 1; j <= Max_Base_Candles; j++) { if(IsBaseCandle(ltf_rates[i-j])) { if(base_start_index == -1) base_start_index = i-j; base_end_index = i-j; } else break; // Base serisi bitti } // Eğer bir base bölgesi bulunduysa if(base_start_index != -1) { // Base'den önce bir yükseliş (Rally) olduğunu onayla if(ltf_rates[base_end_index - 1].close > ltf_rates[base_end_index - 1].open) { // RBR bulundu, Order Block oluştur double ob_high = ltf_rates[base_end_index].high; double ob_low = ltf_rates[base_end_index].low; for(int k=base_end_index + 1; k <= base_start_index; k++) { ob_high = MathMax(ob_high, ltf_rates[k].high); ob_low = MathMin(ob_low, ltf_rates[k].low); } datetime ob_time = ltf_rates[base_end_index].time; AddOrderBlock(ob_high, ob_low, ob_time, false); return; // Bu HTF mumu için bir OB bulundu, aramayı bitir. } } } } } } //================================================================== // BÖLÜM 8: YARDIMCI FONKSİYONLAR //================================================================== /// /// Bir mumun 'Base' (konsolidasyon) mumu olup olmadığını kontrol eder. /// bool IsBaseCandle(const MqlRates &rate) { double body = MathAbs(rate.open - rate.close); double total_range = rate.high - rate.low; if(total_range == 0) return true; // Doji return (body / total_range) < Base_Candle_Max_Body_Ratio; } /// /// Tespit edilen Order Block'u global diziye ekler. /// void AddOrderBlock(double price_high, double price_low, datetime time_start, bool is_bullish) { // Duplikasyon kontrolü for(int i=0; i < ArraySize(g_order_blocks); i++) { if(g_order_blocks[i].time_start == time_start) return; // Zaten mevcut, ekleme } int last_index = ArraySize(g_order_blocks); ArrayResize(g_order_blocks, last_index + 1); g_order_blocks[last_index].price_high = price_high; g_order_blocks[last_index].price_low = price_low; g_order_blocks[last_index].time_start = time_start; g_order_blocks[last_index].is_bullish = is_bullish; g_order_blocks[last_index].is_mitigated = false; g_order_blocks[last_index].name = "SNRC_OB_" + TimeToString(time_start, TIME_DATE|TIME_MINUTES|TIME_SECONDS); } /// /// Mevcut fiyatın Order Block'ları mitige edip etmediğini kontrol eder. /// void CheckMitigation(int rates_total, const double &high[], const double &low[]) { if(rates_total < 1) return; double current_high = high[rates_total - 1]; double current_low = low[rates_total - 1]; for(int i=0; i < ArraySize(g_order_blocks); i++) { if(g_order_blocks[i].is_mitigated) continue; // Bullish OB Mitigasyonu: Fiyat OB'nin alt sınırına değerse if(g_order_blocks[i].is_bullish && current_low <= g_order_blocks[i].price_high) { g_order_blocks[i].is_mitigated = true; } // Bearish OB Mitigasyonu: Fiyat OB'nin üst sınırına değerse else if(!g_order_blocks[i].is_bullish && current_high >= g_order_blocks[i].price_low) { g_order_blocks[i].is_mitigated = true; } } } /// /// Order Block'ları grafiğe çizer veya günceller. /// void DrawOrderBlocks() { datetime current_time = iTime(Symbol(), Period(), 0); for(int i=0; i < ArraySize(g_order_blocks); i++) { OrderBlock ob = g_order_blocks[i]; if(ob.is_mitigated && Delete_Mitigated_OB) { ObjectDelete(0, ob.name); continue; } // Çizim için renk belirle color ob_color; if(ob.is_mitigated) ob_color = Mitigated_OB_Color; else ob_color = ob.is_bullish ? Bullish_OB_Color : Bearish_OB_Color; // Nesne var mı kontrol et if(ObjectFind(0, ob.name) < 0) // Nesne yok, oluştur { ObjectCreate(0, ob.name, OBJ_RECTANGLE, 0, ob.time_start, ob.price_low, current_time, ob.price_high); ObjectSetInteger(0, ob.name, OBJPROP_COLOR, ob_color); ObjectSetInteger(0, ob.name, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, ob.name, OBJPROP_WIDTH, 1); ObjectSetInteger(0, ob.name, OBJPROP_FILL, Fill_Order_Block); ObjectSetInteger(0, ob.name, OBJPROP_BACK, true); ObjectSetString(0, ob.name, OBJPROP_TOOLTIP, (ob.is_bullish ? "Bullish OB" : "Bearish OB")); } else // Nesne var, güncelle { ObjectMove(0, ob.name, 2, current_time, ob.price_high); ObjectSetInteger(0, ob.name, OBJPROP_COLOR, ob_color); } } }