6304 lines
104 KiB
Plaintext
6304 lines
104 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Common Library
|
|
// --------------------------------------
|
|
// Name: XCommonExtensionsLib
|
|
// 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 "../Classes/x-saherelm.x-md5.class.mq5"
|
|
#include "../Libraries/x-saherelm.x-enums.lib.mq5"
|
|
|
|
//
|
|
#include <MovingAverages.mqh>
|
|
|
|
//
|
|
// Constants ...
|
|
#define X_MIN_SIZE 0
|
|
#define X_INVALID_INDEX -1
|
|
|
|
//
|
|
// START Value Checkers ...
|
|
//
|
|
|
|
//
|
|
// Check a Value Not Empty ...
|
|
template <typename T>
|
|
bool NotEmpty(T value)
|
|
{
|
|
return value != EMPTY_VALUE;
|
|
}
|
|
|
|
//
|
|
// Check a Value Not Empty and Zero ...
|
|
template <typename T>
|
|
bool NotEmptyZero(T value)
|
|
{
|
|
return value != 0 &&
|
|
value != EMPTY_VALUE;
|
|
}
|
|
|
|
//
|
|
// END Value Checkers ...
|
|
//
|
|
|
|
//
|
|
// START Validators ...
|
|
//
|
|
|
|
/**
|
|
* Validate Strings ...
|
|
*
|
|
* @param value: string
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsValid(string value)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
value != NULL &&
|
|
StringLen(value) > 0
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
bool IsSpecifiedValid(string value)
|
|
{
|
|
return IsValid(value);
|
|
}
|
|
|
|
/**
|
|
* Validate Date ...
|
|
*
|
|
* @param value: datetime
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsValid(datetime value)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = NotEmpty(value) && value != NULL;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
bool IsSpecifiedValid(datetime value)
|
|
{
|
|
return IsValid(value);
|
|
}
|
|
|
|
/**
|
|
* Validate Time Frame ...
|
|
*
|
|
* @param value: ENUM_TIMEFRAMES member ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsValid(ENUM_TIMEFRAMES value)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
value != NULL
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
bool IsSpecifiedValid(ENUM_TIMEFRAMES value)
|
|
{
|
|
//
|
|
return IsValid(value);
|
|
}
|
|
|
|
/**
|
|
* Validate Specific Period Mode ...
|
|
*
|
|
* @param mMethod: ENUM_X_PERIOD_METHOD member, Period Select Method ...
|
|
* @param mPeriod: ENUM_TIMEFRAMES member, Selected Period ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsValid(
|
|
ENUM_X_PERIOD_METHOD mMethod,
|
|
ENUM_TIMEFRAMES mPeriod //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
mMethod == X_PERIOD_NONE
|
|
? false
|
|
: mMethod == X_PERIOD_MANUALLY
|
|
? mPeriod != NULL
|
|
: mMethod == X_PERIOD_AUTO
|
|
? true
|
|
: false
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
bool IsSpecifiedValid(
|
|
ENUM_X_PERIOD_METHOD mMethod,
|
|
ENUM_TIMEFRAMES mPeriod //
|
|
)
|
|
{
|
|
return IsValid(
|
|
mMethod,
|
|
mPeriod //
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Validate a Size Value ...
|
|
*
|
|
* @param value: int, Provided Size ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsValidSize(int value)
|
|
{
|
|
//
|
|
bool result = value > X_MIN_SIZE;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Check a Given Index is Valid or not ...
|
|
*
|
|
* @param value: int, Provided Index ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsValidIndex(int value)
|
|
{
|
|
return value >= X_MIN_SIZE;
|
|
}
|
|
|
|
//
|
|
// END Validators ...
|
|
//
|
|
|
|
//
|
|
// START Normalizations ...
|
|
//
|
|
|
|
/**
|
|
* Normalize Symbol ...
|
|
*
|
|
* @param value: string, Provided Symbols ...
|
|
*
|
|
* @return ( string )
|
|
*/
|
|
string NormalizeSymbol(string value)
|
|
{
|
|
//
|
|
string result = value;
|
|
|
|
//
|
|
if (!IsValid(result))
|
|
{
|
|
result = _Symbol;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Normalize Time ...
|
|
*
|
|
* @param value: datetime, Provided Time ...
|
|
*
|
|
* @return ( datetime )
|
|
*/
|
|
datetime NormalizeTime(datetime value)
|
|
{
|
|
//
|
|
datetime result = value;
|
|
|
|
//
|
|
if (!IsValid(result))
|
|
{
|
|
result = TimeCurrent();
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Normalize Period ...
|
|
*
|
|
* @param value: ENUM_TIMEFRAMES member, Provided Period ...
|
|
*
|
|
* @return ( ENUM_TIMEFRAMES )
|
|
*/
|
|
ENUM_TIMEFRAMES NormalizePeriod(ENUM_TIMEFRAMES value)
|
|
{
|
|
//
|
|
ENUM_TIMEFRAMES result = value;
|
|
|
|
//
|
|
if (!IsValid(value))
|
|
{
|
|
result = _Period;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Normalize Market Cycle ...
|
|
*
|
|
* @param value: ENUM_X_MARKET_CYCLES, Provided Cycle ...
|
|
*
|
|
* @return ( ENUM_X_MARKET_CYCLES )
|
|
*/
|
|
ENUM_X_MARKET_CYCLES NormalizeCycle(ENUM_X_MARKET_CYCLES value)
|
|
{
|
|
//
|
|
ENUM_X_MARKET_CYCLES result = value;
|
|
|
|
//
|
|
if (!IsValid(result))
|
|
{
|
|
result = X_MARKET_CYCLE_SHORT;
|
|
}
|
|
|
|
//
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* Normalize Integer Value ...
|
|
*
|
|
* @param value: int, Provided Value ...
|
|
* @param min: int, Minimum Allowed Value ...
|
|
* @param max: int, Maximum Allowed Value ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int NormalizeInt(
|
|
int value,
|
|
int min = 0,
|
|
int max = INT_MAX //
|
|
)
|
|
{
|
|
//
|
|
if (value < min)
|
|
{
|
|
value = min;
|
|
}
|
|
|
|
//
|
|
if (value > max)
|
|
{
|
|
value = max;
|
|
}
|
|
|
|
//
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* Normalize Double Value ...
|
|
*
|
|
* @param value: double, Provided Value ...
|
|
* @param min: double, Minimum Allowed Value ...
|
|
* @param max: double, Maximum Allowed Value ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double NormalizeDouble(
|
|
double value,
|
|
double min = 0,
|
|
double max = DBL_MAX //
|
|
)
|
|
{
|
|
//
|
|
if (value < min)
|
|
{
|
|
value = min;
|
|
}
|
|
|
|
//
|
|
if (value > max)
|
|
{
|
|
value = max;
|
|
}
|
|
|
|
//
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* Normalize Index based on Collection ...
|
|
*
|
|
* @param index: int, Provided Index ...
|
|
* @param buffer: Collection Reference ...
|
|
*/
|
|
template <typename T>
|
|
bool NormalizeIndex(
|
|
int &index,
|
|
T &buffer[] //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int size = ArraySize(buffer);
|
|
result = IsValidSize(size);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (!IsValidIndex(index))
|
|
{
|
|
index = X_MIN_SIZE;
|
|
}
|
|
|
|
//
|
|
if (index > size - 1)
|
|
{
|
|
index = size - 1;
|
|
}
|
|
|
|
//
|
|
result = IsValidIndex(index) &&
|
|
index >= X_MIN_SIZE &&
|
|
index < size;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Normalize Start and Count based on Specified Buffer ...
|
|
*
|
|
* @param start: int, Provided Start index ...
|
|
* @param count: int, Provided Number of Iteration ...
|
|
* @param buffer: Collection instance ...
|
|
*/
|
|
template <typename T>
|
|
void NormalizeCount(
|
|
int &start,
|
|
int &count,
|
|
T &buffer[] //
|
|
)
|
|
{
|
|
//
|
|
// Validate Buffer Size ...
|
|
int bufferSize = ArraySize(buffer);
|
|
if (!IsValidSize(bufferSize))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Normalization Start ...
|
|
NormalizeIndex(
|
|
start,
|
|
buffer //
|
|
);
|
|
|
|
//
|
|
if (count < start)
|
|
{
|
|
count = (start - count);
|
|
}
|
|
|
|
//
|
|
// Normalization Count ...
|
|
|
|
//
|
|
if (count < 0)
|
|
{
|
|
count = start;
|
|
}
|
|
|
|
//
|
|
if (count > bufferSize - start)
|
|
{
|
|
count = bufferSize - start;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Normalize a Volume ...
|
|
*
|
|
* @param mVolume: double, Provided Volume ...
|
|
* @param mSymbol: string, Specified Symbol ...
|
|
* @param mLength: int, Provided Default floating Length ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double NormalizeVolume(
|
|
double mVolume,
|
|
string mSymbol = NULL,
|
|
int mLength = 2 //
|
|
)
|
|
{
|
|
//
|
|
double result = mVolume;
|
|
|
|
//
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
|
|
//
|
|
double maxAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MAX);
|
|
double minAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MIN);
|
|
|
|
//
|
|
// Normalize Digits ...
|
|
int digits = GetDigits(minAvailableVolume);
|
|
|
|
//
|
|
mLength =
|
|
mLength == 0 || mLength > digits
|
|
? digits
|
|
: MathMin(mLength, digits);
|
|
|
|
//
|
|
// Normalize Volume ...
|
|
result = NormalizeDouble(result, mLength);
|
|
|
|
//
|
|
// Validate Result ...
|
|
if (result > maxAvailableVolume)
|
|
{
|
|
result = maxAvailableVolume;
|
|
}
|
|
else if (result < minAvailableVolume)
|
|
{
|
|
result = minAvailableVolume;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Normalize a Price Value ...
|
|
*
|
|
* @param mPrice: double, Provided Price ...
|
|
* @param mSymbol: string, Provided Symbol ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double NormalizePrice(
|
|
double mPrice,
|
|
string mSymbol = NULL //
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
|
|
//
|
|
double tickSize = 0;
|
|
result = SymbolInfoDouble(mSymbol, SYMBOL_TRADE_TICK_SIZE, tickSize);
|
|
|
|
//
|
|
int digits = GetDigits(mSymbol);
|
|
result = NormalizeDouble(MathRound(mPrice / tickSize) * tickSize, digits);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// END Normalizations ...
|
|
//
|
|
|
|
//
|
|
// START Position ...
|
|
//
|
|
|
|
/**
|
|
* Determine a Position type is Long or not ...
|
|
*
|
|
* @param value: ENUM_POSITION_TYPE member, Specified Type ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsLong(ENUM_POSITION_TYPE value)
|
|
{
|
|
//
|
|
bool result = value == POSITION_TYPE_BUY;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Determine a Position type is Long or not ...
|
|
*
|
|
* @param value: ENUM_ORDER_TYPE member, Specified Type ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsLong(ENUM_ORDER_TYPE value)
|
|
{
|
|
//
|
|
bool result = value == ORDER_TYPE_BUY;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Determine a Position type is Long or not ...
|
|
*
|
|
* @param value: ENUM_X_DIRECTION member, Specified Type ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsLong(ENUM_X_DIRECTION value)
|
|
{
|
|
//
|
|
bool result = value == X_DIRECTION_BULLISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Determine a Position type is Short or not ...
|
|
*
|
|
* @param value: ENUM_POSITION_TYPE member, Specified Type ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsShort(ENUM_POSITION_TYPE value)
|
|
{
|
|
//
|
|
bool result = value == POSITION_TYPE_SELL;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Determine a Position type is Short or not ...
|
|
*
|
|
* @param value: ENUM_ORDER_TYPE member, Specified Type ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsShort(ENUM_ORDER_TYPE value)
|
|
{
|
|
//
|
|
bool result = value == ORDER_TYPE_SELL;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Determine a Position type is Short or not ...
|
|
*
|
|
* @param value: ENUM_X_DIRECTION member, Specified Type ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsShort(ENUM_X_DIRECTION value)
|
|
{
|
|
//
|
|
bool result = value == X_DIRECTION_BEARISH;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts Opposit Direction Type ...
|
|
*
|
|
* @param value: ENUM_POSITION_TYPE member, Specified Type ...
|
|
*
|
|
* @return ( ENUM_POSITION_TYPE )
|
|
*/
|
|
ENUM_POSITION_TYPE Opposit(ENUM_POSITION_TYPE value)
|
|
{
|
|
//
|
|
ENUM_POSITION_TYPE result = NULL;
|
|
|
|
//
|
|
bool isLong = IsLong(value);
|
|
result = isLong
|
|
? POSITION_TYPE_SELL
|
|
: POSITION_TYPE_BUY;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts Opposit Direction Type ...
|
|
*
|
|
* @param value: ENUM_ORDER_TYPE member, Specified Type ...
|
|
*
|
|
* @return ( ENUM_ORDER_TYPE )
|
|
*/
|
|
ENUM_ORDER_TYPE Opposit(ENUM_ORDER_TYPE value)
|
|
{
|
|
//
|
|
ENUM_ORDER_TYPE result = NULL;
|
|
|
|
//
|
|
bool isLong = IsLong(value);
|
|
result = isLong
|
|
? ORDER_TYPE_SELL
|
|
: ORDER_TYPE_BUY;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts To String ...
|
|
*
|
|
* @param value: ENUM_POSITION_TYPE member ...
|
|
*
|
|
* @return ( string )
|
|
*/
|
|
string ToString(ENUM_POSITION_TYPE value)
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsLong(value)
|
|
? "Long"
|
|
: "Short"
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts To String ...
|
|
*
|
|
* @param value: ENUM_ORDER_TYPE member ...
|
|
*
|
|
* @return ( string )
|
|
*/
|
|
string ToString(ENUM_ORDER_TYPE value)
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
result =
|
|
//
|
|
IsLong(value)
|
|
? "Long"
|
|
: "Short"
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Ask Price ...
|
|
*
|
|
* @param mSymbol: string, Provided Symbol ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double GetAsk(
|
|
string mSymbol = NULL //
|
|
)
|
|
{
|
|
//
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
|
|
//
|
|
double result = SymbolInfoDouble(mSymbol, SYMBOL_ASK);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Bid Price ...
|
|
*
|
|
* @param mSymbol: string, Provided Symbol ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double GetBid(
|
|
string mSymbol = NULL //
|
|
)
|
|
{
|
|
//
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
|
|
//
|
|
double result = SymbolInfoDouble(mSymbol, SYMBOL_BID);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Spread Price ...
|
|
*
|
|
* @param mSymbol: string, Provided Symbol ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double GetSpread(
|
|
string mSymbol = NULL //
|
|
)
|
|
{
|
|
//
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
|
|
//
|
|
double ask = GetAsk(mSymbol);
|
|
double bid = GetBid(mSymbol);
|
|
|
|
//
|
|
double result = MathAbs(ask - bid);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Point Price ...
|
|
*
|
|
* @param mSymbol: string, Provided Symbol ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double GetPoints(
|
|
string mSymbol = NULL // Trading Symbol
|
|
)
|
|
{
|
|
//
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
|
|
//
|
|
double result = SymbolInfoDouble(mSymbol, SYMBOL_POINT);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts Price to Point ...
|
|
*
|
|
* @param price: double, price ...
|
|
* @param mSymbol: string, Symbol ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double PriceToPoint(
|
|
double mPrice, // the price amount which required to calculate
|
|
string mSymbol = NULL // Trading Symbol
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
mPrice = NormalizePrice(mPrice, mSymbol);
|
|
|
|
//
|
|
double point = GetPoints(mSymbol);
|
|
result = mPrice / point;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Digits Length ...
|
|
*
|
|
* @param mSymbol: string, Provided Symbol ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
int GetDigits(
|
|
string mSymbol = NULL // Trading Symbol
|
|
)
|
|
{
|
|
//
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
|
|
//
|
|
int result = (int)SymbolInfoInteger(mSymbol, SYMBOL_DIGITS);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Entry Price ...
|
|
*
|
|
* @param mSymbol: string, Provided Symbol ...
|
|
* @param type: ENUM_POSITION_TYPE member, Specified Entry type ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double GetEntry(
|
|
string mSymbol = NULL,
|
|
ENUM_POSITION_TYPE type = POSITION_TYPE_BUY //
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
|
|
//
|
|
result =
|
|
IsLong(type)
|
|
? GetAsk(mSymbol)
|
|
: GetBid(mSymbol);
|
|
result = NormalizePrice(result, mSymbol);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Entry Price ...
|
|
*
|
|
* @param mSymbol: string, Provided Symbol ...
|
|
* @param type: ENUM_X_DIRECTION member, Specified Entry type ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double GetEntry(
|
|
string mSymbol = NULL,
|
|
ENUM_X_DIRECTION type = X_DIRECTION_BULLISH //
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
|
|
//
|
|
result =
|
|
IsBullish(type)
|
|
? GetAsk(mSymbol)
|
|
: GetBid(mSymbol);
|
|
result = NormalizePrice(result, mSymbol);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Exit Price ...
|
|
*
|
|
* @param mSymbol: string, Provided Symbol ...
|
|
* @param type: ENUM_POSITION_TYPE member, Specified Exit type ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double GetExit(
|
|
string mSymbol = NULL,
|
|
ENUM_POSITION_TYPE type = POSITION_TYPE_BUY //
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
|
|
//
|
|
result =
|
|
IsLong(type)
|
|
? GetBid(mSymbol)
|
|
: GetAsk(mSymbol);
|
|
result = NormalizePrice(result, mSymbol);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get Exit Price ...
|
|
*
|
|
* @param mSymbol: string, Provided Symbol ...
|
|
* @param type: ENUM_X_DIRECTION member, Specified Exit type ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double GetExit(
|
|
string mSymbol = NULL,
|
|
ENUM_X_DIRECTION type = X_DIRECTION_BULLISH //
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
|
|
//
|
|
result =
|
|
IsBullish(type)
|
|
? GetBid(mSymbol)
|
|
: GetAsk(mSymbol);
|
|
result = NormalizePrice(result, mSymbol);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieve Current Tick ...
|
|
*/
|
|
bool GetTick(
|
|
string mSymbol,
|
|
MqlTick &tick //
|
|
)
|
|
{
|
|
return SymbolInfoTick(mSymbol, tick);
|
|
}
|
|
|
|
//
|
|
// END Position ...
|
|
//
|
|
|
|
//
|
|
// START Tools ...
|
|
//
|
|
|
|
/**
|
|
* Check Expert Running in Testing Mode or not ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool IsRunningOnTestMode()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// check programm mode ...
|
|
result = MQL5InfoInteger(MQL5_TESTING);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Find Chart ID ...
|
|
*
|
|
* @param mSymbol: string, Specified Symbol ...
|
|
* @param mPeriod: ENUM_TIMEFRAMES member, Specified Period ...
|
|
*
|
|
* @return ( long )
|
|
*/
|
|
long FindChartID(
|
|
string mSymbol = NULL,
|
|
ENUM_TIMEFRAMES mPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
long result = ChartFirst();
|
|
long first = result;
|
|
|
|
//
|
|
while (result > 0)
|
|
{
|
|
//
|
|
string chSymbol = ChartSymbol(result);
|
|
ENUM_TIMEFRAMES chPeriod = ChartPeriod(result);
|
|
|
|
//
|
|
bool isOwn =
|
|
//
|
|
chSymbol == mSymbol &&
|
|
chPeriod == mPeriod
|
|
//
|
|
;
|
|
if (isOwn)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
result = ChartNext(result);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieve Available Symbols ...
|
|
*
|
|
* @param symbols: string Collection reference to Hold Symbols ...
|
|
* @param onlyInWatchList: bool, Force Extracts only Watch List Symbols ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetAllSymbols(
|
|
string &symbols[], // Hold Result
|
|
bool onlyInWatchList = false // Specified Retrieve only Symbols which in Watch List
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(symbols);
|
|
|
|
//
|
|
int count = SymbolsTotal(onlyInWatchList);
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
string iSymbol = SymbolName(
|
|
i,
|
|
onlyInWatchList //
|
|
);
|
|
if (!IsValid(iSymbol))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
Add(
|
|
iSymbol,
|
|
symbols //
|
|
);
|
|
}
|
|
|
|
//
|
|
result = ArraySize(symbols);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Filter Symbols Collections ...
|
|
*
|
|
* @param query: string, Provided Query to Search Symbols ...
|
|
* @param symbols: string, Collection resources to Hold's Filtered results ...
|
|
* @param onlyInWatchList: bool, Specified Apply Filter only on Watch List Symbols ...
|
|
* @param ignoreCase: bool, Ignore Case Sesitive ...
|
|
* @param querySeparator: string, Provided Separator of Query ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int FilterSymbols(
|
|
string query,
|
|
string &symbols[],
|
|
bool onlyInWatchList = false,
|
|
bool ignoreCase = true,
|
|
string querySeparator = "," // If Provided means query is a Collection of Queries and need to be Splitted
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(symbols);
|
|
|
|
//
|
|
if (!IsValid(query))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Query is an String array or not ...
|
|
string mQueries[];
|
|
int queriesCount = 0;
|
|
if (IsValid(querySeparator) && Contains(querySeparator, query, true))
|
|
{
|
|
//
|
|
queriesCount = SplitContent(
|
|
mQueries,
|
|
query,
|
|
querySeparator //
|
|
);
|
|
}
|
|
|
|
//
|
|
string allSymbols[];
|
|
int allSymbolsCount = GetAllSymbols(
|
|
allSymbols,
|
|
onlyInWatchList //
|
|
);
|
|
if (allSymbolsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop Through all Symbols ...
|
|
for (int i = 0; i < allSymbolsCount; i++)
|
|
{
|
|
//
|
|
string iSymbol = allSymbols[i];
|
|
|
|
//
|
|
bool isFilterPassed = false;
|
|
if (queriesCount == 0)
|
|
{
|
|
//
|
|
isFilterPassed = Contains(
|
|
query,
|
|
iSymbol,
|
|
ignoreCase //
|
|
);
|
|
}
|
|
else if (queriesCount > 0)
|
|
{
|
|
//
|
|
isFilterPassed = Contains(
|
|
mQueries,
|
|
iSymbol,
|
|
ignoreCase //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (isFilterPassed)
|
|
{
|
|
//
|
|
Add(
|
|
iSymbol,
|
|
symbols //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(symbols);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Extract Symbols to Find Only USD Side Assets ...
|
|
*
|
|
* @param symbols: string, Collection resources to Hold's Filtered results ...
|
|
* @param onlyInWatchList: bool, Specified Apply Filter only on Watch List Symbols ...
|
|
* @param ignoreCase: bool, Ignore Case Sesitive ...
|
|
* @param querySeparator: string, Provided Separator of Query ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int FilterUSDSymbols(
|
|
string &symbols[],
|
|
bool onlyInWatchList = false,
|
|
bool ignoreCase = true,
|
|
string querySeparator = "," //
|
|
)
|
|
{
|
|
//
|
|
return FilterSymbols(
|
|
"USD",
|
|
symbols,
|
|
onlyInWatchList,
|
|
ignoreCase,
|
|
querySeparator //
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get Digits Length of Specified Double Value ...
|
|
*
|
|
* @param value: double, Provided Value ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetDigits(double value)
|
|
{
|
|
//
|
|
int d = 0;
|
|
double p = 1;
|
|
while (MathRound(value * p) / p != value)
|
|
{
|
|
p = MathPow(10, ++d);
|
|
}
|
|
|
|
//
|
|
return d;
|
|
}
|
|
|
|
/**
|
|
* Retrieve Specific Object Types Name ...
|
|
*
|
|
* @param t: T object reference ...
|
|
*
|
|
* @return ( string )
|
|
*
|
|
*/
|
|
template <typename T>
|
|
string GetTypeName(const T &t)
|
|
{
|
|
return typename(T);
|
|
}
|
|
|
|
/**
|
|
* Get Specified Types Token ...
|
|
*
|
|
* @param item: T, object reference ...
|
|
*
|
|
* @return ( string )
|
|
*/
|
|
template <typename T>
|
|
string GetToken(T &item)
|
|
{
|
|
//
|
|
string mType = GetTypeName(item);
|
|
|
|
//
|
|
string result = mType;
|
|
|
|
//
|
|
string parts[];
|
|
int partsCount = SplitContent(
|
|
parts,
|
|
result,
|
|
" " //
|
|
);
|
|
if (partsCount <= 0)
|
|
{
|
|
//
|
|
result = mType;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool hasLastPart = GetLastItem(
|
|
result,
|
|
parts //
|
|
);
|
|
if (!hasLastPart)
|
|
{
|
|
//
|
|
result = mType;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
template <typename T>
|
|
string GetSpecificToken(T &item)
|
|
{
|
|
return GetToken(item);
|
|
}
|
|
|
|
/**
|
|
* Generate Unique Tags ...
|
|
*
|
|
* @param model: T, object reference ...
|
|
*
|
|
* @return ( string )
|
|
*/
|
|
template <typename T>
|
|
string GenerateTag(T &model)
|
|
{
|
|
//
|
|
string result = "";
|
|
|
|
//
|
|
string tag = model.ToString();
|
|
if (StringLen(tag) == 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XSCMD5 *md5;
|
|
md5 = new XCMD5();
|
|
|
|
//
|
|
result = md5.Hash(tag);
|
|
|
|
//
|
|
ZeroMemory(md5);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Hash Specified Content ...
|
|
*
|
|
* @param content: T, Proveded Content ...
|
|
*
|
|
* @return ( string )
|
|
*/
|
|
template <typename T>
|
|
string ToMD5(T content)
|
|
{
|
|
//
|
|
string result = "";
|
|
|
|
//
|
|
string strContent = ToString(content);
|
|
if (StringLen(strContent) == 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XCMD5 *md5;
|
|
md5 = new XCMD5();
|
|
|
|
//
|
|
result = md5.Hash(strContent);
|
|
|
|
//
|
|
ZeroMemory(md5);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Calculate Fibo Level ...
|
|
*
|
|
* @param mUp: double, Specified Upper Price ...
|
|
* @param mDown: double, Specified Lower Price ...
|
|
* @param mLevel: ENUM_X_FIBO_LEVELS member, Specified Fibo Level ...
|
|
* @param mForDir: ENUM_X_DIRECTION member, Specified Calculation Direction ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double GetFibonacciLevel(
|
|
double mUp,
|
|
double mDown,
|
|
ENUM_X_FIBO_LEVELS mLevel,
|
|
ENUM_X_DIRECTION mForDir //
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
double levelValue = GetFiboLevelValue(mLevel);
|
|
|
|
//
|
|
bool isValid =
|
|
//
|
|
mUp > 0 &&
|
|
mDown > 0 &&
|
|
levelValue > 0 &&
|
|
mUp > mDown &&
|
|
HasDirection(mForDir)
|
|
//
|
|
;
|
|
if (!isValid)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isBullish = IsBullish(mForDir);
|
|
|
|
//
|
|
double ling = mUp - mDown;
|
|
double pLevel = (ling / 100) * (levelValue * 100);
|
|
|
|
//
|
|
result =
|
|
isBullish
|
|
? mUp - pLevel
|
|
: mDown + pLevel;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Calculate Sspecified Buffer's Moving Averages ...
|
|
*
|
|
* @param rates_total: Integer, number of items ...
|
|
* @param prev_calculated: Integer, Previous Calculate Items ...
|
|
* @param begin: Integer, Bar Index ...
|
|
* @param period: Integer, Moving Average Length ...
|
|
* @param source: Double Array, Specified Array for Calculating Moving Averages ...
|
|
* @param buffer: Double Array, Specified Array to Apply Calculated Moving Average on it ...
|
|
* @param method: ENUM_MA_METHOD member Specified Moving Average Calculation Method ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int iMAOnBuffer(
|
|
const int _rates_total,
|
|
const int _prev_calculated,
|
|
const int _begin,
|
|
const int _period,
|
|
const double &_source[],
|
|
double &_buffer[],
|
|
ENUM_X_MA_METHOD _method = X_MA_MODE_SMA //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (
|
|
_period < 0 ||
|
|
_rates_total <= 0 ||
|
|
_prev_calculated < 0 ||
|
|
_method == X_MA_MODE_NONE ||
|
|
_prev_calculated > _rates_total)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
switch (_method)
|
|
{
|
|
//
|
|
case X_MA_MODE_SMA:
|
|
result = SimpleMAOnBuffer(
|
|
_rates_total,
|
|
_prev_calculated,
|
|
_begin,
|
|
_period,
|
|
_source,
|
|
_buffer //
|
|
);
|
|
break;
|
|
|
|
//
|
|
case X_MA_MODE_EMA:
|
|
result = ExponentialMAOnBuffer(
|
|
_rates_total,
|
|
_prev_calculated,
|
|
_begin,
|
|
_period,
|
|
_source,
|
|
_buffer //
|
|
);
|
|
break;
|
|
|
|
//
|
|
case X_MA_MODE_LWMA:
|
|
result = LinearWeightedMAOnBuffer(
|
|
_rates_total,
|
|
_prev_calculated,
|
|
_begin,
|
|
_period,
|
|
_source,
|
|
_buffer //
|
|
);
|
|
break;
|
|
|
|
//
|
|
case X_MA_MODE_SMMA:
|
|
result = SmoothedMAOnBuffer(
|
|
_rates_total,
|
|
_prev_calculated,
|
|
_begin,
|
|
_period,
|
|
_source,
|
|
_buffer //
|
|
);
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// END Tools ...
|
|
//
|
|
|
|
//
|
|
// START String ...
|
|
//
|
|
|
|
/**
|
|
* Search a Content Contains Specific String or not ...
|
|
*
|
|
* @param mQuery: string, Search Query ...
|
|
* @param mContent: string, Search Content ...
|
|
* @param ignoreCase: bool, Force Ignore Case Sensitive ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Contains(
|
|
string mQuery,
|
|
string mContent,
|
|
bool ignoreCase = true //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Query ...
|
|
result = IsValid(mQuery);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Validate Content ...
|
|
result = IsValid(mContent);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Normalize Inputs ...
|
|
string query = mQuery;
|
|
string content = mContent;
|
|
if (ignoreCase)
|
|
{
|
|
//
|
|
StringToLower(query);
|
|
StringToLower(content);
|
|
}
|
|
|
|
//
|
|
int queryIdx = StringFind(
|
|
content,
|
|
query);
|
|
|
|
//
|
|
result = queryIdx >= 0;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Search a Content Contains Specifics Query or not ...
|
|
*
|
|
* @param mQueries: string collection, Search Queries ...
|
|
* @param mContent: string, Search Content ...
|
|
* @param ignoreCase: bool, Force Ignore Case Sensitive ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool Contains(
|
|
string &mQueries[],
|
|
string mContent,
|
|
bool ignoreCase = true //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Queries ...
|
|
int queriesCount = ArraySize(mQueries);
|
|
result = queriesCount > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Validate Content ...
|
|
result = IsValid(mContent);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int containsCount = 0;
|
|
for (int i = 0; i < queriesCount; i++)
|
|
{
|
|
//
|
|
bool isContains = Contains(
|
|
mQueries[i],
|
|
mContent,
|
|
ignoreCase);
|
|
|
|
//
|
|
if (!isContains)
|
|
{
|
|
//
|
|
result = false;
|
|
break;
|
|
}
|
|
|
|
//
|
|
containsCount++;
|
|
}
|
|
|
|
//
|
|
result = containsCount == queriesCount;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Search a Content and Extract Occuranse Indexes ...
|
|
*
|
|
* @param mQuery: string, Search Query ...
|
|
* @param mContent: string, Search Content ...
|
|
* @param result: int collection reference, Holds Founded Indexes ...
|
|
* @param ignoreCase: bool, Force Ignore Case Sensitive ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int FindIndexes(
|
|
string mQuery,
|
|
string mContent,
|
|
int &result[],
|
|
bool ignoreCase = false //
|
|
)
|
|
{
|
|
//
|
|
int mResult = 0;
|
|
|
|
//
|
|
Clean(result);
|
|
|
|
//
|
|
// Validate Inputs ...
|
|
if (!IsValid(mQuery) ||
|
|
!IsValid(mContent))
|
|
{
|
|
return mResult;
|
|
}
|
|
|
|
//
|
|
// Apply Ignore Case if Provided ...
|
|
if (ignoreCase)
|
|
{
|
|
//
|
|
bool isConverted = StringToLower(mQuery);
|
|
if (!isConverted)
|
|
{
|
|
return mResult;
|
|
}
|
|
|
|
//
|
|
isConverted = StringToLower(mContent);
|
|
if (!isConverted)
|
|
{
|
|
return mResult;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Search First Index ...
|
|
int lastPos = 0;
|
|
int idx = StringFind(
|
|
mContent,
|
|
mQuery,
|
|
lastPos //
|
|
);
|
|
while (idx >= 0)
|
|
{
|
|
//
|
|
// Add Position to Result ...
|
|
Add(
|
|
idx,
|
|
result //
|
|
);
|
|
|
|
//
|
|
lastPos = idx + StringLen(mQuery);
|
|
idx = StringFind(
|
|
mContent,
|
|
mQuery,
|
|
lastPos //
|
|
);
|
|
}
|
|
|
|
//
|
|
mResult = ArraySize(result);
|
|
|
|
//
|
|
return mResult;
|
|
}
|
|
|
|
/**
|
|
* Convert From String ...
|
|
*
|
|
* @param value: string, Provided Value ...
|
|
*
|
|
* @return ( T )
|
|
*/
|
|
template <typename T>
|
|
T FromString(string value)
|
|
{
|
|
//
|
|
T result = NULL;
|
|
|
|
//
|
|
if (!IsValid(value))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = (T)value;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts to String ...
|
|
*
|
|
* @param value: T, Provided Value ...
|
|
*
|
|
* @return ( string )
|
|
*/
|
|
template <typename T>
|
|
string ToString(T value)
|
|
{
|
|
return (string)value;
|
|
}
|
|
|
|
//
|
|
// Used In Report or Summary Generators ...
|
|
string ToString(
|
|
string prefix, // Title
|
|
bool value, // Value
|
|
bool ignoreFalseConditions = true, // Ignore False Conditions
|
|
string lineSeparator = "\n", // Line Separator
|
|
string prefixSeparator = ":" // Title Separator
|
|
)
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
result = (value || !ignoreFalseConditions)
|
|
? prefix +
|
|
prefixSeparator + " " +
|
|
ToString(value) +
|
|
lineSeparator
|
|
: "";
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
template <typename T>
|
|
string ToString(
|
|
string prefix, // Title
|
|
T value, // Value
|
|
string lineSeparator = "\n", // Line Separator
|
|
string prefixSeparator = ":" // Title Separator
|
|
)
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
result = prefix +
|
|
prefixSeparator + " " +
|
|
ToString(value) +
|
|
lineSeparator;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string SetLabel(
|
|
string mLabel, // Provided Label ...
|
|
string value, // Source Value ...
|
|
string separator = "\n", // Line Separator
|
|
bool addTopEmptyLine = true // Add Empty Line On top
|
|
)
|
|
{
|
|
//
|
|
string result = value;
|
|
|
|
//
|
|
if (StringLen(mLabel) <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = (StringLen(value) > 0)
|
|
? (addTopEmptyLine ? separator : "") +
|
|
mLabel +
|
|
separator +
|
|
"-----------------------------" +
|
|
separator +
|
|
value
|
|
: value;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Converts a Buffer to String Representation ...
|
|
template <typename T>
|
|
string ToString(
|
|
const T &buffer[], // Specified Buffer
|
|
string separator = ",", // Specified Separator
|
|
bool addIndex = false, // Specified Add Items Indexes or Not
|
|
string indexLabel = "i:", // Specified Index Label
|
|
string indexSeparator = ">" // Specified Index Separator
|
|
)
|
|
{
|
|
//
|
|
string result = "";
|
|
|
|
//
|
|
int bufferSize = ArraySize(buffer);
|
|
if (bufferSize <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < bufferSize; i++)
|
|
{
|
|
//
|
|
if (addIndex)
|
|
{
|
|
//
|
|
if (StringLen(indexLabel) > 0)
|
|
{
|
|
result += indexLabel + " ";
|
|
}
|
|
|
|
//
|
|
result += (string)i + " ";
|
|
|
|
//
|
|
if (StringLen(indexSeparator) > 0)
|
|
{
|
|
result += indexSeparator + " ";
|
|
}
|
|
}
|
|
|
|
//
|
|
string iItemString = (string)buffer[i];
|
|
|
|
//
|
|
result += iItemString;
|
|
|
|
//
|
|
if (i < bufferSize - 1)
|
|
{
|
|
result += separator;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts String to boolean ...
|
|
*
|
|
* @param value: string, Provided Value ...
|
|
*
|
|
* @return ( bool )
|
|
*/
|
|
bool ToBoolean(string value)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (StringLen(value) <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
StringToLower(value);
|
|
result = value == "true";
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Split an String Representation of an Array ...
|
|
int SplitContent(
|
|
string &result[], // Hold Result ...
|
|
string content, // Source ...
|
|
string separator = ",", // Separator ...
|
|
bool forceCleanResult = true // Clean Result ...
|
|
)
|
|
{
|
|
//
|
|
int mResult = 0;
|
|
|
|
//
|
|
if (forceCleanResult)
|
|
{
|
|
Clean(result);
|
|
}
|
|
|
|
//
|
|
int before = ArraySize(result);
|
|
|
|
//
|
|
if (separator == NULL || StringLen(separator) == 0)
|
|
{
|
|
separator = ",";
|
|
}
|
|
|
|
//
|
|
if (StringLen(content) == 0)
|
|
{
|
|
return mResult;
|
|
}
|
|
|
|
//
|
|
StringSplit(
|
|
content,
|
|
StringGetCharacter(
|
|
separator,
|
|
0),
|
|
result);
|
|
|
|
//
|
|
int after = ArraySize(result);
|
|
|
|
//
|
|
mResult = after - before;
|
|
|
|
//
|
|
return mResult;
|
|
}
|
|
|
|
//
|
|
// Extract Data from String ...
|
|
string ExtractString(
|
|
const string source, // Source String used for Extracting
|
|
const string startString = "(", // Expression Start String must be Unique
|
|
const string endString = ")" // Where to End Extraction, usually a Sign
|
|
)
|
|
{
|
|
//
|
|
string result = "";
|
|
|
|
//
|
|
// Validate String ...
|
|
if (
|
|
StringLen(source) == 0 ||
|
|
StringLen(endString) == 0 ||
|
|
StringLen(startString) == 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Start String Position ...
|
|
int sPos = StringFind(
|
|
source,
|
|
startString);
|
|
if (sPos < 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find End String Position after Start String ...
|
|
int searchEndFromPos = sPos + StringLen(startString);
|
|
int ePos = StringFind(
|
|
source,
|
|
endString,
|
|
searchEndFromPos);
|
|
if (ePos < 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract Data from Source ...
|
|
int dLength = ePos - searchEndFromPos;
|
|
result = StringSubstr(
|
|
source,
|
|
searchEndFromPos,
|
|
dLength);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Extract an Array of Contents ...
|
|
int ExtractStrings(
|
|
string &result[], // Hold Result
|
|
const string source, // Source String used for Extracting
|
|
const string startString = "(", // Expression Start String must be Unique
|
|
const string endString = ")" // Where to End Extraction, usually a Sign
|
|
)
|
|
{
|
|
//
|
|
int mResult = 0;
|
|
|
|
//
|
|
Clean(result);
|
|
|
|
//
|
|
// Validate Args ...
|
|
int sourceLength = StringLen(source);
|
|
int startLength = StringLen(startString);
|
|
int endLength = StringLen(endString);
|
|
|
|
//
|
|
int minRequiredLength = startLength + endLength;
|
|
|
|
//
|
|
if (
|
|
endLength <= 0 ||
|
|
startLength <= 0 ||
|
|
sourceLength <= 0 ||
|
|
sourceLength < minRequiredLength)
|
|
{
|
|
return mResult;
|
|
}
|
|
|
|
//
|
|
// Make a Copy of Source for Manipulating ...
|
|
string workStr = source;
|
|
|
|
//
|
|
// Define a Loop ...
|
|
while (StringLen(workStr) > minRequiredLength)
|
|
{
|
|
//
|
|
// Find Item ...
|
|
string item = ExtractString(
|
|
workStr,
|
|
startString,
|
|
endString);
|
|
|
|
//
|
|
// Breakout when couldn't find anymore item ...
|
|
int itemLength = StringLen(item);
|
|
if (itemLength <= 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Prepare Item Source String for Replacing in Work String ...
|
|
string itemSource = startString + item + endString;
|
|
|
|
//
|
|
// Add Item to Result Array ...
|
|
Add(
|
|
item,
|
|
result);
|
|
|
|
//
|
|
// Replace Item Soure in Work String ...
|
|
StringReplace(
|
|
workStr,
|
|
itemSource,
|
|
"");
|
|
}
|
|
|
|
//
|
|
// Calculate Size of Array ...
|
|
mResult = ArraySize(result);
|
|
|
|
//
|
|
return mResult;
|
|
}
|
|
|
|
//
|
|
string ExtractSurrounded(
|
|
const string surrounded, // Surrounded Content
|
|
const string mToken, // Specified Token
|
|
const string startString = "(", // Expression Start String must be Unique
|
|
const string endString = ")" // Where to End Extraction, usually a Sign
|
|
)
|
|
{
|
|
//
|
|
return ExtractString(
|
|
surrounded,
|
|
mToken + startString,
|
|
endString
|
|
//
|
|
);
|
|
}
|
|
|
|
//
|
|
int ParseIntSurrounded(
|
|
const string surrounded, // Surrounded Content
|
|
const string mToken, // Specified Token
|
|
const string startString = "(", // Expression Start String must be Unique
|
|
const string endString = ")" // Where to End Extraction, usually a Sign
|
|
)
|
|
{
|
|
//
|
|
int result = NULL;
|
|
|
|
//
|
|
string strContent = ExtractSurrounded(
|
|
surrounded,
|
|
mToken,
|
|
startString,
|
|
endString
|
|
//
|
|
);
|
|
if (!IsValid(strContent))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = (int)strContent;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
long ParseLongSurrounded(
|
|
const string surrounded, // Surrounded Content
|
|
const string mToken, // Specified Token
|
|
const string startString = "(", // Expression Start String must be Unique
|
|
const string endString = ")" // Where to End Extraction, usually a Sign
|
|
)
|
|
{
|
|
//
|
|
long result = NULL;
|
|
|
|
//
|
|
string strContent = ExtractSurrounded(
|
|
surrounded,
|
|
mToken,
|
|
startString,
|
|
endString
|
|
//
|
|
);
|
|
if (!IsValid(strContent))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = (long)strContent;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
string ParseStringSurrounded(
|
|
const string surrounded, // Surrounded Content
|
|
const string mToken, // Specified Token
|
|
const string startString = "(", // Expression Start String must be Unique
|
|
const string endString = ")" // Where to End Extraction, usually a Sign
|
|
)
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
string strContent = ExtractSurrounded(
|
|
surrounded,
|
|
mToken,
|
|
startString,
|
|
endString
|
|
//
|
|
);
|
|
if (!IsValid(strContent))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = (string)strContent;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
double ParseDoubleSurrounded(
|
|
const string surrounded, // Surrounded Content
|
|
const string mToken, // Specified Token
|
|
const string startString = "(", // Expression Start String must be Unique
|
|
const string endString = ")" // Where to End Extraction, usually a Sign
|
|
)
|
|
{
|
|
//
|
|
double result = NULL;
|
|
|
|
//
|
|
string strContent = ExtractSurrounded(
|
|
surrounded,
|
|
mToken,
|
|
startString,
|
|
endString
|
|
//
|
|
);
|
|
if (!IsValid(strContent))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = (double)strContent;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
datetime ParseTimeSurrounded(
|
|
const string surrounded, // Surrounded Content
|
|
const string mToken, // Specified Token
|
|
const string startString = "(", // Expression Start String must be Unique
|
|
const string endString = ")" // Where to End Extraction, usually a Sign
|
|
)
|
|
{
|
|
//
|
|
datetime result = NULL;
|
|
|
|
//
|
|
string strContent = ExtractSurrounded(
|
|
surrounded,
|
|
mToken,
|
|
startString,
|
|
endString
|
|
//
|
|
);
|
|
if (!IsValid(strContent))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = (datetime)strContent;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int ParseIntArraySurrounded(
|
|
int &result[], // Holds Result
|
|
const string surrounded, // Surrounded Content
|
|
const string mToken, // Specified Token
|
|
string separator = ",", // Separator ...
|
|
const string startString = "(", // Expression Start String must be Unique
|
|
const string endString = ")", // Where to End Extraction, usually a Sign
|
|
bool forceClean = true // Clean Result ...
|
|
)
|
|
{
|
|
//
|
|
int count = 0;
|
|
|
|
//
|
|
if (forceClean)
|
|
{
|
|
Clean(result);
|
|
}
|
|
|
|
//
|
|
int before = ArraySize(result);
|
|
|
|
//
|
|
string contentStr = ParseStringSurrounded(surrounded, mToken);
|
|
if (!IsValid(contentStr))
|
|
{
|
|
return count;
|
|
}
|
|
|
|
//
|
|
string tmps[];
|
|
int tmpsCount = SplitContent(
|
|
tmps,
|
|
contentStr
|
|
//
|
|
);
|
|
if (tmpsCount <= 0)
|
|
{
|
|
return count;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < tmpsCount; i++)
|
|
{
|
|
//
|
|
string iTMP = tmps[i];
|
|
if (!IsValid(iTMP))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
int iValue = (int)iTMP;
|
|
|
|
//
|
|
Add(
|
|
iValue,
|
|
result
|
|
//
|
|
);
|
|
}
|
|
|
|
//
|
|
int after = ArraySize(result);
|
|
|
|
//
|
|
count = after - before;
|
|
|
|
//
|
|
return count;
|
|
}
|
|
|
|
int ParseLongArraySurrounded(
|
|
long &result[], // Holds Result
|
|
const string surrounded, // Surrounded Content
|
|
const string mToken, // Specified Token
|
|
string separator = ",", // Separator ...
|
|
const string startString = "(", // Expression Start String must be Unique
|
|
const string endString = ")", // Where to End Extraction, usually a Sign
|
|
bool forceClean = true // Clean Result ...
|
|
)
|
|
{
|
|
//
|
|
int count = 0;
|
|
|
|
//
|
|
if (forceClean)
|
|
{
|
|
Clean(result);
|
|
}
|
|
|
|
//
|
|
int before = ArraySize(result);
|
|
|
|
//
|
|
string contentStr = ParseStringSurrounded(surrounded, mToken);
|
|
if (!IsValid(contentStr))
|
|
{
|
|
return count;
|
|
}
|
|
|
|
//
|
|
string tmps[];
|
|
int tmpsCount = SplitContent(
|
|
tmps,
|
|
contentStr
|
|
//
|
|
);
|
|
if (tmpsCount <= 0)
|
|
{
|
|
return count;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < tmpsCount; i++)
|
|
{
|
|
//
|
|
string iTMP = tmps[i];
|
|
if (!IsValid(iTMP))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
long iValue = (long)iTMP;
|
|
|
|
//
|
|
Add(
|
|
iValue,
|
|
result
|
|
//
|
|
);
|
|
}
|
|
|
|
//
|
|
int after = ArraySize(result);
|
|
|
|
//
|
|
count = after - before;
|
|
|
|
//
|
|
return count;
|
|
}
|
|
|
|
int ParseDoubleArraySurrounded(
|
|
double &result[], // Holds Result
|
|
const string surrounded, // Surrounded Content
|
|
const string mToken, // Specified Token
|
|
string separator = ",", // Separator ...
|
|
const string startString = "(", // Expression Start String must be Unique
|
|
const string endString = ")", // Where to End Extraction, usually a Sign
|
|
bool forceClean = true // Clean Result ...
|
|
)
|
|
{
|
|
//
|
|
int count = 0;
|
|
|
|
//
|
|
if (forceClean)
|
|
{
|
|
Clean(result);
|
|
}
|
|
|
|
//
|
|
int before = ArraySize(result);
|
|
|
|
//
|
|
string contentStr = ParseStringSurrounded(surrounded, mToken);
|
|
if (!IsValid(contentStr))
|
|
{
|
|
return count;
|
|
}
|
|
|
|
//
|
|
string tmps[];
|
|
int tmpsCount = SplitContent(
|
|
tmps,
|
|
contentStr
|
|
//
|
|
);
|
|
if (tmpsCount <= 0)
|
|
{
|
|
return count;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < tmpsCount; i++)
|
|
{
|
|
//
|
|
string iTMP = tmps[i];
|
|
if (!IsValid(iTMP))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
double iValue = (double)iTMP;
|
|
|
|
//
|
|
Add(
|
|
iValue,
|
|
result
|
|
//
|
|
);
|
|
}
|
|
|
|
//
|
|
int after = ArraySize(result);
|
|
|
|
//
|
|
count = after - before;
|
|
|
|
//
|
|
return count;
|
|
}
|
|
|
|
int ParseTimeArraySurrounded(
|
|
datetime &result[], // Holds Result
|
|
const string surrounded, // Surrounded Content
|
|
const string mToken, // Specified Token
|
|
string separator = ",", // Separator ...
|
|
const string startString = "(", // Expression Start String must be Unique
|
|
const string endString = ")", // Where to End Extraction, usually a Sign
|
|
bool forceClean = true // Clean Result ...
|
|
)
|
|
{
|
|
//
|
|
int count = 0;
|
|
|
|
//
|
|
if (forceClean)
|
|
{
|
|
Clean(result);
|
|
}
|
|
|
|
//
|
|
int before = ArraySize(result);
|
|
|
|
//
|
|
string contentStr = ParseStringSurrounded(surrounded, mToken);
|
|
if (!IsValid(contentStr))
|
|
{
|
|
return count;
|
|
}
|
|
|
|
//
|
|
string tmps[];
|
|
int tmpsCount = SplitContent(
|
|
tmps,
|
|
contentStr
|
|
//
|
|
);
|
|
if (tmpsCount <= 0)
|
|
{
|
|
return count;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < tmpsCount; i++)
|
|
{
|
|
//
|
|
string iTMP = tmps[i];
|
|
if (!IsValid(iTMP))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
datetime iValue = (datetime)iTMP;
|
|
|
|
//
|
|
Add(
|
|
iValue,
|
|
result
|
|
//
|
|
);
|
|
}
|
|
|
|
//
|
|
int after = ArraySize(result);
|
|
|
|
//
|
|
count = after - before;
|
|
|
|
//
|
|
return count;
|
|
}
|
|
|
|
//
|
|
// Surround an String by Specific Token ...
|
|
template <typename T>
|
|
string Surround(
|
|
string mToken, // an String which used to Tokenize
|
|
T &value, // a Value for Tokenize it
|
|
string startString = "(", // Token Start Content
|
|
string endString = ")" // Token End Content
|
|
)
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
string strValue = ToString(value);
|
|
if (!IsValid(strValue))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result =
|
|
//
|
|
(IsValid(mToken)
|
|
? mToken
|
|
: "") +
|
|
//
|
|
startString +
|
|
strValue +
|
|
endString
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
template <typename T>
|
|
string SurroundArray(
|
|
string mToken,
|
|
T &value[],
|
|
string startString = "(", // Token Start Content
|
|
string endString = ")" // Token End Content
|
|
)
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
string valueStr = ToString(value);
|
|
if (!IsValid(valueStr))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = Surround(
|
|
mToken,
|
|
valueStr,
|
|
startString,
|
|
endString
|
|
//
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// END String ...
|
|
//
|
|
|
|
//
|
|
// START Cycles ...
|
|
//
|
|
|
|
/**
|
|
* Converts String To Period ...
|
|
*
|
|
* @param value: string ...
|
|
*
|
|
* @return ( ENUM_TIMEFRAMES )
|
|
*/
|
|
ENUM_TIMEFRAMES ToPeriod(string value)
|
|
{
|
|
//
|
|
if (StringLen(value) == 0)
|
|
{
|
|
return _Period;
|
|
}
|
|
|
|
//
|
|
StringTrimLeft(value);
|
|
StringTrimRight(value);
|
|
|
|
//
|
|
ENUM_TIMEFRAMES result = _Period;
|
|
|
|
//
|
|
if (value == "M1")
|
|
{
|
|
result = PERIOD_M1;
|
|
}
|
|
else if (value == "M2")
|
|
{
|
|
result = PERIOD_M2;
|
|
}
|
|
else if (value == "M3")
|
|
{
|
|
result = PERIOD_M3;
|
|
}
|
|
else if (value == "M4")
|
|
{
|
|
result = PERIOD_M4;
|
|
}
|
|
else if (value == "M5")
|
|
{
|
|
result = PERIOD_M5;
|
|
}
|
|
else if (value == "M6")
|
|
{
|
|
result = PERIOD_M6;
|
|
}
|
|
else if (value == "M10")
|
|
{
|
|
result = PERIOD_M10;
|
|
}
|
|
else if (value == "M12")
|
|
{
|
|
result = PERIOD_M12;
|
|
}
|
|
else if (value == "M15")
|
|
{
|
|
result = PERIOD_M15;
|
|
}
|
|
else if (value == "M20")
|
|
{
|
|
result = PERIOD_M20;
|
|
}
|
|
else if (value == "M30")
|
|
{
|
|
result = PERIOD_M30;
|
|
}
|
|
else if (value == "H1")
|
|
{
|
|
result = PERIOD_H1;
|
|
}
|
|
else if (value == "H2")
|
|
{
|
|
result = PERIOD_H2;
|
|
}
|
|
else if (value == "H3")
|
|
{
|
|
result = PERIOD_H3;
|
|
}
|
|
else if (value == "H4")
|
|
{
|
|
result = PERIOD_H4;
|
|
}
|
|
else if (value == "H6")
|
|
{
|
|
result = PERIOD_H6;
|
|
}
|
|
else if (value == "H8")
|
|
{
|
|
result = PERIOD_H8;
|
|
}
|
|
else if (value == "H12")
|
|
{
|
|
result = PERIOD_H12;
|
|
}
|
|
else if (value == "D1")
|
|
{
|
|
result = PERIOD_D1;
|
|
}
|
|
else if (value == "W1")
|
|
{
|
|
result = PERIOD_W1;
|
|
}
|
|
else if (value == "MN1")
|
|
{
|
|
result = PERIOD_MN1;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts To String ...
|
|
*
|
|
* @param value: ENUM_TIMEFRAMES member ...
|
|
*
|
|
* @return ( string )
|
|
*/
|
|
string ToString(ENUM_TIMEFRAMES value)
|
|
{
|
|
//
|
|
string result = "";
|
|
|
|
//
|
|
string mPStr = EnumToString(value);
|
|
|
|
string mPStrParts[];
|
|
int partsCount = StringSplit(
|
|
mPStr,
|
|
StringGetCharacter("_", 0),
|
|
mPStrParts);
|
|
if (partsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = mPStrParts[1];
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve All Available Period as an Array ...s
|
|
int GetAllAvailablePeriods(
|
|
ENUM_TIMEFRAMES &result[] // Holds Result ...
|
|
)
|
|
{
|
|
//
|
|
Clean(result);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_M1,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_M2,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_M3,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_M4,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_M5,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_M6,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_M10,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_M12,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_M15,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_M20,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_M30,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_H1,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_H2,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_H3,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_H4,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_H6,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_H8,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_H12,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_D1,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_W1,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
Add(
|
|
PERIOD_MN1,
|
|
result
|
|
//
|
|
);
|
|
|
|
//
|
|
int mResult = ArraySize(result);
|
|
|
|
//
|
|
return mResult;
|
|
}
|
|
|
|
//
|
|
// Get Specific Time Frame Start Candle Time ...
|
|
datetime GetPeriodStartTime(
|
|
string mSymbol = NULL, // Specified Symbol ...
|
|
ENUM_TIMEFRAMES mPeriod = NULL, // Specified Period ...
|
|
datetime mTime = NULL // Specified Bar Time of Host Period ...
|
|
)
|
|
{
|
|
//
|
|
// Normalize Arg ...
|
|
mTime = NormalizeTime(mTime);
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
mPeriod = NormalizePeriod(mPeriod);
|
|
|
|
//
|
|
int barIndex = iBarShift(
|
|
mSymbol,
|
|
mPeriod,
|
|
mTime,
|
|
false //
|
|
);
|
|
|
|
//
|
|
datetime result = GetBarTime(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Nearest Period base on Given Period ...
|
|
ENUM_TIMEFRAMES GetNearestPeriod(ENUM_TIMEFRAMES mPeriod)
|
|
{
|
|
//
|
|
ENUM_TIMEFRAMES result = _Period;
|
|
|
|
//
|
|
mPeriod = NormalizePeriod(mPeriod);
|
|
|
|
//
|
|
switch (mPeriod)
|
|
{
|
|
//
|
|
case PERIOD_M1:
|
|
case PERIOD_M2:
|
|
case PERIOD_M3:
|
|
result = PERIOD_M5;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M4:
|
|
case PERIOD_M5:
|
|
case PERIOD_M6:
|
|
result = PERIOD_M10;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M10:
|
|
case PERIOD_M12:
|
|
case PERIOD_M15:
|
|
result = PERIOD_M20;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M20:
|
|
case PERIOD_M30:
|
|
result = PERIOD_H1;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H1:
|
|
case PERIOD_H2:
|
|
result = PERIOD_H3;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H3:
|
|
result = PERIOD_H4;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H4:
|
|
result = PERIOD_H6;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H6:
|
|
result = PERIOD_H8;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H8:
|
|
result = PERIOD_H12;
|
|
break;
|
|
|
|
//
|
|
default:
|
|
result = mPeriod;
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Mediest Period base on Given Period ...
|
|
ENUM_TIMEFRAMES GetMediestPeriod(ENUM_TIMEFRAMES mPeriod)
|
|
{
|
|
//
|
|
ENUM_TIMEFRAMES result = _Period;
|
|
|
|
//
|
|
mPeriod = NormalizePeriod(mPeriod);
|
|
|
|
//
|
|
switch (mPeriod)
|
|
{
|
|
//
|
|
case PERIOD_M1:
|
|
case PERIOD_M2:
|
|
case PERIOD_M3:
|
|
result = PERIOD_M10;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M4:
|
|
case PERIOD_M5:
|
|
case PERIOD_M6:
|
|
result = PERIOD_M15;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M10:
|
|
case PERIOD_M12:
|
|
case PERIOD_M15:
|
|
result = PERIOD_M30;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M20:
|
|
case PERIOD_M30:
|
|
result = PERIOD_H2;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H1:
|
|
case PERIOD_H2:
|
|
result = PERIOD_H4;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H3:
|
|
result = PERIOD_H6;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H4:
|
|
result = PERIOD_H8;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H6:
|
|
result = PERIOD_H12;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H8:
|
|
result = PERIOD_D1;
|
|
break;
|
|
|
|
//
|
|
default:
|
|
result = mPeriod;
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Longest Period base on Given Period ...
|
|
ENUM_TIMEFRAMES GetLongestPeriod(ENUM_TIMEFRAMES mPeriod)
|
|
{
|
|
//
|
|
ENUM_TIMEFRAMES result = _Period;
|
|
|
|
//
|
|
mPeriod = NormalizePeriod(mPeriod);
|
|
|
|
//
|
|
switch (mPeriod)
|
|
{
|
|
//
|
|
case PERIOD_M1:
|
|
case PERIOD_M2:
|
|
case PERIOD_M3:
|
|
result = PERIOD_M30;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M4:
|
|
case PERIOD_M5:
|
|
case PERIOD_M6:
|
|
result = PERIOD_H1;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M10:
|
|
case PERIOD_M12:
|
|
case PERIOD_M15:
|
|
result = PERIOD_H2;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M20:
|
|
case PERIOD_M30:
|
|
result = PERIOD_H4;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H1:
|
|
case PERIOD_H2:
|
|
result = PERIOD_H6;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H3:
|
|
result = PERIOD_H8;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H4:
|
|
result = PERIOD_H12;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H6:
|
|
result = PERIOD_D1;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H8:
|
|
result = PERIOD_W1;
|
|
break;
|
|
|
|
//
|
|
default:
|
|
result = mPeriod;
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Hindmost Period base on Given Period ...
|
|
ENUM_TIMEFRAMES GetHindMostPeriod(ENUM_TIMEFRAMES mPeriod)
|
|
{
|
|
//
|
|
ENUM_TIMEFRAMES result = _Period;
|
|
|
|
//
|
|
mPeriod = NormalizePeriod(mPeriod);
|
|
|
|
//
|
|
switch (mPeriod)
|
|
{
|
|
//
|
|
case PERIOD_M1:
|
|
case PERIOD_M2:
|
|
case PERIOD_M3:
|
|
result = PERIOD_H1;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M4:
|
|
case PERIOD_M5:
|
|
case PERIOD_M6:
|
|
result = PERIOD_H2;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M10:
|
|
case PERIOD_M12:
|
|
case PERIOD_M15:
|
|
result = PERIOD_H4;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M20:
|
|
case PERIOD_M30:
|
|
result = PERIOD_H6;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H1:
|
|
case PERIOD_H2:
|
|
result = PERIOD_H8;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H3:
|
|
result = PERIOD_H12;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H4:
|
|
result = PERIOD_D1;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H6:
|
|
result = PERIOD_W1;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H8:
|
|
result = PERIOD_MN1;
|
|
break;
|
|
|
|
//
|
|
default:
|
|
result = mPeriod;
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Specified Cycles Period related to Host Period ...
|
|
ENUM_TIMEFRAMES GetCyclePeriod(
|
|
ENUM_X_MARKET_CYCLES mCycle = NULL, // Specified Cycle
|
|
ENUM_TIMEFRAMES mPeriod = NULL // Host Period
|
|
)
|
|
{
|
|
//
|
|
ENUM_TIMEFRAMES result = NULL;
|
|
|
|
//
|
|
mPeriod = NormalizePeriod(mPeriod);
|
|
mCycle = NormalizeCycle(mCycle);
|
|
|
|
//
|
|
switch (mCycle)
|
|
{
|
|
//
|
|
// Short ...
|
|
case X_MARKET_CYCLE_SHORT:
|
|
result = GetNearestPeriod(mPeriod);
|
|
break;
|
|
|
|
//
|
|
// Medium ...
|
|
case X_MARKET_CYCLE_MEDIUM:
|
|
result = GetMediestPeriod(mPeriod);
|
|
break;
|
|
|
|
//
|
|
// Long ...
|
|
case X_MARKET_CYCLE_LONG:
|
|
result = GetLongestPeriod(mPeriod);
|
|
break;
|
|
|
|
//
|
|
// Hind ...
|
|
case X_MARKET_CYCLE_HIND:
|
|
result = GetHindMostPeriod(mPeriod);
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate a Cycle Length based on Host Period ...
|
|
int GetCycleLengthOn(
|
|
ENUM_TIMEFRAMES _hostPeriod,
|
|
ENUM_X_MARKET_CYCLES _cycle,
|
|
ENUM_X_PERIOD_METHOD _method,
|
|
ENUM_TIMEFRAMES _period //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// Validate ...
|
|
bool isValid =
|
|
//
|
|
IsValid(_hostPeriod) &&
|
|
IsValid(_method, _Period)
|
|
//
|
|
;
|
|
if (!isValid)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate Period ...
|
|
isValid =
|
|
_method != X_PERIOD_NONE &&
|
|
_cycle != X_MARKET_CYCLE_UNKNOWN;
|
|
if (!isValid)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
if (_method == X_PERIOD_AUTO)
|
|
{
|
|
//
|
|
_period = GetCyclePeriod(
|
|
_cycle,
|
|
_hostPeriod //
|
|
);
|
|
}
|
|
isValid = IsValid(_period);
|
|
if (!isValid)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int _hostPeriodSeconds = PeriodSeconds(_hostPeriod);
|
|
int _periodSeconds = PeriodSeconds(_period);
|
|
|
|
//
|
|
isValid = _periodSeconds >= _hostPeriodSeconds;
|
|
if (!isValid)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = _periodSeconds / _hostPeriodSeconds;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieve Sharp Change Info for Specified Period ...
|
|
*
|
|
* @param priceChange: double, required Price Change ...
|
|
* @param mPeriod: ENUM_TIMEFRAMES member, Specified Period ...
|
|
*
|
|
* @return ( int )
|
|
*/
|
|
int GetPeriodSharpData(
|
|
double &priceChange,
|
|
ENUM_TIMEFRAMES mPeriod = NULL //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
priceChange = 0.0;
|
|
|
|
//
|
|
mPeriod = NormalizePeriod(mPeriod);
|
|
|
|
//
|
|
switch (mPeriod)
|
|
{
|
|
//
|
|
case PERIOD_M1:
|
|
//
|
|
priceChange = 0.000006;
|
|
result = 14;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M2:
|
|
//
|
|
priceChange = 0.000006;
|
|
result = 14;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M3:
|
|
//
|
|
priceChange = 0.00007;
|
|
result = 14;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M4:
|
|
//
|
|
priceChange = 0.000007;
|
|
result = 14;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M5:
|
|
//
|
|
priceChange = 0.000009;
|
|
result = 14;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M6:
|
|
//
|
|
priceChange = 0.000009;
|
|
result = 14;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M10:
|
|
//
|
|
priceChange = 0.00001;
|
|
result = 12;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M12:
|
|
//
|
|
priceChange = 0.000011;
|
|
result = 11;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M15:
|
|
//
|
|
priceChange = 0.000011;
|
|
result = 9;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M20:
|
|
//
|
|
priceChange = 0.000012;
|
|
result = 9;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M30:
|
|
//
|
|
priceChange = 0.000012;
|
|
result = 7;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H1:
|
|
//
|
|
priceChange = 0.000013;
|
|
result = 5;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H2:
|
|
//
|
|
priceChange = 0.000013;
|
|
result = 5;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H3:
|
|
//
|
|
priceChange = 0.000014;
|
|
result = 5;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H4:
|
|
//
|
|
priceChange = 0.000014;
|
|
result = 5;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H6:
|
|
//
|
|
priceChange = 0.000015;
|
|
result = 5;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H8:
|
|
//
|
|
priceChange = 0.000017;
|
|
result = 5;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H12:
|
|
//
|
|
priceChange = 0.000017;
|
|
result = 5;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_D1:
|
|
//
|
|
priceChange = 0.000019;
|
|
result = 3;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_W1:
|
|
//
|
|
priceChange = 0.00002;
|
|
result = 3;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_MN1:
|
|
//
|
|
priceChange = 0.000021;
|
|
result = 3;
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// END Cycles ...
|
|
//
|
|
|
|
//
|
|
// START Collections ...
|
|
//
|
|
|
|
//
|
|
// Add Specified Item to Array ...
|
|
template <typename T>
|
|
int Add(
|
|
T item, // item want to add
|
|
T &buffer[] // Destination buffer
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
ArrayResize(
|
|
buffer,
|
|
ArraySize(buffer) + 1);
|
|
|
|
//
|
|
buffer[ArraySize(buffer) - 1] = item;
|
|
|
|
//
|
|
result = ArraySize(buffer);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
template <typename T>
|
|
int AddSpecific(
|
|
T item, // item want to add
|
|
T &buffer[] // Destination buffer
|
|
)
|
|
{
|
|
//
|
|
return Add(
|
|
item,
|
|
buffer //
|
|
);
|
|
}
|
|
template <typename T>
|
|
int AddRef(
|
|
T &item, // item want to add
|
|
T &buffer[] // Destination buffer
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
ArrayResize(
|
|
buffer,
|
|
ArraySize(buffer) + 1);
|
|
|
|
//
|
|
buffer[ArraySize(buffer) - 1] = item;
|
|
|
|
//
|
|
result = ArraySize(buffer);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Specified Array Has Childs or not ...
|
|
template <typename T>
|
|
bool HasChild(T &buffer[])
|
|
{
|
|
return IsValidSize(ArraySize(buffer));
|
|
}
|
|
template <typename T>
|
|
bool SpecificHasChild(T &buffer[])
|
|
{
|
|
return HasChild(buffer);
|
|
}
|
|
|
|
//
|
|
// Remove Specified Item from an Array ...
|
|
template <typename T>
|
|
bool Remove(
|
|
T item,
|
|
T &buffer[])
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int itemIndex = FindIndex(
|
|
item,
|
|
buffer);
|
|
if (itemIndex < 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = ArrayRemove(
|
|
buffer,
|
|
itemIndex,
|
|
1);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Clean Specified Array ...
|
|
template <typename T>
|
|
void Clean(T &buffer[])
|
|
{
|
|
//
|
|
ArrayResize(buffer, 0);
|
|
ArrayFree(buffer);
|
|
ZeroMemory(buffer);
|
|
}
|
|
template <typename T>
|
|
void SpecificClean(T &buffer[])
|
|
{
|
|
Clean(buffer);
|
|
}
|
|
|
|
//
|
|
// Copy Whole Content of Source to Dest array ...
|
|
template <typename T>
|
|
void Copy(
|
|
T &source[], // Source Buffer ...
|
|
T &dest[], // Dest Buffer ...
|
|
bool cleanDest = true // Force Clen Dest Buffer ...
|
|
)
|
|
{
|
|
//
|
|
if (cleanDest)
|
|
{
|
|
Clean(dest);
|
|
}
|
|
|
|
//
|
|
int sourceCount = ArraySize(source);
|
|
if (sourceCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < sourceCount; i++)
|
|
{
|
|
//
|
|
T iSource = source[i];
|
|
|
|
//
|
|
AddRef(
|
|
iSource,
|
|
dest);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Copy Items from a Buffer ...
|
|
template <typename T>
|
|
int Copy(
|
|
int start, // Start
|
|
int count, // Number of Items for read
|
|
T &source[], // Source Buffer
|
|
T &dest[], // Dest Buffer
|
|
bool forceClean = true, // Force To Clean buffer
|
|
bool forceStart = true // Force To Clean buffer
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (forceClean)
|
|
{
|
|
Clean(dest);
|
|
}
|
|
|
|
//
|
|
if (start < 0 && forceStart)
|
|
{
|
|
start = 0;
|
|
}
|
|
|
|
//
|
|
if (start >= ArraySize(source))
|
|
{
|
|
start = ArraySize(source) - 1;
|
|
}
|
|
|
|
//
|
|
if (count == 0)
|
|
{
|
|
count = ArraySize(source) - 1 - start;
|
|
}
|
|
|
|
//
|
|
if (start + count > ArraySize(source))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int beforeSize = ArraySize(dest);
|
|
|
|
//
|
|
bool asSeriesDest = ArrayGetAsSeries(dest);
|
|
bool asSeriesSource = ArrayGetAsSeries(source);
|
|
|
|
//
|
|
ArraySetAsSeries(dest, true);
|
|
ArraySetAsSeries(source, true);
|
|
|
|
//
|
|
ArrayCopy(
|
|
dest,
|
|
source,
|
|
0,
|
|
start,
|
|
count
|
|
//
|
|
);
|
|
|
|
//
|
|
int afterSize = ArraySize(dest);
|
|
|
|
//
|
|
result = afterSize - beforeSize;
|
|
|
|
//
|
|
ArraySetAsSeries(dest, asSeriesDest);
|
|
ArraySetAsSeries(source, asSeriesSource);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Copy Items from a Buffer ...
|
|
template <typename T>
|
|
int CopyRef(
|
|
int start, // Start
|
|
int count, // Number of Items for read
|
|
T &source[], // Source Buffer
|
|
T &dest[], // Dest Buffer
|
|
bool forceClean = true // Force To Clean buffer
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (forceClean)
|
|
{
|
|
Clean(dest);
|
|
}
|
|
|
|
//
|
|
if (start < 0)
|
|
{
|
|
start = 0;
|
|
}
|
|
|
|
//
|
|
if (start >= ArraySize(source))
|
|
{
|
|
start = ArraySize(source) - 1;
|
|
}
|
|
|
|
//
|
|
int beforeSize = ArraySize(dest);
|
|
|
|
//
|
|
bool asSeriesDest = ArrayGetAsSeries(dest);
|
|
bool asSeriesSource = ArrayGetAsSeries(source);
|
|
|
|
//
|
|
ArraySetAsSeries(dest, true);
|
|
ArraySetAsSeries(source, true);
|
|
|
|
//
|
|
for (int i = start; i < start + count; i++)
|
|
{
|
|
//
|
|
AddRef(
|
|
source[i],
|
|
dest
|
|
//
|
|
);
|
|
}
|
|
|
|
//
|
|
int afterSize = ArraySize(dest);
|
|
|
|
//
|
|
result = afterSize - beforeSize;
|
|
|
|
//
|
|
ArraySetAsSeries(dest, asSeriesDest);
|
|
ArraySetAsSeries(source, asSeriesSource);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrive Last Item of Specified Buffer ...
|
|
template <typename T>
|
|
bool GetLastItem(
|
|
T &item, // Holds Result
|
|
T &buffer[] // Specified Buffer
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int bufferSize = ArraySize(buffer);
|
|
if (bufferSize <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
item = buffer[bufferSize - 1];
|
|
|
|
//
|
|
result = true;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Remove Last Item of Specified Buffer ...
|
|
template <typename T>
|
|
bool RemoveLastItem(
|
|
T &buffer[] // Specified Buffer
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int count = ArraySize(buffer);
|
|
result = IsValidSize(count);
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
ArrayRemove(
|
|
buffer,
|
|
count - 1,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
void CleanupArray(
|
|
T &buffer[], // Buffer to Cleanup ...
|
|
int maxAllowed = 0 // Max Allowed Number of items ...
|
|
)
|
|
{
|
|
//
|
|
if (maxAllowed <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int count = ArraySize(buffer);
|
|
if (!IsValidSize(count) ||
|
|
count <= maxAllowed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
int mustRemove = count - maxAllowed;
|
|
if (!IsValidSize(mustRemove))
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
ArrayRemove(
|
|
buffer,
|
|
0,
|
|
mustRemove //
|
|
);
|
|
}
|
|
|
|
template <typename T>
|
|
void CleanupArray(
|
|
int &removedIndexes[],
|
|
T &buffer[] // Buffer to Cleanup ...
|
|
)
|
|
{
|
|
//
|
|
bool isValid = HasChild(buffer) &&
|
|
HasChild(removedIndexes);
|
|
if (!isValid)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < ArraySize(removedIndexes); i++)
|
|
{
|
|
//
|
|
int idx = removedIndexes[i];
|
|
if (IsValidIndex(idx) && ArraySize(buffer) > idx)
|
|
{
|
|
//
|
|
ArrayRemove(
|
|
buffer,
|
|
idx,
|
|
1 //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
Clean(removedIndexes);
|
|
}
|
|
|
|
//
|
|
// Search Array For Specific Item ...
|
|
template <typename T>
|
|
int FindIndex(
|
|
T item, // What is Search ...
|
|
T &buffer[] // Search in ...
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
int count = ArraySize(buffer);
|
|
if (count <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
T iT = buffer[i];
|
|
|
|
//
|
|
if (iT == item)
|
|
{
|
|
//
|
|
result = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
//
|
|
// Find Specific Item Index inside a Collection ...
|
|
template <typename T>
|
|
int FindIndex(
|
|
T &item, // Item to Find
|
|
const T &items[] // Items for Search
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
// Check Item Validation ...
|
|
if (!item.IsValid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int itemsCount = ArraySize(items);
|
|
if (itemsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < itemsCount; i++)
|
|
{
|
|
//
|
|
T iItem = items[i];
|
|
|
|
//
|
|
// Validate Item ...
|
|
if (!iItem.IsValid())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
bool isSame = item.IsSameAs(iItem);
|
|
if (isSame && result <= -1)
|
|
{
|
|
//
|
|
result = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check an Array Contains Specified Value ...
|
|
template <typename T>
|
|
bool Contains(
|
|
T item, // What is Search ...
|
|
T &buffer[] // Search in ...
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int idx = FindIndex(
|
|
item,
|
|
buffer);
|
|
result = idx > -1;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate a Buffer's Sum ...
|
|
template <typename T>
|
|
double GetSum(
|
|
T &buffer[], // the Buffer which required to search
|
|
int start = 0, // Start Index
|
|
int count = 0 // Count for Search
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
T tmp[];
|
|
int tmpCount = Copy(
|
|
start,
|
|
count,
|
|
buffer,
|
|
tmp
|
|
//
|
|
);
|
|
if (tmpCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate Summary ...
|
|
for (int i = 0; i < tmpCount; i++)
|
|
{
|
|
result += buffer[i];
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate a Buffer's Average ...
|
|
template <typename T>
|
|
double GetAverage(
|
|
T &buffer[], // the Buffer which required to search
|
|
int start = 0, // Start Index
|
|
int count = 0 // Count for Search
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
T tmp[];
|
|
int tmpCount = Copy(
|
|
start,
|
|
count,
|
|
buffer,
|
|
tmp
|
|
//
|
|
);
|
|
if (tmpCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate Summary ...
|
|
for (int i = 0; i < tmpCount; i++)
|
|
{
|
|
result += buffer[i];
|
|
}
|
|
|
|
//
|
|
// Calculate Average ...
|
|
result = result / tmpCount;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Get Max of Specific Loopback of a Buffer ...
|
|
template <typename T>
|
|
T GetMax(
|
|
T &buffer[], // the Buffer which required to search
|
|
int start = 0, // Start Index
|
|
int count = 0 // Count for Search
|
|
)
|
|
{
|
|
//
|
|
T result = 0;
|
|
|
|
//
|
|
if (count <= 0)
|
|
{
|
|
count = ArraySize(buffer);
|
|
}
|
|
|
|
//
|
|
T tmp[];
|
|
int tmpCount = Copy(
|
|
start,
|
|
count,
|
|
buffer,
|
|
tmp
|
|
//
|
|
);
|
|
if (tmpCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop Through LoopBack ...
|
|
for (int i = 0; i < tmpCount; i++)
|
|
{
|
|
//
|
|
T iValue = tmp[i];
|
|
|
|
//
|
|
result =
|
|
//
|
|
result == 0 || result < iValue
|
|
//
|
|
? iValue
|
|
//
|
|
: result
|
|
//
|
|
;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
template <typename T>
|
|
T GetMax(
|
|
T &buffer[], // the Buffer which required to search
|
|
int &index, // Item Index ...
|
|
int start = 0, // Start Index
|
|
int count = 0 // Count for Search
|
|
)
|
|
{
|
|
//
|
|
T result = 0;
|
|
index = -1;
|
|
|
|
//
|
|
if (count <= 0)
|
|
{
|
|
count = ArraySize(buffer);
|
|
}
|
|
|
|
//
|
|
T tmp[];
|
|
int tmpCount = Copy(
|
|
start,
|
|
count,
|
|
buffer,
|
|
tmp
|
|
//
|
|
);
|
|
if (tmpCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop Through LoopBack ...
|
|
for (int i = 0; i < tmpCount; i++)
|
|
{
|
|
//
|
|
T iValue = tmp[i];
|
|
|
|
//
|
|
bool isNew = result == 0;
|
|
bool canSet = isNew ||
|
|
(!isNew &&
|
|
result < iValue);
|
|
if (canSet)
|
|
{
|
|
//
|
|
index = i;
|
|
result = iValue;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
template <typename T>
|
|
T GetSpecifiedMax(
|
|
T &buffer[], // the Buffer which required to search
|
|
int start = 0, // Start Index
|
|
int count = 0 // Count for Search
|
|
)
|
|
{
|
|
return GetMax(
|
|
buffer,
|
|
start,
|
|
count //
|
|
);
|
|
}
|
|
template <typename T>
|
|
T GetSpecifiedMax(
|
|
T &buffer[], // the Buffer which required to search
|
|
int &index, // Item Index ...
|
|
int start = 0, // Start Index
|
|
int count = 0 // Count for Search
|
|
)
|
|
{
|
|
return GetMax(
|
|
buffer,
|
|
index,
|
|
start,
|
|
count //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Get Min of Specific Loopback of a Buffer ...
|
|
template <typename T>
|
|
T GetMin(
|
|
T &buffer[], // the Buffer which required to search
|
|
int start = 0, // Start Index
|
|
int count = 0 // Count for Search
|
|
)
|
|
{
|
|
//
|
|
T result = 0;
|
|
|
|
//
|
|
if (count <= 0)
|
|
{
|
|
count = ArraySize(buffer);
|
|
}
|
|
|
|
//
|
|
T tmp[];
|
|
int tmpCount = Copy(
|
|
start,
|
|
count,
|
|
buffer,
|
|
tmp
|
|
//
|
|
);
|
|
if (tmpCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop Through LoopBack ...
|
|
for (int i = 0; i < tmpCount; i++)
|
|
{
|
|
//
|
|
T iValue = tmp[i];
|
|
|
|
//
|
|
result =
|
|
//
|
|
result == 0 || result > iValue
|
|
//
|
|
? iValue
|
|
//
|
|
: result
|
|
//
|
|
;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
template <typename T>
|
|
T GetMin(
|
|
T &buffer[], // the Buffer which required to search
|
|
int &index, // Item Index ...
|
|
int start = 0, // Start Index
|
|
int count = 0 // Count for Search
|
|
)
|
|
{
|
|
//
|
|
T result = 0;
|
|
index = -1;
|
|
|
|
//
|
|
if (count <= 0)
|
|
{
|
|
count = ArraySize(buffer);
|
|
}
|
|
|
|
//
|
|
T tmp[];
|
|
int tmpCount = Copy(
|
|
start,
|
|
count,
|
|
buffer,
|
|
tmp
|
|
//
|
|
);
|
|
if (tmpCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop Through LoopBack ...
|
|
for (int i = 0; i < tmpCount; i++)
|
|
{
|
|
//
|
|
T iValue = tmp[i];
|
|
|
|
//
|
|
bool isNew = result == 0;
|
|
bool canSet = isNew ||
|
|
(!isNew &&
|
|
result > iValue);
|
|
if (canSet)
|
|
{
|
|
//
|
|
index = i;
|
|
result = iValue;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
template <typename T>
|
|
T GetSpecifiedMin(
|
|
T &buffer[], // the Buffer which required to search
|
|
int start = 0, // Start Index
|
|
int count = 0 // Count for Search
|
|
)
|
|
{
|
|
return GetMin(
|
|
buffer,
|
|
start,
|
|
count //
|
|
);
|
|
}
|
|
template <typename T>
|
|
T GetSpecifiedMin(
|
|
T &buffer[], // the Buffer which required to search
|
|
int &index, // Item Index ...
|
|
int start = 0, // Start Index
|
|
int count = 0 // Count for Search
|
|
)
|
|
{
|
|
return GetMin(
|
|
buffer,
|
|
index,
|
|
start,
|
|
count //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Find a Value less than Specified ...
|
|
template <typename T>
|
|
T FindLesserThan(
|
|
T value, // Specified Value ...
|
|
const T &source[], // Source ...
|
|
bool isDescend = false // Find Biggest Lesser Value ...
|
|
)
|
|
{
|
|
//
|
|
T result = -1;
|
|
|
|
//
|
|
int itemsCount = ArraySize(source);
|
|
if (itemsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Make a Copy of source ...
|
|
T tmp[];
|
|
|
|
//
|
|
ArrayResize(
|
|
tmp,
|
|
ArraySize(source) //
|
|
);
|
|
|
|
//
|
|
ArrayCopy(
|
|
tmp,
|
|
source //
|
|
);
|
|
|
|
//
|
|
// Sort Temp Buffer ...
|
|
ArraySort(tmp);
|
|
if (isDescend)
|
|
{
|
|
ArrayReverse(tmp);
|
|
}
|
|
|
|
//
|
|
int tmpCount = ArraySize(tmp);
|
|
for (int i = 0; i < tmpCount; i++)
|
|
{
|
|
//
|
|
T iValue = tmp[i];
|
|
|
|
//
|
|
if (iValue < value)
|
|
{
|
|
//
|
|
result = iValue;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
template <typename T>
|
|
T FindLesserThan(
|
|
T value, // Specified Value ...
|
|
int &index, // Item Index ...
|
|
const T &source[], // Source ...
|
|
bool isDescend = false // Find Biggest Lesser Value ...
|
|
)
|
|
{
|
|
//
|
|
T result = -1;
|
|
index = -1;
|
|
|
|
//
|
|
int itemsCount = ArraySize(source);
|
|
if (itemsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Make a Copy of source ...
|
|
T tmp[];
|
|
|
|
//
|
|
ArrayResize(
|
|
tmp,
|
|
ArraySize(source) //
|
|
);
|
|
|
|
//
|
|
ArrayCopy(
|
|
tmp,
|
|
source //
|
|
);
|
|
|
|
//
|
|
// Sort Temp Buffer ...
|
|
ArraySort(tmp);
|
|
if (isDescend)
|
|
{
|
|
ArrayReverse(tmp);
|
|
}
|
|
|
|
//
|
|
int tmpCount = ArraySize(tmp);
|
|
for (int i = 0; i < tmpCount; i++)
|
|
{
|
|
//
|
|
T iValue = tmp[i];
|
|
|
|
//
|
|
if (iValue < value)
|
|
{
|
|
//
|
|
index = i;
|
|
result = iValue;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find a Value less than Specified ...
|
|
template <typename T>
|
|
T FindBiggerThan(
|
|
T value, // Specified Value ...
|
|
const T &source[], // Source ...
|
|
bool isDescend = false // Find Smallest Bigger Value ...
|
|
)
|
|
{
|
|
//
|
|
T result = -1;
|
|
|
|
//
|
|
int itemsCount = ArraySize(source);
|
|
if (itemsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Make a Copy of source ...
|
|
T tmp[];
|
|
|
|
//
|
|
ArrayResize(
|
|
tmp,
|
|
ArraySize(source) //
|
|
);
|
|
|
|
//
|
|
ArrayCopy(
|
|
tmp,
|
|
source //
|
|
);
|
|
|
|
//
|
|
// Sort Temp Buffer ...
|
|
ArraySort(tmp);
|
|
if (!isDescend)
|
|
{
|
|
ArrayReverse(tmp);
|
|
}
|
|
|
|
//
|
|
int tmpCount = ArraySize(tmp);
|
|
for (int i = 0; i < tmpCount; i++)
|
|
{
|
|
//
|
|
T iValue = tmp[i];
|
|
|
|
//
|
|
if (iValue > value)
|
|
{
|
|
//
|
|
result = iValue;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
template <typename T>
|
|
T FindBiggerThan(
|
|
T value, // Specified Value ...
|
|
int &index, // Item Index ...
|
|
const T &source[], // Source ...
|
|
bool isDescend = false // Find Smallest Bigger Value ...
|
|
)
|
|
{
|
|
//
|
|
T result = -1;
|
|
index = -1;
|
|
|
|
//
|
|
int itemsCount = ArraySize(source);
|
|
if (itemsCount <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Make a Copy of source ...
|
|
T tmp[];
|
|
|
|
//
|
|
ArrayResize(
|
|
tmp,
|
|
ArraySize(source) //
|
|
);
|
|
|
|
//
|
|
ArrayCopy(
|
|
tmp,
|
|
source //
|
|
);
|
|
|
|
//
|
|
// Sort Temp Buffer ...
|
|
ArraySort(tmp);
|
|
if (!isDescend)
|
|
{
|
|
ArrayReverse(tmp);
|
|
}
|
|
|
|
//
|
|
int tmpCount = ArraySize(tmp);
|
|
for (int i = 0; i < tmpCount; i++)
|
|
{
|
|
//
|
|
T iValue = tmp[i];
|
|
|
|
//
|
|
if (iValue > value)
|
|
{
|
|
//
|
|
index = i;
|
|
result = iValue;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Same Values in Array ...
|
|
template <typename T>
|
|
void FindSames(
|
|
T &result[], // Holds Result ...
|
|
T &source[], // Source ...
|
|
int verifications = 3 // Number of Consequence Repeat ...
|
|
)
|
|
{
|
|
//
|
|
Clean(result);
|
|
|
|
//
|
|
// TenkanSen Flats ...
|
|
int sourceCount = ArraySize(source);
|
|
if (sourceCount > verifications)
|
|
{
|
|
//
|
|
T mLast = 0;
|
|
int mVerified = 0;
|
|
for (int i = 0; i < sourceCount; i++)
|
|
{
|
|
//
|
|
T iVal = source[i];
|
|
if (mLast == 0)
|
|
{
|
|
mLast = iVal;
|
|
}
|
|
else if (mLast == iVal)
|
|
{
|
|
mVerified++;
|
|
}
|
|
else
|
|
{
|
|
mLast = iVal;
|
|
mVerified = 0;
|
|
}
|
|
|
|
//
|
|
if (iVal == mLast && mVerified >= verifications)
|
|
{
|
|
//
|
|
Add(
|
|
iVal,
|
|
result);
|
|
|
|
//
|
|
mLast = 0;
|
|
mVerified = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Add an Item to a Buffer if not Exists ...
|
|
void AddIfNotExists(
|
|
double value,
|
|
double &values[],
|
|
double smoothingPoint = 3 //
|
|
)
|
|
{
|
|
//
|
|
double smoothingValue = smoothingPoint * GetPoints(_Symbol);
|
|
|
|
//
|
|
int valuesCount = ArraySize(values);
|
|
if (valuesCount <= 0)
|
|
{
|
|
//
|
|
Add(value,
|
|
values);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
bool isExists = false;
|
|
for (int i = 0; i < valuesCount; i++)
|
|
{
|
|
//
|
|
double iVal = values[i];
|
|
|
|
//
|
|
double diff = MathAbs(iVal - value);
|
|
|
|
//
|
|
if (iVal == value || diff < smoothingValue)
|
|
{
|
|
//
|
|
isExists = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
if (!isExists)
|
|
{
|
|
//
|
|
Add(value,
|
|
values);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Add a Buffers Child to another Buffer
|
|
// if it's not Contains them ...
|
|
void AddsIfNotExists(
|
|
double &source[],
|
|
double &dest[],
|
|
double smoothingPoint = 3)
|
|
{
|
|
//
|
|
double smoothingValue = smoothingPoint * GetPoints(_Symbol);
|
|
|
|
//
|
|
int sourceCount = ArraySize(source);
|
|
if (sourceCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < sourceCount; i++)
|
|
{
|
|
//
|
|
double iSource = source[i];
|
|
|
|
//
|
|
AddIfNotExists(
|
|
iSource,
|
|
dest,
|
|
smoothingPoint);
|
|
}
|
|
}
|
|
|
|
//
|
|
// END Collections ...
|
|
//
|
|
|
|
//
|
|
// START Buffers ...
|
|
//
|
|
|
|
//
|
|
template <typename T>
|
|
bool IsSame(
|
|
T &buffer[], // Search Buffer
|
|
int count = 5, // Number of Searchs
|
|
int start = 0 // Start ...
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int bufferSize = ArraySize(buffer);
|
|
result = bufferSize > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Validate Count ...
|
|
result = start + count < bufferSize;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
T iTem = buffer[start];
|
|
for (int i = start; i < start + count; i++)
|
|
{
|
|
//
|
|
if (iTem != buffer[i])
|
|
{
|
|
result = false;
|
|
break;
|
|
}
|
|
|
|
//
|
|
if (!result)
|
|
{
|
|
result = true;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check first Cross Over second at index ...
|
|
bool IsCrossedOver(
|
|
const double &first[], // the buffer which check crossing over second buffer
|
|
const double &second[], // first buffer checks based on this buffer
|
|
const int index = 0 // check crosses in specific index
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = first[index] > second[index] &&
|
|
!(first[index + 1] > second[index + 1]);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check first is Over second at index ...
|
|
bool IsOver(
|
|
const double &first[], // the buffer which check over second buffer
|
|
const double &second[], // first buffer checks based on this buffer
|
|
const int index = 0 // check crosses in specific index
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = first[index] > second[index] &&
|
|
first[index + 1] > second[index + 1];
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check first Cross Under second at index ...
|
|
bool IsCrossedUnder(
|
|
const double &first[], // the buffer which check crossing under second buffer
|
|
const double &second[], // first buffer checks based on this buffer
|
|
const int index = 0 // check crosses in specific index
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = first[index] < second[index] &&
|
|
!(first[index + 1] < second[index + 1]);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check first is Under second at index ...
|
|
bool IsUnder(
|
|
const double &first[], // the buffer which check under second buffer
|
|
const double &second[], // first buffer checks based on this buffer
|
|
const int index = 0 // check crosses in specific index
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = first[index] < second[index] &&
|
|
first[index + 1] < second[index + 1];
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check if a Value Increasing in Loopback ...
|
|
bool IsIncreasing(
|
|
const double &buffer[], // the Buffer which required to search
|
|
int from = -1, // Last Time Index
|
|
int to = -1 // Fisrs Tima Index
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (from == -1)
|
|
{
|
|
from = ArraySize(buffer) - 1;
|
|
}
|
|
|
|
//
|
|
if (to == -1)
|
|
{
|
|
to = 0;
|
|
}
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (
|
|
from <= to ||
|
|
ArraySize(buffer) < from + 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop through Items ...
|
|
double toValue = buffer[to];
|
|
double fromValue = buffer[from];
|
|
result = toValue >= fromValue;
|
|
for (int i = to + 1; i <= from - 1; i++)
|
|
{
|
|
//
|
|
double iValue = buffer[i];
|
|
bool isPassed = toValue >= iValue;
|
|
|
|
//
|
|
bool isIIncreasing = IsIncreasing(
|
|
buffer,
|
|
from,
|
|
i //
|
|
);
|
|
|
|
//
|
|
// Check Result ...
|
|
result = result && isPassed && isIIncreasing;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check if a Value Decreasing in Loopback ...
|
|
bool IsDecreasing(
|
|
const double &buffer[], // the Buffer which required to search
|
|
int from = -1, // Last Time Index
|
|
int to = -1 // Fisrs Tima Index
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
if (from == -1)
|
|
{
|
|
from = ArraySize(buffer) - 1;
|
|
}
|
|
|
|
//
|
|
if (to == -1)
|
|
{
|
|
to = 0;
|
|
}
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (
|
|
from <= to ||
|
|
ArraySize(buffer) < from + 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop through Items ...
|
|
double toValue = buffer[to];
|
|
double fromValue = buffer[from];
|
|
result = toValue <= fromValue;
|
|
for (int i = to + 1; i <= from - 1; i++)
|
|
{
|
|
//
|
|
double iValue = buffer[i];
|
|
bool isPassed = toValue <= iValue;
|
|
|
|
//
|
|
bool isIDecreasing = IsDecreasing(
|
|
buffer,
|
|
from,
|
|
i //
|
|
);
|
|
|
|
//
|
|
// Check Result ...
|
|
result = result && isPassed && isIDecreasing;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool IsTrendingUp(
|
|
const double &buffer1[], // First Buffer
|
|
const double &buffer2[] // Seccend Buffer
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int buffer1Count = ArraySize(buffer1);
|
|
int buffer2Count = ArraySize(buffer2);
|
|
if (buffer1Count <= 0 || buffer2Count <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = MathMin(buffer1Count, buffer2Count);
|
|
if (count <= 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int upCounts = 0;
|
|
int downCounts = 0;
|
|
double value = MathAbs(buffer1[0] - buffer2[0]);
|
|
for (int i = 1; i < count; i++)
|
|
{
|
|
//
|
|
double iValue = MathAbs(buffer1[i] - buffer2[i]);
|
|
|
|
//
|
|
if (value > iValue)
|
|
{
|
|
upCounts++;
|
|
}
|
|
|
|
//
|
|
if (value < iValue)
|
|
{
|
|
downCounts++;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = upCounts > 1 && upCounts > downCounts;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool IsTrendingDown(
|
|
const double &buffer1[], // First Buffer
|
|
const double &buffer2[] // Seccend Buffer
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int buffer1Count = ArraySize(buffer1);
|
|
int buffer2Count = ArraySize(buffer2);
|
|
if (buffer1Count <= 0 || buffer2Count <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = MathMin(buffer1Count, buffer2Count);
|
|
if (count <= 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int upCounts = 0;
|
|
int downCounts = 0;
|
|
double value = MathAbs(buffer1[0] - buffer2[0]);
|
|
for (int i = 1; i < count; i++)
|
|
{
|
|
//
|
|
double iValue = MathAbs(buffer1[i] - buffer2[i]);
|
|
|
|
//
|
|
if (value > iValue)
|
|
{
|
|
upCounts++;
|
|
}
|
|
|
|
//
|
|
if (value < iValue)
|
|
{
|
|
downCounts++;
|
|
}
|
|
}
|
|
|
|
//
|
|
result = downCounts > 1 && downCounts > upCounts;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate Slope of Specified Buffer at Specified Index ...
|
|
double GetSlope(
|
|
const double &buffer[], // Buffer
|
|
int from, // In Past Index ...
|
|
int to // In Past Index ...
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
if (from > ArraySize(buffer) || to > ArraySize(buffer))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double toValue = buffer[to];
|
|
double fromValue = buffer[from];
|
|
double deltaValue = toValue - fromValue;
|
|
double deltaTime = from - to;
|
|
|
|
//
|
|
result = deltaValue / deltaTime;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// END Buffers ...
|
|
//
|
|
|
|
//
|
|
// START Time ...
|
|
//
|
|
|
|
//
|
|
// Converts Time to Seconds ...
|
|
ulong TimeToSeconds(
|
|
datetime time // Specify time to Convert ...
|
|
)
|
|
{
|
|
//
|
|
ulong result = (ulong)time;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
ulong TimeToSeconds(
|
|
MqlDateTime &time // Specify time to Convert ...
|
|
)
|
|
{
|
|
//
|
|
datetime dTime = StructToTime(time);
|
|
|
|
//
|
|
ulong result = TimeToSeconds(dTime);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Converts Seconds To Time ...
|
|
datetime SecondsToTime(
|
|
ulong seconds // Specify Seconds to Convert ...
|
|
)
|
|
{
|
|
//
|
|
datetime result = (datetime)seconds;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
MqlDateTime SecondsToStruct(
|
|
ulong seconds // Specify Seconds to Convert ...
|
|
)
|
|
{
|
|
//
|
|
datetime dTime = SecondsToTime(seconds);
|
|
|
|
//
|
|
MqlDateTime result = {};
|
|
TimeToStruct(
|
|
dTime,
|
|
result);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Converts Time to MilliSeconds ...
|
|
ulong TimeToMilliSeconds(
|
|
datetime time // Specify time to Convert ...
|
|
)
|
|
{
|
|
//
|
|
ulong result = TimeToSeconds(time) * 1000;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
ulong TimeToMilliSeconds(
|
|
MqlDateTime &time // Specify time to Convert ...
|
|
)
|
|
{
|
|
//
|
|
datetime dTime = StructToTime(time);
|
|
|
|
//
|
|
ulong result = TimeToMilliSeconds(dTime);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Converts MillisSeconds to Time ...
|
|
datetime MilliSecondsToTiem(
|
|
ulong milliSeconds // Specify MilliSeconds to Convert ...
|
|
)
|
|
{
|
|
//
|
|
ulong seconds = milliSeconds / 1000;
|
|
|
|
//
|
|
datetime result = SecondsToTime(seconds);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
MqlDateTime MilliSecondsToStruct(
|
|
ulong milliSeconds // Specify MilliSeconds to Convert ...
|
|
)
|
|
{
|
|
//
|
|
datetime dTime = MilliSecondsToTiem(milliSeconds);
|
|
|
|
//
|
|
MqlDateTime result = {};
|
|
TimeToStruct(
|
|
dTime,
|
|
result);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Converts Hours to Seconds ...
|
|
int HoursToSeconds(int value)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
if (value < 0)
|
|
{
|
|
value = 0;
|
|
}
|
|
|
|
//
|
|
if (value == 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = value * 60 * 60;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve DateTime Structure ...
|
|
MqlDateTime GetCurrentTime()
|
|
{
|
|
//
|
|
MqlDateTime result = {};
|
|
|
|
//
|
|
datetime cTime = TimeCurrent();
|
|
TimeToStruct(cTime, result);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Current Time as Seconds ...
|
|
ulong GetCurrentTimeAsSeconds()
|
|
{
|
|
//
|
|
datetime time = TimeCurrent();
|
|
|
|
//
|
|
ulong result = TimeToSeconds(time);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Current Time as MilliSeconds ...
|
|
ulong GetCurrentTimeAsMilliSeconds()
|
|
{
|
|
//
|
|
datetime time = TimeCurrent();
|
|
|
|
//
|
|
ulong result = TimeToMilliSeconds(time);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int GetLocalOffset()
|
|
{
|
|
//
|
|
MqlDateTime cTimeStruct;
|
|
datetime cTime = TimeCurrent(cTimeStruct);
|
|
|
|
//
|
|
MqlDateTime cLTimeStruct;
|
|
datetime cLTime = TimeLocal(cLTimeStruct);
|
|
|
|
//
|
|
cTimeStruct.sec = 0;
|
|
cTime = StructToTime(cTimeStruct);
|
|
|
|
//
|
|
cLTimeStruct.sec = 0;
|
|
cLTime = StructToTime(cLTimeStruct);
|
|
|
|
//
|
|
int result = ((int)cLTime - (int)cTime);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int GetUTCRequiredTimeOffset()
|
|
{
|
|
//
|
|
int utcOffset = TimeGMTOffset();
|
|
int localOffset = GetLocalOffset();
|
|
|
|
//
|
|
int result = utcOffset + localOffset;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
datetime GetUTCTime(
|
|
datetime time = NULL,
|
|
bool applyTradeServerTime = false //
|
|
)
|
|
{
|
|
//
|
|
datetime result = NULL;
|
|
|
|
//
|
|
NormalizeTime(time);
|
|
|
|
//
|
|
datetime cTime = TimeCurrent();
|
|
datetime cTimeLocal = TimeLocal();
|
|
|
|
//
|
|
int cLocalOffset = ((int)cTimeLocal - (int)cTime);
|
|
int gmtOffset = TimeGMTOffset();
|
|
int offsetDelte = gmtOffset + cLocalOffset;
|
|
int requiredUTCOffset = GetUTCRequiredTimeOffset();
|
|
if (requiredUTCOffset > 0)
|
|
{
|
|
requiredUTCOffset = -1 * requiredUTCOffset;
|
|
}
|
|
|
|
//
|
|
int timeSeconds = (int)time;
|
|
int resultSeconds = timeSeconds + requiredUTCOffset;
|
|
|
|
//
|
|
result = (datetime)(resultSeconds);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve only Hour and Minute as String ...
|
|
string GetTimeString(
|
|
datetime time = NULL //
|
|
)
|
|
{
|
|
//
|
|
NormalizeTime(time);
|
|
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
MqlDateTime tStruct;
|
|
bool isStructed = TimeToStruct(time, tStruct);
|
|
if (!isStructed)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string hour = ToString(tStruct.hour);
|
|
hour =
|
|
StringLen(hour) == 1
|
|
? "0" + hour
|
|
: hour;
|
|
|
|
//
|
|
string minute = ToString(tStruct.min);
|
|
minute =
|
|
StringLen(minute) == 1
|
|
? "0" + minute
|
|
: minute;
|
|
|
|
//
|
|
result = hour + ":" + minute;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Converts a Date time to File Format ...
|
|
string ToFormatString(
|
|
datetime mTime,
|
|
string separator = "_" //
|
|
)
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
if (!IsValid(mTime))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
MqlDateTime timeStruct;
|
|
bool isConverts = TimeToStruct(
|
|
mTime,
|
|
timeStruct //
|
|
);
|
|
if (!isConverts)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string year = ToString(timeStruct.year);
|
|
string month = ToString(timeStruct.mon);
|
|
string day = ToString(timeStruct.day);
|
|
string hour = ToString(timeStruct.hour);
|
|
string minute = ToString(timeStruct.min);
|
|
string second = ToString(timeStruct.sec);
|
|
|
|
//
|
|
result =
|
|
//
|
|
// Year ...
|
|
year + separator +
|
|
//
|
|
// Month ...
|
|
(StringLen(month) == 1
|
|
? "0" + month
|
|
: month) +
|
|
separator +
|
|
//
|
|
// Day ...
|
|
(StringLen(day) == 1
|
|
? "0" + day
|
|
: day) +
|
|
separator +
|
|
//
|
|
// Hour ...
|
|
(StringLen(hour) == 1
|
|
? "0" + hour
|
|
: hour) +
|
|
separator +
|
|
//
|
|
// Minute ...
|
|
(StringLen(minute) == 1
|
|
? "0" + minute
|
|
: minute) +
|
|
separator +
|
|
//
|
|
// Seconds ...
|
|
(StringLen(second) == 1
|
|
? "0" + second
|
|
: second) +
|
|
separator +
|
|
//
|
|
""
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Converts an String Represetation of Time (00:00) to Date Time ..
|
|
*
|
|
* @param value: String ...
|
|
*
|
|
* @return ( datetime )
|
|
*/
|
|
datetime ParseDateTimeFromTimeString(string value)
|
|
{
|
|
//
|
|
datetime result = NULL;
|
|
|
|
//
|
|
if (!IsValid(value))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Signalling Time ...
|
|
MqlDateTime cTime;
|
|
bool isTimeRecieved = TimeCurrent(cTime);
|
|
if (!isTimeRecieved)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Split ...
|
|
string parts[];
|
|
int partsCount = SplitContent(
|
|
parts,
|
|
value,
|
|
":"
|
|
//
|
|
);
|
|
if (!IsValidSize(partsCount))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int hour = 0;
|
|
int minute = 0;
|
|
if (partsCount >= 1)
|
|
{
|
|
hour = (int)(parts[0]);
|
|
}
|
|
if (partsCount >= 2)
|
|
{
|
|
minute = (int)(parts[1]);
|
|
}
|
|
|
|
//
|
|
cTime.day_of_week = 0;
|
|
cTime.day_of_year = 0;
|
|
|
|
//
|
|
cTime.hour = hour;
|
|
cTime.min = minute;
|
|
|
|
//
|
|
result = StructToTime(cTime);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Specific Time in Range of another Time ...
|
|
bool IsTimeInRange(
|
|
datetime currentTime = NULL,
|
|
datetime startTime = NULL,
|
|
datetime stopTime = NULL //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Normallize Current Time ...
|
|
currentTime = NormalizeTime(currentTime);
|
|
|
|
//
|
|
result = !IsValid(startTime) &&
|
|
!IsValid(stopTime);
|
|
if (result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = IsValid(startTime) &&
|
|
IsValid(stopTime);
|
|
if (!result)
|
|
{
|
|
//
|
|
result = IsValid(startTime) &&
|
|
currentTime >= startTime;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = currentTime >= startTime &&
|
|
currentTime < stopTime;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
bool IsTimeInRange(
|
|
datetime currentTime,
|
|
string startTime,
|
|
string endTime //
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = IsValid(startTime) &&
|
|
IsValid(endTime);
|
|
if (!result)
|
|
{
|
|
//
|
|
// Here Since there isnot provide any
|
|
// data source we pass result as true ...
|
|
result = true;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Converts String Representation to Time ...
|
|
datetime st = ParseDateTimeFromTimeString(startTime);
|
|
datetime et = ParseDateTimeFromTimeString(endTime);
|
|
|
|
//
|
|
result = IsTimeInRange(
|
|
currentTime,
|
|
st,
|
|
et //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// END Time ...
|
|
//
|
|
|
|
//
|
|
// START Price ...
|
|
//
|
|
|
|
//
|
|
// Get 1 Pip in Price Value ...
|
|
double GetPipPrice(
|
|
string mSymbol = NULL // Trading Symbol
|
|
)
|
|
{
|
|
//
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
|
|
//
|
|
double symbolPoint = GetPoints(mSymbol);
|
|
int symbolDigits = GetDigits(mSymbol);
|
|
|
|
//
|
|
double result = symbolPoint;
|
|
if (symbolDigits == 3 || symbolDigits == 5)
|
|
{
|
|
result *= 10;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Calculate Applied Price ...
|
|
*
|
|
* @param mType: ENUM_X_PRICE member, Price Type ...
|
|
* @param mOpen: double collection, Open Prices ...
|
|
* @param mHigh: double collection, High Prices ...
|
|
* @param mLow: double collection, Low Prices ...
|
|
* @param mClose: double collection, Close Prices ...
|
|
* @param barIndex: int, Index ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double GetAppliedPrice(
|
|
ENUM_X_PRICE mType, // Type of Price Selection
|
|
double &mOpen[], // Open Prices
|
|
double &mHigh[], // High Preices
|
|
double &mLow[], // Low Prices
|
|
double &mClose[], // Close Prices
|
|
int barIndex // Bar Index
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
switch (mType)
|
|
{
|
|
//
|
|
case X_PRICE_NONE:
|
|
result = 0;
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_HIGH:
|
|
result = mHigh[barIndex];
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_OPEN:
|
|
result = mOpen[barIndex];
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_CLOSE:
|
|
result = mClose[barIndex];
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_LOW:
|
|
result = mLow[barIndex];
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_UP:
|
|
result = MathMax(mOpen[barIndex], mClose[barIndex]);
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_DOWN:
|
|
result = MathMin(mOpen[barIndex], mClose[barIndex]);
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_MEDIAN:
|
|
result = ((mHigh[barIndex] + mLow[barIndex]) / 2.0);
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_BODY_MEDIAN:
|
|
result = ((mOpen[barIndex] + mClose[barIndex]) / 2.0);
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_TYPICAL:
|
|
result = ((mHigh[barIndex] + mLow[barIndex] + mClose[barIndex]) / 3.0);
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_WEIGHTED:
|
|
result = (((mHigh[barIndex] + mLow[barIndex] + mClose[barIndex] + mClose[barIndex]) / 4.0));
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Calculate Applied Price ...
|
|
*
|
|
* @param mType: ENUM_X_PRICE member, Price Type ...
|
|
* @param mOpen: double, Open Price ...
|
|
* @param mHigh: double, High Price ...
|
|
* @param mLow: double, Low Price ...
|
|
* @param mClose: double, Close Price ...
|
|
* @param barIndex: int, Index ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double GetAppliedPrice(
|
|
ENUM_X_PRICE mType, // Type of Price Selection
|
|
double mOpen, // Open Prices
|
|
double mHigh, // High Preices
|
|
double mLow, // Low Prices
|
|
double mClose // Close Prices
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
switch (mType)
|
|
{
|
|
//
|
|
case X_PRICE_NONE:
|
|
result = 0;
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_HIGH:
|
|
result = mHigh;
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_OPEN:
|
|
result = mOpen;
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_CLOSE:
|
|
result = mClose;
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_LOW:
|
|
result = mLow;
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_UP:
|
|
result = MathMax(mOpen, mClose);
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_DOWN:
|
|
result = MathMin(mOpen, mClose);
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_MEDIAN:
|
|
result = ((mHigh + mLow) / 2.0);
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_BODY_MEDIAN:
|
|
result = ((mOpen + mClose) / 2.0);
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_TYPICAL:
|
|
result = ((mHigh + mLow + mClose) / 3.0);
|
|
break;
|
|
|
|
//
|
|
case X_PRICE_WEIGHTED:
|
|
result = (((mHigh + mLow + mClose + mClose) / 4.0));
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Calculate Applied Price ...
|
|
*
|
|
* @param mSymbol: string, Specified Symbol ...
|
|
* @param mPeriod: ENUM_TIMEFRAMES member, Specified PEriod ...
|
|
* @param barIndex: int, Specified Bar Index ...
|
|
* @param mType: ENUM_X_PRICE member, Specified Price Type ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double GetAppliedPrice(
|
|
string mSymbol = NULL, // Symbol
|
|
ENUM_TIMEFRAMES mPeriod = NULL, // Period
|
|
int barIndex = 0, // Bar Index
|
|
ENUM_X_PRICE mType = X_PRICE_CLOSE // Type of Price Selection,
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
mPeriod = NormalizePeriod(mPeriod);
|
|
barIndex = NormalizeInt(barIndex, 0);
|
|
|
|
//
|
|
bool has = IsValid(mType);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
double open = iOpen(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
double high = iHigh(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
double low = iLow(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
double close = iClose(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
// Retrieve Applied Price ...
|
|
result = GetAppliedPrice(
|
|
mType,
|
|
open,
|
|
high,
|
|
low,
|
|
close //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Calculate Applied Price ...
|
|
*
|
|
* @param mSymbol: string, Specified Symbol ...
|
|
* @param mPeriod: ENUM_TIMEFRAMES member, Specified PEriod ...
|
|
* @param time: int, Specified Bar Time ...
|
|
* @param mType: ENUM_X_PRICE member, Specified Price Type ...
|
|
*
|
|
* @return ( double )
|
|
*/
|
|
double GetAppliedPrice(
|
|
string mSymbol = NULL, // Symbol
|
|
ENUM_TIMEFRAMES mPeriod = NULL, // Period
|
|
datetime mTime = NULL, // Bar Time
|
|
ENUM_X_PRICE mType = X_PRICE_CLOSE // Type of Price Selection,
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
mTime = NormalizeTime(mTime);
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
mPeriod = NormalizePeriod(mPeriod);
|
|
|
|
//
|
|
bool has = IsValid(mType);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int barIndex = GetBarIndex(
|
|
mSymbol,
|
|
mPeriod,
|
|
mTime //
|
|
);
|
|
has = IsValidIndex(barIndex);
|
|
if (!has)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Applied Price ...
|
|
result = GetAppliedPrice(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex,
|
|
mType //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// END Price ...
|
|
//
|
|
|
|
//
|
|
// START Bar ...
|
|
//
|
|
|
|
/**
|
|
* Retrieve Specific Bar's Time ...
|
|
*
|
|
* @param mSymbol: string, Provided Symbol ...
|
|
* @param mPeriod: ENUM_TIMEFRAMES member, Provided Period ...
|
|
* @param barIndex: int, Provided Bar Index ...
|
|
*
|
|
* @return ( datetime )
|
|
*/
|
|
datetime GetBarTime(
|
|
string mSymbol = NULL, // Specify Symbol
|
|
ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame
|
|
int barIndex = 0 // Specify Bar Index
|
|
)
|
|
{
|
|
//
|
|
// Validate and Normalize Args ...
|
|
|
|
//
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
mPeriod = NormalizePeriod(mPeriod);
|
|
|
|
//
|
|
// Retrieve Bar Time ...
|
|
datetime result = iTime(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieve Specific Bar's Index ...
|
|
*
|
|
* @param mSymbol: string, Provided Symbol ...
|
|
* @param mPeriod: ENUM_TIMEFRAMES member, Provided Period ...
|
|
* @param barTime: datetime, Provided Bar Time ...
|
|
*
|
|
* @return ( datetime )
|
|
*/
|
|
int GetBarIndex(
|
|
string mSymbol = NULL, // Specify Symbol
|
|
ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame
|
|
datetime barTime = NULL // Specify Bar Time
|
|
)
|
|
{
|
|
//
|
|
// Validate and Normalize Args ...
|
|
|
|
//
|
|
mSymbol = NormalizeSymbol(mSymbol);
|
|
mPeriod = NormalizePeriod(mPeriod);
|
|
|
|
//
|
|
// Retrieve Bar Time ...
|
|
int result = iBarShift(
|
|
mSymbol,
|
|
mPeriod,
|
|
barTime //
|
|
);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// EN Bar ...
|
|
//
|
|
|
|
//
|