//+------------------------------------------------------------------+ //| Advanced Trend Indicator v2 | //| Kombinacija 200 EMA, modifikovanog Ichimoku oblaka i Supertrend | //| Dodatne validacije: | //| - Minimalna distanca između 200 EMA i oblaka | //| - Cooldown period nakon velikog pokreta | //+------------------------------------------------------------------+ #property indicator_chart_window #property indicator_buffers 2 #property indicator_color1 Lime // Buy strelica #property indicator_color2 Red // Sell strelica #property indicator_width1 2 #property indicator_width2 2 //--- Indicator buffers double BuySignalBuffer[]; double SellSignalBuffer[]; //--- Input parametri input int EMA_Period = 200; // Period za 200 EMA input int TenkanPeriod = 9; // Period za Tenkan-sen input int KijunPeriod = 26; // Period za Kijun-sen input int SenkouBPeriod = 52; // Period za Senkou Span B input int ATR_Period = 10; // Period za ATR u Supertrend-u input double ATR_Factor = 3.0; // Faktor za Supertrend // Dodatni parametri za validaciju input double Min_EMA_Cloud_Dist = 5.0; // Minimalna distanca (u point-ovima) između 200 EMA i oblaka input double LargeMoveThreshold = 0.03; // Procenat promene (3%) za cooldown period //--- Arrow codes (Wingdings) #define BUY_ARROW 233 #define SELL_ARROW 234 //--- Varijabla za praćenje trenutnog trenda int currentTrend = 0; // 0 - Neutral, 1 - Buy, -1 - Sell //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { IndicatorBuffers(2); // Postavi buffer za Buy signale SetIndexStyle(0, DRAW_ARROW, 0, 2); SetIndexArrow(0, BUY_ARROW); SetIndexBuffer(0, BuySignalBuffer); // Postavi buffer za Sell signale SetIndexStyle(1, DRAW_ARROW, 0, 2); SetIndexArrow(1, SELL_ARROW); SetIndexBuffer(1, SellSignalBuffer); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { } //+------------------------------------------------------------------+ //| Helper function: Izračunaj Tenkan-sen | //+------------------------------------------------------------------+ double CalcTenkan(int shift) { double highest = High[iHighest(NULL,0,MODE_HIGH,TenkanPeriod,shift)]; double lowest = Low[iLowest(NULL,0,MODE_LOW,TenkanPeriod,shift)]; return (highest + lowest) / 2.0; } //+------------------------------------------------------------------+ //| Helper function: Izračunaj Kijun-sen | //+------------------------------------------------------------------+ double CalcKijun(int shift) { double highest = High[iHighest(NULL,0,MODE_HIGH,KijunPeriod,shift)]; double lowest = Low[iLowest(NULL,0,MODE_LOW,KijunPeriod,shift)]; return (highest + lowest) / 2.0; } //+------------------------------------------------------------------+ //| Helper function: Izračunaj Senkou Span B | //+------------------------------------------------------------------+ double CalcSenkouB(int shift) { double highest = High[iHighest(NULL,0,MODE_HIGH,SenkouBPeriod,shift)]; double lowest = Low[iLowest(NULL,0,MODE_LOW,SenkouBPeriod,shift)]; return (highest + lowest) / 2.0; } //+------------------------------------------------------------------+ //| 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[]) { int counted_bars = prev_calculated; if(counted_bars < 0) return(-1); if(counted_bars > 0) counted_bars--; int limit = rates_total - counted_bars; //--- Priprema lokalnih nizova za Supertrend int total = rates_total; double BasicUpper[], BasicLower[], FinalUpper[], FinalLower[], ST[]; ArrayResize(BasicUpper, total); ArrayResize(BasicLower, total); ArrayResize(FinalUpper, total); ArrayResize(FinalLower, total); ArrayResize(ST, total); //--- Izračunaj Supertrend od najstarijeg bara do najnovijeg for(int j = total - 1; j >= 0; j--) { double atr = iATR(NULL, 0, ATR_Period, j); BasicUpper[j] = (high[j] + low[j]) / 2.0 + ATR_Factor * atr; BasicLower[j] = (high[j] + low[j]) / 2.0 - ATR_Factor * atr; if(j == total - 1) { FinalUpper[j] = BasicUpper[j]; FinalLower[j] = BasicLower[j]; } else { // Final Upper band if(BasicUpper[j] < FinalUpper[j+1] || close[j+1] > FinalUpper[j+1]) FinalUpper[j] = BasicUpper[j]; else FinalUpper[j] = FinalUpper[j+1]; // Final Lower band if(BasicLower[j] > FinalLower[j+1] || close[j+1] < FinalLower[j+1]) FinalLower[j] = BasicLower[j]; else FinalLower[j] = FinalLower[j+1]; } // Odredi Supertrend liniju if(close[j] <= FinalUpper[j]) ST[j] = FinalUpper[j]; else ST[j] = FinalLower[j]; } //--- Glavna petlja za svaki bar (od najstarijeg ka najnovijem) for(int i = limit - 1; i >= 0; i--) { // Resetuj signale BuySignalBuffer[i] = EMPTY_VALUE; SellSignalBuffer[i] = EMPTY_VALUE; // 200 EMA double ema200 = iMA(NULL, 0, EMA_Period, 0, MODE_EMA, PRICE_CLOSE, i); //--- Izračunaj Ichimoku elemente double tenkan = CalcTenkan(i); double kijun = CalcKijun(i); double senkouA = (tenkan + kijun) / 2.0; double senkouB = CalcSenkouB(i); double cloudUpper = (senkouA > senkouB) ? senkouA : senkouB; double cloudLower = (senkouA < senkouB) ? senkouA : senkouB; // Provera minimalne distance između EMA i oblaka bool validCloudDistLong = ((cloudUpper - ema200) > (Min_EMA_Cloud_Dist * Point)); bool validCloudDistShort = ((ema200 - cloudLower) > (Min_EMA_Cloud_Dist * Point)); //--- Uslovi za LONG i SHORT signal bool condLong = (close[i] > cloudUpper) && validCloudDistLong && (close[i] > ST[i]); bool condShort = (close[i] < cloudLower) && validCloudDistShort && (close[i] < ST[i]); // Provera prethodnog bara (ako postoji) za potvrdu signala bool prevCondLong = false; bool prevCondShort = false; if(i < rates_total - 1) { double tenkan_prev = CalcTenkan(i+1); double kijun_prev = CalcKijun(i+1); double senkouA_prev = (tenkan_prev + kijun_prev) / 2.0; double senkouB_prev = CalcSenkouB(i+1); double cloudUpper_prev = (senkouA_prev > senkouB_prev) ? senkouA_prev : senkouB_prev; double cloudLower_prev = (senkouA_prev < senkouB_prev) ? senkouA_prev : senkouB_prev; double ema200_prev = iMA(NULL, 0, EMA_Period, 0, MODE_EMA, PRICE_CLOSE, i+1); prevCondLong = (close[i+1] > cloudUpper_prev) && ((cloudUpper_prev - ema200_prev) > (Min_EMA_Cloud_Dist * Point)) && (close[i+1] > ST[i+1]); prevCondShort = (close[i+1] < cloudLower_prev) && ((ema200_prev - cloudLower_prev) > (Min_EMA_Cloud_Dist * Point)) && (close[i+1] < ST[i+1]); } //--- Cooldown: ako prethodni bar pokazuje veliki pokret, ignoriši signal bool cooldown = false; if(i < rates_total - 1) { double pctMove = MathAbs(close[i+1] - close[i]) / close[i+1]; if(pctMove > LargeMoveThreshold) cooldown = true; } //--- Postavi signal (razlikuj slab i jak signal) samo ako nije cooldown if(!cooldown) { if(condLong) { double offsetLong = (prevCondLong) ? 5 * Point : 3 * Point; BuySignalBuffer[i] = low[i] - offsetLong; SellSignalBuffer[i] = EMPTY_VALUE; // Provera promene trenda i emitovanje zvucnog obavestenja if(i == 0 && currentTrend != 1) { Alert("BUY Signal Detected!"); PlaySound("buy_alert.wav"); currentTrend = 1; } } else if(condShort) { double offsetShort = (prevCondShort) ? 5 * Point : 3 * Point; SellSignalBuffer[i] = high[i] + offsetShort; BuySignalBuffer[i] = EMPTY_VALUE; // Provera promene trenda i emitovanje zvucnog obavestenja if(i == 0 && currentTrend != -1) { Alert("SELL Signal Detected!"); PlaySound("sell_alert.wav"); currentTrend = -1; } } else { BuySignalBuffer[i] = EMPTY_VALUE; SellSignalBuffer[i] = EMPTY_VALUE; // Resetovanje trenda ako nema signala (bez alerta) if(i == 0) { currentTrend = 0; // Održavamo logiku praćenja trenda, samo uklanjamo alert } } } else { BuySignalBuffer[i] = EMPTY_VALUE; SellSignalBuffer[i] = EMPTY_VALUE; // Resetovanje trenda ako je cooldown (bez alerta) if(i == 0) { currentTrend = 0; // Održavamo logiku praćenja trenda, samo uklanjamo alert } } } return(rates_total); }