//+------------------------------------------------------------------+
//|                                             A! MoonPhases.mq4    |
//|                                                                  |
//|                                           Copyright 2024-2025    |
//+------------------------------------------------------------------+

#property strict
#property indicator_chart_window

// Input Parameters
input datetime StartDate = D'2024.01.01';  // Start Date
input datetime EndDate = D'2025.12.31';    // End Date
input string FontName = "OCR A Extended";           // Font Type
input int FontSize = 15;                    // Font Size
input color FullMoonColor = clrDodgerBlue;     // Full Moon Color
input color NewMoonColor = clrRed;       // New Moon Color
input color FullMoonTextColor = clrDodgerBlue; // Full Moon Text Color
input color NewMoonTextColor = clrRed;   // New Moon Text Color
input uchar FullMoonArrow = 233;          // Full Moon Arrow Code (default: up arrow)
input uchar NewMoonArrow = 234;           // New Moon Arrow Code (default: down arrow)
input int ArrowSize = 2;                  // Arrow Size
input int TextDistance = 10;              // Text Distance (in points)

// Arrays to store moon phase dates and times
datetime fullMoonDates[];
datetime newMoonDates[];
string fullMoonLabels[];
string newMoonLabels[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                           |
//+------------------------------------------------------------------+
int OnInit()
{
    // Initialize arrays with moon phase data
    int fullMoonCount = 25;  // Number of full moons for 2024-2025
    int newMoonCount = 25;   // Number of new moons for 2024-2025
    
    ArrayResize(fullMoonDates, fullMoonCount);
    ArrayResize(newMoonDates, newMoonCount);
    ArrayResize(fullMoonLabels, fullMoonCount);
    ArrayResize(newMoonLabels, newMoonCount);
    
    // Full Moon dates and times for 2024-2025
    fullMoonDates[0] = StringToTime("2024.01.25 17:54");
    fullMoonDates[1] = StringToTime("2024.02.24 12:30");
    fullMoonDates[2] = StringToTime("2024.03.25 07:00");
    fullMoonDates[3] = StringToTime("2024.04.23 23:49");
    fullMoonDates[4] = StringToTime("2024.05.23 13:53");
    fullMoonDates[5] = StringToTime("2024.06.22 01:08");
    fullMoonDates[6] = StringToTime("2024.07.21 10:17");
    fullMoonDates[7] = StringToTime("2024.08.19 18:26");
    fullMoonDates[8] = StringToTime("2024.09.18 02:34");
    fullMoonDates[9] = StringToTime("2024.10.17 11:26");
    fullMoonDates[10] = StringToTime("2024.11.15 21:28");
    fullMoonDates[11] = StringToTime("2024.12.15 09:02");
    fullMoonDates[12] = StringToTime("2025.01.13 22:27");
    fullMoonDates[13] = StringToTime("2025.02.12 13:54");
    fullMoonDates[14] = StringToTime("2025.03.14 06:55");
    fullMoonDates[15] = StringToTime("2025.04.13 00:22");
    fullMoonDates[16] = StringToTime("2025.05.12 16:56");
    fullMoonDates[17] = StringToTime("2025.06.11 07:43");
    fullMoonDates[18] = StringToTime("2025.07.10 20:37");
    fullMoonDates[19] = StringToTime("2025.08.09 07:55");
    fullMoonDates[20] = StringToTime("2025.09.07 18:08");
    fullMoonDates[21] = StringToTime("2025.10.07 03:48");
    fullMoonDates[22] = StringToTime("2025.11.05 13:19");
    fullMoonDates[23] = StringToTime("2025.12.04 23:14");
    fullMoonDates[24] = StringToTime("2025.12.31 10:27");
    
    // New Moon dates and times for 2024-2025
    newMoonDates[0] = StringToTime("2024.01.11 11:57");
    newMoonDates[1] = StringToTime("2024.02.09 22:59");
    newMoonDates[2] = StringToTime("2024.03.10 09:00");
    newMoonDates[3] = StringToTime("2024.04.08 18:21");
    newMoonDates[4] = StringToTime("2024.05.08 03:22");
    newMoonDates[5] = StringToTime("2024.06.06 12:38");
    newMoonDates[6] = StringToTime("2024.07.05 22:57");
    newMoonDates[7] = StringToTime("2024.08.04 11:13");
    newMoonDates[8] = StringToTime("2024.09.03 01:55");
    newMoonDates[9] = StringToTime("2024.10.02 18:49");
    newMoonDates[10] = StringToTime("2024.11.01 12:47");
    newMoonDates[11] = StringToTime("2024.12.01 06:21");
    newMoonDates[12] = StringToTime("2025.01.29 15:37");
    newMoonDates[13] = StringToTime("2025.02.28 03:44");
    newMoonDates[14] = StringToTime("2025.03.29 18:57");
    newMoonDates[15] = StringToTime("2025.04.28 12:31");
    newMoonDates[16] = StringToTime("2025.05.28 07:02");
    newMoonDates[17] = StringToTime("2025.06.27 01:42");
    newMoonDates[18] = StringToTime("2025.07.26 19:12");
    newMoonDates[19] = StringToTime("2025.08.25 10:53");
    newMoonDates[20] = StringToTime("2025.09.24 00:55");
    newMoonDates[21] = StringToTime("2025.10.23 13:26");
    newMoonDates[22] = StringToTime("2025.11.22 00:48");
    newMoonDates[23] = StringToTime("2025.12.21 11:45");
    newMoonDates[24] = StringToTime("2025.12.31 10:27");
    
    // Create labels for each moon phase within the date range
    for(int i = 0; i < fullMoonCount; i++)
    {
        if(fullMoonDates[i] >= StartDate && fullMoonDates[i] <= EndDate)
        {
            double price = iHigh(NULL, 0, iBarShift(NULL, 0, fullMoonDates[i]));
            
            fullMoonLabels[i] = "FullMoon_" + IntegerToString(i);
            ObjectCreate(0, fullMoonLabels[i], OBJ_ARROW, 0, fullMoonDates[i], price);
            ObjectSetInteger(0, fullMoonLabels[i], OBJPROP_ARROWCODE, FullMoonArrow);
            ObjectSetInteger(0, fullMoonLabels[i], OBJPROP_COLOR, FullMoonColor);
            ObjectSetInteger(0, fullMoonLabels[i], OBJPROP_WIDTH, ArrowSize);
            ObjectSetInteger(0, fullMoonLabels[i], OBJPROP_STYLE, STYLE_SOLID);
            ObjectSetInteger(0, fullMoonLabels[i], OBJPROP_SELECTABLE, false);
            ObjectSetInteger(0, fullMoonLabels[i], OBJPROP_HIDDEN, true);
            
            string textLabel = fullMoonLabels[i] + "_text";
            ObjectCreate(0, textLabel, OBJ_TEXT, 0, fullMoonDates[i], price + (TextDistance * Point));
            ObjectSetString(0, textLabel, OBJPROP_TEXT, "Full Moon\n" + TimeToString(fullMoonDates[i], TIME_DATE|TIME_MINUTES));
            ObjectSetString(0, textLabel, OBJPROP_FONT, FontName);
            ObjectSetInteger(0, textLabel, OBJPROP_FONTSIZE, FontSize);
            ObjectSetInteger(0, textLabel, OBJPROP_COLOR, FullMoonTextColor);
            ObjectSetInteger(0, textLabel, OBJPROP_ANCHOR, ANCHOR_BOTTOM);
            ObjectSetInteger(0, textLabel, OBJPROP_SELECTABLE, false);
            ObjectSetInteger(0, textLabel, OBJPROP_HIDDEN, true);
        }
    }
    
    for(int i = 0; i < newMoonCount; i++)
    {
        if(newMoonDates[i] >= StartDate && newMoonDates[i] <= EndDate)
        {
            double price = iLow(NULL, 0, iBarShift(NULL, 0, newMoonDates[i]));
            
            newMoonLabels[i] = "NewMoon_" + IntegerToString(i);
            ObjectCreate(0, newMoonLabels[i], OBJ_ARROW, 0, newMoonDates[i], price);
            ObjectSetInteger(0, newMoonLabels[i], OBJPROP_ARROWCODE, NewMoonArrow);
            ObjectSetInteger(0, newMoonLabels[i], OBJPROP_COLOR, NewMoonColor);
            ObjectSetInteger(0, newMoonLabels[i], OBJPROP_WIDTH, ArrowSize);
            ObjectSetInteger(0, newMoonLabels[i], OBJPROP_STYLE, STYLE_SOLID);
            ObjectSetInteger(0, newMoonLabels[i], OBJPROP_SELECTABLE, false);
            ObjectSetInteger(0, newMoonLabels[i], OBJPROP_HIDDEN, true);
            
            string textLabel = newMoonLabels[i] + "_text";
            ObjectCreate(0, textLabel, OBJ_TEXT, 0, newMoonDates[i], price - (TextDistance * Point));
            ObjectSetString(0, textLabel, OBJPROP_TEXT, "New Moon\n" + TimeToString(newMoonDates[i], TIME_DATE|TIME_MINUTES));
            ObjectSetString(0, textLabel, OBJPROP_FONT, FontName);
            ObjectSetInteger(0, textLabel, OBJPROP_FONTSIZE, FontSize);
            ObjectSetInteger(0, textLabel, OBJPROP_COLOR, NewMoonTextColor);
            ObjectSetInteger(0, textLabel, OBJPROP_ANCHOR, ANCHOR_TOP);
            ObjectSetInteger(0, textLabel, OBJPROP_SELECTABLE, false);
            ObjectSetInteger(0, textLabel, OBJPROP_HIDDEN, true);
        }
    }
    
    ChartRedraw();
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                         |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    // Remove all objects created by the indicator
    ObjectsDeleteAll(0, "FullMoon_");
    ObjectsDeleteAll(0, "NewMoon_");
}

//+------------------------------------------------------------------+
//| 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[])
{
    return(rates_total);
}