last ...
This commit is contained in:
@@ -0,0 +1,347 @@
|
|||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| ForexSessionHighLowIndicator.mq5 |
|
||||||
|
//| Copyright 2023, MetaQuotes Software Corp. |
|
||||||
|
//| https://www.metaquotes.net/ |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
#property copyright "Copyright 2023, MetaQuotes Software Corp."
|
||||||
|
#property link "https://www.metaquotes.net/"
|
||||||
|
#property version "1.00"
|
||||||
|
#property indicator_chart_window
|
||||||
|
#property indicator_buffers 8
|
||||||
|
#property indicator_plots 4
|
||||||
|
|
||||||
|
// Session times (in broker time)
|
||||||
|
input string SydneyStart = "22:00"; // Sydney session start (GMT+10 when DST)
|
||||||
|
input string SydneyEnd = "07:00"; // Sydney session end
|
||||||
|
input string TokyoStart = "00:00"; // Tokyo session start (GMT+9)
|
||||||
|
input string TokyoEnd = "09:00"; // Tokyo session end
|
||||||
|
input string LondonStart = "08:00"; // London session start (GMT+0)
|
||||||
|
input string LondonEnd = "17:00"; // London session end
|
||||||
|
input string NewYorkStart = "13:00"; // New York session start (GMT-4/5)
|
||||||
|
input string NewYorkEnd = "22:00"; // New York session end
|
||||||
|
|
||||||
|
input color SydneyColor = clrDodgerBlue; // Sydney session color
|
||||||
|
input color TokyoColor = clrMediumSeaGreen; // Tokyo session color
|
||||||
|
input color LondonColor = clrGold; // London session color
|
||||||
|
input color NewYorkColor = clrTomato; // New York session color
|
||||||
|
input int LineWidth = 1; // Line width
|
||||||
|
input bool ShowLabels = true; // Show session labels
|
||||||
|
input bool ShowHighLow = true; // Show high/low prices
|
||||||
|
|
||||||
|
// Buffers for session high/low
|
||||||
|
double SydneyHighBuffer[];
|
||||||
|
double SydneyLowBuffer[];
|
||||||
|
double TokyoHighBuffer[];
|
||||||
|
double TokyoLowBuffer[];
|
||||||
|
double LondonHighBuffer[];
|
||||||
|
double LondonLowBuffer[];
|
||||||
|
double NewYorkHighBuffer[];
|
||||||
|
double NewYorkLowBuffer[];
|
||||||
|
|
||||||
|
// Global variables
|
||||||
|
int SydneyStartHour, SydneyStartMin;
|
||||||
|
int SydneyEndHour, SydneyEndMin;
|
||||||
|
int TokyoStartHour, TokyoStartMin;
|
||||||
|
int TokyoEndHour, TokyoEndMin;
|
||||||
|
int LondonStartHour, LondonStartMin;
|
||||||
|
int LondonEndHour, LondonEndMin;
|
||||||
|
int NewYorkStartHour, NewYorkStartMin;
|
||||||
|
int NewYorkEndHour, NewYorkEndMin;
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Custom indicator initialization function |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
int OnInit()
|
||||||
|
{
|
||||||
|
// Parse session times
|
||||||
|
ParseTime(SydneyStart, SydneyStartHour, SydneyStartMin);
|
||||||
|
ParseTime(SydneyEnd, SydneyEndHour, SydneyEndMin);
|
||||||
|
ParseTime(TokyoStart, TokyoStartHour, TokyoStartMin);
|
||||||
|
ParseTime(TokyoEnd, TokyoEndHour, TokyoEndMin);
|
||||||
|
ParseTime(LondonStart, LondonStartHour, LondonStartMin);
|
||||||
|
ParseTime(LondonEnd, LondonEndHour, LondonEndMin);
|
||||||
|
ParseTime(NewYorkStart, NewYorkStartHour, NewYorkStartMin);
|
||||||
|
ParseTime(NewYorkEnd, NewYorkEndHour, NewYorkEndMin);
|
||||||
|
|
||||||
|
// Set indicator properties
|
||||||
|
SetIndexBuffer(0, SydneyHighBuffer, INDICATOR_DATA);
|
||||||
|
SetIndexBuffer(1, SydneyLowBuffer, INDICATOR_DATA);
|
||||||
|
SetIndexBuffer(2, TokyoHighBuffer, INDICATOR_DATA);
|
||||||
|
SetIndexBuffer(3, TokyoLowBuffer, INDICATOR_DATA);
|
||||||
|
SetIndexBuffer(4, LondonHighBuffer, INDICATOR_DATA);
|
||||||
|
SetIndexBuffer(5, LondonLowBuffer, INDICATOR_DATA);
|
||||||
|
SetIndexBuffer(6, NewYorkHighBuffer, INDICATOR_DATA);
|
||||||
|
SetIndexBuffer(7, NewYorkLowBuffer, INDICATOR_DATA);
|
||||||
|
|
||||||
|
// Set drawing styles
|
||||||
|
PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);
|
||||||
|
PlotIndexSetInteger(0, PLOT_LINE_COLOR, SydneyColor);
|
||||||
|
PlotIndexSetInteger(0, PLOT_LINE_WIDTH, LineWidth);
|
||||||
|
PlotIndexSetString(0, PLOT_LABEL, "Sydney High");
|
||||||
|
|
||||||
|
PlotIndexSetInteger(1, PLOT_DRAW_TYPE, DRAW_LINE);
|
||||||
|
PlotIndexSetInteger(1, PLOT_LINE_COLOR, SydneyColor);
|
||||||
|
PlotIndexSetInteger(1, PLOT_LINE_STYLE, STYLE_DOT);
|
||||||
|
PlotIndexSetInteger(1, PLOT_LINE_WIDTH, LineWidth);
|
||||||
|
PlotIndexSetString(1, PLOT_LABEL, "Sydney Low");
|
||||||
|
|
||||||
|
PlotIndexSetInteger(2, PLOT_DRAW_TYPE, DRAW_LINE);
|
||||||
|
PlotIndexSetInteger(2, PLOT_LINE_COLOR, TokyoColor);
|
||||||
|
PlotIndexSetInteger(2, PLOT_LINE_WIDTH, LineWidth);
|
||||||
|
PlotIndexSetString(2, PLOT_LABEL, "Tokyo High");
|
||||||
|
|
||||||
|
PlotIndexSetInteger(3, PLOT_DRAW_TYPE, DRAW_LINE);
|
||||||
|
PlotIndexSetInteger(3, PLOT_LINE_COLOR, TokyoColor);
|
||||||
|
PlotIndexSetInteger(3, PLOT_LINE_STYLE, STYLE_DOT);
|
||||||
|
PlotIndexSetInteger(3, PLOT_LINE_WIDTH, LineWidth);
|
||||||
|
PlotIndexSetString(3, PLOT_LABEL, "Tokyo Low");
|
||||||
|
|
||||||
|
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[])
|
||||||
|
{
|
||||||
|
// Check if we have enough data
|
||||||
|
if(rates_total < 2) return(0);
|
||||||
|
|
||||||
|
// Set all buffers to EMPTY_VALUE initially
|
||||||
|
ArrayInitialize(SydneyHighBuffer, EMPTY_VALUE);
|
||||||
|
ArrayInitialize(SydneyLowBuffer, EMPTY_VALUE);
|
||||||
|
ArrayInitialize(TokyoHighBuffer, EMPTY_VALUE);
|
||||||
|
ArrayInitialize(TokyoLowBuffer, EMPTY_VALUE);
|
||||||
|
ArrayInitialize(LondonHighBuffer, EMPTY_VALUE);
|
||||||
|
ArrayInitialize(LondonLowBuffer, EMPTY_VALUE);
|
||||||
|
ArrayInitialize(NewYorkHighBuffer, EMPTY_VALUE);
|
||||||
|
ArrayInitialize(NewYorkLowBuffer, EMPTY_VALUE);
|
||||||
|
|
||||||
|
// Calculate start position
|
||||||
|
int start = (prev_calculated == 0) ? 0 : prev_calculated - 1;
|
||||||
|
|
||||||
|
// Main calculation loop
|
||||||
|
for(int i = start; i < rates_total; i++)
|
||||||
|
{
|
||||||
|
MqlDateTime dt;
|
||||||
|
TimeToStruct(time[i], dt);
|
||||||
|
|
||||||
|
// Check if current time is within any session
|
||||||
|
bool inSydney = IsInSession(dt.hour, dt.min, SydneyStartHour, SydneyStartMin, SydneyEndHour, SydneyEndMin);
|
||||||
|
bool inTokyo = IsInSession(dt.hour, dt.min, TokyoStartHour, TokyoStartMin, TokyoEndHour, TokyoEndMin);
|
||||||
|
bool inLondon = IsInSession(dt.hour, dt.min, LondonStartHour, LondonStartMin, LondonEndHour, LondonEndMin);
|
||||||
|
bool inNewYork = IsInSession(dt.hour, dt.min, NewYorkStartHour, NewYorkStartMin, NewYorkEndHour, NewYorkEndMin);
|
||||||
|
|
||||||
|
// Find session boundaries and calculate high/low
|
||||||
|
if(inSydney)
|
||||||
|
{
|
||||||
|
CalculateSessionHighLow(i, rates_total, time, high, low, SydneyHighBuffer, SydneyLowBuffer, SydneyStartHour, SydneyStartMin, SydneyEndHour, SydneyEndMin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(inTokyo)
|
||||||
|
{
|
||||||
|
CalculateSessionHighLow(i, rates_total, time, high, low, TokyoHighBuffer, TokyoLowBuffer, TokyoStartHour, TokyoStartMin, TokyoEndHour, TokyoEndMin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(inLondon)
|
||||||
|
{
|
||||||
|
CalculateSessionHighLow(i, rates_total, time, high, low, LondonHighBuffer, LondonLowBuffer, LondonStartHour, LondonStartMin, LondonEndHour, LondonEndMin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(inNewYork)
|
||||||
|
{
|
||||||
|
CalculateSessionHighLow(i, rates_total, time, high, low, NewYorkHighBuffer, NewYorkLowBuffer, NewYorkStartHour, NewYorkStartMin, NewYorkEndHour, NewYorkEndMin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add labels if enabled
|
||||||
|
if(ShowLabels && i == rates_total - 1)
|
||||||
|
{
|
||||||
|
AddSessionLabels(time[rates_total-1], high[rates_total-1], low[rates_total-1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(rates_total);
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Parse time string into hours and minutes |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
void ParseTime(string timeStr, int &hour, int &min)
|
||||||
|
{
|
||||||
|
string parts[];
|
||||||
|
StringSplit(timeStr, ':', parts);
|
||||||
|
hour = (int)StringToInteger(parts[0]);
|
||||||
|
min = (ArraySize(parts) > 1) ? (int)StringToInteger(parts[1]) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Check if current time is within a session |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
bool IsInSession(int currentHour, int currentMin, int startHour, int startMin, int endHour, int endMin)
|
||||||
|
{
|
||||||
|
int currentTime = currentHour * 100 + currentMin;
|
||||||
|
int sessionStart = startHour * 100 + startMin;
|
||||||
|
int sessionEnd = endHour * 100 + endMin;
|
||||||
|
|
||||||
|
// Handle sessions that cross midnight
|
||||||
|
if(sessionStart > sessionEnd)
|
||||||
|
{
|
||||||
|
return(currentTime >= sessionStart || currentTime < sessionEnd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return(currentTime >= sessionStart && currentTime < sessionEnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Calculate session high and low |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
void CalculateSessionHighLow(int index, int rates_total, const datetime &time[], const double &high[], const double &low[],
|
||||||
|
double &highBuffer[], double &lowBuffer[], int startHour, int startMin, int endHour, int endMin)
|
||||||
|
{
|
||||||
|
// Find the start of the current session
|
||||||
|
MqlDateTime currentDt, sessionStartDt;
|
||||||
|
TimeToStruct(time[index], currentDt);
|
||||||
|
TimeToStruct(time[index], sessionStartDt);
|
||||||
|
|
||||||
|
sessionStartDt.hour = startHour;
|
||||||
|
sessionStartDt.min = startMin;
|
||||||
|
sessionStartDt.sec = 0;
|
||||||
|
|
||||||
|
datetime sessionStartTime = StructToTime(sessionStartDt);
|
||||||
|
|
||||||
|
// If session crosses midnight, adjust the start time
|
||||||
|
int sessionStart = startHour * 100 + startMin;
|
||||||
|
int sessionEnd = endHour * 100 + endMin;
|
||||||
|
|
||||||
|
if(sessionStart > sessionEnd)
|
||||||
|
{
|
||||||
|
// Session crosses midnight, check if we need to use previous day
|
||||||
|
int currentTime = currentDt.hour * 100 + currentDt.min;
|
||||||
|
if(currentTime < sessionEnd)
|
||||||
|
{
|
||||||
|
sessionStartTime -= 86400; // Subtract one day
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the bar index for the session start
|
||||||
|
int sessionStartIndex = iBarShift(NULL, 0, sessionStartTime);
|
||||||
|
if(sessionStartIndex < 0) sessionStartIndex = 0;
|
||||||
|
|
||||||
|
// Calculate high and low for the session
|
||||||
|
double sessionHigh = high[sessionStartIndex];
|
||||||
|
double sessionLow = low[sessionStartIndex];
|
||||||
|
|
||||||
|
for(int j = sessionStartIndex; j <= index; j++)
|
||||||
|
{
|
||||||
|
if(j >= rates_total) continue;
|
||||||
|
|
||||||
|
if(high[j] > sessionHigh) sessionHigh = high[j];
|
||||||
|
if(low[j] < sessionLow) sessionLow = low[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the values in buffers
|
||||||
|
highBuffer[index] = sessionHigh;
|
||||||
|
lowBuffer[index] = sessionLow;
|
||||||
|
|
||||||
|
// If ShowHighLow is enabled, draw the levels
|
||||||
|
if(ShowHighLow && index == rates_total - 1)
|
||||||
|
{
|
||||||
|
string sessionName = "";
|
||||||
|
color sessionClr = clrNONE;
|
||||||
|
|
||||||
|
if(startHour == SydneyStartHour && startMin == SydneyStartMin)
|
||||||
|
{
|
||||||
|
sessionName = "Sydney";
|
||||||
|
sessionClr = SydneyColor;
|
||||||
|
}
|
||||||
|
else if(startHour == TokyoStartHour && startMin == TokyoStartMin)
|
||||||
|
{
|
||||||
|
sessionName = "Tokyo";
|
||||||
|
sessionClr = TokyoColor;
|
||||||
|
}
|
||||||
|
else if(startHour == LondonStartHour && startMin == LondonStartMin)
|
||||||
|
{
|
||||||
|
sessionName = "London";
|
||||||
|
sessionClr = LondonColor;
|
||||||
|
}
|
||||||
|
else if(startHour == NewYorkStartHour && startMin == NewYorkStartMin)
|
||||||
|
{
|
||||||
|
sessionName = "NewYork";
|
||||||
|
sessionClr = NewYorkColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sessionName != "")
|
||||||
|
{
|
||||||
|
string highLabel = sessionName + " High: " + DoubleToString(sessionHigh, _Digits);
|
||||||
|
string lowLabel = sessionName + " Low: " + DoubleToString(sessionLow, _Digits);
|
||||||
|
|
||||||
|
ObjectCreate(0, highLabel, OBJ_HLINE, 0, 0, sessionHigh);
|
||||||
|
ObjectSetInteger(0, highLabel, OBJPROP_COLOR, sessionClr);
|
||||||
|
ObjectSetInteger(0, highLabel, OBJPROP_WIDTH, LineWidth);
|
||||||
|
ObjectSetInteger(0, highLabel, OBJPROP_BACK, true);
|
||||||
|
|
||||||
|
ObjectCreate(0, lowLabel, OBJ_HLINE, 0, 0, sessionLow);
|
||||||
|
ObjectSetInteger(0, lowLabel, OBJPROP_COLOR, sessionClr);
|
||||||
|
ObjectSetInteger(0, lowLabel, OBJPROP_WIDTH, LineWidth);
|
||||||
|
ObjectSetInteger(0, lowLabel, OBJPROP_STYLE, STYLE_DOT);
|
||||||
|
ObjectSetInteger(0, lowLabel, OBJPROP_BACK, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Add session labels to the chart |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
void AddSessionLabels(datetime currentTime, double currentHigh, double currentLow)
|
||||||
|
{
|
||||||
|
MqlDateTime dt;
|
||||||
|
TimeToStruct(currentTime, dt);
|
||||||
|
|
||||||
|
// Remove previous labels
|
||||||
|
ObjectsDeleteAll(0, "SessionLabel_");
|
||||||
|
|
||||||
|
if(IsInSession(dt.hour, dt.min, SydneyStartHour, SydneyStartMin, SydneyEndHour, SydneyEndMin))
|
||||||
|
{
|
||||||
|
ObjectCreate(0, "SessionLabel_Sydney", OBJ_TEXT, 0, currentTime, currentHigh + 10 * _Point);
|
||||||
|
ObjectSetString(0, "SessionLabel_Sydney", OBJPROP_TEXT, "Sydney Session");
|
||||||
|
ObjectSetInteger(0, "SessionLabel_Sydney", OBJPROP_COLOR, SydneyColor);
|
||||||
|
ObjectSetInteger(0, "SessionLabel_Sydney", OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(IsInSession(dt.hour, dt.min, TokyoStartHour, TokyoStartMin, TokyoEndHour, TokyoEndMin))
|
||||||
|
{
|
||||||
|
ObjectCreate(0, "SessionLabel_Tokyo", OBJ_TEXT, 0, currentTime, currentHigh + 20 * _Point);
|
||||||
|
ObjectSetString(0, "SessionLabel_Tokyo", OBJPROP_TEXT, "Tokyo Session");
|
||||||
|
ObjectSetInteger(0, "SessionLabel_Tokyo", OBJPROP_COLOR, TokyoColor);
|
||||||
|
ObjectSetInteger(0, "SessionLabel_Tokyo", OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(IsInSession(dt.hour, dt.min, LondonStartHour, LondonStartMin, LondonEndHour, LondonEndMin))
|
||||||
|
{
|
||||||
|
ObjectCreate(0, "SessionLabel_London", OBJ_TEXT, 0, currentTime, currentHigh + 30 * _Point);
|
||||||
|
ObjectSetString(0, "SessionLabel_London", OBJPROP_TEXT, "London Session");
|
||||||
|
ObjectSetInteger(0, "SessionLabel_London", OBJPROP_COLOR, LondonColor);
|
||||||
|
ObjectSetInteger(0, "SessionLabel_London", OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(IsInSession(dt.hour, dt.min, NewYorkStartHour, NewYorkStartMin, NewYorkEndHour, NewYorkEndMin))
|
||||||
|
{
|
||||||
|
ObjectCreate(0, "SessionLabel_NewYork", OBJ_TEXT, 0, currentTime, currentHigh + 40 * _Point);
|
||||||
|
ObjectSetString(0, "SessionLabel_NewYork", OBJPROP_TEXT, "New York Session");
|
||||||
|
ObjectSetInteger(0, "SessionLabel_NewYork", OBJPROP_COLOR, NewYorkColor);
|
||||||
|
ObjectSetInteger(0, "SessionLabel_NewYork", OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
@@ -0,0 +1,318 @@
|
|||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Forex Sessions and Day Range Indicator |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
#property copyright "Your Name"
|
||||||
|
#property link "https://www.example.com"
|
||||||
|
#property version "1.00"
|
||||||
|
#property indicator_chart_window
|
||||||
|
#property indicator_buffers 8 // 4 sessions * (High + Low)
|
||||||
|
|
||||||
|
#include "../Libraries/x-saherelm.common.lib.mq5"
|
||||||
|
#include <Arrays/ArrayObj.mqh>
|
||||||
|
|
||||||
|
// Define an enumeration for DST rules
|
||||||
|
enum DST_RULE
|
||||||
|
{
|
||||||
|
DST_SYDNEY,
|
||||||
|
DST_TOKYO,
|
||||||
|
DST_LONDON,
|
||||||
|
DST_NEW_YORK
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SessionInfo
|
||||||
|
{
|
||||||
|
string name;
|
||||||
|
int startHour; // Standard start hour (GMT)
|
||||||
|
int startMinute;
|
||||||
|
int endHour; // Standard end hour (GMT)
|
||||||
|
int endMinute;
|
||||||
|
DST_RULE dstRule; // DST rule for the session
|
||||||
|
int dstAdjustment; // Hours to add during DST
|
||||||
|
};
|
||||||
|
|
||||||
|
SessionInfo sessions[] = {
|
||||||
|
{"Sydney", 21, 0, 5, 0, DST_SYDNEY, 1},
|
||||||
|
{"Tokyo", 23, 0, 8, 0, DST_TOKYO, 0},
|
||||||
|
{"London", 7, 0, 15, 0, DST_LONDON, 1},
|
||||||
|
{"New York", 12, 0, 17, 0, DST_NEW_YORK, 1}};
|
||||||
|
|
||||||
|
double sessionHighBuffers[]; // Buffer for session highs
|
||||||
|
double sessionLowBuffers[]; // Buffer for session lows
|
||||||
|
|
||||||
|
bool sessionActive[];
|
||||||
|
double sessionHigh[];
|
||||||
|
double sessionLow[];
|
||||||
|
datetime sessionStartTime[];
|
||||||
|
datetime sessionEndTime[];
|
||||||
|
|
||||||
|
double dayHigh = 0;
|
||||||
|
double dayLow = 0;
|
||||||
|
datetime dayStartTime;
|
||||||
|
|
||||||
|
// Function to extract the year from a datetime value
|
||||||
|
int GetYear(datetime time)
|
||||||
|
{
|
||||||
|
return (int)StringSubstr(TimeToString(time, TIME_DATE), 0, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to extract the day of the month from a datetime value
|
||||||
|
int GetDay(datetime time)
|
||||||
|
{
|
||||||
|
MqlDateTime dt;
|
||||||
|
TimeToStruct(time, dt);
|
||||||
|
return dt.day;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to extract the day of the week from a datetime value (0=Sunday, 6=Saturday)
|
||||||
|
int GetDayOfWeek(datetime time)
|
||||||
|
{
|
||||||
|
MqlDateTime dt;
|
||||||
|
TimeToStruct(time, dt);
|
||||||
|
return dt.day_of_week;
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Custom indicator initialization function |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
int OnInit()
|
||||||
|
{
|
||||||
|
ArrayResize(sessionActive, ArraySize(sessions));
|
||||||
|
ArrayResize(sessionHigh, ArraySize(sessions));
|
||||||
|
ArrayResize(sessionLow, ArraySize(sessions));
|
||||||
|
ArrayResize(sessionStartTime, ArraySize(sessions));
|
||||||
|
ArrayResize(sessionEndTime, ArraySize(sessions));
|
||||||
|
|
||||||
|
for (int i = 0; i < ArraySize(sessions); i++)
|
||||||
|
{
|
||||||
|
sessionActive[i] = false;
|
||||||
|
sessionHigh[i] = 0;
|
||||||
|
sessionLow[i] = 0;
|
||||||
|
sessionStartTime[i] = 0;
|
||||||
|
sessionEndTime[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dayHigh = 0;
|
||||||
|
dayLow = 0;
|
||||||
|
dayStartTime = 0;
|
||||||
|
|
||||||
|
// Initialize buffers for session highs and lows
|
||||||
|
int totalSessions = ArraySize(sessions);
|
||||||
|
int totalBars = iBars(NULL, 0); // Get the number of bars on the chart
|
||||||
|
|
||||||
|
ArrayResize(sessionHighBuffers, totalBars); // Resize to match the number of bars
|
||||||
|
ArrayResize(sessionLowBuffers, totalBars); // Resize to match the number of bars
|
||||||
|
|
||||||
|
for (int i = 0; i < totalSessions; i++)
|
||||||
|
{
|
||||||
|
SetIndexBuffer(i * 2, sessionHighBuffers, INDICATOR_DATA);
|
||||||
|
SetIndexBuffer(i * 2 + 1, sessionLowBuffers, INDICATOR_DATA);
|
||||||
|
|
||||||
|
// Optional: Set colors for high and low buffers
|
||||||
|
PlotIndexSetInteger(i * 2, PLOT_LINE_COLOR, clrGreen);
|
||||||
|
PlotIndexSetInteger(i * 2 + 1, PLOT_LINE_COLOR, clrRed);
|
||||||
|
|
||||||
|
IndicatorSetInteger(INDICATOR_LEVELS, 0); // No predefined levels
|
||||||
|
IndicatorSetString(INDICATOR_SHORTNAME, "Forex Sessions");
|
||||||
|
}
|
||||||
|
|
||||||
|
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[])
|
||||||
|
{
|
||||||
|
// Ensure buffers are resized to match the number of bars
|
||||||
|
if (ArraySize(sessionHighBuffers) < rates_total)
|
||||||
|
{
|
||||||
|
ArrayResize(sessionHighBuffers, rates_total);
|
||||||
|
ArrayResize(sessionLowBuffers, rates_total);
|
||||||
|
}
|
||||||
|
|
||||||
|
datetime currentTime = TimeCurrent();
|
||||||
|
|
||||||
|
// Retrieve Ask and Bid prices dynamically
|
||||||
|
double askPrice = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
|
||||||
|
double bidPrice = SymbolInfoDouble(Symbol(), SYMBOL_BID);
|
||||||
|
|
||||||
|
// Check each session
|
||||||
|
for (int i = 0; i < ArraySize(sessions); i++)
|
||||||
|
{
|
||||||
|
SessionInfo session = sessions[i];
|
||||||
|
|
||||||
|
// Determine if DST is active using the session's DST rule
|
||||||
|
bool dstActive = IsDSTActive(session.dstRule, currentTime);
|
||||||
|
int adjStartHour = session.startHour + (dstActive ? session.dstAdjustment : 0);
|
||||||
|
int adjEndHour = session.endHour + (dstActive ? session.dstAdjustment : 0);
|
||||||
|
|
||||||
|
datetime todayStart = StringToTime(TimeToString(currentTime, TIME_DATE) + " " +
|
||||||
|
IntegerToString(adjStartHour) + ":" +
|
||||||
|
IntegerToString(session.startMinute));
|
||||||
|
datetime todayEnd = StringToTime(TimeToString(currentTime, TIME_DATE) + " " +
|
||||||
|
IntegerToString(adjEndHour) + ":" +
|
||||||
|
IntegerToString(session.endMinute));
|
||||||
|
|
||||||
|
// Handle sessions spanning midnight
|
||||||
|
if (adjEndHour < adjStartHour)
|
||||||
|
{
|
||||||
|
todayEnd += 24 * 3600;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentTime >= todayStart && currentTime < todayEnd)
|
||||||
|
{
|
||||||
|
if (!sessionActive[i])
|
||||||
|
{
|
||||||
|
sessionActive[i] = true;
|
||||||
|
sessionStartTime[i] = todayStart;
|
||||||
|
sessionEndTime[i] = todayEnd;
|
||||||
|
sessionHigh[i] = askPrice;
|
||||||
|
sessionLow[i] = bidPrice;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (askPrice > sessionHigh[i])
|
||||||
|
sessionHigh[i] = askPrice;
|
||||||
|
if (bidPrice < sessionLow[i])
|
||||||
|
sessionLow[i] = bidPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update buffers for the current bar
|
||||||
|
sessionHighBuffers[rates_total - 1] = sessionHigh[i];
|
||||||
|
sessionLowBuffers[rates_total - 1] = sessionLow[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sessionActive[i] = false;
|
||||||
|
sessionHighBuffers[rates_total - 1] = EMPTY_VALUE; // Clear buffer when session is inactive
|
||||||
|
sessionLowBuffers[rates_total - 1] = EMPTY_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check day range
|
||||||
|
bool dstActiveNY = IsDSTActive(DST_NEW_YORK, currentTime);
|
||||||
|
int dayStartHour = dstActiveNY ? 21 : 22;
|
||||||
|
datetime todayDayStart = StringToTime(TimeToString(currentTime, TIME_DATE) + " " +
|
||||||
|
IntegerToString(dayStartHour) + ":00");
|
||||||
|
|
||||||
|
if (currentTime < todayDayStart)
|
||||||
|
{
|
||||||
|
todayDayStart -= 24 * 3600;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dayStartTime != todayDayStart)
|
||||||
|
{
|
||||||
|
dayStartTime = todayDayStart;
|
||||||
|
dayHigh = askPrice;
|
||||||
|
dayLow = bidPrice;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (askPrice > dayHigh)
|
||||||
|
dayHigh = askPrice;
|
||||||
|
if (bidPrice < dayLow)
|
||||||
|
dayLow = bidPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display information on chart
|
||||||
|
string comment = "Active Forex Sessions:\n";
|
||||||
|
for (int i = 0; i < ArraySize(sessions); i++)
|
||||||
|
{
|
||||||
|
if (sessionActive[i])
|
||||||
|
{
|
||||||
|
comment += sessions[i].name + " Session\n" +
|
||||||
|
"High: " + DoubleToString(sessionHigh[i], _Digits) + "\n" +
|
||||||
|
"Low: " + DoubleToString(sessionLow[i], _Digits) + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
comment += "\nDay Range:\n" +
|
||||||
|
"High: " + DoubleToString(dayHigh, _Digits) + "\n" +
|
||||||
|
"Low: " + DoubleToString(dayLow, _Digits);
|
||||||
|
Comment(comment);
|
||||||
|
|
||||||
|
return (rates_total);
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Check if DST is active for a given session |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
bool IsDSTActive(DST_RULE dstRule, datetime time)
|
||||||
|
{
|
||||||
|
switch (dstRule)
|
||||||
|
{
|
||||||
|
case DST_SYDNEY:
|
||||||
|
return IsSydneyDST(time);
|
||||||
|
case DST_TOKYO:
|
||||||
|
return IsTokyoDST(time);
|
||||||
|
case DST_LONDON:
|
||||||
|
return IsLondonDST(time);
|
||||||
|
case DST_NEW_YORK:
|
||||||
|
return IsNewYorkDST(time);
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| DST Check Functions |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
bool IsLondonDST(datetime time)
|
||||||
|
{
|
||||||
|
int year = GetYear(time);
|
||||||
|
datetime march31 = StringToTime(ToString(year) + ".03.31 00:00");
|
||||||
|
int lastSundayMarch = GetDay(march31) - (GetDayOfWeek(march31) % 7);
|
||||||
|
datetime dstStart = StringToTime(ToString(year) + ".03." + IntegerToString(lastSundayMarch) + " 01:00");
|
||||||
|
|
||||||
|
datetime oct31 = StringToTime(ToString(year) + ".10.31 00:00");
|
||||||
|
int lastSundayOct = GetDay(oct31) - (GetDayOfWeek(oct31) % 7);
|
||||||
|
datetime dstEnd = StringToTime(ToString(year) + ".10." + IntegerToString(lastSundayOct) + " 01:00");
|
||||||
|
|
||||||
|
return time >= dstStart && time < dstEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsNewYorkDST(datetime time)
|
||||||
|
{
|
||||||
|
int year = GetYear(time);
|
||||||
|
datetime march1 = StringToTime(ToString(year) + ".03.01 00:00");
|
||||||
|
int dayOfWeekMarch1 = GetDayOfWeek(march1);
|
||||||
|
int secondSundayMarch = 1 + (7 - dayOfWeekMarch1) % 7 + 7;
|
||||||
|
datetime dstStart = StringToTime(ToString(year) + ".03." + IntegerToString(secondSundayMarch) + " 07:00");
|
||||||
|
|
||||||
|
datetime nov1 = StringToTime(ToString(year) + ".11.01 00:00");
|
||||||
|
int dayOfWeekNov1 = GetDayOfWeek(nov1);
|
||||||
|
int firstSundayNov = 1 + (7 - dayOfWeekNov1) % 7;
|
||||||
|
datetime dstEnd = StringToTime(ToString(year) + ".11." + IntegerToString(firstSundayNov) + " 06:00");
|
||||||
|
|
||||||
|
return time >= dstStart && time < dstEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsSydneyDST(datetime time)
|
||||||
|
{
|
||||||
|
int year = GetYear(time);
|
||||||
|
datetime oct1 = StringToTime(ToString(year) + ".10.01 00:00");
|
||||||
|
int dayOfWeekOct1 = GetDayOfWeek(oct1);
|
||||||
|
int firstSundayOct = 1 + (7 - dayOfWeekOct1) % 7;
|
||||||
|
datetime dstStart = StringToTime(ToString(year) + ".10." + IntegerToString(firstSundayOct) + " 13:00");
|
||||||
|
|
||||||
|
datetime apr1 = StringToTime(ToString(year) + ".04.01 00:00");
|
||||||
|
int dayOfWeekApr1 = GetDayOfWeek(apr1);
|
||||||
|
int firstSundayApr = 1 + (7 - dayOfWeekApr1) % 7;
|
||||||
|
datetime dstEnd = StringToTime(ToString(year) + ".04." + IntegerToString(firstSundayApr) + " 15:00");
|
||||||
|
|
||||||
|
return time >= dstStart && time < dstEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsTokyoDST(datetime time)
|
||||||
|
{
|
||||||
|
// Tokyo does not observe Daylight Saving Time (DST)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user