worldFxHoliday/include/worldFxHoliday.mqh
MagotMagogMegaMoney 6250769201 Update include/worldFxHoliday.mqh
Header for global bank and currency exchange holidays.

worldFxHoliday.mqh encapsulates a reusable holiday‐calendar module for MQL5, enabling scripts to load, store, and query currency‐specific holiday dates via an object‐oriented interface.

##### Core Responsibilities



Defines the *HolidayEntry* class



* Inherits from *CObject* to support cloning and integration with array/list containers
* Encapsulates three fields: currency code (m\_currency), holiday name (m\_name), and exact date (m\_date)
* Provides accessors (*Date(), Currency(), Name()*) for safe retrieval of entry data



Implements the *CHolidays* manager class



* Maintains an internal CList or *CArrayObj* of cloned *HolidayEntry* objects
* Offers *LoadHolidays()* to populate the list from a static definition or external source, computing both fixed and dynamic holidays (e.g., nth weekday events)
* Exposes *IsHoliday(datetime date, string currency)* to determine whether a given date is a holiday for a specified currency
* Leverages MQL5’s built-in *StructToTime* and *TimeToStruct* (disambiguated where necessary) to convert between datetime and structured date representations



Ensures modularity and future-proofing



* Uses include guards (#ifndef…#define…) and clearly namespaced file naming
* Integrates cleanly with other utility modules (ArrayObj, List, Object, StdLibErr) for dependency-driven extension



##### Typical Use Case



1. Include worldFxHoliday.mqh in an Expert Advisor or script.
2. Instantiate *CHolidays*, call *LoadHolidays()* at initialization.
3. On each tick or at critical decision points, invoke *IsHoliday(TimeCurrent(), "USD")* (or another currency) to determine if trading logic should respect market closures.
2025-09-06 20:22:58 +00:00

457 lines
16 KiB
MQL5

//+------------------------------------------------------------------+
//| worldFxHoliday.mqh |
//| A reusable holiday‐calendar module for MQL5 |
//| Copyright 2025, Kimar Miller |
//| https://www.AtomosMaestoso.com |
//+------------------------------------------------------------------+
#ifndef _WORLD_FX_HOLIDAY_MQH_
#define _WORLD_FX_HOLIDAY_MQH_
//--- Include necessary libraries
#include <Arrays\ArrayObj.mqh>
#include <Arrays\List.mqh>
#include <Object.mqh>
//+------------------------------------------------------------------+
//| HolidayEntry class |
//+------------------------------------------------------------------+
class HolidayEntry : public CObject
{
private:
string m_currency; // e.g. "USD"
string m_name; // e.g. "Christmas Day"
datetime m_date; // full date with correct year
public:
// initialization
void Init(const string currency_, const string name_, const datetime date_)
{
m_currency = currency_;
m_name = name_;
m_date = date_;
}
// accessors
string Currency() const { return(m_currency); }
string Name() const { return(m_name); }
datetime Date() const { return(m_date); }
// required override for CArrayObj cloning
virtual CObject* Clone() const
{
HolidayEntry* copy = new HolidayEntry();
copy.Init(m_currency, m_name, m_date);
return(copy);
}
};
//+------------------------------------------------------------------+
//| Static fixed‐date holidays: currency, MM, DD, description |
//+------------------------------------------------------------------+
static const string staticHolidays[][4] =
{
{"AUD","01","25","Australia Day"},
{"AUD","04","25","Anzac Day"},
{"AUD","12","23","Christmas Eve"},
{"AUD","12","24","Christmas Day"},
{"AUD","12","25","Boxing Day"},
{"AUD","12","25","Proclamation Day"},
{"AUD","12","30","New Year's Eve"},
{"AUD","12","31","New Year's Day"},
{"CAD","06","21","National Indigenous Peoples Day"},
{"CAD","06","22","June Day"},
{"CAD","07","01","Canada Day"},
{"CAD","09","30","National Day for Truth and Reconciliation"},
{"CAD","11","10","Remembrance Day"},
{"CAD","12","24","Christmas Day"},
{"CAD","12","25","Boxing Day"},
{"CAD","12","31","New Year's Day"},
{"CHF","01","01","Berchtolds Day"},
{"CHF","01","05","Three King's Day"},
{"CHF","02","28","Republic Day"},
{"CHF","03","19","St. Joseph's Day"},
{"CHF","05","01","May Day"},
{"CHF","06","23","Fête d'Indépendance"},
{"CHF","06","29","Saint Peter and Saint Paul"},
{"CHF","08","01","National Day"},
{"CHF","08","15","Assumption Day"},
{"CHF","11","01","All Saints' Day"},
{"CHF","12","07","Immaculate Conception Day"},
{"CHF","12","23","Christmas Eve"},
{"CHF","12","24","Christmas Day"},
{"CHF","12","25","St. Stephen's Day"},
{"CHF","12","30","New Year's Eve"},
{"CHF","12","30","Restoration Day"},
{"CHF","12","31","New Year's Day"},
{"CNY","04","05","Ching Ming Festival"},
{"CNY","05","01","Labour Day"},
{"CNY","10","01","Chinese National Day"},
{"CNY","10","02","Chinese National Day Holiday"},
{"CNY","10","03","Chinese National Day Holiday"},
{"CNY","10","04","Chinese National Day Holiday"},
{"CNY","10","05","Chinese National Day Holiday"},
{"EUR","01","05","Three King's Day"},
{"EUR","01","05","Epiphany"},
{"EUR","02","27","Andalucía Day"},
{"EUR","03","01","Balearic Day (in lieu)"},
{"EUR","03","07","International Women's Day"},
{"EUR","03","19","St. Joseph's Day"},
{"EUR","04","17","Feast of San Vicente Ferrer"},
{"EUR","04","23","Castile & León Community Day"},
{"EUR","04","23","St. George's Day"},
{"EUR","04","24","Saint Vincent the Martyr"},
{"EUR","04","25","Feast of St. Mark"},
{"EUR","04","25","Liberation Day"},
{"EUR","04","28","Sardinia's Day"},
{"EUR","05","01","Labour Day"},
{"EUR","05","02","Community Festival of Madrid"},
{"EUR","05","08","V-E Day"},
{"EUR","05","13","Saint Peter de Regalado"},
{"EUR","05","15","Feast of St. Isidro"},
{"EUR","05","17","Galician Literature Day"},
{"EUR","05","30","Canary Islands Day"},
{"EUR","05","31","Castilla-La Mancha Day"},
{"EUR","06","02","Republic Day"},
{"EUR","06","09","Day of Murcia"},
{"EUR","06","09","La Rioja Day"},
{"EUR","06","13","Feast of St. Anthony"},
{"EUR","06","24","Feast of St. John the Baptist"},
{"EUR","06","29","Saint Peter and Saint Paul"},
{"EUR","07","14","Bastille Day"},
{"EUR","07","15","Feast of St. Rosalia"},
{"EUR","07","25","St. James' Day"},
{"EUR","07","28","Day of Cantabria Institutions"},
{"EUR","08","05","Our Lady of Africa"},
{"EUR","08","15","Assumption Day"},
{"EUR","09","02","Ceuta Day"},
{"EUR","09","08","Feast of Our Lady of Victories"},
{"EUR","09","11","National Day of Catalonia"},
{"EUR","09","15","Lady of Aparecida"},
{"EUR","09","17","Day of Melilla"},
{"EUR","09","19","Feast of St. Gennaro"},
{"EUR","09","20","World Children's Day"},
{"EUR","09","24","La Mercè"},
{"EUR","10","03","German Unity Day"},
{"EUR","10","04","Feast of St. Petronius"},
{"EUR","10","12","Hispanic Day"},
{"EUR","10","13","Hispanic Day (in lieu)"},
{"EUR","10","31","Reformation Day"},
{"EUR","11","01","All Saints' Day"},
{"EUR","11","02","Feast of St. Giusto"},
{"EUR","11","08","Our Lady of the Almudena"},
{"EUR","11","09","Our Lady of the Almudena (in lieu)"},
{"EUR","11","10","Armistice Day"},
{"EUR","11","17","Repentance Day"},
{"EUR","12","02","Feast of St. Francis Xavier"},
{"EUR","12","05","Constitution Day"},
{"EUR","12","05","Feast of St. Nicholas"},
{"EUR","12","06","Constitution Day (in lieu)"},
{"EUR","12","06","Feast of St. Ambrose"},
{"EUR","12","07","Immaculate Conception Day"},
{"EUR","12","24","Christmas Day"},
{"EUR","12","25","St. Stephen's Day"},
{"EUR","12","31","New Year's Day"},
{"GBP","01","01","Day after New Year's Day"},
{"GBP","11","29","St. Andrew's Day"},
{"GBP","12","24","Christmas Day"},
{"GBP","12","25","Boxing Day"},
{"GBP","12","31","New Year's Day"},
{"JPY","02","10","National Foundation Day"},
{"JPY","02","22","The Emperor's Birthday"},
{"JPY","04","29","Showa Day"},
{"JPY","05","04","Greenery Day"},
{"JPY","05","05","Children's Day"},
{"JPY","08","11","Mountain Day"},
{"JPY","11","02","Culture Day"},
{"JPY","11","22","Labour Thanksgiving Day"},
{"JPY","12","31","New Year's Day"},
{"NZD","12","24","Christmas Day"},
{"NZD","12","25","Boxing Day"},
{"NZD","12","31","New Year's Day"},
{"USD","06","19","Juneteenth"},
{"USD","07","04","Independence Day"},
{"USD","11","10","Veterans Day"},
{"USD","12","24","Christmas Day"},
{"USD","12","31","New Year's Day"}
};
//+------------------------------------------------------------------+
//| Class to manage the holiday calendar |
//+------------------------------------------------------------------+
class CHolidays : public CObject
{
private:
CList *m_holidayList;
public:
//--- Constructor
void CHolidays()
{
m_holidayList = new CList();
if(CheckPointer(m_holidayList) == POINTER_INVALID)
{
Print("Failed to create CList instance.");
return;
}
// Populate the calendar with holidays
LoadHolidays();
}
//--- Destructor
void ~CHolidays()
{
if(CheckPointer(m_holidayList) != POINTER_INVALID)
{
// FreeAll is a method of CList that correctly deallocates all
// dynamically created objects (which inherit from CObject) in the list.
m_holidayList.Clear();
delete m_holidayList;
}
}
//+------------------------------------------------------------------+
//| LoadHolidays: populates g_holidays with correct-year dates |
//+------------------------------------------------------------------+
void LoadHolidays()
{
// clear any existing entries
m_holidayList.Clear();
// grab current year
MqlDateTime now;
TimeToStruct(TimeCurrent(), now);
// iterate fixed holidays
int total = ArraySize(staticHolidays);
for(int i = 0; i < total; i++)
{
// parse month/day
int mon = (int)StringToInteger(staticHolidays[i][1]);
int day = (int)StringToInteger(staticHolidays[i][2]);
// build full date at midnight
MqlDateTime hd = {now.year, mon, day, 0, 0, 0};
datetime dt = ::StructToTime(hd);
// create and initialize object
HolidayEntry *entry = new HolidayEntry();
entry.Init(staticHolidays[i][0], staticHolidays[i][3], dt);
// add to list (CList owns cloned objects)
m_holidayList.Add(entry);
}
}
//+------------------------------------------------------------------+
//| Checks if a given date is a holiday for a specific currency |
//+------------------------------------------------------------------+
bool IsHoliday(datetime date, string currency)
{
// Break the datetime into Y/M/D
MqlDateTime dt;
TimeToStruct(date, dt);
// Iterate by index
int total = m_holidayList.Total();
for(int i = 0; i < total; i++)
{
// GetNodeAtIndex(i) returns a CObject*
CObject *obj = m_holidayList.GetNodeAtIndex(i);
if(obj == NULL)
continue;
// MQL5 only supports C-style casts
HolidayEntry *h = (HolidayEntry*)obj;
// decompose the holiday's stored datetime
MqlDateTime hdt;
TimeToStruct(h.Date(), hdt);
// compare Y/M/D and currency
if(hdt.year == dt.year
&& hdt.mon == dt.mon
&& hdt.day == dt.day
&& h.Currency() == currency)
{
Print("Found holiday: ", h.Name(), " for ", h.Currency());
return true;
}
}
return false;
}
//+------------------------------------------------------------------+
//| Calculates the Easter date for a given year using the Gauss algorithm. |
//+------------------------------------------------------------------+
int GetEasterDay(int year)
{
int a = year % 19;
int b = year / 100;
int c = year % 100;
int d = b / 4;
int e = b % 4;
int g = (8 * b + 13) / 25;
int h = (19 * a + b - d - g + 15) % 30;
int i = c / 4;
int k = c % 4;
int L = (32 + 2 * e + 2 * i - h - k) % 7;
int m = (a + 11 * h + 22 * L) / 451;
int month = (h + L - 7 * m + 114) / 31;
int day = ((h + L - 7 * m + 114) % 31) + 1;
return (month * 100) + day;
}
//+------------------------------------------------------------------+
//| Helper to get the Nth weekday of a month |
//| CORRECTED: Now calls the built-in StructToTime with :: operator. |
//| The logic for finding the last weekday of a month is also corrected. |
//+------------------------------------------------------------------+
int GetNthWeekdayOfMonth(int year, int month, int weekday, int count)
{
// For 'last' weekday of month, count is -1
if (count == -1)
{
MqlDateTime date_struct;
date_struct.year = year;
date_struct.mon = month + 1;
date_struct.day = 1;
datetime next_month_start = ::StructToTime(date_struct);
datetime current_date = next_month_start - 1;
MqlDateTime current_struct;
while(true)
{
TimeToStruct(current_date, current_struct);
if(current_struct.day_of_week == weekday)
{
return current_struct.day;
}
current_date--;
}
}
MqlDateTime date_struct;
date_struct.year = year;
date_struct.mon = month;
date_struct.day = 1;
datetime start_date = ::StructToTime(date_struct);
MqlDateTime start_struct;
TimeToStruct(start_date, start_struct);
int day = 1;
int found_count = 0;
while(day <= 31)
{
MqlDateTime current_struct;
current_struct.year = year;
current_struct.mon = month;
current_struct.day = day;
datetime current_date = ::StructToTime(current_struct);
TimeToStruct(current_date, current_struct);
if(current_struct.mon != month)
break;
if(current_struct.day_of_week == weekday)
{
found_count++;
if(found_count == count)
{
return day;
}
}
day++;
}
return -1; // Not found
}
//+------------------------------------------------------------------+
//| Wrapper for StructToTime that takes 6 integers. |
//| CORRECTED: Now calls the built-in StructToTime with :: operator. |
//+------------------------------------------------------------------+
datetime StructToTime(int year, int month, int day, int hour, int minute, int second)
{
MqlDateTime datetime_struct;
datetime_struct.year = year;
datetime_struct.mon = month;
datetime_struct.day = day;
datetime_struct.hour = hour;
datetime_struct.min = minute;
datetime_struct.sec = second;
return ::StructToTime(datetime_struct);
}
};
//--- Global instance of the holiday calendar
CHolidays g_holidays;
#endif //WORLD_FX_HOLIDAY
/*
Header for global bank and currency exchange holidays.
worldFxHoliday.mqh encapsulates a reusable holiday‐calendar module for MQL5, enabling scripts to load, store, and query currency‐specific holiday dates via an object‐oriented interface.
##### Core Responsibilities
Defines the *HolidayEntry* class
* Inherits from *CObject* to support cloning and integration with array/list containers
* Encapsulates three fields: currency code (m\_currency), holiday name (m\_name), and exact date (m\_date)
* Provides accessors (*Date(), Currency(), Name()*) for safe retrieval of entry data
Implements the *CHolidays* manager class
* Maintains an internal CList or *CArrayObj* of cloned *HolidayEntry* objects
* Offers *LoadHolidays()* to populate the list from a static definition or external source, computing both fixed and dynamic holidays (e.g., nth weekday events)
* Exposes *IsHoliday(datetime date, string currency)* to determine whether a given date is a holiday for a specified currency
* Leverages MQL5’s built-in *StructToTime* and *TimeToStruct* (disambiguated where necessary) to convert between datetime and structured date representations
Ensures modularity and future-proofing
* Uses include guards (#ifndef…#define…) and clearly namespaced file naming
* Integrates cleanly with other utility modules (ArrayObj, List, Object, StdLibErr) for dependency-driven extension
##### Typical Use Case
1. Include worldFxHoliday.mqh in an Expert Advisor or script.
2. Instantiate *CHolidays*, call *LoadHolidays()* at initialization.
3. On each tick or at critical decision points, invoke *IsHoliday(TimeCurrent(), "USD")* (or another currency) to determine if trading logic should respect market closures.
*/