diff --git a/Classes/x-saherelm.base.class.lib.mq5 b/Classes/x-saherelm.base.class.lib.mq5 new file mode 100644 index 00000000..2b9bab48 --- /dev/null +++ b/Classes/x-saherelm.base.class.lib.mq5 @@ -0,0 +1,36 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XBaseClass +// Description: provides all based classes for use ... +// +// +// 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 + +// +// XBase Class ... +class XCBase +{ + // + // Public ... +public: + // + // Protected ... +protected: + + // + // Private ... +private: +}; diff --git a/Classes/x-saherelm.provider.lib.mq5 b/Classes/x-saherelm.provider.lib.mq5 new file mode 100644 index 00000000..9008879d --- /dev/null +++ b/Classes/x-saherelm.provider.lib.mq5 @@ -0,0 +1,4430 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XProvider +// Description: provides all indicators based provider classes for use ... +// +// +// 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 Define Enums ... +// + +// +enum ENUM_X_SIGNAL_PROVIDERS +{ + // + // XSP Expert Support Mechanism ... + XSP, + // + // XTD ... + XTD, + // + // XTAM ... + XTAM, + // + // XSI ... + XSI, + // + // XTSFI ... + XTSFI, + // + // XOBDLH ... + XOBDLH, + // + // XCHMACC ... + XCHMACC, + // + // XCHMACMN ... + XCHMAMN, + // + // XCHMACMX ... + XCHMAMX, +}; + +// +// Represent Market Conditions ... +struct XMarketConditions +{ + // + // XTM ... + bool isXTMPeak; + bool isXTMVale; + bool isXTMBullish; + bool isXTMBearish; + bool isXTMNeutural; + bool isXTMEndBullish; + bool isXTMEndBearish; + bool isXTMStartBullish; + bool isXTMStartBearish; + bool isXTMEndBullishByNeutural; + bool isXTMEndBearishByNeutural; + bool isXTMStartBullishAfterNeutural; + bool isXTMStartBearishAfterNeutural; + + // + // XAMA ... + bool isXAMAPeak; + bool isXAMAVale; + bool isXAMABullish; + bool isXAMABearish; + bool isXAMANeutural; + bool isXAMAEndBullish; + bool isXAMAEndBearish; + bool isXAMAStartBullish; + bool isXAMAStartBearish; + bool isXAMAEndBullishByNeutural; + bool isXAMAEndBearishByNeutural; + bool isXAMAStartBullishAfterNeutural; + bool isXAMAStartBearishAfterNeutural; + + // + // XLH ... + bool isXLHHHIncreased; + bool isXLHHHDecreased; + bool isXLHLLIncreased; + bool isXLHLLDecreased; + bool isXLHLowAttachedLL; + bool isXLHHighAttachedHH; + bool isXLHHHSameInLength; + bool isXLHLLSameInLength; + bool isXLHPriceOverSignal; + bool isXLHPriceUnderSignal; + bool isXLHPriceInSignalRange; + bool isXLHPriceCrossedOverSignal; + bool isXLHPriceCrossedUnderSignal; + + // + // XTD ... + bool isXTDSignalPeak; + bool isXTDSignalVale; + bool isXTDBullishPeak; + bool isXTDBullishVale; + bool isXTDBearishPeak; + bool isXTDBearishVale; + bool isXTDBullOverBear; + bool isXTDBullUnderBear; + bool isXTDSignalOverBear; + bool isXTDSignalUnderBear; + bool isXTDBullCrossedOverBear; + bool isXTDBullCrossedUnderBear; + bool isXTDSignalCrossedOverBear; + bool isXTDSignalCrossedUnderBear; + + // + // XFI ... + bool isXFIPeak; + bool isXFIVale; + bool isXFICrossedOverZero; + bool isXFIOverZero; + bool isXFICrossedUnderZero; + bool isXFIUnderZero; + + // + // XTS ... + bool isXTSAllSame; + bool isXTSCurrentMin; + bool isXTSCurrentMax; + bool isXTSCurrentOverFarest; + bool isXTSCurrentOverNearest; + bool isXTSCurrentOverMediest; + bool isXTSCurrentUnderFarest; + bool isXTSCurrentUnderNearest; + bool isXTSCurrentUnderMediest; + bool isXTSCurrentCrossedOverFarest; + bool isXTSCurrentCrossedOverNearest; + bool isXTSCurrentCrossedOverMediest; + bool isXTSCurrentCrossedUnderFarest; + bool isXTSCurrentCrossedUnderNearest; + bool isXTSCurrentCrossedUnderMediest; + + // + // XRSI ... + bool isXRSIPeak; + bool isXRSIVale; + bool isXRSICrossedOverLongExit; + bool isXRSICrossedOverLongEntry; + bool isXRSICrossedUnderShortExit; + bool isXRSICrossedUnderShortEntry; + + // + // XOBD ... + bool isXOBDSwingLow; + bool isXOBDSwingHigh; + + // + // XCHLH ... + // + bool isXCHLHSameHHs; + bool isXCHLHSameLLs; + // + bool isXCHLHSCMCHHSame; + bool isXCHLHSCMCLLSame; + // + bool isXCHLHSCLCHHSame; + bool isXCHLHSCLCLLSame; + // + bool isXCHLHMCLCHHSame; + bool isXCHLHMCLCLLSame; + // + bool isXCHLHMCOnTopOfLC; + bool isXCHLHMCInBottomOfLC; + + // + // XCHMA ... + // + bool isXCHMASCOverMax; + bool isXCHMASCOverMin; + bool isXCHMASCUnderMax; + bool isXCHMASCUnderMin; + // + bool isXCHMASCCrossedOverMax; + bool isXCHMASCCrossedUnderMax; + bool isXCHMASCCrossedOverMin; + bool isXCHMASCCrossedUnderMin; + // + bool isXCHMASCPeak; + bool isXCHMASCVale; + bool isXCHMASCTrendsUp; + bool isXCHMASCTrendsDown; + bool isXCHMASCFastOverSlow; + bool isXCHMASCFastUnderSlow; + bool isXCHMASCFastCrossedOverSlow; + bool isXCHMASCFastCrossedUnderSlow; + // + bool isXCHMAMCPeak; + bool isXCHMAMCVale; + bool isXCHMAMCTrendsUp; + bool isXCHMAMCTrendsDown; + bool isXCHMAMCFastOverSlow; + bool isXCHMAMCFastUnderSlow; + bool isXCHMAMCFastCrossedOverSlow; + bool isXCHMAMCFastCrossedUnderSlow; + // + bool isXCHMALCPeak; + bool isXCHMALCVale; + bool isXCHMALCTrendsUp; + bool isXCHMALCTrendsDown; + bool isXCHMALCFastOverSlow; + bool isXCHMALCFastUnderSlow; + bool isXCHMALCFastCrossedOverSlow; + bool isXCHMALCFastCrossedUnderSlow; +}; + +// +// END Define Enums ... +// + +// +// START Includes Requirements ... +// + +// +// Includes Classes ... +#include "x-saherelm.base.class.lib.mq5" + +// +// Includes all Indicator's Helpers ... +#include "../Helpers/x-saherelm.xlh.indicator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xtm.indicator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xama.indicator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xfi.oscillator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xobd.indicator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xts.oscillator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xtd.oscillator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xrsi.oscillator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xchlh.oscillator.helper.lib.mq5" +#include "../Helpers/x-saherelm.xchma.oscillator.helper.lib.mq5" + +// +// END Includes Requirements ... +// + +// +class XCProvider : public XCBase +{ + // + // Public ... +public: + // + // Constructor ... + XCProvider( + // + // Common Requirements ... + string xSymbol, // Which Symbol is Used + ENUM_TIMEFRAMES xPeriod, // Which Period is Used + // + // Signallers Requirements ... + // + // XTD ... + bool xTDEnableSignaller, // Enable Signaller + bool xTDAllowLongSignals, // Allow Long Signals + bool xTDAllowShortSignals, // Allow Short Signals + // + // XTAM ... + bool xTAMEnableSignaller, // Enable Signaller + bool xTAMAllowLongSignals, // Allow Long Signals + bool xTAMAllowShortSignals, // Allow Short Signals + // + // XSI ... + bool xSIEnableSignaller, // Enable Signaller + bool xSIAllowLongSignals, // Allow Long Signals + bool xSIAllowShortSignals, // Allow Short Signals + // + // XTSFI ... + bool XTSFIEnableSignaller, // Enable Signaller + bool XTSFIAllowLongSignals, // Allow Long Signals + bool XTSFIAllowShortSignals, // Allow Short Signals + // + // XOBDLH ... + bool xOBDLHEnableSignaller, // Enable Signaller + bool xOBDLHAllowLongSignals, // Allow Long Signals + bool xOBDLHAllowShortSignals, // Allow Short Signals + // + // XCHMACC ... + bool xCHMACCEnableSignaller, // Enable Signaller + bool xCHMACCAllowLongSignals, // Allow Long Signals + bool xCHMACCAllowShortSignals, // Allow Short Signals + // + // XCHMAMX ... + bool xCHMACMXEnableSignaller, // Enable Signaller + bool xCHMACMXAllowLongSignals, // Allow Long Signals + bool xCHMACMXAllowShortSignals, // Allow Short Signals + // + // XCHMAMN ... + bool xCHMACMNEnableSignaller, // Enable Signaller + bool xCHMACMNAllowLongSignals, // Allow Long Signals + bool xCHMACMNAllowShortSignals // Allow Short Signals + // + ) + { + // + // XTD ... + mXTDEnableSignaller = xTDEnableSignaller; + mXTDAllowLongSignals = xTDAllowLongSignals; + mXTDAllowShortSignals = xTDAllowShortSignals; + + // + // XTAM ... + mXTAMEnableSignaller = xTAMEnableSignaller; + mXTAMAllowLongSignals = xTAMAllowLongSignals; + mXTAMAllowShortSignals = xTAMAllowShortSignals; + + // + // XSI ... + mXSIEnableSignaller = xSIEnableSignaller; + mXSIAllowLongSignals = xSIAllowLongSignals; + mXSIAllowShortSignals = xSIAllowShortSignals; + + // + // XTSFI ... + mXTSFIEnableSignaller = XTSFIEnableSignaller; + mXTSFIAllowLongSignals = XTSFIAllowLongSignals; + mXTSFIAllowShortSignals = XTSFIAllowShortSignals; + + // + // XOBDLH ... + mXOBDLHEnableSignaller = xOBDLHEnableSignaller; + mXOBDLHAllowLongSignals = xOBDLHAllowLongSignals; + mXOBDLHAllowShortSignals = xOBDLHAllowShortSignals; + + // + // XCHMACC ... + mXCHMACCEnableSignaller = xCHMACCEnableSignaller; + mXCHMACCAllowLongSignals = xCHMACCAllowLongSignals; + mXCHMACCAllowShortSignals = xCHMACCAllowShortSignals; + + // + // XCHMAMX ... + mXCHMAMXEnableSignaller = xCHMACMXEnableSignaller; + mXCHMAMXAllowLongSignals = xCHMACMXAllowLongSignals; + mXCHMAMXAllowShortSignals = xCHMACMXAllowShortSignals; + + // + // XCHMAMN ... + mXCHMAMNEnableSignaller = xCHMACMNEnableSignaller; + mXCHMAMNAllowLongSignals = xCHMACMNAllowLongSignals; + mXCHMAMNAllowShortSignals = xCHMACMNAllowShortSignals; + } + + // + // Deconstructor ... + ~XCProvider() {} + + // + // START Common Functions ... + // + + // + // Read All Globally Required Conditions ... + void ReadConditions() + { + // + ClearConditions(); + + // + mXConditions = GenerateMarketConditions(1); + } + + // + // Cleanup Conditions ... + void ClearConditions() + { + // + XMarketConditions mConditions = {}; + + // + mXConditions = mConditions; + } + + // + // Generate Merket Conditions for Specified Bar Index ... + XMarketConditions GenerateMarketConditions( + int bar_index = 1 // Specified Bar Index ... + ) + { + // + XMarketConditions mConditions = {}; + + // + // XTM ... + mConditions.isXTMPeak = XTMIsPeak(bar_index); + mConditions.isXTMVale = XTMIsVale(bar_index); + mConditions.isXTMBullish = XTMIsBullish(bar_index); + mConditions.isXTMBearish = XTMIsBearish(bar_index); + mConditions.isXTMNeutural = XTMIsNeutural(bar_index); + mConditions.isXTMEndBullish = XTMIsEndBullish(bar_index); + mConditions.isXTMEndBearish = XTMIsEndBearish(bar_index); + mConditions.isXTMStartBullish = XTMIsStartBullish(bar_index); + mConditions.isXTMStartBearish = XTMIsStartBearish(bar_index); + mConditions.isXTMEndBullishByNeutural = XTMIsEndBullishByNeutural(bar_index); + mConditions.isXTMEndBearishByNeutural = XTMIsEndBearishByNeutural(bar_index); + mConditions.isXTMStartBullishAfterNeutural = XTMIsStartBullishAfterNeutural(bar_index); + mConditions.isXTMStartBearishAfterNeutural = XTMIsStartBearishAfterNeutural(bar_index); + + // + // XAMA ... + mConditions.isXAMAPeak = XAMAIsPeak(bar_index); + mConditions.isXAMAVale = XAMAIsVale(bar_index); + mConditions.isXAMABullish = XAMAIsBullish(bar_index); + mConditions.isXAMABearish = XAMAIsBearish(bar_index); + mConditions.isXAMANeutural = XAMAIsNeutural(bar_index); + mConditions.isXAMAEndBullish = XAMAIsEndBullish(bar_index); + mConditions.isXAMAEndBearish = XAMAIsEndBearish(bar_index); + mConditions.isXAMAStartBullish = XAMAIsStartBullish(bar_index); + mConditions.isXAMAStartBearish = XAMAIsStartBearish(bar_index); + mConditions.isXAMAEndBullishByNeutural = XAMAIsEndBullishByNeutural(bar_index); + mConditions.isXAMAEndBearishByNeutural = XAMAIsEndBearishByNeutural(bar_index); + mConditions.isXAMAStartBullishAfterNeutural = XAMAIsStartBullishAfterNeutural(bar_index); + mConditions.isXAMAStartBearishAfterNeutural = XAMAIsStartBearishAfterNeutural(bar_index); + + // + // XLH ... + mConditions.isXLHHHIncreased = XLHIsHHIncreased(bar_index); + mConditions.isXLHHHDecreased = XLHIsHHDecreased(bar_index); + mConditions.isXLHLLIncreased = XLHIsLLIncreased(bar_index); + mConditions.isXLHLLDecreased = XLHIsLLDecreased(bar_index); + mConditions.isXLHLowAttachedLL = XLHIsLowAttachedLL(bar_index); + mConditions.isXLHHighAttachedHH = XLHIsHighAttachedHH(bar_index); + mConditions.isXLHHHSameInLength = XLHIsHHSameInLength(bar_index); + mConditions.isXLHLLSameInLength = XLHIsLLSameInLength(bar_index); + mConditions.isXLHPriceOverSignal = XLHIsPriceOverSignal(bar_index); + mConditions.isXLHPriceUnderSignal = XLHIsPriceUnderSignal(bar_index); + mConditions.isXLHPriceInSignalRange = XLHIsPriceInSignalRange(bar_index); + mConditions.isXLHPriceCrossedOverSignal = XLHIsPriceCrossedOverSignal(bar_index); + mConditions.isXLHPriceCrossedUnderSignal = XLHIsPriceCrossedUnderSignal(bar_index); + + // + // XTD ... + mConditions.isXTDSignalPeak = XTDIsSignalPeak(bar_index); + mConditions.isXTDSignalVale = XTDIsSignalVale(bar_index); + mConditions.isXTDBullishPeak = XTDIsBullishPeak(bar_index); + mConditions.isXTDBullishVale = XTDIsBullishVale(bar_index); + mConditions.isXTDBearishPeak = XTDIsBearishPeak(bar_index); + mConditions.isXTDBearishVale = XTDIsBearishVale(bar_index); + mConditions.isXTDBullOverBear = XTDIsBullOverBear(bar_index); + mConditions.isXTDBullUnderBear = XTDIsBullUnderBear(bar_index); + mConditions.isXTDSignalOverBear = XTDIsSignalOverBear(bar_index); + mConditions.isXTDSignalUnderBear = XTDIsSignalUnderBear(bar_index); + mConditions.isXTDBullCrossedOverBear = XTDIsBullCrossedOverBear(bar_index); + mConditions.isXTDBullCrossedUnderBear = XTDIsBullCrossedUnderBear(bar_index); + mConditions.isXTDSignalCrossedOverBear = XTDIsSignalCrossedOverBear(bar_index); + mConditions.isXTDSignalCrossedUnderBear = XTDIsSignalCrossedUnderBear(bar_index); + + // + // XFI ... + mConditions.isXFIPeak = XFIIsPeak(bar_index); + mConditions.isXFIVale = XFIIsVale(bar_index); + mConditions.isXFIOverZero = XFIIsOverZero(bar_index); + mConditions.isXFIUnderZero = XFIIsUnderZero(bar_index); + mConditions.isXFICrossedOverZero = XFIIsCrossedOverZero(bar_index); + mConditions.isXFICrossedUnderZero = XFIIsCrossedUnderZero(bar_index); + + // + // XTS ... + mConditions.isXTSAllSame = XTSIsAllSame(bar_index); + mConditions.isXTSCurrentMin = XTSIsCurrentMin(bar_index); + mConditions.isXTSCurrentMax = XTSIsCurrentMax(bar_index); + mConditions.isXTSCurrentOverFarest = XTSIsCurrentOverFarest(bar_index); + mConditions.isXTSCurrentOverNearest = XTSIsCurrentOverNearest(bar_index); + mConditions.isXTSCurrentOverMediest = XTSIsCurrentOverMediest(bar_index); + mConditions.isXTSCurrentUnderFarest = XTSIsCurrentUnderFarest(bar_index); + mConditions.isXTSCurrentUnderNearest = XTSIsCurrentUnderNearest(bar_index); + mConditions.isXTSCurrentUnderMediest = XTSIsCurrentUnderMediest(bar_index); + mConditions.isXTSCurrentCrossedOverFarest = XTSIsCurrentCrossedOverFarest(bar_index); + mConditions.isXTSCurrentCrossedOverNearest = XTSIsCurrentCrossedOverNearest(bar_index); + mConditions.isXTSCurrentCrossedOverMediest = XTSIsCurrentCrossedOverMediest(bar_index); + mConditions.isXTSCurrentCrossedUnderFarest = XTSIsCurrentCrossedUnderFarest(bar_index); + mConditions.isXTSCurrentCrossedUnderNearest = XTSIsCurrentCrossedUnderNearest(bar_index); + mConditions.isXTSCurrentCrossedUnderMediest = XTSIsCurrentCrossedUnderMediest(bar_index); + + // + // XRSI ... + mConditions.isXRSIPeak = XRSIIsPeak(bar_index); + mConditions.isXRSIVale = XRSIIsVale(bar_index); + mConditions.isXRSICrossedOverLongExit = XRSIIsCrossedOverLongExit(bar_index); + mConditions.isXRSICrossedOverLongEntry = XRSIIsCrossedOverLongEntry(bar_index); + mConditions.isXRSICrossedUnderShortExit = XRSIIsCrossedUnderShortExit(bar_index); + mConditions.isXRSICrossedUnderShortEntry = XRSIIsCrossedUnderShortEntry(bar_index); + + // + // XOBD ... + mConditions.isXOBDSwingLow = XOBDIsSwingLow(bar_index); + mConditions.isXOBDSwingHigh = XOBDIsSwingHigh(bar_index); + + // + // XCHLH ... + // + mConditions.isXCHLHSameHHs = XCHLHIsSameHHs(bar_index); + mConditions.isXCHLHSameLLs = XCHLHIsSameLLs(bar_index); + // + mConditions.isXCHLHSCMCHHSame = XCHLHIsMCSCHasSameHH(bar_index); + mConditions.isXCHLHSCMCLLSame = XCHLHIsMCSCHasSameLL(bar_index); + // + mConditions.isXCHLHSCLCHHSame = XCHLHIsLCSCHasSameHH(bar_index); + mConditions.isXCHLHSCLCLLSame = XCHLHIsLCSCHasSameLL(bar_index); + // + mConditions.isXCHLHMCLCHHSame = XCHLHIsLCMCHasSameHH(bar_index); + mConditions.isXCHLHMCLCLLSame = XCHLHIsLCMCHasSameLL(bar_index); + // + mConditions.isXCHLHMCOnTopOfLC = XCHLHIsMCOnTopOfLC(bar_index); + mConditions.isXCHLHMCInBottomOfLC = XCHLHIsMCInBottomOfLC(bar_index); + + // + // XCHMA ... + // + mConditions.isXCHMASCOverMax = XCHMAIsSCOverMax(bar_index); + mConditions.isXCHMASCOverMin = XCHMAIsSCOverMin(bar_index); + mConditions.isXCHMASCUnderMax = XCHMAIsSCUnderMax(bar_index); + mConditions.isXCHMASCUnderMin = XCHMAIsSCUnderMin(bar_index); + // + mConditions.isXCHMASCCrossedOverMax = XCHMAIsSCCrossedOverMax(bar_index); + mConditions.isXCHMASCCrossedUnderMax = XCHMAIsSCCrossedUnderMax(bar_index); + mConditions.isXCHMASCCrossedOverMin = XCHMAIsSCCrossedOverMin(bar_index); + mConditions.isXCHMASCCrossedUnderMin = XCHMAIsSCCrossedUnderMin(bar_index); + // + mConditions.isXCHMASCPeak = XCHMAIsSCPeak(bar_index); + mConditions.isXCHMASCVale = XCHMAIsSCVale(bar_index); + mConditions.isXCHMASCTrendsUp = XCHMAIsSCTrendsUp(bar_index); + mConditions.isXCHMASCTrendsDown = XCHMAIsSCTrendsDown(bar_index); + mConditions.isXCHMASCFastOverSlow = XCHMAIsSCFastOverSlow(bar_index); + mConditions.isXCHMASCFastUnderSlow = XCHMAIsSCFastUnderSlow(bar_index); + mConditions.isXCHMASCFastCrossedOverSlow = XCHMAIsSCFastCrossedOverSlow(bar_index); + mConditions.isXCHMASCFastCrossedUnderSlow = XCHMAIsSCFastCrossedUnderSlow(bar_index); + // + mConditions.isXCHMAMCPeak = XCHMAIsMCPeak(bar_index); + mConditions.isXCHMAMCVale = XCHMAIsMCVale(bar_index); + mConditions.isXCHMAMCTrendsUp = XCHMAIsMCTrendsUp(bar_index); + mConditions.isXCHMAMCTrendsDown = XCHMAIsMCTrendsDown(bar_index); + mConditions.isXCHMAMCFastOverSlow = XCHMAIsMCFastOverSlow(bar_index); + mConditions.isXCHMAMCFastUnderSlow = XCHMAIsMCFastUnderSlow(bar_index); + mConditions.isXCHMAMCFastCrossedOverSlow = XCHMAIsMCFastCrossedOverSlow(bar_index); + mConditions.isXCHMAMCFastCrossedUnderSlow = XCHMAIsMCFastCrossedUnderSlow(bar_index); + // + mConditions.isXCHMALCPeak = XCHMAIsLCPeak(bar_index); + mConditions.isXCHMALCVale = XCHMAIsLCVale(bar_index); + mConditions.isXCHMALCTrendsUp = XCHMAIsLCTrendsUp(bar_index); + mConditions.isXCHMALCTrendsDown = XCHMAIsLCTrendsDown(bar_index); + mConditions.isXCHMALCFastOverSlow = XCHMAIsLCFastOverSlow(bar_index); + mConditions.isXCHMALCFastUnderSlow = XCHMAIsLCFastUnderSlow(bar_index); + mConditions.isXCHMALCFastCrossedOverSlow = XCHMAIsLCFastCrossedOverSlow(bar_index); + mConditions.isXCHMALCFastCrossedUnderSlow = XCHMAIsLCFastCrossedUnderSlow(bar_index); + + // + return mConditions; + } + + // + // Access Last Readed Market Conditions ... + XMarketConditions GetLastMarketCondition() + { + // + XMarketConditions result = {}; + + // + result = mXConditions; + + // + return result; + } + + // + // Check Market Conditions is Ready for Long Signals or not ... + bool IsReadyForLong( + bool checkXCHMAMin = true, // Force Check XCHMA Min State + bool checkXCHMAMax = true, // Force Check XCHMA Max State + bool checkXCHMACycles = true, // Force Check XCHMA Cycles State + bool checkXCHMAPeaks = true, // Force Check XCHMA Peaks State + bool checkXCHMATrendPowers = true, // Force Check XCHMA Trend Powers + bool checkXOBD = true, // Force Check XOBD State + bool checkXTS = true // Force Check XTS State + ) + { + // + bool result = true; + + // + if (checkXCHMAMin) + { + // + result = + // + // XCHMA MIN ... + !( + // + (mXConditions.isXCHMASCOverMin || + mXConditions.isXCHMASCCrossedOverMin) && + (mXConditions.isXCHMASCUnderMin || + mXConditions.isXCHMASCCrossedUnderMin) + // + ); + } + + // + if (checkXCHMAMax && result) + { + // + result = + // + // XCHMA MAX ... + !( + // + (mXConditions.isXCHMASCOverMax || + mXConditions.isXCHMASCCrossedOverMax) && + (mXConditions.isXCHMASCUnderMax || + mXConditions.isXCHMASCCrossedUnderMax) + // + ) + // + ; + } + + // + if (checkXCHMACycles && result) + { + // + result = + // + // Check XCHMA Trend Bullish ... + ( + // + // All Cycles Bullish ... + ( + // + // SC ... + (mXConditions.isXCHMASCFastOverSlow || + mXConditions.isXCHMASCFastCrossedOverSlow) + // + && + // + // MC ... + (mXConditions.isXCHMAMCFastOverSlow || + mXConditions.isXCHMAMCFastCrossedOverSlow) + // + && + // + // LC ... + (mXConditions.isXCHMALCFastOverSlow || + mXConditions.isXCHMALCFastCrossedOverSlow) + // + ) + // + || + // + // Two Cycle Fully Bullish ... + ( + // + // SC and MC ... + ( + // + // SC ... + (mXConditions.isXCHMASCFastOverSlow || + mXConditions.isXCHMASCFastCrossedOverSlow) + // + && + // + // MC ... + (mXConditions.isXCHMAMCFastOverSlow || + mXConditions.isXCHMAMCFastCrossedOverSlow) + // + ) + // + || + // + // SC and LC ... + ( + // + // SC ... + (mXConditions.isXCHMASCFastOverSlow || + mXConditions.isXCHMASCFastCrossedOverSlow) + // + && + // + // LC ... + (mXConditions.isXCHMALCFastOverSlow || + mXConditions.isXCHMALCFastCrossedOverSlow) + // + ) + // + || + // + // MC and LC ... + ( + // + // MC ... + (mXConditions.isXCHMAMCFastOverSlow || + mXConditions.isXCHMAMCFastCrossedOverSlow) + // + && + // + // LC ... + (mXConditions.isXCHMALCFastOverSlow || + mXConditions.isXCHMALCFastCrossedOverSlow) + // + ) + // + ) + // + ) + // + ; + } + + // + if (checkXCHMAPeaks && result) + { + // + result = + // + // XCHMA Check Peaks ... + !( + // + // All Cycles Peak ... + (mXConditions.isXCHMASCPeak && + mXConditions.isXCHMAMCPeak && + mXConditions.isXCHMALCPeak) + // + || + // + ( + // + // SC MC ... + (mXConditions.isXCHMASCPeak && + mXConditions.isXCHMAMCPeak) + // + || + // + // SC LC ... + (mXConditions.isXCHMASCPeak && + mXConditions.isXCHMALCPeak) + // + || + // + // MC LC ... + (mXConditions.isXCHMAMCPeak && + mXConditions.isXCHMALCPeak) + // + ) + // + ) + // + ; + } + + // + if (checkXCHMATrendPowers && result) + { + // + result = + // + // XCHMA Check Trends Power ... + !( + // + // All Trends Down ... + (mXConditions.isXCHMASCTrendsDown && + mXConditions.isXCHMAMCTrendsDown && + mXConditions.isXCHMALCTrendsDown) + // + || + // + // Twisted pairs ... + ( + // + (mXConditions.isXCHMASCTrendsDown && + mXConditions.isXCHMAMCTrendsDown) + // + || + // + (mXConditions.isXCHMASCTrendsDown && + mXConditions.isXCHMALCTrendsDown) + // + || + // + (mXConditions.isXCHMAMCTrendsDown && + mXConditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + ; + } + + // + if (checkXOBD && result) + { + // + result = + // + // XOBD Check Swings ... + !mXConditions.isXOBDSwingLow + // + ; + } + + // + if (checkXTS && result) + { + result = + // + // XTS Check ... + !( + // + mXConditions.isXTSCurrentMin && + // + ( + // + // All Under ... + ( + (mXConditions.isXTSCurrentUnderNearest || + mXConditions.isXTSCurrentCrossedUnderNearest) && + (mXConditions.isXTSCurrentUnderMediest || + mXConditions.isXTSCurrentCrossedUnderMediest) && + (mXConditions.isXTSCurrentUnderFarest || + mXConditions.isXTSCurrentCrossedUnderFarest)) + // + || + // + // Pairs ... + ( + // + ((mXConditions.isXTSCurrentUnderNearest || + mXConditions.isXTSCurrentCrossedUnderNearest) && + (mXConditions.isXTSCurrentUnderMediest || + mXConditions.isXTSCurrentCrossedUnderMediest)) + // + || + // + ((mXConditions.isXTSCurrentUnderNearest || + mXConditions.isXTSCurrentCrossedUnderNearest) && + (mXConditions.isXTSCurrentUnderFarest || + mXConditions.isXTSCurrentCrossedUnderFarest)) + // + || + // + ((mXConditions.isXTSCurrentUnderMediest || + mXConditions.isXTSCurrentCrossedUnderMediest) && + (mXConditions.isXTSCurrentUnderFarest || + mXConditions.isXTSCurrentCrossedUnderFarest)) + // + ) + // + ) + // + ) + // + ; + } + + // + return result; + } + + // + // Check Market Conditions is Ready for Short Signals or not ... + bool IsReadyForShort( + bool checkXCHMAMin = true, // Force Check XCHMA Min State + bool checkXCHMAMax = true, // Force Check XCHMA Max State + bool checkXCHMACycles = true, // Force Check XCHMA Cycles State + bool checkXCHMAVales = true, // Force Check XCHMA Vales State + bool checkXCHMATrendPowers = true, // Force Check XCHMA Trend Powers + bool checkXOBD = true, // Force Check XOBD State + bool checkXTS = true // Force Check XTS State + ) + { + // + bool result = true; + + // + if (checkXCHMAMin) + { + // + result = + // + // XCHMA MIN ... + !( + // + (mXConditions.isXCHMASCOverMin || + mXConditions.isXCHMASCCrossedOverMin) && + (mXConditions.isXCHMASCUnderMin || + mXConditions.isXCHMASCCrossedUnderMin) + // + ); + } + + // + if (checkXCHMAMax && result) + { + // + result = + // + // XCHMA MAX ... + !( + // + (mXConditions.isXCHMASCOverMax || + mXConditions.isXCHMASCCrossedOverMax) && + (mXConditions.isXCHMASCUnderMax || + mXConditions.isXCHMASCCrossedUnderMax) + // + ) + // + ; + } + + // + if (checkXCHMACycles && result) + { + // + result = + // + // Check XCHMA Trend Bullish ... + ( + // + // All Cycles Bullish ... + ( + // + // SC ... + (mXConditions.isXCHMASCFastUnderSlow || + mXConditions.isXCHMASCFastCrossedUnderSlow) + // + && + // + // MC ... + (mXConditions.isXCHMAMCFastUnderSlow || + mXConditions.isXCHMAMCFastCrossedUnderSlow) + // + && + // + // LC ... + (mXConditions.isXCHMALCFastUnderSlow || + mXConditions.isXCHMALCFastCrossedUnderSlow) + // + ) + // + || + // + // Two Cycle Fully Bullish ... + ( + // + // SC and MC ... + ( + // + // SC ... + (mXConditions.isXCHMASCFastUnderSlow || + mXConditions.isXCHMASCFastCrossedOverSlow) + // + && + // + // MC ... + (mXConditions.isXCHMAMCFastUnderSlow || + mXConditions.isXCHMAMCFastCrossedOverSlow) + // + ) + // + || + // + // SC and LC ... + ( + // + // SC ... + (mXConditions.isXCHMASCFastUnderSlow || + mXConditions.isXCHMASCFastCrossedUnderSlow) + // + && + // + // LC ... + (mXConditions.isXCHMALCFastUnderSlow || + mXConditions.isXCHMALCFastCrossedUnderSlow) + // + ) + // + || + // + // MC and LC ... + ( + // + // MC ... + (mXConditions.isXCHMAMCFastUnderSlow || + mXConditions.isXCHMAMCFastCrossedOverSlow) + // + && + // + // LC ... + (mXConditions.isXCHMALCFastUnderSlow || + mXConditions.isXCHMALCFastCrossedOverSlow) + // + ) + // + ) + // + ) + // + ; + } + + // + if (checkXCHMAVales && result) + { + // + result = + // + // XCHMA Check Vales ... + !( + // + // All Cycles Vale ... + (mXConditions.isXCHMASCVale && + mXConditions.isXCHMAMCVale && + mXConditions.isXCHMALCVale) + // + || + // + ( + // + // SC MC ... + (mXConditions.isXCHMASCVale && + mXConditions.isXCHMAMCVale) + // + || + // + // SC LC ... + (mXConditions.isXCHMASCVale && + mXConditions.isXCHMALCVale) + // + || + // + // MC LC ... + (mXConditions.isXCHMAMCVale && + mXConditions.isXCHMALCVale) + // + ) + // + ) + // + ; + } + + // + if (checkXCHMATrendPowers && result) + { + // + result = + // + // XCHMA Check Trends Power ... + !( + // + // All Trends Down ... + (mXConditions.isXCHMASCTrendsDown && + mXConditions.isXCHMAMCTrendsDown && + mXConditions.isXCHMALCTrendsDown) + // + || + // + // Twisted pairs ... + ( + // + (mXConditions.isXCHMASCTrendsDown && + mXConditions.isXCHMAMCTrendsDown) + // + || + // + (mXConditions.isXCHMASCTrendsDown && + mXConditions.isXCHMALCTrendsDown) + // + || + // + (mXConditions.isXCHMAMCTrendsDown && + mXConditions.isXCHMALCTrendsDown) + // + ) + // + ) + // + ; + } + + // + if (checkXOBD && result) + { + // + result = + // + // XOBD Check Swings ... + !mXConditions.isXOBDSwingHigh + // + ; + } + + // + if (checkXTS && result) + { + // + result = + // + // XTS Check ... + !( + // + mXConditions.isXTSCurrentMax && + // + ( + // + // All Over ... + ( + (mXConditions.isXTSCurrentOverNearest || + mXConditions.isXTSCurrentCrossedOverNearest) && + (mXConditions.isXTSCurrentOverMediest || + mXConditions.isXTSCurrentCrossedOverMediest) && + (mXConditions.isXTSCurrentOverFarest || + mXConditions.isXTSCurrentCrossedOverFarest)) + // + || + // + // Pairs ... + ( + // + ((mXConditions.isXTSCurrentOverNearest || + mXConditions.isXTSCurrentCrossedOverNearest) && + (mXConditions.isXTSCurrentOverMediest || + mXConditions.isXTSCurrentCrossedOverMediest)) + // + || + // + ((mXConditions.isXTSCurrentOverNearest || + mXConditions.isXTSCurrentCrossedOverNearest) && + (mXConditions.isXTSCurrentOverFarest || + mXConditions.isXTSCurrentCrossedOverFarest)) + // + || + // + ((mXConditions.isXTSCurrentOverMediest || + mXConditions.isXTSCurrentCrossedOverMediest) && + (mXConditions.isXTSCurrentOverFarest || + mXConditions.isXTSCurrentCrossedOverFarest)) + // + ) + // + ) + // + ) + // + ; + } + + // + return result; + } + + // + // Converts Market Conditions to Specific String Representation ... + string GenerateConditionsString( + XMarketConditions &condition, // Specify Conditiond + string separator = "\n", // Specify Separator + bool ignoreFalses = true // Ignore False Conditions + ) + { + // + XMarketConditions mConditions = {}; + + // + mConditions = condition; + + // + string result = "\n"; + + // + // XOBD ... + result += + "| XOBD |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXOBDSwingLow)) + { + result += "isXOBDSwingLow: " + (string)mConditions.isXOBDSwingLow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXOBDSwingHigh)) + { + result += "isXOBDSwingHigh: " + (string)mConditions.isXOBDSwingHigh + separator; + } + + // + // Separator ... + result += separator; + + // + // XTM ... + result += + "| XTM |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMPeak)) + { + result += "isXTMPeak: " + (string)mConditions.isXTMPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMVale)) + { + result += "isXTMVale: " + (string)mConditions.isXTMVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMStartBullish)) + { + result += "isXTMStartBullish: " + (string)mConditions.isXTMStartBullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMStartBullishAfterNeutural)) + { + result += "isXTMStartBullishAfterNeutural: " + (string)mConditions.isXTMStartBullishAfterNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMBullish)) + { + result += "isXTMBullish: " + (string)mConditions.isXTMBullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMEndBullish)) + { + result += "isXTMEndBullish: " + (string)mConditions.isXTMEndBullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMEndBullishByNeutural)) + { + result += "isXTMEndBullishByNeutural: " + (string)mConditions.isXTMEndBullishByNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMStartBearish)) + { + result += "isXTMStartBearish: " + (string)mConditions.isXTMStartBearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMStartBearishAfterNeutural)) + { + result += "isXTMStartBearishAfterNeutural: " + (string)mConditions.isXTMStartBearishAfterNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMBearish)) + { + result += "isXTMBearish: " + (string)mConditions.isXTMBearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMEndBearish)) + { + result += "isXTMEndBearish: " + (string)mConditions.isXTMEndBearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMEndBearishByNeutural)) + { + result += "isXTMEndBearishByNeutural: " + (string)mConditions.isXTMEndBearishByNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTMNeutural)) + { + result += "isXTMNeutural: " + (string)mConditions.isXTMNeutural + separator; + } + + // + // Separator ... + result += separator; + + // + // XAMA ... + result += + "| XAMA |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAPeak)) + { + result += "isXAMAPeak: " + (string)mConditions.isXAMAPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAVale)) + { + result += "isXAMAVale: " + (string)mConditions.isXAMAVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAStartBullish)) + { + result += "isXAMAStartBullish: " + (string)mConditions.isXAMAStartBullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAStartBullishAfterNeutural)) + { + result += "isXAMAStartBullishAfterNeutural: " + (string)mConditions.isXAMAStartBullishAfterNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMABullish)) + { + result += "isXAMABullish: " + (string)mConditions.isXAMABullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAEndBullish)) + { + result += "isXAMAEndBullish: " + (string)mConditions.isXAMAEndBullish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAEndBullishByNeutural)) + { + result += "isXAMAEndBullishByNeutural: " + (string)mConditions.isXAMAEndBullishByNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAStartBearish)) + { + result += "isXAMAStartBearish: " + (string)mConditions.isXAMAStartBearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAStartBearishAfterNeutural)) + { + result += "isXAMAStartBearishAfterNeutural: " + (string)mConditions.isXAMAStartBearishAfterNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMABearish)) + { + result += "isXAMABearish: " + (string)mConditions.isXAMABearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAEndBearish)) + { + result += "isXAMAEndBearish: " + (string)mConditions.isXAMAEndBearish + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMAEndBearishByNeutural)) + { + result += "isXAMAEndBearishByNeutural: " + (string)mConditions.isXAMAEndBearishByNeutural + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXAMANeutural)) + { + result += "isXAMANeutural: " + (string)mConditions.isXAMANeutural + separator; + } + + // + // Separator ... + result += separator; + + // + // XTD ... + result += + "| XTD |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalPeak)) + { + result += "isXTDSignalPeak: " + (string)mConditions.isXTDSignalPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalVale)) + { + result += "isXTDSignalVale: " + (string)mConditions.isXTDSignalVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullishPeak)) + { + result += "isXTDBullishPeak: " + (string)mConditions.isXTDBullishPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullishVale)) + { + result += "isXTDBullishVale: " + (string)mConditions.isXTDBullishVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBearishPeak)) + { + result += "isXTDBearishPeak: " + (string)mConditions.isXTDBearishPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBearishVale)) + { + result += "isXTDBearishVale: " + (string)mConditions.isXTDBearishVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullOverBear)) + { + result += "isXTDBullOverBear: " + (string)mConditions.isXTDBullOverBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullUnderBear)) + { + result += "isXTDBullUnderBear: " + (string)mConditions.isXTDBullUnderBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalOverBear)) + { + result += "isXTDSignalOverBear: " + (string)mConditions.isXTDSignalOverBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalUnderBear)) + { + result += "isXTDSignalUnderBear: " + (string)mConditions.isXTDSignalUnderBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullCrossedOverBear)) + { + result += "isXTDBullCrossedOverBear: " + (string)mConditions.isXTDBullCrossedOverBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDBullCrossedUnderBear)) + { + result += "isXTDBullCrossedUnderBear: " + (string)mConditions.isXTDBullCrossedUnderBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalCrossedOverBear)) + { + result += "isXTDSignalCrossedOverBear: " + (string)mConditions.isXTDSignalCrossedOverBear + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTDSignalCrossedUnderBear)) + { + result += "isXTDSignalCrossedUnderBear: " + (string)mConditions.isXTDSignalCrossedUnderBear + separator; + } + + // + // Separator ... + result += separator; + + // + // XFI ... + result += + "| XFI |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFIPeak)) + { + result += "isXFIPeak: " + (string)mConditions.isXFIPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFIVale)) + { + result += "isXFIVale: " + (string)mConditions.isXFIVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFIOverZero)) + { + result += "isXFIOverZero: " + (string)mConditions.isXFIOverZero + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFIUnderZero)) + { + result += "isXFIUnderZero: " + (string)mConditions.isXFIUnderZero + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFICrossedOverZero)) + { + result += "isXFICrossedOverZero: " + (string)mConditions.isXFICrossedOverZero + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXFICrossedUnderZero)) + { + result += "isXFICrossedUnderZero: " + (string)mConditions.isXFICrossedUnderZero + separator; + } + + // + // Separator ... + result += separator; + + // + // XTS ... + result += + "| XTS |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSAllSame)) + { + result += "isXTSAllSame: " + (string)mConditions.isXTSAllSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentMin)) + { + result += "isXTSCurrentMin: " + (string)mConditions.isXTSCurrentMin + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentMax)) + { + result += "isXTSCurrentMax: " + (string)mConditions.isXTSCurrentMax + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentOverFarest)) + { + result += "isXTSCurrentOverFarest: " + (string)mConditions.isXTSCurrentOverFarest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentOverNearest)) + { + result += "isXTSCurrentOverNearest: " + (string)mConditions.isXTSCurrentOverNearest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentOverMediest)) + { + result += "isXTSCurrentOverMediest: " + (string)mConditions.isXTSCurrentOverMediest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentUnderFarest)) + { + result += "isXTSCurrentUnderFarest: " + (string)mConditions.isXTSCurrentUnderFarest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentUnderNearest)) + { + result += "isXTSCurrentUnderNearest: " + (string)mConditions.isXTSCurrentUnderNearest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentUnderMediest)) + { + result += "isXTSCurrentUnderMediest: " + (string)mConditions.isXTSCurrentUnderMediest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedOverFarest)) + { + result += "isXTSCurrentCrossedOverFarest: " + (string)mConditions.isXTSCurrentCrossedOverFarest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedOverNearest)) + { + result += "isXTSCurrentCrossedOverNearest: " + (string)mConditions.isXTSCurrentCrossedOverNearest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedOverMediest)) + { + result += "isXTSCurrentCrossedOverMediest: " + (string)mConditions.isXTSCurrentCrossedOverMediest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedUnderFarest)) + { + result += "isXTSCurrentCrossedUnderFarest: " + (string)mConditions.isXTSCurrentCrossedUnderFarest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedUnderNearest)) + { + result += "isXTSCurrentCrossedUnderNearest: " + (string)mConditions.isXTSCurrentCrossedUnderNearest + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXTSCurrentCrossedUnderMediest)) + { + result += "isXTSCurrentCrossedUnderMediest: " + (string)mConditions.isXTSCurrentCrossedUnderMediest + separator; + } + + // + // Separator ... + result += separator; + + // + // XLH ... + result += + "| XLH |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHHHIncreased)) + { + result += "isXLHHHIncreased: " + (string)mConditions.isXLHHHIncreased + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHHHDecreased)) + { + result += "isXLHHHDecreased: " + (string)mConditions.isXLHHHDecreased + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHLLIncreased)) + { + result += "isXLHLLIncreased: " + (string)mConditions.isXLHLLIncreased + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHLLDecreased)) + { + result += "isXLHLLDecreased: " + (string)mConditions.isXLHLLDecreased + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHHighAttachedHH)) + { + result += "isXLHHighAttachedHH: " + (string)mConditions.isXLHHighAttachedHH + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHLowAttachedLL)) + { + result += "isXLHLowAttachedLL: " + (string)mConditions.isXLHLowAttachedLL + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHHHSameInLength)) + { + result += "isXLHHHSameInLength: " + (string)mConditions.isXLHHHSameInLength + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHLLSameInLength)) + { + result += "isXLHLLSameInLength: " + (string)mConditions.isXLHLLSameInLength + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHPriceCrossedOverSignal)) + { + result += "isXLHPriceCrossedOverSignal: " + (string)mConditions.isXLHPriceCrossedOverSignal + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHPriceOverSignal)) + { + result += "isXLHPriceOverSignal: " + (string)mConditions.isXLHPriceOverSignal + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHPriceCrossedUnderSignal)) + { + result += "isXLHPriceCrossedUnderSignal: " + (string)mConditions.isXLHPriceCrossedUnderSignal + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHPriceUnderSignal)) + { + result += "isXLHPriceUnderSignal: " + (string)mConditions.isXLHPriceUnderSignal + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXLHPriceInSignalRange)) + { + result += "isXLHPriceInSignalRange: " + (string)mConditions.isXLHPriceInSignalRange + separator; + } + + // + // Separator ... + result += separator; + + // + // XRSI ... + result += + "| XRSI |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSIPeak)) + { + result += "isXRSIPeak: " + (string)mConditions.isXRSIPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSIVale)) + { + result += "isXRSIVale: " + (string)mConditions.isXRSIVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSICrossedOverLongExit)) + { + result += "isXRSICrossedOverLongExit: " + (string)mConditions.isXRSICrossedOverLongExit + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSICrossedOverLongEntry)) + { + result += "isXRSICrossedOverLongEntry: " + (string)mConditions.isXRSICrossedOverLongEntry + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSICrossedUnderShortExit)) + { + result += "isXRSICrossedUnderShortExit: " + (string)mConditions.isXRSICrossedUnderShortExit + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXRSICrossedUnderShortEntry)) + { + result += "isXRSICrossedUnderShortEntry: " + (string)mConditions.isXRSICrossedUnderShortEntry + separator; + } + + // + // Separator ... + result += separator; + + // + // XCHLH ... + result += + "| XCHLH |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSameHHs)) + { + result += "isXCHLHSameHHs: " + (string)mConditions.isXCHLHSameHHs + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSameLLs)) + { + result += "isXCHLHSameLLs: " + (string)mConditions.isXCHLHSameLLs + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSCMCHHSame)) + { + result += "isXCHLHSCMCHHSame: " + (string)mConditions.isXCHLHSCMCHHSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSCMCLLSame)) + { + result += "isXCHLHSCMCLLSame: " + (string)mConditions.isXCHLHSCMCLLSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSCLCHHSame)) + { + result += "isXCHLHSCLCHHSame: " + (string)mConditions.isXCHLHSCLCHHSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHSCLCLLSame)) + { + result += "isXCHLHSCLCLLSame: " + (string)mConditions.isXCHLHSCLCLLSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHMCLCHHSame)) + { + result += "isXCHLHMCLCHHSame: " + (string)mConditions.isXCHLHMCLCHHSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHMCLCLLSame)) + { + result += "isXCHLHMCLCLLSame: " + (string)mConditions.isXCHLHMCLCLLSame + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHMCOnTopOfLC)) + { + result += "isXCHLHMCOnTopOfLC: " + (string)mConditions.isXCHLHMCOnTopOfLC + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHLHMCInBottomOfLC)) + { + result += "isXCHLHMCInBottomOfLC: " + (string)mConditions.isXCHLHMCInBottomOfLC + separator; + } + + // + // Separator ... + result += separator; + + // + // XCHMA ... + result += + "| XCHMA |" + separator; + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCOverMax)) + { + result += "isXCHMASCOverMax: " + (string)mConditions.isXCHMASCOverMax + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCOverMin)) + { + result += "isXCHMASCOverMin: " + (string)mConditions.isXCHMASCOverMin + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCUnderMax)) + { + result += "isXCHMASCUnderMax: " + (string)mConditions.isXCHMASCUnderMax + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCUnderMin)) + { + result += "isXCHMASCUnderMin: " + (string)mConditions.isXCHMASCUnderMin + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCCrossedOverMax)) + { + result += "isXCHMASCCrossedOverMax: " + (string)mConditions.isXCHMASCCrossedOverMax + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCCrossedUnderMax)) + { + result += "isXCHMASCCrossedUnderMax: " + (string)mConditions.isXCHMASCCrossedUnderMax + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCCrossedOverMin)) + { + result += "isXCHMASCCrossedOverMin: " + (string)mConditions.isXCHMASCCrossedOverMin + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCCrossedUnderMin)) + { + result += "isXCHMASCCrossedUnderMin: " + (string)mConditions.isXCHMASCCrossedUnderMin + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCPeak)) + { + result += "isXCHMASCPeak: " + (string)mConditions.isXCHMASCPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCVale)) + { + result += "isXCHMASCVale: " + (string)mConditions.isXCHMASCVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCTrendsUp)) + { + result += "isXCHMASCTrendsUp: " + (string)mConditions.isXCHMASCTrendsUp + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCTrendsDown)) + { + result += "isXCHMASCTrendsDown: " + (string)mConditions.isXCHMASCTrendsDown + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCFastOverSlow)) + { + result += "isXCHMASCFastOverSlow: " + (string)mConditions.isXCHMASCFastOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCFastUnderSlow)) + { + result += "isXCHMASCFastUnderSlow: " + (string)mConditions.isXCHMASCFastUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCFastCrossedOverSlow)) + { + result += "isXCHMASCFastCrossedOverSlow: " + (string)mConditions.isXCHMASCFastCrossedOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMASCFastCrossedUnderSlow)) + { + result += "isXCHMASCFastCrossedUnderSlow: " + (string)mConditions.isXCHMASCFastCrossedUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCPeak)) + { + result += "isXCHMAMCPeak: " + (string)mConditions.isXCHMAMCPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCVale)) + { + result += "isXCHMAMCVale: " + (string)mConditions.isXCHMAMCVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCTrendsUp)) + { + result += "isXCHMAMCTrendsUp: " + (string)mConditions.isXCHMAMCTrendsUp + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCTrendsDown)) + { + result += "isXCHMAMCTrendsDown: " + (string)mConditions.isXCHMAMCTrendsDown + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCFastOverSlow)) + { + result += "isXCHMAMCFastOverSlow: " + (string)mConditions.isXCHMAMCFastOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCFastUnderSlow)) + { + result += "isXCHMAMCFastUnderSlow: " + (string)mConditions.isXCHMAMCFastUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCFastCrossedOverSlow)) + { + result += "isXCHMAMCFastCrossedOverSlow: " + (string)mConditions.isXCHMAMCFastCrossedOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMAMCFastCrossedUnderSlow)) + { + result += "isXCHMAMCFastCrossedUnderSlow: " + (string)mConditions.isXCHMAMCFastCrossedUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCPeak)) + { + result += "isXCHMALCPeak: " + (string)mConditions.isXCHMALCPeak + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCVale)) + { + result += "isXCHMALCVale: " + (string)mConditions.isXCHMALCVale + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCTrendsUp)) + { + result += "isXCHMALCTrendsUp: " + (string)mConditions.isXCHMALCTrendsUp + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCTrendsDown)) + { + result += "isXCHMALCTrendsDown: " + (string)mConditions.isXCHMALCTrendsDown + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCFastOverSlow)) + { + result += "isXCHMALCFastOverSlow: " + (string)mConditions.isXCHMALCFastOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCFastUnderSlow)) + { + result += "isXCHMALCFastUnderSlow: " + (string)mConditions.isXCHMALCFastUnderSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCFastCrossedOverSlow)) + { + result += "isXCHMALCFastCrossedOverSlow: " + (string)mConditions.isXCHMALCFastCrossedOverSlow + separator; + } + + // + if ( + !ignoreFalses || + (ignoreFalses && mConditions.isXCHMALCFastCrossedUnderSlow)) + { + result += "isXCHMALCFastCrossedUnderSlow: " + (string)mConditions.isXCHMALCFastCrossedUnderSlow + separator; + } + + // + // Separator ... + result += separator; + + // + return result; + } + + // + // END Common Functions ... + // + + // + // START Actions Based On Signallers ... + // + + // + // START XTD Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXTDignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXTDEnableSignaller) + { + return result; + } + + // + result = true; + mXTDEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXTDSignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXTDEnableSignaller) + { + return result; + } + + // + result = true; + mXTDEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXTDLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTDEnableSignaller || + mXTDAllowLongSignals) + { + return result; + } + + // + result = true; + mXTDAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXTDLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTDEnableSignaller || + !mXTDAllowLongSignals) + { + return result; + } + + // + result = true; + mXTDAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXTDShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTDEnableSignaller || + mXTDAllowShortSignals) + { + return result; + } + + // + result = true; + mXTDAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXTDShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTDEnableSignaller || + !mXTDAllowShortSignals) + { + return result; + } + + // + result = true; + mXTDAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XTDHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTDEnableSignaller || + !mXTDAllowLongSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + mXConditions.isXTDSignalCrossedOverBear + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong() + // + ) + // + ; + + // + return result; + } + + // + // Check Market Base Conditions for Short Signals ... + bool XTDHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTDEnableSignaller || + !mXTDAllowShortSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + mXConditions.isXTDSignalCrossedUnderBear + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForShort() + // + ) + // + ; + + // + return result; + } + + // + // END XTD Signaller ... + // + + // + // START XTAM Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXTAMignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXTAMEnableSignaller) + { + return result; + } + + // + result = true; + mXTAMEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXTAMSignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXTAMEnableSignaller) + { + return result; + } + + // + result = true; + mXTAMEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXTAMLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTAMEnableSignaller || + mXTAMAllowLongSignals) + { + return result; + } + + // + result = true; + mXTAMAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXTAMLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTAMEnableSignaller || + !mXTAMAllowLongSignals) + { + return result; + } + + // + result = true; + mXTAMAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXTAMShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTAMEnableSignaller || + mXTAMAllowShortSignals) + { + return result; + } + + // + result = true; + mXTAMAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXTAMShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTAMEnableSignaller || + !mXTAMAllowShortSignals) + { + return result; + } + + // + result = true; + mXTAMAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XTAMHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTAMEnableSignaller || + !mXTAMAllowLongSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + (xAMAMaBuffer[1] > xTMMaBuffer[1] && + xAMAMaBuffer[2] > xTMMaBuffer[2]) + // + && + // + !(xAMAMaBuffer[2] > xTMMaBuffer[2] && + xAMAMaBuffer[3] > xTMMaBuffer[3]) + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong() + // + ) + // + ; + + // + return result; + } + + // + // Check Market Base Conditions for Short Signals ... + bool XTAMHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTAMEnableSignaller || + !mXTAMAllowShortSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + (xAMAMaBuffer[1] < xTMMaBuffer[1] && + xAMAMaBuffer[2] < xTMMaBuffer[2]) + // + && + // + !(xAMAMaBuffer[2] < xTMMaBuffer[2] && + xAMAMaBuffer[3] < xTMMaBuffer[3]) + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForShort() + // + ) + // + ; + + // + return result; + } + + // + // END XTAM Signaller ... + // + + // + // START XSI Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXSIignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXSIEnableSignaller) + { + return result; + } + + // + result = true; + mXSIEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXSISignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXSIEnableSignaller) + { + return result; + } + + // + result = true; + mXSIEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXSILongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSIEnableSignaller || + mXSIAllowLongSignals) + { + return result; + } + + // + result = true; + mXSIAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXSILongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSIEnableSignaller || + !mXSIAllowLongSignals) + { + return result; + } + + // + result = true; + mXSIAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXSIShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSIEnableSignaller || + mXSIAllowShortSignals) + { + return result; + } + + // + result = true; + mXSIAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXSIShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSIEnableSignaller || + !mXSIAllowShortSignals) + { + return result; + } + + // + result = true; + mXSIAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XSIHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSIEnableSignaller || + !mXSIAllowLongSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + mXConditions.isXRSICrossedOverLongEntry && + xRSIBuffer[3] < xRSILongEntryValue + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong( + true, // XCHMA Min + true, // XCHMA Max + true, // XCHMA Cycles + true, // XCHMA Peaks + false, // XCHMA Trend Powers + true, // XOBD + true // XTS + ) + // + ) + // + ; + + // + return result; + } + + // + // Check Market Base Conditions for Short Signals ... + bool XSIHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXSIEnableSignaller || + !mXSIAllowShortSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + mXConditions.isXRSICrossedUnderShortEntry && + xRSIBuffer[3] > xRSIShortEntryValue + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForShort( + true, // XCHMA Min + true, // XCHMA Max + true, // XCHMA Cycles + true, // XCHMA Peaks + false, // XCHMA Trend Powers + true, // XOBD + true // XTS + ) + // + ) + // + ; + + // + return result; + } + + // + // END XSI Signaller ... + // + + // + // START XTSFI Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXTSFIignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXTSFIEnableSignaller) + { + return result; + } + + // + result = true; + mXTSFIEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXTSFISignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXTSFIEnableSignaller) + { + return result; + } + + // + result = true; + mXTSFIEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXTSFILongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTSFIEnableSignaller || + mXTSFIAllowLongSignals) + { + return result; + } + + // + result = true; + mXTSFIAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXTSFILongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTSFIEnableSignaller || + !mXTSFIAllowLongSignals) + { + return result; + } + + // + result = true; + mXTSFIAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXTSFIShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTSFIEnableSignaller || + mXTSFIAllowShortSignals) + { + return result; + } + + // + result = true; + mXTSFIAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXTSFIShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTSFIEnableSignaller || + !mXTSFIAllowShortSignals) + { + return result; + } + + // + result = true; + mXTSFIAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XTSFIHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTSFIEnableSignaller || + !mXTSFIAllowLongSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + XTSGetMinValue(1) == xTSFarestBuffer[1] && + (mXConditions.isXTSCurrentOverFarest || + mXConditions.isXTSCurrentCrossedOverFarest) && + (xTSCurrentBuffer[1] < xTSNearestBuffer[1] || + xTSCurrentBuffer[1] < xTSMediestBuffer[1]) && + !(mXConditions.isXTSCurrentUnderNearest || + mXConditions.isXTSCurrentCrossedUnderNearest) + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong() + // + ) + // + ; + + // + return result; + } + + // + // Check Market Base Conditions for Short Signals ... + bool XTSFIHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXTSFIEnableSignaller || + !mXTSFIAllowShortSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + XTSGetMaxValue(1) == xTSFarestBuffer[1] && + (mXConditions.isXTSCurrentUnderFarest || + mXConditions.isXTSCurrentCrossedUnderFarest) && + (xTSCurrentBuffer[1] > xTSNearestBuffer[1] || + xTSCurrentBuffer[1] > xTSMediestBuffer[1]) && + !(mXConditions.isXTSCurrentOverNearest || + mXConditions.isXTSCurrentCrossedOverNearest) + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForShort() + // + ) + // + ; + + // + return result; + } + + // + // END XTSFI Signaller ... + // + + // + // START XOBDLH Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXOBDLHignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXOBDLHEnableSignaller) + { + return result; + } + + // + result = true; + mXOBDLHEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXOBDLHSignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXOBDLHEnableSignaller) + { + return result; + } + + // + result = true; + mXOBDLHEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXOBDLHLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXOBDLHEnableSignaller || + mXOBDLHAllowLongSignals) + { + return result; + } + + // + result = true; + mXOBDLHAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXOBDLHLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXOBDLHEnableSignaller || + !mXOBDLHAllowLongSignals) + { + return result; + } + + // + result = true; + mXOBDLHAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXOBDLHShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXOBDLHEnableSignaller || + mXOBDLHAllowShortSignals) + { + return result; + } + + // + result = true; + mXOBDLHAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXOBDLHShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXOBDLHEnableSignaller || + !mXOBDLHAllowShortSignals) + { + return result; + } + + // + result = true; + mXOBDLHAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XOBDLHHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXOBDLHEnableSignaller || + !mXOBDLHAllowLongSignals) + { + return result; + } + + // + XMarketConditions xConditions2 = GenerateMarketConditions(2); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + xConditions2.isXOBDSwingLow && + xConditions2.isXLHLowAttachedLL && + xLHLLBuffer[1] >= xLHLLBuffer[2] + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong( + true, // XCHMA Min + true, // XCHMA Max + false, // XCHMA Cycles + false, // XCHMA Peaks + false, // XCHMA Trend Powers + false, // XOBD + false // XTS + ) + // + ) + // + ; + + // + return result; + } + + // + // Check Market Base Conditions for Short Signals ... + bool XOBDLHHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXOBDLHEnableSignaller || + !mXOBDLHAllowShortSignals) + { + return result; + } + + // + XMarketConditions xConditions2 = GenerateMarketConditions(2); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + xConditions2.isXOBDSwingHigh && + xConditions2.isXLHHighAttachedHH && + xLHHHBuffer[1] <= xLHHHBuffer[2] + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForShort( + true, // XCHMA Min + true, // XCHMA Max + false, // XCHMA Cycles + false, // XCHMA Peaks + false, // XCHMA Trend Powers + false, // XOBD + false // XTS + ) + // + ) + // + ; + + // + return result; + } + + // + // END XOBDLH Signaller ... + // + + // + // START XCHMACC Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXCHMACCignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXCHMACCEnableSignaller) + { + return result; + } + + // + result = true; + mXCHMACCEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXCHMACCSignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXCHMACCEnableSignaller) + { + return result; + } + + // + result = true; + mXCHMACCEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXCHMACCLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMACCEnableSignaller || + mXCHMACCAllowLongSignals) + { + return result; + } + + // + result = true; + mXCHMACCAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXCHMACCLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMACCEnableSignaller || + !mXCHMACCAllowLongSignals) + { + return result; + } + + // + result = true; + mXCHMACCAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXCHMACCShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMACCEnableSignaller || + mXCHMACCAllowShortSignals) + { + return result; + } + + // + result = true; + mXCHMACCAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXCHMACCShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMACCEnableSignaller || + !mXCHMACCAllowShortSignals) + { + return result; + } + + // + result = true; + mXCHMACCAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XCHMACCHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMACCEnableSignaller || + !mXCHMACCAllowLongSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + xCHMAScFastBuffer[1] > xCHMAScSlowBuffer[1] && + xCHMAMcFastBuffer[1] > xCHMAMcSlowBuffer[1] && + xCHMALcFastBuffer[1] > xCHMALcSlowBuffer[1] && + // + xCHMAScFastBuffer[2] > xCHMAScSlowBuffer[2] && + xCHMAMcFastBuffer[2] > xCHMAMcSlowBuffer[2] && + xCHMALcFastBuffer[2] > xCHMALcSlowBuffer[2] && + // + !( + // + xCHMAScFastBuffer[3] > xCHMAScSlowBuffer[3] && + xCHMAMcFastBuffer[3] > xCHMAMcSlowBuffer[3] && + xCHMALcFastBuffer[3] > xCHMALcSlowBuffer[3] + // + ) + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong() + // + ) + // + ; + + // + return result; + } + + // + // Check Market Base Conditions for Short Signals ... + bool XCHMACCHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMACCEnableSignaller || + !mXCHMACCAllowShortSignals) + { + return result; + } + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + xCHMAScFastBuffer[1] < xCHMAScSlowBuffer[1] && + xCHMAMcFastBuffer[1] < xCHMAMcSlowBuffer[1] && + xCHMALcFastBuffer[1] < xCHMALcSlowBuffer[1] && + // + xCHMAScFastBuffer[2] < xCHMAScSlowBuffer[2] && + xCHMAMcFastBuffer[2] < xCHMAMcSlowBuffer[2] && + xCHMALcFastBuffer[2] < xCHMALcSlowBuffer[2] && + // + !( + // + xCHMAScFastBuffer[3] < xCHMAScSlowBuffer[3] && + xCHMAMcFastBuffer[3] < xCHMAMcSlowBuffer[3] && + xCHMALcFastBuffer[3] < xCHMALcSlowBuffer[3] + // + ) + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForShort() + // + ) + // + ; + + // + return result; + } + + // + // END XCHMACC Signaller ... + // + + // + // START XCHMAMX Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXCHMAMXignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXCHMAMXEnableSignaller) + { + return result; + } + + // + result = true; + mXCHMAMXEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXCHMAMXSignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXCHMAMXEnableSignaller) + { + return result; + } + + // + result = true; + mXCHMAMXEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXCHMAMXLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMXEnableSignaller || + mXCHMAMXAllowLongSignals) + { + return result; + } + + // + result = true; + mXCHMAMXAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXCHMAMXLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMXEnableSignaller || + !mXCHMAMXAllowLongSignals) + { + return result; + } + + // + result = true; + mXCHMAMXAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXCHMAMXShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMXEnableSignaller || + mXCHMAMXAllowShortSignals) + { + return result; + } + + // + result = true; + mXCHMAMXAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXCHMAMXShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMXEnableSignaller || + !mXCHMAMXAllowShortSignals) + { + return result; + } + + // + result = true; + mXCHMAMXAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XCHMAMXHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMXEnableSignaller || + !mXCHMAMXAllowLongSignals) + { + return result; + } + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double xCHMANonSCMax2 = XCHMAGetCyclesMaxValue(2, cycles); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + mXConditions.isXCHMASCCrossedOverMax && + xCHMAScFastBuffer[2] < xCHMANonSCMax2 && + xCHMAScSlowBuffer[2] < xCHMANonSCMax2 && + MathAbs(xCHMANonSCMax2 - xCHMAScFastBuffer[2]) > MathAbs(xCHMAScFastBuffer[2] - xCHMAScSlowBuffer[2]) && + MathAbs(xCHMANonSCMax2 - xCHMAScSlowBuffer[2]) > MathAbs(xCHMAScFastBuffer[2] - xCHMAScSlowBuffer[2]) + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong( + true, // XCHMA Min + true, // XCHMA Max + false, // XCHMA Cycles + false, // XCHMA Peaks + false, // XCHMA Trend Powers + true, // XOBD + true // XTS + ) + // + ) + // + ; + + // + return result; + } + + // + // Check Market Base Conditions for Short Signals ... + bool XCHMAMXHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMXEnableSignaller || + !mXCHMAMXAllowShortSignals) + { + return result; + } + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double xCHMANonSCMax2 = XCHMAGetCyclesMaxValue(2, cycles); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + mXConditions.isXCHMASCCrossedUnderMax && + xCHMAScFastBuffer[2] > xCHMANonSCMax2 && + xCHMAScSlowBuffer[2] > xCHMANonSCMax2 + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForShort( + true, // XCHMA Min + true, // XCHMA Max + false, // XCHMA Cycles + false, // XCHMA Peaks + false, // XCHMA Trend Powers + true, // XOBD + true // XTS + ) + // + ) + // + ; + // + return result; + } + + // + // END XCHMAMX Signaller ... + // + + // + // START XCHMAMN Signaller ... + // + + // + // Enable Signaller ... + bool EnableSXCHMAMNignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (mXCHMAMNEnableSignaller) + { + return result; + } + + // + result = true; + mXCHMAMNEnableSignaller = true; + + // + return result; + } + + // + // Disable Signaller ... + bool DisbaleXCHMAMNSignaller() + { + // + bool result = false; + + // + // Validate Args ... + if (!mXCHMAMNEnableSignaller) + { + return result; + } + + // + result = true; + mXCHMAMNEnableSignaller = false; + + // + return result; + } + + // + // Allow Sginaller to Issue Long Signals ... + bool EnableXCHMAMNLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMNEnableSignaller || + mXCHMAMNAllowLongSignals) + { + return result; + } + + // + result = true; + mXCHMAMNAllowLongSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Long Signals ... + bool DisbaleXCHMAMNLongs() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMNEnableSignaller || + !mXCHMAMNAllowLongSignals) + { + return result; + } + + // + result = true; + mXCHMAMNAllowLongSignals = false; + + // + return result; + } + + // + // Allow Signaller to Issue Short Sginals ... + bool EnableXCHMAMNShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMNEnableSignaller || + mXCHMAMNAllowShortSignals) + { + return result; + } + + // + result = true; + mXCHMAMNAllowShortSignals = true; + + // + return result; + } + + // + // Disallow Signaller to Issue Short Signals ... + bool DisableXCHMAMNShorts() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMNEnableSignaller || + !mXCHMAMNAllowShortSignals) + { + return result; + } + + // + result = true; + mXCHMAMNAllowShortSignals = false; + + // + return result; + } + + // + // Check Market Base Conditions for Long Signals ... + bool XCHMAMNHasLongConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMNEnableSignaller || + !mXCHMAMNAllowLongSignals) + { + return result; + } + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double xCHMANonSCMin2 = XCHMAGetCyclesMinValue(2, cycles); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + mXConditions.isXCHMASCCrossedOverMin && + xCHMAScFastBuffer[2] < xCHMANonSCMin2 && + xCHMAScSlowBuffer[2] < xCHMANonSCMin2 + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong( + true, // XCHMA Min + true, // XCHMA Max + false, // XCHMA Cycles + false, // XCHMA Peaks + false, // XCHMA Trend Powers + true, // XOBD + true // XTS + ) + // + ) + // + ; + + // + return result; + } + + // + // Check Market Base Conditions for Short Signals ... + bool XCHMAMNHasShortConditions() + { + // + bool result = false; + + // + // Validate Args ... + if ( + !mXCHMAMNEnableSignaller || + !mXCHMAMNAllowShortSignals) + { + return result; + } + + // + ENUM_XCHMA_CYCLES cycles[]; + Add( + X_XCHMA_CYCLE_MEDIUM, + cycles); + Add( + X_XCHMA_CYCLE_LONG, + cycles); + + // + double xCHMANonSCMin2 = XCHMAGetCyclesMinValue(2, cycles); + + // + // Start Analysing Market based On Conditions ... + result = + // + // Base Condition: + // each Strategy must has a Base Conditions, which they are usually common combinations + // of Market Properties that must be happens to lookup for signals ... + ( + // + mXConditions.isXCHMASCCrossedUnderMin && + xCHMAScFastBuffer[2] > xCHMANonSCMin2 && + xCHMAScSlowBuffer[2] > xCHMANonSCMin2 + // + ) + // + && + // + // Next Step is combine sorts of Conditions which make our choice + // so Exact in Market ... + ( + // + IsReadyForLong( + true, // XCHMA Min + true, // XCHMA Max + false, // XCHMA Cycles + false, // XCHMA Peaks + false, // XCHMA Trend Powers + true, // XOBD + true // XTS + ) + // + ) + // + ; + // + return result; + } + + // + // END XCHMAMN Signaller ... + // + + // + // END Actions Based On Signallers ... + // + + // + // Protected ... +protected: + // + // Private ... +private: + // + // XTD ... + bool mXTDEnableSignaller; + bool mXTDAllowLongSignals; + bool mXTDAllowShortSignals; + + // + // XTAM ... + bool mXTAMEnableSignaller; + bool mXTAMAllowLongSignals; + bool mXTAMAllowShortSignals; + + // + // XSI ... + bool mXSIEnableSignaller; + bool mXSIAllowLongSignals; + bool mXSIAllowShortSignals; + + // + // XTSFI ... + bool mXTSFIEnableSignaller; + bool mXTSFIAllowLongSignals; + bool mXTSFIAllowShortSignals; + + // + // XOBDLH ... + bool mXOBDLHEnableSignaller; + bool mXOBDLHAllowLongSignals; + bool mXOBDLHAllowShortSignals; + + // + // XCHMACC ... + bool mXCHMACCEnableSignaller; + bool mXCHMACCAllowLongSignals; + bool mXCHMACCAllowShortSignals; + + // + // XCHMAMX ... + bool mXCHMAMXEnableSignaller; + bool mXCHMAMXAllowLongSignals; + bool mXCHMAMXAllowShortSignals; + + // + // XCHMAMN ... + bool mXCHMAMNEnableSignaller; + bool mXCHMAMNAllowLongSignals; + bool mXCHMAMNAllowShortSignals; + + // + // Here we Define some Global Market Variables to Analyse MArket Conditions + // using them at each time ... + XMarketConditions mXConditions; +}; \ No newline at end of file diff --git a/Indicators/x-saherelm.xama.indicator.mq5 b/Indicators/x-saherelm.xama.indicator.mq5 new file mode 100644 index 00000000..14d1ef70 --- /dev/null +++ b/Indicators/x-saherelm.xama.indicator.mq5 @@ -0,0 +1,353 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XAMA Indicator +// --------------------------------------------- +// Name: XAMA +// Description: Trend Magic Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XAMA Indicator" +#property strict + +// +// START Constants ... +// +#define ShortName "XAMA" + +// +// XAMA Indicator States ... +enum ENUM_X_XAMA_STATES +{ + X_XAMA_BULLISH = 1, + X_XAMA_BEARISH = -1, + X_XAMA_NEUTURAL = 0, +}; +// +// END Constants ... +// + +// +// START Inputs ... +// +input int length = 18; // Period +input int fastEMA = 2; // Fast EMA Period +input int slowEMA = 30; // Slow EMA Period +input int maShift = 0; // Shift +input ENUM_APPLIED_PRICE appliedTo = PRICE_CLOSE; // Applied To +// +// END Inputs ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 3 +#property indicator_plots 1 + +// +// maBuffer ... +#define maBufferIndex 0 +#define maColorBufferIndex 1 +#define stateBufferIndex 2 + +double maBuffer[]; +double maColorBuffer[]; +double stateBuffer[]; + +#property indicator_label1 "XAMA" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrLime, clrGray, clrRed +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +int maHandler = INVALID_HANDLE; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // Initializing MA Handler ... + maHandler = iAMA( + _Symbol, + _Period, + length, + fastEMA, + slowEMA, + maShift, + appliedTo); + if (maHandler == INVALID_HANDLE) + { + // + string message = "Error Initializing Ma Handler ..."; + LogMessage(message); + + // + return INIT_FAILED; + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + IndicatorRelease(maHandler); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + int maxLength = MathMax(fastEMA, slowEMA); + maxLength = MathMax(maxLength, length); + + // + // Check Calculated Bars ... + int maCalculatedBars = BarsCalculated(maHandler); + if (maCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedMas = CopyBuffer(maHandler, 0, 0, limit, maBuffer); + if (copiedMas <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + // Do Buffers Calculation ... + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (length >= 2) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + string maBufferLabel = "XAMA " + "(" + (string)length + ")"; + + // + // Ma Buffer ... + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + PlotIndexSetString(maBufferIndex, PLOT_LABEL, maBufferLabel); + + // + // Ma Color Buffer ... + ArraySetAsSeries(maColorBuffer, true); + SetIndexBuffer(maColorBufferIndex, maColorBuffer, INDICATOR_COLOR_INDEX); + + // + // State Buffer ... + ArraySetAsSeries(stateBuffer, true); + SetIndexBuffer(stateBufferIndex, stateBuffer, INDICATOR_CALCULATIONS); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, " ", "(", length, ")"); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers(int bar_index) +{ + // + // Requirements ... + XOHCL candle = GetCandle(bar_index); + + // + double maValue = maBuffer[bar_index]; + + // + double lineColorIndex = + maValue < candle.low ? 0 : maValue > candle.high ? 2 + : 1; + + // + // Define State Value ... + // lineColorIndex == 0 => Bullish => 1; + // lineColorIndex == 1 => Neutural => 0; + // lineColorIndex == 2 => Bearish => -1; + double stateValue = + lineColorIndex == 0 ? X_XAMA_BULLISH : lineColorIndex == 2 ? X_XAMA_BEARISH + : X_XAMA_NEUTURAL; + + // + // Set Ma Buffer Color Index ... + maColorBuffer[bar_index] = lineColorIndex; + + // + // Set State Buffer Value ... + stateBuffer[bar_index] = stateValue; +} + +// +// END Functions ... +// diff --git a/Indicators/x-saherelm.xchlh.oscillator.mq5 b/Indicators/x-saherelm.xchlh.oscillator.mq5 new file mode 100644 index 00000000..5c74787c --- /dev/null +++ b/Indicators/x-saherelm.xchlh.oscillator.mq5 @@ -0,0 +1,753 @@ +////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Cycle Channel LH Oscillator +// --------------------------------------------------- +// Name: XCHLH +// Description: detecting HH and LL based on cycles ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCHLH Oscillator" +#property strict + +// +// START Constants ... +// +#define ShortName "XCHLH" + +// +// XCHLH Hot States ... +enum ENUM_X_XCHLH_HOT_STATES +{ + X_XCHLH_HOT_HH = 1, + X_XCHLH_NEUTURAL = 0, + X_XCHLH_HOT_LL = -1, +}; + +// +// Including Models Library ... +#include "../Libraries/x-saherelm.models.lib.mq5" +// +// END Constants ... +// + +// +// START Inputs ... +// +// +// Common ... +input group "Hot Areas"; +input bool drawHotAreas = true; // Draw Hot Areas Symbol +input uchar hotHHArrowCode = 234; // Hot HH Arrow Code +input color hotHHArrowColor = clrAqua; // Hot HH Arrow Color +input uchar hotLLArrowCode = 233; // Hot LL Arrow Code +input color hotLLArrowColor = clrFuchsia; // Hot LL Arrow Color + +// +// LC Inputs ... +input group "Long Cycle"; +input group "LC Market"; +input int lcLength = 28; // Length +input double lcThresholdInPips = 0.3; // Threshold In Pips +input ENUM_SERIESMODE lcHHMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE lcLLMode = MODE_LOW; // Lowest Low Calculation Method +input group "LC Style"; +input int lcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE lcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE lcDrawStyle = STYLE_DOT; // Draw Style +input color lcHHColor = clrAqua; // Highest High Color +input color lcLLColor = clrFuchsia; // Lowest Low Color +input group "LC Drawings"; +input bool lcDrawHH = true; // Draw Highest High +input bool lcDrawLL = true; // Draw Lowest Low + +// +// MC Inputs ... +input group "Medium Cycle"; +input group "MC Market"; +input int mcLength = 14; // Length +input double mcThresholdInPips = 0.3; // Threshold In Pips +input ENUM_SERIESMODE mcHHMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE mcLLMode = MODE_LOW; // Lowest Low Calculation Method +input group "MC Style"; +input int mcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE mcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE mcDrawStyle = STYLE_DOT; // Draw Style +input color mcHHColor = clrLime; // Highest High Color +input color mcLLColor = clrRed; // Lowest Low Color +input group "MC Drawings"; +input bool mcDrawHH = true; // Draw Highest High +input bool mcDrawLL = true; // Draw Lowest Low + +// +// SC Inputs ... +input group "Short Cycle"; +input group "SC Market"; +input int scLength = 7; // Length +input double scThresholdInPips = 0.3; // Threshold In Pips +input ENUM_SERIESMODE scHHMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE scLLMode = MODE_LOW; // Lowest Low Calculation Method +input group "SC Style"; +input int scDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE scDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE scDrawStyle = STYLE_DOT; // Draw Style +input color scHHColor = clrLightBlue; // Highest High Color +input color scLLColor = clrLightSalmon; // Lowest Low Color +input group "SC Drawings"; +input bool scDrawHH = true; // Draw Highest High +input bool scDrawLL = true; // Draw Lowest Low +// +// END Inputs ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5"; + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5"; + +// +// Includes Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5"; + +// +// START Buffers ... +// +#property indicator_separate_window + +// +#property indicator_buffers 7 +#property indicator_plots 6 + +// +// LC ... +#define lcHHBufferIndex 0 +#define lcLLBufferIndex 1 + +// +double lcHHBuffer[]; +double lcLLBuffer[]; + +// +// MC ... +#define mcHHBufferIndex 2 +#define mcLLBufferIndex 3 + +// +double mcHHBuffer[]; +double mcLLBuffer[]; + +// +// SC ... +#define scHHBufferIndex 4 +#define scLLBufferIndex 5 + +// +double scHHBuffer[]; +double scLLBuffer[]; + +// +// Hot State ... +// +#define hotStateBufferIndex 6 + +// +double hotStateBuffer[]; +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + drawPrefix = ShortName; + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + + // + // ReDraw Chart ... + ChartRedraw(); + + // + // De Init Draw Library ... + OnDeinitDrawLibrary(); + + // + Comment(""); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + int maxLength = MathMax(lcLength, mcLength); + maxLength = MathMax(maxLength, scLength); + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + // Main Loop ... + for (int i = limit; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + bool isLCInputsValid = + lcLength >= 4 && + lcLength > mcLength && + lcLength > scLength; + bool isMCInputsValid = + mcLength >= 4 && + mcLength > scLength && + mcLength < lcLength; + bool isSCInputsValid = + scLength >= 4 && + scLength < mcLength && + scLength < lcLength; + if ( + isLCInputsValid && + isMCInputsValid && + isSCInputsValid) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // LC ... + LCDefineBuffers(); + + // + // MC ... + MCDefineBuffers(); + + // + // SC ... + SCDefineBuffers(); + + // + // Hot State Buffer ... + HotStateDefineBuffers(); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // LC ... + LCCalculateBuffers(bar_index); + + // + // MC ... + MCCalculateBuffers(bar_index); + + // + // SC ... + SCCalculateBuffers(bar_index); + + // + // SIGNAL ... + SignalCalculateBuffers(bar_index); + + // + // HOT State Buffer ... + HotStateCalculateBuffers(bar_index); + + // + // After all Calculations we are ready to Draw what we want ... + DrawBuffers(bar_index); +} + +// +// LC Buffers Definitions ... +void LCDefineBuffers() +{ + // + // LC HH Buffer ... + string lcHHBufferLabel = ShortName + " LC HH (" + (string)lcLength + ")"; + ENUM_DRAW_TYPE lcHHDrawType = lcDrawHH ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(lcHHBuffer, true); + SetIndexBuffer(lcHHBufferIndex, lcHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_DRAW_BEGIN, lcLength); + PlotIndexSetString(lcHHBufferIndex, PLOT_LABEL, lcHHBufferLabel); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_LINE_COLOR, lcHHColor); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_LINE_STYLE, lcDrawStyle); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_LINE_WIDTH, lcDrawWidth); + PlotIndexSetInteger(lcHHBufferIndex, PLOT_DRAW_TYPE, lcHHDrawType); + + // + // LC LL Buffer ... + string lcLLBufferLabel = ShortName + " LC LL (" + (string)lcLength + ")"; + ENUM_DRAW_TYPE lcLLDrawType = lcDrawLL ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(lcLLBuffer, true); + SetIndexBuffer(lcLLBufferIndex, lcLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_DRAW_BEGIN, lcLength); + PlotIndexSetString(lcLLBufferIndex, PLOT_LABEL, lcLLBufferLabel); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_LINE_COLOR, lcLLColor); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_LINE_STYLE, lcDrawStyle); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_LINE_WIDTH, lcDrawWidth); + PlotIndexSetInteger(lcLLBufferIndex, PLOT_DRAW_TYPE, lcLLDrawType); +} + +// +// MC Buffers Definitions ... +void MCDefineBuffers() +{ + // + // MC HH Buffer ... + string mcHHBufferLabel = ShortName + " MC HH (" + (string)mcLength + ")"; + ENUM_DRAW_TYPE mcHHDrawType = mcDrawHH ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(mcHHBuffer, true); + SetIndexBuffer(mcHHBufferIndex, mcHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_DRAW_BEGIN, mcLength); + PlotIndexSetString(mcHHBufferIndex, PLOT_LABEL, mcHHBufferLabel); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_LINE_COLOR, mcHHColor); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_LINE_STYLE, mcDrawStyle); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_LINE_WIDTH, mcDrawWidth); + PlotIndexSetInteger(mcHHBufferIndex, PLOT_DRAW_TYPE, mcHHDrawType); + + // + // MC LL Buffer ... + string mcLLBufferLabel = ShortName + " MC LL (" + (string)mcLength + ")"; + ENUM_DRAW_TYPE mcLLDrawType = mcDrawLL ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(mcLLBuffer, true); + SetIndexBuffer(mcLLBufferIndex, mcLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_DRAW_BEGIN, mcLength); + PlotIndexSetString(mcLLBufferIndex, PLOT_LABEL, mcLLBufferLabel); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_LINE_COLOR, mcLLColor); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_LINE_STYLE, mcDrawStyle); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_LINE_WIDTH, mcDrawWidth); + PlotIndexSetInteger(mcLLBufferIndex, PLOT_DRAW_TYPE, mcLLDrawType); +} + +// +// SC Buffers Definitions ... +void SCDefineBuffers() +{ + // + // SC HH Buffer ... + string scHHBufferLabel = ShortName + " SC HH (" + (string)scLength + ")"; + ENUM_DRAW_TYPE scHHDrawType = scDrawHH ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(scHHBuffer, true); + SetIndexBuffer(scHHBufferIndex, scHHBuffer, INDICATOR_DATA); + PlotIndexSetInteger(scHHBufferIndex, PLOT_DRAW_BEGIN, scLength); + PlotIndexSetString(scHHBufferIndex, PLOT_LABEL, scHHBufferLabel); + PlotIndexSetInteger(scHHBufferIndex, PLOT_LINE_COLOR, scHHColor); + PlotIndexSetInteger(scHHBufferIndex, PLOT_LINE_STYLE, scDrawStyle); + PlotIndexSetInteger(scHHBufferIndex, PLOT_LINE_WIDTH, scDrawWidth); + PlotIndexSetInteger(scHHBufferIndex, PLOT_DRAW_TYPE, scHHDrawType); + + // + // SC LL Buffer ... + string scLLBufferLabel = ShortName + " SC LL (" + (string)scLength + ")"; + ENUM_DRAW_TYPE scLLDrawType = scDrawLL ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(scLLBuffer, true); + SetIndexBuffer(scLLBufferIndex, scLLBuffer, INDICATOR_DATA); + PlotIndexSetInteger(scLLBufferIndex, PLOT_DRAW_BEGIN, scLength); + PlotIndexSetString(scLLBufferIndex, PLOT_LABEL, scLLBufferLabel); + PlotIndexSetInteger(scLLBufferIndex, PLOT_LINE_COLOR, scLLColor); + PlotIndexSetInteger(scLLBufferIndex, PLOT_LINE_STYLE, scDrawStyle); + PlotIndexSetInteger(scLLBufferIndex, PLOT_LINE_WIDTH, scDrawWidth); + PlotIndexSetInteger(scLLBufferIndex, PLOT_DRAW_TYPE, scLLDrawType); +} + +// +// Hot State Buffer ... +void HotStateDefineBuffers() +{ + // + // Hot State Buffer ... + ArraySetAsSeries(hotStateBuffer, true); + SetIndexBuffer(hotStateBufferIndex, hotStateBuffer, INDICATOR_CALCULATIONS); +} + +// +// LC Calculations ... +void LCCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // Detect Cycle HH and LL ... + int length = lcLength; + ENUM_SERIESMODE hhMode = lcHHMode; + ENUM_SERIESMODE llMode = lcLLMode; + double threshold = PipsToPrice(lcThresholdInPips); + double hh = GetHighestHigh( + length, + bar_index, + hhMode); + double hhValue = hh + threshold; + double ll = GetLowestLow( + length, + bar_index, + llMode); + double llValue = ll - threshold; + + // + lcHHBuffer[bar_index] = hhValue; + lcLLBuffer[bar_index] = llValue; +} + +// +// MC Calculations ... +void MCCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // Detect Cycle HH and LL ... + int length = mcLength; + ENUM_SERIESMODE hhMode = mcHHMode; + ENUM_SERIESMODE llMode = mcLLMode; + double threshold = PipsToPrice(mcThresholdInPips); + double hh = GetHighestHigh( + length, + bar_index, + hhMode); + double hhValue = hh + threshold; + double ll = GetLowestLow( + length, + bar_index, + llMode); + double llValue = ll - threshold; + + // + mcHHBuffer[bar_index] = hhValue; + mcLLBuffer[bar_index] = llValue; +} + +// +// SC Calculations ... +void SCCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // Detect Cycle HH and LL ... + int length = scLength; + ENUM_SERIESMODE hhMode = scHHMode; + ENUM_SERIESMODE llMode = scLLMode; + double threshold = PipsToPrice(scThresholdInPips); + double hh = GetHighestHigh( + length, + bar_index, + hhMode); + double hhValue = hh + threshold; + double ll = GetLowestLow( + length, + bar_index, + llMode); + double llValue = ll - threshold; + + // + scHHBuffer[bar_index] = hhValue; + scLLBuffer[bar_index] = llValue; +} + +// +// SIGNAL Calculations ... +void SignalCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // LC Values ... + double lcHH = lcHHBuffer[bar_index]; + double lcLL = lcLLBuffer[bar_index]; + double lcDelta = lcHH - lcLL; + double lcAvg = lcDelta / 2; + + // + // MC Values ... + double mcHH = mcHHBuffer[bar_index]; + double mcLL = mcLLBuffer[bar_index]; + double mcDelta = mcHH - mcLL; + double mcAvg = mcDelta / 2; + + // + // SC Values ... + double scHH = scHHBuffer[bar_index]; + double scLL = scLLBuffer[bar_index]; + double scDelta = scHH - scLL; + double scAvg = scDelta / 2; + + // + // Min Value ... + double minValue = MathMin( + scLL, mcLL); + minValue = MathMin( + lcLL, minValue); + + // + // Max Value ... + double maxValue = MathMin( + scHH, mcHH); + maxValue = MathMin( + lcHH, maxValue); +} + +// +// HOT State Calculate Buffers ... +void HotStateCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // LC ... + double lcHH = lcHHBuffer[bar_index]; + double lcLL = lcLLBuffer[bar_index]; + // + double lcHH1 = lcHHBuffer[bar_index + 1]; + double lcLL1 = lcLLBuffer[bar_index + 1]; + + // + // MC ... + double mcHH = mcHHBuffer[bar_index]; + double mcLL = mcLLBuffer[bar_index]; + // + double mcHH1 = mcHHBuffer[bar_index + 1]; + double mcLL1 = mcLLBuffer[bar_index + 1]; + + // + // SC ... + double scHH = scHHBuffer[bar_index]; + double scLL = scLLBuffer[bar_index]; + // + double scHH1 = scHHBuffer[bar_index + 1]; + double scLL1 = scLLBuffer[bar_index + 1]; + + // + bool isHotLLState = scLL == mcLL && mcLL == lcLL; + bool isHotLLState1 = scLL1 == mcLL1 && mcLL1 == lcLL1; + // + bool isHotHHState = scHH == mcHH && mcHH == lcHH; + bool isHotHHState1 = scHH1 == mcHH1 && mcHH1 == lcHH1; + + // + bool isHotLL = isHotLLState && !isHotLLState1; + bool isHotHH = isHotHHState && !isHotHHState1; + + // + double hotStateValue = X_XCHLH_NEUTURAL; + if (isHotHH) + { + hotStateValue = X_XCHLH_HOT_HH; + } + else if (isHotLL) + { + hotStateValue = X_XCHLH_HOT_LL; + } + + // + hotStateBuffer[bar_index] = hotStateValue; +} + +// +// Draw Buffers ... +void DrawBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // General Requirements ... + + // + // Retrieve Candle Model ... + XOHCL candle = GetCandle(bar_index); + datetime time = iTime(_Symbol, _Period, bar_index); + + // + // Draw Arrow on Hot Areas ... + if (drawHotAreas) + { + // + double hotStateValue = hotStateBuffer[bar_index]; + bool isHotHHArea = hotStateValue == 1; + bool isHotLLArea = hotStateValue == -1; + if (isHotHHArea || isHotLLArea) + { + // + bool isHH = isHotHHArea; + + // + double price = isHH ? candle.high : candle.low; + ENUM_ARROW_ANCHOR anchor = isHH ? ANCHOR_BOTTOM : ANCHOR_TOP; + color clr = isHH ? hotHHArrowColor : hotLLArrowColor; + uchar arrowCode = isHH ? hotHHArrowCode : hotLLArrowCode; + string name = "HOT " + (isHH ? "HH" : "LL") + "_" + (string)price + "_" + (string)time; + + // + DrawArrow( + 0, + name, + 0, + time, + price, + arrowCode, + anchor, + clr, + STYLE_SOLID, + 1); + } + } +} +// +// END Functions ... +// diff --git a/Indicators/x-saherelm.xchma.oscillator.mq5 b/Indicators/x-saherelm.xchma.oscillator.mq5 new file mode 100644 index 00000000..12d6c691 --- /dev/null +++ b/Indicators/x-saherelm.xchma.oscillator.mq5 @@ -0,0 +1,1153 @@ +/////////////////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Cycle Channel Moving Averages Oscillator +// ---------------------------------------------------------------- +// Name: XCHMA +// Description: trend detecting based on cycles ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCHMA Oscillator" +#property strict + +// +// START Constants ... +// +#define ShortName "XCHMA" + +// +// XCHMA Oscillator Cycles State Presentation ... +enum ENUM_XCHMA_CYCLE_STATES +{ + X_XCHMA_FAST_CROSSED_OVER_SLOW = 2, + X_XCHMA_FAST_OVER_SLOW = 1, + X_XCHMA_NEUTURAL = 0, + X_XCHMA_FAST_UNDER_SLOW = -1, + X_XCHMA_FAST_CROSSED_UNDER_SLOW = -2, +}; +// +// END Constants ... +// + +// +// START Inputs ... +// +// +// Common ... +input group "Hot Areas"; +input bool drawHotAreas = true; // Draw Hot Areas Symbol +input uchar hotBullishArrowCode = 228; // Hot Bullish Arrow Code +input color hotBullishArrowColor = clrAqua; // Hot Bullish Arrow Color +input uchar hotBearishArrowCode = 230; // Hot Bearish Arrow Code +input color hotBearishArrowColor = clrFuchsia; // Hot Bearish Arrow Color + +// +// LC Inputs ... +input group "Long Cycle"; +input group "LC Market"; +input int lcFastLength = 20; // Fast Length +input int lcSlowLength = 50; // Slow Length +input ENUM_MA_METHOD lcMethod = MODE_EMA; // Calculation Method +input ENUM_APPLIED_PRICE lcAppliedTo = PRICE_CLOSE; // Applied To +input group "LC Style"; +input int lcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE lcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE lcDrawStyle = STYLE_DOT; // Draw Style +input color lcFastColor = clrAqua; // Fast Color +input color lcSlowColor = clrFuchsia; // Slow Color +input group "LC Drawings"; +input bool lcDrawFast = true; // Draw Fast +input bool lcDrawSlow = true; // Draw Slow +input bool lcDrawCrosses = true; // Draw Cross Lines + +// +// MC Inputs ... +input group "Medium Cycle"; +input group "MC Market"; +input int mcFastLength = 10; // Fast Length +input int mcSlowLength = 30; // Slow Length +input ENUM_MA_METHOD mcMethod = MODE_EMA; // Calculation Method +input ENUM_APPLIED_PRICE mcAppliedTo = PRICE_CLOSE; // Applied To +input group "MC Style"; +input int mcDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE mcDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE mcDrawStyle = STYLE_DOT; // Draw Style +input color mcFastColor = clrLime; // Fast Color +input color mcSlowColor = clrRed; // Slow Color +input group "MC Drawings"; +input bool mcDrawFast = true; // Draw Fast +input bool mcDrawSlow = true; // Draw Slow +input bool mcDrawCrosses = false; // Draw Cross Lines + +// +// SC Inputs ... +input group "Short Cycle"; +input group "SC Market"; +input int scFastLength = 7; // Fast Length +input int scSlowLength = 14; // Slow Length +input ENUM_MA_METHOD scMethod = MODE_EMA; // Calculation Method +input ENUM_APPLIED_PRICE scAppliedTo = PRICE_CLOSE; // Applied To +input group "SC Style"; +input int scDrawWidth = 1; // Draw Width +input ENUM_DRAW_TYPE scDrawType = DRAW_LINE; // Draw Type +input ENUM_LINE_STYLE scDrawStyle = STYLE_SOLID; // Draw Style +input color scFastColor = clrLightBlue; // Fast Color +input color scSlowColor = clrLightSalmon; // Slow Color +input group "SC Drawings"; +input bool scDrawFast = true; // Draw Fast +input bool scDrawSlow = true; // Draw Slow +input bool scDrawCrosses = false; // Draw Cross Lines +// +// END Inputs ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Includes Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5" + +// +// START Buffers ... +// +#property indicator_separate_window + +// +#property indicator_buffers 7 +#property indicator_plots 6 + +// +// LC ... +#define lcFastBufferIndex 0 +#define lcSlowBufferIndex 1 + +// +double lcFastBuffer[]; +double lcSlowBuffer[]; + +// +// MC ... +#define mcFastBufferIndex 2 +#define mcSlowBufferIndex 3 + +// +double mcFastBuffer[]; +double mcSlowBuffer[]; + +// +// SC ... +#define scFastBufferIndex 4 +#define scSlowBufferIndex 5 + +// +double scFastBuffer[]; +double scSlowBuffer[]; + +// +// Hot State ... +// +#define hotStateBufferIndex 6 + +// +double hotStateBuffer[]; +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +// LC ... +int lcFastHandler = INVALID_HANDLE; +int lcSlowHandler = INVALID_HANDLE; + +// +// MC ... +int mcFastHandler = INVALID_HANDLE; +int mcSlowHandler = INVALID_HANDLE; + +// +// SC ... +int scFastHandler = INVALID_HANDLE; +int scSlowHandler = INVALID_HANDLE; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + drawPrefix = ShortName; + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init All Required Handlers ... + if (!InitHandlers()) + { + return INIT_FAILED; + } + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + + // + // ReDraw Chart ... + ChartRedraw(); + + // + // De Init Draw Library ... + OnDeinitDrawLibrary(); + + // + Comment(""); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + int maxLength = MathMax(lcFastLength, lcSlowLength); + + // + // Get Retrieved Values from indicators ... + // + // LC ... + int lcFastCalculatedBars = BarsCalculated(lcFastHandler); + int lcSlowCalculatedBars = BarsCalculated(lcSlowHandler); + + // + // MC ... + int mcFastCalculatedBars = BarsCalculated(mcFastHandler); + int mcSlowCalculatedBars = BarsCalculated(mcSlowHandler); + + // + // SC ... + int scFastCalculatedBars = BarsCalculated(scFastHandler); + int scSlowCalculatedBars = BarsCalculated(scSlowHandler); + + // + // Check Calculated Bars ... + if ( + // + // LC ... + lcFastCalculatedBars < maxLength || + lcSlowCalculatedBars < maxLength || + // + // MC ... + mcFastCalculatedBars < maxLength || + mcSlowCalculatedBars < maxLength || + // + // SC ... + scFastCalculatedBars < maxLength || + scSlowCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + // Copy Buffers from indicators ... + // + // LC ... + int lcFastCopiedItems = CopyBuffer(lcFastHandler, 0, 0, limit + 1, lcFastBuffer); + int lcSlowCopiedItems = CopyBuffer(lcSlowHandler, 0, 0, limit + 1, lcSlowBuffer); + + // + // MC ... + int mcFastCopiedItems = CopyBuffer(mcFastHandler, 0, 0, limit + 1, mcFastBuffer); + int mcSlowCopiedItems = CopyBuffer(mcSlowHandler, 0, 0, limit + 1, mcSlowBuffer); + + // + // SC ... + int scFastCopiedItems = CopyBuffer(scFastHandler, 0, 0, limit + 1, scFastBuffer); + int scSlowCopiedItems = CopyBuffer(scSlowHandler, 0, 0, limit + 1, scSlowBuffer); + + // + // Check Copied Items Number ... + if ( + // + // LC ... + lcFastCopiedItems <= 0 || + lcSlowCopiedItems <= 0 || + // + // MC ... + mcFastCopiedItems <= 0 || + mcSlowCopiedItems <= 0 || + // + // MC ... + mcFastCopiedItems <= 0 || + mcSlowCopiedItems <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + bool isLCInputsValid = lcFastLength >= 4 && lcSlowLength > lcFastLength; + bool isMCInputsValid = mcFastLength >= 4 && mcSlowLength > mcFastLength; + bool isSCInputsValid = scFastLength >= 4 && scSlowLength > scFastLength; + if ( + isLCInputsValid && + isMCInputsValid && + isSCInputsValid && + lcFastLength > mcFastLength && + mcFastLength > scFastLength) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // LC ... + LCDefineBuffers(); + + // + // MC ... + MCDefineBuffers(); + + // + // SC ... + SCDefineBuffers(); + + // + // Hot State Buffer ... + HotStateDefineBuffers(); +} + +// +// Init Handlers ... +bool InitHandlers() +{ + // + bool result = false; + + // + // LC ... + result = LCInitHandlers(); + if (!result) + { + return result; + } + + // + // MC ... + result = MCInitHandlers(); + if (!result) + { + return result; + } + + // + // SC ... + result = SCInitHandlers(); + if (!result) + { + return result; + } + + // + return result; +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // HOT State Buffer ... + HotStateCalculateBuffers(bar_index); + + // + // After all Calculations we are ready to Draw what we want ... + DrawBuffers(bar_index); +} + +// +// LC Buffers Definitions ... +void LCDefineBuffers() +{ + // + // LC Fast Buffer ... + string lcFastBufferLabel = ShortName + " LC Fast (" + (string)lcFastLength + ")"; + ENUM_DRAW_TYPE lcFastDrawType = lcDrawFast ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(lcFastBuffer, true); + SetIndexBuffer(lcFastBufferIndex, lcFastBuffer, INDICATOR_DATA); + PlotIndexSetString(lcFastBufferIndex, PLOT_LABEL, lcFastBufferLabel); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_LINE_COLOR, lcFastColor); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_LINE_STYLE, lcDrawStyle); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_LINE_WIDTH, lcDrawWidth); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_DRAW_BEGIN, lcFastLength); + PlotIndexSetInteger(lcFastBufferIndex, PLOT_DRAW_TYPE, lcFastDrawType); + + // + // LC Slow Buffer ... + string lcSlowBufferLabel = ShortName + " LC Slow (" + (string)lcSlowLength + ")"; + ENUM_DRAW_TYPE lcSlowDrawType = lcDrawSlow ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(lcSlowBuffer, true); + SetIndexBuffer(lcSlowBufferIndex, lcSlowBuffer, INDICATOR_DATA); + PlotIndexSetString(lcSlowBufferIndex, PLOT_LABEL, lcSlowBufferLabel); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_LINE_COLOR, lcSlowColor); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_LINE_STYLE, lcDrawStyle); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_LINE_WIDTH, lcDrawWidth); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_DRAW_BEGIN, lcSlowLength); + PlotIndexSetInteger(lcSlowBufferIndex, PLOT_DRAW_TYPE, lcSlowDrawType); +} + +// +// MC Buffers Definitions ... +void MCDefineBuffers() +{ + // + // MC Fast Buffer ... + string mcFastBufferLabel = ShortName + " MC Fast (" + (string)mcFastLength + ")"; + ENUM_DRAW_TYPE mcFastDrawType = mcDrawFast ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(mcFastBuffer, true); + SetIndexBuffer(mcFastBufferIndex, mcFastBuffer, INDICATOR_DATA); + PlotIndexSetString(mcFastBufferIndex, PLOT_LABEL, mcFastBufferLabel); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_LINE_COLOR, mcFastColor); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_LINE_STYLE, mcDrawStyle); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_LINE_WIDTH, mcDrawWidth); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_DRAW_BEGIN, mcFastLength); + PlotIndexSetInteger(mcFastBufferIndex, PLOT_DRAW_TYPE, mcFastDrawType); + + // + // MC Slow Buffer ... + string mcSlowBufferLabel = ShortName + " MC Slow (" + (string)mcSlowLength + ")"; + ENUM_DRAW_TYPE mcSlowDrawType = mcDrawSlow ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(mcSlowBuffer, true); + SetIndexBuffer(mcSlowBufferIndex, mcSlowBuffer, INDICATOR_DATA); + PlotIndexSetString(mcSlowBufferIndex, PLOT_LABEL, mcSlowBufferLabel); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_LINE_COLOR, mcSlowColor); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_LINE_STYLE, mcDrawStyle); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_LINE_WIDTH, mcDrawWidth); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_DRAW_BEGIN, mcSlowLength); + PlotIndexSetInteger(mcSlowBufferIndex, PLOT_DRAW_TYPE, mcSlowDrawType); +} + +// +// SC Buffers Definitions ... +void SCDefineBuffers() +{ + // + // SC Fast Buffer ... + string scFastBufferLabel = ShortName + " SC Fast (" + (string)scFastLength + ")"; + ENUM_DRAW_TYPE scFastDrawType = scDrawFast ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(scFastBuffer, true); + SetIndexBuffer(scFastBufferIndex, scFastBuffer, INDICATOR_DATA); + PlotIndexSetString(scFastBufferIndex, PLOT_LABEL, scFastBufferLabel); + PlotIndexSetInteger(scFastBufferIndex, PLOT_LINE_COLOR, scFastColor); + PlotIndexSetInteger(scFastBufferIndex, PLOT_LINE_STYLE, scDrawStyle); + PlotIndexSetInteger(scFastBufferIndex, PLOT_LINE_WIDTH, scDrawWidth); + PlotIndexSetInteger(scFastBufferIndex, PLOT_DRAW_BEGIN, scFastLength); + PlotIndexSetInteger(scFastBufferIndex, PLOT_DRAW_TYPE, scFastDrawType); + + // + // SC Slow Buffer ... + string scSlowBufferLabel = ShortName + " SC Slow (" + (string)scSlowLength + ")"; + ENUM_DRAW_TYPE scSlowDrawType = scDrawSlow ? lcDrawType : DRAW_NONE; + ArraySetAsSeries(scSlowBuffer, true); + SetIndexBuffer(scSlowBufferIndex, scSlowBuffer, INDICATOR_DATA); + PlotIndexSetString(scSlowBufferIndex, PLOT_LABEL, scSlowBufferLabel); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_LINE_COLOR, scSlowColor); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_LINE_STYLE, scDrawStyle); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_LINE_WIDTH, scDrawWidth); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_DRAW_BEGIN, scSlowLength); + PlotIndexSetInteger(scSlowBufferIndex, PLOT_DRAW_TYPE, scSlowDrawType); +} + +// +// Hot State Buffer ... +void HotStateDefineBuffers() +{ + // + // Hot State Buffer ... + ArraySetAsSeries(hotStateBuffer, true); + SetIndexBuffer(hotStateBufferIndex, hotStateBuffer, INDICATOR_CALCULATIONS); +} + +// +// LC Init Handlers ... +bool LCInitHandlers() +{ + // + ResetLastError(); + + // + // LC Fast Handler ... + lcFastHandler = iMA( + _Symbol, + _Period, + lcFastLength, + 0, + lcMethod, + lcAppliedTo); + if (lcFastHandler == INVALID_HANDLE) + { + // + LogMessage("LC Fast Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + // LC Slow Handler ... + lcSlowHandler = iMA( + _Symbol, + _Period, + lcSlowLength, + 0, + lcMethod, + lcAppliedTo); + if (lcSlowHandler == INVALID_HANDLE) + { + // + LogMessage("LC Slow Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + return true; +} + +// +// MC Init Handlers ... +bool MCInitHandlers() +{ + // + ResetLastError(); + + // + // MC Fast Handler ... + mcFastHandler = iMA( + _Symbol, + _Period, + mcFastLength, + 0, + mcMethod, + mcAppliedTo); + if (mcFastHandler == INVALID_HANDLE) + { + // + LogMessage("MC Fast Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + // MC Slow Handler ... + mcSlowHandler = iMA( + _Symbol, + _Period, + mcSlowLength, + 0, + mcMethod, + mcAppliedTo); + if (mcSlowHandler == INVALID_HANDLE) + { + // + LogMessage("MC Slow Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + return true; +} + +// +// SC Init Handlers ... +bool SCInitHandlers() +{ + // + ResetLastError(); + + // + // SC Fast Handler ... + scFastHandler = iMA( + _Symbol, + _Period, + scFastLength, + 0, + scMethod, + scAppliedTo); + if (scFastHandler == INVALID_HANDLE) + { + // + LogMessage("SC Fast Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + // SC Slow Handler ... + scSlowHandler = iMA( + _Symbol, + _Period, + scSlowLength, + 0, + scMethod, + scAppliedTo); + if (scSlowHandler == INVALID_HANDLE) + { + // + LogMessage("SC Slow Indicator initialization failed: " + (string)GetLastError()); + + // + return false; + } + + // + return true; +} + +// +// LC State ... +double GetLCState( + int bar_index // Current Candle Index ... +) +{ + // + // Fast Cross Over Slow Detection ... + bool isFastCrossedOverSlow = IsCrossOver( + lcFastBuffer, + lcSlowBuffer, + bar_index); + + // + // Fast Over Slow Detection ... + bool isFastOverSlow = IsOver( + lcFastBuffer, + lcSlowBuffer, + bar_index); + + // + // Fast Cross Under Slow Detection ... + bool isFastCrossedUnderSlow = IsCrossUnder( + lcFastBuffer, + lcSlowBuffer, + bar_index); + + // + // Fast Under Slow Detection ... + bool isFastUnderSlow = IsUnder( + lcFastBuffer, + lcSlowBuffer, + bar_index); + + // + // Generate state value which represent curren bar index + // state between fast and slow lines ... + double result = X_XCHMA_NEUTURAL; + + // + // Filling state value based on Market Conditions ... + if (isFastCrossedOverSlow) + { + result = X_XCHMA_FAST_CROSSED_OVER_SLOW; + } + else if (isFastCrossedUnderSlow) + { + result = X_XCHMA_FAST_CROSSED_UNDER_SLOW; + } + else if (isFastOverSlow) + { + result = X_XCHMA_FAST_OVER_SLOW; + } + else if (isFastUnderSlow) + { + result = X_XCHMA_FAST_UNDER_SLOW; + } + + // + return result; +} + +// +// MC State ... +double GetMCState( + int bar_index // Current Candle Index ... +) +{ + // + // Fast Cross Over Slow Detection ... + bool isFastCrossedOverSlow = IsCrossOver( + mcFastBuffer, + mcSlowBuffer, + bar_index); + + // + // Fast Over Slow Detection ... + bool isFastOverSlow = IsOver( + mcFastBuffer, + mcSlowBuffer, + bar_index); + + // + // Fast Cross Under Slow Detection ... + bool isFastCrossedUnderSlow = IsCrossUnder( + mcFastBuffer, + mcSlowBuffer, + bar_index); + + // + // Fast Under Slow Detection ... + bool isFastUnderSlow = IsUnder( + mcFastBuffer, + mcSlowBuffer, + bar_index); + + // + // Generate state value which represent curren bar index + // state between fast and slow lines ... + double result = X_XCHMA_NEUTURAL; + + // + // Filling state value based on Market Conditions ... + if (isFastCrossedOverSlow) + { + result = X_XCHMA_FAST_CROSSED_OVER_SLOW; + } + else if (isFastCrossedUnderSlow) + { + result = X_XCHMA_FAST_CROSSED_UNDER_SLOW; + } + else if (isFastOverSlow) + { + result = X_XCHMA_FAST_OVER_SLOW; + } + else if (isFastUnderSlow) + { + result = X_XCHMA_FAST_UNDER_SLOW; + } + + // + return result; +} + +// +// SC State ... +double GetSCState( + int bar_index // Current Candle Index ... +) +{ + // + // Fast Cross Over Slow Detection ... + bool isFastCrossedOverSlow = IsCrossOver( + scFastBuffer, + scSlowBuffer, + bar_index); + + // + // Fast Over Slow Detection ... + bool isFastOverSlow = IsOver( + scFastBuffer, + scSlowBuffer, + bar_index); + + // + // Fast Cross Under Slow Detection ... + bool isFastCrossedUnderSlow = IsCrossUnder( + scFastBuffer, + scSlowBuffer, + bar_index); + + // + // Fast Under Slow Detection ... + bool isFastUnderSlow = IsUnder( + scFastBuffer, + scSlowBuffer, + bar_index); + + // + // Generate state value which represent curren bar index + // state between fast and slow lines ... + double result = X_XCHMA_NEUTURAL; + + // + // Filling state value based on Market Conditions ... + if (isFastCrossedOverSlow) + { + result = X_XCHMA_FAST_CROSSED_OVER_SLOW; + } + else if (isFastCrossedUnderSlow) + { + result = X_XCHMA_FAST_CROSSED_UNDER_SLOW; + } + else if (isFastOverSlow) + { + result = X_XCHMA_FAST_OVER_SLOW; + } + else if (isFastUnderSlow) + { + result = X_XCHMA_FAST_UNDER_SLOW; + } + + // + return result; +} + +// +// HOT State Calculate Buffers ... +void HotStateCalculateBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // LC ... + double lcFast = lcFastBuffer[bar_index]; + double lcSlow = lcSlowBuffer[bar_index]; + // + double lcFastPrev = lcFastBuffer[bar_index + 1]; + double lcSlowPrev = lcSlowBuffer[bar_index + 1]; + // + double lcState = GetLCState(bar_index); + + // + // MC ... + double mcFast = mcFastBuffer[bar_index]; + double mcSlow = mcSlowBuffer[bar_index]; + // + double mcFastPrev = mcFastBuffer[bar_index + 1]; + double mcSlowPrev = mcSlowBuffer[bar_index + 1]; + // + double mcState = GetMCState(bar_index); + + // + // SC ... + double scFast = scFastBuffer[bar_index]; + double scSlow = scSlowBuffer[bar_index]; + // + double scFastPrev = scFastBuffer[bar_index + 1]; + double scSlowPrev = scSlowBuffer[bar_index + 1]; + // + double scState = GetSCState(bar_index); + + // + // Detect HOT Bearish Area ... + bool isHotBearishArea = + lcFast < lcSlow && + mcFast < mcSlow && + scFast < scSlow; + // + bool isPrevHotBearishArea = + lcFastPrev < lcSlowPrev && + mcFastPrev < mcSlowPrev && + scFastPrev < scSlowPrev; + + // + // Detect HOT Bearish Area ... + bool isHotBullishArea = + lcFast > lcSlow && + mcFast > mcSlow && + scFast > scSlow; + // + bool isPrevHotBullishArea = + lcFastPrev > lcSlowPrev && + mcFastPrev > mcSlowPrev && + scFastPrev > scSlowPrev; + + // + // Generate HotState Value ... + double hotStateValue = + isHotBullishArea && !isPrevHotBullishArea + ? 1 + : isHotBearishArea && !isPrevHotBearishArea + ? -1 + : 0; + hotStateBuffer[bar_index] = hotStateValue; +} + +// +// Draw Buffers ... +void DrawBuffers( + int bar_index // Current Candle Index ... +) +{ + // + // General Requirements ... + + // + // Retrieve Candle Model ... + XOHCL candle = GetCandle(bar_index); + datetime time = iTime(_Symbol, _Period, bar_index); + + // + // Draw Arrow on Hot Areas ... + if (drawHotAreas) + { + // + double hotStateValue = hotStateBuffer[bar_index]; + bool isHotBullishArea = hotStateValue == 1; + bool isHotBearishArea = hotStateValue == -1; + if (isHotBullishArea || isHotBearishArea) + { + // + bool isBull = isHotBullishArea; + + // + double price = isBull ? candle.low : candle.high; + ENUM_ARROW_ANCHOR anchor = isBull ? ANCHOR_TOP : ANCHOR_BOTTOM; + color clr = isBull ? hotBullishArrowColor : hotBearishArrowColor; + uchar arrowCode = isBull ? hotBullishArrowCode : hotBearishArrowCode; + string name = "HOT " + (isBull ? "Bullish" : "Bearish") + "_" + (string)price + "_" + (string)time; + + // + DrawArrow( + 0, + name, + 0, + time, + price, + arrowCode, + anchor, + clr); + } + } + + // + // Draw LC Crosses ... + if (lcDrawCrosses) + { + // + double lcStateValue = GetLCState(bar_index); + bool isLcFastCrossedOverSlow = lcStateValue == X_XCHMA_FAST_CROSSED_OVER_SLOW; + bool isLcFastCrossedUnderSlow = lcStateValue == X_XCHMA_FAST_CROSSED_UNDER_SLOW; + if (isLcFastCrossedOverSlow || isLcFastCrossedUnderSlow) + { + // + bool isBull = isLcFastCrossedOverSlow; + + // + color clr = isBull ? lcFastColor : lcSlowColor; + string name = "LC Fast Cross " + (isBull ? "Over" : "Under") + "_" + (string)time; + + // + DrawVerticalLine( + 0, + name, + 0, + time, + clr); + } + } + + // + // Draw MC Crosses ... + if (mcDrawCrosses) + { + // + double mcStateValue = GetMCState(bar_index); + bool isMcFastCrossedOverSlow = mcStateValue == X_XCHMA_FAST_CROSSED_OVER_SLOW; + bool isMcFastCrossedUnderSlow = mcStateValue == X_XCHMA_FAST_CROSSED_UNDER_SLOW; + if (isMcFastCrossedOverSlow || isMcFastCrossedUnderSlow) + { + // + bool isBull = isMcFastCrossedOverSlow; + + // + color clr = isBull ? mcFastColor : mcSlowColor; + string name = "MC Fast Cross " + (isBull ? "Over" : "Under") + "_" + (string)time; + + // + DrawVerticalLine( + 0, + name, + 0, + time, + clr); + } + } + + // + // Draw SC Crosses ... + if (scDrawCrosses) + { + // + double scStateValue = GetSCState(bar_index); + bool isScFastCrossedOverSlow = scStateValue == X_XCHMA_FAST_CROSSED_OVER_SLOW; + bool isScFastCrossedUnderSlow = scStateValue == X_XCHMA_FAST_CROSSED_UNDER_SLOW; + if (isScFastCrossedOverSlow || isScFastCrossedUnderSlow) + { + // + bool isBull = isScFastCrossedOverSlow; + + // + color clr = isBull ? scFastColor : scSlowColor; + string name = "SC Fast Cross " + (isBull ? "Over" : "Under") + "_" + (string)time; + + // + DrawVerticalLine( + 0, + name, + 0, + time, + clr); + } + } +} +// +// END Functions ... +// diff --git a/Indicators/x-saherelm.xctimer.indicator.mq5 b/Indicators/x-saherelm.xctimer.indicator.mq5 new file mode 100644 index 00000000..6a064212 --- /dev/null +++ b/Indicators/x-saherelm.xctimer.indicator.mq5 @@ -0,0 +1,206 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XCTimer Indicator +// --------------------------------------------- +// Name: XCTimer +// Description: Trend Magic Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XCTimer Indicator" +#property strict + +// +// START Constants ... +// +#define ShortName "XCTimer" +// +// END Constants ... +// + +// +// START Inputs ... +// +input color clr = clrYellow; +input ENUM_BASE_CORNER corner = CORNER_RIGHT_LOWER; +// +// END Inputs ... +// + +// +// START Buffers ... +// +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + CreateIndicatorObject(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Delete Object ... + ObjectDelete(0, ShortName); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + ArraySetAsSeries(time, true); + + // + int m = int(time[0] + PeriodSeconds() - TimeCurrent()); + int s = m % 60; + m = (m - s) / 60; + + // + long mSpread = SymbolInfoInteger(Symbol(), SYMBOL_SPREAD); + + string _sp = "", _m = "", _s = ""; + if (mSpread < 10) + _sp = ".."; + else if (mSpread < 100) + _sp = "."; + if (m < 10) + _m = "0"; + if (s < 10) + _s = "0"; + + // + string objText = "Spread: " + IntegerToString(mSpread) + _sp + " Next Bar in " + _m + IntegerToString(m) + ":" + _s + IntegerToString(s); + + // + ObjectSetInteger(0, ShortName, OBJPROP_COLOR, clr); + ObjectSetString(0, ShortName, OBJPROP_TEXT, objText); + ObjectSetInteger(0, ShortName, OBJPROP_FONTSIZE, 10); + ObjectSetString(0, ShortName, OBJPROP_FONT, "Courier"); + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +void CreateIndicatorObject() +{ + // + ObjectCreate(0, ShortName, OBJ_LABEL, 0, 0, 0); + ObjectSetInteger(0, ShortName, OBJPROP_CORNER, corner); + ObjectSetInteger(0, ShortName, OBJPROP_XDISTANCE, 10); + ObjectSetInteger(0, ShortName, OBJPROP_YDISTANCE, 2); + ENUM_ANCHOR_POINT Anchor = ANCHOR_LEFT_UPPER; + switch (corner) + { + case CORNER_LEFT_UPPER: + Anchor = ANCHOR_LEFT_UPPER; + break; + case CORNER_RIGHT_UPPER: + Anchor = ANCHOR_RIGHT_UPPER; + break; + case CORNER_LEFT_LOWER: + Anchor = ANCHOR_LEFT_LOWER; + break; + case CORNER_RIGHT_LOWER: + Anchor = ANCHOR_RIGHT_LOWER; + break; + } + + // + ObjectSetInteger(0, ShortName, OBJPROP_ANCHOR, Anchor); +} +// +// END Functions ... +// diff --git a/Indicators/x-saherelm.xfi.oscillator.mq5 b/Indicators/x-saherelm.xfi.oscillator.mq5 new file mode 100644 index 00000000..cfd393ca --- /dev/null +++ b/Indicators/x-saherelm.xfi.oscillator.mq5 @@ -0,0 +1,317 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XFI Oscillator +// --------------------------------------------- +// Name: XFI +// Description: Price Momentum Power Detection +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XFI Oscillator" +#property strict + +// +// START Constants ... +// +#define ShortName "XFI" +// +// END Constants ... +// + +// +// START Inputs ... +// +input int length = 18; // Length +input ENUM_MA_METHOD method = MODE_SMA; // MA Method +input ENUM_APPLIED_VOLUME appliedTo = VOLUME_TICK; // Applied To +// +// END Inputs ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Buffers ... +// +#property indicator_separate_window + +// +#property indicator_buffers 2 +#property indicator_plots 1 + +// +// FI Buffer ... +#define fiBufferIndex 0 +#define fiColorBufferIndex 1 + +// +double fiBuffer[]; +double fiColorBuffer[]; + +// +#property indicator_label1 "XFI" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrAqua, clrGray, clrFuchsia +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +int fiHandler = INVALID_HANDLE; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + fiHandler = iForce( + _Symbol, + _Period, + length, + method, + appliedTo); + if (fiHandler == INVALID_HANDLE) + { + // + string message = "Error Initializing Handler ..."; + LogMessage(message); + + // + return INIT_FAILED; + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + IndicatorRelease(fiHandler); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + int maxLength = MathMax(0, length); + + // + // Check Calculated Bars ... + int fiCalculatedBars = BarsCalculated(fiHandler); + if (fiCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedFis = CopyBuffer(fiHandler, 0, 0, limit, fiBuffer); + if (copiedFis <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = 0; i < limit && !IsStopped(); i++) + { + // + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (length >= 2) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + string fiBufferLabel = "XFI " + "(" + (string)length + ")"; + + // + // FI Buffer ... + ArraySetAsSeries(fiBuffer, true); + SetIndexBuffer(fiBufferIndex, fiBuffer, INDICATOR_DATA); + PlotIndexSetString(fiBufferIndex, PLOT_LABEL, fiBufferLabel); + + // + // FI Color Buffer ... + ArraySetAsSeries(fiColorBuffer, true); + SetIndexBuffer(fiColorBufferIndex, fiColorBuffer, INDICATOR_COLOR_INDEX); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + double iValue = fiBuffer[bar_index]; + + // + double iColorIndex = + iValue > 0 ? 0 : iValue < 0 ? 2 + : 1; + + // + // Set Buffer Color Index ... + fiColorBuffer[bar_index] = iColorIndex; +} +// +// END Functions ... +// diff --git a/Indicators/x-saherelm.xlh.indicator.mq5 b/Indicators/x-saherelm.xlh.indicator.mq5 new file mode 100644 index 00000000..4dfc64e2 --- /dev/null +++ b/Indicators/x-saherelm.xlh.indicator.mq5 @@ -0,0 +1,346 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XLH Indicator +// --------------------------------------------- +// Name: XLH +// Description: Moving Average Indicator +// Market Analysor ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XLH Indicator" +#property strict + +// +// START Constants ... +// +#define ShortName "XLH" +// +// END Constants ... +// + +// +// START Inputs ... +// +input int length = 14; // Length +input ENUM_SERIESMODE hhMode = MODE_HIGH; // Highest High Calculation Method +input ENUM_SERIESMODE llMode = MODE_LOW; // Lowest Low Calculation Method +// +// END Inputs ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 3 +#property indicator_plots 3 + +// +// HH Buffer ... +#define hhBufferIndex 0 + +// +double hhBuffer[]; + +// +#property indicator_label1 "XLH HH" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrAqua +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +// LL Buffer ... +#define llBufferIndex 1 + +// +double llBuffer[]; + +// +#property indicator_label2 "XLH LL" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrFuchsia +#property indicator_style2 STYLE_DOT +#property indicator_width2 1 + +// +// Signal Buffer ... +#define signalBufferIndex 2 + +// +double signalBuffer[]; + +// +#property indicator_label3 "XLH S" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrGold +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + int maxLength = MathMax(0, length); + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (length >= 2) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // HH Buffer ... + string hhBufferLabel = ShortName + " HH " + "(" + (string)length + ")"; + ArraySetAsSeries(hhBuffer, true); + SetIndexBuffer(hhBufferIndex, hhBuffer, INDICATOR_DATA); + PlotIndexSetInteger(hhBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(hhBufferIndex, PLOT_LABEL, hhBufferLabel); + + // + // LL Buffer ... + string llBufferLabel = ShortName + " LL " + "(" + (string)length + ")"; + ArraySetAsSeries(llBuffer, true); + SetIndexBuffer(llBufferIndex, llBuffer, INDICATOR_DATA); + PlotIndexSetInteger(llBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(llBufferIndex, PLOT_LABEL, llBufferLabel); + + // + // Signal Buffer ... + string signalBufferLabel = ShortName + " S " + "(" + (string)length + ")"; + ArraySetAsSeries(signalBuffer, true); + SetIndexBuffer(signalBufferIndex, signalBuffer, INDICATOR_DATA); + PlotIndexSetInteger(signalBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(signalBufferIndex, PLOT_LABEL, signalBufferLabel); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, ""); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index // Selected Bar Index +) +{ + // + // Calculate Threshold ... + // + // HH Buffer ... + int hhIndex = iHighest( + _Symbol, + _Period, + hhMode, + length, + bar_index); + double hhValue = GetAppliedPrice( + hhIndex, + hhMode); + + // + hhBuffer[bar_index] = hhValue; + + // + // LL Buffer ... + int llIndex = iLowest( + _Symbol, + _Period, + llMode, + length, + bar_index); + double llValue = GetAppliedPrice( + llIndex, + llMode); + + // + llBuffer[bar_index] = llValue; + + // + XOHCL c = GetCandle(bar_index); + double lhDiff = hhValue - llValue; + double signalValue = (lhDiff / 2); + + // + signalBuffer[bar_index] = (hhValue - signalValue); +} +// +// END Functions ... +// diff --git a/Indicators/x-saherelm.xobd.indicator.mq5 b/Indicators/x-saherelm.xobd.indicator.mq5 new file mode 100644 index 00000000..4ac05cf6 --- /dev/null +++ b/Indicators/x-saherelm.xobd.indicator.mq5 @@ -0,0 +1,390 @@ +///////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 OrderBlock Detector Indicator +// ----------------------------------------------------- +// Name: XOBD +// Description: detect Order Blocks based on Swings ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XOBD Indicator" +#property strict + +// +// START Constants ... +// +#define ShortName "XOBD" +// +// END Constants ... +// + +// +// START Inputs ... +// +// +input int length = 5; // Swing Length + +// +input uchar swingHighArrowCode = 108; // Swing High Arrow Code +input color swingHighArrowColor = clrMagenta; // Swing High Arrow Color + +// +input uchar swingLowArrowCode = 108; // Swing Low Arrow Code +input color swingLowArrowColor = clrAqua; // Swing Low Arrow Color +// +// END Inputs ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Include Common and Models Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// Include Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5" + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 1 +#property indicator_plots 0 + +// +#define swingBufferIndex 0 +double swingBuffer[]; +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + drawPrefix = ShortName; + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + OnDeinitDrawLibrary(); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + int maxLength = MathMax(0, length * 3); + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + // Main Loop ... + for (int i = limit; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (length >= 2) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + ArraySetAsSeries(swingBuffer, true); + SetIndexBuffer(swingBufferIndex, swingBuffer, INDICATOR_CALCULATIONS); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, " ", "( ", length, " )"); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers(int bar_index) +{ + // + // GetCandleSwing(bar_index); + ENUM_X_SWING_TYPE type = X_NO_SWING; + + // + // Try To Detect Order Blocks ... + bool isSwingLow = false; + bool isSwingHigh = false; + + // + // Reading Candles Data ... + XOHCL candles[]; + for (int i = bar_index; i < bar_index + ((length * 2) + 2); i++) + { + // + XOHCL iCandle = GetCandle( + _Symbol, + _Period, + i); + + // + Add( + iCandle, + candles); + } + + // + // Swing Low ... + isSwingLow = + // + candles[1].close > candles[2].close && + candles[2].close > candles[3].close && + // + candles[3].close < candles[4].close && + // + candles[5].close > candles[4].close && + candles[6].close > candles[5].close + // + ; + + // + if (isSwingLow) + { + type = X_SWING_LOW; + } + + // + if (!isSwingLow) + { + // + // Swing High ... + isSwingHigh = + // + candles[1].close < candles[2].close && + candles[2].close < candles[3].close && + // + candles[3].close > candles[4].close && + // + candles[5].close < candles[4].close && + candles[6].close < candles[5].close + // + ; + + // + if (isSwingHigh) + { + type = X_SWING_HIGH; + } + } + + // + switch (type) + { + // + // Swing High ... + case X_SWING_HIGH: + // + swingBuffer[bar_index] = type; + DrawSwingArrow(1, bar_index); + break; + + // + // Swinmg Low ... + case X_SWING_LOW: + // + swingBuffer[bar_index] = type; + DrawSwingArrow(0, bar_index); + break; + + // + // No Swing ... + default: + case X_NO_SWING: + // + swingBuffer[bar_index] = 0; + break; + } +} + +// +// Draw a Swing Arrow Shape ... +void DrawSwingArrow( + int type, // Swing Type: 0 - Low / 1 - High ... + int bar_index) +{ + // + bool isSwingHigh = type == 1; + XOHCL candle = GetCandle(bar_index + 3); + double arrowDistanceInPoint = 0; + + // + // Define Required Object Properties fro Draw an Arrow ... + datetime time = iTime(_Symbol, _Period, bar_index + 3); + double purePrice = isSwingHigh ? candle.high : candle.low; + color clr = isSwingHigh ? swingHighArrowColor : swingLowArrowColor; + ENUM_ARROW_ANCHOR anchor = isSwingHigh ? ANCHOR_BOTTOM : ANCHOR_TOP; + uchar arrowCode = uchar(isSwingHigh ? swingHighArrowCode : swingLowArrowCode); + double price = isSwingHigh ? purePrice + arrowDistanceInPoint : purePrice - arrowDistanceInPoint; + string name = "Swing " + (isSwingHigh ? "High" : "Low") + "_" + (string)time + "_" + (string)purePrice; + + // + // Draw desired Arrow ... + DrawArrow( + 0, + name, + 0, + time, + price, + arrowCode, + anchor, + clr); +} +// +// END Functions ... +// diff --git a/Indicators/x-saherelm.xrsi.oscillator.mq5 b/Indicators/x-saherelm.xrsi.oscillator.mq5 new file mode 100644 index 00000000..5659e07d --- /dev/null +++ b/Indicators/x-saherelm.xrsi.oscillator.mq5 @@ -0,0 +1,397 @@ +///////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 OrderBlock Detector Oscillator +// ------------------------------------------------------ +// Name: XRSI +// Description: detect market conditions based on RSI ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XRSI Oscillator" +#property strict + +// +// START Constants ... +// + +#define ShortName "XRSI" + +// +// END Constants ... +// + +// +// START Inputs ... +// + +// +input group "Market"; +input int length = 14; // Market Length +input ENUM_APPLIED_PRICE appliedTo = PRICE_CLOSE; // Applied To + +// +input group "Short Entry"; +input double shortEntryValue = 70; // Short Entry Level +input color shortEntryColor = clrRed; // Short Entry Level Color +input ENUM_LINE_STYLE shortEntryLineStyle = STYLE_DOT; // Short Entry Style + +// +input group "Short Exit"; +input double shortExitValue = 40; // Short Exit Level +input color shortExitColor = clrRed; // Short Exit Level Color +input ENUM_LINE_STYLE shortExitLineStyle = STYLE_DOT; // Short Exit Style + +// +input group "Long Entry"; +input double longEntryValue = 30; // Long Entry Level +input color longEntryColor = clrRed; // Long Entry Level Color +input ENUM_LINE_STYLE longEntryLineStyle = STYLE_DOT; // Long Entry Style + +// +input group "Long Exit"; +input double longExitValue = 60; // Long Exit Level +input color longExitColor = clrRed; // Long Exit Level Color +input ENUM_LINE_STYLE longExitLineStyle = STYLE_DOT; // Long Exit Style + +// +// START Inputs ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Include Common and Models Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Buffers ... +// + +// +#property indicator_separate_window +#property indicator_buffers 2 +#property indicator_plots 1 + +// +#define rsiBufferIndex 0 +#define rsiColorBufferIndex 1 + +// +double rsiBuffer[]; +double rsiColorBuffer[]; + +// +#property indicator_label1 "XRSI" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrAqua, clrGray, clrFuchsia +#property indicator_style1 STYLE_DOT +#property indicator_width1 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +int rsiHandler = INVALID_HANDLE; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + rsiHandler = iRSI( + _Symbol, + _Period, + length, + appliedTo); + if (rsiHandler == INVALID_HANDLE) + { + return INIT_FAILED; + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + + // + IndicatorRelease(rsiHandler); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + int maxLength = MathMax(0, length); + + // + int rsiCalculatedBars = BarsCalculated(rsiHandler); + if (rsiCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + int rsiCopiedItems = CopyBuffer(rsiHandler, 0, 0, limit, rsiBuffer); + if (rsiCopiedItems <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (length >= 2) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // RSI ... + string rsiBufferLabel = ShortName + " (" + (string)length + ")"; + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_DATA); + PlotIndexSetInteger(rsiBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(rsiBufferIndex, PLOT_LABEL, rsiBufferLabel); + + // + // RSI Color Buffer ... + ArraySetAsSeries(rsiColorBuffer, true); + SetIndexBuffer(rsiColorBufferIndex, rsiColorBuffer, INDICATOR_COLOR_INDEX); + + // + // Set Indicator Levels here ... + // OB, ExitLong, ExitShort, OS ... + IndicatorSetInteger(INDICATOR_LEVELS, 4); + + // + // SHORTENTRY ... + IndicatorSetDouble(INDICATOR_LEVELVALUE, 0, shortEntryValue); + IndicatorSetInteger(INDICATOR_LEVELCOLOR, 0, shortEntryColor); + IndicatorSetInteger(INDICATOR_LEVELSTYLE, 0, shortEntryLineStyle); + IndicatorSetString(INDICATOR_LEVELTEXT, 0, "Short Entry"); + + // + // LONGEXIT ... + IndicatorSetDouble(INDICATOR_LEVELVALUE, 1, longExitValue); + IndicatorSetInteger(INDICATOR_LEVELCOLOR, 1, longExitColor); + IndicatorSetInteger(INDICATOR_LEVELSTYLE, 1, shortExitLineStyle); + IndicatorSetString(INDICATOR_LEVELTEXT, 1, "Long Exit"); + + // + // SHORTEXIT ... + IndicatorSetDouble(INDICATOR_LEVELVALUE, 2, shortExitValue); + IndicatorSetInteger(INDICATOR_LEVELCOLOR, 2, shortExitColor); + IndicatorSetInteger(INDICATOR_LEVELSTYLE, 2, longEntryLineStyle); + IndicatorSetString(INDICATOR_LEVELTEXT, 2, "Short Exit"); + + // + // LONGENTRY ... + IndicatorSetDouble(INDICATOR_LEVELVALUE, 3, longEntryValue); + IndicatorSetInteger(INDICATOR_LEVELCOLOR, 3, longEntryColor); + IndicatorSetInteger(INDICATOR_LEVELSTYLE, 3, longExitLineStyle); + IndicatorSetString(INDICATOR_LEVELTEXT, 3, "Long Entry"); + + // + // Set Maximum and Minimum for subwindow + IndicatorSetInteger(INDICATOR_DIGITS, 2); + IndicatorSetDouble(INDICATOR_MINIMUM, 0); + IndicatorSetDouble(INDICATOR_MAXIMUM, 100); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, " ", "( ", length, " )"); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers(int bar_index) +{ + // + double iValue = rsiBuffer[bar_index]; + + // + double iColorIndex = 0; + + // + if ( + iValue >= shortEntryValue || + iValue <= longEntryValue || + (iValue < longExitValue && + iValue > shortExitValue)) + { + iColorIndex = 0; + } + else if ( + iValue <= shortEntryValue && + iValue >= longExitValue) + { + iColorIndex = 2; + } + else if ( + iValue < shortExitValue && + iValue > longEntryValue) + { + iColorIndex = 1; + } + + // + rsiColorBuffer[bar_index] = iColorIndex; +} + +// +// END Functions ... +// diff --git a/Indicators/x-saherelm.xtd.oscillator.mq5 b/Indicators/x-saherelm.xtd.oscillator.mq5 new file mode 100644 index 00000000..5f46d187 --- /dev/null +++ b/Indicators/x-saherelm.xtd.oscillator.mq5 @@ -0,0 +1,465 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Trend Detector Oscillator +// -------------------------------------------------- +// Name: XTD +// Description: trend detecting in both sides ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XTD Oscillator" +#property strict + +// +// START Constants ... +// +#define ShortName "XTD" + +// +// XTD Oscillator States ... +enum ENUM_X_XTD_STATES +{ + X_XTD_BULLISH_CROSSED_OVER_BEARISH = 2, + X_XTD_BULLISH_OVER_BEARISH = 1, + X_XTD_NEUTURAL = 0, + X_XTD_BULLISH_UNDER_BEARISH = -1, + X_XTD_BULLISH_CROSSED_UNDER_BEARISH = -2 +}; +// +// END Constants ... +// + +// +// Include Models Library ... +#include "../Libraries/x-saherelm.models.lib.mq5" + +// +// START Inputs ... +// +input int length = 14; // Market Length +input bool drawCrosses = true; // Draw Cross Arrows + +// +// Bullish ... +input uchar bullishArrowCode = 228; // Cross Over Arrow Code +input color bullishArrowColor = clrAqua; // Cross Over Arrow Color + +// +// Bearish ... +input uchar bearishArrowCode = 230; // Cross Under Arrow Code +input color bearishArrowColor = clrMagenta; // Cross Under Arrow Color +// +// END Inputs ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5"; + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5"; + +// +// Includes Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5"; + +// +// START Buffers ... +// +#property indicator_separate_window + +// +#property indicator_buffers 3 +#property indicator_plots 3 + +// +#define bullishBufferIndex 0 +#define bearishBufferIndex 1 +#define signalBufferIndex 2 + +// +double bullishBuffer[]; +double bearishBuffer[]; +double signalBuffer[]; + +// +#property indicator_label1 "XBullPower" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrLime +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +#property indicator_label2 "XBearPower" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrRed +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +#property indicator_label3 "XSignal" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrGold +#property indicator_style3 STYLE_DOT +#property indicator_width3 1 +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +int xtdBullishCandleCount = 0; +int xtdBearishCandleCount = 0; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + drawPrefix = ShortName; + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... + + // + // De Init Draw Library ... + OnDeinitDrawLibrary(); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + int maxLength = MathMax(0, length); + + // + limit = prev_calculated < maxLength ? rates_total - (maxLength + 1) : rates_total - prev_calculated; + + // + // Main Loop ... + for (int i = limit; i >= 0 && !IsStopped(); i--) + { + // + CalculateBuffers(i, close); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (length >= 5) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + // Bullish Buffer ... + string bullishBufferLabel = ShortName + "BullPow " + "(" + (string)length + ")"; + ArraySetAsSeries(bullishBuffer, true); + SetIndexBuffer(bullishBufferIndex, bullishBuffer, INDICATOR_DATA); + PlotIndexSetInteger(bullishBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(bullishBufferIndex, PLOT_LABEL, bullishBufferLabel); + + // + // Bearish Buffer ... + string bearishBufferLabel = ShortName + "BearPow " + "(" + (string)length + ")"; + ArraySetAsSeries(bearishBuffer, true); + SetIndexBuffer(bearishBufferIndex, bearishBuffer, INDICATOR_DATA); + PlotIndexSetInteger(bearishBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(bearishBufferIndex, PLOT_LABEL, bearishBufferLabel); + + // + // Signal Buffer ... + string signalBufferLabel = ShortName + "Signal " + "(" + (string)length + ")"; + ArraySetAsSeries(signalBuffer, true); + SetIndexBuffer(signalBufferIndex, signalBuffer, INDICATOR_DATA); + PlotIndexSetInteger(signalBufferIndex, PLOT_DRAW_BEGIN, length); + PlotIndexSetString(signalBufferIndex, PLOT_LABEL, signalBufferLabel); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, " ", "( ", length, " )"); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers( + int bar_index, + const double &close[]) +{ + // + // Reset Global Counters ... + xtdBullishCandleCount = 0; + xtdBearishCandleCount = 0; + + // + // Loop through Closes ... + for (int i = bar_index; i <= bar_index + length; i++) + { + for (int j = i + 1; j <= bar_index + length; j++) + { + // + if (close[i] > close[j]) + { + xtdBullishCandleCount++; + } + + // + if (close[i] < close[j]) + { + xtdBearishCandleCount++; + } + } + } + + // + // Bullish Power Buffer ... + bullishBuffer[bar_index] = MathAbs(xtdBullishCandleCount); + + // + // Bearish Power Buffer ... + bearishBuffer[bar_index] = MathAbs(xtdBearishCandleCount); + + // + // Signal Buffer ... + signalBuffer[bar_index] = bullishBuffer[bar_index] - bearishBuffer[bar_index]; + + // + // Check and Draw Crosses if it's Specified ... + if (drawCrosses) + { + DrawCrosses(bar_index); + } +} + +// +// +double GetState( + int bar_index // Specified Bar Index +) +{ + // + // Check Cross Points ... + // bullishCrossedOverBearish = 2; + // bullishOverBearish = 1; + // bullishCrossedUnderBearish = -2; + // bullishUnderBearish = -1; + // OtherWise = 0; + bool isBullishCrossedOverBearish = IsCrossOver( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishCrossedUnderBearish = IsCrossUnder( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishOverBearish = IsOver( + bullishBuffer, + bearishBuffer, + bar_index); + bool isBullishUnderBearish = IsUnder( + bullishBuffer, + bearishBuffer, + bar_index); + + // + double result = X_XTD_NEUTURAL; + if (isBullishCrossedOverBearish) + { + result = X_XTD_BULLISH_CROSSED_OVER_BEARISH; + } + else if (isBullishCrossedUnderBearish) + { + result = X_XTD_BULLISH_CROSSED_UNDER_BEARISH; + } + else if (isBullishOverBearish) + { + result = X_XTD_BULLISH_OVER_BEARISH; + } + else if (isBullishUnderBearish) + { + result = X_XTD_BULLISH_UNDER_BEARISH; + } + else + { + result = X_XTD_NEUTURAL; + } + + // + return result; +} + +// +// Draw Crosses ... +void DrawCrosses( + int bar_index // the bars which required to draw cross arrow on it ... +) +{ + // + double stateValue = GetState(bar_index); + + // + bool isOver = stateValue == 2; + double low = iLow(_Symbol, _Period, bar_index); + double high = iHigh(_Symbol, _Period, bar_index); + + // + double price = isOver ? low : high; + datetime time = iTime(_Symbol, _Period, bar_index); + ENUM_ARROW_ANCHOR anchor = isOver ? ANCHOR_TOP : ANCHOR_BOTTOM; + uchar arrowCode = isOver ? bullishArrowCode : bearishArrowCode; + color arrowColor = isOver ? bullishArrowColor : bearishArrowColor; + string crossName = "Trend " + (isOver ? "Up" : "Down") + "_" + (string)time + "_" + (string)price; + + // + DrawArrow( + 0, + crossName, + 0, + time, + price, + arrowCode, + anchor, + arrowColor); +} +// +// END Functions ... +// diff --git a/Indicators/x-saherelm.xtm.indicator.mq5 b/Indicators/x-saherelm.xtm.indicator.mq5 new file mode 100644 index 00000000..eac88e0a --- /dev/null +++ b/Indicators/x-saherelm.xtm.indicator.mq5 @@ -0,0 +1,349 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Candle Indicator +// --------------------------------------------- +// Name: XTM +// Description: Trend Magic Indicator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XTM Indicator" +#property strict + +// +// START Constants ... +// +#define ShortName "XTM" + +// +// XTM Indicator States ... +enum ENUM_X_XTM_STATES +{ + X_XTM_BULLISH = 1, + X_XTM_BEARISH = -1, + X_XTM_NEUTURAL = 0, +}; +// +// END Constants ... +// + +// +// START Inputs ... +// +input int maPeriod = 14; // Period +input int maShift = 0; // Shift +input ENUM_MA_METHOD maMethod = MODE_SMA; // Method +input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // Applied To +// +// END Inputs ... +// + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Buffers ... +// +#property indicator_chart_window + +// +#property indicator_buffers 3 +#property indicator_plots 1 + +// +// maBuffer ... +#define maBufferIndex 0 +#define maColorBufferIndex 1 +#define stateBufferIndex 2 + +double maBuffer[]; +double maColorBuffer[]; +double stateBuffer[]; + +#property indicator_label1 "XTM" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 clrLime, clrGray, clrRed +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +int maHandler = INVALID_HANDLE; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + + // + // Initializing MA Handler ... + maHandler = iMA( + _Symbol, + _Period, + maPeriod, + maShift, + maMethod, + maAppliedTo); + if (maHandler == INVALID_HANDLE) + { + // + string message = "Error Initializing Ma Handler ..."; + LogMessage(message); + + // + return INIT_FAILED; + } + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Indicator ShortName ... + SetIndicatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function + // REASON_REMOVE 1 Program removed from a chart + // REASON_RECOMPILE 2 Program recompiled + // REASON_CHARTCHANGE 3 A symbol or a chart period is changed + // REASON_CHARTCLOSE 4 Chart closed + // REASON_PARAMETERS 5 Inputs changed by a user + // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings + // REASON_TEMPLATE 7 Another chart template applied + // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value + // REASON_CLOSE 9 Terminal closed + + // + // Here we can handle De Initialization Reasons ... +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + int maxLength = MathMax(0, maPeriod); + + // + // Check Calculated Bars ... + int maCalculatedBars = BarsCalculated(maHandler); + if (maCalculatedBars < maxLength) + { + return prev_calculated; + } + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Buffers Copy ... + int copiedMas = CopyBuffer(maHandler, 0, 0, limit, maBuffer); + if (copiedMas <= 0) + { + return prev_calculated; + } + + // + // Main Loop ... + for (int i = limit - 1; i >= 0 && !IsStopped(); i--) + { + // + // Do Buffers Calculation ... + CalculateBuffers(i); + } + + // + return rates_total; +} +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = false; + + // + // Validate Args ... + if (maPeriod >= 2) + { + result = true; + } + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + string maBufferLabel = "XTM " + "(" + (string)maPeriod + ")"; + + // + // Ma Buffer ... + ArraySetAsSeries(maBuffer, true); + SetIndexBuffer(maBufferIndex, maBuffer, INDICATOR_DATA); + PlotIndexSetString(maBufferIndex, PLOT_LABEL, maBufferLabel); + + // + // Ma Color Buffer ... + ArraySetAsSeries(maColorBuffer, true); + SetIndexBuffer(maColorBufferIndex, maColorBuffer, INDICATOR_COLOR_INDEX); + + // + // State Buffer ... + ArraySetAsSeries(stateBuffer, true); + SetIndexBuffer(stateBufferIndex, stateBuffer, INDICATOR_CALCULATIONS); +} + +// +// Set Indicator Short Name and also we can define Buffers Labels ... +void SetIndicatorName() +{ + // + string indicatorShortName = ""; + StringConcatenate(indicatorShortName, ShortName, " ", "(", maPeriod, ")"); + + // + IndicatorSetString(INDICATOR_SHORTNAME, indicatorShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers(int bar_index) +{ + // + // Requirements ... + XOHCL candle = GetCandle(bar_index); + + // + double maValue = maBuffer[bar_index]; + + // + double lineColorIndex = + maValue < candle.low ? 0 : maValue > candle.high ? 2 + : 1; + + // + // Define State Value ... + // lineColorIndex == 0 => Bullish => 1; + // lineColorIndex == 1 => Neutural => 0; + // lineColorIndex == 2 => Bearish => -1; + double stateValue = + lineColorIndex == 0 ? X_XTM_BULLISH : lineColorIndex == 2 ? X_XTM_BEARISH + : X_XTM_NEUTURAL; + + // + // Set Ma Buffer Color Index ... + maColorBuffer[bar_index] = lineColorIndex; + + // + // Set State Buffer Value ... + stateBuffer[bar_index] = stateValue; +} + +// +// END Functions ... +// diff --git a/Indicators/x-saherelm.xts.oscillator.mq5 b/Indicators/x-saherelm.xts.oscillator.mq5 new file mode 100644 index 00000000..46e9fbf9 --- /dev/null +++ b/Indicators/x-saherelm.xts.oscillator.mq5 @@ -0,0 +1,558 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 XTS Oscillator +// --------------------------------------------- +// Name: XTS +// Description: Time Sections Oscillator ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XTS Oscillator" +#property strict + +// +// START Constants ... +// + +#define ShortName "XTS" + +enum ENUM_X_PERIOD_METHOD +{ + // + X_PERIOD_NOTHING, + // + X_PERIOD_AUTO, + // + X_PERIOD_MANUALLY +}; + +// +// XTS Oscillator States ... + +// +// END Constants ... +// + +// +// START Inputs ... +// +input group "Current Period"; +input ENUM_APPLIED_PRICE currentAppliedTo = PRICE_CLOSE; // Current Applied To +// +input group "Nearest Period"; +input ENUM_X_PERIOD_METHOD nearestMethod = X_PERIOD_AUTO; // How to Find Nearest Period +input ENUM_TIMEFRAMES nearestPeriod = NULL; // Nearest Time Frame +input ENUM_APPLIED_PRICE nearestAppliedTo = PRICE_CLOSE; // Nearest Applied To +// +input group "Mediest Period"; +input ENUM_X_PERIOD_METHOD mediestMethod = X_PERIOD_AUTO; // How to Find Mediest Period +input ENUM_TIMEFRAMES mediestPeriod = NULL; // Mediest Time Frame +input ENUM_APPLIED_PRICE mediestAppliedTo = PRICE_CLOSE; // Mediest Applied To +// +input group "Farest Period"; +input ENUM_X_PERIOD_METHOD farestMethod = X_PERIOD_AUTO; // How to Find Farest Period +input ENUM_TIMEFRAMES farestPeriod = NULL; // Farest Time Frame +input ENUM_APPLIED_PRICE farestAppliedTo = PRICE_CLOSE; // Farest Applied To + +// +// Includes Logging Library ... +#include "../Libraries/x-saherelm.log.lib.mq5" + +// +// Includes Draw Library ... +#include "../Libraries/x-saherelm.draw.lib.mq5" + +// +// Includes Common Library ... +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// START Buffers ... +// +#property indicator_separate_window + +// +#property indicator_buffers 4 +#property indicator_plots 4 + +// +// Current ... +#define currentBufferIndex 0 + +double currentBuffer[]; + +#property indicator_label1 "XTS C" +#property indicator_type1 DRAW_LINE +#property indicator_color1 clrBrown +#property indicator_style1 STYLE_SOLID +#property indicator_width1 1 + +// +// Nearest ... +#define nearestBufferIndex 1 + +double nearestBuffer[]; + +#property indicator_label2 "XTS N" +#property indicator_type2 DRAW_LINE +#property indicator_color2 clrAqua +#property indicator_style2 STYLE_SOLID +#property indicator_width2 1 + +// +// Mediest ... +#define mediestBufferIndex 2 + +double mediestBuffer[]; + +#property indicator_label3 "XTS M" +#property indicator_type3 DRAW_LINE +#property indicator_color3 clrLime +#property indicator_style3 STYLE_SOLID +#property indicator_width3 1 + +// +// Farest ... +#define farestBufferIndex 3 + +double farestBuffer[]; + +#property indicator_label4 "XTS F" +#property indicator_type4 DRAW_LINE +#property indicator_color4 clrLightBlue +#property indicator_style4 STYLE_SOLID +#property indicator_width4 1 + +// +// END Buffers ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +ENUM_TIMEFRAMES mNearestPeriod = NULL; +ENUM_TIMEFRAMES mMediestPeriod = NULL; +ENUM_TIMEFRAMES mFarestPeriod = NULL; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Event Handlers ... +// + +// +// Initialization ... +int OnInit() +{ + // + // Validate Inputs ... + if (!ValidateInputs()) + { + return INIT_PARAMETERS_INCORRECT; + } + + // + logTag = ShortName; + drawPrefix = ShortName; + + // + // Define Index Buffers ... + DefineBuffers(); + + // + // Set Oscillator ShortName ... + SetOscillatorName(); + + // + // Init Succeed ... + return INIT_SUCCEEDED; +} + +// +// DeInitialization ... +void OnDeinit(const int reason) +{ + // + OnDeinitDrawLibrary(); + + // + Comment(""); +} + +// +// Calculations ... +// +// Calculating what we want ... +int OnCalculate( + // + // total Candles on chart ... + const int rates_total, + // + // total calculated Candles on charts ... + const int prev_calculated, + // + // history of Candles Open Time ... + const datetime &time[], + // + // history of Candles Open Price ... + const double &open[], + // + // history of Candles High Price ... + const double &high[], + // + // history of Candles Low Price ... + const double &low[], + // + // history of Candles Close Price ... + const double &close[], + // + // history of Tick Volumes on Candle ... + const long &tick_volume[], + // + // history of Trade Volumes ... + const long &volume[], + // + // history of Candles Spread Price ... + const int &spread[]) +{ + // + // Prepare Buffers ... + ArraySetAsSeries(time, true); + ArraySetAsSeries(open, true); + ArraySetAsSeries(high, true); + ArraySetAsSeries(low, true); + ArraySetAsSeries(close, true); + ArraySetAsSeries(tick_volume, true); + ArraySetAsSeries(volume, true); + ArraySetAsSeries(spread, true); + + // + // this counts Available Bars ... + int limit; + + // + // because in some cases we may have more than one input for + // calculation and we must prevent any calculation + // untill we pass the biggest input length, here we get max Input length + // and then wait until pass it ... + int maxLength = 30; + + // + limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; + + // + // Main Loop ... + for (int i = 0; i < limit && !IsStopped(); i++) + { + // + // Do Buffers Calculation ... + CalculateBuffers(i); + } + + // + return rates_total; +} + +// +// END Event Handlers ... +// + +// +// START Functions ... +// +// +// Validate Input Args for Initialization ... +bool ValidateInputs() +{ + // + bool result = true; + + // + return result; +} + +// +// Define Indexes and Styles ... +void DefineBuffers() +{ + // + int maxLength = 30; + + // + // Current ... + ArraySetAsSeries(currentBuffer, true); + SetIndexBuffer(currentBufferIndex, currentBuffer, INDICATOR_DATA); + PlotIndexSetInteger(currentBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // Nearest ... + ArraySetAsSeries(nearestBuffer, true); + SetIndexBuffer(nearestBufferIndex, nearestBuffer, INDICATOR_DATA); + PlotIndexSetInteger(nearestBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // Mediest ... + ArraySetAsSeries(mediestBuffer, true); + SetIndexBuffer(mediestBufferIndex, mediestBuffer, INDICATOR_DATA); + PlotIndexSetInteger(mediestBufferIndex, PLOT_DRAW_BEGIN, maxLength); + + // + // Farest ... + ArraySetAsSeries(farestBuffer, true); + SetIndexBuffer(farestBufferIndex, farestBuffer, INDICATOR_DATA); + PlotIndexSetInteger(farestBufferIndex, PLOT_DRAW_BEGIN, maxLength); +} + +// +// Set Oscillator Short Name and also we can define Buffers Labels ... +void SetOscillatorName() +{ + IndicatorSetString(INDICATOR_SHORTNAME, ShortName); +} + +// +// Calculate Buffers ... +void CalculateBuffers(int bar_index) +{ + // + // Current ... + CalculateCurrent(bar_index); + + // + // Nearest ... + CalculateNearest(bar_index); + + // + // Mediest ... + CalculateMediest(bar_index); + + // + // Farest ... + CalculateFarest(bar_index); + + // + // Commenting ... + string comment = GenerateDescriptionComment(); + Comment(comment); +} + +// +// Current ... +void CalculateCurrent(int bar_index) +{ + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index); + datetime startTime = GetPeriodStartTime( + _Symbol, + _Period, + barTime); + int startBarIndex = iBarShift( + _Symbol, + _Period, + startTime); + + // + XOHCL c = GetCandle( + _Symbol, + _Period, + startBarIndex); + + // + double value = GetAppliedPrice( + c, + currentAppliedTo); + + // + currentBuffer[bar_index] = value; +} + +// +// Nearest ... +void CalculateNearest(int bar_index) +{ + // + if (mNearestPeriod == NULL) + { + // + switch (nearestMethod) + { + // + case X_PERIOD_AUTO: + mNearestPeriod = GetNearestTimeFrame(_Period); + break; + + // + case X_PERIOD_NOTHING: + case X_PERIOD_MANUALLY: + mNearestPeriod = nearestPeriod; + break; + } + } + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index); + datetime startTime = GetPeriodStartTime( + _Symbol, + mNearestPeriod, + barTime); + int startBarIndex = iBarShift( + _Symbol, + _Period, + startTime); + + // + XOHCL c = GetCandle( + _Symbol, + _Period, + startBarIndex); + + // + double value = GetAppliedPrice( + c, + nearestAppliedTo); + + // + nearestBuffer[bar_index] = value; +} + +// +// Mediest ... +void CalculateMediest(int bar_index) +{ + // + if (mMediestPeriod == NULL) + { + // + switch (mediestMethod) + { + // + case X_PERIOD_AUTO: + mMediestPeriod = GetMediestTimeFrame(_Period); + break; + + // + case X_PERIOD_NOTHING: + case X_PERIOD_MANUALLY: + mMediestPeriod = mediestPeriod; + break; + } + } + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index); + datetime startTime = GetPeriodStartTime( + _Symbol, + mMediestPeriod, + barTime); + int startBarIndex = iBarShift( + _Symbol, + _Period, + startTime); + + // + XOHCL c = GetCandle( + _Symbol, + _Period, + startBarIndex); + + // + double value = GetAppliedPrice( + c, + mediestAppliedTo); + + // + mediestBuffer[bar_index] = value; +} + +// +// Farest ... +void CalculateFarest(int bar_index) +{ + // + if (mFarestPeriod == NULL) + { + // + switch (farestMethod) + { + // + case X_PERIOD_AUTO: + mFarestPeriod = GetFarestTimeFrame(_Period); + break; + + // + case X_PERIOD_NOTHING: + case X_PERIOD_MANUALLY: + mFarestPeriod = farestPeriod; + break; + } + } + + // + datetime barTime = iTime( + _Symbol, + _Period, + bar_index); + datetime startTime = GetPeriodStartTime( + _Symbol, + mFarestPeriod, + barTime); + int startBarIndex = iBarShift( + _Symbol, + _Period, + startTime); + + // + XOHCL c = GetCandle( + _Symbol, + _Period, + startBarIndex); + + // + double value = GetAppliedPrice( + c, + farestAppliedTo); + + // + farestBuffer[bar_index] = value; +} + +// +// Generate Comment ... +string GenerateDescriptionComment() +{ + // + string result = ""; + + // + result += "Nearest : " + EnumToString(mNearestPeriod) + "\n"; + result += "Mediest : " + EnumToString(mMediestPeriod) + "\n"; + result += "Farest : " + EnumToString(mFarestPeriod) + "\n"; + + // + return result; +} +// +// END Functions ... +// diff --git a/Libraries/x-saherelm.alert.lib.mq5 b/Libraries/x-saherelm.alert.lib.mq5 new file mode 100644 index 00000000..429d830e --- /dev/null +++ b/Libraries/x-saherelm.alert.lib.mq5 @@ -0,0 +1,187 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Alert Library +// -------------------------------------- +// Name: XAlert +// Description: provides Alerts abilities ... +// +// +// 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 ... +// +input group "Alerts"; +input bool enableAlerts = true; // Enable Alerts +input bool logAlerts = true; // Log Alerts +input bool terminalAlerts = false; // Terminal Alerts +input bool mailAlerts = false; // Mail Alerts +input bool pushAlerts = false; // Push Alerts +// +// END Inputs ... +// + +// +#include "x-saherelm.log.lib.mq5" + +// +// START Global Definitions: Variables, Properties and etc ... +// +string alertPrefix = "X-Alert"; +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Provided Functions ... +// +// +// Initial Library if required ... +bool OnInInitAlertLibrary() +{ + return false; +} + +// +// DeInitial Library if required ... +void OnDeinitAlertLibrary() +{ +} + +// +// Attach Alert Prefix to Message ... +string PrepareAlertMessage(string message) +{ + // + StringReplace(message, "\n", " | "); + + // + StringConcatenate(message, alertPrefix, " > ", message); + + // + return message; +} + +// +// Logging an Alert ... +void LogAlert(string message) +{ + // + // Validate Args ... + if (!enableAlerts || !logAlerts) + { + return; + } + + // + LogMessage(alertPrefix, message); +} + +// +// Terminal Alert ... +void TerminalAlert(string message) +{ + // + // Validate Args ... + if (!enableAlerts || !terminalAlerts) + { + return; + } + + // + // Prepare Message ... + message = PrepareAlertMessage(message); + + // Send Terminal Alert ... + Alert(message); +} + +// +// Mail Alert ... +void MailAlert(string message) +{ + // + // Validate Args ... + if (!enableAlerts || !mailAlerts) + { + return; + } + + // + // Send Mail Alert ... + SendMail(alertPrefix, message); +} + +// +// Send Push Notification ... +void PushAlert(string message) +{ + // + // Validate Args ... + if (!enableAlerts || !pushAlerts) + { + return; + } + + // + // Prepare Message ... + message = PrepareAlertMessage(message); + + // + // Send Push Notification Alert ... + SendNotification(message); +} + +// +// Alert Sending ... +void SendAlert(string message) +{ + // + // Validate Args ... + if (!enableAlerts) + { + return; + } + + // + // Log ... + if (logAlerts) + { + LogAlert(message); + } + + // + // Terminal ... + if (terminalAlerts) + { + TerminalAlert(message); + } + + // + // Mail ... + if (mailAlerts) + { + MailAlert(message); + } + + // + // Push ... + if (pushAlerts) + { + PushAlert(message); + } +} +// +// END Provided Functions ... +// diff --git a/Libraries/x-saherelm.common.lib.mq5 b/Libraries/x-saherelm.common.lib.mq5 new file mode 100644 index 00000000..96b33e68 --- /dev/null +++ b/Libraries/x-saherelm.common.lib.mq5 @@ -0,0 +1,5618 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XCommonLib +// 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 + +// +// Imports ... + +// +// Models ... + +// +// Specified Price Type ... +enum ENUM_X_PRICE +{ + X_PRICE_HIGH, + X_PRICE_OPEN, + X_PRICE_CLOSE, + X_PRICE_LOW +}; + +// +// Swing Types Enum ... +enum ENUM_X_SWING_TYPE +{ + X_NO_SWING = 0, + X_SWING_HIGH = 1, + X_SWING_LOW = -1, +}; + +// +// XPERIOD Calculation Method ... +enum ENUM_X_PERIOD_METHOD +{ + // + X_PERIOD_NOTHING, // Nothing + X_PERIOD_AUTO, // Auto Select + X_PERIOD_MANUALLY // Manually +}; + +// +// Available Market Cycles ... +enum ENUM_X_MARKET_CYCLES +{ + // + X_MARKET_CYCLE_UNKNOWN, // Unknown Cycle + X_MARKET_CYCLE_SHORT, // Short Cycle + X_MARKET_CYCLE_MEDIUM, // Medium Cycle + X_MARKET_CYCLE_LONG, // Long Cycle + X_MARKET_CYCLE_HIND, // Hind Cycle +}; + +// +// Structs ... + +// +// Model a Bar Remains Time ... +struct XBarRemainsTime +{ + // + int days; + int hours; + int minutes; + int seconds; + + // + // Constructor ... + XBarRemainsTime() + { + Clean(); + } + + // + // Always Calculate Current 0 Bar Timing ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL // Trading Period + ) + { + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int minuteSecoonds = 60; + int hourSeconds = minuteSecoonds * 60; + int daySeconds = 24 * hourSeconds; + + // + int periodSeconds = PeriodSeconds( + mPeriod); + datetime startTime = GetBarTime( + mSymbol, + mPeriod, + 0 + // + ); + + // + int secondsDiff = (int)startTime + periodSeconds - (int)TimeCurrent(); + + // + int mWorkingSecondsDiff = secondsDiff; + if (mWorkingSecondsDiff > daySeconds) + { + // + days = mWorkingSecondsDiff / daySeconds; + mWorkingSecondsDiff -= days * daySeconds; + } + if (mWorkingSecondsDiff > hourSeconds) + { + // + hours = mWorkingSecondsDiff / hourSeconds; + mWorkingSecondsDiff -= hours * hourSeconds; + } + if (mWorkingSecondsDiff > minuteSecoonds) + { + // + minutes = mWorkingSecondsDiff / minuteSecoonds; + mWorkingSecondsDiff -= minutes * minuteSecoonds; + } + seconds = mWorkingSecondsDiff; + + // + result = true; + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + days = 0; + hours = 0; + minutes = 0; + seconds = 0; + } + + // + // To String Representation ... + string ToString( + string dayId = "d", + string hourId = "h", + string minuteId = "m", + string secondId = "s", + string idSeparator = ": ", + string separator = ", ", + bool ignoreZeroValues = true + // + ) + { + // + string result = ""; + + // + // Days ... + if (!ignoreZeroValues || days > 0) + { + result += dayId + idSeparator + (string)days + separator; + } + + // + // Hours ... + if (!ignoreZeroValues || hours > 0) + { + // + string strHour = ToString(hours); + if (StringLen(strHour) == 1) + { + strHour = "0" + strHour; + } + + // + result += hourId + idSeparator + strHour + separator; + } + + // + // Minutes ... + if (!ignoreZeroValues || minutes > 0) + { + // + string strMinute = ToString(minutes); + if (StringLen(strMinute) == 1) + { + strMinute = "0" + strMinute; + } + + // + result += minuteId + idSeparator + strMinute + separator; + } + + // + // Seconds ... + if (!ignoreZeroValues || seconds > 0) + { + // + string strSec = ToString(seconds); + if (StringLen(strSec) == 1) + { + strSec = "0" + strSec; + } + + // + result += secondId + idSeparator + strSec; + } + + // + return result; + } +}; + +// +// Describe an Specific Candle ... +struct XOHCL +{ + // + // Props ... + + // + double high; + double open; + double close; + double low; + + // + string symbol; + datetime time; + ENUM_TIMEFRAMES period; + + // + // Constructor ... + XOHCL() + { + Clean(); + } + + // + // Init a Bar ... + // Using Bar Index ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + int barIndex = 0 // Bar Index + ) + { + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + symbol = mSymbol; + period = mPeriod; + + // + time = iTime( + mSymbol, + mPeriod, + barIndex + // + ); + + // + open = iOpen( + mSymbol, + mPeriod, + barIndex + // + ); + + // + close = iClose( + mSymbol, + mPeriod, + barIndex + // + ); + + // + high = iHigh( + mSymbol, + mPeriod, + barIndex); + + // + low = iLow( + mSymbol, + mPeriod, + barIndex + // + ); + + // + bool result = IsValid(); + + // + return result; + } + + // + // Init a Bar ... + // Using Bar Time ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + datetime mTime = NULL // Bar Time + ) + { + // + mTime = NormalizeTime(mTime); + + // + int barIndex = iBarShift( + mSymbol, + mPeriod, + mTime, + false // + ); + + // + bool result = Init( + mSymbol, + mPeriod, + barIndex + // + ); + + // + return result; + } + + // + // Tools ... + + // + void Clean() + { + // + high = 0; + open = 0; + close = 0; + low = 0; + + // + time = NULL; + symbol = NULL; + period = NULL; + } + + // + // Validate Bar ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + high > 0 && + open > 0 && + close > 0 && + low > 0 + // + ; + + // + return result; + } + + // + // Calculate X_PRICE Specified Type ... + double GetPrice(ENUM_X_PRICE mPType) + { + // + double result = 0; + + // + if (mPType == NULL) + { + mPType = X_PRICE_CLOSE; + } + + // + if (!IsValid()) + { + return result; + } + + // + switch (mPType) + { + // + case X_PRICE_OPEN: + result = open; + break; + // + case X_PRICE_HIGH: + result = high; + break; + // + case X_PRICE_CLOSE: + result = close; + break; + // + case X_PRICE_LOW: + result = low; + break; + } + + // + return result; + } + + // + // Calculate Applied Price ... + double GetPrice( + ENUM_APPLIED_PRICE appliedTo // Select Application Method + ) + { + // + double result = 0; + + // + // Calculate Applied Price ... + switch (appliedTo) + { + // + case PRICE_CLOSE: + result = close; + break; + + // + case PRICE_OPEN: + result = open; + break; + + // + case PRICE_HIGH: + result = high; + break; + + // + case PRICE_LOW: + result = low; + break; + + // + case PRICE_MEDIAN: + result = (high + low) / 2; + break; + + // + case PRICE_TYPICAL: + result = (high + low + close) / 3; + break; + + // + case PRICE_WEIGHTED: + result = (high + low + close + close) / 4; + break; + } + + // + return result; + } + + // + // Calculate Bar Mid Line ... + double GetMid() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = (high + low) / 2; + + // + return result; + } + + // + // Calculate up Price ... + double GetUp() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathMax(open, close); + + // + return result; + } + + // + // Calculate Down Price ... + double GetDown() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathMin(open, close); + + // + return result; + } + + // + // Calculate Bar Body ... + double GetBody() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetUp() - GetDown(); + + // + return result; + } + + // + // Calculate Bar Range ... + double GetRange() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = high - low; + + // + return result; + } + + // + // Calculate Bar Shadows ... + double GetShadows() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetRange() - GetBody(); + + // + return result; + } + + // + // Calculate Bar High Shadow ... + double GetHighShadow() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + high - GetUp() + // + ; + + // + return result; + } + + // + // Calculate Bar Low Shadow ... + double GetLowShadow() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + GetDown() - low; + // + ; + + // + return result; + } + + // + // Check Bar is Bullish ... + bool IsBullish() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = open < close; + + // + return result; + } + + // + // Check Bar is Bearish ... + bool IsBearish() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = open > close; + + // + return result; + } + + // + // Find Next Bar Time ... + datetime NextAt() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int prSeconds = PeriodSeconds(period); + + // + result = time + prSeconds; + + // + return result; + } + + // + // Find Prev Bar Time ... + datetime BeforeOn() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int prSeconds = PeriodSeconds(period); + + // + result = time - prSeconds; + + // + return result; + } + + // + // Find Current Bar Index on Chart ... + int Index() + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + result = iBarShift( + symbol, + period, + time + // + ); + + // + return result; + } + + // + // Check Bar has Strong Body or Not ... + bool HasStrongBody() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + double body = GetBody(); + double shadow = GetShadows(); + + // + result = body > shadow * 1.5; + + // + return result; + } + + // + // Determines Swings based On this Bar ... + // Calculates Based on atleast 3 Bars Prev ... + ENUM_X_SWING_TYPE GetSwingType() + { + // + ENUM_X_SWING_TYPE result = X_NO_SWING; + + // + // Find Current Index of Bar ... + int barIndex = Index(); + if (barIndex <= -1) + { + return result; + } + + // + // First we have to Retrieve atleast 3 Bars before this bar ... + XOHCL bars[]; + int barsCount = GetBars( + bars, + symbol, + period, + barIndex + 1, + 3 + // + ); + if (barsCount < 3) + { + return result; + } + + // + // Check Swing Start Candle has Strong Body ... + bool isStrongBodyCandle = bars[2].HasStrongBody(); + if (!isStrongBodyCandle) + { + return result; + } + + // + // Check Swing Low Conditions ... + bool isSwingLowOrderBlock = + bars[2].low < bars[1].low && + bars[1].low < bars[0].low && + bars[2].low < bars[0].low; + if (isSwingLowOrderBlock) + { + result = X_SWING_LOW; + } + + // + // Check Swing High Conditions ... + bool isSwingHighOrderBlock = + bars[2].high > bars[1].high && + bars[1].high > bars[0].high && + bars[2].high > bars[0].high; + if (isSwingHighOrderBlock) + { + result = X_SWING_HIGH; + } + + // + return result; + } + + // + // Find Swings (Highs nd Lows) ... + int FindSwing( + ENUM_X_SWING_TYPE swing, // Swing Based On Price mode ... + int mLength // Loopback ... + ) + { + // + int result = -1; + + // + if (!IsValid() || + !IsValid(swing)) + { + return result; + } + + // + int current = Index(); + int founded = FindNextSwing( + swing, + (mLength * 2) + 1, + current - mLength + // + ); + + // + while (founded != current) + { + // + current = FindNextSwing( + swing, + mLength, + current + 1 + // + ); + + // + founded = FindNextSwing( + swing, + (mLength * 2) + 1, + current - mLength + // + ); + } + + // + result = current; + + // + return result; + } + + // + // Find Next Swing ... + int FindNextSwing( + ENUM_X_SWING_TYPE swing, // Swing Based On Price mode ... + int from, // from Bar Index + int mLength // Loopback ... + ) + { + // + int result = -1; + + // + if (!IsValid() || + !IsValid(swing)) + { + return result; + } + + // + if (from < 0) + { + mLength += from; + from = 0; + } + + // + ENUM_SERIESMODE mode = swing == X_SWING_HIGH + ? MODE_HIGH + : MODE_LOW; + + // + result = swing == X_SWING_HIGH + ? iHighest( + symbol, + period, + mode, + mLength, + from) + : iLowest( + symbol, + period, + mode, + mLength, + from); + + // + return result; + } + + // + // Find Lowest Bar Index ... + int FindHighestIndex( + int mLength, // Loopback ... + ENUM_SERIESMODE mode // Calculation mode + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (mLength < 2) + { + mLength = 2; + } + + // + result = iHighest( + symbol, + period, + mode, + mLength, + Index()); + + // + return result; + } + + // + // Find Lowest ... + double FindHighest( + int mLength, // Loopback ... + ENUM_SERIESMODE mode // Calculation mode + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + int idx = FindHighestIndex( + mLength, + mode); + if (idx <= -1) + { + return result; + } + + // + ENUM_X_PRICE pMode = ToPrice(mode); + + // + XOHCL iH; + result = iH.Init( + symbol, + period, + idx + // + ); + if (!result) + { + return result; + } + + // + result = iH.GetPrice(pMode); + + // + return result; + } + + // + // Find Lowest Bar Index ... + int FindLowestIndex( + int mLength, // Loopback ... + ENUM_SERIESMODE mode // Calculation mode + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (mLength < 2) + { + mLength = 2; + } + + // + result = iLowest( + symbol, + period, + mode, + mLength, + Index()); + + // + return result; + } + + // + // Find Lowest ... + double FindLowest( + int mLength, // Loopback ... + ENUM_SERIESMODE mode // Calculation mode + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + int idx = FindLowestIndex( + mLength, + mode); + if (idx <= -1) + { + return result; + } + + // + ENUM_X_PRICE pMode = ToPrice(mode); + + // + XOHCL iL; + result = iL.Init( + symbol, + period, + idx + // + ); + if (!result) + { + return result; + } + + // + result = iL.GetPrice(pMode); + + // + return result; + } + + // + // Convert to String Representation ... + string ToString() + { + // + string result = ""; + + // + result = GetTypeName(this) + + "(O(" + ToString(open) + "),H(" + ToString(high) + "),C(" + ToString(close) + "),L(" + ToString(low) + "))"; + + // + return result; + } +}; + +// +// Model Support and Resistance +// for Specific Bar ... +struct XOHCLSupRes +{ + // + // Props ... + + // + /// Resistances ... + double res[]; + + // + // Supports ... + double sup[]; + + // + // Constructor ... + XOHCLSupRes() + { + Clean(); + } + + // + // Init ... + bool Init( + double price, // Price ... + const double &pivots[], // Provided Pivot Points ... + int count = 3, // Number of Requireds ... + double step = 0 // Distance between each item with it's Last Side ... + ) + { + // + bool result = false; + + // + Clean(); + + // + if (price <= 0) + { + return result; + } + + // + int pivotsCount = ArraySize(pivots); + if (pivotsCount <= 0) + { + return result; + } + + // + if (count <= 0 || + count > pivotsCount - 1) + { + return result; + } + + // + double lastR = 0; + double tmpR[]; + + // + double lastS = 0; + double tmpS[]; + + // + // Extract Supports ... + // which prices is under low of candle ... + // + // Extract Resistance ... + // which prices is over high of candle ... + for (int i = 0; i < pivotsCount; i++) + { + // + double iFlat = pivots[i]; + + // + if (iFlat > price) + { + // + bool canAdd = + step <= 0 + ? true + : lastR == 0 || MathAbs(iFlat - lastR) >= step; + if (canAdd) + { + // + Add( + iFlat, + tmpR); + + // + lastR = iFlat; + } + } + else if (iFlat < price) + { + // + bool canAdd = + step <= 0 + ? true + : lastS == 0 || MathAbs(iFlat - lastS) >= step; + if (canAdd) + { + // + Add( + iFlat, + tmpS); + + // + lastS = iFlat; + } + } + } + + // + // Sorting Founded Resistance and Supports ... + + // + // Since Resistance Levels must be Increasing ... + ArraySort(tmpR); + + // + // Since Support Levels must be Decreasing ... + ArraySort(tmpS); + ArrayReverse(tmpS); + + // + // Fill Resistance ... + int tmpRCount = ArraySize(tmpR); + if (tmpRCount > 0) + { + // + if (tmpRCount < count) + { + // + ArrayCopy( + res, + tmpR); + } + else + { + // + ArrayCopy( + res, + tmpR, + 0, + 0, + count); + } + } + + // + // Fill Supports ... + int tmpSCount = ArraySize(tmpS); + if (tmpSCount > 0) + { + // + if (tmpSCount < count) + { + // + ArrayCopy( + sup, + tmpS); + } + else + { + // + ArrayCopy( + sup, + tmpS, + 0, + 0, + count); + } + } + + // + result = IsValid(); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + Clean(sup); + Clean(res); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + CountSupports() > 0 || + CountResistances() > 0 + // + ; + + // + return result; + } + + // + int CountSupports() + { + return ArraySize(sup); + } + + // + int CountResistances() + { + return ArraySize(res); + } +}; + +// +// Tracking Times ... +struct XTimeTracker +{ + // + // Props ... + int xMonth; + int xDayOfWeek; + int xForWeekDay; + int xDay; + int xHour; + + // + // Constructor ... + XTimeTracker() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + xDay = -1; + xHour = -1; + xMonth = -1; + xDayOfWeek = -1; + xForWeekDay = -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; + } +}; + +// +// Tracking Bars on Specified Environment ... +struct XBarTracker +{ + // + string symbol; // Tracking Symbol + ENUM_TIMEFRAMES period; // Tracking Time Frame + + // + int lastTrackedBar; // Last Tracked Bar ... + + // + // Constructor ... + XBarTracker() + { + Clean(); + } + + // + // Initializer ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL // Trading Period + ) + { + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + this.symbol = mSymbol; + this.period = mPeriod; + + // + this.lastTrackedBar = 0; + + // + result = true; + + // + return result; + } + + // + // Retrieve all Bars ... + int CountBars() + { + // + return Bars( + symbol, + period + // + ); + } + + // + // Check if it's New Bar ... + bool IsNewBar() + { + // + bool result = false; + + // + int currentBars = CountBars(); + + // + result = currentBars > lastTrackedBar; + if (result) + { + lastTrackedBar = currentBars; + } + + // + return result; + } + + // + // Tools ... + void Clean() + { + // + symbol = NormalizeSymbol(NULL); + period = NormalizePeriod(NULL); + } +}; + +// +// Track Value Changes ... +template +struct XValueTracker +{ + // + // Definitions ... + + // + // Model a Value Change ... + struct XValueChange + { + // + // Props ... + datetime at; // Change Time + T from; // Before Change Value + T to; // After Change Value + + // + // Constructor ... + XValueChange() + { + Clean(); + } + + // + // Cleanup ... + void Clean() + { + // + at = NULL; + from = NULL; + to = NULL; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = IsValid(at); + if (!result) + { + return result; + } + + // + result = NotEmpty(from) && + NotEmpty(to); + + // + return result; + } + }; + + // + // Props ... + XValueChange changes[]; // Hold Changes + + // + // Constructor ... + XValueTracker() + { + Clean(); + } + + // + // Track a Change Happens Or Not ... + bool Track( + const T &source[] // Data Source for Track Changes + ) + { + // + bool result = false; + + // + if (ArraySize(source) <= 1) + { + return result; + } + + // + datetime time = TimeCurrent(); + + // + double from = source[1]; + double to = source[0]; + + // + result = to != from; + if (result) + { + return result; + } + + // + XValueChange lastChange; + bool hasLastChange = + GetLastItem( + lastChange, + changes + // + ); + result = + !hasLastChange + ? true + : lastChange.at < time && + lastChange.to != to && + lastChange.from != from; + if (!result) + { + return result; + } + + // + lastChange.Clean(); + + // + lastChange.to = to; + lastChange.at = time; + lastChange.from = from; + + // + AddRef( + lastChange, + changes + // + ); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + Clean(changes); + } +}; + +// +// Model a Market Cycle ... +struct XMarketCycle +{ + // + // Props ... + + // + string prefix; // Prefix Trag ... + + // + string symbol; // Market Symbol ... + + // + ENUM_TIMEFRAMES period; // Period of Cycle ... + ENUM_X_PERIOD_METHOD method; // Period Selection Method ... + ENUM_X_MARKET_CYCLES cycle; // Cycles of MArket ... + + // + int length; // Number Of Candles per Current Time Frame ... + ENUM_TIMEFRAMES hostPeriod; // Current Time Frame ... + + // + datetime lastStart; // Last Candle Bar Time ... + + // + XBarTracker barTracker; // Bar Tracker ... + XBarRemainsTime remains; // Current Bar Remains Model ... + + // + // Constructor ... + XMarketCycle() + { + Clean(); + } + + // + // Init Cycle ... + bool Init( + string mSymbol, // Trading Symbol + ENUM_TIMEFRAMES mHostPeriod, // Host Period + ENUM_X_MARKET_CYCLES mCycle, // Init Cycle + string mPrefix = "" // Prefix + ) + { + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + mHostPeriod = NormalizePeriod(mHostPeriod); + + // + result = IsValid(mCycle); + if (!result) + { + return result; + } + + // + this.cycle = mCycle; + + // + // Set Automatically Prefix ... + if (StringLen(mPrefix) == 0) + { + this.prefix = ToString(cycle); + } + + // + result = IsValid( + method, + period // + ); + if (!result) + { + return result; + } + + // + this.symbol = mSymbol; + this.hostPeriod = mHostPeriod; + + // + // Find Cycle Period ... + if (method == X_PERIOD_AUTO) + { + // + // Select Period ... + this.period = GetCyclePeriod( + this.cycle, + this.hostPeriod); + } + + // + // Set Prefix if Provided ... + if (StringLen(mPrefix) > 0) + { + this.prefix = mPrefix; + } + + // + // Calculate Required Info ... + + // + // Length ... + this.length = PeriodSeconds(this.period) / PeriodSeconds(this.hostPeriod); + + // + // Update Additional Data ... + result = this.Update(0); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + length = 0; + lastStart = 0; + + // + cycle = NULL; + prefix = NULL; + symbol = NULL; + period = NULL; + method = NULL; + hostPeriod = NULL; + + // + remains.Clean(); + barTracker.Clean(); + } + + // + // Check Structure Valid ... + bool IsValid() + { + // + bool result = false; + + // + result = IsValid( + method, + period); + if (!result) + { + return result; + } + + // + result = + // + length > 0 && + symbol != NULL && + period != NULL && + method != NULL && + hostPeriod != NULL && + method != X_PERIOD_NOTHING + // + ; + + // + return result; + } + + // + // Update Market Cycle Additional Info ... + bool Update(int hostBarIndex) + { + // + bool result = false; + + // + result = this.IsValid(); + if (!result) + { + return result; + } + + // + // Init Remains ... + result = remains.Init( + this.symbol, + this.period); + if (!result) + { + return result; + } + + // + // Init Bar Tracker ... + result = barTracker.Init( + this.symbol, + this.period); + if (!result) + { + return result; + } + + // + return result; + } + + // + // Count Bars ... + int CountBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = barTracker.CountBars(); + + // + return result; + } + + // + // Check New Bar ... + bool IsNewBar() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = barTracker.IsNewBar(); + + // + return result; + } + + // + // Retrieve Current Bar Index based on Host Period bar Index ... + int GetBarIndex(int barIndex) + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + if (barIndex < 0) + { + return result; + } + + // + int totalBars = CountBars(); + if (barIndex >= totalBars) + { + // + result = totalBars - 1; + return result; + } + + // + datetime hostBarTime = iTime( + this.symbol, + this.hostPeriod, + barIndex + // + ); + + // + result = iBarShift( + this.symbol, + this.period, + hostBarTime + // + ); + + // + return result; + } + + // + // Retrieve Current Cycles Specific Bar ... + XOHCL GetBar(int barIndex) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int totalBars = CountBars(); + if (barIndex >= totalBars) + { + barIndex = totalBars - 1; + } + + // + XOHCL result; + result.Init( + this.symbol, + this.period, + barIndex + // + ); + + // + return result; + } + + // + // Retrieve Bar Time ... + datetime GetBarTime(int barIndex) + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int totalBars = CountBars(); + if (barIndex >= totalBars) + { + barIndex = totalBars - 1; + } + + // + result = iTime( + this.symbol, + this.period, + barIndex + // + ); + + // + return result; + } + + // + // Create and String Representation for Unique Taging ... + string ToString() + { + // + string result = ""; + + // + if (!IsValid()) + { + return result; + } + + // + result = + GetTypeName(this) + "(" + + "PRFX(" + this.prefix + ")" + + "SMBL(" + this.symbol + ")" + + "CYC(" + ToString(this.cycle) + ")" + + "PRD(" + ToString(this.period) + ")" + + "PRDHST(" + ToString(this.hostPeriod) + ")" + + "MTH(" + EnumToString(this.method) + ")" + + ")"; + + // + return result; + } + + // + // Here we Produce a Summary brief of + // state of Cycle ... + string GenerateSummary() + { + // + string result = ""; + + // + bool hasPrefix = + StringLen(this.prefix) > 0 && + this.prefix != ToString(this.cycle); + result += (hasPrefix ? this.prefix + "[" : "") + + ToString(this.cycle) + + (hasPrefix ? "]" : "") + "\n"; + + // + result += " - PR: " + ToString(this.period) + "\n"; + + // + XOHCL cBar = GetBar(0); + + // + result += " - State: " + (cBar.IsBullish() ? "Bullish" : cBar.IsBearish() ? "Bearish" + : "Neutural"); + + // + return result; + } +}; + +// +// Functions ... + +// +// Validators ... + +// +// Validate an String has length and not NULL ... +bool IsValid(string value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + StringLen(value) > 0 + // + ; + + // + return result; +} + +// +// Validate a Date ... +bool IsValid(datetime value) +{ + // + bool result = false; + + // + result = NotEmpty(value) && value != NULL; + + // + return result; +} + +// +// Validate a Period Param ... +bool IsValid(ENUM_TIMEFRAMES value) +{ + // + bool result = false; + + // + result = + // + value != NULL + // + ; + + // + return result; +} + +// +// Validate Specified Cycle ... +bool IsValid(ENUM_X_MARKET_CYCLES value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + value != X_MARKET_CYCLE_UNKNOWN + // + ; + + // + return result; +} + +// +// Validate Specific Period Mode ... +bool IsValid( + ENUM_X_PERIOD_METHOD mMethod, // Period Select Method + ENUM_TIMEFRAMES mPeriod // Selected Period +) +{ + // + bool result = false; + + // + result = + // + mMethod == X_PERIOD_NOTHING + ? false + : mMethod == X_PERIOD_MANUALLY + ? mPeriod != NULL + : mMethod == X_PERIOD_AUTO + ? true + : false + // + ; + + // + return result; +} + +// +// Validate Swing Mode ... +bool IsValid(ENUM_X_SWING_TYPE value) +{ + // + bool result = false; + + // + result = + // + value == X_SWING_HIGH || + value == X_SWING_LOW + // + ; + + // + return result; +} + +// +// As IS ... + +// +// Determine a Position type is Long or not ... +bool IsLong(ENUM_POSITION_TYPE type) +{ + // + bool result = type == POSITION_TYPE_BUY; + + // + return result; +} +bool IsLong(ENUM_ORDER_TYPE type) +{ + // + bool result = type == ORDER_TYPE_BUY; + + // + return result; +} + +// +// Determine a Position type is Short or not ... +bool IsShort(ENUM_POSITION_TYPE type) +{ + // + bool result = type == POSITION_TYPE_SELL; + + // + return result; +} +bool IsShort(ENUM_ORDER_TYPE type) +{ + // + bool result = type == ORDER_TYPE_SELL; + + // + return result; +} + +// +// Check Expert Running in Testing Mode or not ... +bool IsRunningOnTestMode() +{ + // + bool result = false; + + // + // check programm mode ... + result = MQL5InfoInteger(MQL5_TESTING); + + // + return result; +} + +// +// Normalizers ... + +// +// Check a Symbol provided or not ... +// if not use Default ... +string NormalizeSymbol(string value) +{ + // + string result = value; + + // + if (!IsValid(result)) + { + result = _Symbol; + } + + // + return result; +} + +// +// Check a Datetime provided or not ... +// if not use Current ... +datetime NormalizeTime(datetime value) +{ + // + datetime result = value; + + // + if (!IsValid(result)) + { + result = TimeCurrent(); + } + + // + return result; +} + +// +// Check a Period provided or not ... +// if not use Default ... +ENUM_TIMEFRAMES NormalizePeriod(ENUM_TIMEFRAMES value) +{ + // + ENUM_TIMEFRAMES result = value; + + // + if (!IsValid(value)) + { + result = _Period; + } + + // + return result; +} + +// +// Normalize Cycle ... +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 a give Volume ... +double NormalizeVolume( + double mVolume, // desired volume to normalize + string mSymbol = NULL, // Trading Symbol + int mLength = 2 // Length of Digits +) +{ + // + double result = mVolume; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + // Normalize Digits ... + int digits = GetDigits(mSymbol); + + // + mLength = + mLength == 0 || mLength > digits + ? digits + : MathMin(mLength, digits); + + // + // Normalize Volume ... + result = NormalizeDouble(result, mLength); + + // + double maxAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MAX); + double minAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MIN); + + // + // Validate Result ... + if (result > maxAvailableVolume) + { + result = maxAvailableVolume; + } + else if (result < minAvailableVolume) + { + result = minAvailableVolume; + } + + // + return result; +} + +// +// Normallize Price ... +double NormalizePrice( + double mPrice, // desired Price for normalization + string mSymbol = NULL // Trading Symbol +) +{ + // + 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; +} + +// +// Prices ... + +// +// Retrieve Ask Price ... +double GetAsk( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_ASK); + + // + return result; +} + +// +// Retrieve Bid Price ... +double GetBid( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_BID); + + // + return result; +} + +// +// Retrieve Spread Price ... +double GetSpread( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double ask = GetAsk(mSymbol); + double bid = GetBid(mSymbol); + + // + double result = MathAbs(ask - bid); + + // + return result; +} + +// +// Retrieve Point Value ... +double GetPoints( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_POINT); + + // + return result; +} + +// +// Retrieve Point Digits ... +int GetDigits( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + int result = (int)SymbolInfoInteger(mSymbol, SYMBOL_DIGITS); + + // + return result; +} + +// +// Retrieve Entry Price ... +double GetEntry( + string mSymbol = NULL, // Trading Symbol + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? GetAsk(mSymbol) + : GetBid(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// Retrieve Exit Price ... +double GetExit( + string mSymbol = NULL, // Trading Symbol + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // Get entry price for Which direction trade ... +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? GetBid(mSymbol) + : GetAsk(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// 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; +} + +// +// Converts Pips To Price ... +double PipsToPrice( + double mPips, // pips amount + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + int digits = GetDigits(mSymbol); + double pipValue = GetPipPrice(mSymbol); + double result = mPips * pipValue; + + // + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// Converts Price to Pips ... +double PriceToPips( + double mPrice, // the price amount which required to calculate + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + mPrice = NormalizePrice(mPrice, mSymbol); + + // + int digits = GetDigits(mSymbol); + double pipPrice = GetPipPrice(mSymbol); + + // + double result = mPrice / pipPrice; + + // + result = NormalizeDouble(result, digits); + + // + return result; +} + +// +// Convert Price to Point ... +double PriceToPoint( + double price, // the price amount which required to calculate + string mSymbol = NULL // Trading Symbol +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + price = NormalizePrice(price, mSymbol); + + // + double point = GetPoints(mSymbol); + result = price / point; + + // + return result; +} + +// +// Converts Point to Price ... +double PointToPrice( + double points, // Points Amount + string mSymbol = NULL // Trading Symbol +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double point = GetPoints(mSymbol); + result = points * point; + + // + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// Converts Series Mode to XPRICE ... +ENUM_X_PRICE ToPrice( + ENUM_SERIESMODE mode // Specified Series Mode ... +) +{ + // + ENUM_X_PRICE result = X_PRICE_CLOSE; + + // + switch (mode) + { + // + // High ... + case MODE_HIGH: + result = X_PRICE_HIGH; + break; + + // + // Open ... + case MODE_OPEN: + result = X_PRICE_OPEN; + break; + + // + // Low ... + case MODE_LOW: + result = X_PRICE_LOW; + break; + + // + // Close ... + // Default ... + case MODE_CLOSE: + default: + result = X_PRICE_CLOSE; + break; + } + + // + return result; +} + +// +// Retrieve Applied Price ... +template +double GetAppliedPrice( + ENUM_APPLIED_PRICE tprice, // Type of Price Selection + T &open[], // Open Prices + T &high[], // High Preices + T &low[], // Low Prices + T &close[], // Close Prices + int i // Bar Index +) +{ + switch (tprice) + { + case PRICE_CLOSE: + return (close[i]); + case PRICE_OPEN: + return (open[i]); + case PRICE_HIGH: + return (high[i]); + case PRICE_LOW: + return (low[i]); + case PRICE_MEDIAN: + return ((high[i] + low[i]) / 2.0); + case PRICE_TYPICAL: + return ((high[i] + low[i] + close[i]) / 3.0); + case PRICE_WEIGHTED: + return ((high[i] + low[i] + close[i] + close[i]) / 4.0); + } + return (0); +} + +// +// Time / Date ... + +// +// 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; +} + +// +// Bar Times ... + +// +// Retrieve Specified Bar Time ... +datetime GetBarTime( + string mSymbol = "", // 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 Specified Bar Time ... +ulong GetBarTimeAsSeconds( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + // Retrieve Bar Time ... + datetime time = GetBarTime( + mSymbol, + mPeriod, + barIndex); + + // + ulong result = TimeToSeconds(time); + + // + return result; +} + +// +// Retrieve Specified Bar Time ... +ulong GetBarTimeAsMilliSeconds( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + // Retrieve Bar Time ... + datetime time = GetBarTime( + mSymbol, + mPeriod, + barIndex); + + // + ulong result = TimeToMilliSeconds(time); + + // + return result; +} + +// +// Retrieve a Bar Time Structure ... +MqlDateTime GetBarTimeStruct( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + MqlDateTime result = {}; + + // + // Retrieve Bar Time ... + datetime barTime = GetBarTime( + mSymbol, + mPeriod, + barIndex); + + // + // Convert to Structure ... + TimeToStruct(barTime, result); + + // + return result; +} + +// +// Other Tools ... + +// +// 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; +} + +// +// 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; +} + +// +// Calculate Fib Level ... +double GetFibonacciLevel( + double upPrice, // Upper Bound + double downPrice, // Downer Bound + double level, // Level Multiplier Factor + int direction // From Down to Up < 0, other wise Vice Versa + // +) +{ + // + double ling = upPrice - downPrice; + double pLevel = (ling / 100) * (level * 100); + + // + double result = direction > 0 ? upPrice - pLevel : downPrice + pLevel; + + // + return result; +} + +// +// Templates ... + +// +// Retrieve Specific Object Types Name ... +template +string GetTypeName(const T &t) +{ + return typename(T); +} + +// +// Generate Unique Tags ... +template +string GenerateTag(T &model) +{ + // + string result = ""; + + // + string tag = model.ToString(); + if (StringLen(tag) == 0) + { + return result; + } + + // + static XSCMD5 md5; + + // + result = md5.Hash(tag); + + // + return result; +} + +// +// Hash Specified Content ... +template +string ToMD5(T content) +{ + // + string result = ""; + + // + string strContent = ToString(content); + if (StringLen(strContent) == 0) + { + return result; + } + + // + static XSCMD5 md5; + + // + result = md5.Hash(strContent); + + // + return result; +} + +// +// Check a Value Not Empty ... +template +bool NotEmpty(T value) +{ + return value != EMPTY_VALUE; +} + +// +// Add Specified Item to Array ... +template +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 +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; +} + +// +// Remove Specified Item from an Array ... +template +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 +void Clean(T &buffer[]) +{ + // + ArrayFree(buffer); + ArrayResize(buffer, 0); +} + +// +// Copy Whole Content of Source to Dest array ... +template +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 +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 +) +{ + // + 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); + + // + ArrayCopy( + dest, + source, + 0, + start, + count + // + ); + + // + int afterSize = ArraySize(dest); + + // + result = afterSize - beforeSize; + + // + ArraySetAsSeries(dest, asSeriesDest); + ArraySetAsSeries(source, asSeriesSource); + + // + return result; +} + +// +// Retrive Last Item of Specified Buffer ... +template +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; +} + +// +// Search Array For Specific Item ... +template +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; +} + +// +// Check an Array Contains Specified Value ... +template +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 Average ... +template +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 +double GetMax( + 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; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + double iValue = tmp[i]; + + // + result = + // + result == 0 || result < iValue + // + ? iValue + // + : result + // + ; + } + + // + return result; +} + +// +// Get Min of Specific Loopback of a Buffer ... +template +double GetMinValue( + 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; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + double iValue = tmp[i]; + + // + result = + // + result == 0 || result > iValue + // + ? iValue + // + : result + // + ; + } + + // + return result; +} + +// +// Find a Value less than Specified ... +template +T FindLesserThanValue( + 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; +} + +// +// Find a Value less than Specified ... +template +T FindBiggerThanValue( + 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; +} + +// +// Find Same Values in Array ... +template +void FindSameValues( + 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); + } +} + +// +// Bar XOHCL ... + +// +// Extract Specific Range of Bars ... +// using Start Bar Index ... +int GetBars( + XOHCL &result[], // Hold Result + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Time Frame + int from = 0, // Start Bar Index + int count = 1, // Number of Bars + bool forceClean = true // Clean Result Array +) +{ + // + int mResult = 0; + + // + if (from < 0) + { + from = 0; + } + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int total = Bars( + mSymbol, + mPeriod); + if (from > total - 2) + { + from = total - 2; + } + + // + if (count < 0) + { + count = 1; + } + + // + int start = from; + int end = start + count; + if (end > total - 1) + { + end = total - 1; + } + + // + if (forceClean) + { + Clean(result); + } + + // + int beforeSize = ArraySize(result); + + // + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + bool isValid = iBar.Init( + mSymbol, + mPeriod, + i + // + ); + + // + if (isValid) + { + // + AddRef( + iBar, + result + // + ); + } + } + + // + int afterSize = ArraySize(result); + + // + mResult = afterSize - beforeSize; + + // + return mResult; +} + +// +// Extract Specific Range of Bars ... +// using Start Bar Time ... +int GetBars( + XOHCL &result[], // Hold Result + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Time Frame + datetime from = NULL, // Start Bar Time + int count = 1, // Number of Bars + bool forceClean = true // Clean Result Array +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + from = NormalizeTime(from); + + // + int barIndex = iBarShift( + mSymbol, + mPeriod, + from, + false + // + ); + + // + return GetBars( + result, + mSymbol, + mPeriod, + barIndex, + count, + forceClean + // + ); +} + +// +// String ... + +// +// Convert From String ... +template +T FromString(string value) +{ + // + T result = NULL; + + // + if (!IsValid(value)) + { + return result; + } + + // + result = (T)value; + + // + return result; +} + +// +// Converts an item to String ... +template +string ToString(T value) +{ + return (string)value; +} + +// +// Converts a Buffer to String Representation ... +template +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 ... +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; +} + +// +// Surround an String by Specific Token ... +template +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; +} + +// +// Periods / Cycles ... + +// +// Converts an String to TimeFrame ... +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 Period to String ... +string ToString(ENUM_TIMEFRAMES mPeriod) +{ + // + string result = ""; + + // + string mPStr = EnumToString(mPeriod); + + 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; +} + +// +// Converts an String to it's related Market Cycle ... +ENUM_X_MARKET_CYCLES ToCycle(string value) +{ + // + ENUM_X_MARKET_CYCLES result = X_MARKET_CYCLE_UNKNOWN; + + // + ENUM_X_MARKET_CYCLES cycles[]; + int count = GetAllMarketCycles(cycles); + for (int i = 0; i < count; i++) + { + // + ENUM_X_MARKET_CYCLES iCycle = cycles[i]; + string iStr = ToString(iCycle); + + // + if (value == iStr) + { + // + result = iCycle; + break; + } + } + + // + return result; +} + +// +// Converts a Cycle to it's String Representation ... +string ToString(ENUM_X_MARKET_CYCLES cycle) +{ + // + string result = ""; + + // + string mPStr = EnumToString(cycle); + + string mPStrParts[]; + int partsCount = StringSplit( + mPStr, + StringGetCharacter("_", 0), + mPStrParts); + if (partsCount <= 0) + { + return result; + } + + // + result = mPStrParts[3]; + + // + return result; +} + +// +// Retrieve all Available Cycles ... +int GetAllMarketCycles(ENUM_X_MARKET_CYCLES &result[]) +{ + // + int mResult = 0; + + // + Clean(result); + + // + ENUM_X_MARKET_CYCLES tmp[] = { + X_MARKET_CYCLE_UNKNOWN, + X_MARKET_CYCLE_SHORT, + X_MARKET_CYCLE_MEDIUM, + X_MARKET_CYCLE_LONG, + X_MARKET_CYCLE_HIND}; + + // + Copy( + tmp, + result); + + // + Clean(tmp); + + // + mResult = ArraySize(result); + + // + return mResult; +} + +// +// 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: + result = PERIOD_M4; + break; + + // + case PERIOD_M3: + case PERIOD_M4: + result = PERIOD_M6; + 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_H1: + case PERIOD_H2: + case PERIOD_H3: + result = PERIOD_H4; + break; + + // + case PERIOD_H6: + case PERIOD_H8: + result = PERIOD_H12; + break; + + // + case PERIOD_H12: + result = PERIOD_D1; + break; + + // + case PERIOD_D1: + result = PERIOD_W1; + break; + + // + default: + result = PERIOD_MN1; + 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: + result = PERIOD_M15; + break; + + // + case PERIOD_M3: + case PERIOD_M4: + result = PERIOD_M30; + break; + + // + case PERIOD_M5: + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + result = PERIOD_H1; + break; + + // + case PERIOD_M15: + case PERIOD_M20: + result = PERIOD_H2; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + result = PERIOD_H8; + break; + + // + case PERIOD_H6: + case PERIOD_H8: + result = PERIOD_D1; + break; + + // + case PERIOD_H12: + result = PERIOD_W1; + break; + + // + case PERIOD_D1: + result = PERIOD_MN1; + break; + + // + default: + result = PERIOD_MN1; + 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: + result = PERIOD_M30; + break; + + // + case PERIOD_M3: + case PERIOD_M4: + result = PERIOD_H1; + break; + + // + case PERIOD_M5: + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + result = PERIOD_H2; + break; + + // + case PERIOD_M15: + case PERIOD_M20: + result = PERIOD_H4; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + result = PERIOD_H12; + break; + + // + case PERIOD_H6: + case PERIOD_H8: + result = PERIOD_W1; + break; + + // + case PERIOD_H12: + result = PERIOD_MN1; + break; + + // + case PERIOD_D1: + result = PERIOD_MN1; + break; + + // + default: + result = PERIOD_MN1; + 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: + result = PERIOD_H1; + break; + + // + case PERIOD_M3: + case PERIOD_M4: + result = PERIOD_H2; + break; + + // + case PERIOD_M5: + case PERIOD_M6: + case PERIOD_M10: + case PERIOD_M12: + result = PERIOD_H4; + break; + + // + case PERIOD_M15: + case PERIOD_M20: + result = PERIOD_H8; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + case PERIOD_H3: + result = PERIOD_D1; + break; + + // + case PERIOD_H6: + case PERIOD_H8: + result = PERIOD_MN1; + break; + + // + case PERIOD_H12: + result = PERIOD_MN1; + break; + + // + case PERIOD_D1: + result = PERIOD_MN1; + break; + + // + default: + result = PERIOD_MN1; + 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; +} \ No newline at end of file diff --git a/Libraries/x-saherelm.draw.lib.mq5 b/Libraries/x-saherelm.draw.lib.mq5 new file mode 100644 index 00000000..b714abaf --- /dev/null +++ b/Libraries/x-saherelm.draw.lib.mq5 @@ -0,0 +1,3608 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Draw Library +// -------------------------------------- +// Name: XDraw +// Description: provides Draw abilities ... +// +// +// 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 Logger Library ... +#include "x-saherelm.log.lib.mq5" +#include "x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xmd5.class.mq5" + +// +// START Global Definitions: Variables, Properties and etc ... +// + +// +string drawPrefix = "X-OBJ"; + +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Provided Functions ... +// + +// +// DeInitial Library if required ... +void OnDeinitDrawLibrary() +{ + RemoveDraws(); +} + +// +// remove drawn objects ... +void RemoveDraws( + string tag = NULL, + long chartId = -1, + int subWindow = -1) +{ + // + // Normalize Args ... + // + if (tag == NULL) + { + tag = drawPrefix; + } + + // + if (chartId == -1) + { + chartId = 0; + } + + // + if (subWindow == -1) + { + subWindow = 0; + } + + // + for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--) + { + // + string on = ObjectName(chartId, iObj, subWindow); + if (StringFind(on, tag) >= 0) + { + ObjectDelete(chartId, on); + } + } + + // + // Redraw Chart ... + ChartRedraw(); +} + +// +bool RemoveDraw( + string name, + long chartId = -1, + int subWindow = -1) +{ + // + bool result = false; + + // + if (chartId == -1) + { + chartId = 0; + } + + // + if (subWindow == -1) + { + subWindow = 0; + } + + // + string objName = ""; + for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--) + { + // + string on = ObjectName(chartId, iObj, subWindow); + if (StringFind(on, name) >= 0) + { + // + objName = on; + break; + } + } + + // + if (StringLen(objName) > 0) + { + result = ObjectDelete(chartId, objName); + } + + // + return result; +} + +// +// Deselect All Draws ... +void DeselectAllDraws() +{ + // + int objs = ObjectsTotal(ChartID(), 0); + for (int o = 0; o < objs; o++) + { + ObjectSetInteger(ChartID(), ObjectName(ChartID(), o, 0), OBJPROP_SELECTED, false); + } + + // + ChartRedraw(); +} + +// +// Check Object Exists ... +bool IsDrawExists( + string name, + long chartId = -1, + int subWindow = -1) +{ + // + bool result = false; + + // + if (chartId == -1) + { + chartId = 0; + } + + // + if (subWindow == -1) + { + subWindow = 0; + } + + // + for (int iObj = ObjectsTotal(chartId, subWindow) - 1; iObj >= 0; iObj--) + { + // + string on = ObjectName(chartId, iObj, subWindow); + result = StringFind(on, name) >= 0; + if (result) + { + break; + } + } + + // + return result; +} + +// +// END Provided Functions ... +// + +// +// START Regular Draws ... +// + +// +// START Arrow Functions ... +// + +// +// Draw an Arrow Object on Chart ... +bool DrawArrow( + const long chartID = 0, // chart's ID + const string name = "Arrow", // arrow name + const int subWindow = 0, // subwindow index + datetime time = 0, // anchor point time + double price = 0, // anchor point price + const uchar arrowCode = 252, // arrow code + const ENUM_ARROW_ANCHOR anchor = ANCHOR_BOTTOM, // anchor point position + const color clr = clrAqua, // arrow color + const ENUM_LINE_STYLE style = STYLE_SOLID, // border line style + const int width = 3, // arrow size + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // Order Object ... +) +{ + // + // set anchor point coordinates if they are not set ... + ChangeArrowEmptyPoint(time, price); + + // + // reset the error value ... + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create an arrow ... + if (!ObjectCreate(chartID, objName, OBJ_ARROW, subWindow, time, price)) + { + // + string message = + __FUNCTION__ + + ": failed to create an arrow! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set the arrow code ... + ObjectSetInteger(chartID, objName, OBJPROP_ARROWCODE, arrowCode); + + // + // set anchor type ... + ObjectSetInteger(chartID, objName, OBJPROP_ANCHOR, anchor); + + // + // set the arrow color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set the border line style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set the arrow's size ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the arrow by mouse + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is false by default, if you want making it possible to highlight and move the object + // change it to true ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return true; +} + +// +// Move the anchor point of Arrow ... +bool MoveArrow( + const long chartID = 0, // chart's ID + const string name = "Arrow", // object name + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + // if point position is not set, move it to the current bar having Bid price ... + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } + + // + // reset the error value + ResetLastError(); + + // + // move the anchor point ... + if (!ObjectMove(chartID, name, 0, time, price)) + { + // + string message = + __FUNCTION__ + + ": failed to move the anchor point! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Delete an arrow ... +bool DeleteArrow( + const long chartID = 0, // chart's ID + const string name = "Arrow" // arrow name +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // delete an arrow ... + if (!ObjectDelete(chartID, name)) + { + // + string message = + __FUNCTION__ + + ": failed to delete an arrow! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Change the arrow code ... +bool ArrowCodeChange( + const long chartID = 0, // chart's ID + const string name = "Arrow", // object name + const uchar code = 252 // arrow code +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // change the arrow code ... + if (!ObjectSetInteger(chartID, name, OBJPROP_ARROWCODE, code)) + { + // + string message = + __FUNCTION__ + + ": failed to change the arrow code! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Change anchor type ... +bool ArrowAnchorChange( + const long chartID = 0, // chart's ID + const string name = "Arrow", // object name + const ENUM_ARROW_ANCHOR anchor = ANCHOR_TOP // anchor type +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // change anchor type ... + if (!ObjectSetInteger(chartID, name, OBJPROP_ANCHOR, anchor)) + { + // + string message = + __FUNCTION__ + + ": failed to change anchor type! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Check anchor point values and set default values +// for empty ones ... +void ChangeArrowEmptyPoint( + datetime &time, + double &price) +{ + // + // if the point's time is not set, it will be on the current bar ... + if (!time) + { + time = TimeCurrent(); + } + + // + // if the point's price is not set, it will have Bid value ... + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } +} + +// +// END Arrow Functions ... +// + +// +// START Horizontal Line Functions ... +// + +// +// Create, Draw the horizontal line ... +bool DrawHorizontalLine( + const long chartID = 0, // chart's ID + const string name = "HLine", // line name + const int subWindow = 0, // subwindow index + double price = 0, // line price + const color clr = clrRed, // line color + const ENUM_LINE_STYLE style = STYLE_SOLID, // line style + const int width = 1, // line width + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + // if the price is not set, set it at the current Bid price level ... + if (!price) + { + price = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // reset the error value ... + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create a horizontal line ... + if (!ObjectCreate(chartID, objName, OBJ_HLINE, subWindow, 0, price)) + { + // + string message = + __FUNCTION__ + + ": failed to create a horizontal line! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set line color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line display style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the line by mouse + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, selection); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return true; +} + +// +// Move horizontal line ... +bool MoveHorizontalLine( + const long chartID = 0, // chart's ID + const string name = "HLine", // line name + double price = 0 // line price +) +{ + // + // if the line price is not set, move it to the current Bid price level ... + if (!price) + { + price = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // reset the error value ... + ResetLastError(); + + // + // move a horizontal line ... + if (!ObjectMove(chartID, name, 0, 0, price)) + { + // + string message = + __FUNCTION__ + + ": failed to move the horizontal line! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Delete a horizontal line ... +bool DeleteHorizontalLine( + const long chartID = 0, // chart's ID + const string name = "HLine" // line name +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // delete a horizontal line ... + if (!ObjectDelete(chartID, name)) + { + // + string message = + __FUNCTION__ + + ": failed to delete a horizontal line! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// END Horizontal Line Functions ... +// + +// +// START Vertical Line Functions ... +// + +// +// Create the vertical line ... +bool DrawVerticalLine( + const long chartID = 0, // chart's ID + const string name = "VLine", // line name + const int subWindow = 0, // subwindow index + datetime time = 0, // line time + const color clr = clrRed, // line color + const ENUM_LINE_STYLE style = STYLE_SOLID, // line style + const int width = 1, // line width + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + // if the line time is not set, draw it via the last bar ... + if (!time) + { + time = TimeCurrent(); + } + + // + // reset the error value + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create a vertical line ... + if (!ObjectCreate(chartID, objName, OBJ_VLINE, subWindow, time, 0)) + { + // + string message = + __FUNCTION__ + + ": failed to create a vertical line! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set line color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line display style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the line by mouse + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return true; +} + +// +// Move the vertical line ... +bool MoveVerticalLine( + const long chartID = 0, // chart's ID + const string name = "VLine", // line name + datetime time = 0 // line time +) +{ + // + // if line time is not set, move the line to the last bar ... + if (!time) + { + time = TimeCurrent(); + } + + // + // reset the error value ... + ResetLastError(); + + // + // move the vertical line ... + if (!ObjectMove(chartID, name, 0, time, 0)) + { + // + string message = + __FUNCTION__ + + ": failed to move the vertical line! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Delete the vertical line ... +bool DeleteVerticalLine( + const long chartID = 0, // chart's ID + const string name = "VLine" // line name +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // delete the vertical line ... + if (!ObjectDelete(chartID, name)) + { + // + string message = + __FUNCTION__ + + ": failed to delete the vertical line! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// END Vertical Line Functions ... +// + +// +// START Rectangle Functions ... +// + +// +// Create rectangle by the given coordinates ... +bool DrawRectangle( + const long chartID = 0, // chart's ID + const string name = "Rectangle", // rectangle name + const int subWindow = 0, // subwindow index + datetime time1 = 0, // first point time + double price1 = 0, // first point price + datetime time2 = 0, // second point time + double price2 = 0, // second point price + const color clr = clrRed, // rectangle color + const ENUM_LINE_STYLE style = STYLE_SOLID, // style of rectangle lines + const int width = 1, // width of rectangle lines + const bool fill = false, // filling rectangle with color + const bool back = false, // in the background + const bool selection = true, // highlight to move + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // Set anchor points' coordinates if they are not set ... + ChangeRectangleEmptyPoints(time1, price1, time2, price2); + + // + // Create a rectangle by the given coordinates ... + result = ObjectCreate(chartID, name, OBJ_RECTANGLE, subWindow, time1, price1, time2, price2); + if (!result) + { + return result; + } + + // + // Set rectangle color ... + ObjectSetInteger(chartID, name, OBJPROP_COLOR, clr); + + // + // Set the style of rectangle lines + ObjectSetInteger(chartID, name, OBJPROP_STYLE, style); + + // + // Set width of the rectangle lines ... + ObjectSetInteger(chartID, name, OBJPROP_WIDTH, width); + + // + // Enable (true) or disable (false) the mode of filling the rectangle ... + ObjectSetInteger(chartID, name, OBJPROP_FILL, fill); + + // + // Display in the foreground (false) or background (true) ... + ObjectSetInteger(chartID, name, OBJPROP_BACK, back); + + // + // Enable (true) or disable (false) the mode of highlighting the rectangle for moving + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object + ObjectSetInteger(chartID, name, OBJPROP_SELECTABLE, selection); + + // + ObjectSetInteger(chartID, name, OBJPROP_SELECTED, selection); + + // + // Hide (true) or display (false) graphical object name in the object list ... + ObjectSetInteger(chartID, name, OBJPROP_HIDDEN, hidden); + + // + // Set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, name, OBJPROP_ZORDER, zOrder); + + // + // Successful execution + return result; +} + +// +// Move the rectangle anchor point ...s +bool RectanglePointChange( + const long chartID = 0, // chart's ID + const string name = "Rectangle", // rectangle name + const int pointIndex = 0, // anchor point index + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + bool result = false; + + // + // if point position is not set, move it to the current bar having Bid price ... + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // Move the anchor point ... + result = ObjectMove(chartID, name, pointIndex, time, price); + if (!result) + { + return result; + } + + // + // Successful execution + return result; +} + +// +// Delete the rectangle ... +bool DeleteRectangle( + const long chartID = 0, // chart's ID + const string name = "Rectangle" // rectangle name +) +{ + // + bool result = false; + + // + result = ObjectDelete(chartID, name); + + // + return result; +} + +// +// Check the values of rectangle's anchor points and set default +// values for empty ones +void ChangeRectangleEmptyPoints( + datetime &time1, double &price1, + datetime &time2, double &price2) +{ + // + // if the first point's time is not set, it will be on the current bar ... + if (!time1) + { + time1 = TimeCurrent(); + } + + // + // if the first point's price is not set, it will have Bid value ... + if (!price1) + { + price1 = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // if the second point's time is not set, it is located 9 bars left from the second one ... + if (!time2) + { + // + // array for receiving the open time of the last 10 bars ... + datetime temp[10]; + CopyTime(Symbol(), Period(), time1, 10, temp); + + // + // set the second point 9 bars left from the first one ... + time2 = temp[0]; + } + + // + // if the second point's price is not set, move it 300 points lower than the first one ... + if (!price2) + { + price2 = price1 - 300 * SymbolInfoDouble(Symbol(), SYMBOL_POINT); + } +} + +// +// END Rectangle Functions ... +// + +// +// START RectangleLabel Functions ... +// + +// +// Create Rectangle Label Object ... +bool DrawRectangleLabel( + const long chartID = 0, // chart's ID + const string name = "RectLabel", // label name + const int subWindow = 0, // subwindow index + const int x = 0, // X coordinate + const int y = 0, // Y coordinate + const int width = 50, // width + const int height = 18, // height + const color bgColor = clrWhiteSmoke, // background color + const ENUM_BORDER_TYPE border = BORDER_SUNKEN, // border type + const ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER, // chart corner for anchoring + const color clr = clrRed, // flat border color (Flat) + const ENUM_LINE_STYLE style = STYLE_SOLID, // flat border style + const int lineWidth = 1, // flat border width + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // + // create a rectangle label + if (!ObjectCreate(chartID, objName, OBJ_RECTANGLE_LABEL, subWindow, 0, 0)) + { + // + string message = + __FUNCTION__ + + ": failed to create a rectangle label! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set label coordinates ... + ObjectSetInteger(chartID, objName, OBJPROP_XDISTANCE, x); + ObjectSetInteger(chartID, objName, OBJPROP_YDISTANCE, y); + + // + // set label size ... + ObjectSetInteger(chartID, objName, OBJPROP_XSIZE, width); + ObjectSetInteger(chartID, objName, OBJPROP_YSIZE, height); + + // + // set background color ... + ObjectSetInteger(chartID, objName, OBJPROP_BGCOLOR, bgColor); + + // + // set border type ... + ObjectSetInteger(chartID, objName, OBJPROP_BORDER_TYPE, border); + + // + // set the chart's corner, relative to which point coordinates are defined ... + ObjectSetInteger(chartID, objName, OBJPROP_CORNER, corner); + + // + // set flat border color (in Flat mode) ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set flat border line style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set flat border width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, lineWidth); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the label by mouse ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, selection); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return true; +} + +// +// Move Rectangle Label .. +bool MoveRectangleLabel( + const long chartID = 0, // chart's ID + const string name = "RectLabel", // label name + const int x = 0, // X coordinate + const int y = 0 // Y coordinate +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // move the rectangle label ... + if (!ObjectSetInteger(chartID, name, OBJPROP_XDISTANCE, x)) + { + // + string message = + __FUNCTION__ + + ": failed to move X coordinate of the label! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + if (!ObjectSetInteger(chartID, name, OBJPROP_YDISTANCE, y)) + { + // + string message = + __FUNCTION__ + + ": failed to move Y coordinate of the label! Error code = " + + (string)GetLastError(); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Delete the rectangle label ... +bool DeleteRectangleLabel( + const long chartID = 0, // chart's ID + const string name = "RectLabel" // label name +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // delete the label ... + if (!ObjectDelete(chartID, name)) + { + // + string message = + __FUNCTION__ + + ": failed to delete a rectangle label! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Change Rectangle Label Size ... +bool ChangeSizeRectangleLabel( + const long chartID = 0, // chart's ID + const string name = "RectLabel", // label name + const int width = 50, // label width + const int height = 18 // label height +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // change label size ... + if (!ObjectSetInteger(chartID, name, OBJPROP_XSIZE, width)) + { + // + string message = + __FUNCTION__ + + ": failed to change the label's width! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + if (!ObjectSetInteger(chartID, name, OBJPROP_YSIZE, height)) + { + // + string message = + __FUNCTION__ + + ": failed to change the label's height! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Change rectangle label border type ... +bool RectLabelChangeBorderType( + const long chartID = 0, // chart's ID + const string name = "RectLabel", // label name + const ENUM_BORDER_TYPE border = BORDER_SUNKEN // border type +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // change border type ... + if (!ObjectSetInteger(chartID, name, OBJPROP_BORDER_TYPE, border)) + { + // + string message = + __FUNCTION__ + + ": failed to change the border type! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// END RectangleLabel Functions ... +// + +// +// START TrendLine Funcions ... +// + +// +// Create a trend line by the given coordinates ... +bool DrawTrendLine( + const long chartID = 0, // chart's ID + const string name = "TrendLine", // line name + const int subWindow = 0, // subwindow index + datetime time1 = 0, // first point time + double price1 = 0, // first point price + datetime time2 = 0, // second point time + double price2 = 0, // second point price + const color clr = clrYellow, // line color + const ENUM_LINE_STYLE style = STYLE_SOLID, // line style + const int width = 1, // line width + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool rayRight = false, // line's continuation to the right + const bool hidden = false, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + // set anchor points' coordinates if they are not set ... + ChangeTrendLineEmptyPoints( + time1, + price1, + time2, + price2); + + // + // reset the error value ... + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // create a trend line by the given coordinates ... + if (!ObjectCreate(chartID, objName, OBJ_TREND, subWindow, time1, price1, time2, price2)) + { + // + string message = + __FUNCTION__ + + ": failed to create a trend line! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set line color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line display style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the line by mouse + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // enable true or disable false the mode of continuation of the line's display to the right ... + ObjectSetInteger(chartID, objName, OBJPROP_RAY_RIGHT, rayRight); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return true; +} + +// +// Move trend line anchor point ... | +bool ChangeTrendLinePoint( + const long chartID = 0, // chart's ID + const string name = "TrendLine", // line name + const int pointindex = 0, // anchor point index + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + // if point position is not set, move it to the current bar having Bid price ... + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // reset the error value ... + ResetLastError(); + + // + // move trend line's anchor point ... + if (!ObjectMove(chartID, name, pointindex, time, price)) + { + // + string message = + __FUNCTION__ + + ": failed to move the anchor point! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// The function deletes the trend line from the chart ... +bool DeleteTrendLine( + const long chartID = 0, // chart's ID + const string name = "TrendLine" // line name +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // delete a trend line ... + if (!ObjectDelete(chartID, name)) + { + // + string message = + __FUNCTION__ + + ": failed to delete a trend line! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Check the values of trend line's anchor points and set default ... +// values for empty ones ... +void ChangeTrendLineEmptyPoints( + datetime &time1, + double &price1, + datetime &time2, + double &price2) +{ + // + // if the first point's time is not set, it will be on the current bar ... + if (!time1) + { + time1 = TimeCurrent(); + } + + // + // if the first point's price is not set, it will have Bid value ... + if (!price1) + { + price1 = SymbolInfoDouble(Symbol(), SYMBOL_BID); + } + + // + // if the second point's time is not set, it is located 9 bars left from the second one ... + if (!time2) + { + // + // array for receiving the open time of the last 10 bars ... + datetime temp[10]; + CopyTime(Symbol(), Period(), time1, 10, temp); + + // + // set the second point 9 bars left from the first one ... + time2 = temp[0]; + } + + // + // if the second point's price is not set, it is equal to the first point's one ... + if (!price2) + { + price2 = price1; + } +} + +// +// END TrendLine Functions ... +// + +// +// START Text Functions ... +// + +// +// Create and Draw a Text Object ... +bool DrawText( + const long chartID = 0, // chart's ID + const string name = "Text", // object name + const int subWindow = 0, // subwindow index + datetime time = 0, // anchor point time + double price = 0, // anchor point price + const string text = "Text", // the text itself + const string font = "Arial", // font + const int fontSize = 10, // font size + const color clr = clrRed, // color + const double angle = 0.0, // text slope + const ENUM_ANCHOR_POINT anchor = ANCHOR_CENTER, // anchor type + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + // set anchor point coordinates if they are not set ... + ChangeTextEmptyPoint(time, price); + + // + // reset the error value ... + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // + // create Text object + if (!ObjectCreate(chartID, objName, OBJ_TEXT, subWindow, time, price)) + { + // + string message = + __FUNCTION__ + + ": failed to create \"Text\" object! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set the text ... + ObjectSetString(chartID, objName, OBJPROP_TEXT, text); + + // + // set text font ... + ObjectSetString(chartID, objName, OBJPROP_FONT, font); + + // + // set font size ... + ObjectSetInteger(chartID, objName, OBJPROP_FONTSIZE, fontSize); + + // + // set the slope angle of the text ... + ObjectSetDouble(chartID, objName, OBJPROP_ANGLE, angle); + + // + // set anchor type ... + ObjectSetInteger(chartID, objName, OBJPROP_ANCHOR, anchor); + + // + // set color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving the object by mouse ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return true; +} + +// +// Move the anchor point ... +bool MoveText( + const long chartID = 0, // chart's ID + const string name = "Text", // object name + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + // + // if point position is not set, move it to the current bar having Bid price + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } + + // + // reset the error value ... + ResetLastError(); + + // + // move the anchor point .. + if (!ObjectMove(chartID, name, 0, time, price)) + { + // + string message = + __FUNCTION__ + + ": failed to move the anchor point! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Change the object text ... +bool ChangeText( + const long chartID = 0, // chart's ID + const string name = "Text", // object name + const string text = "Text" // text +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // change object text ... + if (!ObjectSetString(chartID, name, OBJPROP_TEXT, text)) + { + // + string message = + __FUNCTION__ + + ": failed to change the text! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Delete Text object ... +bool DeleteText( + const long chartID = 0, // chart's ID + const string name = "Text" // object name +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // delete the object ... + if (!ObjectDelete(chartID, name)) + { + // + string message = + __FUNCTION__ + + ": failed to delete \"Text\" object! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution + return true; +} + +// +// Check anchor point values and set default values +// for empty ones ... +void ChangeTextEmptyPoint( + datetime &time, + double &price) +{ + // + // if the point's time is not set, it will be on the current bar ... + if (!time) + { + time = TimeCurrent(); + } + + // + // if the point's price is not set, it will have Bid value ... + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } +} + +// +// END Text Functions ... +// + +// +// START Fibonacchi Functions ... +// + +// +// Create Fibonacci Retracement by the given coordinates ... +bool DrawFibonacci( + const long chartID = 0, // chart's ID + const string name = "Fibonacci", // object name + const int subWindow = 0, // subwindow index + datetime time1 = 0, // first point time + double price1 = 0, // first point price + datetime time2 = 0, // second point time + double price2 = 0, // second point price + const color clr = clrRed, // object color + const ENUM_LINE_STYLE style = STYLE_SOLID, // object line style + const int width = 1, // object line width + const bool back = false, // in the background + const bool selection = true, // highlight to move + const bool rayRight = false, // object's continuation to the right + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + // set anchor points' coordinates if they are not set ... + ChangeFibonacciEmptyPoints(time1, price1, time2, price2); + + // + // reset the error value ... + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // Create Fibonacci Retracement by the given coordinates ... + if (!ObjectCreate(chartID, objName, OBJ_FIBO, subWindow, time1, price1, time2, price2)) + { + // + string message = + __FUNCTION__ + + ": failed to create \"Fibonacci Retracement\"! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of highlighting the channel for moving + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // enable true or disable false the mode of continuation of the object's display to the right ... + ObjectSetInteger(chartID, objName, OBJPROP_RAY_RIGHT, rayRight); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // successful execution ... + return true; +} + +// +// Create Fibonacci Retracement by the given coordinates ... +bool DrawCustomFibonacci( + // + int levels, // number of level lines + double &values[], // values of level lines + color &colors[], // color of level lines + ENUM_LINE_STYLE &styles[], // style of level lines + int &widths[], // width of level lines + string &descriptions[], // level Descriptions + // + const long chartID = 0, // chart's ID + const string name = "Fibonacci", // object name + const int subWindow = 0, // subwindow index + datetime time1 = 0, // first point time + double price1 = 0, // first point price + datetime time2 = 0, // second point time + double price2 = 0, // second point price + const color clr = clrAqua, // object color + const ENUM_LINE_STYLE style = STYLE_DOT, // object line style + const int width = 1, // object line width + const bool back = false, // in the background + const bool selection = true, // highlight to move + const bool rayRight = false, // object's continuation to the right + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + // set anchor points' coordinates if they are not set ... + ChangeFibonacciEmptyPoints(time1, price1, time2, price2); + + // + // reset the error value ... + ResetLastError(); + + // + // Normalize Name ... + string objName = drawPrefix + "_" + name; + + // + // Create Fibonacci Retracement by the given coordinates ... + if (!ObjectCreate(chartID, name, OBJ_FIBO, subWindow, time1, price1, time2, price2)) + { + // + string message = + __FUNCTION__ + + ": failed to create \"Fibonacci Retracement\"! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set color ... + ObjectSetInteger(chartID, objName, OBJPROP_COLOR, clr); + + // + // set line style ... + ObjectSetInteger(chartID, objName, OBJPROP_STYLE, style); + + // + // set line width ... + ObjectSetInteger(chartID, objName, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true ... + ObjectSetInteger(chartID, objName, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of highlighting the channel for moving + // when creating a graphical object using ObjectCreate function, the object cannot be + // highlighted and moved by default. Inside this method, selection parameter + // is true by default making it possible to highlight and move the object ... + ObjectSetInteger(chartID, objName, OBJPROP_SELECTABLE, true); + ObjectSetInteger(chartID, objName, OBJPROP_SELECTED, selection); + + // + // enable true or disable false the mode of continuation of the object's display to the right ... + ObjectSetInteger(chartID, objName, OBJPROP_RAY_RIGHT, rayRight); + + // + // hide true or display false graphical object name in the object list ... + ObjectSetInteger(chartID, objName, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart ... + ObjectSetInteger(chartID, objName, OBJPROP_ZORDER, zOrder); + + // + // Change Levels Of Fibonacci ... + bool result = FibonacciLevelsSet( + levels, + values, + colors, + styles, + widths, + descriptions, + chartID, + objName); + + // + // successful execution ... + return result; +} + +// +// Set number of levels and their parameters ... +bool FibonacciLevelsSet( + int levels, // number of level lines + double &values[], // values of level lines + color &colors[], // color of level lines + ENUM_LINE_STYLE &styles[], // style of level lines + int &widths[], // width of level lines + string &descriptions[], // level Descriptions + const long chartID = 0, // chart's ID + const string name = "Fibonacci" // object name +) +{ + // + // check array sizes ... + if ( + levels != ArraySize(colors) || + levels != ArraySize(styles) || + levels != ArraySize(widths) || + levels != ArraySize(widths)) + { + // + string message = + __FUNCTION__ + + ": array length does not correspond to the number of levels, error!"; + + // + LogMessage(message); + + // + return false; + } + + // + // set the number of levels ... + ObjectSetInteger(chartID, name, OBJPROP_LEVELS, levels); + + // + // set the properties of levels in the loop ... + for (int i = 0; i < levels; i++) + { + // + // level value ... + ObjectSetDouble(chartID, name, OBJPROP_LEVELVALUE, i, values[i]); + + // + // level color ... + ObjectSetInteger(chartID, name, OBJPROP_LEVELCOLOR, i, colors[i]); + + // + // level style ... + ObjectSetInteger(chartID, name, OBJPROP_LEVELSTYLE, i, styles[i]); + + // + // level width ... + ObjectSetInteger(chartID, name, OBJPROP_LEVELWIDTH, i, widths[i]); + + // + // level description ... + // ObjectSetString(chartID, name, OBJPROP_LEVELTEXT, i, DoubleToString(100 * values[i], 1)); + ObjectSetString(chartID, name, OBJPROP_LEVELTEXT, i, descriptions[i]); + } + + // + // successful execution ... + return true; +} + +// +// Move Fibonacci Retracement anchor point ... +bool FibonacciPointChange( + const long chartID = 0, // chart's ID + const string name = "Fibonacci", // object name + const int pointIndex = 0, // anchor point index + datetime time = 0, // anchor point time coordinate + double price = 0 // anchor point price coordinate +) +{ + // + // if point position is not set, move it to the current bar having Bid price ... + if (!time) + { + time = TimeCurrent(); + } + + // + if (!price) + { + price = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } + + // + // reset the error value ... + ResetLastError(); + + // + // move the anchor point ... + if (!ObjectMove(chartID, name, pointIndex, time, price)) + { + // + string message = + __FUNCTION__ + + ": failed to move the anchor point! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Delete Fibonacci Retracement ... +bool DeleteFibonachi( + const long chartID = 0, // chart's ID + const string name = "Fibonacci" // object name +) +{ + // + // reset the error value ... + ResetLastError(); + + // + // delete the object ... + if (!ObjectDelete(chartID, name)) + { + // + string message = + __FUNCTION__ + + ": failed to delete \"Fibonacci Retracement\"! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution ... + return true; +} + +// +// Check the values of Fibonacci Retracement anchor points and set +// default values for empty ones ... +void ChangeFibonacciEmptyPoints( + datetime &time1, + double &price1, + datetime &time2, + double &price2) +{ + // + // if the second point's time is not set, it will be on the current bar ... + if (!time2) + { + time2 = TimeCurrent(); + } + + // + // if the second point's price is not set, it will have Bid value ... + if (!price2) + { + price2 = SymbolInfoDouble(_Symbol, SYMBOL_BID); + } + + // + // if the first point's time is not set, it is located 9 bars left from the second one ... + if (!time1) + { + // + // array for receiving the open time of the last 10 bars ... + datetime temp[10]; + CopyTime(Symbol(), Period(), time2, 10, temp); + + // + // set the first point 9 bars left from the second one ... + time1 = temp[0]; + } + + // + // if the first point's price is not set, move it 200 points below the second one ... + if (!price1) + { + price1 = price2 - 200 * SymbolInfoDouble(_Symbol, SYMBOL_POINT); + } +} + +// +// END Fibonacci Functions ... +// + +// +// START Event Functions ... +// + +// +// Create an Event ... +bool EventCreate( + const long chartID = 0, // chart's ID + const string name = "Event", // object name + const int subWindow = 0, // subwindow index + const string text = "Content", // event text + datetime time = 0, // anchor point time + const color clr = clrRed, // color + const int width = 1, // point width when highlighted + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + if (!time) + { + time = TimeCurrent(); + } + + // + ResetLastError(); + + // + if (!ObjectCreate(chartID, name, OBJ_EVENT, subWindow, time, 0)) + { + // + string message = + __FUNCTION__ + + ": failed to create \"Event\" object! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // set event text + ObjectSetString(chartID, name, OBJPROP_TEXT, text); + + // + // set color + ObjectSetInteger(chartID, name, OBJPROP_COLOR, clr); + + // + // set anchor point width if the object is highlighted + ObjectSetInteger(chartID, name, OBJPROP_WIDTH, width); + + // + // display in the foreground false or background true + ObjectSetInteger(chartID, name, OBJPROP_BACK, back); + + // + // enable true or disable false the mode of moving event by mouse + ObjectSetInteger(chartID, name, OBJPROP_SELECTABLE, selection); + ObjectSetInteger(chartID, name, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list + ObjectSetInteger(chartID, name, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart + ObjectSetInteger(chartID, name, OBJPROP_ZORDER, zOrder); + + // + // successful execution + return true; +} + +// +// Change Event object text +bool EventTextChange( + const long chartID = 0, // chart's ID + const string name = "Event", // event name + const string text = "Content" // text +) +{ + // + // reset the error value + ResetLastError(); + + // + // change object text + if (!ObjectSetString(chartID, name, OBJPROP_TEXT, text)) + { + // + string message = + __FUNCTION__ + + ": failed to change the text! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution + return true; +} + +// +// Move Event object +bool EventMove( + const long chartID = 0, // chart's ID + const string name = "Event", // event name + datetime time = 0 // time +) +{ + // + // if time is not set, move event to the last bar + if (!time) + { + time = TimeCurrent(); + } + + // + // reset the error value + ResetLastError(); + + // + // move the object + if (!ObjectMove(chartID, name, 0, time, 0)) + { + // + string message = + __FUNCTION__ + + ": failed to move \"Event\" object! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution + return true; +} + +// +// Delete Event object +bool EventDelete( + const long chartID = 0, // chart's ID + const string name = "Event" // event name +) +{ + // + // reset the error value + ResetLastError(); + + // + // delete the object + if (!ObjectDelete(chartID, name)) + { + // + string message = + __FUNCTION__ + + ": failed to delete \"Event\" object! Error code = " + + (string)GetLastError(); + + // + LogMessage(message); + + // + return false; + } + + // + // successful execution + return true; +} + +// +// END Event Functions ... +// + +// +// START Button Functions ... +// + +// +// Create the button ... +bool ButtonCreate( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const int subWindow = 0, // subwindow index + const int x = 0, // X coordinate + const int y = 0, // Y coordinate + const int width = 50, // button width + const int height = 15, // button height + const ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER, // chart corner for anchoring + const string text = "Button", // text + const string font = "Arial", // font + const int fontSize = 8, // font size + const color clr = clrBlack, // text color + const color bgColor = clrLightGray, // background color + const color borderColor = clrNONE, // border color + const bool state = false, // pressed/released + const bool back = false, // in the background + const bool selection = false, // highlight to move + const bool hidden = true, // hidden in the object list + const long zOrder = 0 // priority for mouse click +) +{ + // + bool result = false; + + // + // create the button + result = ObjectCreate(chartID, name, OBJ_BUTTON, subWindow, 0, 0); + if (!result) + { + return result; + } + + // + // set button coordinates + ObjectSetInteger(chartID, name, OBJPROP_XDISTANCE, x); + ObjectSetInteger(chartID, name, OBJPROP_YDISTANCE, y); + + // + // set button size + ObjectSetInteger(chartID, name, OBJPROP_XSIZE, width); + ObjectSetInteger(chartID, name, OBJPROP_YSIZE, height); + + // + // set the chart's corner, relative to which point coordinates are defined + ObjectSetInteger(chartID, name, OBJPROP_CORNER, corner); + + // + // set the text + ObjectSetString(chartID, name, OBJPROP_TEXT, text); + + // + // set text font + ObjectSetString(chartID, name, OBJPROP_FONT, font); + + // + // set font size + ObjectSetInteger(chartID, name, OBJPROP_FONTSIZE, fontSize); + + // + // set text color + ObjectSetInteger(chartID, name, OBJPROP_COLOR, clr); + + // + // set background color + ObjectSetInteger(chartID, name, OBJPROP_BGCOLOR, bgColor); + + // + // set border color + ObjectSetInteger(chartID, name, OBJPROP_BORDER_COLOR, borderColor); + + // + // display in the foreground false or background true + ObjectSetInteger(chartID, name, OBJPROP_BACK, back); + + // + // set button state + ObjectSetInteger(chartID, name, OBJPROP_STATE, state); + + // + // enable true or disable false the mode of moving the button by mouse + ObjectSetInteger(chartID, name, OBJPROP_SELECTABLE, selection); + ObjectSetInteger(chartID, name, OBJPROP_SELECTED, selection); + + // + // hide true or display false graphical object name in the object list + ObjectSetInteger(chartID, name, OBJPROP_HIDDEN, hidden); + + // + // set the priority for receiving the event of a mouse click in the chart + ObjectSetInteger(chartID, name, OBJPROP_ZORDER, zOrder); + + // + return result; +} + +// +// Move the button ... +bool ButtonMove( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const int x = 0, // X coordinate + const int y = 0 // Y coordinate +) +{ + // + bool result = false; + + // + // move the button + + // + result = ObjectSetInteger(chartID, name, OBJPROP_XDISTANCE, x); + if (!result) + { + return result; + } + + // + result = ObjectSetInteger(chartID, name, OBJPROP_YDISTANCE, y); + + // + return result; +} + +// +// Change button size ... +bool ButtonChangeSize( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const int width = 50, // button width + const int height = 18 // button height +) +{ + // + bool result = false; + + // + // change the button size + + // + result = ObjectSetInteger(chartID, name, OBJPROP_XSIZE, width); + if (!result) + { + return result; + } + + // + result = ObjectSetInteger(chartID, name, OBJPROP_YSIZE, height); + + // + return result; +} + +// +// Change corner of the chart for binding the button ... +bool ButtonChangeCorner( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER // chart corner for anchoring +) +{ + // + bool result = false; + + // + // change anchor corner + + // + result = ObjectSetInteger(chartID, name, OBJPROP_CORNER, corner); + + // + return result; +} + +// +// Change button text ... +bool ButtonTextChange( + const long chartID = 0, // chart's ID + const string name = "Button", // button name + const string text = "Text" // text +) +{ + // + bool result = false; + + // + // change object text + result = ObjectSetString(chartID, name, OBJPROP_TEXT, text); + + // + return result; +} + +// +// Delete the button ... +bool ButtonDelete( + const long chartID = 0, // chart's ID + const string name = "Button" // button name +) +{ + // + bool result = false; + + // + // delete the button + result = ObjectDelete(chartID, name); + + // + return result; +} + +// +// END Button Functions ... +// + +// +// END Regular Draws ... +// + +// +// START Chart Style Drawers ... +// + +// +// Apply Styles On Chart ... +void ApplyChartStyle( + long mChartId = -1, // chart's ID + ENUM_CHART_MODE mMode = CHART_CANDLES, // chart's mMode + bool mShowBidLine = true, // show bid line + bool mShowAskLine = true, // show ask line + bool mShowGrid = false, // show grids on chart + bool mShowVolumes = false, // show volumes + bool mShowTradeLevels = true, // Displaying trade levels in the chart (levels of open positions, Stop Loss, Take Profit and pending orders) + bool mAutoScroll = true, // chart autoscroll + bool mQuickNavigation = true, // chart quick navigation state + color mForeGroundColor = clrWhite, // chart's foreground color + color mBackGroundColor = clrBlack, // chart's background color + color mUpColor = clrGreen, // Up Color + color mDownColor = clrRed, // Down Color + color mBullishColor = clrGreen, // Bullish color + color mBearishColor = clrRed, // Bearish color + color mGridColor = clrGray, // grid color + color mBidLineColor = clrGray, // bid line color + color mAskLineColor = clrRed, // ask line color + color mLineColor = clrLime, // line mMode and doji candlestick color + color mStopColor = clrGold, // Color of stop order levels (Stop Loss and Take Profit) + color mVolumesColor = clrGreen // volumes color +) +{ + // + // Validate Args ... + if (mChartId == -1) + { + mChartId = 0; + } + + // + ChartSetInteger(mChartId, CHART_MODE, mMode); + ChartSetInteger(mChartId, CHART_SHOW_BID_LINE, mShowBidLine); + ChartSetInteger(mChartId, CHART_SHOW_ASK_LINE, mShowAskLine); + ChartSetInteger(mChartId, CHART_SHOW_GRID, mShowGrid); + ChartSetInteger(mChartId, CHART_SHOW_VOLUMES, mShowVolumes); + ChartSetInteger(mChartId, CHART_SHOW_TRADE_LEVELS, mShowTradeLevels); + ChartSetInteger(mChartId, CHART_AUTOSCROLL, mAutoScroll); + ChartSetInteger(mChartId, CHART_QUICK_NAVIGATION, mQuickNavigation); + ChartSetInteger(mChartId, CHART_COLOR_FOREGROUND, mForeGroundColor); + ChartSetInteger(mChartId, CHART_COLOR_BACKGROUND, mBackGroundColor); + ChartSetInteger(mChartId, CHART_COLOR_CHART_UP, mUpColor); + ChartSetInteger(mChartId, CHART_COLOR_CHART_DOWN, mDownColor); + ChartSetInteger(mChartId, CHART_COLOR_CANDLE_BULL, mBullishColor); + ChartSetInteger(mChartId, CHART_COLOR_CANDLE_BEAR, mBearishColor); + ChartSetInteger(mChartId, CHART_COLOR_GRID, mGridColor); + ChartSetInteger(mChartId, CHART_COLOR_BID, mBidLineColor); + ChartSetInteger(mChartId, CHART_COLOR_ASK, mAskLineColor); + ChartSetInteger(mChartId, CHART_COLOR_STOP_LEVEL, mStopColor); + ChartSetInteger(mChartId, CHART_COLOR_CHART_LINE, mLineColor); + ChartSetInteger(mChartId, CHART_COLOR_VOLUME, mVolumesColor); +} + +// +// Retrieve Chart Size in Pixel ... +struct XSize +{ + long width; + long height; + + // + int x; + int y; + int w; + int h; + + // + int wStep; + int hStep; +}; + +// +// Retrieve Chart Size ... +bool GetChartSize( + XSize &result, // Holds Result ... + long chartID = 0 // Specified Chart ID ... +) +{ + // + bool mResult = false; + + // + mResult = ChartGetInteger(0, CHART_WIDTH_IN_PIXELS, 0, result.width); + if (!mResult) + { + return mResult; + } + + // + mResult = ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS, 0, result.height); + + // + return mResult; +} + +// +// END Chart Style Drawers ... +// + +// +// START Custom Drawings ... +// + +// +// Define a Draw Specifications ... +struct XDrawSpecifications +{ + // + // Props ... + + // + bool draw; // Draw or Not ... + + // + int width; // Draw Witdth ... + color clr; // Draw Color ... + ENUM_LINE_STYLE style; // Draw Style ... + + // + bool back; // in the background + bool fill; // fill object if supported + bool selection; // highlight to move + bool rayRight; // line's continuation to the right + bool hidden; // hidden in the object list + long zOrder; // priority for mouse click + + // + string label; // Label ... + color labelColor; // Label Color ... + double labelAngel; // Label Angle ... + string labelFont; // Label Font ... + int labelFontSize; // Label Font Size ... + ENUM_ANCHOR_POINT labelAnchor; // Label Anchor Point ... + + // + // Constructor ... + XDrawSpecifications() + { + Clean(); + } + + // + // Operator ... + void operator=(const XDrawSpecifications &value) + { + // + clr = value.clr; + draw = value.draw; + width = value.width; + style = value.style; + + // + back = value.back; + hidden = value.hidden; + zOrder = value.zOrder; + rayRight = value.rayRight; + selection = value.selection; + + // + fill = value.fill; + + // + label = value.label; + labelColor = value.labelColor; + labelAngel = value.labelAngel; + labelFont = value.labelFont; + labelFontSize = value.labelFontSize; + labelAnchor = value.labelAnchor; + } + + // + // Functions ... + + // + void Clean() + { + // + draw = false; + width = 1; + clr = CLR_NONE; + style = STYLE_SOLID; + + // + back = false; + hidden = false; + rayRight = false; + selection = false; + fill = false; + + // + zOrder = 0; + + // + label = ""; + labelColor = CLR_NONE; + labelAngel = 0; + labelFont = "Arial"; + labelFontSize = 20; + labelAnchor = ANCHOR_LEFT_UPPER; + } + + // + void Label( + string mLabel = "", // Label ... + color mLabelColor = CLR_NONE, // Label Color ... + string mLabelFont = "Arial", // Label Font ... + int mLabelFontSize = 20, // Label Font Size ... + ENUM_ANCHOR_POINT mLabelAnchor = ANCHOR_LEFT_UPPER, // Label Anchor Point ... + double mLabelAngel = 0 // Label Angle ... + ) + { + // + label = mLabel; + labelFont = mLabelFont; + labelColor = mLabelColor; + labelAngel = mLabelAngel; + labelAnchor = mLabelAnchor; + labelFontSize = mLabelFontSize; + } +}; + +// +// Candle Draw Specifications ... +struct XOHCLDrawSpecification +{ + // + // Props ... + XDrawSpecifications openStyle; + XDrawSpecifications highStyle; + XDrawSpecifications closeStyle; + XDrawSpecifications lowStyle; + + // + // Constructors ... + XOHCLDrawSpecification() + { + Clean(); + } + + // + // Operators ... + void operator=(const XOHCLDrawSpecification &value) + { + // + lowStyle = value.lowStyle; + openStyle = value.openStyle; + highStyle = value.highStyle; + closeStyle = value.closeStyle; + } + + // + // Functions ... + + // + void Clean() + { + // + lowStyle.Clean(); + openStyle.Clean(); + highStyle.Clean(); + closeStyle.Clean(); + } + + // + void Default() + { + // + // Open ... + openStyle.width = 1; + openStyle.draw = true; + openStyle.clr = clrLime; + openStyle.style = STYLE_SOLID; + openStyle.Label( + "O", + openStyle.clr); + + // + // High ... + highStyle.width = 1; + highStyle.draw = true; + highStyle.clr = clrAqua; + highStyle.style = STYLE_SOLID; + highStyle.Label( + "H", + highStyle.clr); + + // + // Close ... + closeStyle.width = 1; + closeStyle.draw = true; + closeStyle.clr = clrRed; + closeStyle.style = STYLE_SOLID; + closeStyle.Label( + "C", + closeStyle.clr); + + // + // Low ... + lowStyle.width = 1; + lowStyle.draw = true; + lowStyle.clr = clrMagenta; + lowStyle.style = STYLE_SOLID; + lowStyle.Label( + "L", + lowStyle.clr); + } + + // + void Width(int value) + { + // + lowStyle.width = value; + openStyle.width = value; + highStyle.width = value; + closeStyle.width = value; + } + + // + void Style(ENUM_LINE_STYLE value) + { + // + lowStyle.style = value; + openStyle.style = value; + highStyle.style = value; + closeStyle.style = value; + } + + // + void Color(color value) + { + // + lowStyle.clr = value; + openStyle.clr = value; + highStyle.clr = value; + closeStyle.clr = value; + } + + // + void RayRight(bool value) + { + // + lowStyle.rayRight = value; + openStyle.rayRight = value; + highStyle.rayRight = value; + closeStyle.rayRight = value; + } + + // + void Draw(bool value) + { + // + lowStyle.draw = value; + openStyle.draw = value; + highStyle.draw = value; + closeStyle.draw = value; + } + + // + void Back(bool value) + { + // + lowStyle.back = value; + openStyle.back = value; + highStyle.back = value; + closeStyle.back = value; + } + + // + void Fill(bool value) + { + // + lowStyle.fill = value; + openStyle.fill = value; + highStyle.fill = value; + closeStyle.fill = value; + } + + // + void Label(string value) + { + // + lowStyle.Label(value); + openStyle.Label(value); + highStyle.Label(value); + closeStyle.Label(value); + } + + // + void SetLabelPrefix(string value) + { + // + lowStyle.label = value + " " + lowStyle.label; + openStyle.label = value + " " + openStyle.label; + highStyle.label = value + " " + highStyle.label; + closeStyle.label = value + " " + closeStyle.label; + } +}; + +// +bool RemoveCandle( + XOHCL &c, + long chartId = 0, + int subWindow = 0 // +) +{ + // + bool result = false; + + // + string cTag = GenerateTag(c); + + // + result = IsDrawExists( + cTag, + chartId, + subWindow); + if (!result) + { + return result; + } + + // + RemoveDraws( + cTag, + chartId, + subWindow); + + // + return result; +} + +// +// XOHCL ... +void DrawCandleAsLine( + long chartId, // Chart ID ... + int subWindow, // SubWindow ... + XOHCL &c, // the Candle Which required to Draw ... + const datetime time, // Candle Time ... + XOHCLDrawSpecification &config, // Draw Specifications ... + string tag = "", // Draw Tag ... + bool update = true, // Update Draw if Exists ... + bool drawMidLine = true // Draw Open Close Middle Line ... +) +{ + // + datetime cTime = TimeCurrent(); + XDrawSpecifications specs; + + // + string baseTag = tag + GenerateTag(c); + + // + // Open ... + specs = config.openStyle; + if (specs.draw) + { + // + double value = c.open; + string valueTag = "|O|"; + + // + string mTag = baseTag + valueTag + ToString(value); + string mLblTag = baseTag + valueTag + "_lbl"; + + // + // Check if Object Exists Delete it ... + bool isExists = IsDrawExists( + mTag, + chartId, + subWindow // + ); + bool canDraw = !isExists || (isExists && update); + + // + if (isExists && canDraw) + { + // + DeleteText( + chartId, + mLblTag // + ); + + // + DeleteTrendLine( + chartId, + mTag // + ); + } + + // + if (canDraw) + { + // + // Draw Label ... + if (StringLen(specs.label) > 0) + { + DrawText( + chartId, + mLblTag, + subWindow, + cTime, + value, + specs.label, + specs.labelFont, + specs.labelFontSize, + specs.labelColor, + specs.labelAngel, + specs.labelAnchor, + specs.back, + specs.selection, + specs.hidden, + specs.zOrder // + ); + } + + // + // Draw ... + DrawTrendLine( + chartId, + mTag, + subWindow, + time, + value, + cTime, + value, + specs.clr, + specs.style, + specs.width, + specs.back, + specs.selection, + specs.rayRight, + specs.hidden, + specs.zOrder // + ); + } + } + + // + // High ... + specs = config.highStyle; + if (specs.draw) + { + // + double value = c.high; + string valueTag = "|H|"; + + // + string mTag = baseTag + valueTag + ToString(value); + string mLblTag = baseTag + valueTag + "_lbl"; + + // + // Check if Object Exists Delete it ... + bool isExists = IsDrawExists( + mTag, + chartId, + subWindow // + ); + bool canDraw = !isExists || (isExists && update); + + // + if (isExists && canDraw) + { + // + DeleteText( + chartId, + mLblTag // + ); + + // + DeleteTrendLine( + chartId, + mTag // + ); + } + + // + if (canDraw) + { + // + // Draw Label ... + if (StringLen(specs.label) > 0) + { + DrawText( + chartId, + mLblTag, + subWindow, + cTime, + value, + specs.label, + specs.labelFont, + specs.labelFontSize, + specs.labelColor, + specs.labelAngel, + specs.labelAnchor, + specs.back, + specs.selection, + specs.hidden, + specs.zOrder // + ); + } + + // + // Draw ... + DrawTrendLine( + chartId, + mTag, + subWindow, + time, + value, + cTime, + value, + specs.clr, + specs.style, + specs.width, + specs.back, + specs.selection, + specs.rayRight, + specs.hidden, + specs.zOrder // + ); + } + } + + // + // Close ... + specs = config.closeStyle; + if (specs.draw) + { + // + double value = c.close; + string valueTag = "|C|"; + + // + string mTag = baseTag + valueTag + ToString(value); + string mLblTag = baseTag + valueTag + "_lbl"; + + // + // Check if Object Exists Delete it ... + bool isExists = IsDrawExists( + mTag, + chartId, + subWindow // + ); + bool canDraw = !isExists || (isExists && update); + + // + if (isExists && canDraw) + { + // + DeleteText( + chartId, + mLblTag // + ); + + // + DeleteTrendLine( + chartId, + mTag); + } + + // + if (canDraw) + { + // + // Draw Label ... + if (StringLen(specs.label) > 0) + { + DrawText( + chartId, + mLblTag, + subWindow, + cTime, + value, + specs.label, + specs.labelFont, + specs.labelFontSize, + specs.labelColor, + specs.labelAngel, + specs.labelAnchor, + specs.back, + specs.selection, + specs.hidden, + specs.zOrder // + ); + } + + // + // Draw ... + DrawTrendLine( + chartId, + mTag, + subWindow, + time, + value, + cTime, + value, + specs.clr, + specs.style, + specs.width, + specs.back, + specs.selection, + specs.rayRight, + specs.hidden, + specs.zOrder // + ); + } + } + + // + // Low ... + specs = config.lowStyle; + if (specs.draw) + { + // + double value = c.low; + string valueTag = "|L|"; + + // + string mTag = baseTag + valueTag + ToString(value); + string mLblTag = baseTag + valueTag + "_lbl"; + + // + // Check if Object Exists Delete it ... + bool isExists = IsDrawExists( + mTag, + chartId, + subWindow // + ); + bool canDraw = !isExists || (isExists && update); + + // + if (isExists && canDraw) + { + // + DeleteText( + chartId, + mLblTag // + ); + + // + DeleteTrendLine( + chartId, + mTag); + } + + // + if (canDraw) + { + // + // Draw Label ... + if (StringLen(specs.label) > 0) + { + DrawText( + chartId, + mLblTag, + subWindow, + cTime, + value, + specs.label, + specs.labelFont, + specs.labelFontSize, + specs.labelColor, + specs.labelAngel, + specs.labelAnchor, + specs.back, + specs.selection, + specs.hidden, + specs.zOrder // + ); + } + + // + // Draw ... + DrawTrendLine( + chartId, + mTag, + subWindow, + time, + value, + cTime, + value, + specs.clr, + specs.style, + specs.width, + specs.back, + specs.selection, + specs.rayRight, + specs.hidden, + specs.zOrder // + ); + } + } +} + +// +void DrawCandleAsBox( + long chartId, // Chart ID ... + int subWindow, // SubWindow ... + XOHCL &c, // the Candle Which required to Draw ... + const datetime time, // Candle Time ... + XOHCLDrawSpecification &config, // Draw Specifications ... + string tag = "", // Draw Tag ... + bool drawBody = true, // Draw Body ... + bool drawShadows = true, // Draw Shadows ... + bool update = true // Update Draw if Exists ... +) +{ + // + datetime cTime = TimeCurrent(); + + // + // First Check all Styles Must Be Draw true ... + bool canDraw = + // + config.openStyle.draw && + config.highStyle.draw && + config.closeStyle.draw && + config.lowStyle.draw + // + ; + + // + if (!canDraw) + { + return; + } + + // + // Next we have to determine Candle is Bullish or Bearish ... + // + bool isBullish = + c.open < c.close; + + // + bool isBearish = + c.open > c.close; + + // + XDrawSpecifications bodySpec; + if (isBullish) + { + bodySpec = config.openStyle; + } + else if (isBearish) + { + bodySpec = config.closeStyle; + } + else + { + // + bodySpec.clr = clrGray; + } + + // + // Now We have to Draw 3 Rectangle ... + // 1- Up Shadow + // 2- Candle Body + // 3- Down Shadow + + // + double upPrice = MathMax(c.open, c.close); + double downPrice = MathMin(c.open, c.close); + double upShadowSize = c.high - upPrice; + double downShadowSize = downPrice - c.low; + + // + string mTag = GenerateTag(c); + + // + // Draw Up Shadow ... + if (drawShadows) + { + // + string upShadowTag = mTag + "|US|"; + + XDrawSpecifications spec = config.highStyle; + + // + // Check if Object Exists Delete it ... + bool isExists = IsDrawExists( + upShadowTag, + chartId, + subWindow // + ); + + // + bool canDraw = !isExists || (isExists && update); + + // + if (isExists && canDraw) + { + // + DeleteRectangle( + chartId, + upShadowTag // + ); + } + + // + if (canDraw) + { + // + // New ... + DrawRectangle( + chartId, + upShadowTag, + subWindow, + time, + c.high, + cTime, + upPrice, + spec.clr, + spec.style, + spec.width, + spec.fill, + spec.back, + spec.selection, + spec.hidden, + spec.zOrder // + ); + } + } + + // + // Draw Body ... + if (drawBody) + { + // + string bodyTag = mTag + "|BDY|"; + + // + // Check if Object Exists Delete it ... + bool isExists = IsDrawExists( + bodyTag, + chartId, + subWindow // + ); + + // + bool canDraw = !isExists || (isExists && update); + + // + if (isExists && canDraw) + { + // + DeleteRectangle( + chartId, + bodyTag // + ); + } + + // + if (canDraw) + { + // + // New ... + DrawRectangle( + chartId, + bodyTag, + subWindow, + time, + upPrice, + cTime, + downPrice, + bodySpec.clr, + bodySpec.style, + bodySpec.width, + bodySpec.fill, + bodySpec.back, + bodySpec.selection, + bodySpec.hidden, + bodySpec.zOrder // + ); + } + } + + // + // Draw Down Shadow ... + if (drawShadows) + { + // + string downShadowTag = mTag + "|DS|"; + + XDrawSpecifications spec = config.lowStyle; + + // + // Check if Object Exists Delete it ... + bool isExists = IsDrawExists( + downShadowTag, + chartId, + subWindow // + ); + + // + bool canDraw = !isExists || (isExists && update); + + // + if (isExists && canDraw) + { + // + DeleteRectangle( + chartId, + downShadowTag // + ); + } + + // + if (canDraw) + { + // + // New ... + DrawRectangle( + chartId, + downShadowTag, + subWindow, + time, + downPrice, + cTime, + downPrice + downShadowSize, + spec.clr, + spec.style, + spec.width, + spec.fill, + spec.back, + spec.selection, + spec.hidden, + spec.zOrder // + ); + } + } +} + +// +// END Custom Drawings ... +// diff --git a/Libraries/x-saherelm.http.lib.mq5 b/Libraries/x-saherelm.http.lib.mq5 new file mode 100644 index 00000000..97f7ac0a --- /dev/null +++ b/Libraries/x-saherelm.http.lib.mq5 @@ -0,0 +1,177 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Http Library +// ------------------------------------------ +// Name: XHttp +// Description: provide http communication +// abilities ... +// +// +// 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 Model Definition ... +// +enum X_HTTP_METHOD +{ + X_HTTP_GET, + X_HTTP_POST +}; +// +// END Model Definition ... +// + +// +// START Inputs ... +// +// +// END Inputs ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Provided Functions ... +// +// +// Initial Library if required ... +bool OnInInitHttpLibrary() +{ + return false; +} + +// +// DeInitial Library if required ... +void OnDeinitHttpLibrary() +{ +} + +// +// Convert enum to String ... +string ToString(X_HTTP_METHOD method) +{ + // + string result = ""; + + // + switch (method) + { + // + case X_HTTP_GET: + result = "GET"; + break; + + // + case X_HTTP_POST: + result = "POST"; + break; + } + + // + return result; +} + +// +// Send Global Request ... +int SendRequest( + X_HTTP_METHOD method, // Httm Request Method + const string url, // Server Address + const string headers, // Headers providing + const char &payload[], // the Data which needs to Send + char &response[], // Response of request + string responseHeaders, // Response Headers + int timeout = 500 // Timeout for response default is 500 +) +{ + // + int result = -1; + + // + string strMethod = ToString(method); + if (StringLen(strMethod) == 0) { + return result; + } + + // + result = WebRequest( + strMethod, + url, + headers, + timeout, + payload, + response, + responseHeaders + ); + + // + return result; +} + +// +// Get Request ... +int GetRequest( + const string url, // Server Address + const string headers, // Headers providing + const char &payload[], // the Data which needs to Send + char &response[], // Response of request + string responseHeaders, // Response Headers + int timeout = 500 // Timeout for response default is 500 +) { + // + int result = SendRequest( + X_HTTP_GET, + url, + headers, + payload, + response, + responseHeaders, + timeout + ); + + // + return result; +} + +// +// Post Request ... +int PostRequest( + const string url, // Server Address + const string headers, // Headers providing + const char &payload[], // the Data which needs to Send + char &response[], // Response of request + string responseHeaders, // Response Headers + int timeout = 500 // Timeout for response default is 500 +) { + // + int result = SendRequest( + X_HTTP_POST, + url, + headers, + payload, + response, + responseHeaders, + timeout + ); + + // + return result; +} +// +// END Provided Functions ... +// diff --git a/Libraries/x-saherelm.log.lib.mq5 b/Libraries/x-saherelm.log.lib.mq5 new file mode 100644 index 00000000..ad341253 --- /dev/null +++ b/Libraries/x-saherelm.log.lib.mq5 @@ -0,0 +1,1084 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Logger Library +// --------------------------------------- +// Name: XLogger +// Description: provides Logging abilities ... +// +// +// 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 ... +// +// input group "Logging"; +// input bool enableLogging = true; // Enable Logging +bool enableLogging = true; // Enable Logging +// +// END Inputs ... +// + +// +// START Global Definitions: Variables, Properties and etc ... +// +string logTag = "X-Logger"; // LogTag +// +// END Global Definitions: Variables, Properties and etc ... +// + +// +// START Provided Functions ... +// +// +// Logging a Message ... +void LogMessage(string message) +{ + // + if (!enableLogging) + { + return; + } + + // + Print(logTag, " > ", message); +} +void LogMessage(string tag, string message) +{ + // + if (!enableLogging) + { + return; + } + + // + Print(tag, " > ", message); +} + +// +void LogEmptyLine() +{ + LogMessage(" "); +} + +// +void LogError( + int error = -1 // Specific Error +) { + // + if (error <= -1) { + error = GetLastError(); + } + + // + string errorMsg = GetErrorDescription(error); + + // + LogMessage("Error: " + errorMsg); +} + +// +// Logging an Array ... +void LogArray(int &array[]) +{ + // + if (!enableLogging) + { + return; + } + + // + Print(logTag, ">"); + ArrayPrint(array); +} +void LogArray(double &array[]) +{ + // + if (!enableLogging) + { + return; + } + + // + Print(logTag, ">"); + ArrayPrint(array); +} +void LogArray(string &array[]) +{ + // + if (!enableLogging) + { + return; + } + + // + Print(logTag, ">"); + ArrayPrint(array); +} +// +// END Provided Functions ... +// + + +// +// 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; +} diff --git a/Libraries/x-saherelm.xtrade.lib.mq5 b/Libraries/x-saherelm.xtrade.lib.mq5 new file mode 100644 index 00000000..c52370ba --- /dev/null +++ b/Libraries/x-saherelm.xtrade.lib.mq5 @@ -0,0 +1,3018 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Seriallize Library +// --------------------------------------- +// Name: XTradeLib +// Description: All models related to Trade ... +// +// +// 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 + +// +// Imports ... +#include +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Classes/x-saherelm.xdata-collector.mq5" + +// +// Definitions ... + +// +// a List of Used Tokens ... + +// +// Common ... +string XIDToken = "ID"; +string XModeToken = "MD"; +string XTypeToken = "TY"; +string XPeriodToken = "PR"; +string XProviderToken = "PRV"; + +// +string XTPToken = "TP"; +string XSLToken = "SL"; +string XTimeToken = "TM"; +string XEntryToken = "EN"; +string XVolumeToken = "VL"; +string XSymbolToken = "SMBL"; + +// +string XSupportToken = "SP"; +string XEQMSupportToken = "EQM"; + +// +// Available Order Modes ... +enum ENUM_X_ORDER_MODES +{ + X_ORDER_MODE_NOTHING, // Nothing + X_ORDER_MODE_MARKET, // Market Order + X_ORDER_MODE_STOP, // Pending Stop Order + X_ORDER_MODE_LIMIT, // Pending Limit Order + X_ORDER_MODE_STOP_LIMIT, // Pending Stop Limit Order +}; + +// +// Select Positions Type ... +enum ENUM_X_POSITION_SELECT_METHODS +{ + X_POSITION_SELECT_NONE, // None + X_POSITION_SELECT_MAX, // Max + X_POSITION_SELECT_MIN, // Min + X_POSITION_SELECT_BOTH, // Min and Max + X_POSITION_SELECT_ALL, // All +}; + +// +// Signal Execution Result ... +// note that some of them must be handles in +// EA's ... +enum ENUM_X_SIGNAL_EXECUTION_RESULT +{ + // + X_SIGNAL_EXECUTION_UNKNOWN, // Unknown + X_SIGNAL_EXECUTION_SUCCEED, // Succed + X_SIGNAL_EXECUTION_FAILED_NO_EQUITY, // No Equity for Trade + X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR, // Price Error + X_SIGNAL_EXECUTION_FAILED_MAX_REACHED, // Max Allowed Positions Reached + X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS, // Invalid Params +}; + +// +// Structs ... + +// +// Model a Signal ... +struct XSignal +{ + // + // Props ... + + // + ulong positionId; // if Executed this filled ... + double entry; // Exntry or Execution Price ... + double volume; // Position Volume ... + + // + datetime time; // Issue Time ... + + // + double tps[]; // a Collection of TP(s) ... + double sls[]; // a Collection of SL(s) ... + + // + string symbol; // Trading Symbol ... + string provider; // Signaller ... + string comment; // Comment ... + + // + ENUM_TIMEFRAMES period; // Trading TimeFrame ... + ENUM_POSITION_TYPE type; // Long (Buy) or Short (Sell) ... + ENUM_X_ORDER_MODES mode; // Execution Mode ... + + // + XSignal supports[]; // a Collecion of Support Signals ... + XOHCLSupRes supportResistances; // Support and Resistances ... + + // + // Constructor ... + XSignal() + { + Clean(); + } + + // + bool Prepare( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_POSITION_TYPE mType, // Long (Buy) or Short (Sell) + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mVolume, // Volume + double sl = 0, // Stop Loss + double tp = 0 // Take Profit + ) + { + // + bool result = false; + + // + result = + // + IsValid(mMode) && + IsValid(mSymbol) && + IsValid(mPeriod) && + NotEmpty(mEntry) && + NotEmpty(mVolume) && + IsValid(mProvider) + // + ; + if (!result) + { + return result; + } + + // + type = mType; + mode = mMode; + symbol = mSymbol; + period = mPeriod; + provider = mProvider; + + // + // Normalization Values ... + sl = NormalizePrice(sl, mSymbol); + tp = NormalizePrice(tp, mSymbol); + mEntry = NormalizePrice(mEntry, mSymbol); + mVolume = NormalizeVolume(mVolume, mSymbol); + + // + entry = mEntry; + volume = mVolume; + + // + Add( + sl, + sls + // + ); + + // + Add( + tp, + tps + // + ); + + // + time = TimeCurrent(); + + // + result = IsValid(); + + // + return result; + } + + // + bool PrepareLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mVolume, // Volume + double sl = 0, // Stop Loss + double tp = 0 // Take Profit + ) + { + // + return Prepare( + mSymbol, + mProvider, + mPeriod, + POSITION_TYPE_BUY, + mMode, + mEntry, + mVolume, + sl, + tp + // + ); + } + + // + bool PrepareShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + ENUM_X_ORDER_MODES mMode, // Execution Mode + double mEntry, // Entry Price + double mVolume, // Volume + double sl = 0, // Stop Loss + double tp = 0 // Take Profit + ) + { + // + return Prepare( + mSymbol, + mProvider, + mPeriod, + POSITION_TYPE_SELL, + mMode, + mEntry, + mVolume, + sl, + tp + // + ); + } + + // + // Market Mode ... + + // + bool PrepareMarketLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double sl = 0, // Stop Loss + double tp = 0 // Take Profit + ) + { + // + return Prepare( + mSymbol, + mProvider, + mPeriod, + POSITION_TYPE_BUY, + X_ORDER_MODE_MARKET, + mEntry, + mVolume, + sl, + tp + // + ); + } + + // + bool PrepareMarketShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double sl = 0, // Stop Loss + double tp = 0 // Take Profit + ) + { + // + return Prepare( + mSymbol, + mProvider, + mPeriod, + POSITION_TYPE_SELL, + X_ORDER_MODE_MARKET, + mEntry, + mVolume, + sl, + tp + // + ); + } + + // + // Stop Mode ... + + // + bool PrepareStopLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double sl = 0, // Stop Loss + double tp = 0 // Take Profit + ) + { + // + return Prepare( + mSymbol, + mProvider, + mPeriod, + POSITION_TYPE_BUY, + X_ORDER_MODE_STOP, + mEntry, + mVolume, + sl, + tp + // + ); + } + + // + bool PrepareStopShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double sl = 0, // Stop Loss + double tp = 0 // Take Profit + ) + { + // + return Prepare( + mSymbol, + mProvider, + mPeriod, + POSITION_TYPE_SELL, + X_ORDER_MODE_STOP, + mEntry, + mVolume, + sl, + tp + // + ); + } + + // + // Limit Mode ... + + // + bool PrepareLimitLong( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double sl = 0, // Stop Loss + double tp = 0 // Take Profit + ) + { + // + return Prepare( + mSymbol, + mProvider, + mPeriod, + POSITION_TYPE_BUY, + X_ORDER_MODE_LIMIT, + mEntry, + mVolume, + sl, + tp + // + ); + } + + // + bool PrepareLimitShort( + string mSymbol, // Trading Symbol + string mProvider, // Signal Provider + ENUM_TIMEFRAMES mPeriod, // Trading TimeFrame + double mEntry, // Entry Price + double mVolume, // Volume + double sl = 0, // Stop Loss + double tp = 0 // Take Profit + ) + { + // + return Prepare( + mSymbol, + mProvider, + mPeriod, + POSITION_TYPE_SELL, + X_ORDER_MODE_LIMIT, + mEntry, + mVolume, + sl, + tp + // + ); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + entry = 0; + volume = 0; + positionId = 0; + + // + time = NULL; + type = NULL; + mode = NULL; + symbol = NULL; + period = NULL; + comment = NULL; + provider = NULL; + + // + Clean(tps); + Clean(sls); + Clean(supports); + supportResistances.Clean(); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(period) && + IsValid(symbol) && + NotEmpty(volume) && + NotEmpty(entry) && + (ArraySize(tps) > 0 || + ArraySize(sls) > 0) + // + ; + + // + return result; + } + + // + // Check Signal Executed or not ... + bool IsExecuted() + { + // + bool result = false; + + // + result = + // + IsValid() && + NotEmpty(positionId) + // + ; + + // + return result; + } + + // + // Generate Comment for Signal ... + string GenerateComment() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + if (IsValid(provider)) + { + // + // Generate Provider Tag ... + result += GenerateProviderTag(provider); + } + + // + if (IsValid(period)) + { + // + // Generate Period Tag ... + result += GeneratePeriodTag(period); + } + + // + return result; + } + + // + // Check this instance is Same os Given instance or not ... + bool IsSameAs( + const XSignal &value // instance for Compare + ) + { + // + bool result = false; + + // + result = + // + type == value.type && + mode == value.mode && + entry == value.entry && + volume == value.volume && + symbol == value.symbol && + provider == value.provider && + positionId == value.positionId && + ArraySize(sls) == ArraySize(value.sls) && + ArraySize(tps) == ArraySize(value.tps) + // + ; + + // + return result; + } + + // + // Find index in a Collection ... + int FindIndex( + const XSignal &values[] // Collection to Find + ) + { + // + return FindIndex( + this, + values + // + ); + } + + // + // Check Items Passed Specific Filters or not ... + bool IsFiltersPassed( + string mSymbol = NULL, // Trading Symbol + string mProvider = NULL, // Signal Provider + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe + ENUM_POSITION_TYPE mType = NULL, // Long (Buy), Short (Sell) + ENUM_X_ORDER_MODES mMode = NULL // Execution Mode + ) + { + // + bool result = false; + + // + result = + // + // Symbol Filter ... + IsSymbolFilterPassed( + mSymbol, + this + // + ) + // + && + // + // Provider Filter ... + IsProviderFilterPassed( + mProvider, + this + // + ) + // + && + // + // Period Filter ... + IsPeriodFilterPassed( + mPeriod, + this + // + ) + // + && + // + // Type Filter ... + IsTypeFilterPassed( + mType, + this + // + ) + // + && + // + // Mode Filter ... + IsModeFilterPassed( + mMode, + this + // + ) + // + ; + + // + return result; + } + + // + string GetToken() + { + // + string mType = GetTypeName(this); + + // + 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; + } + + // + // To String Representation ... + string ToString() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + // For Modeling a Signal we Only Used: + // - Period; + // - Provider; + // - Type; + // - Mode; + // - Symbol; + // - PositionID; + // - Entry; + // - Volume; + // - TPS; + // - SLS; + // - Issue Time; + + // + int iPeriodInt = (int)period; + + // + string periodStr = Surround(XPeriodToken, iPeriodInt); + string providerStr = Surround(XProviderToken, provider); + string typeStr = Surround(XTypeToken, type); + string modeStr = Surround(XModeToken, mode); + string SymbolStr = Surround(XSymbolToken, symbol); + string positionIdStr = Surround(XIDToken, positionId); + string entryStr = Surround(XEntryToken, entry); + string volumeStr = Surround(XVolumeToken, volume); + string timeStr = Surround(XTimeToken, time); + + // + // TP ... + string tpsContentStr = ToString(tps); + string tpsStr = Surround(XTPToken, tpsContentStr); + + // + // SL ... + string slsContentStr = ToString(sls); + string slsStr = Surround(XSLToken, slsContentStr); + + // + result = + // + GetToken() + + "[" + + // + periodStr + + providerStr + + typeStr + + modeStr + + SymbolStr + + positionIdStr + + entryStr + + volumeStr + + tpsStr + + slsStr + + timeStr + + // + "]" + // + ; + + // + return result; + } + + // + // Parse String Model and Fill Available + // Items ... + bool Parse(string value) + { + // + bool result = false; + + // + Clean(); + + // + if (!IsValid(value)) + { + return false; + } + + // + // For Modeling a Signal we Only Used: + // - Period; + // - Provider; + // - Type; + // - Mode; + // - Symbol; + // - PositionID; + // - Entry; + // - Volume; + // - TPS; + // - SLS; + // - Issue Time; + + // + entry = ParseDoubleSurrounded(value, XEntryToken); + volume = ParseDoubleSurrounded(value, XVolumeToken); + positionId = ParseLongSurrounded(value, XIDToken); + + // + time = ParseTimeSurrounded(value, XTimeToken); + symbol = ParseStringSurrounded(value, XSymbolToken); + provider = ParseStringSurrounded(value, XProviderToken); + type = ((ENUM_POSITION_TYPE)ParseIntSurrounded(value, XTypeToken)); + mode = ((ENUM_X_ORDER_MODES)ParseIntSurrounded(value, XModeToken)); + period = ((ENUM_TIMEFRAMES)ParseIntSurrounded(value, XPeriodToken)); + + // + // TPS ... + ParseDoubleArraySurrounded( + tps, + value, + XTPToken + // + ); + + // + // SLS ... + ParseDoubleArraySurrounded( + sls, + value, + XSLToken + // + ); + + // + // Validate ... + result = IsValid(); + ; + + // + return result; + } +}; + +// +// Model an Open Position ... +struct XPosition +{ + // + // Props ... + + // + // Magic Number ... + ulong magic; + + // + // Ticket ID ... + ulong ticket; + + // + // Tradinng Symbol ... + string symbol; + + // + // Trading Period ... + ENUM_TIMEFRAMES period; + + // + // Position Type ... + ENUM_POSITION_TYPE type; + + // + // Take Profit ... + double tp; + + // + // Stop Loss ... + double sl; + + // + // Position Current Profit ... + double profit; + + // + // Position Open Price ... + double entry; + + // + // Current Symbol Price ... + double price; + + // + // Position Swap ... + double swap; + + // + // Position Commission ... + double commission; + + // + // Volume ... + double volume; + + // + // Position Open Time ... + datetime openAt; + + // + // Sifnal Provider ... + string provider; + + // + // Position Comment ... + string comment; + + // + // Constructor ... + XPosition() + { + Clean(); + } + + // + // Initializers ... + + bool ByIndex(int index) + { + // + bool result = false; + + // + static CPositionInfo mPositionInfo; + + // + result = mPositionInfo.SelectByIndex(index); + if (!result) + { + return result; + } + + // + ulong mTicket = mPositionInfo.Ticket(); + + // + result = ByTicket(mTicket); + + // + return result; + } + + bool ByTicket(ulong mTicket) + { + // + bool result = false; + + // + static CPositionInfo mPositionInfo; + + // + result = mPositionInfo.SelectByTicket(mTicket); + if (!result) + { + return result; + } + + // + swap = mPositionInfo.Swap(); + magic = mPositionInfo.Magic(); + openAt = mPositionInfo.Time(); + sl = mPositionInfo.StopLoss(); + ticket = mPositionInfo.Ticket(); + symbol = mPositionInfo.Symbol(); + tp = mPositionInfo.TakeProfit(); + profit = mPositionInfo.Profit(); + volume = mPositionInfo.Volume(); + comment = mPositionInfo.Comment(); + entry = mPositionInfo.PriceOpen(); + type = mPositionInfo.PositionType(); + price = mPositionInfo.PriceCurrent(); + commission = mPositionInfo.Commission(); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + magic = 0; + ticket = 0; + tp = 0; + sl = 0; + swap = 0; + entry = 0; + price = 0; + profit = 0; + volume = 0; + openAt = 0; + commission = 0; + + // + type = NULL; + period = NULL; + + // + symbol = NULL; + comment = NULL; + provider = NULL; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(symbol) && + NotEmpty(ticket) + // + ; + + // + return result; + } + + // + // Calculate Age ... + int GetAge( + ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period + ) + { + return GetAge(this, mPeriod); + } + + // + // Check this instance is Same os Given instance or not ... + bool IsSameAs( + const XPosition &value // instance for Compare + ) + { + // + bool result = false; + + // + result = + // + type == value.type && + magic == value.magic && + entry == value.entry && + ticket == value.ticket && + volume == value.volume && + symbol == value.symbol && + provider == value.provider + // + ; + + // + return result; + } + + // + // Find index in a Collection ... + int FindIndex( + const XPosition &values[] // Collection to Find + ) + { + // + return FindIndex( + this, + values + // + ); + } + + // + // Check Items Passed Specific Filters or not ... + bool IsFiltersPassed( + string mSymbol = NULL, // Trading Symbol + string mProvider = NULL, // Signal Provider + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe + ENUM_POSITION_TYPE mType = NULL, // Long (Buy), Short (Sell) + ulong mMagic = NULL, // Magic Number + bool mFilterByMagic = true // Get Only Self Open Positions + ) + { + // + bool result = false; + + // + result = + // + // Magic Filter ... + IsMagicFilterPassed( + mMagic, + mFilterByMagic, + this + // + ) + // + && + // + // Symbol Filter ... + IsSymbolFilterPassed( + mSymbol, + this + // + ) + // + && + // + // Provider Filter ... + IsProviderFilterPassed( + mProvider, + this + // + ) + // + && + // + // Period Filter ... + IsPeriodFilterPassed( + mPeriod, + this + // + ) + // + && + // + // Type Filter ... + IsTypeFilterPassed( + mType, + this + // + ) + // + ; + + // + return result; + } +}; + +// +// Model an Order ... +struct XOrder +{ + // + // Time of order placement ... + datetime setupAt; + + // + // Time of order expiration ... + datetime expiredAt; + + // + // Time of order execution or cancellation ... + datetime executedAt; + + // + // Order type ... + ENUM_ORDER_TYPE type; + + // + // Order state ... + ENUM_ORDER_STATE state; + + // + // Type of execution by remainder ... + ENUM_ORDER_TYPE_FILLING filling; + + // + // Order lifetime ... + ENUM_ORDER_TYPE_TIME lifetime; + + // + // Order ticket ... + ulong ticket; + + // + // Magic Number ... + long magic; + + // + // Position id, that is placed on order, + // when it is executed. Each executed order invokes a + // deal, that opens new or changes existing + // position. Id of that position is placed on + // executed order in this moment. + long positionId; + + // + // Initial volume on order placement ... + double initialVolume; + + // + // Unfilled volume ... + double currentVolume; + + // + // Price, specified in the order ... + double openPrice; + + // + // Current price by order symbol ... + double currentPrice; + + // + // Price of placing Limit order when StopLimit order is triggered ... + double stopLimitPrice; + + // + // Take Profit level ... + double tp; + + // + // Stop Loss level ... + double sl; + + // + // Trading Symbol ... + string symbol; + + // + // Signal Provider ... + string provider; + + // + // Order Comment ... + string comment; + + // + ENUM_TIMEFRAMES period; + + // + // Constructor ... + XOrder() + { + Clean(); + } + + // + // Initializers ... + bool ByIndex( + int index // Fill By Index ... + ) + { + // + bool result = false; + + // + int ordersCount = OrdersTotal(); + if (ordersCount <= 0) + { + return result; + } + + // + static COrderInfo mOrderInfo; + + // + result = mOrderInfo.SelectByIndex(index); + if (!result) + { + return result; + } + + // + // Reading Order Info ... + magic = mOrderInfo.Magic(); + sl = mOrderInfo.StopLoss(); + tp = mOrderInfo.TakeProfit(); + ticket = mOrderInfo.Ticket(); + openPrice = mOrderInfo.PriceOpen(); + positionId = mOrderInfo.PositionId(); + currentPrice = mOrderInfo.PriceCurrent(); + initialVolume = mOrderInfo.VolumeInitial(); + currentVolume = mOrderInfo.VolumeCurrent(); + stopLimitPrice = mOrderInfo.PriceStopLimit(); + + // + symbol = mOrderInfo.Symbol(); + comment = mOrderInfo.Comment(); + + // + state = mOrderInfo.State(); + type = mOrderInfo.OrderType(); + lifetime = mOrderInfo.TypeTime(); + filling = mOrderInfo.TypeFilling(); + + // + setupAt = mOrderInfo.TimeSetup(); + executedAt = mOrderInfo.TimeDone(); + expiredAt = mOrderInfo.TimeExpiration(); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + result = IsValid(); + + // + return result; + } + + // + // Retrieve Specific History Order ... + bool HistoryByIndex( + int index // Fill By Index ... + ) + { + // + bool result = false; + + // + int ordersCount = HistoryOrdersTotal(); + if (ordersCount <= 0) + { + return result; + } + + // + static CHistoryOrderInfo mOrderInfo; + + // + result = mOrderInfo.SelectByIndex(index); + if (!result) + { + return result; + } + + // + // Reading Order Info ... + magic = mOrderInfo.Magic(); + sl = mOrderInfo.StopLoss(); + tp = mOrderInfo.TakeProfit(); + ticket = mOrderInfo.Ticket(); + openPrice = mOrderInfo.PriceOpen(); + positionId = mOrderInfo.PositionId(); + currentPrice = mOrderInfo.PriceCurrent(); + initialVolume = mOrderInfo.VolumeInitial(); + currentVolume = mOrderInfo.VolumeCurrent(); + stopLimitPrice = mOrderInfo.PriceStopLimit(); + + // + symbol = mOrderInfo.Symbol(); + comment = mOrderInfo.Comment(); + + // + state = mOrderInfo.State(); + type = mOrderInfo.OrderType(); + lifetime = mOrderInfo.TypeTime(); + filling = mOrderInfo.TypeFilling(); + + // + setupAt = mOrderInfo.TimeSetup(); + executedAt = mOrderInfo.TimeDone(); + expiredAt = mOrderInfo.TimeExpiration(); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + result = IsValid(); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + tp = 0; + sl = 0; + magic = 0; + ticket = 0; + positionId = 0; + openPrice = 0; + currentPrice = 0; + initialVolume = 0; + currentVolume = 0; + stopLimitPrice = 0; + + // + setupAt = NULL; + expiredAt = NULL; + executedAt = NULL; + + // + symbol = NULL; + comment = NULL; + provider = NULL; + + // + type = NULL; + state = NULL; + period = NULL; + filling = NULL; + lifetime = NULL; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(symbol) && + NotEmpty(ticket) && + NotEmpty(positionId) + // + ; + + // + return result; + } + + // + // Calculate Age ... + int GetAge( + ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period + ) + { + return GetAge(this, mPeriod); + } + + // + // Check this instance is Same os Given instance or not ... + bool IsSameAs( + const XOrder &value // instance for Compare + ) + { + // + bool result = false; + + // + result = + // + type == value.type && + state == value.state && + magic == value.magic && + ticket == value.ticket && + symbol == value.symbol && + provider == value.provider && + positionId == value.positionId + // + ; + + // + return result; + } + + // + // Find index in a Collection ... + int FindIndex( + const XOrder &values[] // Collection to Find + ) + { + // + return FindIndex( + this, + values + // + ); + } + + // + // Check Items Passed Specific Filters or not ... + bool IsFiltersPassed( + string mSymbol = NULL, // Trading Symbol + string mProvider = NULL, // Signal Provider + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe + ENUM_ORDER_TYPE mType = NULL, // Long (Buy), Short (Sell) + ENUM_ORDER_STATE mState = NULL, // Order State + ulong mMagic = NULL, // Magic Number + bool mFilterByMagic = true // Get Only Self Open Positions + ) + { + // + bool result = false; + + // + result = + // + // Magic Filter ... + IsMagicFilterPassed( + mMagic, + mFilterByMagic, + this + // + ) + // + && + // + // Symbol Filter ... + IsSymbolFilterPassed( + mSymbol, + this + // + ) + // + && + // + // Provider Filter ... + IsProviderFilterPassed( + mProvider, + this + // + ) + // + && + // + // Period Filter ... + IsPeriodFilterPassed( + mPeriod, + this + // + ) + // + && + // + // Type Filter ... + IsTypeFilterPassed( + mType, + this + // + ) + // + && + // + // State Filter ... + IsStateFilterPassed( + mState, + this + // + ) + // + ; + + // + return result; + } +}; + +// +// Model a Deal ... +struct XDeal +{ + // + // the ID of the Expert Advisor, that executed the deal ... + ulong magic; + + // + // the ID of position, in which the deal was involved ... + ulong positionId; + + // + // Ticket ... + ulong ticket; + + // + // the name of the deal symbol ... + string symbol; + + // + // order by which the deal is executed ... + ulong order; + + // + // the time of deal execution ... + datetime time; + + // + // Deal price ... + double price; + + // + // the financial result of the deal (in deposit currency) ... + double profit; + + // + // the amount of swap when position is closed ... + double swap; + + // + // the amount of commission of the deal ... + double commission; + + // + // the volume of deal ... + double volume; + + // + // the deal comment ... + string comment; + + // + string provider; + + // + ENUM_TIMEFRAMES period; + + // + // the deal type ... + // ------------------------------------------------------------------ + // DEAL_TYPE_BUY => Buy ... + // DEAL_TYPE_SELL => Sell ... + // DEAL_TYPE_BUY_CANCELED => Canceled buy deal ... + // There can be a situation when a previously executed buy deal is canceled. In this case, + // the type of the previously executed deal (DEAL_TYPE_BUY) is changed to DEAL_TYPE_BUY_CANCELED, + // and its profit/loss is zeroized. Previously obtained profit/loss is charged/withdrawn using a separated balance operation ... + // + // DEAL_TYPE_SELL_CANCELED => Canceled sell deal ... + // There can be a situation when a previously executed sell deal is canceled. In this case, + // the type of the previously executed deal (DEAL_TYPE_SELL) is changed to DEAL_TYPE_SELL_CANCELED, + // and its profit/loss is zeroized. Previously obtained profit/loss is charged/withdrawn using a separated balance operation + // + // DEAL_TYPE_BALANCE => Balance ... + // DEAL_TYPE_CREDIT => Credit ... + // DEAL_TYPE_CHARGE => Additional charge ... + // DEAL_TYPE_CORRECTION => Correction ... + // DEAL_TAX => Tax charges ... + // DEAL_TYPE_BONUS => Bonus ... + // DEAL_TYPE_INTEREST => Interest rate ... + // DEAL_DIVIDEND => Dividend operations... + // DEAL_DIVIDEND_FRANKED => Franked (non-taxable) dividend operations ... + // DEAL_TYPE_COMMISSION => Additional commission ... + // DEAL_TYPE_COMMISSION_DAILY => Daily commission ... + // DEAL_TYPE_COMMISSION_MONTHLY => Monthly commission ... + // DEAL_TYPE_COMMISSION_AGENT_DAILY => Daily agent commission ... + // DEAL_TYPE_COMMISSION_AGENT_MONTHLY => Monthly agent commission + ENUM_DEAL_TYPE type; + + // + // the deal direction ... + // ---------------------------------- + // DEAL_ENTRY_IN => Entry in ... + // DEAL_ENTRY_OUT => Entry out ... + // DEAL_ENTRY_INOUT => Reverse ... + // DEAL_ENTRY_OUT_BY => Close a position by an opposite one ... + ENUM_DEAL_ENTRY entry; + + // + // deal reson ... + // --------------------- + // DEAL_REASON_SL => The deal was executed as a result of Stop Loss activation ... + // DEAL_REASON_TP => The deal was executed as a result of Take Profit activation ... + // DEAL_REASON_SO => The deal was executed as a result of the Stop Out event ... + // DEAL_REASON_WEB => The deal was executed as a result of activation of an order placed from the web platform ... + // DEAL_REASON_SPLIT => The deal was executed after the split (price reduction) of an instrument, which had an open position during split announcement ... + // DEAL_REASON_CLIENT => The deal was executed as a result of activation of an order placed from a desktop terminal ... + // DEAL_REASON_MOBILE => The deal was executed as a result of activation of an order placed from a mobile application ... + // DEAL_REASON_EXPERT => The deal was executed as a result of activation of an order placed from an MQL5 program, i.e. an Expert Advisor or a script ... + // DEAL_REASON_VMARGIN => The deal was executed after charging the variation margin ... + // DEAL_REASON_ROLLOVER => The deal was executed due to a rollover ... + ENUM_DEAL_REASON reason; + + // + // Constructor ... + XDeal() + { + Clean(); + } + + // + // Initializers ... + bool ByIndex( + int index // Deal Index + ) + { + // + bool result = false; + + // + int dealsCount = HistoryDealsTotal(); + result = dealsCount > 0; + if (!result) + { + return result; + } + + // + static CDealInfo mDealInfo; + + // + result = mDealInfo.SelectByIndex(index); + if (!result) + { + // + return result; + } + + // + // Reading Order Info ... + swap = mDealInfo.Swap(); + magic = mDealInfo.Magic(); + order = mDealInfo.Order(); + ticket = mDealInfo.Ticket(); + time = mDealInfo.Time(); + price = mDealInfo.Price(); + symbol = mDealInfo.Symbol(); + profit = mDealInfo.Profit(); + volume = mDealInfo.Volume(); + comment = mDealInfo.Comment(); + positionId = mDealInfo.PositionId(); + entry = mDealInfo.Entry(); + commission = mDealInfo.Commission(); + type = mDealInfo.DealType(); + reason = (ENUM_DEAL_REASON)HistoryDealGetInteger( + ticket, + DEAL_REASON); + + // + period = ExtractPeriod(comment); + provider = ExtractProvider(comment); + + // + result = IsValid(); + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + magic = 0; + positionId = 0; + ticket = 0; + order = 0; + time = 0; + price = 0; + profit = 0; + swap = 0; + commission = 0; + volume = 0; + + // + symbol = NULL; + comment = NULL; + provider = NULL; + + // + type = NULL; + entry = NULL; + period = NULL; + reason = NULL; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(symbol) && + NotEmpty(ticket) && + NotEmpty(positionId) + // + ; + + // + return result; + } + + // + // Calculate Age ... + int GetAge( + ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period + ) + { + return GetAge(this, mPeriod); + } + + // + // Check this instance is Same os Given instance or not ... + bool IsSameAs( + const XDeal &value // instance for Compare + ) + { + // + bool result = false; + + // + result = + // + type == value.type && + magic == value.magic && + entry == value.entry && + reason == value.reason && + ticket == value.ticket && + volume == value.volume && + symbol == value.symbol && + provider == value.provider && + positionId == value.positionId + // + ; + + // + return result; + } + + // + // Find index in a Collection ... + int FindIndex( + const XDeal &values[] // Collection to Find + ) + { + // + return FindIndex( + this, + values + // + ); + } + + // + // Check Items Passed Specific Filters or not ... + bool IsFiltersPassed( + string mSymbol = NULL, // Trading Symbol + string mProvider = NULL, // Signal Provider + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe + ENUM_DEAL_TYPE mType = NULL, // Deal Type + ENUM_DEAL_ENTRY mEntry = NULL, // Deal Entry + ENUM_DEAL_REASON mReason = NULL, // Deal Reason + ulong mMagic = NULL, // Magic Number + bool mFilterByMagic = true // Get Only Self Open Positions + ) + { + // + bool result = false; + + // + result = + // + // Magic Filter ... + IsMagicFilterPassed( + mMagic, + mFilterByMagic, + this + // + ) + // + && + // + // Symbol Filter ... + IsSymbolFilterPassed( + mSymbol, + this + // + ) + // + && + // + // Provider Filter ... + IsProviderFilterPassed( + mProvider, + this + // + ) + // + && + // + // Period Filter ... + IsPeriodFilterPassed( + mPeriod, + this + // + ) + // + && + // + // Type Filter ... + IsTypeFilterPassed( + mType, + this + // + ) + // + && + // + // Entry Filter ... + IsEntryFilterPassed( + mEntry, + this + // + ) + // + && + // + // Reason Filter ... + IsReasonFilterPassed( + mReason, + this + // + ) + // + ; + + // + return result; + } +}; + +// +// Model OnTrade Event Handler Result on XCTrade Class ... +struct XOnTradeHandlerState +{ + // + bool hasNewDeal; + int newDeals; + + // + bool hasNewOrder; + int newOrders; + + // + bool hasNewPosition; + int newPositions; + + // + bool hasNewHistoryOrder; + int newHistoryOrders; + + // + // Constructor ... + XOnTradeHandlerState() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + hasNewDeal = false; + hasNewOrder = false; + hasNewPosition = false; + hasNewHistoryOrder = false; + + // + newDeals = 0; + newOrders = 0; + newPositions = 0; + newHistoryOrders = 0; + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + ( + // + hasNewDeal + ? newDeals > 0 + : true + // + ) + // + && + // + ( + // + hasNewOrder + ? newOrders > 0 + : true + // + ) + // + && + // + ( + // + hasNewPosition + ? newPositions > 0 + : true + // + ) + // + && + // + ( + // + hasNewHistoryOrder + ? newHistoryOrders > 0 + : true + // + ) + // + ; + + // + return result; + } +}; + +// +// Model a Position with all of it's Supports ... +struct XPositionPack +{ + // + ulong ticket; // Main Position's Ticket + + // + XPosition position; // Main Position (if Exists) + + // + int supportOrdersCount; // Supported Orders (Untriggered) + int supportPositionsCount; // Supported Positions + + // + XOrder supportOrders[]; // Supported Orders (Untriggered) + XPosition supportPositions[]; // Supported Positions + + // + // Constructor ... + XPositionPack() + { + Clean(); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + ticket = 0; + + // + position.Clean(); + + // + supportOrdersCount = 0; + supportPositionsCount = 0; + + // + Clean(supportOrders); + Clean(supportPositions); + } + + // + // Validate ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + NotEmpty(ticket) && + ( + // + supportOrdersCount > 0 + ? ArraySize(supportOrders) == supportOrdersCount + : true + // + ) + // + && + // + ( + // + supportPositionsCount > 0 + ? ArraySize(supportPositions) == supportPositionsCount + : true + // + ) + // + ; + + // + return result; + } +}; + +// +// TypeDefs ... + +// +typedef void (*TOnDealsChanged)(int count); + +// +typedef void (*TOnOrdersChanged)(int count); + +// +typedef void (*TOnPositionsChanged)(int count); + +// +typedef void (*TOnStopLoss)(const XDeal &deal); +typedef void (*TOnTakeProfit)(const XDeal &deal); + +// +typedef void (*TOnTradeStateChanged)(const XOnTradeHandlerState &state); + +// +// Classes ... + +// +// Create a Signal Specfic Data Collector ... +class XSCSignalCollector +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructor ... + void XSCSignalCollector() + { + // + XSCDataCollector mBase; + mBase.Clear(); + } + + // + // Deconstructor ... + + // + // Tools ... + + // + // Inheritanced Functions ... + + // + // Cleaning Store ... + void Clear() + { + // + XSCDataCollector mBase; + + // + mBase.Clear(); + } + + // + // Collect All Store ... + int Collect(XSignal &result[]) + { + // + int mResult = 0; + + // + XSCDataCollector mBase; + + // + mResult = mBase.Collect(result); + + // + return mResult; + } + + // + // Add Item To Store ... + bool Add(XSignal &item) + { + // + bool result = false; + + // + XSCDataCollector mBase; + + // + result = mBase.Add(item); + + // + return result; + } + + // + // Add Item(s) To Store ... + int Add(XSignal &items[]) + { + // + int result = 0; + + // + XSCDataCollector mBase; + + // + result = mBase.Add(items); + + // + return result; + } + + // + // Remove an Item from Store ... + bool Remove(XSignal &item) + { + // + bool result = false; + + // + XSCDataCollector mBase; + + // + result = mBase.Remove(item); + + // + return result; + } + + // + // Custom Functions ... + + // + int CollectSignals( + XSignal &result[], // Hold Result + string symbol = NULL, // Trading Symbol + string provider = NULL, // Signal Provider + ENUM_TIMEFRAMES period = NULL, // Trading Timeframe + ENUM_POSITION_TYPE type = NULL, // Long (Buy), Short (Sell) + ENUM_X_ORDER_MODES mode = NULL // Execution Mode + ) + { + // + int mResult = 0; + + // // + // XSignal signals[]; + // int signalsCount = Collect(signals); + // if (signalsCount <= 0) + // { + // return mResult; + // } + + // // + // mResult = ArraySize(result); + + // // + // // Now we Have to Apply Filters ... + // for (int i = 0; i < signalsCount; i++) + // { + // // + // XSignal iSignal = signals[i]; + + // // // + // // bool isFiltersPassed = + // // iSignal.IsFilteresPassed( + // // symbol, + // // provider, + // // period, + // // type, + // // mode + // // // + // // ); + // // if (!isFiltersPassed) + // // { + // // continue; + // // } + + // // // + // // AddRef( + // // iPosition, + // // result + // // // + // // ); + // } + + // + return mResult; + } + + // + // Protected ... +protected: + // + // Tools ... + + // + // Private ... +private: + // + // Props ... + + // + // Tools ... +}; + +// +// Tools ... + +// +bool IsValid(ENUM_X_ORDER_MODES value) +{ + return value != X_ORDER_MODE_NOTHING; +} + +// +// Ages ... + +// +// Retrieve a Position Age ... +int GetAge( + XPosition &position, // Selected Position ... + ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... +) +{ + // + int result = -1; + + // + if (period == NULL) + { + period = _Period; + } + + // + result = iBarShift( + position.symbol, + period, + position.openAt); + + // + return result; +} + +// +// Retrieve an Order Age ... +int GetAge( + XOrder &order, // Selected Order ... + ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... +) +{ + // + int result = -1; + + // + if (period == NULL) + { + period = _Period; + } + + // + result = iBarShift( + order.symbol, + period, + order.setupAt); + + // + return result; +} + +// +// Retrieve a Deal Age ... +int GetAge( + XDeal &deal, // Selected Deal ... + ENUM_TIMEFRAMES period = NULL // Dest Time Frame ... +) +{ + // + int result = -1; + + // + if (period == NULL) + { + period = _Period; + } + + // + result = iBarShift( + deal.symbol, + period, + deal.time); + + // + return result; +} + +// +// Get Oldest Deal ... +int GetOldest( + XDeal &item, // Hold Result ... + XDeal &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XDeal tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XDeal iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge < iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +// Get Youngest Deal ... +int GetYoungest( + XDeal &item, // Hold Result ... + XDeal &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XDeal tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XDeal iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge > iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +// Get Oldest Order ... +int GetOldest( + XOrder &item, // Hold Result ... + XOrder &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XOrder tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XOrder iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge < iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +// Get Youngest Order ... +int GetYoungest( + XOrder &item, // Hold Result ... + XOrder &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XOrder tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XOrder iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge > iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +// Get Oldes Position ... +int GetOldest( + XPosition &item, // Hold Result ... + XPosition &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XPosition tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge < iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +// Get Youngest Position ... +int GetYoungest( + XPosition &item, // Hold Result ... + XPosition &items[] // Source Array ... +) +{ + // + int result = -1; + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + int tmpAge = 0; + XPosition tmpItem; + for (int i = 0; i < itemsCount; i++) + { + // + XPosition iItem = items[i]; + + // + int iAge = GetAge(iItem); + if (iAge > 0 && + (tmpAge == 0 || tmpAge > iAge)) + { + // + tmpAge = iAge; + tmpItem = iItem; + } + } + + // + if (tmpAge > 0) + { + // + result = tmpAge; + item = tmpItem; + } + + // + return result; +} + +// +// Check Filters ... + +// +// Magic Filter ... +template +bool IsMagicFilterPassed( + ulong magic, + bool filterByMagic, + T &item + // +) +{ + // + return !filterByMagic + ? true + : !NotEmpty(magic) + ? false + : magic == item.magic; +} + +// +// Symbol Filter ... +template +bool IsSymbolFilterPassed( + string symbol, + T &item + // +) +{ + // + return !IsValid(symbol) + ? true + : symbol == item.symbol; +} + +// +// Provider Filter ... +template +bool IsProviderFilterPassed( + string provider, + T &item + // +) +{ + // + return !IsValid(provider) + ? true + : provider == item.provider; +} + +// +// Period Filter ... +template +bool IsPeriodFilterPassed( + ENUM_TIMEFRAMES period, + T &item + // +) +{ + // + return !IsValid(period) + ? true + : period == item.period; +} + +// +// Type Filter ... +template +bool IsTypeFilterPassed( + ENUM_POSITION_TYPE type, + T &item + // +) +{ + // + return type == NULL + ? true + : type == item.type; +} +template +bool IsTypeFilterPassed( + ENUM_ORDER_TYPE type, + T &item + // +) +{ + // + return type == NULL + ? true + : type == item.type; +} +template +bool IsTypeFilterPassed( + ENUM_DEAL_TYPE type, + T &item + // +) +{ + // + return type == NULL + ? true + : type == item.type; +} + +// +// Mode Filter ... +template +bool IsModeFilterPassed( + ENUM_X_ORDER_MODES mode, + T &item + // +) +{ + // + return mode == NULL + ? true + : mode == item.mode; +} + +// +// Entry Filter ... +template +bool IsEntryFilterPassed( + ENUM_DEAL_ENTRY entry, + T &item + // +) +{ + // + return entry == NULL + ? true + : entry == item.entry; +} + +// +// Reason Filter ... +template +bool IsReasonFilterPassed( + ENUM_DEAL_REASON reason, + T &item + // +) +{ + // + return reason == NULL + ? true + : reason == item.reason; +} + +// +// State Filter ... +template +bool IsStateFilterPassed( + ENUM_ORDER_STATE state, + T &item + // +) +{ + // + return state == NULL + ? true + : state == item.state; +} + +// + +// +// Find Specific Item Index inside a Collection ... +template +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; +} + +// +// Tagging ... + +// +// Generate Specified Tag for Using in Comments ... +string GeneratePeriodTag(ENUM_TIMEFRAMES period) +{ + // + string strPeriod = ToString(period); + return Surround( + XPeriodToken, + strPeriod + // + ); +} + +// +// Extract Period from a Tagged string ... +ENUM_TIMEFRAMES ExtractPeriod(string value) +{ + // + ENUM_TIMEFRAMES result = NULL; + + // + string pStr = ParseStringSurrounded( + value, + XPeriodToken + // + ); + if (!IsValid(pStr)) + { + return result; + } + + // + result = ToPeriod(pStr); + + // + return result; +} + +// Generate Specified Tag for Using in Comments ... +string GenerateProviderTag(string provider) +{ + // + return Surround( + XProviderToken, + provider + // + ); +} + +// +// Extract Provider from a Tagged string ... +string ExtractProvider(string value) +{ + // + return ParseStringSurrounded( + value, + XProviderToken + // + ); +} + +// +// Generate Support Comment Tag ... +string GenerateSupportTag(ulong ticket) +{ + // + return Surround( + XSupportToken, + ticket + // + ); +} + +// +// Extract Support Positions from a Tagged string ... +ulong ExtractSupportedTicket(string value) +{ + // + return ParseLongSurrounded( + value, + XSupportToken + // + ); +} + +// +// Generate EQM Support Comment Tag ... +string GenerateEQMSupportTag(ulong ticket) +{ + // + return Surround( + XEQMSupportToken, + ticket + // + ); +} + +// +// Extract EQM Support Positions from a Tagged string ... +ulong ExtractEQMSupportedTicket(string value) +{ + // + return ParseLongSurrounded( + value, + XEQMSupportToken + // + ); +} + +//