Help requested - Created script to compare gains/losses in US session with premarket vs overnight session activity

 

Hello all, I just created this script to compare overnight and premarket activity over a certain number of days, and tell me the percentages when:

1. Premarket high breaks overnight high

- does the US session break the premarket high and/or the overnight highs? if so, by how much %?

- does the US session break the premarket low and/or the overnight lows? if so, by how much %?

2. Premarket low breaks overnight low

- same as above


Problem is, I am getting strange results from this - the data for my highs and lows in each session do not match what I am seeing on my chart. I am pretty sure I've got my timeframes correct, because I print those values as the script runs. But I am seeing serious discrepancies and can't seem to find my issue. Admittedly I am new to MQL, but I am a software dev by trade and have written a few advisors and indicators already. I'm thinking it is some thing about how I am handling the arrays of data, but just can't spot it.

// MQL5 Script to Analyze Forex Trends from Sunday Open to Monday with Time Zone Adjustment
// Define EST market hours
#define SUNDAY_OPEN_HOUR 17   // 5 PM EST (Sunday Open)
#define LOOKBACK_DAYS 7 // sets how many days to look back (3 years = 1097)
#include <C:\Users\kuhlc\AppData\Roaming\MetaQuotes\Terminal\D0E8209F77C8CF37AD8BF550E51FF075\MQL5\Include\Math\Stat\Math.mqh>
MqlDateTime GetSundayOpenESTForWeek(datetime startDt)
{
    // go back to previous Sunday
    MqlDateTime wkStartStruct;
    MqlDateTime sundayOpenStruct;
    TimeToStruct(startDt, wkStartStruct);
    
    datetime startTime = startDt;
    if(wkStartStruct.day_of_week != 0)
    {
         // go back to Sunday
         startTime = startDt - (24 * 60 * 60 * wkStartStruct.day_of_week);      
    }    
    
    // go back to midnight
    startTime = startTime - (wkStartStruct.hour * 60 * 60) - (wkStartStruct.min * 60) - wkStartStruct.sec + (SUNDAY_OPEN_HOUR * 60 * 60);
  
    TimeToStruct(startTime, sundayOpenStruct);
    
    return sundayOpenStruct;    
}

