NUNA_FORK/Logs/Indicators/Downloads/Open Range Breakout-H-Max.mq5
2026-01-06 05:44:21 +00:00

691 行
无行尾
27 KiB
MQL5

//+------------------------------------------------------------------+
//| Open Range Breakout-H-Max.mq5 |
//| By Hieronymos Starch - Quotesy of The Nevek Ratio |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Hieronymos Starch - arete2077@gmail.com - +263785974079 "
#property link "https://www.mql5.com"
#property version "9.00"
#property indicator_chart_window
#property indicator_buffers 22
#property indicator_plots 22
// Plot buffers
#property indicator_label1 "ORB High"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrLime
#property indicator_style1 STYLE_SOLID
#property indicator_width1 2
#property indicator_label2 "ORB Low"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrRed
#property indicator_style2 STYLE_SOLID
#property indicator_width2 2
#property indicator_label3 "ORB Mid Point"
#property indicator_type3 DRAW_LINE
#property indicator_color3 clrGray
#property indicator_style3 STYLE_SOLID
#property indicator_width3 1
#property indicator_label4 "ORB High PT 0.5"
#property indicator_type4 DRAW_LINE
#property indicator_color4 clrPurple
#property indicator_style4 STYLE_SOLID
#property indicator_width4 2
#property indicator_label5 "ORB High PT 1.0"
#property indicator_type5 DRAW_LINE
#property indicator_color5 clrBlue
#property indicator_style5 STYLE_SOLID
#property indicator_width5 2
#property indicator_label6 "ORB Low PT 0.5"
#property indicator_type6 DRAW_LINE
#property indicator_color6 clrPurple
#property indicator_style6 STYLE_SOLID
#property indicator_width6 2
#property indicator_label7 "ORB Low PT 1.0"
#property indicator_type7 DRAW_LINE
#property indicator_color7 clrBlue
#property indicator_style7 STYLE_SOLID
#property indicator_width7 2
// Extended targets
#property indicator_label8 "ORB High PT 1.5"
#property indicator_type8 DRAW_LINE
#property indicator_color8 clrTeal
#property indicator_label9 "ORB High PT 2.0"
#property indicator_type9 DRAW_LINE
#property indicator_color9 clrTeal
#property indicator_label10 "ORB High PT 2.5"
#property indicator_type10 DRAW_LINE
#property indicator_color10 clrTeal
#property indicator_label11 "ORB High PT 3.0"
#property indicator_type11 DRAW_LINE
#property indicator_color11 clrTeal
#property indicator_label12 "ORB High PT 3.5"
#property indicator_type12 DRAW_LINE
#property indicator_color12 clrTeal
#property indicator_label13 "ORB High PT 4.0"
#property indicator_type13 DRAW_LINE
#property indicator_color13 clrTeal
#property indicator_label14 "ORB High PT 4.5"
#property indicator_type14 DRAW_LINE
#property indicator_color14 clrTeal
#property indicator_label15 "ORB High PT 5.0"
#property indicator_type15 DRAW_LINE
#property indicator_color15 clrTeal
#property indicator_label16 "ORB Low PT 1.5"
#property indicator_type16 DRAW_LINE
#property indicator_color16 clrTeal
#property indicator_label17 "ORB Low PT 2.0"
#property indicator_type17 DRAW_LINE
#property indicator_color17 clrTeal
#property indicator_label18 "ORB Low PT 2.5"
#property indicator_type18 DRAW_LINE
#property indicator_color18 clrTeal
#property indicator_label19 "ORB Low PT 3.0"
#property indicator_type19 DRAW_LINE
#property indicator_color19 clrTeal
#property indicator_label20 "ORB Low PT 3.5"
#property indicator_type20 DRAW_LINE
#property indicator_color20 clrTeal
#property indicator_label21 "ORB Low PT 4.0"
#property indicator_type21 DRAW_LINE
#property indicator_color21 clrTeal
#property indicator_label22 "ORB Low PT 4.5"
#property indicator_type22 DRAW_LINE
#property indicator_color22 clrTeal
// Input parameters
input string sOpeningRangeMinutes = "15"; // Period (minutes): 5,15,30,0
input bool alertBreakoutsOnly = false; // Alert only on ORB breakouts (not price ticks)
input bool showLabels = true; // Show ORB labels
input bool showPreviousDayORBs = true; // Show ORB ranges on previous days
input bool showEntries = true; // Show potential ORB Breakouts and Retests (BRB)
input bool showPriceTargets = true; // Show Default Price Targets (50%, 100%)
input bool showPriceTargetsExtended = false; // Show Extended Price Targets (150%, 200%)
input bool showMidPoint = false; // Show ORB Mid Point
input bool showShadedBox = true; // Shade the ORB Range
input color shadeColor = clrTeal; // Shaded ORB Range Color
input color orb50Color = clrPurple; // ORB 50 Price Target
input color orb100Color = clrBlue; // ORB 100 Price Target
input color orbOtherColor = clrTeal; // All Other ORB Price Targets
input string sORBStartTime = "0930-0945"; // Time Override (Format: 0930-0945)
input string sTimeZone = "EST"; // Timezone
input int labelOffsetBars = 5; // Label Horizontal Offset (bars)
input int labelOffsetPips = 0; // Label Vertical Offset (pips)
input int labelFontSize = 8; // Label Font Size
input ENUM_ANCHOR_POINT labelAnchor = ANCHOR_LEFT; // Label Anchor Point
input int maxLineBars = 500; // Maximum Line Length (bars)
// Indicator buffers
double OrbHighBuffer[];
double OrbLowBuffer[];
double OrbMidBuffer[];
double OrbHigh50Buffer[];
double OrbHigh100Buffer[];
double OrbLow50Buffer[];
double OrbLow100Buffer[];
double OrbHigh150Buffer[];
double OrbHigh200Buffer[];
double OrbHigh250Buffer[];
double OrbHigh300Buffer[];
double OrbHigh350Buffer[];
double OrbHigh400Buffer[];
double OrbHigh450Buffer[];
double OrbHigh500Buffer[];
double OrbLow150Buffer[];
double OrbLow200Buffer[];
double OrbLow250Buffer[];
double OrbLow300Buffer[];
double OrbLow350Buffer[];
double OrbLow400Buffer[];
double OrbLow450Buffer[];
// Global variables
struct ORBData {
double orbHighPrice;
double orbLowPrice;
datetime orbStartTime;
datetime orbEndTime;
bool isActive;
string boxName;
int dayOfYear;
int sessionStartBar;
int sessionEndBar;
};
ORBData currentORB;
bool inBreakout = false;
int openingRangeMinutes;
int sessionStartHour, sessionStartMin;
int sessionEndHour, sessionEndMin;
string orbTitle;
double pointMultiplier;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
openingRangeMinutes = (int)StringToInteger(sOpeningRangeMinutes);
pointMultiplier = (_Point * 10);
// Determine session times
if(openingRangeMinutes == 5)
{
sessionStartHour = 9; sessionStartMin = 30;
sessionEndHour = 9; sessionEndMin = 35;
}
else if(openingRangeMinutes == 15)
{
sessionStartHour = 9; sessionStartMin = 30;
sessionEndHour = 9; sessionEndMin = 45;
}
else if(openingRangeMinutes == 30)
{
sessionStartHour = 9; sessionStartMin = 30;
sessionEndHour = 10; sessionEndMin = 0;
}
else if(openingRangeMinutes == 0)
{
string parts[];
if(StringSplit(sORBStartTime, '-', parts) == 2)
{
string startTime = parts[0];
string endTime = parts[1];
sessionStartHour = (int)StringToInteger(StringSubstr(startTime, 0, 2));
sessionStartMin = (int)StringToInteger(StringSubstr(startTime, 2, 2));
sessionEndHour = (int)StringToInteger(StringSubstr(endTime, 0, 2));
sessionEndMin = (int)StringToInteger(StringSubstr(endTime, 2, 2));
}
}
else
{
sessionStartHour = 9; sessionStartMin = 30;
sessionEndHour = 9; sessionEndMin = 45;
}
orbTitle = "ORB" + IntegerToString(openingRangeMinutes);
// Initialize ORB data
currentORB.orbHighPrice = 0.0;
currentORB.orbLowPrice = 0.0;
currentORB.isActive = false;
currentORB.boxName = "";
currentORB.dayOfYear = 0;
currentORB.sessionStartBar = -1;
currentORB.sessionEndBar = -1;
// Set indicator buffers
SetIndexBuffer(0, OrbHighBuffer, INDICATOR_DATA);
SetIndexBuffer(1, OrbLowBuffer, INDICATOR_DATA);
SetIndexBuffer(2, OrbMidBuffer, INDICATOR_DATA);
SetIndexBuffer(3, OrbHigh50Buffer, INDICATOR_DATA);
SetIndexBuffer(4, OrbHigh100Buffer, INDICATOR_DATA);
SetIndexBuffer(5, OrbLow50Buffer, INDICATOR_DATA);
SetIndexBuffer(6, OrbLow100Buffer, INDICATOR_DATA);
SetIndexBuffer(7, OrbHigh150Buffer, INDICATOR_DATA);
SetIndexBuffer(8, OrbHigh200Buffer, INDICATOR_DATA);
SetIndexBuffer(9, OrbHigh250Buffer, INDICATOR_DATA);
SetIndexBuffer(10, OrbHigh300Buffer, INDICATOR_DATA);
SetIndexBuffer(11, OrbHigh350Buffer, INDICATOR_DATA);
SetIndexBuffer(12, OrbHigh400Buffer, INDICATOR_DATA);
SetIndexBuffer(13, OrbHigh450Buffer, INDICATOR_DATA);
SetIndexBuffer(14, OrbHigh500Buffer, INDICATOR_DATA);
SetIndexBuffer(15, OrbLow150Buffer, INDICATOR_DATA);
SetIndexBuffer(16, OrbLow200Buffer, INDICATOR_DATA);
SetIndexBuffer(17, OrbLow250Buffer, INDICATOR_DATA);
SetIndexBuffer(18, OrbLow300Buffer, INDICATOR_DATA);
SetIndexBuffer(19, OrbLow350Buffer, INDICATOR_DATA);
SetIndexBuffer(20, OrbLow400Buffer, INDICATOR_DATA);
SetIndexBuffer(21, OrbLow450Buffer, INDICATOR_DATA);
// Set colors
PlotIndexSetInteger(3, PLOT_LINE_COLOR, orb50Color);
PlotIndexSetInteger(4, PLOT_LINE_COLOR, orb100Color);
PlotIndexSetInteger(5, PLOT_LINE_COLOR, orb50Color);
PlotIndexSetInteger(6, PLOT_LINE_COLOR, orb100Color);
for(int i = 7; i < 22; i++)
PlotIndexSetInteger(i, PLOT_LINE_COLOR, orbOtherColor);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, "ORB_");
}
//+------------------------------------------------------------------+
//| 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[])
{
if(rates_total < 10) return(0);
int start = MathMax(1, prev_calculated);
if(start == 1) start = 0;
for(int i = start; i < rates_total; i++)
{
InitializeBuffers(i);
MqlDateTime dt;
TimeToStruct(time[i], dt);
bool inSession = IsInSession(dt);
bool isFirstBar = IsFirstBarOfSession(time, i, dt);
bool newDayStart = IsNewDay(time, i);
bool isToday = IsToday(time[i]);
bool drawOrbs = showPreviousDayORBs || (!showPreviousDayORBs && isToday);
// Start new ORB session
if(isFirstBar && inSession)
{
currentORB.orbHighPrice = high[i];
currentORB.orbLowPrice = low[i];
currentORB.orbStartTime = time[i];
currentORB.sessionStartBar = i;
currentORB.isActive = true;
currentORB.dayOfYear = dt.day_of_year;
inBreakout = false;
// Calculate session end time
MqlDateTime sessionEnd = dt;
sessionEnd.hour = sessionEndHour;
sessionEnd.min = sessionEndMin;
currentORB.orbEndTime = StructToTime(sessionEnd);
currentORB.boxName = "ORB_Box_" + IntegerToString(dt.day_of_year);
}
// Update ORB levels during session
if(inSession && currentORB.isActive)
{
if(high[i] > currentORB.orbHighPrice)
currentORB.orbHighPrice = high[i];
if(low[i] < currentORB.orbLowPrice)
currentORB.orbLowPrice = low[i];
}
// Mark end of session
if(!inSession && currentORB.isActive && i > 0)
{
MqlDateTime prevDt;
TimeToStruct(time[i-1], prevDt);
if(IsInSession(prevDt))
{
currentORB.sessionEndBar = i - 1;
currentORB.isActive = false;
// Draw the rectangle now that session is complete
if(showShadedBox)
DrawORBRectangle();
}
}
// Plot ORB levels and targets
if(currentORB.orbHighPrice > 0 && currentORB.orbLowPrice > 0)
{
bool shouldPlot = false;
if(!inSession && drawOrbs)
{
// Limit line length
int barsFromSessionEnd = (currentORB.sessionEndBar > 0) ? i - currentORB.sessionEndBar : 0;
if(barsFromSessionEnd <= maxLineBars)
shouldPlot = true;
}
if(shouldPlot)
{
double orbRange = currentORB.orbHighPrice - currentORB.orbLowPrice;
// Always show ORB High and Low
OrbHighBuffer[i] = currentORB.orbHighPrice;
OrbLowBuffer[i] = currentORB.orbLowPrice;
if(showMidPoint && showPriceTargets)
OrbMidBuffer[i] = currentORB.orbLowPrice + (orbRange * 0.5);
if(showPriceTargets)
PlotPriceTargets(i, orbRange);
// Draw labels only for today and only once
if(isToday && showLabels && i == rates_total - 1)
DrawPriceTargetLabels(time[i], orbRange);
}
}
// Handle breakout detection
if(!inSession && i > 2 && currentORB.orbHighPrice > 0)
ProcessBreakouts(time, high, low, close, i, isToday);
}
return(rates_total);
}
//+------------------------------------------------------------------+
//| Initialize all buffers to EMPTY_VALUE |
//+------------------------------------------------------------------+
void InitializeBuffers(int index)
{
OrbHighBuffer[index] = EMPTY_VALUE;
OrbLowBuffer[index] = EMPTY_VALUE;
OrbMidBuffer[index] = EMPTY_VALUE;
OrbHigh50Buffer[index] = EMPTY_VALUE;
OrbHigh100Buffer[index] = EMPTY_VALUE;
OrbLow50Buffer[index] = EMPTY_VALUE;
OrbLow100Buffer[index] = EMPTY_VALUE;
OrbHigh150Buffer[index] = EMPTY_VALUE;
OrbHigh200Buffer[index] = EMPTY_VALUE;
OrbHigh250Buffer[index] = EMPTY_VALUE;
OrbHigh300Buffer[index] = EMPTY_VALUE;
OrbHigh350Buffer[index] = EMPTY_VALUE;
OrbHigh400Buffer[index] = EMPTY_VALUE;
OrbHigh450Buffer[index] = EMPTY_VALUE;
OrbHigh500Buffer[index] = EMPTY_VALUE;
OrbLow150Buffer[index] = EMPTY_VALUE;
OrbLow200Buffer[index] = EMPTY_VALUE;
OrbLow250Buffer[index] = EMPTY_VALUE;
OrbLow300Buffer[index] = EMPTY_VALUE;
OrbLow350Buffer[index] = EMPTY_VALUE;
OrbLow400Buffer[index] = EMPTY_VALUE;
OrbLow450Buffer[index] = EMPTY_VALUE;
}
//+------------------------------------------------------------------+
//| Plot price targets |
//+------------------------------------------------------------------+
void PlotPriceTargets(int index, double orbRange)
{
OrbHigh50Buffer[index] = currentORB.orbHighPrice + (orbRange * 0.5);
OrbHigh100Buffer[index] = currentORB.orbHighPrice + (orbRange * 1.0);
OrbLow50Buffer[index] = currentORB.orbLowPrice + (orbRange * -0.5);
OrbLow100Buffer[index] = currentORB.orbLowPrice + (orbRange * -1.0);
if(showPriceTargetsExtended)
{
OrbHigh150Buffer[index] = currentORB.orbHighPrice + (orbRange * 1.5);
OrbHigh200Buffer[index] = currentORB.orbHighPrice + (orbRange * 2.0);
OrbHigh250Buffer[index] = currentORB.orbHighPrice + (orbRange * 2.5);
OrbHigh300Buffer[index] = currentORB.orbHighPrice + (orbRange * 3.0);
OrbHigh350Buffer[index] = currentORB.orbHighPrice + (orbRange * 3.5);
OrbHigh400Buffer[index] = currentORB.orbHighPrice + (orbRange * 4.0);
OrbHigh450Buffer[index] = currentORB.orbHighPrice + (orbRange * 4.5);
OrbHigh500Buffer[index] = currentORB.orbHighPrice + (orbRange * 5.0);
OrbLow150Buffer[index] = currentORB.orbLowPrice + (orbRange * -1.5);
OrbLow200Buffer[index] = currentORB.orbLowPrice + (orbRange * -2.0);
OrbLow250Buffer[index] = currentORB.orbLowPrice + (orbRange * -2.5);
OrbLow300Buffer[index] = currentORB.orbLowPrice + (orbRange * -3.0);
OrbLow350Buffer[index] = currentORB.orbLowPrice + (orbRange * -3.5);
OrbLow400Buffer[index] = currentORB.orbLowPrice + (orbRange * -4.0);
OrbLow450Buffer[index] = currentORB.orbLowPrice + (orbRange * -4.5);
}
}
//+------------------------------------------------------------------+
//| Draw price target labels |
//+------------------------------------------------------------------+
void DrawPriceTargetLabels(datetime time, double orbRange)
{
if(!showLabels) return;
string prefix = "ORB_Label_" + IntegerToString(currentORB.dayOfYear);
ObjectsDeleteAll(0, prefix);
datetime labelTime = time + labelOffsetBars * PeriodSeconds();
double pipOffset = labelOffsetPips * pointMultiplier;
// Basic ORB levels
CreatePriceLabel(labelTime, currentORB.orbHighPrice + pipOffset + (20 * _Point), orbTitle + " HIGH", clrLime);
CreatePriceLabel(labelTime, currentORB.orbLowPrice + pipOffset - (20 * _Point), orbTitle + " LOW", clrRed);
if(showPriceTargets)
{
CreatePriceLabel(labelTime, currentORB.orbHighPrice + (orbRange * 0.5) + pipOffset, "PT 50%", orb50Color);
CreatePriceLabel(labelTime, currentORB.orbHighPrice + (orbRange * 1.0) + pipOffset, "PT 100%", orb100Color);
CreatePriceLabel(labelTime, currentORB.orbLowPrice + (orbRange * -0.5) + pipOffset, "PT 50%", orb50Color);
CreatePriceLabel(labelTime, currentORB.orbLowPrice + (orbRange * -1.0) + pipOffset, "PT 100%", orb100Color);
if(showPriceTargetsExtended)
{
CreatePriceLabel(labelTime, currentORB.orbHighPrice + (orbRange * 1.5) + pipOffset, "PT 150%", orbOtherColor);
CreatePriceLabel(labelTime, currentORB.orbHighPrice + (orbRange * 2.0) + pipOffset, "PT 200%", orbOtherColor);
CreatePriceLabel(labelTime, currentORB.orbHighPrice + (orbRange * 2.5) + pipOffset, "PT 250%", orbOtherColor);
CreatePriceLabel(labelTime, currentORB.orbHighPrice + (orbRange * 3.0) + pipOffset, "PT 300%", orbOtherColor);
CreatePriceLabel(labelTime, currentORB.orbLowPrice + (orbRange * -1.5) + pipOffset, "PT 150%", orbOtherColor);
CreatePriceLabel(labelTime, currentORB.orbLowPrice + (orbRange * -2.0) + pipOffset, "PT 200%", orbOtherColor);
CreatePriceLabel(labelTime, currentORB.orbLowPrice + (orbRange * -2.5) + pipOffset, "PT 250%", orbOtherColor);
CreatePriceLabel(labelTime, currentORB.orbLowPrice + (orbRange * -3.0) + pipOffset, "PT 300%", orbOtherColor);
}
if(showMidPoint)
{
CreatePriceLabel(labelTime, currentORB.orbLowPrice + (orbRange * 0.5) + pipOffset, "MIDPOINT", clrGray);
}
}
}
//+------------------------------------------------------------------+
//| Create price label |
//+------------------------------------------------------------------+
void CreatePriceLabel(datetime time, double price, string text, color clr)
{
string labelName = "ORB_Label_" + IntegerToString(currentORB.dayOfYear) + "_" + text;
if(ObjectCreate(0, labelName, OBJ_TEXT, 0, time, price))
{
ObjectSetString(0, labelName, OBJPROP_TEXT, text);
ObjectSetInteger(0, labelName, OBJPROP_COLOR, clr);
ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, labelFontSize);
ObjectSetInteger(0, labelName, OBJPROP_ANCHOR, labelAnchor);
ObjectSetString(0, labelName, OBJPROP_FONT, "Arial");
}
}
//+------------------------------------------------------------------+
//| Process breakout detection |
//+------------------------------------------------------------------+
void ProcessBreakouts(const datetime &time[], const double &high[], const double &low[], const double &close[], int i, bool isToday)
{
bool highCrossBO = CheckHighBreakout(high, low, close, i);
bool lowCrossBO = CheckLowBreakout(high, low, close, i);
if(showEntries)
{
if(highCrossBO)
{
CreateBreakoutLabel(time[i], high[i], "Breakout\nWait for Retest", clrGreen, true);
inBreakout = true;
}
if(lowCrossBO)
{
CreateBreakoutLabel(time[i], low[i], "Breakout\nWait for Retest", clrGreen, false);
inBreakout = true;
}
if(inBreakout)
{
bool isRetestHigh = close[i-1] > currentORB.orbHighPrice && low[i] <= currentORB.orbHighPrice && close[i] >= currentORB.orbHighPrice;
bool isRetestLow = close[i-1] < currentORB.orbLowPrice && high[i] >= currentORB.orbLowPrice && close[i] <= currentORB.orbLowPrice;
bool failedRetest = (close[i-1] > currentORB.orbHighPrice && close[i] < currentORB.orbHighPrice) ||
(close[i-1] < currentORB.orbLowPrice && close[i] > currentORB.orbLowPrice);
if(isRetestHigh || isRetestLow)
{
CreateBreakoutLabel(time[i], high[i], "Retest", clrGreen, true);
inBreakout = false;
}
else if(failedRetest)
{
CreateBreakoutLabel(time[i], high[i], "Failed Retest", clrRed, true);
inBreakout = false;
}
}
}
if(isToday)
{
if(!alertBreakoutsOnly)
{
bool highCross = CheckCross(close, i, currentORB.orbHighPrice);
bool lowCross = CheckCross(close, i, currentORB.orbLowPrice);
if(highCross)
SendNotification("Price crossing ORB High Level");
if(lowCross)
SendNotification("Price crossing ORB Low Level");
}
else
{
if(highCrossBO)
SendNotification("Price breaking out of ORB High Level, Look for Retest");
if(lowCrossBO)
SendNotification("Price breaking out of ORB Low Level, Look for Retest");
}
}
}
//+------------------------------------------------------------------+
//| Create breakout label |
//+------------------------------------------------------------------+
void CreateBreakoutLabel(datetime time, double price, string text, color clr, bool above)
{
string labelName = "ORB_Breakout_" + TimeToString(time) + "_" + DoubleToString(price, 5);
double adjustedPrice = above ? price + (50 * _Point) : price - (50 * _Point);
if(ObjectCreate(0, labelName, OBJ_TEXT, 0, time, adjustedPrice))
{
ObjectSetString(0, labelName, OBJPROP_TEXT, text);
ObjectSetInteger(0, labelName, OBJPROP_COLOR, clr);
ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 8);
ObjectSetInteger(0, labelName, OBJPROP_ANCHOR, above ? ANCHOR_LOWER : ANCHOR_UPPER);
ObjectSetString(0, labelName, OBJPROP_FONT, "Arial");
}
}
//+------------------------------------------------------------------+
//| Draw ORB Rectangle |
//+------------------------------------------------------------------+
void DrawORBRectangle()
{
if(!showShadedBox || currentORB.boxName == "" || currentORB.sessionStartBar < 0 || currentORB.sessionEndBar < 0)
return;
ObjectDelete(0, currentORB.boxName);
if(ObjectCreate(0, currentORB.boxName, OBJ_RECTANGLE, 0, currentORB.orbStartTime, currentORB.orbHighPrice, currentORB.orbEndTime, currentORB.orbLowPrice))
{
ObjectSetInteger(0, currentORB.boxName, OBJPROP_COLOR, shadeColor);
ObjectSetInteger(0, currentORB.boxName, OBJPROP_STYLE, STYLE_SOLID);
ObjectSetInteger(0, currentORB.boxName, OBJPROP_WIDTH, 2);
ObjectSetInteger(0, currentORB.boxName, OBJPROP_BACK, true);
ObjectSetInteger(0, currentORB.boxName, OBJPROP_FILL, true);
ObjectSetInteger(0, currentORB.boxName, OBJPROP_BGCOLOR, shadeColor);
}
}
//+------------------------------------------------------------------+
//| Helper functions |
//+------------------------------------------------------------------+
bool IsInSession(MqlDateTime &dt)
{
int currentMinutes = dt.hour * 60 + dt.min;
int sessionStart = sessionStartHour * 60 + sessionStartMin;
int sessionEnd = sessionEndHour * 60 + sessionEndMin;
return (currentMinutes >= sessionStart && currentMinutes < sessionEnd);
}
bool IsFirstBarOfSession(const datetime &time[], int i, MqlDateTime &dt)
{
if(i == 0) return false;
MqlDateTime prevDt;
TimeToStruct(time[i-1], prevDt);
bool inSession = IsInSession(dt);
bool wasInSession = IsInSession(prevDt);
return (inSession && !wasInSession);
}
bool IsNewDay(const datetime &time[], int i)
{
if(i == 0) return true;
MqlDateTime dt, prevDt;
TimeToStruct(time[i], dt);
TimeToStruct(time[i-1], prevDt);
return (dt.day != prevDt.day);
}
bool IsToday(datetime barTime)
{
MqlDateTime dt, currentDt;
TimeToStruct(barTime, dt);
TimeToStruct(TimeCurrent(), currentDt);
return (dt.year == currentDt.year && dt.day_of_year == currentDt.day_of_year);
}
bool CheckHighBreakout(const double &high[], const double &low[], const double &close[], int i)
{
return (low[i-2] < currentORB.orbHighPrice && close[i-2] > currentORB.orbHighPrice &&
low[i-1] > currentORB.orbHighPrice && close[i-1] > currentORB.orbHighPrice &&
close[i] > low[i-1] && low[i] > currentORB.orbHighPrice);
}
bool CheckLowBreakout(const double &high[], const double &low[], const double &close[], int i)
{
return (high[i-2] > currentORB.orbLowPrice && close[i-2] < currentORB.orbLowPrice &&
high[i-1] < currentORB.orbLowPrice && close[i-1] < currentORB.orbLowPrice &&
close[i] < high[i-1] && high[i] < currentORB.orbLowPrice);
}
bool CheckCross(const double &close[], int i, double level)
{
if(i == 0) return false;
return ((close[i-1] <= level && close[i] > level) ||
(close[i-1] >= level && close[i] < level));
}