2214 lines
38 KiB
Plaintext
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 //
|
|
);
|
|
}
|
|
|
|
// |