Files
MQL5Data/Libraries/x-saherelm.x-ohcl.lib.mq5
T
2025-09-16 10:55:50 +03:30

2214 lines
38 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Common Library
// --------------------------------------
// Name: XOHCLLib
// Description: provide all commonly used functions ...
//
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property library
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://www.saherelm.ir"
#property version "1.00"
#property strict
//
#include "../Libraries/x-saherelm.common.extensions.lib.mq5"
//
// Describe an Specific Candle ...
struct XOHCL
{
//
// Props ...
//
double high;
double open;
double close;
double low;
long volume;
double spread;
//
string symbol;
datetime time;
ENUM_TIMEFRAMES period;
//
// Constructor ...
XOHCL()
{
Clean();
}
//
// Init a Bar ...
// Using Bar Index ...
bool Init(
string mSymbol = NULL, // Trading Symbol
ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period
int barIndex = 0 // Bar Index
)
{
//
mSymbol = NormalizeSymbol(mSymbol);
mPeriod = NormalizePeriod(mPeriod);
//
symbol = mSymbol;
period = mPeriod;
//
time = iTime(
mSymbol,
mPeriod,
barIndex //
);
//
open = iOpen(
mSymbol,
mPeriod,
barIndex //
);
open = NormalizePrice(open, mSymbol);
//
close = iClose(
mSymbol,
mPeriod,
barIndex //
);
close = NormalizePrice(close, mSymbol);
//
high = iHigh(
mSymbol,
mPeriod,
barIndex //
);
high = NormalizePrice(high, mSymbol);
//
low = iLow(
mSymbol,
mPeriod,
barIndex //
);
low = NormalizePrice(low, mSymbol);
//
spread = iSpread(
mSymbol,
mPeriod,
barIndex //
);
spread = NormalizePrice(spread, mSymbol);
//
volume = iTickVolume(
mSymbol,
mPeriod,
barIndex //
);
//
bool result = IsValid();
//
return result;
}
//
// Init a Bar ...
// Using Bar Time ...
bool Init(
string mSymbol = NULL, // Trading Symbol
ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period
datetime mTime = NULL // Bar Time
)
{
//
mTime = NormalizeTime(mTime);
//
int barIndex = iBarShift(
mSymbol,
mPeriod,
mTime,
false //
);
//
bool result = Init(
mSymbol,
mPeriod,
barIndex
//
);
//
return result;
}
//
// Tools ...
//
void Clean()
{
//
low = 0;
high = 0;
open = 0;
close = 0;
spread = 0;
volume = 0;
//
time = NULL;
symbol = NULL;
period = NULL;
//
ZeroMemory(this);
}
//
// Validate Bar ...
bool IsValid()
{
//
bool result = false;
//
result =
//
low > 0 &&
high > 0 &&
open > 0 &&
close > 0 &&
volume > 0
//
// TODO: Fix in Some Cases for Zero Spread ...
// spread > 0 &&
//
;
//
return result;
}
//
int TotalBars()
{
//
int result = 0;
//
result = iBars(
symbol,
period //
);
//
return result;
}
//
// Calculate X_PRICE Specified Type ...
double GetPrice(ENUM_X_PRICE mPType)
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
return GetAppliedPrice(
mPType,
open,
high,
low,
close //
);
}
//
// Retrieve Price base On Series Mode ...
double GetPrice(ENUM_SERIESMODE mMode)
{
//
ENUM_X_PRICE mType = ToXPrice(mMode);
//
return GetPrice(mType);
}
//
// Calculate Applied Price ...
double GetPrice(ENUM_APPLIED_PRICE mPType)
{
//
ENUM_X_PRICE mType = ToXPrice(mPType);
//
return GetPrice(mType);
}
//
// Find Specific Price ...
bool FindHigherPriceBar(
XOHCL &bar,
double price,
ENUM_X_PRICE _type = X_PRICE_HIGH //
)
{
//
bool result = false;
//
result = IsValid();
if (!result)
{
return result;
}
//
int totalBars = TotalBars();
result = IsValidSize(totalBars);
if (!result)
{
return result;
}
//
int start = Index();
int maxAllowedLoopback = totalBars / 5;
for (int i = start; i < maxAllowedLoopback; i++)
{
//
result = bar.Init(
symbol,
period,
i //
);
//
if (!result)
{
break;
}
//
double iPrice = bar.GetPrice(_type);
//
result =
//
iPrice > 0 &&
iPrice > price
//
;
if (result)
{
break;
}
}
//
if (!result)
{
bar.Clean();
}
//
return result;
}
//
// Find Specific Price ...
bool FindLowerPriceBar(
XOHCL &bar,
double price,
ENUM_X_PRICE _type = X_PRICE_HIGH //
)
{
//
bool result = false;
//
result = IsValid();
if (!result)
{
return result;
}
//
int totalBars = TotalBars();
result = IsValidSize(totalBars);
if (!result)
{
return result;
}
//
int start = Index();
int maxAllowedLoopback = totalBars / 5;
for (int i = start; i < maxAllowedLoopback; i++)
{
//
result = bar.Init(
symbol,
period,
i //
);
//
if (!result)
{
break;
}
//
double iPrice = bar.GetPrice(_type);
//
result =
//
iPrice > 0 &&
iPrice < price
//
;
if (result)
{
break;
}
}
//
if (!result)
{
bar.Clean();
}
//
return result;
}
//
// Calculate up Price ...
double GetUp()
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result = MathMax(open, close);
//
return result;
}
//
// Calculate Down Price ...
double GetDown()
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result = MathMin(open, close);
//
return result;
}
//
// Calculate Bar Body ...
double GetBody()
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result = GetUp() - GetDown();
//
return result;
}
//
// Calculate Bar Range ...
double GetRange()
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result = high - low;
//
return result;
}
//
// Calculate Bar Shadows ...
double GetShadows()
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result = GetRange() - GetBody();
//
return result;
}
//
// Calculate Bar High Shadow ...
double GetHighShadow()
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result =
//
high - GetUp()
//
;
//
return result;
}
//
// Calculate Bar Low Shadow ...
double GetLowShadow()
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result =
//
GetDown() - low;
//
;
//
return result;
}
//
// Check Bar is Bullish ...
bool IsBullish()
{
//
bool result = false;
//
if (!IsValid())
{
return result;
}
//
result = open < close;
//
return result;
}
//
// Check Bar is Bearish ...
bool IsBearish()
{
//
bool result = false;
//
if (!IsValid())
{
return result;
}
//
result = open > close;
//
return result;
}
//
// Get Direction of Bar ...
ENUM_X_DIRECTION GetDirection()
{
//
ENUM_X_DIRECTION result = X_DIRECTION_NONE;
//
bool isBullish = IsBullish();
bool isBearish = IsBearish();
//
result =
isBullish && isBearish
? X_DIRECTION_ALL
: !isBullish && !isBearish
? X_DIRECTION_NONE
: isBullish
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
return result;
}
//
// Find Next Bar Time ...
datetime NextAt()
{
//
datetime result = NULL;
//
if (!IsValid())
{
return result;
}
//
int prSeconds = PeriodSeconds(period);
//
result = time + prSeconds;
//
return result;
}
//
// Find Prev Bar Time ...
datetime BeforeOn()
{
//
datetime result = NULL;
//
if (!IsValid())
{
return result;
}
//
int prSeconds = PeriodSeconds(period);
//
result = time - prSeconds;
//
return result;
}
//
// Calculate Last Bar Open Time in Smaller Period ...
datetime GetLastBarTimeOfPeriod(
ENUM_TIMEFRAMES smallerPeriod //
)
{
//
datetime result = NULL;
//
if (!IsValid())
{
return result;
}
//
int sourceSeconds = PeriodSeconds(period);
int destSeconds = PeriodSeconds(smallerPeriod);
if (destSeconds >= sourceSeconds)
{
//
result = time;
return result;
}
//
result = (datetime)((((int)time) + sourceSeconds) - destSeconds);
//
return result;
}
//
// Calculate Close Time ...
datetime GetCloseTime()
{
//
datetime result = NULL;
//
if (!IsValid())
{
return result;
}
//
int seconds = PeriodSeconds(period);
//
result = (datetime)(((int)time) + seconds);
//
return result;
}
//
bool BarAt(
int index,
XOHCL &bar //
)
{
//
bool result = false;
//
bar.Clean();
//
result = IsValid();
if (!result)
{
return result;
}
//
if (index < 0)
{
index = 0;
}
//
result = bar.Init(
symbol,
period,
index //
);
//
return result;
}
//
bool BarIn(
ENUM_TIMEFRAMES _period,
XOHCL &bar //
)
{
//
bool result = false;
//
bar.Clean();
//
result = IsValid() &&
IsSpecifiedValid(_period);
if (!result)
{
return result;
}
//
int index = Index(_period);
result = bar.Init(
symbol,
_period,
index //
);
//
return result;
}
//
// Find Current Bar Index on Chart ...
int Index()
{
//
int result = -1;
//
if (!IsValid())
{
return result;
}
//
result = iBarShift(
symbol,
period,
time
//
);
//
return result;
}
//
int Index(datetime value)
{
//
int result = -1;
//
value = NormalizeTime(value);
//
result = IsValid();
if (!result)
{
return result;
}
//
result = iBarShift(
symbol,
period,
value //
);
//
return result;
}
//
int Index(ENUM_TIMEFRAMES value)
{
//
int result = -1;
//
result = IsValid() &&
IsSpecifiedValid(value);
if (!result)
{
return result;
}
//
result = iBarShift(
symbol,
value,
time //
);
//
return result;
}
//
bool GetNextBar(XOHCL &bar)
{
//
bool result = false;
//
result = IsValid();
if (!result)
{
return result;
}
//
int idx = Index();
result = idx > 0;
if (!result)
{
return result;
}
//
result = bar.Init(
this.symbol,
this.period,
idx - 1 //
);
//
if (!result)
{
bar.Clean();
}
//
return result;
}
//
bool GetPreviousBar(XOHCL &bar)
{
//
bool result = false;
//
result = IsValid();
if (!result)
{
return result;
}
//
int idx = Index();
//
result = bar.Init(
this.symbol,
this.period,
idx + 1 //
);
//
if (!result)
{
bar.Clean();
}
//
return result;
}
//
bool HasFiboPressure(
ENUM_X_DIRECTION forDir,
ENUM_X_FIBO_LEVELS level = X_FIBO_LEVEL_382 //
)
{
//
bool result = false;
//
result = IsValid() &&
HasDirection(forDir);
if (!result)
{
return result;
}
//
bool isBullish = IsSpecifiedBullish(forDir);
bool isBearish = IsSpecifiedBearish(forDir);
//
double fiboLevelValue = GetFibonacciLevel(
high,
low,
level,
forDir //
);
//
isBullish =
isBullish &&
GetDown() > fiboLevelValue;
isBearish =
isBearish &&
GetUp() < fiboLevelValue;
//
result = isBullish ||
isBearish;
//
return result;
}
//
bool IsRejected(
double price,
ENUM_X_DIRECTION forDir,
bool forceType = false,
bool forcePressure = false //
)
{
//
bool result = false;
//
result = IsValid() &&
price > 0 &&
HasDirection(forDir);
if (!result)
{
return result;
}
//
bool isBullish =
IsSpecifiedBullish(forDir) &&
low < price &&
GetDown() > price;
//
bool isBearish =
IsSpecifiedBearish(forDir) &&
high > price &&
GetUp() < price;
//
if (forceType)
{
//
isBullish =
isBullish &&
IsBullish();
//
isBearish =
isBearish &&
IsBearish();
}
//
if (forcePressure)
{
//
isBullish =
isBullish &&
HasFiboPressure(forDir);
//
isBearish =
isBearish &&
HasFiboPressure(forDir);
}
//
result = isBullish ||
isBearish;
//
return result;
}
//
bool IsBreaked(
double price,
ENUM_X_DIRECTION forDir,
ENUM_X_FIBO_LEVELS fibLevel = X_FIBO_LEVEL_500,
ENUM_X_BOUNDARY_PRICE boundaryType = X_BOUNDARY_PRICE_UP_DOWN //
)
{
//
bool result = false;
//
result = IsValid() &&
price > 0 &&
HasDirection(forDir) &&
IsSpecifiedValid(boundaryType);
if (!result)
{
return result;
}
//
bool isUpDownPriceType = boundaryType == X_BOUNDARY_PRICE_UP_DOWN;
//
bool isBullish =
IsBullish() &&
low < price &&
high > price &&
IsSpecifiedBullish(forDir);
//
bool isBearish =
IsBearish() &&
low < price &&
high > price &&
IsSpecifiedBearish(forDir);
//
result = isBullish ||
isBearish;
if (result)
{
//
// Calculate Range ...
double range =
isUpDownPriceType
? GetBody()
: GetRange();
//
// Apply Edge Range ...
double iReqRange =
(range / 100) * (GetFiboLevelValue(fibLevel) * 100);
//
// Calculate Boundary Price ...
double iBoundary =
isUpDownPriceType
? isBullish
? GetUp()
: GetDown()
: isBullish
? high
: low;
//
// Detect Breaked Value ...
//
double breakedPrice =
isBullish
? (high - price)
: (price - low);
//
result =
breakedPrice >= iReqRange;
}
//
return result;
}
//
// Find Highest Bar Index ...
int FindHighestIndex(
int mLength, // Loopback ...
ENUM_SERIESMODE mMode // Calculation mode
)
{
//
int result = -1;
//
if (!IsValid())
{
return result;
}
//
if (mLength < 2)
{
mLength = 2;
}
//
result = iHighest(
symbol,
period,
mMode,
mLength,
Index());
//
return result;
}
//
// Find Highest ...
double FindHighest(
int mLength, // Loopback ...
ENUM_SERIESMODE mMode // Calculation mode
)
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
int idx = FindHighestIndex(
mLength,
mMode);
if (idx <= -1)
{
return result;
}
//
XOHCL iH;
result = iH.Init(
symbol,
period,
idx
//
);
if (!result)
{
return result;
}
//
result = iH.GetPrice(mMode);
//
return result;
}
//
// Find Highest ...
double FindHighestUp(
int mLength // Loopback ...
)
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result = FindHighest(mLength, MODE_OPEN);
result = MathMax(mLength, FindHighest(mLength, MODE_CLOSE));
//
return result;
}
//
// Find Lowest Bar Index ...
int FindLowestIndex(
int mLength, // Loopback ...
ENUM_SERIESMODE mMode // Calculation mode
)
{
//
int result = -1;
//
if (!IsValid())
{
return result;
}
//
if (mLength < 2)
{
mLength = 2;
}
//
result = iLowest(
symbol,
period,
mMode,
mLength,
Index());
//
return result;
}
//
// Find Lowest ...
double FindLowest(
int mLength, // Loopback ...
ENUM_SERIESMODE mMode // Calculation mode
)
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
int idx = FindLowestIndex(
mLength,
mMode);
if (idx <= -1)
{
return result;
}
//
XOHCL iL;
result = iL.Init(
symbol,
period,
idx
//
);
if (!result)
{
return result;
}
//
result = iL.GetPrice(mMode);
//
return result;
}
//
// Find Lowest ...
double FindLowesttDown(
int mLength // Loopback ...
)
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result = FindLowest(mLength, MODE_OPEN);
result = MathMax(mLength, FindLowest(mLength, MODE_CLOSE));
//
return result;
}
//
// Swing Detection ...
//
int FindSwing(
ENUM_X_SWING_TYPE type,
int shoulders = 3 //
)
{
//
int result = -1;
//
// Validate ...
bool isValid = IsValid() &&
IsXValid(type);
if (!isValid)
{
return result;
}
//
// Find Next Swing ...
result = FindXSwing(
type,
symbol,
period,
Index(),
shoulders //
);
//
return result;
}
//
int FindNextSwing(
ENUM_X_SWING_TYPE type,
int shoulders = 3 //
)
{
//
int result = -1;
//
// Validate ...
bool isValid = IsValid() &&
IsXValid(type);
if (!isValid)
{
return result;
}
//
// Find Next Swing ...
result = FindXSwing(
type,
symbol,
period,
Index() + 1,
shoulders //
);
//
return result;
}
//
bool FindSwingBar(
ENUM_X_SWING_TYPE type,
XOHCL &swingBar,
int shoulders = 3 //
)
{
//
bool result = false;
//
// Prepare ...
swingBar.Clean();
//
// Validate ...
result = IsValid() &&
IsXValid(type);
if (!result)
{
return result;
}
//
// Find Next Swing ...
int idx = FindXSwing(
type,
symbol,
period,
Index(),
shoulders //
);
result = IsValidIndex(idx);
if (!result)
{
return result;
}
//
result = swingBar.Init(
symbol,
period,
idx //
);
//
return result;
}
//
bool FindNextSwingBar(
ENUM_X_SWING_TYPE type,
XOHCL &swingBar,
int shoulders = 3 //
)
{
//
bool result = false;
//
// Prepare ...
swingBar.Clean();
//
// Validate ...
result = IsValid() &&
IsXValid(type);
if (!result)
{
return result;
}
//
// Find Next Swing ...
int idx = FindXSwing(
type,
symbol,
period,
Index() + 1,
shoulders //
);
result = IsValidIndex(idx);
if (!result)
{
return result;
}
//
result = swingBar.Init(
symbol,
period,
idx //
);
//
return result;
}
//
// Other ...
string GetTag(string prefix = "")
{
//
string result = NULL;
//
result =
(IsSpecifiedValid(prefix)
? prefix + "_"
: "") +
"XOHCL_" + symbol + "_" + ToXString(period) + "_" + ToFormatString(time);
//
return result;
}
//
// Convert to String Representation ...
string ToString()
{
//
string result = "";
//
result = GetTypeName(this) +
"(O(" + ToXString(open) + "),H(" + ToXString(high) + "),C(" + ToXString(close) + "),L(" + ToXString(low) + "))";
//
return result;
}
};
//
// Models ...
//
// Model a Bar Remains Time ...
struct XBarRemainsTime
{
//
int days;
int hours;
int minutes;
int seconds;
//
// Constructor ...
XBarRemainsTime()
{
Clean();
}
//
// Always Calculate Current 0 Bar Timing ...
bool Init(
string mSymbol = NULL, // Trading Symbol
ENUM_TIMEFRAMES mPeriod = NULL // Trading Period
)
{
//
bool result = false;
//
mSymbol = NormalizeSymbol(mSymbol);
mPeriod = NormalizePeriod(mPeriod);
//
int minuteSecoonds = 60;
int hourSeconds = minuteSecoonds * 60;
int daySeconds = 24 * hourSeconds;
//
int periodSeconds = PeriodSeconds(
mPeriod);
datetime startTime = GetBarTime(
mSymbol,
mPeriod,
0
//
);
//
int secondsDiff = (int)startTime + periodSeconds - (int)TimeCurrent();
//
int mWorkingSecondsDiff = secondsDiff;
if (mWorkingSecondsDiff > daySeconds)
{
//
days = mWorkingSecondsDiff / daySeconds;
mWorkingSecondsDiff -= days * daySeconds;
}
if (mWorkingSecondsDiff > hourSeconds)
{
//
hours = mWorkingSecondsDiff / hourSeconds;
mWorkingSecondsDiff -= hours * hourSeconds;
}
if (mWorkingSecondsDiff > minuteSecoonds)
{
//
minutes = mWorkingSecondsDiff / minuteSecoonds;
mWorkingSecondsDiff -= minutes * minuteSecoonds;
}
seconds = mWorkingSecondsDiff;
//
result = true;
//
return result;
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
days = 0;
hours = 0;
minutes = 0;
seconds = 0;
//
ZeroMemory(this);
}
//
// To String Representation ...
string ToString(
string dayId = "d",
string hourId = "h",
string minuteId = "m",
string secondId = "s",
string idSeparator = ": ",
string separator = ", ",
bool ignoreZeroValues = true
//
)
{
//
string result = "";
//
// Days ...
if (!ignoreZeroValues || days > 0)
{
result += dayId + idSeparator + (string)days + separator;
}
//
// Hours ...
if (!ignoreZeroValues || hours > 0)
{
//
string strHour = ToXString(hours);
if (StringLen(strHour) == 1)
{
strHour = "0" + strHour;
}
//
result += hourId + idSeparator + strHour + separator;
}
//
// Minutes ...
if (!ignoreZeroValues || minutes > 0)
{
//
string strMinute = ToXString(minutes);
if (StringLen(strMinute) == 1)
{
strMinute = "0" + strMinute;
}
//
result += minuteId + idSeparator + strMinute + separator;
}
//
// Seconds ...
if (!ignoreZeroValues || seconds > 0)
{
//
string strSec = ToXString(seconds);
if (StringLen(strSec) == 1)
{
strSec = "0" + strSec;
}
//
result += secondId + idSeparator + strSec;
}
//
return result;
}
};
//
// Tracking Times ...
struct XTimeTracker
{
//
// Props ...
int xMonth;
int xDayOfWeek;
int xForWeekDay;
int xDay;
int xHour;
int xMinute;
//
// Constructor ...
XTimeTracker()
{
Clean();
}
//
// Tools ...
//
void Clean()
{
//
xDay = -1;
xHour = -1;
xMonth = -1;
xMinute = -1;
xDayOfWeek = -1;
xForWeekDay = -1;
//
ZeroMemory(this);
}
//
// Detecting New Minute ...
bool IsNewMinute()
{
//
bool result = false;
//
// Retrieve Current Time as Struct ...
MqlDateTime timeStruct = GetCurrentTime();
//
// Check Houre ...
result = timeStruct.min != xMinute;
if (result)
{
xMinute = timeStruct.min;
}
//
return result;
}
//
// Detecting New Houre ...
bool IsNewHour()
{
//
bool result = false;
//
// Retrieve Current Time as Struct ...
MqlDateTime timeStruct = GetCurrentTime();
//
// Check Houre ...
result = timeStruct.hour != xHour;
if (result)
{
xHour = timeStruct.hour;
}
//
return result;
}
//
// Detecting New Day ...
bool IsNewDay()
{
//
bool result = false;
//
// Retrieve Current Time as Struct ...
MqlDateTime timeStruct = GetCurrentTime();
//
// Check Houre ...
result = timeStruct.day_of_year != xDay;
if (result)
{
xDay = timeStruct.day_of_year;
}
//
return result;
}
//
// Detecting New Week ...
bool IsNewWeek()
{
//
bool result = false;
//
// Retrieve Current Time as Struct ...
MqlDateTime timeStruct = GetCurrentTime();
//
// Check Week ...
// Since Week Starts From Monday in Forex World ...
// we Calculate Start of Week by 1-Monday ...
result =
xDayOfWeek == -1 &&
xForWeekDay == -1
? true
: timeStruct.day_of_week == 1 &&
timeStruct.day_of_year > xForWeekDay;
//
xForWeekDay = timeStruct.day_of_year;
xDayOfWeek = timeStruct.day_of_week;
//
return result;
}
//
// Detecting End Of Week ...
bool IsWeekEnd()
{
//
bool result = false;
//
// Retrieve Current Time as Struct ...
MqlDateTime timeStruct = GetCurrentTime();
//
// Check WeekEnd ...
// Since Week Starts From Monday in Forex World ...
// we Calculate End of Week by 5-Friday ...
result =
xDayOfWeek != -1 &&
timeStruct.day_of_week == 5 &&
timeStruct.hour == 23 &&
timeStruct.min == 59 &&
timeStruct.sec == 59;
//
return result;
}
//
// Detecting New Month ...
bool IsNewMonth()
{
//
bool result = false;
//
// Retrieve Current Time as Struct ...
MqlDateTime timeStruct = GetCurrentTime();
//
// Check Houre ...
result = timeStruct.mon != xMonth;
if (result)
{
xMonth = timeStruct.mon;
}
//
return result;
}
};
//
// Tracking Bars on Specified Environment ...
struct XBarTracker
{
//
string symbol; // Tracking Symbol
ENUM_TIMEFRAMES period; // Tracking Time Frame
//
int lastTrackedBar; // Last Tracked Bar ...
//
bool waitsUntilNext; // Waits Until Next Bar ...
//
// Constructor ...
XBarTracker()
{
Clean();
}
//
// Initializer ...
bool Init(
string mSymbol = NULL, // Trading Symbol
ENUM_TIMEFRAMES mPeriod = NULL // Trading Period
)
{
//
bool result = false;
//
mSymbol = NormalizeSymbol(mSymbol);
mPeriod = NormalizePeriod(mPeriod);
//
this.symbol = mSymbol;
this.period = mPeriod;
//
this.lastTrackedBar = 0;
//
result = true;
//
return result;
}
//
// Retrieve all Bars ...
int CountBars()
{
//
return iBars(
symbol,
period
//
);
}
//
// Check if it's New Bar ...
bool IsNewBar()
{
//
bool result = false;
//
int currentBars = CountBars();
//
result = currentBars > lastTrackedBar;
if (result)
{
lastTrackedBar = currentBars;
}
//
return result;
}
//
bool CanProcessBar()
{
//
bool _isInTestMode = IsRunningOnTestMode();
//
bool isNewBar = IsNewBar();
//
bool result =
_isInTestMode
? isNewBar
: !waitsUntilNext
? true
: isNewBar;
if (result && waitsUntilNext)
{
waitsUntilNext = false;
}
//
return result;
}
//
void Waits()
{
this.waitsUntilNext = true;
}
//
// Tools ...
void Clean()
{
//
symbol = NormalizeSymbol(NULL);
period = NormalizePeriod(NULL);
//
ZeroMemory(this);
}
//
bool GetBar(
XOHCL &bar,
int index = 0 //
)
{
//
bool result = false;
//
result = bar.Init(
symbol,
period,
index //
);
//
return result;
}
//
bool GetBar(
XOHCL &bar,
datetime time = NULL //
)
{
//
bool result = false;
//
NormalizeTime(time);
//
int barIndex = iBarShift(
symbol,
period,
time,
false //
);
//
result = barIndex >= 0;
if (!result)
{
return result;
}
//
result = bar.Init(
symbol,
period,
barIndex //
);
//
return result;
}
//
int Index(datetime time = NULL)
{
//
int result = 0;
//
NormalizeTime(time);
//
result = iBarShift(
symbol,
period,
time,
false //
);
//
return result;
}
};
//
// Extensions ...
//
// Extract Specific Range of Bars ...
// using Start Bar Index ...
int GetBars(
XOHCL &bars[], // Hold Result
string mSymbol = NULL, // Trading Symbol
ENUM_TIMEFRAMES mPeriod = NULL, // Trading Time Frame
int from = 0, // Start Bar Index
int count = 1 // Number of Bars
)
{
//
int result = 0;
//
from = NormalizeInt(from);
mSymbol = NormalizeSymbol(mSymbol);
mPeriod = NormalizePeriod(mPeriod);
//
int total = Bars(
mSymbol,
mPeriod //
);
if (from > total - 2)
{
from = total - 2;
}
//
if (count < 0)
{
count = 1;
}
//
int start = from;
int end = start + count;
if (end > total - 1)
{
end = total - 1;
}
//
Clean(bars);
//
for (int i = start; i < end; i++)
{
//
XOHCL iBar;
bool isValid = iBar.Init(
mSymbol,
mPeriod,
i //
);
//
if (isValid)
{
//
AddRef(
iBar,
bars //
);
}
}
//
result = ArraySize(bars);
//
return result;
}
//
// Extract Specific Range of Bars ...
// using Start Bar Time ...
int GetBars(
XOHCL &bars[], // Hold Result
string mSymbol = NULL, // Trading Symbol
ENUM_TIMEFRAMES mPeriod = NULL, // Trading Time Frame
datetime from = NULL, // Start Bar Time
int count = 1 // Number of Bars
)
{
//
from = NormalizeTime(from);
mSymbol = NormalizeSymbol(mSymbol);
mPeriod = NormalizePeriod(mPeriod);
//
int barIndex = GetBarIndex(
mSymbol,
mPeriod,
from //
);
//
return GetBars(
bars,
mSymbol,
mPeriod,
barIndex,
count //
);
}
//