4430 lines
83 KiB
Plaintext
4430 lines
83 KiB
Plaintext
///////////////////////////////////////////////////////
|
|
//
|
|
// SaherElm IT Center MQL5 Common Library
|
|
// --------------------------------------
|
|
// Name: XCommon
|
|
// 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
|
|
|
|
//
|
|
// START Inputs ...
|
|
//
|
|
|
|
//
|
|
// END Inputs ...
|
|
//
|
|
|
|
//
|
|
// Include Models Library ...
|
|
#include "x-saherelm.models.lib.mq5"
|
|
|
|
//
|
|
// START Global Definitions: Variables, Properties and etc ...
|
|
//
|
|
//
|
|
// END Global Definitions: Variables, Properties and etc ...
|
|
//
|
|
|
|
//
|
|
// START Provided Functions ...
|
|
//
|
|
|
|
//
|
|
// Detect is new Candle or not ...
|
|
bool IsNewCandle()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
static int barsOnChart = 0;
|
|
int currentBarsOnChart = Bars(_Symbol, _Period);
|
|
result = currentBarsOnChart > barsOnChart;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
barsOnChart = currentBarsOnChart;
|
|
result = true;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrive Ask Price ...
|
|
double GetAsk()
|
|
{
|
|
return SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
|
}
|
|
double GetAsk(
|
|
string symbol // selected symbol for calculations
|
|
)
|
|
{
|
|
//
|
|
double result = SymbolInfoDouble(symbol, SYMBOL_ASK);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Bid Price ...
|
|
double GetBid()
|
|
{
|
|
return SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
|
}
|
|
double GetBid(
|
|
string symbol // selected symbol for calculations
|
|
)
|
|
{
|
|
//
|
|
double result = SymbolInfoDouble(symbol, SYMBOL_BID);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate and Retrieve Spread Price ...
|
|
double GetSpread()
|
|
{
|
|
//
|
|
double ask = GetAsk();
|
|
double bid = GetBid();
|
|
double result = MathAbs(ask - bid);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
double GetSpread(
|
|
string symbol // selected symbol for calculations
|
|
)
|
|
{
|
|
//
|
|
double ask = GetAsk(symbol);
|
|
double bid = GetBid(symbol);
|
|
double result = MathAbs(ask - bid);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Get Points ...
|
|
double GetPoints()
|
|
{
|
|
return _Point;
|
|
}
|
|
double GetPoints(
|
|
string symbol // selected symbol for calculations
|
|
)
|
|
{
|
|
//
|
|
double result = SymbolInfoDouble(symbol, SYMBOL_POINT);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Get Digits ...
|
|
int GetDigits()
|
|
{
|
|
return _Digits;
|
|
}
|
|
int GetDigits(
|
|
string symbol // selected symbol for calculations
|
|
)
|
|
{
|
|
//
|
|
int result = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Get Signal Entry ...
|
|
double GetEntry(
|
|
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Get entry price for Which direction trade ...
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
// Validate Arg ...
|
|
if (type == X_SIGNAL_UNKNOWN)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isLong = type == X_SIGNAL_LONG;
|
|
result = isLong ? GetAsk() : GetBid();
|
|
result = NormalizePrice(result);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
double GetEntry(
|
|
string symbol, // Specified Symbol
|
|
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Get entry price for Which direction trade ...
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
// Validate Arg ...
|
|
if (type == X_SIGNAL_UNKNOWN)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isLong = type == X_SIGNAL_LONG;
|
|
result = isLong ? GetAsk(symbol) : GetBid(symbol);
|
|
result = NormalizePrice(result, symbol);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Get Signal Exit ...
|
|
double GetExit(
|
|
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Get entry price for Which direction trade ...
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
// Validate Arg ...
|
|
if (type == X_SIGNAL_UNKNOWN)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isLong = type == X_SIGNAL_LONG;
|
|
result = isLong ? GetBid() : GetAsk();
|
|
result = NormalizePrice(result);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
double GetExit(
|
|
string symbol, // Specified Symbol
|
|
ENUM_X_SIGNAL_TYPE type = X_SIGNAL_UNKNOWN // Get entry price for Which direction trade ...
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
// Validate Arg ...
|
|
if (type == X_SIGNAL_UNKNOWN)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool isLong = type == X_SIGNAL_LONG;
|
|
result = isLong ? GetBid(symbol) : GetAsk(symbol);
|
|
result = NormalizePrice(result, symbol);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Get 1 Pip in Price Value ...
|
|
double GetPipPrice()
|
|
{
|
|
//
|
|
double result = _Point;
|
|
if (_Digits == 3 || _Digits == 5)
|
|
{
|
|
result *= 10;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
double GetPipPrice(
|
|
string symbol // selected symbol for calculations
|
|
)
|
|
{
|
|
//
|
|
double symbolPoint = GetPoints(symbol);
|
|
int symbolDigits = GetDigits(symbol);
|
|
|
|
//
|
|
double result = symbolPoint;
|
|
if (symbolDigits == 3 || symbolDigits == 5)
|
|
{
|
|
result *= 10;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Converts Pips To Price ...
|
|
double PipsToPrice(
|
|
int pips // pips amount
|
|
)
|
|
{
|
|
//
|
|
int digits = GetDigits();
|
|
double pipValue = GetPipPrice();
|
|
double result = pips * pipValue;
|
|
|
|
//
|
|
result = NormalizeDouble(result, digits);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
double PipsToPrice(
|
|
double pips // pips amount
|
|
)
|
|
{
|
|
//
|
|
int digits = GetDigits();
|
|
double pipValue = GetPipPrice();
|
|
double result = pips * pipValue;
|
|
|
|
//
|
|
result = NormalizeDouble(result, digits);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
double PipsToPrice(
|
|
string symbol, // selected symbol for calculation
|
|
int pips // pips amount
|
|
)
|
|
{
|
|
//
|
|
int digits = GetDigits(symbol);
|
|
double pipValue = GetPipPrice(symbol);
|
|
double result = pips * pipValue;
|
|
|
|
//
|
|
result = NormalizeDouble(result, digits);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
double PipsToPrice(
|
|
string symbol, // selected symbol for calculation
|
|
double pips // pips amount
|
|
)
|
|
{
|
|
//
|
|
int digits = GetDigits(symbol);
|
|
double pipValue = GetPipPrice(symbol);
|
|
double result = pips * pipValue;
|
|
|
|
//
|
|
result = NormalizeDouble(result, digits);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Converts Price to Pips ...
|
|
double PriceToPips(
|
|
double price // the price amount which required to calculate
|
|
)
|
|
{
|
|
//
|
|
int digits = GetDigits();
|
|
double pipPrice = GetPipPrice();
|
|
|
|
//
|
|
double result = price / pipPrice;
|
|
|
|
//
|
|
result = NormalizeDouble(result, digits);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
double PriceToPips(
|
|
string symbol, // Selected Symbol
|
|
double price // the price amount which required to calculate
|
|
)
|
|
{
|
|
//
|
|
int digits = GetDigits(symbol);
|
|
double pipPrice = GetPipPrice(symbol);
|
|
|
|
//
|
|
double result = price / pipPrice;
|
|
|
|
//
|
|
result = NormalizeDouble(result, digits);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Get a Candle Body ...
|
|
double GetCandleBody(
|
|
XOHCL &candle // specified candle
|
|
)
|
|
{
|
|
//
|
|
double result = MathAbs(candle.open - candle.close);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Get a Candle Range ...
|
|
double GetCandleRange(
|
|
XOHCL &candle // specified candle
|
|
)
|
|
{
|
|
//
|
|
double result = MathAbs(candle.high - candle.low);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Get a Candle Shadow ...
|
|
double GetCandleShadow(
|
|
XOHCL &candle // specified candle
|
|
)
|
|
{
|
|
//
|
|
double range = GetCandleRange(candle);
|
|
double body = GetCandleBody(candle);
|
|
|
|
//
|
|
double result = MathAbs(range - body);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Applied Price at Specific Candle ...
|
|
double GetAppliedPrice(
|
|
XOHCL &candle, // specified candle
|
|
ENUM_APPLIED_PRICE source = PRICE_CLOSE // specified Applied To
|
|
)
|
|
{
|
|
//
|
|
double result = EMPTY_VALUE;
|
|
|
|
//
|
|
switch (source)
|
|
{
|
|
//
|
|
// Open ...
|
|
case PRICE_OPEN:
|
|
result = candle.open;
|
|
break;
|
|
|
|
//
|
|
// High ...
|
|
case PRICE_HIGH:
|
|
result = candle.high;
|
|
break;
|
|
|
|
//
|
|
// Low ...
|
|
case PRICE_LOW:
|
|
result = candle.low;
|
|
break;
|
|
|
|
//
|
|
// Median ((High + Low) / 2) ...
|
|
case PRICE_MEDIAN:
|
|
result = (candle.high + candle.low) / 2;
|
|
break;
|
|
|
|
//
|
|
// Typical ((High + Low + Close)/3) ...
|
|
case PRICE_TYPICAL:
|
|
result = (candle.high + candle.low + candle.close) / 3;
|
|
break;
|
|
|
|
//
|
|
// Weighted ((High + Low + Close + Close)/4) ...
|
|
case PRICE_WEIGHTED:
|
|
result = (candle.high + candle.low + (candle.close * 2)) / 4;
|
|
break;
|
|
|
|
//
|
|
// Close ...
|
|
default:
|
|
case PRICE_CLOSE:
|
|
result = candle.close;
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
double GetAppliedPrice(
|
|
int bar_index, // specify candle index
|
|
ENUM_APPLIED_PRICE source = PRICE_CLOSE // specified Applied To
|
|
)
|
|
{
|
|
//
|
|
double result = EMPTY_VALUE;
|
|
|
|
//
|
|
XOHCL candle = GetCandle(bar_index);
|
|
result = GetAppliedPrice(candle, source);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
double GetAppliedPrice(
|
|
int bar_index, // specify candle index
|
|
ENUM_SERIESMODE mode // converts Series Mode to Applied Price ...
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
ENUM_APPLIED_PRICE mAppliedTo = To(mode);
|
|
result = GetAppliedPrice(
|
|
bar_index,
|
|
mAppliedTo);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Converts ...
|
|
ENUM_APPLIED_PRICE To(
|
|
ENUM_SERIESMODE mode // converts Series Mode to Applied Price ...
|
|
)
|
|
{
|
|
//
|
|
ENUM_APPLIED_PRICE result = PRICE_CLOSE;
|
|
|
|
//
|
|
switch (mode)
|
|
{
|
|
//
|
|
// High ...
|
|
case MODE_HIGH:
|
|
result = PRICE_HIGH;
|
|
break;
|
|
|
|
//
|
|
// Open ...
|
|
case MODE_OPEN:
|
|
result = PRICE_OPEN;
|
|
break;
|
|
|
|
//
|
|
// Low ...
|
|
case MODE_LOW:
|
|
result = PRICE_LOW;
|
|
break;
|
|
|
|
//
|
|
// Close ...
|
|
// Default ...
|
|
case MODE_CLOSE:
|
|
default:
|
|
result = PRICE_CLOSE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve a Candel Data ...
|
|
XOHCL GetCandle(int bar_index)
|
|
{
|
|
//
|
|
XOHCL result = {};
|
|
|
|
//
|
|
double open = iOpen(_Symbol, _Period, bar_index);
|
|
double high = iHigh(_Symbol, _Period, bar_index);
|
|
double close = iClose(_Symbol, _Period, bar_index);
|
|
double low = iLow(_Symbol, _Period, bar_index);
|
|
|
|
//
|
|
result.low = low;
|
|
result.open = open;
|
|
result.high = high;
|
|
result.close = close;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
XOHCL GetCandle(
|
|
ENUM_TIMEFRAMES mPeriod, // specify timeframe
|
|
int bar_index // specify candle index
|
|
)
|
|
{
|
|
//
|
|
XOHCL result = {};
|
|
|
|
//
|
|
double open = iOpen(_Symbol, mPeriod, bar_index);
|
|
double high = iHigh(_Symbol, mPeriod, bar_index);
|
|
double close = iClose(_Symbol, mPeriod, bar_index);
|
|
double low = iLow(_Symbol, mPeriod, bar_index);
|
|
|
|
//
|
|
result.low = low;
|
|
result.open = open;
|
|
result.high = high;
|
|
result.close = close;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
XOHCL GetCandle(
|
|
string symbol, // specify symbol
|
|
ENUM_TIMEFRAMES mPeriod, // specify timeframe
|
|
int bar_index // specify candle index
|
|
)
|
|
{
|
|
//
|
|
XOHCL result = {};
|
|
|
|
//
|
|
double open = iOpen(symbol, mPeriod, bar_index);
|
|
double high = iHigh(symbol, mPeriod, bar_index);
|
|
double close = iClose(symbol, mPeriod, bar_index);
|
|
double low = iLow(symbol, mPeriod, bar_index);
|
|
|
|
//
|
|
result.low = low;
|
|
result.open = open;
|
|
result.high = high;
|
|
result.close = close;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve a candle index in current timeframe inside another timeframe ...
|
|
int GetCandleBarIndex(
|
|
int bar_index, // Specify Candle index in current timeframe
|
|
ENUM_TIMEFRAMES destPeriod // Specify destination timeframe
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
datetime barTime = iTime(_Symbol, _Period, bar_index);
|
|
result = iBarShift(_Symbol, destPeriod, barTime);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve a symbol candle index in source time frame inside dest timeframe ...
|
|
int GetCandleBarIndex(
|
|
int bar_index, // Specify Candle index in current timeframe
|
|
string symbol, // Specify desired Symbol
|
|
ENUM_TIMEFRAMES sourcePeriod, // Specify bar_index timeframe
|
|
ENUM_TIMEFRAMES destPeriod // Specify destination timeframe
|
|
)
|
|
{
|
|
//
|
|
int result = -1;
|
|
|
|
//
|
|
datetime barTime = iTime(symbol, sourcePeriod, bar_index);
|
|
result = iBarShift(symbol, destPeriod, barTime);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check a Candle is Bullish or not ...
|
|
bool IsBullishCandle(
|
|
XOHCL &candle // specified candle
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = candle.open < candle.close;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
bool IsBullishCandle(
|
|
int bar_index // candle index
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XOHCL candle = GetCandle(bar_index);
|
|
|
|
//
|
|
result = IsBullishCandle(candle);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
bool IsBullishCandle(
|
|
string symbol, // specify symbol
|
|
ENUM_TIMEFRAMES mPeriod, // specify timeframe
|
|
int bar_index // candle index
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XOHCL candle = GetCandle(
|
|
symbol,
|
|
mPeriod,
|
|
bar_index);
|
|
|
|
//
|
|
result = IsBullishCandle(candle);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check a Candle is Bullish or not ...
|
|
bool IsBearishCandle(
|
|
XOHCL &candle // specified candle
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result = candle.open > candle.close;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
bool IsBearishCandle(
|
|
int bar_index // candle index
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XOHCL candle = GetCandle(bar_index);
|
|
|
|
//
|
|
result = IsBearishCandle(candle);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
bool IsBearishCandle(
|
|
string symbol, // specify symbol
|
|
ENUM_TIMEFRAMES mPeriod, // specify timeframe
|
|
int bar_index // candle index
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
XOHCL candle = GetCandle(
|
|
symbol,
|
|
mPeriod,
|
|
bar_index);
|
|
|
|
//
|
|
result = IsBearishCandle(candle);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Candle Body Bigger Than it's Shadow ...
|
|
bool HasStrongBody(XOHCL &candle)
|
|
{
|
|
//
|
|
double bodySize = MathAbs(candle.open - candle.close);
|
|
double shadowSize = MathAbs(candle.high - candle.low) - bodySize;
|
|
|
|
//
|
|
bool result = bodySize > (shadowSize * 1.5);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Determines a cnadle is Swing High
|
|
// or Swing Low order block ...
|
|
ENUM_X_SWING_TYPE GetCandleSwing(int bar_index)
|
|
{
|
|
//
|
|
ENUM_X_SWING_TYPE result = X_NO_SWING;
|
|
|
|
//
|
|
// Reading Candle Models ...
|
|
XOHCL candles[3];
|
|
candles[0] = GetCandle(bar_index + 1);
|
|
candles[1] = GetCandle(bar_index + 2);
|
|
candles[2] = GetCandle(bar_index + 3);
|
|
|
|
//
|
|
// Check Swing Start Candle has Strong Body ...
|
|
bool isStrongBodyCandle = HasStrongBody(candles[2]);
|
|
if (!isStrongBodyCandle)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Swing Low Conditions ...
|
|
bool isSwingLowOrderBlock =
|
|
candles[2].low < candles[1].low &&
|
|
candles[1].low < candles[0].low &&
|
|
candles[2].low < candles[0].low;
|
|
if (isSwingLowOrderBlock)
|
|
{
|
|
result = X_SWING_LOW;
|
|
}
|
|
|
|
//
|
|
// Check Swing High Conditions ...
|
|
bool isSwingHighOrderBlock =
|
|
candles[2].high > candles[1].high &&
|
|
candles[1].high > candles[0].high &&
|
|
candles[2].high > candles[0].high;
|
|
if (isSwingHighOrderBlock)
|
|
{
|
|
result = X_SWING_HIGH;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
ENUM_X_SWING_TYPE GetCandleSwing(
|
|
ENUM_TIMEFRAMES mPeriod, // specify timeframe
|
|
int bar_index // specify candle index
|
|
)
|
|
{
|
|
//
|
|
ENUM_X_SWING_TYPE result = X_NO_SWING;
|
|
|
|
//
|
|
// Reading Candle Models ...
|
|
XOHCL candles[3];
|
|
candles[0] = GetCandle(mPeriod, bar_index + 1);
|
|
candles[1] = GetCandle(mPeriod, bar_index + 2);
|
|
candles[2] = GetCandle(mPeriod, bar_index + 3);
|
|
|
|
//
|
|
// Check Swing Start Candle has Strong Body ...
|
|
bool isStrongBodyCandle = HasStrongBody(candles[2]);
|
|
if (!isStrongBodyCandle)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Swing Low Conditions ...
|
|
bool isSwingLowOrderBlock =
|
|
candles[2].low < candles[1].low &&
|
|
candles[1].low < candles[0].low &&
|
|
candles[2].low < candles[0].low;
|
|
if (isSwingLowOrderBlock)
|
|
{
|
|
result = X_SWING_LOW;
|
|
}
|
|
|
|
//
|
|
// Check Swing High Conditions ...
|
|
bool isSwingHighOrderBlock =
|
|
candles[2].high > candles[1].high &&
|
|
candles[1].high > candles[0].high &&
|
|
candles[2].high > candles[0].high;
|
|
if (isSwingHighOrderBlock)
|
|
{
|
|
result = X_SWING_HIGH;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
ENUM_X_SWING_TYPE GetCandleSwing(
|
|
string symbol, // specify symbol
|
|
ENUM_TIMEFRAMES mPeriod, // specify timeframe
|
|
int bar_index // specify candle index
|
|
)
|
|
{
|
|
//
|
|
ENUM_X_SWING_TYPE result = X_NO_SWING;
|
|
|
|
//
|
|
// Reading Candle Models ...
|
|
XOHCL candles[3];
|
|
candles[0] = GetCandle(symbol, mPeriod, bar_index + 1);
|
|
candles[1] = GetCandle(symbol, mPeriod, bar_index + 2);
|
|
candles[2] = GetCandle(symbol, mPeriod, bar_index + 3);
|
|
|
|
//
|
|
// Check Swing Start Candle has Strong Body ...
|
|
bool isStrongBodyCandle = HasStrongBody(candles[2]);
|
|
if (!isStrongBodyCandle)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Swing Low Conditions ...
|
|
bool isSwingLowOrderBlock =
|
|
candles[2].low < candles[1].low &&
|
|
candles[1].low < candles[0].low &&
|
|
candles[2].low < candles[0].low;
|
|
if (isSwingLowOrderBlock)
|
|
{
|
|
result = X_SWING_LOW;
|
|
}
|
|
|
|
//
|
|
// Check Swing High Conditions ...
|
|
bool isSwingHighOrderBlock =
|
|
candles[2].high > candles[1].high &&
|
|
candles[1].high > candles[0].high &&
|
|
candles[2].high > candles[0].high;
|
|
if (isSwingHighOrderBlock)
|
|
{
|
|
result = X_SWING_HIGH;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Market Highest High ...
|
|
double GetHighestHigh(
|
|
int mLength, // Which market Length use
|
|
int bar_index // bar index
|
|
)
|
|
{
|
|
//
|
|
double result = -1;
|
|
|
|
//
|
|
int rIdx = iHighest(
|
|
_Symbol,
|
|
_Period,
|
|
MODE_HIGH,
|
|
mLength,
|
|
bar_index);
|
|
|
|
//
|
|
result = iHigh(
|
|
_Symbol,
|
|
_Period,
|
|
rIdx);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
double GetHighestHigh(
|
|
int mLength, // Which market Length use
|
|
int bar_index, // bar index
|
|
ENUM_SERIESMODE mode // Calculation mode
|
|
)
|
|
{
|
|
//
|
|
double result = -1;
|
|
|
|
//
|
|
int rIdx = iHighest(
|
|
_Symbol,
|
|
_Period,
|
|
mode,
|
|
mLength,
|
|
bar_index);
|
|
|
|
//
|
|
result = iHigh(
|
|
_Symbol,
|
|
_Period,
|
|
rIdx);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
double GetHighestHigh(
|
|
string symbol, // Specified Symbol
|
|
ENUM_TIMEFRAMES mPeriod, // Specified Period
|
|
int mLength, // Which market Length use
|
|
int bar_index // bar index
|
|
)
|
|
{
|
|
//
|
|
double result = -1;
|
|
|
|
//
|
|
int rIdx = iHighest(
|
|
symbol,
|
|
mPeriod,
|
|
MODE_HIGH,
|
|
mLength,
|
|
bar_index);
|
|
|
|
//
|
|
result = iHigh(
|
|
symbol,
|
|
mPeriod,
|
|
rIdx);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
double GetHighestHigh(
|
|
string symbol, // Specified Symbol
|
|
ENUM_TIMEFRAMES mPeriod, // Specified Period
|
|
ENUM_SERIESMODE mode, // Calculation mode
|
|
int mLength, // Which market Length use
|
|
int bar_index // bar index
|
|
)
|
|
{
|
|
//
|
|
double result = -1;
|
|
|
|
//
|
|
int rIdx = iHighest(
|
|
symbol,
|
|
mPeriod,
|
|
mode,
|
|
mLength,
|
|
bar_index);
|
|
|
|
//
|
|
result = iHigh(
|
|
symbol,
|
|
mPeriod,
|
|
rIdx);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Market Lowest Low ...
|
|
double GetLowestLow(
|
|
int mLength, // Which market Length use
|
|
int bar_index // bar index
|
|
)
|
|
{
|
|
//
|
|
double result = -1;
|
|
|
|
//
|
|
int rIdx = iLowest(
|
|
_Symbol,
|
|
_Period,
|
|
MODE_LOW,
|
|
mLength,
|
|
bar_index);
|
|
|
|
//
|
|
result = iLow(
|
|
_Symbol,
|
|
_Period,
|
|
rIdx);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
double GetLowestLow(
|
|
int mLength, // Which market Length use
|
|
int bar_index, // bar index
|
|
ENUM_SERIESMODE mode // Calculation mode
|
|
)
|
|
{
|
|
//
|
|
double result = -1;
|
|
|
|
//
|
|
int rIdx = iLowest(
|
|
_Symbol,
|
|
_Period,
|
|
mode,
|
|
mLength,
|
|
bar_index);
|
|
|
|
//
|
|
result = iLow(
|
|
_Symbol,
|
|
_Period,
|
|
rIdx);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
double GetLowestLow(
|
|
string symbol, // Specified Symbol
|
|
ENUM_TIMEFRAMES mPeriod, // Specified Period
|
|
int mLength, // Which market Length use
|
|
int bar_index // bar index
|
|
)
|
|
{
|
|
//
|
|
double result = -1;
|
|
|
|
//
|
|
int rIdx = iLowest(
|
|
symbol,
|
|
mPeriod,
|
|
MODE_LOW,
|
|
mLength,
|
|
bar_index);
|
|
|
|
//
|
|
result = iLow(
|
|
symbol,
|
|
mPeriod,
|
|
rIdx);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
double GetLowestLow(
|
|
string symbol, // Specified Symbol
|
|
ENUM_TIMEFRAMES mPeriod, // Specified Period
|
|
ENUM_SERIESMODE mode, // Calculation mode
|
|
int mLength, // Which market Length use
|
|
int bar_index // bar index
|
|
)
|
|
{
|
|
//
|
|
double result = -1;
|
|
|
|
//
|
|
int rIdx = iLowest(
|
|
symbol,
|
|
mPeriod,
|
|
mode,
|
|
mLength,
|
|
bar_index);
|
|
|
|
//
|
|
result = iLow(
|
|
symbol,
|
|
mPeriod,
|
|
rIdx);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate Fib Level ...
|
|
double GetFibonacciLevel(
|
|
double upPrice,
|
|
double downPrice,
|
|
double level,
|
|
int direction)
|
|
{
|
|
//
|
|
double ling = upPrice - downPrice;
|
|
double pLevel = (ling / 100) * (level * 100);
|
|
|
|
//
|
|
double result = direction > 0 ? upPrice - pLevel : downPrice + pLevel;
|
|
result = NormalizeDouble(result, _Digits);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check first Cross Over second at bar_index ...
|
|
bool IsCrossOver(
|
|
const double &first[], // the buffer which check crossing over second buffer
|
|
const double &second[], // first buffer checks based on this buffer
|
|
const int bar_index // check crosses in specific index
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
ArraySetAsSeries(first, true);
|
|
ArraySetAsSeries(second, true);
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (ArraySize(first) < bar_index + 1 || ArraySize(second) < bar_index + 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = first[bar_index] > second[bar_index] &&
|
|
!(first[bar_index + 1] > second[bar_index + 1]);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check first is Over second at bar_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 bar_index // check crosses in specific index
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
ArraySetAsSeries(first, true);
|
|
ArraySetAsSeries(second, true);
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (ArraySize(first) < bar_index + 1 || ArraySize(second) < bar_index + 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = first[bar_index] > second[bar_index] &&
|
|
first[bar_index + 1] > second[bar_index + 1];
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check first Cross Under second at bar_index ...
|
|
bool IsCrossUnder(
|
|
const double &first[], // the buffer which check crossing under second buffer
|
|
const double &second[], // first buffer checks based on this buffer
|
|
const int bar_index // check crosses in specific index
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
ArraySetAsSeries(first, true);
|
|
ArraySetAsSeries(second, true);
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (ArraySize(first) < bar_index + 1 || ArraySize(second) < bar_index + 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = first[bar_index] < second[bar_index] &&
|
|
!(first[bar_index + 1] < second[bar_index + 1]);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check first is Under second at bar_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 bar_index // check crosses in specific index
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
ArraySetAsSeries(first, true);
|
|
ArraySetAsSeries(second, true);
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (ArraySize(first) < bar_index + 1 || ArraySize(second) < bar_index + 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = first[bar_index] < second[bar_index] &&
|
|
first[bar_index + 1] < second[bar_index + 1];
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Calculate Slope of Specified Buffer at Specified Index ...
|
|
double GetSlope(
|
|
int from, // In Past Index ...
|
|
int to, // In Past Index ...
|
|
double &buffer[])
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
double toValue = buffer[to];
|
|
double fromValue = buffer[from];
|
|
double deltaValue = toValue - fromValue;
|
|
double deltaTime = from - to;
|
|
|
|
//
|
|
result = deltaValue / deltaTime;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check if a Value Increasing in Loopback ...
|
|
bool IsIncreasing(
|
|
int from, // Last Time Index
|
|
int to, // Fisr Tima Index
|
|
double &buffer[] // the Buffer which required to search
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// 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(
|
|
from,
|
|
i,
|
|
buffer);
|
|
|
|
//
|
|
// Check Result ...
|
|
result = result && isPassed && isIIncreasing;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check if a Value Decreasing in Loopback ...
|
|
bool IsDecreasing(
|
|
int from, // Last Time Index
|
|
int to, // Fisr Tima Index
|
|
double &buffer[] // the Buffer which required to search
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// 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(
|
|
from,
|
|
i,
|
|
buffer);
|
|
|
|
//
|
|
// Check Result ...
|
|
result = result && isPassed && isIDecreasing;
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Get Max Value of Specific Loopback of a Buffer ...
|
|
double GetMaxValue(
|
|
int mLoopback, // loopback length
|
|
double &buffer[] // the Buffer which required to search
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (
|
|
mLoopback < 2 ||
|
|
ArraySize(buffer) < mLoopback)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop Through LoopBack ...
|
|
for (int i = 0; i < mLoopback; i++)
|
|
{
|
|
//
|
|
double iValue = buffer[i];
|
|
|
|
//
|
|
result =
|
|
//
|
|
result == 0 || result < iValue
|
|
//
|
|
? iValue
|
|
//
|
|
: result
|
|
//
|
|
;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Get Min Value of Specific Loopback of a Buffer ...
|
|
double GetMinValue(
|
|
int mLoopback, // loopback length
|
|
double &buffer[] // the Buffer which required to search
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (
|
|
mLoopback < 2 ||
|
|
ArraySize(buffer) < mLoopback)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop Through LoopBack ...
|
|
for (int i = 0; i < mLoopback; i++)
|
|
{
|
|
//
|
|
double iValue = buffer[i];
|
|
|
|
//
|
|
result =
|
|
//
|
|
result == 0 || result > iValue
|
|
//
|
|
? iValue
|
|
//
|
|
: result
|
|
//
|
|
;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool IsInPeak(
|
|
int mLoopback, // loopback length
|
|
double &buffer[] // the Buffer which required to search
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (
|
|
mLoopback < 2 ||
|
|
ArraySize(buffer) < mLoopback + 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int q1Length = mLoopback / 4;
|
|
int halfLength = mLoopback / 2;
|
|
int q2Length = halfLength + q1Length;
|
|
|
|
//
|
|
double firstValue = buffer[1];
|
|
double q1Value = buffer[q1Length];
|
|
double q2Value = buffer[q2Length];
|
|
double halfValue = buffer[halfLength];
|
|
double lastValue = buffer[ArraySize(buffer) - 1];
|
|
|
|
//
|
|
// Peak ...
|
|
result =
|
|
//
|
|
firstValue > lastValue
|
|
//
|
|
&&
|
|
//
|
|
(
|
|
firstValue > q1Value &&
|
|
firstValue > halfValue)
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
bool IsInVale(
|
|
int mLoopback, // loopback length
|
|
double &buffer[] // the Buffer which required to search
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (
|
|
mLoopback < 2 ||
|
|
ArraySize(buffer) < mLoopback + 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int q1Length = mLoopback / 4;
|
|
int halfLength = mLoopback / 2;
|
|
int q2Length = halfLength + q1Length;
|
|
|
|
//
|
|
double firstValue = buffer[1];
|
|
double q1Value = buffer[q1Length];
|
|
double q2Value = buffer[q2Length];
|
|
double halfValue = buffer[halfLength];
|
|
double lastValue = buffer[ArraySize(buffer) - 1];
|
|
|
|
//
|
|
// Peak ...
|
|
result =
|
|
//
|
|
firstValue < lastValue
|
|
//
|
|
&&
|
|
//
|
|
(
|
|
firstValue < q1Value &&
|
|
firstValue < halfValue)
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Sharp Happens or not ...
|
|
bool IsSharpChanged(
|
|
double fromValue, // Past Value
|
|
double toValue, // Present Value
|
|
double maxValue, // Max in Range Value
|
|
double minValue // Min in Range Value
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// This Used In Increased or Decreased Sharp Detection ...
|
|
bool isIncreased = toValue > fromValue;
|
|
|
|
//
|
|
double toFromDelta = MathAbs(toValue - fromValue);
|
|
double minMaxDelta = maxValue - minValue;
|
|
|
|
//
|
|
result = toFromDelta >= (minMaxDelta / 3);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
bool IsSharpChanged(
|
|
int from, // Past Index in Series
|
|
int to, // Present Index in Series
|
|
double &buffer[] // the Buffer which required to search
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (
|
|
from <= to ||
|
|
ArraySize(buffer) < from + 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop through Items ...
|
|
double toValue = buffer[to];
|
|
double fromValue = buffer[from];
|
|
|
|
//
|
|
// This Used In Increased or Decreased Sharp Detection ...
|
|
bool isIncreased = toValue > fromValue;
|
|
|
|
//
|
|
double minValue = GetMinValue(
|
|
ArraySize(buffer) - 1,
|
|
buffer);
|
|
double maxValue = GetMaxValue(
|
|
ArraySize(buffer) - 1,
|
|
buffer);
|
|
double minMaxDelta = maxValue - minValue;
|
|
|
|
//
|
|
// Sharp Detection ...
|
|
result = IsSharpChanged(
|
|
fromValue,
|
|
toValue,
|
|
maxValue,
|
|
minValue);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
bool IsSharpChanged(
|
|
int from, // Past Bar Index
|
|
int to, // Present Bar Index
|
|
ENUM_APPLIED_PRICE appliedPrice // Which Price Choose in From or To
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
double toValue = GetAppliedPrice(
|
|
to,
|
|
appliedPrice);
|
|
double fromValue = GetAppliedPrice(
|
|
from,
|
|
appliedPrice);
|
|
|
|
//
|
|
int hIdx = iHighest(
|
|
_Symbol,
|
|
_Period,
|
|
MODE_HIGH,
|
|
from,
|
|
to);
|
|
double maxValue = iHigh(
|
|
_Symbol,
|
|
_Period,
|
|
hIdx);
|
|
|
|
//
|
|
int lIdx = iLowest(
|
|
_Symbol,
|
|
_Period,
|
|
MODE_LOW,
|
|
from,
|
|
to);
|
|
double minValue = iLow(
|
|
_Symbol,
|
|
_Period,
|
|
lIdx);
|
|
|
|
//
|
|
result = IsSharpChanged(
|
|
fromValue,
|
|
toValue,
|
|
maxValue,
|
|
minValue);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check InCreased Sharp Happens or not ...
|
|
bool IsSharpIncreasedChanged(
|
|
double fromValue, // Past Value
|
|
double toValue, // Present Value
|
|
double maxValue, // Max in Range Value
|
|
double minValue // Min in Range Value
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// This Used In Increased or Decreased Sharp Detection ...
|
|
bool isIncreased = toValue > fromValue;
|
|
|
|
//
|
|
double toFromDelta = MathAbs(toValue - fromValue);
|
|
double minMaxDelta = maxValue - minValue;
|
|
|
|
//
|
|
result =
|
|
isIncreased &&
|
|
toFromDelta >= (minMaxDelta / 3);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
bool IsSharpIncreasedChanged(
|
|
int from, // Past Index in Series
|
|
int to, // Present Index in Series
|
|
double &buffer[] // the Buffer which required to search
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (
|
|
from <= to ||
|
|
ArraySize(buffer) < from + 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop through Items ...
|
|
double toValue = buffer[to];
|
|
double fromValue = buffer[from];
|
|
|
|
//
|
|
double minValue = GetMinValue(
|
|
ArraySize(buffer) - 1,
|
|
buffer);
|
|
double maxValue = GetMaxValue(
|
|
ArraySize(buffer) - 1,
|
|
buffer);
|
|
double minMaxDelta = maxValue - minValue;
|
|
|
|
//
|
|
// Sharp Detection ...
|
|
result = IsSharpIncreasedChanged(
|
|
fromValue,
|
|
toValue,
|
|
maxValue,
|
|
minValue);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
bool IsSharpIncreasedChanged(
|
|
int from, // Past Bar Index
|
|
int to, // Present Bar Index
|
|
ENUM_APPLIED_PRICE appliedPrice // Which Price Choose in From or To
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
double toValue = GetAppliedPrice(
|
|
to,
|
|
appliedPrice);
|
|
double fromValue = GetAppliedPrice(
|
|
from,
|
|
appliedPrice);
|
|
|
|
//
|
|
int hIdx = iHighest(
|
|
_Symbol,
|
|
_Period,
|
|
MODE_HIGH,
|
|
from,
|
|
to);
|
|
double maxValue = iHigh(
|
|
_Symbol,
|
|
_Period,
|
|
hIdx);
|
|
|
|
//
|
|
int lIdx = iLowest(
|
|
_Symbol,
|
|
_Period,
|
|
MODE_LOW,
|
|
from,
|
|
to);
|
|
double minValue = iLow(
|
|
_Symbol,
|
|
_Period,
|
|
lIdx);
|
|
|
|
//
|
|
result = IsSharpIncreasedChanged(
|
|
fromValue,
|
|
toValue,
|
|
maxValue,
|
|
minValue);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Decreased Sharp Happens or not ...
|
|
bool IsSharpDecreasedChanged(
|
|
double fromValue, // Past Value
|
|
double toValue, // Present Value
|
|
double maxValue, // Max in Range Value
|
|
double minValue // Min in Range Value
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// This Used In Increased or Decreased Sharp Detection ...
|
|
bool isIncreased = toValue > fromValue;
|
|
|
|
//
|
|
double toFromDelta = MathAbs(toValue - fromValue);
|
|
double minMaxDelta = maxValue - minValue;
|
|
|
|
//
|
|
result =
|
|
!isIncreased &&
|
|
toFromDelta >= (minMaxDelta / 3);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
bool IsSharpDecreasedChanged(
|
|
int from, // Past Index in Series
|
|
int to, // Present Index in Series
|
|
double &buffer[] // the Buffer which required to search
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Args ...
|
|
if (
|
|
from <= to ||
|
|
ArraySize(buffer) < from + 1)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Loop through Items ...
|
|
double toValue = buffer[to];
|
|
double fromValue = buffer[from];
|
|
|
|
//
|
|
double minValue = GetMinValue(
|
|
ArraySize(buffer) - 1,
|
|
buffer);
|
|
double maxValue = GetMaxValue(
|
|
ArraySize(buffer) - 1,
|
|
buffer);
|
|
double minMaxDelta = maxValue - minValue;
|
|
|
|
//
|
|
// Sharp Detection ...
|
|
result = IsSharpDecreasedChanged(
|
|
fromValue,
|
|
toValue,
|
|
maxValue,
|
|
minValue);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
bool IsSharpDecreasedChanged(
|
|
int from, // Past Bar Index
|
|
int to, // Present Bar Index
|
|
ENUM_APPLIED_PRICE appliedPrice // Which Price Choose in From or To
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
double toValue = GetAppliedPrice(
|
|
to,
|
|
appliedPrice);
|
|
double fromValue = GetAppliedPrice(
|
|
from,
|
|
appliedPrice);
|
|
|
|
//
|
|
int hIdx = iHighest(
|
|
_Symbol,
|
|
_Period,
|
|
MODE_HIGH,
|
|
from,
|
|
to);
|
|
double maxValue = iHigh(
|
|
_Symbol,
|
|
_Period,
|
|
hIdx);
|
|
|
|
//
|
|
int lIdx = iLowest(
|
|
_Symbol,
|
|
_Period,
|
|
MODE_LOW,
|
|
from,
|
|
to);
|
|
double minValue = iLow(
|
|
_Symbol,
|
|
_Period,
|
|
lIdx);
|
|
|
|
//
|
|
result = IsSharpDecreasedChanged(
|
|
fromValue,
|
|
toValue,
|
|
maxValue,
|
|
minValue);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Validate Struct ...
|
|
bool IsValid(XSignal &model, ulong magicNumber)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Validate Signal Type ...
|
|
result = model.type != X_SIGNAL_UNKNOWN;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Symbol ...
|
|
result = StringLen(model.symbol) == 0 ? true : model.symbol == _Symbol;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check magic number ...
|
|
result = model.magicNumber <= 0 ? true : model.magicNumber == magicNumber;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Entry ...
|
|
result = model.entry > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check SL ...
|
|
result = model.sl == 0 ? true : model.type == X_SIGNAL_LONG ? model.sl < model.entry
|
|
: model.sl > model.entry;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check TP ...
|
|
result = model.tp == 0 ? true : model.type == X_SIGNAL_LONG ? model.tp > model.entry
|
|
: model.tp < model.entry;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Volume ...
|
|
result = model.volume > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Time ...
|
|
result = model.time > 0;
|
|
if (!result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void CleanBuffer(int &buffer[])
|
|
{
|
|
//
|
|
ArrayFree(buffer);
|
|
ArrayResize(buffer, 0);
|
|
}
|
|
void CleanBuffer(ulong &buffer[])
|
|
{
|
|
//
|
|
ArrayFree(buffer);
|
|
ArrayResize(buffer, 0);
|
|
}
|
|
void CleanBuffer(double &buffer[])
|
|
{
|
|
//
|
|
ArrayFree(buffer);
|
|
ArrayResize(buffer, 0);
|
|
}
|
|
void CleanBuffer(XSignal &buffer[])
|
|
{
|
|
//
|
|
ArrayFree(buffer);
|
|
ArrayResize(buffer, 0);
|
|
}
|
|
void CleanBuffer(XDeal &buffer[])
|
|
{
|
|
//
|
|
ArrayFree(buffer);
|
|
ArrayResize(buffer, 0);
|
|
}
|
|
void CleanBuffer(XOrder &buffer[])
|
|
{
|
|
//
|
|
ArrayFree(buffer);
|
|
ArrayResize(buffer, 0);
|
|
}
|
|
|
|
//
|
|
bool GetLastItem(
|
|
double &item, // Holds Result
|
|
double &buffer[] // Specified Buffer
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int bufferSize = ArraySize(buffer);
|
|
if (bufferSize <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
item = buffer[bufferSize - 1];
|
|
|
|
//
|
|
result = true;
|
|
return result;
|
|
}
|
|
bool GetLastItem(
|
|
datetime &item, // Holds Result
|
|
datetime &buffer[] // Specified Buffer
|
|
)
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
int bufferSize = ArraySize(buffer);
|
|
if (bufferSize <= 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
item = buffer[bufferSize - 1];
|
|
|
|
//
|
|
result = true;
|
|
return result;
|
|
}
|
|
|
|
//
|
|
void Add(
|
|
int item, // item want to add
|
|
int &buffer[] // Destination buffer
|
|
)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
buffer,
|
|
ArraySize(buffer) + 1);
|
|
|
|
//
|
|
buffer[ArraySize(buffer) - 1] = item;
|
|
}
|
|
void Add(
|
|
ulong item, // item want to add
|
|
ulong &buffer[] // Destination buffer
|
|
)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
buffer,
|
|
ArraySize(buffer) + 1);
|
|
|
|
//
|
|
buffer[ArraySize(buffer) - 1] = item;
|
|
}
|
|
void Add(
|
|
string item, // item want to add
|
|
string &buffer[] // Destination buffer
|
|
)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
buffer,
|
|
ArraySize(buffer) + 1);
|
|
|
|
//
|
|
buffer[ArraySize(buffer) - 1] = item;
|
|
}
|
|
void Add(
|
|
double item, // item want to add
|
|
double &buffer[] // Destination buffer
|
|
)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
buffer,
|
|
ArraySize(buffer) + 1);
|
|
|
|
//
|
|
buffer[ArraySize(buffer) - 1] = item;
|
|
}
|
|
void Add(
|
|
XOHCL &item, // item want to add
|
|
XOHCL &buffer[] // Destination buffer
|
|
)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
buffer,
|
|
ArraySize(buffer) + 1);
|
|
|
|
//
|
|
buffer[ArraySize(buffer) - 1] = item;
|
|
}
|
|
void Add(
|
|
datetime &item, // item want to add
|
|
datetime &buffer[] // Destination buffer
|
|
)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
buffer,
|
|
ArraySize(buffer) + 1);
|
|
|
|
//
|
|
buffer[ArraySize(buffer) - 1] = item;
|
|
}
|
|
void Add(
|
|
XSignal &item, // item want to add
|
|
XSignal &buffer[] // Destination buffer
|
|
)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
buffer,
|
|
ArraySize(buffer) + 1);
|
|
|
|
//
|
|
buffer[ArraySize(buffer) - 1] = item;
|
|
}
|
|
void Add(
|
|
XDeal &item, // item want to add
|
|
XDeal &buffer[] // Destination buffer
|
|
)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
buffer,
|
|
ArraySize(buffer) + 1);
|
|
|
|
//
|
|
buffer[ArraySize(buffer) - 1] = item;
|
|
}
|
|
void Add(
|
|
XOrder &item, // item want to add
|
|
XOrder &buffer[] // Destination buffer
|
|
)
|
|
{
|
|
//
|
|
ArrayResize(
|
|
buffer,
|
|
ArraySize(buffer) + 1);
|
|
|
|
//
|
|
buffer[ArraySize(buffer) - 1] = item;
|
|
}
|
|
|
|
//
|
|
// Converts a Buffer to String Representation ...
|
|
string ToString(
|
|
const int &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;
|
|
}
|
|
string ToString(
|
|
const double &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;
|
|
}
|
|
string ToString(
|
|
const string &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;
|
|
}
|
|
string ToString(
|
|
const datetime &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;
|
|
}
|
|
|
|
//
|
|
// Check a Signal is Long or not ...
|
|
bool IsLong(ENUM_X_SIGNAL_TYPE type)
|
|
{
|
|
return type == X_SIGNAL_LONG;
|
|
}
|
|
bool IsLong(XSignal &signal)
|
|
{
|
|
//
|
|
bool result = IsLong(signal.type);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check a Signal is Short or not ...
|
|
bool IsShort(ENUM_X_SIGNAL_TYPE type)
|
|
{
|
|
return type == X_SIGNAL_SHORT;
|
|
}
|
|
bool IsShort(XSignal &signal)
|
|
{
|
|
//
|
|
bool result = IsShort(signal.type);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve a Signal Type String Value ...
|
|
string GetSignalType(ENUM_X_SIGNAL_TYPE type)
|
|
{
|
|
//
|
|
string result = "";
|
|
|
|
//
|
|
if (type == X_SIGNAL_UNKNOWN)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
result = type == X_SIGNAL_LONG ? "Long" : "Short";
|
|
|
|
//
|
|
return result;
|
|
}
|
|
string GetSignalType(XSignal &signal)
|
|
{
|
|
//
|
|
string result = "";
|
|
|
|
//
|
|
result = GetSignalType(signal.type);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
ENUM_X_SIGNAL_TYPE GetSignalType(string typeStr)
|
|
{
|
|
//
|
|
ENUM_X_SIGNAL_TYPE result = X_SIGNAL_UNKNOWN;
|
|
|
|
//
|
|
if (typeStr == GetSignalType(X_SIGNAL_LONG))
|
|
{
|
|
result = X_SIGNAL_LONG;
|
|
}
|
|
else if (typeStr == GetSignalType(X_SIGNAL_SHORT))
|
|
{
|
|
result = X_SIGNAL_SHORT;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Signal Execution String ...
|
|
string GetSignalExecutionError(int error)
|
|
{
|
|
//
|
|
string result = "";
|
|
|
|
//
|
|
switch (error)
|
|
{
|
|
//
|
|
case X_TRADER_INVALID_SIGNAL_ERROR:
|
|
result = "Invalid Signal ...";
|
|
break;
|
|
|
|
//
|
|
case X_TRADER_NOT_ENOUGH_EQUITY_ERROR:
|
|
result = "Not Enough Equity for Trade ...";
|
|
break;
|
|
|
|
//
|
|
case X_TRADER_NOT_ENOUGH_BALANCE_ERROR:
|
|
result = "Not Enough Balance for Trade ...";
|
|
break;
|
|
|
|
//
|
|
case X_TRADER_NOT_ENOUGH_MARIGIN_ERROR:
|
|
result = "Not Enough Marigin For Trade ...";
|
|
break;
|
|
|
|
//
|
|
case X_TRADER_MAX_TRADES_REACHED_ERROR:
|
|
result = "Max Allowed Trade Reached ...";
|
|
break;
|
|
|
|
//
|
|
case X_TRADER_UNKNOWN_ERROR:
|
|
default:
|
|
result = "Unknown Issue ...";
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
// Normalize a give Volume ...
|
|
double NormalizeVolume(
|
|
double volume, // desired volume to normalize
|
|
string symbol = NULL, // Specified Symbol for Normalization
|
|
int mLength = 2 // Length of Digits
|
|
)
|
|
{
|
|
//
|
|
double result = volume;
|
|
|
|
//
|
|
// Normalize Symbol ...
|
|
if (StringLen(symbol) == 0)
|
|
{
|
|
symbol = _Symbol;
|
|
}
|
|
|
|
//
|
|
// Normalize Digits ...
|
|
int digits = GetDigits(symbol);
|
|
mLength =
|
|
mLength == 0 || mLength > digits
|
|
? digits
|
|
: MathMin(mLength, digits);
|
|
|
|
//
|
|
// Normalize Volume ...
|
|
result = NormalizeDouble(result, mLength);
|
|
|
|
//
|
|
double maxAvailableVolume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
|
|
double minAvailableVolume = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
|
|
|
|
//
|
|
// Validate Result ...
|
|
if (result > maxAvailableVolume)
|
|
{
|
|
result = maxAvailableVolume;
|
|
}
|
|
else if (result < minAvailableVolume)
|
|
{
|
|
result = minAvailableVolume;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Normallize Price ...
|
|
double NormalizePrice(
|
|
double price, // desired Price for normalization
|
|
string symbol = NULL // Specified Symbol for Normalization
|
|
)
|
|
{
|
|
//
|
|
double result = 0;
|
|
|
|
//
|
|
// Mormalize Symbol ...
|
|
if (StringLen(symbol) == 0)
|
|
{
|
|
symbol = _Symbol;
|
|
}
|
|
|
|
//
|
|
int digits = GetDigits(symbol);
|
|
result = NormalizeDouble(price, digits);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Error Descriptions Functions ...
|
|
//
|
|
|
|
//
|
|
// Retrieve Specified Error Code Description ...
|
|
string GetErrorDescription(int err_code)
|
|
{
|
|
//
|
|
string result = "";
|
|
|
|
//
|
|
switch (err_code)
|
|
{
|
|
//
|
|
//--- Constant Description
|
|
|
|
//
|
|
case ERR_SUCCESS:
|
|
result = "The operation completed successfully";
|
|
break;
|
|
|
|
//
|
|
case ERR_INTERNAL_ERROR:
|
|
result = "Unexpected internal error";
|
|
break;
|
|
|
|
//
|
|
case ERR_WRONG_INTERNAL_PARAMETER:
|
|
result = "Wrong parameter in the inner call of the client terminal function";
|
|
break;
|
|
|
|
//
|
|
case ERR_INVALID_PARAMETER:
|
|
result = "Wrong parameter when calling the system function";
|
|
break;
|
|
|
|
//
|
|
case ERR_NOT_ENOUGH_MEMORY:
|
|
result = "Not enough memory to perform the system function";
|
|
break;
|
|
|
|
//
|
|
case ERR_STRUCT_WITHOBJECTS_ORCLASS:
|
|
result = "The structure contains objects of strings and/or dynamic arrays and/or structure of such objects and/or classes";
|
|
break;
|
|
|
|
//
|
|
case ERR_INVALID_ARRAY:
|
|
result = "Array of a wrong type, wrong size, or a damaged object of a dynamic array";
|
|
break;
|
|
|
|
//
|
|
case ERR_ARRAY_RESIZE_ERROR:
|
|
result = "Not enough memory for the relocation of an array, or an attempt to change the size of a static array";
|
|
break;
|
|
|
|
//
|
|
case ERR_STRING_RESIZE_ERROR:
|
|
result = "Not enough memory for the relocation of string";
|
|
break;
|
|
|
|
//
|
|
case ERR_NOTINITIALIZED_STRING:
|
|
result = "Not initialized string";
|
|
break;
|
|
|
|
//
|
|
case ERR_INVALID_DATETIME:
|
|
result = "Invalid date and/or time";
|
|
break;
|
|
|
|
//
|
|
case ERR_ARRAY_BAD_SIZE:
|
|
result = "Requested array size exceeds 2 GB";
|
|
break;
|
|
|
|
//
|
|
case ERR_INVALID_POINTER:
|
|
result = "Wrong pointer";
|
|
break;
|
|
|
|
//
|
|
case ERR_INVALID_POINTER_TYPE:
|
|
result = "Wrong type of pointer";
|
|
break;
|
|
|
|
//
|
|
case ERR_FUNCTION_NOT_ALLOWED:
|
|
result = "System function is not allowed to call";
|
|
break;
|
|
|
|
//
|
|
//--- Charts
|
|
|
|
//
|
|
case ERR_CHART_WRONG_ID:
|
|
result = "Wrong chart ID";
|
|
break;
|
|
|
|
//
|
|
case ERR_CHART_NO_REPLY:
|
|
result = "Chart does not respond";
|
|
break;
|
|
|
|
//
|
|
case ERR_CHART_NOT_FOUND:
|
|
result = "Chart not found";
|
|
break;
|
|
|
|
//
|
|
case ERR_CHART_NO_EXPERT:
|
|
result = "No Expert Advisor in the chart that could handle the event";
|
|
break;
|
|
|
|
//
|
|
case ERR_CHART_CANNOT_OPEN:
|
|
result = "Chart opening error";
|
|
break;
|
|
|
|
//
|
|
case ERR_CHART_CANNOT_CHANGE:
|
|
result = "Failed to change chart symbol and period";
|
|
break;
|
|
|
|
//
|
|
case ERR_CHART_CANNOT_CREATE_TIMER:
|
|
result = "Failed to create timer";
|
|
break;
|
|
|
|
//
|
|
case ERR_CHART_WRONG_PROPERTY:
|
|
result = "Wrong chart property ID";
|
|
break;
|
|
|
|
//
|
|
case ERR_CHART_SCREENSHOT_FAILED:
|
|
result = "Error creating screenshots";
|
|
break;
|
|
|
|
//
|
|
case ERR_CHART_NAVIGATE_FAILED:
|
|
result = "Error navigating through chart";
|
|
break;
|
|
|
|
//
|
|
case ERR_CHART_TEMPLATE_FAILED:
|
|
result = "Error applying template";
|
|
break;
|
|
|
|
//
|
|
case ERR_CHART_WINDOW_NOT_FOUND:
|
|
result = "Subwindow containing the indicator was not found";
|
|
break;
|
|
|
|
//
|
|
case ERR_CHART_INDICATOR_CANNOT_ADD:
|
|
result = "Error adding an indicator to chart";
|
|
break;
|
|
|
|
//
|
|
case ERR_CHART_INDICATOR_CANNOT_DEL:
|
|
result = "Error deleting an indicator from the chart";
|
|
break;
|
|
|
|
//
|
|
case ERR_CHART_INDICATOR_NOT_FOUND:
|
|
result = "Indicator not found on the specified chart";
|
|
break;
|
|
|
|
//
|
|
//--- Graphical Objects
|
|
case ERR_OBJECT_ERROR:
|
|
result = "Error working with a graphical object";
|
|
break;
|
|
|
|
//
|
|
case ERR_OBJECT_NOT_FOUND:
|
|
result = "Graphical object was not found";
|
|
break;
|
|
|
|
//
|
|
case ERR_OBJECT_WRONG_PROPERTY:
|
|
result = "Wrong ID of a graphical object property";
|
|
break;
|
|
|
|
//
|
|
case ERR_OBJECT_GETDATE_FAILED:
|
|
result = "Unable to get date corresponding to the value";
|
|
break;
|
|
|
|
//
|
|
case ERR_OBJECT_GETVALUE_FAILED:
|
|
result = "Unable to get value corresponding to the date";
|
|
break;
|
|
|
|
//
|
|
//--- MarketInfo
|
|
|
|
//
|
|
case ERR_MARKET_UNKNOWN_SYMBOL:
|
|
result = "Unknown symbol";
|
|
break;
|
|
|
|
//
|
|
case ERR_MARKET_NOT_SELECTED:
|
|
result = "Symbol is not selected in MarketWatch";
|
|
break;
|
|
|
|
//
|
|
case ERR_MARKET_WRONG_PROPERTY:
|
|
result = "Wrong identifier of a symbol property";
|
|
break;
|
|
|
|
//
|
|
case ERR_MARKET_LASTTIME_UNKNOWN:
|
|
result = "Time of the last tick is not known (no ticks)";
|
|
break;
|
|
|
|
//
|
|
case ERR_MARKET_SELECT_ERROR:
|
|
result = "Error adding or deleting a symbol in MarketWatch";
|
|
break;
|
|
|
|
//
|
|
//--- History Access
|
|
|
|
//
|
|
case ERR_HISTORY_NOT_FOUND:
|
|
result = "Requested history not found";
|
|
break;
|
|
|
|
//
|
|
case ERR_HISTORY_WRONG_PROPERTY:
|
|
result = "Wrong ID of the history property";
|
|
break;
|
|
|
|
//
|
|
//--- Global_Variables
|
|
|
|
//
|
|
case ERR_GLOBALVARIABLE_NOT_FOUND:
|
|
result = "Global variable of the client terminal is not found";
|
|
break;
|
|
|
|
//
|
|
case ERR_GLOBALVARIABLE_EXISTS:
|
|
result = "Global variable of the client terminal with the same name already exists";
|
|
break;
|
|
|
|
//
|
|
case ERR_MAIL_SEND_FAILED:
|
|
result = "Email sending failed";
|
|
break;
|
|
|
|
//
|
|
case ERR_PLAY_SOUND_FAILED:
|
|
result = "Sound playing failed";
|
|
break;
|
|
|
|
//
|
|
case ERR_MQL5_WRONG_PROPERTY:
|
|
result = "Wrong identifier of the program property";
|
|
break;
|
|
|
|
//
|
|
case ERR_TERMINAL_WRONG_PROPERTY:
|
|
result = "Wrong identifier of the terminal property";
|
|
break;
|
|
|
|
//
|
|
case ERR_FTP_SEND_FAILED:
|
|
result = "File sending via ftp failed";
|
|
break;
|
|
|
|
//
|
|
case ERR_NOTIFICATION_SEND_FAILED:
|
|
result = "Error in sending notification";
|
|
break;
|
|
|
|
//
|
|
//--- Custom Indicator Buffers
|
|
|
|
//
|
|
case ERR_BUFFERS_NO_MEMORY:
|
|
result = "Not enough memory for the distribution of indicator buffers";
|
|
break;
|
|
|
|
//
|
|
case ERR_BUFFERS_WRONG_INDEX:
|
|
result = "Wrong indicator buffer index";
|
|
break;
|
|
|
|
//
|
|
//--- Custom Indicator Properties
|
|
|
|
//
|
|
case ERR_CUSTOM_WRONG_PROPERTY:
|
|
result = "Wrong ID of the custom indicator property";
|
|
break;
|
|
|
|
//
|
|
//--- Account
|
|
|
|
//
|
|
case ERR_ACCOUNT_WRONG_PROPERTY:
|
|
result = "Wrong account property ID";
|
|
break;
|
|
|
|
//
|
|
case ERR_TRADE_WRONG_PROPERTY:
|
|
result = "Wrong trade property ID";
|
|
break;
|
|
|
|
//
|
|
case ERR_TRADE_DISABLED:
|
|
result = "Trading by Expert Advisors prohibited";
|
|
break;
|
|
|
|
//
|
|
case ERR_TRADE_POSITION_NOT_FOUND:
|
|
result = "Position not found";
|
|
break;
|
|
|
|
//
|
|
case ERR_TRADE_ORDER_NOT_FOUND:
|
|
result = "Order not found";
|
|
break;
|
|
|
|
//
|
|
case ERR_TRADE_DEAL_NOT_FOUND:
|
|
result = "Deal not found";
|
|
break;
|
|
|
|
//
|
|
case ERR_TRADE_SEND_FAILED:
|
|
result = "Trade request sending failed";
|
|
break;
|
|
|
|
//
|
|
//--- Indicators
|
|
|
|
//
|
|
case ERR_INDICATOR_UNKNOWN_SYMBOL:
|
|
result = "Unknown symbol";
|
|
break;
|
|
|
|
//
|
|
case ERR_INDICATOR_CANNOT_CREATE:
|
|
result = "Indicator cannot be created";
|
|
break;
|
|
|
|
//
|
|
case ERR_INDICATOR_NO_MEMORY:
|
|
result = "Not enough memory to add the indicator";
|
|
break;
|
|
|
|
//
|
|
case ERR_INDICATOR_CANNOT_APPLY:
|
|
result = "The indicator cannot be applied to another indicator";
|
|
break;
|
|
|
|
//
|
|
case ERR_INDICATOR_CANNOT_ADD:
|
|
result = "Error applying an indicator to chart";
|
|
break;
|
|
|
|
//
|
|
case ERR_INDICATOR_DATA_NOT_FOUND:
|
|
result = "Requested data not found";
|
|
break;
|
|
|
|
//
|
|
case ERR_INDICATOR_WRONG_HANDLE:
|
|
result = "Wrong indicator handle";
|
|
break;
|
|
|
|
//
|
|
case ERR_INDICATOR_WRONG_PARAMETERS:
|
|
result = "Wrong number of parameters when creating an indicator";
|
|
break;
|
|
|
|
//
|
|
case ERR_INDICATOR_PARAMETERS_MISSING:
|
|
result = "No parameters when creating an indicator";
|
|
break;
|
|
|
|
//
|
|
case ERR_INDICATOR_CUSTOM_NAME:
|
|
result = "The first parameter in the array must be the name of the custom indicator";
|
|
break;
|
|
|
|
//
|
|
case ERR_INDICATOR_PARAMETER_TYPE:
|
|
result = "Invalid parameter type in the array when creating an indicator";
|
|
break;
|
|
|
|
//
|
|
case ERR_INDICATOR_WRONG_INDEX:
|
|
result = "Wrong index of the requested indicator buffer";
|
|
break;
|
|
|
|
//
|
|
//--- Depth of Market
|
|
|
|
//
|
|
case ERR_BOOKS_CANNOT_ADD:
|
|
result = "Depth Of Market can not be added";
|
|
break;
|
|
|
|
//
|
|
case ERR_BOOKS_CANNOT_DELETE:
|
|
result = "Depth Of Market can not be removed";
|
|
break;
|
|
|
|
//
|
|
case ERR_BOOKS_CANNOT_GET:
|
|
result = "The data from Depth Of Market can not be obtained";
|
|
break;
|
|
|
|
//
|
|
case ERR_BOOKS_CANNOT_SUBSCRIBE:
|
|
result = "Error in subscribing to receive new data from Depth Of Market";
|
|
break;
|
|
|
|
//
|
|
//--- File Operations
|
|
|
|
//
|
|
case ERR_TOO_MANY_FILES:
|
|
result = "More than 64 files cannot be opened at the same time";
|
|
break;
|
|
|
|
//
|
|
case ERR_WRONG_FILENAME:
|
|
result = "Invalid file name";
|
|
break;
|
|
|
|
//
|
|
case ERR_TOO_LONG_FILENAME:
|
|
result = "Too long file name";
|
|
break;
|
|
|
|
//
|
|
case ERR_CANNOT_OPEN_FILE:
|
|
result = "File opening error";
|
|
break;
|
|
|
|
//
|
|
case ERR_FILE_CACHEBUFFER_ERROR:
|
|
result = "Not enough memory for cache to read";
|
|
break;
|
|
|
|
//
|
|
case ERR_CANNOT_DELETE_FILE:
|
|
result = "File deleting error";
|
|
break;
|
|
|
|
//
|
|
case ERR_INVALID_FILEHANDLE:
|
|
result = "A file with this handle was closed, or was not opening at all";
|
|
break;
|
|
|
|
//
|
|
case ERR_WRONG_FILEHANDLE:
|
|
result = "Wrong file handle";
|
|
break;
|
|
|
|
//
|
|
case ERR_FILE_NOTTOWRITE:
|
|
result = "The file must be opened for writing";
|
|
break;
|
|
|
|
//
|
|
case ERR_FILE_NOTTOREAD:
|
|
result = "The file must be opened for reading";
|
|
break;
|
|
|
|
//
|
|
case ERR_FILE_NOTBIN:
|
|
result = "The file must be opened as a binary one";
|
|
break;
|
|
|
|
//
|
|
case ERR_FILE_NOTTXT:
|
|
result = "The file must be opened as a text";
|
|
break;
|
|
|
|
//
|
|
case ERR_FILE_NOTTXTORCSV:
|
|
result = "The file must be opened as a text or CSV";
|
|
break;
|
|
|
|
//
|
|
case ERR_FILE_NOTCSV:
|
|
result = "The file must be opened as CSV";
|
|
break;
|
|
|
|
//
|
|
case ERR_FILE_READERROR:
|
|
result = "File reading error";
|
|
break;
|
|
|
|
//
|
|
case ERR_FILE_BINSTRINGSIZE:
|
|
result = "String size must be specified, because the file is opened as binary";
|
|
break;
|
|
|
|
//
|
|
case ERR_INCOMPATIBLE_FILE:
|
|
result = "A text file must be for string arrays, for other arrays - binary";
|
|
break;
|
|
|
|
//
|
|
case ERR_FILE_IS_DIRECTORY:
|
|
result = "This is not a file, this is a directory";
|
|
break;
|
|
|
|
//
|
|
case ERR_FILE_NOT_EXIST:
|
|
result = "File does not exist";
|
|
break;
|
|
|
|
//
|
|
case ERR_FILE_CANNOT_REWRITE:
|
|
result = "File can not be rewritten";
|
|
break;
|
|
|
|
//
|
|
case ERR_WRONG_DIRECTORYNAME:
|
|
result = "Wrong directory name";
|
|
break;
|
|
|
|
//
|
|
case ERR_DIRECTORY_NOT_EXIST:
|
|
result = "Directory does not exist";
|
|
break;
|
|
|
|
//
|
|
case ERR_FILE_ISNOT_DIRECTORY:
|
|
result = "This is a file, not a directory";
|
|
break;
|
|
|
|
//
|
|
case ERR_CANNOT_DELETE_DIRECTORY:
|
|
result = "The directory cannot be removed";
|
|
break;
|
|
|
|
//
|
|
case ERR_CANNOT_CLEAN_DIRECTORY:
|
|
result = "Failed to clear the directory (probably one or more files are blocked and removal operation failed)";
|
|
break;
|
|
|
|
//
|
|
case ERR_FILE_WRITEERROR:
|
|
result = "Failed to write a resource to a file";
|
|
break;
|
|
|
|
//
|
|
//--- String Casting
|
|
|
|
//
|
|
case ERR_NO_STRING_DATE:
|
|
result = "No date in the string";
|
|
break;
|
|
|
|
//
|
|
case ERR_WRONG_STRING_DATE:
|
|
result = "Wrong date in the string";
|
|
break;
|
|
|
|
//
|
|
case ERR_WRONG_STRING_TIME:
|
|
result = "Wrong time in the string";
|
|
break;
|
|
|
|
//
|
|
case ERR_STRING_TIME_ERROR:
|
|
result = "Error converting string to date";
|
|
break;
|
|
|
|
//
|
|
case ERR_STRING_OUT_OF_MEMORY:
|
|
result = "Not enough memory for the string";
|
|
break;
|
|
|
|
//
|
|
case ERR_STRING_SMALL_LEN:
|
|
result = "The string length is less than expected";
|
|
break;
|
|
|
|
//
|
|
case ERR_STRING_TOO_BIGNUMBER:
|
|
result = "Too large number, more than ULONG_MAX";
|
|
break;
|
|
|
|
//
|
|
case ERR_WRONG_FORMATSTRING:
|
|
result = "Invalid format string";
|
|
break;
|
|
|
|
//
|
|
case ERR_TOO_MANY_FORMATTERS:
|
|
result = "Amount of format specifiers more than the parameters";
|
|
break;
|
|
|
|
//
|
|
case ERR_TOO_MANY_PARAMETERS:
|
|
result = "Amount of parameters more than the format specifiers";
|
|
break;
|
|
|
|
//
|
|
case ERR_WRONG_STRING_PARAMETER:
|
|
result = "Damaged parameter of string type";
|
|
break;
|
|
|
|
//
|
|
case ERR_STRINGPOS_OUTOFRANGE:
|
|
result = "Position outside the string";
|
|
break;
|
|
|
|
//
|
|
case ERR_STRING_ZEROADDED:
|
|
result = "0 added to the string end, a useless operation";
|
|
break;
|
|
|
|
//
|
|
case ERR_STRING_UNKNOWNTYPE:
|
|
result = "Unknown data type when converting to a string";
|
|
break;
|
|
|
|
//
|
|
case ERR_WRONG_STRING_OBJECT:
|
|
result = "Damaged string object";
|
|
break;
|
|
|
|
//
|
|
//--- Operations with Arrays
|
|
|
|
//
|
|
case ERR_INCOMPATIBLE_ARRAYS:
|
|
result = "Copying incompatible arrays. String array can be copied only to a string array, and a numeric array - in numeric array only";
|
|
break;
|
|
|
|
//
|
|
case ERR_SMALL_ASSERIES_ARRAY:
|
|
result = "The receiving array is declared as AS_SERIES, and it is of insufficient size";
|
|
break;
|
|
|
|
//
|
|
case ERR_SMALL_ARRAY:
|
|
result = "Too small array, the starting position is outside the array";
|
|
break;
|
|
|
|
//
|
|
case ERR_ZEROSIZE_ARRAY:
|
|
result = "An array of zero length";
|
|
break;
|
|
|
|
//
|
|
case ERR_NUMBER_ARRAYS_ONLY:
|
|
result = "Must be a numeric array";
|
|
break;
|
|
|
|
//
|
|
case ERR_ONEDIM_ARRAYS_ONLY:
|
|
result = "Must be a one-dimensional array";
|
|
break;
|
|
|
|
//
|
|
case ERR_SERIES_ARRAY:
|
|
result = "Timeseries cannot be used";
|
|
break;
|
|
|
|
//
|
|
case ERR_DOUBLE_ARRAY_ONLY:
|
|
result = "Must be an array of type double";
|
|
break;
|
|
|
|
//
|
|
case ERR_FLOAT_ARRAY_ONLY:
|
|
result = "Must be an array of type float";
|
|
break;
|
|
|
|
//
|
|
case ERR_LONG_ARRAY_ONLY:
|
|
result = "Must be an array of type long";
|
|
break;
|
|
|
|
//
|
|
case ERR_INT_ARRAY_ONLY:
|
|
result = "Must be an array of type int";
|
|
break;
|
|
|
|
//
|
|
case ERR_SHORT_ARRAY_ONLY:
|
|
result = "Must be an array of type short";
|
|
break;
|
|
|
|
//
|
|
case ERR_CHAR_ARRAY_ONLY:
|
|
result = "Must be an array of type char";
|
|
break;
|
|
|
|
//
|
|
//--- Operations with OpenCL
|
|
|
|
//
|
|
case ERR_OPENCL_NOT_SUPPORTED:
|
|
result = "OpenCL functions are not supported on this computer";
|
|
break;
|
|
|
|
//
|
|
case ERR_OPENCL_INTERNAL:
|
|
result = "Internal error occurred when running OpenCL";
|
|
break;
|
|
|
|
//
|
|
case ERR_OPENCL_INVALID_HANDLE:
|
|
result = "Invalid OpenCL handle";
|
|
break;
|
|
|
|
//
|
|
case ERR_OPENCL_CONTEXT_CREATE:
|
|
result = "Error creating the OpenCL context";
|
|
break;
|
|
|
|
//
|
|
case ERR_OPENCL_QUEUE_CREATE:
|
|
result = "Failed to create a run queue in OpenCL";
|
|
break;
|
|
|
|
//
|
|
case ERR_OPENCL_PROGRAM_CREATE:
|
|
result = "Error occurred when compiling an OpenCL program";
|
|
break;
|
|
|
|
//
|
|
case ERR_OPENCL_TOO_LONG_KERNEL_NAME:
|
|
result = "Too long kernel name (OpenCL kernel)";
|
|
break;
|
|
|
|
//
|
|
case ERR_OPENCL_KERNEL_CREATE:
|
|
result = "Error creating an OpenCL kernel";
|
|
break;
|
|
|
|
//
|
|
case ERR_OPENCL_SET_KERNEL_PARAMETER:
|
|
result = "Error occurred when setting parameters for the OpenCL kernel";
|
|
break;
|
|
|
|
//
|
|
case ERR_OPENCL_EXECUTE:
|
|
result = "OpenCL program runtime error";
|
|
break;
|
|
|
|
//
|
|
case ERR_OPENCL_WRONG_BUFFER_SIZE:
|
|
result = "Invalid size of the OpenCL buffer";
|
|
break;
|
|
|
|
//
|
|
case ERR_OPENCL_WRONG_BUFFER_OFFSET:
|
|
result = "Invalid offset in the OpenCL buffer";
|
|
break;
|
|
|
|
//
|
|
case ERR_OPENCL_BUFFER_CREATE:
|
|
result = "Failed to create and OpenCL buffer";
|
|
break;
|
|
|
|
//
|
|
//--- User-Defined Errors
|
|
default:
|
|
result = "UNKNOWN Erro ...";
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Specified Error Code Description ...
|
|
string GetTradeServerReturnCodeDescription(int return_code)
|
|
{
|
|
//
|
|
string result = "";
|
|
|
|
//
|
|
switch (return_code)
|
|
{
|
|
//
|
|
case TRADE_RETCODE_REQUOTE:
|
|
result = "Requote";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_REJECT:
|
|
result = "Request rejected";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_CANCEL:
|
|
result = "Request canceled by trader";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_PLACED:
|
|
result = "Order placed";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_DONE:
|
|
result = "Request completed";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_DONE_PARTIAL:
|
|
result = "Only part of the request was completed";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_ERROR:
|
|
result = "Request processing error";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_TIMEOUT:
|
|
result = "Request canceled by timeout";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_INVALID:
|
|
result = "Invalid request";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_INVALID_VOLUME:
|
|
result = "Invalid volume in the request";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_INVALID_PRICE:
|
|
result = "Invalid price in the request";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_INVALID_STOPS:
|
|
result = "Invalid stops in the request";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_TRADE_DISABLED:
|
|
result = "Trade is disabled";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_MARKET_CLOSED:
|
|
result = "Market is closed";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_NO_MONEY:
|
|
result = "There is not enough money to complete the request";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_PRICE_CHANGED:
|
|
result = "Prices changed";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_PRICE_OFF:
|
|
result = "There are no quotes to process the request";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_INVALID_EXPIRATION:
|
|
result = "Invalid order expiration date in the request";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_ORDER_CHANGED:
|
|
result = "Order state changed";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_TOO_MANY_REQUESTS:
|
|
result = "Too frequent requests";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_NO_CHANGES:
|
|
result = "No changes in request";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_SERVER_DISABLES_AT:
|
|
result = "Autotrading disabled by server";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_CLIENT_DISABLES_AT:
|
|
result = "Autotrading disabled by client terminal";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_LOCKED:
|
|
result = "Request locked for processing";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_FROZEN:
|
|
result = "Order or position frozen";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_INVALID_FILL:
|
|
result = "Invalid order filling type";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_CONNECTION:
|
|
result = "No connection with the trade server";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_ONLY_REAL:
|
|
result = "Operation is allowed only for live accounts";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_LIMIT_ORDERS:
|
|
result = "The number of pending orders has reached the limit";
|
|
break;
|
|
|
|
//
|
|
case TRADE_RETCODE_LIMIT_VOLUME:
|
|
result = "The volume of orders and positions for the symbol has reached the limit";
|
|
break;
|
|
|
|
//
|
|
default:
|
|
result = "Invalid return code of the trade server";
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Check Expert Running in Testing Mode or not ...
|
|
bool IsRunningOnTestMode()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// check programm mode ...
|
|
result = MQL5InfoInteger(MQL5_TESTING);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Date Time Manipulation Functions ...
|
|
//
|
|
|
|
//
|
|
// Representation of Time Struct ...
|
|
// struct MqlDateTime
|
|
// {
|
|
// int year; // Year
|
|
// int mon; // Month
|
|
// int day; // Day
|
|
// int hour; // Hour
|
|
// int min; // Minutes
|
|
// int sec; // Seconds
|
|
// int day_of_week; // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday)
|
|
// int day_of_year; // Day number of the year (January 1st is assigned the number value of zero)
|
|
// };
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
// Retrieve DateTime Structure ...
|
|
MqlDateTime GetCurrentTime()
|
|
{
|
|
//
|
|
MqlDateTime result = {};
|
|
|
|
//
|
|
TimeCurrent(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;
|
|
}
|
|
|
|
//
|
|
// Retrieve Specified Candle Time ...
|
|
datetime GetCandleTime(
|
|
string symbol = "", // Specify Symbol
|
|
ENUM_TIMEFRAMES period = NULL, // Specify TimeFrame
|
|
int bar_index = 0 // Specify Bar Index
|
|
)
|
|
{
|
|
//
|
|
// Validate and Normalize Args ...
|
|
|
|
//
|
|
// Normalize Symbol ...
|
|
symbol = StringLen(symbol) == 0
|
|
? _Symbol
|
|
: symbol;
|
|
|
|
//
|
|
// Normalize Period ...
|
|
period = period == NULL
|
|
? _Period
|
|
: period;
|
|
|
|
//
|
|
// Retrieve Bar Time ...
|
|
datetime result = iTime(
|
|
symbol,
|
|
period,
|
|
bar_index);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Specified Candle Time ...
|
|
ulong GetCandleTimeAsSeconds(
|
|
string symbol = "", // Specify Symbol
|
|
ENUM_TIMEFRAMES period = NULL, // Specify TimeFrame
|
|
int bar_index = 0 // Specify Bar Index
|
|
)
|
|
{
|
|
//
|
|
// Retrieve Bar Time ...
|
|
datetime time = GetCandleTime(
|
|
symbol,
|
|
period,
|
|
bar_index);
|
|
|
|
//
|
|
ulong result = TimeToSeconds(time);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve Specified Candle Time ...
|
|
ulong GetCandleTimeAsMilliSeconds(
|
|
string symbol = "", // Specify Symbol
|
|
ENUM_TIMEFRAMES period = NULL, // Specify TimeFrame
|
|
int bar_index = 0 // Specify Bar Index
|
|
)
|
|
{
|
|
//
|
|
// Retrieve Bar Time ...
|
|
datetime time = GetCandleTime(
|
|
symbol,
|
|
period,
|
|
bar_index);
|
|
|
|
//
|
|
ulong result = TimeToMilliSeconds(time);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Retrieve a Candle Time Structure ...
|
|
MqlDateTime GetCandleTimeStruct(
|
|
string symbol = "", // Specify Symbol
|
|
ENUM_TIMEFRAMES period = NULL, // Specify TimeFrame
|
|
int bar_index = 0 // Specify Bar Index
|
|
)
|
|
{
|
|
//
|
|
MqlDateTime result = {};
|
|
|
|
//
|
|
// Retrieve Bar Time ...
|
|
datetime barTime = GetCandleTime(
|
|
symbol,
|
|
period,
|
|
bar_index);
|
|
|
|
//
|
|
// Convert to Structure ...
|
|
TimeToStruct(barTime, result);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
//
|
|
// Holds Month ...
|
|
static int xMonth = -1;
|
|
|
|
//
|
|
// Holds Day Of Week ...
|
|
static int xDayOfWeek = -1;
|
|
static int xForWeekDay = -1;
|
|
|
|
//
|
|
// Holds Day ...
|
|
static int xDay = -1;
|
|
|
|
//
|
|
// Holds Hour ...
|
|
static int xHour = -1;
|
|
|
|
//
|
|
// Reset Timing Variables ...
|
|
void ResetTiming()
|
|
{
|
|
//
|
|
xHour = -1;
|
|
xDay = -1;
|
|
xDayOfWeek = -1;
|
|
xMonth = -1;
|
|
}
|
|
|
|
//
|
|
// Detecting New Houre ...
|
|
bool IsNewHour()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Retrieve Current Time as Struct ...
|
|
MqlDateTime timeStruct = GetCurrentTime();
|
|
|
|
//
|
|
// Check Houre ...
|
|
result = timeStruct.hour != xHour;
|
|
if (result)
|
|
{
|
|
xHour = timeStruct.hour;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Detecting New Day ...
|
|
bool IsNewDay()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Retrieve Current Time as Struct ...
|
|
MqlDateTime timeStruct = GetCurrentTime();
|
|
|
|
//
|
|
// Check Houre ...
|
|
result = timeStruct.day_of_year != xDay;
|
|
if (result)
|
|
{
|
|
xDay = timeStruct.day_of_year;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Detecting New Week ...
|
|
bool IsNewWeek()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Retrieve Current Time as Struct ...
|
|
MqlDateTime timeStruct = GetCurrentTime();
|
|
|
|
//
|
|
// Check Week ...
|
|
// Since Week Starts From Monday in Forex World ...
|
|
// we Calculate Start of Week by 1-Monday ...
|
|
result =
|
|
xDayOfWeek == -1 &&
|
|
xForWeekDay == -1
|
|
? true
|
|
: timeStruct.day_of_week == 1 &&
|
|
timeStruct.day_of_year > xForWeekDay;
|
|
|
|
//
|
|
xForWeekDay = timeStruct.day_of_year;
|
|
xDayOfWeek = timeStruct.day_of_week;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Detecting End Of Week ...
|
|
bool IsWeekEnd()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Retrieve Current Time as Struct ...
|
|
MqlDateTime timeStruct = GetCurrentTime();
|
|
|
|
//
|
|
// Check WeekEnd ...
|
|
// Since Week Starts From Monday in Forex World ...
|
|
// we Calculate End of Week by 5-Friday ...
|
|
result =
|
|
xDayOfWeek != -1 &&
|
|
timeStruct.day_of_week == 5 &&
|
|
timeStruct.hour == 23 &&
|
|
timeStruct.min == 59 &&
|
|
timeStruct.sec == 59;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Detecting New Month ...
|
|
bool IsNewMonth()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
// Retrieve Current Time as Struct ...
|
|
MqlDateTime timeStruct = GetCurrentTime();
|
|
|
|
//
|
|
// Check Houre ...
|
|
result = timeStruct.mon != xMonth;
|
|
if (result)
|
|
{
|
|
xMonth = timeStruct.mon;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Farest Time Frame ...
|
|
ENUM_TIMEFRAMES GetFarestTimeFrame(
|
|
ENUM_TIMEFRAMES mPeriod // Specified Period
|
|
)
|
|
{
|
|
//
|
|
ENUM_TIMEFRAMES result = NULL;
|
|
|
|
//
|
|
// Normalize Period ...
|
|
if (
|
|
mPeriod < 0 ||
|
|
mPeriod == NULL)
|
|
{
|
|
mPeriod = _Period;
|
|
}
|
|
|
|
//
|
|
switch (mPeriod)
|
|
{
|
|
//
|
|
case PERIOD_M1:
|
|
case PERIOD_M2:
|
|
case PERIOD_M3:
|
|
case PERIOD_M4:
|
|
case PERIOD_M5:
|
|
case PERIOD_M6:
|
|
case PERIOD_M10:
|
|
case PERIOD_M12:
|
|
case PERIOD_M15:
|
|
case PERIOD_M20:
|
|
case PERIOD_M30:
|
|
result = PERIOD_H4;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H1:
|
|
case PERIOD_H2:
|
|
case PERIOD_H3:
|
|
case PERIOD_H4:
|
|
result = PERIOD_H12;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H6:
|
|
case PERIOD_H8:
|
|
case PERIOD_H12:
|
|
case PERIOD_D1:
|
|
result = PERIOD_W1;
|
|
break;
|
|
|
|
//
|
|
default:
|
|
result = PERIOD_MN1;
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Medium Time Frame ...
|
|
ENUM_TIMEFRAMES GetMediestTimeFrame(
|
|
ENUM_TIMEFRAMES mPeriod // Specified Period
|
|
)
|
|
{
|
|
//
|
|
ENUM_TIMEFRAMES result = NULL;
|
|
|
|
//
|
|
// Normalize Period ...
|
|
if (
|
|
mPeriod < 0 ||
|
|
mPeriod == NULL)
|
|
{
|
|
mPeriod = _Period;
|
|
}
|
|
|
|
//
|
|
switch (mPeriod)
|
|
{
|
|
//
|
|
case PERIOD_M1:
|
|
case PERIOD_M2:
|
|
case PERIOD_M3:
|
|
case PERIOD_M4:
|
|
case PERIOD_M5:
|
|
case PERIOD_M6:
|
|
case PERIOD_M10:
|
|
case PERIOD_M12:
|
|
case PERIOD_M15:
|
|
case PERIOD_M20:
|
|
result = PERIOD_H1;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M30:
|
|
result = PERIOD_H2;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H1:
|
|
case PERIOD_H2:
|
|
case PERIOD_H3:
|
|
result = PERIOD_H4;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H4:
|
|
case PERIOD_H6:
|
|
case PERIOD_H8:
|
|
result = PERIOD_H12;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H12:
|
|
result = PERIOD_D1;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_D1:
|
|
result = PERIOD_W1;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_W1:
|
|
result = PERIOD_MN1;
|
|
break;
|
|
|
|
//
|
|
default:
|
|
result = PERIOD_MN1;
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Find Nearest Time Frame ...
|
|
ENUM_TIMEFRAMES GetNearestTimeFrame(
|
|
ENUM_TIMEFRAMES mPeriod // Specified Period
|
|
)
|
|
{
|
|
//
|
|
ENUM_TIMEFRAMES result = NULL;
|
|
|
|
//
|
|
// Normalize Period ...
|
|
if (
|
|
mPeriod < 0 ||
|
|
mPeriod == NULL)
|
|
{
|
|
mPeriod = _Period;
|
|
}
|
|
|
|
//
|
|
switch (mPeriod)
|
|
{
|
|
//
|
|
case PERIOD_M1:
|
|
case PERIOD_M2:
|
|
case PERIOD_M3:
|
|
case PERIOD_M4:
|
|
result = PERIOD_M5;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M5:
|
|
case PERIOD_M6:
|
|
case PERIOD_M10:
|
|
case PERIOD_M12:
|
|
result = PERIOD_M15;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M15:
|
|
case PERIOD_M20:
|
|
result = PERIOD_M30;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_M30:
|
|
result = PERIOD_H1;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H1:
|
|
case PERIOD_H2:
|
|
case PERIOD_H3:
|
|
result = PERIOD_H4;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H4:
|
|
case PERIOD_H6:
|
|
case PERIOD_H8:
|
|
result = PERIOD_H12;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_H12:
|
|
result = PERIOD_D1;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_D1:
|
|
result = PERIOD_W1;
|
|
break;
|
|
|
|
//
|
|
case PERIOD_W1:
|
|
result = PERIOD_MN1;
|
|
break;
|
|
|
|
//
|
|
default:
|
|
result = PERIOD_MN1;
|
|
break;
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// 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 ...
|
|
)
|
|
{
|
|
//
|
|
// Normalize Arg ...
|
|
|
|
//
|
|
if (
|
|
mSymbol == NULL ||
|
|
StringLen(mSymbol) == 0)
|
|
{
|
|
mSymbol = _Symbol;
|
|
}
|
|
|
|
//
|
|
if (
|
|
mPeriod < 0 ||
|
|
mPeriod == NULL)
|
|
{
|
|
mPeriod = _Period;
|
|
}
|
|
|
|
//
|
|
if (
|
|
mTime < 0 ||
|
|
mTime == NULL)
|
|
{
|
|
mTime = TimeCurrent();
|
|
}
|
|
|
|
//
|
|
int barIndex = iBarShift(
|
|
mSymbol,
|
|
mPeriod,
|
|
mTime,
|
|
false);
|
|
|
|
//
|
|
datetime result = iTime(
|
|
mSymbol,
|
|
mPeriod,
|
|
barIndex);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// END Provided Functions ...
|
|
//
|