//+------------------------------------------------------------------+
//|                                                     MillionMoves |
//|                      Copyright 2024, MetaTrader 5 Codebase       |
//|                                        https://www.mql5.com      |
//+------------------------------------------------------------------+
#property strict
#property indicator_chart_window
#property indicator_buffers 9
#property indicator_plots   1

#property indicator_label1  "TrendLine"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrBlue

// Input parameters
input int length = 14;
input ENUM_APPLIED_PRICE src = PRICE_CLOSE;
input int sl_atr_length = 14;
input double tp1 = 1.5;
input double tp2 = 3.0;
input double tp3 = 4.5;
input double atr_multiplier = 1.0;
input int sma_length = 20;
input double sma_offset = 1.3;
input int ema_length = 9;
input int sma200_length = 200;

input int ma1_length = 5;
input int ma2_length = 10;
input int ma3_length = 15;
input int ma4_length = 20;
input int ma5_length = 25;

input int order_block_length = 20;
input int rsi_length = 14;
input double overbought = 70;
input double oversold = 30;

// Buffers
double sma_buffer[];
double ema_buffer[];
double sma200_buffer[];
double ma1_buffer[];
double ma2_buffer[];
double ma3_buffer[];
double ma4_buffer[];
double ma5_buffer[];
double atr_buffer[];

double entryPrice;
double slPrice;
double tp1Price;
double tp2Price;
double tp3Price;
bool lastBuySignal = false;
bool lastSellSignal = false;

int OnInit() {
   SetIndexBuffer(0, sma_buffer);
   SetIndexBuffer(1, ema_buffer);
   SetIndexBuffer(2, sma200_buffer);
   SetIndexBuffer(3, ma1_buffer);
   SetIndexBuffer(4, ma2_buffer);
   SetIndexBuffer(5, ma3_buffer);
   SetIndexBuffer(6, ma4_buffer);
   SetIndexBuffer(7, ma5_buffer);
   SetIndexBuffer(8, atr_buffer);

   return(INIT_SUCCEEDED);
}

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 start = prev_calculated > 0 ? prev_calculated - 1 : 0;

   for (int i = start; i < rates_total; i++) {
      sma_buffer[i] = iMA(NULL, 0, sma_length, 0, MODE_SMA, src, i) + sma_offset;
      ema_buffer[i] = iMA(NULL, 0, ema_length, 0, MODE_EMA, src, i);
      sma200_buffer[i] = iMA(NULL, 0, sma200_length, 0, MODE_SMA, src, i);
      ma1_buffer[i] = iMA(NULL, 0, ma1_length, 0, MODE_SMA, src, i);
      ma2_buffer[i] = iMA(NULL, 0, ma2_length, 0, MODE_SMA, src, i);
      ma3_buffer[i] = iMA(NULL, 0, ma3_length, 0, MODE_SMA, src, i);
      ma4_buffer[i] = iMA(NULL, 0, ma4_length, 0, MODE_SMA, src, i);
      ma5_buffer[i] = iMA(NULL, 0, ma5_length, 0, MODE_SMA, src, i);
      atr_buffer[i] = iATR(NULL, 0, sl_atr_length, i);
   }

   for (int i = start; i < rates_total; i++) {
      bool trendUp = close[i] > ema_buffer[i] && close[i] > sma_buffer[i];
      bool trendDown = close[i] < ema_buffer[i] && close[i] < sma_buffer[i];

      if (Crossover(close, sma_buffer, i)) {
         entryPrice = close[i];
         slPrice = entryPrice - atr_buffer[i] * atr_multiplier;
         tp1Price = entryPrice + atr_buffer[i] * tp1;
         tp2Price = entryPrice + atr_buffer[i] * tp2;
         tp3Price = entryPrice + atr_buffer[i] * tp3;
         lastBuySignal = true;
         lastSellSignal = false;

         DrawLabel("Entry", entryPrice, time[i], clrBlue);
         DrawLabel("SL", slPrice, time[i], clrRed);
         DrawLabel("TP1", tp1Price, time[i], clrGreen);
         DrawLabel("TP2", tp2Price, time[i], clrGreen);
         DrawLabel("TP3", tp3Price, time[i], clrGreen);
      } else if (Crossunder(close, sma_buffer, i)) {
         entryPrice = close[i];
         slPrice = entryPrice + atr_buffer[i] * atr_multiplier;
         tp1Price = entryPrice - atr_buffer[i] * tp1;
         tp2Price = entryPrice - atr_buffer[i] * tp2;
         tp3Price = entryPrice - atr_buffer[i] * tp3;
         lastBuySignal = false;
         lastSellSignal = true;

         DrawLabel("Entry", entryPrice, time[i], clrBlue);
         DrawLabel("SL", slPrice, time[i], clrRed);
         DrawLabel("TP1", tp1Price, time[i], clrGreen);
         DrawLabel("TP2", tp2Price, time[i], clrGreen);
         DrawLabel("TP3", tp3Price, time[i], clrGreen);
      }

      bool smartBuySignal = lastBuySignal && trendUp;
      bool smartSellSignal = lastSellSignal && trendDown;
      
      if (smartBuySignal) {
         ObjectCreate(0, "SmartBuy"+IntegerToString(i), OBJ_ARROW, 0, time[i], low[i] - atr_buffer[i]);
         ObjectSetInteger(0, "SmartBuy"+IntegerToString(i), OBJPROP_COLOR, clrGreen);
      }
      if (smartSellSignal) {
         ObjectCreate(0, "SmartSell"+IntegerToString(i), OBJ_ARROW, 0, time[i], high[i] + atr_buffer[i]);
         ObjectSetInteger(0, "SmartSell"+IntegerToString(i), OBJPROP_COLOR, clrRed);
      }
   }

   return(rates_total);
}

bool Crossover(const double &data1[], const double &data2[], int index) {
   if (index > 0) {
      return (data1[index] > data2[index] && data1[index - 1] <= data2[index - 1]);
   }
   return false;
}

bool Crossunder(const double &data1[], const double &data2[], int index) {
   if (index > 0) {
      return (data1[index] < data2[index] && data1[index - 1] >= data2[index - 1]);
   }
   return false;
}

void DrawLabel(string name, double price, datetime time, color clr) {
   string objName = name + TimeToString(time, TIME_DATE | TIME_MINUTES);
   if (ObjectFind(0, objName) >= 0) {
      ObjectDelete(0, objName);
   }
   ObjectCreate(0, objName, OBJ_TEXT, 0, time, price);
   ObjectSetInteger(0, objName, OBJPROP_COLOR, clr);
   ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, 10);
   ObjectSetString(0, objName, OBJPROP_TEXT, name + ": " + DoubleToString(price, 2));
}