//+------------------------------------------------------------------+
//|                                       TrendlineProjection413.mq4        
//|                                              
//+------------------------------------------------------------------+
#property indicator_chart_window
#property strict

// Input parameters
extern color TrendlineColor_H4 = clrLime;   // Color of H4 trendline
extern color TrendlineColor_H1 = clrGold;     // Color of H1 trendline
extern color TrendlineColor_M30 = clrRed;     // Color of M30 trendline
extern color ArrowColorDown = clrRed;         // Color of the down arrow
extern color ArrowColorUp = clrGreen;         // Color of the up arrow
extern int ArrowSize = 2;                     // Size of the arrows
extern int LineWidth = 2;                     // Line width for trendlines
extern int TrendlineProjectionBars = 1;      // Length of trendline projection in bars

// Handles for trendlines
int TrendlineHandle_H4 = -1;  
int TrendlineHandle_H1 = -1;  
int TrendlineHandle_M30 = -1; 

double prevH4Price = 0.0;  // Previous H4 trendline price
double prevH1Price = 0.0;  // Previous H1 trendline price
double prevM30Price = 0.0; // Previous M30 trendline price

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
    // Draw trendlines for H4, H1, and M30
    TrendlineHandle_H4 = DrawTrendlineOnTimeframe(PERIOD_H4, "Trendline_H4", TrendlineColor_H4);
    TrendlineHandle_H1 = DrawTrendlineOnTimeframe(PERIOD_H1, "Trendline_H1", TrendlineColor_H1);
    TrendlineHandle_M30 = DrawTrendlineOnTimeframe(PERIOD_M30, "Trendline_M30", TrendlineColor_M30);
   
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| 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[])
{
    if(TrendlineHandle_H4 != -1 && TrendlineHandle_H1 != -1 && TrendlineHandle_M30 != -1)
    {
        double priceH4, priceH1, priceM30;

        // Get the price on the trendlines at the current bar's time
        bool h4_valid = ObjectGetValueByTime(TrendlineHandle_H4, time[0], priceH4);
        bool h1_valid = ObjectGetValueByTime(TrendlineHandle_H1, time[0], priceH1);
        bool m30_valid = ObjectGetValueByTime(TrendlineHandle_M30, time[0], priceM30);
      
        // Ensure all trendline prices are valid
        if(h4_valid && h1_valid && m30_valid)
        {
            // Check if all trendlines are above the current price
            if(priceH4 > close[0] && priceH1 > close[0] && priceM30 > close[0])
            {
                DrawArrow(time[0], high[0] + 10 * Point, false); // Plot down arrow above the bar
            }

            // Check for crossing conditions
            if (prevH4Price < priceH1 && priceH4 >= priceH1) // H4 crosses above H1
            {
                DrawArrow(time[0], high[0] + 15 * Point, true); // Plot up arrow above the bar
            }
            else if (prevH4Price > priceH1 && priceH4 <= priceH1) // H4 crosses below H1
            {
                DrawArrow(time[0], low[0] - 10 * Point, false); // Plot down arrow below the bar
            }

            // Check for H4 crossing M30
            if (prevH4Price < priceM30 && priceH4 >= priceM30) // H4 crosses above M30
            {
                DrawArrow(time[0], high[0] + 20 * Point, true); // Plot up arrow above the bar
            }
            else if (prevH4Price > priceM30 && priceH4 <= priceM30) // H4 crosses below M30
            {
                DrawArrow(time[0], low[0] - 15 * Point, false); // Plot down arrow below the bar
            }

            // Update previous trendline prices
            prevH4Price = priceH4;
            prevH1Price = priceH1;
            prevM30Price = priceM30;
        }
    }
   
    return(rates_total);
}

//+------------------------------------------------------------------+
//| Function to draw trendlines on the specified timeframe            |
int DrawTrendlineOnTimeframe(int timeframe, string name, color trendlineColor)
{
    int shiftHigh = iHighest(NULL, timeframe, MODE_HIGH, 50, 0); // Get the highest point over 50 bars
    int shiftLow = iLowest(NULL, timeframe, MODE_LOW, 50, 0);    // Get the lowest point over 50 bars
   
    double priceHigh = iHigh(NULL, timeframe, shiftHigh);  // High price
    double priceLow = iLow(NULL, timeframe, shiftLow);     // Low price
    datetime timeHigh = iTime(NULL, timeframe, shiftHigh); // Time of the high point
    datetime timeLow = iTime(NULL, timeframe, shiftLow);   // Time of the low point
   
    // Create a trendline from high to low with projection
    int handle = ObjectCreate(0, name, OBJ_TREND, 0, timeLow, priceLow, timeHigh + TrendlineProjectionBars * PeriodSeconds(), priceHigh);
    if(handle > 0)
    {
        ObjectSetInteger(0, name, OBJPROP_COLOR, trendlineColor);
        ObjectSetInteger(0, name, OBJPROP_WIDTH, LineWidth); // Set the line width
        ObjectSetInteger(0, name, OBJPROP_RAY_RIGHT, true); // Extend the trendline to the right
    }
   
    return handle;
}

//+------------------------------------------------------------------+
//| Function to draw arrows                                           |
void DrawArrow(datetime time, double price, bool isUp)
{
    string arrowName = "Arrow_" + TimeToString(time, TIME_DATE | TIME_MINUTES);
    if(!ObjectFind(0, arrowName))
    {
        int arrowCode = isUp ? 233 : 234; // 233 = up arrow, 234 = down arrow
        color arrowColor = isUp ? ArrowColorUp : ArrowColorDown;
      
        ObjectCreate(0, arrowName, OBJ_ARROW, 0, time, price);
        ObjectSetInteger(0, arrowName, OBJPROP_COLOR, arrowColor);
        ObjectSetInteger(0, arrowName, OBJPROP_WIDTH, ArrowSize);
        ObjectSetInteger(0, arrowName, OBJPROP_ARROWCODE, arrowCode); // Set arrow direction
    }
}
//+------------------------------------------------------------------+
