Files
MQL5Data/Documents/BKP/forex.sessions.mq5
T
2025-04-21 19:28:38 +03:30

347 lines
14 KiB
Plaintext

//+------------------------------------------------------------------+
//| 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);
}
}
//+------------------------------------------------------------------+