Files
MQL5Data/Indicators/x-fses.mq5
T
2025-05-05 12:16:36 +03:30

286 lines
12 KiB
Plaintext

//+------------------------------------------------------------------+
//| ForexSessionDetector.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 0
#property indicator_plots 0
//+------------------------------------------------------------------+
//| Session Times |
//+------------------------------------------------------------------+
input color SydneyColor = clrRoyalBlue; // Sydney session color
input color TokyoColor = clrGreen; // Tokyo session color
input color LondonColor = clrRed; // London session color
input color NewYorkColor = clrDodgerBlue; // New York session color
input int TextSize = 8; // Font size
input bool ShowHighLow = true; // Show High/Low prices
input bool ShowSessionTimes = true; // Show Session Times
//+------------------------------------------------------------------+
//| Global Variables |
//+------------------------------------------------------------------+
struct SessionInfo
{
string name;
int startHour;
int startMinute;
int endHour;
int endMinute;
color clr;
datetime sessionStart;
datetime sessionEnd;
double high;
double low;
bool active;
};
SessionInfo sessions[4];
string fontFace = "Arial";
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Initialize session information
sessions[0].name = "Sydney";
sessions[0].startHour = 22;
sessions[0].startMinute = 0;
sessions[0].endHour = 6;
sessions[0].endMinute = 0;
sessions[0].clr = SydneyColor;
sessions[1].name = "Tokyo";
sessions[1].startHour = 0;
sessions[1].startMinute = 0;
sessions[1].endHour = 9;
sessions[1].endMinute = 0;
sessions[1].clr = TokyoColor;
sessions[2].name = "London";
sessions[2].startHour = 8;
sessions[2].startMinute = 0;
sessions[2].endHour = 17;
sessions[2].endMinute = 0;
sessions[2].clr = LondonColor;
sessions[3].name = "New York";
sessions[3].startHour = 13;
sessions[3].startMinute = 0;
sessions[3].endHour = 22;
sessions[3].endMinute = 0;
sessions[3].clr = NewYorkColor;
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[])
{
// Clear previous objects
ObjectsDeleteAll(0, "Session_");
// Process each session
for (int i = 0; i < 4; i++)
{
ProcessSession(i, time, high, low, rates_total);
}
return (rates_total);
}
//+------------------------------------------------------------------+
//| Process a single session |
//+------------------------------------------------------------------+
void ProcessSession(int sessionIndex, const datetime &time[], const double &high[], const double &low[], int rates_total)
{
SessionInfo session = sessions[sessionIndex];
// Find current session start and end times
datetime currentTime = TimeCurrent();
MqlDateTime currentTimeStruct;
TimeToStruct(currentTime, currentTimeStruct);
datetime sessionStart, sessionEnd;
// Handle sessions that span midnight
if (session.startHour > session.endHour)
{
// Session spans midnight (e.g., Sydney 22:00-6:00)
if (currentTimeStruct.hour >= session.startHour || currentTimeStruct.hour < session.endHour)
{
sessionStart = StructToTime(currentTimeStruct.year, currentTimeStruct.mon, currentTimeStruct.day, session.startHour, session.startMinute, 0);
if (currentTimeStruct.hour < session.startHour)
sessionStart -= 86400; // Previous day
sessionEnd = sessionStart + (session.endHour - session.startHour) * 3600 + (session.endMinute - session.startMinute) * 60;
if (sessionEnd <= sessionStart)
sessionEnd += 86400;
session.active = true;
}
else
{
sessionStart = StructToTime(currentTimeStruct.year, currentTimeStruct.mon, currentTimeStruct.day, session.startHour, session.startMinute, 0);
sessionEnd = sessionStart + (session.endHour - session.startHour) * 3600 + (session.endMinute - session.startMinute) * 60;
if (sessionEnd <= sessionStart)
sessionEnd += 86400;
session.active = false;
}
}
else
{
// Normal session (doesn't span midnight)
if (currentTimeStruct.hour >= session.startHour && currentTimeStruct.hour < session.endHour)
{
sessionStart = StructToTime(currentTimeStruct.year, currentTimeStruct.mon, currentTimeStruct.day, session.startHour, session.startMinute, 0);
sessionEnd = StructToTime(currentTimeStruct.year, currentTimeStruct.mon, currentTimeStruct.day, session.endHour, session.endMinute, 0);
session.active = true;
}
else
{
sessionStart = StructToTime(currentTimeStruct.year, currentTimeStruct.mon, currentTimeStruct.day, session.startHour, session.startMinute, 0);
sessionEnd = StructToTime(currentTimeStruct.year, currentTimeStruct.mon, currentTimeStruct.day, session.endHour, session.endMinute, 0);
session.active = false;
}
}
session.sessionStart = sessionStart;
session.sessionEnd = sessionEnd;
// Find high/low for the session
int startIndex = iBarShift(NULL, 0, sessionStart);
int endIndex = iBarShift(NULL, 0, sessionEnd);
if (startIndex == -1 || endIndex == -1)
return;
session.high = high[ArrayMaximum(high, endIndex, startIndex - endIndex + 1)];
session.low = low[ArrayMinimum(low, endIndex, startIndex - endIndex + 1)];
// Draw session information on chart
DrawSessionInfo(session, startIndex, endIndex, sessionIndex);
}
//+------------------------------------------------------------------+
//| Get chart window price max |
//+------------------------------------------------------------------+
double GetWindowPriceMax()
{
double maxPrice;
ChartGetDouble(0, CHART_PRICE_MAX, 0, maxPrice);
return maxPrice;
}
//+------------------------------------------------------------------+
//| Get chart window price min |
//+------------------------------------------------------------------+
double GetWindowPriceMin()
{
double minPrice;
ChartGetDouble(0, CHART_PRICE_MIN, 0, minPrice);
return minPrice;
}
//+------------------------------------------------------------------+
//| Draw session information on chart |
//+------------------------------------------------------------------+
void DrawSessionInfo(SessionInfo &session, int startIndex, int endIndex, int sessionIndex)
{
string objName;
color textColor = session.clr;
double priceMax = GetWindowPriceMax();
double priceMin = GetWindowPriceMin();
// Draw vertical lines for session start/end
objName = "Session_" + session.name + "_Start";
ObjectCreate(0, objName, OBJ_VLINE, 0, session.sessionStart, 0);
ObjectSetInteger(0, objName, OBJPROP_COLOR, session.clr);
ObjectSetInteger(0, objName, OBJPROP_STYLE, STYLE_DOT);
ObjectSetInteger(0, objName, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, objName, OBJPROP_BACK, true);
objName = "Session_" + session.name + "_End";
ObjectCreate(0, objName, OBJ_VLINE, 0, session.sessionEnd, 0);
ObjectSetInteger(0, objName, OBJPROP_COLOR, session.clr);
ObjectSetInteger(0, objName, OBJPROP_STYLE, STYLE_DOT);
ObjectSetInteger(0, objName, OBJPROP_WIDTH, 1);
ObjectSetInteger(0, objName, OBJPROP_BACK, true);
// Draw session name label
if (ShowSessionTimes)
{
objName = "Session_" + session.name + "_Label";
ObjectCreate(0, objName, OBJ_TEXT, 0, session.sessionStart, priceMax - (priceMax - priceMin) * 0.1 * (sessionIndex + 1));
ObjectSetString(0, objName, OBJPROP_TEXT, session.name + " " + TimeToString(session.sessionStart, TIME_MINUTES) + " - " + TimeToString(session.sessionEnd, TIME_MINUTES));
ObjectSetInteger(0, objName, OBJPROP_COLOR, textColor);
ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, TextSize);
ObjectSetString(0, objName, OBJPROP_FONT, fontFace);
ObjectSetInteger(0, objName, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
ObjectSetInteger(0, objName, OBJPROP_BACK, false);
}
// Draw high/low prices if enabled
if (ShowHighLow)
{
objName = "Session_" + session.name + "_High";
ObjectCreate(0, objName, OBJ_TEXT, 0, session.sessionStart + (session.sessionEnd - session.sessionStart) / 2, session.high);
ObjectSetString(0, objName, OBJPROP_TEXT, "H: " + DoubleToString(session.high, _Digits));
ObjectSetInteger(0, objName, OBJPROP_COLOR, textColor);
ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, TextSize);
ObjectSetString(0, objName, OBJPROP_FONT, fontFace);
ObjectSetInteger(0, objName, OBJPROP_ANCHOR, ANCHOR_LOWER);
ObjectSetInteger(0, objName, OBJPROP_BACK, false);
objName = "Session_" + session.name + "_Low";
ObjectCreate(0, objName, OBJ_TEXT, 0, session.sessionStart + (session.sessionEnd - session.sessionStart) / 2, session.low);
ObjectSetString(0, objName, OBJPROP_TEXT, "L: " + DoubleToString(session.low, _Digits));
ObjectSetInteger(0, objName, OBJPROP_COLOR, textColor);
ObjectSetInteger(0, objName, OBJPROP_FONTSIZE, TextSize);
ObjectSetString(0, objName, OBJPROP_FONT, fontFace);
ObjectSetInteger(0, objName, OBJPROP_ANCHOR, ANCHOR_UPPER);
ObjectSetInteger(0, objName, OBJPROP_BACK, false);
}
// Highlight active session
if (session.active)
{
objName = "Session_" + session.name + "_Background";
ObjectCreate(0, objName, OBJ_RECTANGLE, 0, session.sessionStart, priceMax, session.sessionEnd, priceMin);
ObjectSetInteger(0, objName, OBJPROP_COLOR, session.clr);
ObjectSetInteger(0, objName, OBJPROP_BGCOLOR, session.clr);
ObjectSetInteger(0, objName, OBJPROP_BACK, true);
ObjectSetInteger(0, objName, OBJPROP_FILL, true);
ObjectSetInteger(0, objName, OBJPROP_WIDTH, 1);
}
}
//+------------------------------------------------------------------+
//| Create datetime from components |
//+------------------------------------------------------------------+
datetime StructToTime(int year, int month, int day, int hour, int minute, int second)
{
MqlDateTime mdt;
mdt.year = year;
mdt.mon = month;
mdt.day = day;
mdt.hour = hour;
mdt.min = minute;
mdt.sec = second;
return StructToTime(mdt);
}
//+------------------------------------------------------------------+