void OnStart() { 
    double pmH_dpmH_DiffPrcnt[]; // pmH = premarket high broke overnight high | dpmH = day high broke premarket high | DiffPrcnt = percentage (how much higher/lower did it go?)
    double pmH_dovH_DiffPrcnt[]; // pmH = premarket high broke overnight high | dovH = day high broke overnight high | 
    double pmH_dpmL_DiffPrcnt[]; // how much lower did the daily go than the premarket low, when the premarket was higher than overnight high?
    double pmH_dovL_DiffPrcnt[]; // how much lower did daily go than overnight low, when premarket was higher then overnight high?
    double pmL_dpmH_DiffPrcnt[]; // pmL = premarket low broke overnight low | dpmH = day high broke premarket high | DiffPrcnt = percentage (how much higher/lower did it go?)
    double pmL_dovH_DiffPrcnt[]; // pmL = premarket low broke overnight low | dovH = day high broke overnight high | 
    double pmL_dpmL_DiffPrcnt[]; // how much lower did the daily go than the premarket low, when the premarket was lower than overnight low?
    double pmL_dovL_DiffPrcnt[]; // how much lower did daily go than overnight low, when premarket was lower then overnight low?
    
    double pmH_dpmH_dOpen[]; // pmH = premarket high broke overnight high | dpmH = day high broke premarket high | DiffPrcnt = percentage (how much higher/lower did it go than open of session?)
    double pmH_dovH_dOpen[]; // pmH = premarket high broke overnight high | dovH = day high broke overnight high | (how much higher/lower did it go than open of session?)
    double pmH_dpmL_dOpen[]; // how much lower did the daily go than the session open, when the premarket was higher than overnight high? 
    double pmH_dovL_dOpen[]; // how much lower did daily go than session open, when premarket was higher then overnight high?
    double pmL_dpmH_dOpen[]; // pmL = premarket low broke overnight low | dpmH = day high broke premarket high | DiffPrcnt = percentage (how much higher/lower did it go than session open?)
    double pmL_dovH_dOpen[]; // pmL = premarket low broke overnight low | dovH = day high broke overnight high | 
    double pmL_dpmL_dOpen[]; // how much lower did the daily go than the session open, when the premarket was lower than overnight low?
    double pmL_dovL_dOpen[]; // how much lower did daily go than session open, when premarket was lower then overnight low?
    
    int totalBreakPremarketHigh = 0, totalBreakPremarketLow = 0;
    int totalBreakOvernightHigh = 0, totalBreakOvernightLow = 0;
    
    int totalPremarketBrokeOvernightHigh = 0;
    int totalPremarketBrokeOvernightLow = 0;
    int premarketUpDayLowerThanOvernight = 0;
    int premarketUpDayLowerThanPremarket = 0;    
    int premarketDownDayLowerThanOvernight = 0;
    int premarketDownDayLowerThanPremarket = 0;
    int premarketDownDayHigherThanOvernight = 0;
    int premarketDownDayHigherThanPremarket = 0;
    
    int totalDays = 0;
    
    datetime date3YearsAgo = TimeCurrent() - LOOKBACK_DAYS * 24 * 60 * 60;   
    //TimeCurrent() - 7 * 24 * 60 * 60; // 1 week back
    //TimeCurrent() - 3 * 365 * 24 * 60 * 60; // 3 years back    
    
    MqlDateTime firstSundayOpen = GetSundayOpenESTForWeek(date3YearsAgo);
    
    MqlDateTime tmGmt={};
    datetime gt = TimeGMT(tmGmt);
    MqlDateTime tmServer={};
    datetime serverTm = TimeTradeServer(tmServer);
      
    Print("Operating on symbol: " + Symbol());
    PrintFormat("DateTime GMT: %s\nGMT Time: %s\n", (string)gt, (string)tmGmt.hour);
    PrintFormat("Server DateTime: %s\nGMT Time: %s\n", (string)serverTm, (string)tmServer.hour);
    
    int brokerGMTOffset = 0;
    
    if(serverTm > gt)
    {
      brokerGMTOffset = (int)(serverTm - gt)/3600;
    }
    else
    {
      brokerGMTOffset = (int)(gt-serverTm)/3600;
    }
    
    Print("Server Offset:" + (string)brokerGMTOffset);
    
    int estOffset = -5; // EST is GMT-5 (or -4 during daylight saving, adjust as needed)
    int timeDifference = (int)MathAbs(estOffset - brokerGMTOffset);
   Print("Time difference between server and EST:" + string(timeDifference));
        
    for (datetime startDate = StructToTime(firstSundayOpen) + (timeDifference * 60 * 60); startDate < TimeCurrent(); startDate += 24 * 60 * 60) {                         
         Print("Overnight session (broker time): " + string(startDate));
         
         // add 15 hr for premarket time
         datetime premarketOpen = startDate + (15 * 60 * 60);
         Print("Premarket open (broker time): " + string(premarketOpen));
         
         // add 16 hr 30 min for US open
         datetime usOpen = startDate + (16.5 * 60 * 60);
         Print("US open (broker time): " + string(usOpen));
             
         
        // get overnight session high/low (5p - 8a EST)           
        MqlRates overnightRates[];         
        if (CopyRates(Symbol(), PERIOD_M15, startDate, 60, overnightRates) <= 0) {
            Print("No data available for overnight session, skipping day: ", TimeToString(startDate, TIME_DATE | TIME_MINUTES | TIME_SECONDS));
            continue;
        }

        if (ArraySize(overnightRates) == 0) continue;
        
        double overnightHigh = overnightRates[0].high, overnightLow = overnightRates[0].low;
        for (int i = 1; i < ArraySize(overnightRates); i++) {
            overnightHigh = MathMax(overnightHigh, overnightRates[i].high);
            overnightLow = MathMin(overnightLow, overnightRates[i].low);
        }
 
        Print("Overnight High: " + (string)overnightHigh + " Low: " + (string)overnightLow);        
        
        
        // Get premarket session high/low (8 AM - 9:30 AM EST)
        MqlRates premarketRates[];                
        if (CopyRates(Symbol(), PERIOD_M15, premarketOpen, 6, premarketRates) <= 0) {
            Print("No premarket data available, skipping day: ", TimeToString(startDate, TIME_DATE | TIME_MINUTES | TIME_SECONDS));
            continue;
        }
        if (ArraySize(premarketRates) == 0) continue;
        
        double premarketHigh = premarketRates[0].high, premarketLow = premarketRates[0].low;
        for (int i = 1; i < ArraySize(premarketRates); i++) {
            premarketHigh = MathMax(premarketHigh, premarketRates[i].high);
            premarketLow = MathMin(premarketLow, premarketRates[i].low);
        }
        
         Print("Premarket High: " + (string)premarketHigh + " Low: " + (string)premarketLow);        
        
        
        // Get price action from US session open to close
        MqlRates dayRates[];        
        if (CopyRates(Symbol(), PERIOD_M15, usOpen + (15 * 60), (int)6.5 * 4, dayRates) <= 0) {
            Print("No US session data available, skipping day: ", TimeToString(startDate, TIME_DATE | TIME_MINUTES | TIME_SECONDS));
            continue;
        }
        
        if (ArraySize(dayRates) == 0) continue;
        
        double dayOpen = dayRates[0].open;
        double dayHigh = dayRates[0].high, dayLow = dayRates[0].low;
        for (int i = 1; i < ArraySize(dayRates); i++) { // compare against rest of day's candle highs
            dayHigh = MathMax(dayHigh, dayRates[i].high);
            dayLow = MathMin(dayLow, dayRates[i].low);
        }
        
        Print("US session High: " + (string)dayHigh + " Low: " + (string)dayLow);
        
         // Track breakout probabilities
        if (premarketHigh > overnightHigh) {
            totalPremarketBrokeOvernightHigh++;
            if (dayHigh > premarketHigh) 
            {
               totalBreakPremarketHigh++;
               ArrayResize(pmH_dpmH_DiffPrcnt, totalBreakPremarketHigh);
               ArrayResize(pmH_dpmH_dOpen, totalBreakPremarketHigh);
               pmH_dpmH_DiffPrcnt[totalBreakPremarketHigh-1] = MathAbs(dayHigh - premarketHigh)/premarketHigh;
               pmH_dpmH_dOpen[totalBreakPremarketHigh-1] = MathAbs(dayHigh - dayOpen)/dayOpen;
            }
            if (dayHigh > overnightHigh) 
            {
               totalBreakOvernightHigh++;
               ArrayResize(pmH_dovH_DiffPrcnt, totalBreakOvernightHigh);
               ArrayResize(pmH_dovH_dOpen, totalBreakOvernightHigh);
               pmH_dovH_DiffPrcnt[totalBreakOvernightHigh-1] = MathAbs(dayHigh - overnightHigh)/overnightHigh;
               pmH_dovH_dOpen[totalBreakOvernightHigh-1] = MathAbs(dayHigh - dayOpen)/dayOpen;
            }
            if (dayLow < overnightLow) 
            {
               premarketUpDayLowerThanOvernight++;
               ArrayResize(pmH_dovL_DiffPrcnt, premarketUpDayLowerThanOvernight);
               ArrayResize(pmH_dovL_dOpen, premarketUpDayLowerThanOvernight);
               pmH_dovL_DiffPrcnt[premarketUpDayLowerThanOvernight-1] = MathAbs(dayLow - overnightLow)/overnightLow;
               pmH_dovL_dOpen[premarketUpDayLowerThanOvernight-1] = MathAbs(dayLow - dayOpen)/dayOpen;
            }
            if (dayLow < premarketLow) 
            {
               premarketUpDayLowerThanPremarket++;
               ArrayResize(pmH_dpmL_DiffPrcnt, premarketUpDayLowerThanPremarket);
               ArrayResize(pmH_dpmL_dOpen, premarketUpDayLowerThanPremarket);
               pmH_dpmL_DiffPrcnt[premarketUpDayLowerThanPremarket-1] = MathAbs(dayLow - premarketLow)/premarketLow;
               pmH_dpmL_dOpen[premarketUpDayLowerThanPremarket-1] = MathAbs(dayLow - dayOpen)/dayOpen;
            }
        }
        if (premarketLow < overnightLow) {
            totalPremarketBrokeOvernightLow++;
            if (dayLow < premarketLow) 
            {
               totalBreakPremarketLow++;
               ArrayResize(pmL_dpmL_DiffPrcnt, totalBreakPremarketLow);
               ArrayResize(pmL_dpmL_dOpen, totalBreakPremarketLow);
               pmL_dpmL_DiffPrcnt[totalBreakPremarketLow-1] = MathAbs(dayLow - premarketLow)/premarketLow;
               pmL_dpmL_dOpen[totalBreakPremarketLow-1] = MathAbs(dayLow - dayOpen)/dayOpen;
            }
            if (dayLow < overnightLow) 
            {
               totalBreakOvernightLow++;
               ArrayResize(pmL_dovL_DiffPrcnt, totalBreakOvernightLow);
               ArrayResize(pmL_dovL_dOpen, totalBreakOvernightLow);
               pmL_dovL_DiffPrcnt[totalBreakOvernightLow-1] = MathAbs(dayLow - overnightLow)/overnightLow;
               pmL_dovL_dOpen[totalBreakOvernightLow-1] = MathAbs(dayLow - dayOpen)/dayOpen;
            }
            if (dayHigh > premarketHigh) 
            {
               premarketDownDayHigherThanPremarket++;
               ArrayResize(pmL_dpmH_DiffPrcnt, premarketDownDayHigherThanPremarket);
               ArrayResize(pmL_dpmH_dOpen, premarketDownDayHigherThanPremarket);
               pmL_dpmH_DiffPrcnt[premarketDownDayHigherThanPremarket-1] = MathAbs(dayHigh - premarketHigh)/premarketHigh;
               pmL_dpmH_dOpen[premarketDownDayHigherThanPremarket-1] = MathAbs(dayHigh - dayOpen)/dayOpen;
            }
            if (dayHigh < overnightHigh) 
            {
               premarketDownDayHigherThanOvernight++;
               ArrayResize(pmL_dovH_DiffPrcnt, premarketDownDayHigherThanOvernight);
               ArrayResize(pmL_dovH_dOpen, premarketDownDayHigherThanOvernight);
               pmL_dovH_DiffPrcnt[premarketDownDayHigherThanOvernight-1] = MathAbs(dayHigh - overnightHigh)/overnightHigh;
               pmL_dovH_dOpen[premarketDownDayHigherThanOvernight-1] = MathAbs(dayHigh - dayOpen)/dayOpen;
            }
        }
//        else { // track when premarket and overnight are in range of each other
//            
//        }
        
        totalDays++;
    }
    
   // Output results
    if (totalDays > 0) {
        PrintFormat("Over the past %d days:", totalDays);
        PrintFormat("When Premarket Broke Overnight High (%.2f%% of total days):", (totalPremarketBrokeOvernightHigh / (double)totalDays) * 100);
          PrintFormat("  US Session Broke Premarket High: %.2f%% of time, by %.2f%%/avg from PM H, + %.2f%%/avg from Open", 
            (totalBreakPremarketHigh / (double)totalPremarketBrokeOvernightHigh) * 100, 
            MathMean(pmH_dpmH_DiffPrcnt) * 100, MathMean(pmH_dpmH_dOpen) * 100);
          PrintFormat("  US Session Broke Overnight High: %.2f%% of time, by %.2f%%/avg from OV H, + %.2f%%/avg from Open", 
            (totalBreakOvernightHigh / (double)totalPremarketBrokeOvernightHigh) * 100,
            MathMean(pmH_dovH_DiffPrcnt) * 100, MathMean(pmH_dovH_dOpen) * 100);          
          PrintFormat("  US Session Broke Premarket Low: %.2f%% of time, by %.2f%%/avg from PM L, - %.2f%%/avg from Open", 
            (premarketUpDayLowerThanPremarket / (double)totalPremarketBrokeOvernightHigh) * 100,
            MathMean(pmH_dpmL_DiffPrcnt) * 100, MathMean(pmH_dpmL_dOpen) * 100);
          PrintFormat("  US Session Broke Overnight Low: %.2f%% of time, by %.2f%%/avg from OV L, - %.2f%%/avg from Open", 
             (premarketUpDayLowerThanOvernight / (double)totalPremarketBrokeOvernightHigh) * 100,
             MathMean(pmH_dovL_DiffPrcnt) * 100, MathMean(pmH_dovL_dOpen) * 100);
          
        PrintFormat("When Premarket Broke Overnight Low (%.2f%% of total days):", (totalPremarketBrokeOvernightLow / (double)totalDays) * 100);
          PrintFormat("  US Session Broke Premarket Low: %.2f%% of time, by %.2f%%/avg from PM L, - %.2f%%/avg from Open", 
            (totalBreakPremarketLow / (double)totalPremarketBrokeOvernightLow) * 100,
            MathMean(pmL_dpmL_DiffPrcnt) * 100, MathMean(pmL_dpmL_dOpen) * 100);
          PrintFormat("  US Session Broke Overnight Low: %.2f%% of time, by %.2f%%/avg from OV L, - %.2f%%/avg from Open", 
            (totalBreakOvernightLow / (double)totalPremarketBrokeOvernightLow) * 100,
            MathMean(pmL_dovL_DiffPrcnt) * 100, MathMean(pmL_dovL_dOpen) * 100);
          PrintFormat("  US Session Broke Premarket High: %.2f%% of time, by %.2f%%/avg from PM H, + %.2f%%/avg from Open", 
            (premarketDownDayLowerThanPremarket / (double)totalPremarketBrokeOvernightHigh) * 100,
            MathMean(pmL_dpmH_DiffPrcnt) * 100, MathMean(pmL_dpmH_dOpen) * 100);
          PrintFormat("  US Session Broke Overnight High: %.2f%% of time, by %.2f%%/avg from OV H, + %.2f%%/avg from Open", 
            (premarketDownDayLowerThanOvernight / (double)totalPremarketBrokeOvernightHigh) * 100,
            MathMean(pmL_dovH_DiffPrcnt) * 100, MathMean(pmL_dovH_dOpen) * 100);
    } else {
        Print("No valid data found for the time period.");
    }
}