/////////////////////////////////////////////////////// // // SaherElm IT Center XTest MQL5 Expert Advisor // ------------------------------------------------- // Name: XBackTester // Description: a Backtest Tools Strategy Tester // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // //////////////////////////////////////////////////////x // // Global Properties ... #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://saherelm.ir" #property version "1.00" #property description "SaherElm XBackTester" #property icon "../Images/SaherElm_Logo_Color.ico" #property strict // #define ShortName "XBackTester" // // Imports ... #include "../Classes/x-saherelm.x-backtester.expert.class.mq5" #include "../XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5" // // Definitions ... // // Inputs ... // // Common ... input group "Common"; input long eaMagicNumber = 78692110; // Magic Number input int eaSlippage = 10; // Slippgae input string eaLogSuffix = ""; // Log Suffix // // Alert ... // Here we Provider All Requirements for // Configuring Alert Provider ... input group "Alert"; input bool eaEnableAlerts = true; // Enable Alerts input bool eaLogAlerts = true; // Log Alerts input bool eaMailAlerts = false; // Mail Alerts input bool eaPushAlerts = false; // Push Alerts input bool eaTerminalAlerts = false; // Terminal Alerts // // Configurations ... input group "Configuration"; input bool eaProcessAllTicks = false; // Process All Ticks input double eaSignallerR2R = 2.0; // Risk To Reward Ratio input double eaSignallerVolume = 0.01; // Default Volume input double eaSignallerRiskInPoint = 50; // Default Risk In Point // // Indicator Inputs ... // input group "Calculation"; // // Short ... input ENUM_X_PERIOD_METHOD scMethod = X_PERIOD_AUTO; // How to Find Short Period input ENUM_TIMEFRAMES scPeriod = NULL; // Short Period // // Medium ... input ENUM_X_PERIOD_METHOD mcMethod = X_PERIOD_AUTO; // How to Find Medium Period input ENUM_TIMEFRAMES mcPeriod = NULL; // Medium Period // // Long ... input ENUM_X_PERIOD_METHOD lcMethod = X_PERIOD_AUTO; // How to Find Long Period input ENUM_TIMEFRAMES lcPeriod = NULL; // Long Period // // Hind ... input ENUM_X_PERIOD_METHOD hcMethod = X_PERIOD_AUTO; // How to Find Hind Period input ENUM_TIMEFRAMES hcPeriod = NULL; // Hind Period // // PV ... input ENUM_SERIESMODE upperMode = MODE_HIGH; // Peak Method input ENUM_SERIESMODE lowerMode = MODE_LOW; // Vale Method // // Others ... input ENUM_X_FIBO_LEVELS fiboUpperZoneLevel = X_FIBO_LEVEL_382; // Upper Zone Level input ENUM_X_FIBO_LEVELS fiboMiddleZoneLevel = X_FIBO_LEVEL_500; // Middle Zone Level input ENUM_X_FIBO_LEVELS fiboLowerZoneLevel = X_FIBO_LEVEL_618; // Lower Zone Level input double sarStep = 0.02; // SAR Step input double sarMax = 0.2; // SAR Maximum input ENUM_MA_METHOD maMethod = MODE_EMA; // MA Method input ENUM_APPLIED_PRICE maAppliedTo = PRICE_CLOSE; // MA Applied To input int maFastLength = 7; // Fast MA Length input int maSlowLength = 20; // Slow MA Length input int maBandLength = 7; // MA Band Length input int zigzagDepth = 12; // ZigZag Depth input int zigzagDeviation = 5; // ZigZag Deviation input int zigzagBackStep = 3; // ZigZag Back Step input ENUM_X_PRICE zigzagUppersMode = X_PRICE_HIGH; // ZigZag High Detect Mode input ENUM_X_PRICE zigzagLowersMode = X_PRICE_LOW; // ZigZag Low Detect Mode // input group "Bar Timer"; input int barTimeFontSize = 10; // Font Size input string barTimeFont = "Arial"; // Font input color barTimeColor = clrYellow; // Text Color input ENUM_BASE_CORNER barTimeCorner = CORNER_RIGHT_LOWER; // Text Position // // Presentation ... input group "Presentation"; input bool showPV = true; // Show PV input bool showHK = true; // Show HK input bool showSAR = true; // Show Sar input bool showMAFast = true; // Show MA Fast input bool showMASlow = true; // Show MA Slow input bool showMABand = true; // Show MA Band input bool showBarTime = true; // Show Bar Time input bool showZigZag = true; // Show ZigZag input bool showFiboZone = true; // Show Fibo Zone // input int startCalculationForLastBars = 1500; // Calculate Last n Bars // input int sarArrowCode = 159; // Parabolic Sar Arrow Code input int peakArrowCode = 159; // Peaks Arrow Code input int valeArrowCode = 159; // Vales Arrow Code // // Define Local Variables ... // // Requirements ... string eaLogTag; // EA Log Prefix ... XCBackTesterEA *eaExpert; // EA Expert ... // // Registered Signallers ... XCXFIMAStrategy1Signaller *fima1Signaller; // XFIMA1 Signaller ... XCXFIMAStrategy2Signaller *fima2Signaller; // XFIMA2 Signaller ... // XFIMAMarketStructure marketStructure; // POI Analysis Result ... XFIMAPatternDetectorConfig detectorConfig; // POI Detector Config ... XFIMAMarketStructureDrawerConfig marketStructureDrawerConfig; // POI Drawer Config ... // // Drawer and eaDraws ... CArrayObj eaDraws; // Drawn Objects ... CArrayObj *marketStructureObjects; // Market Structure Objects ... // XBarTracker eaBarTracker; // EA Bar Traker ... // // Registered Handlers ... int eaCTHandler = INVALID_HANDLE; // Candle Timer Handler ... // bool eaIsNewBar; // Check New Bar ... // // Define Indicators Here ... // // Event Handlers ... // // Initialization ... int OnInit() { // // Preparing Tags ... string eaTag = (IsValid(eaLogSuffix) ? eaLogSuffix + "_" : "") + ShortName; // // Validate Inputs and Required Parameters // for EA to Works fine ... if (!ValidateInputs()) { return INIT_PARAMETERS_INCORRECT; } // // Initialize Timer ... if (!InitTimer()) { return INIT_FAILED; } // // Configure EA Expert Class ... eaExpert = new XCBackTesterEA(); // // Symbol / Period ... eaExpert.symbol = _Symbol; eaExpert.period = _Period; // // Common ... eaExpert.eaMagicNumber = eaMagicNumber; eaExpert.eaSlippage = eaSlippage; eaExpert.eaLogSuffix = eaTag; // // Alert ... eaExpert.eaEnableAlerts = eaEnableAlerts; eaExpert.eaLogAlerts = eaLogAlerts; eaExpert.eaMailAlerts = eaMailAlerts; eaExpert.eaPushAlerts = eaPushAlerts; eaExpert.eaTerminalAlerts = eaTerminalAlerts; // // Attach Event Handlers ... eaExpert.AddOnDealsChangedEventHandler(OnDealsChanged); eaExpert.AddOnStopLossEventHandler(OnStopLossTriggered); eaExpert.AddOnOrdersChangedEventHandler(OnOrdersChanged); eaExpert.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); eaExpert.AddOnModifyPositionEventHandler(OnPositionModified); eaExpert.AddOnPositionsChangedEventHandler(OnPositionsChanged); eaExpert.AddOnTradeStateChangedEventHandler(OnTradeStateChanged); eaExpert.AddOnForceClosePositionEventHandler(OnPositionForceClosed); eaExpert.AddOnPartialClosePositionEventHandler(OnPositionPartialClosed); // // Configure Other Requirements ... eaExpert.allowedTPSLStep = 10; eaExpert.minAllowedRiskInPoint = 20; eaExpert.volume = eaSignallerVolume; eaExpert.riskToRewardRatio = eaSignallerR2R; eaExpert.riskInPoint = eaSignallerRiskInPoint; // // Try to Initialize eaExpert ... bool isInited = eaExpert.HandleOnInit(); if (!isInited) { // Print(ShortName, ": Initialization Failed ..."); return INIT_FAILED; } // // Here Instantiate Signaller Class ... // // Preparing Indicator Inputs ... XFIMAInputs fimaInputs; // // This is Default Configuration ... fimaInputs.Default(); fimaInputs.Hide(); // // Here we Attach Inputs to Indicator ... fimaInputs.scMethod = scMethod; fimaInputs.scPeriod = scPeriod; fimaInputs.mcMethod = mcMethod; fimaInputs.mcPeriod = mcPeriod; fimaInputs.lcMethod = lcMethod; fimaInputs.lcPeriod = lcPeriod; fimaInputs.hcMethod = hcMethod; fimaInputs.hcPeriod = hcPeriod; fimaInputs.upperMode = upperMode; fimaInputs.lowerMode = lowerMode; fimaInputs.fiboUpperZoneLevel = fiboUpperZoneLevel; fimaInputs.fiboMiddleZoneLevel = fiboMiddleZoneLevel; fimaInputs.fiboLowerZoneLevel = fiboLowerZoneLevel; fimaInputs.sarStep = sarStep; fimaInputs.sarMax = sarMax; fimaInputs.maMethod = maMethod; fimaInputs.maAppliedTo = maAppliedTo; fimaInputs.maFastLength = maFastLength; fimaInputs.maSlowLength = maSlowLength; fimaInputs.maBandLength = maBandLength; fimaInputs.zigzagDepth = zigzagDepth; fimaInputs.zigzagDeviation = zigzagDeviation; fimaInputs.zigzagBackStep = zigzagBackStep; fimaInputs.zigzagUppersMode = zigzagUppersMode; fimaInputs.zigzagLowersMode = zigzagLowersMode; fimaInputs.showPV = showPV; fimaInputs.showHK = showHK; fimaInputs.showSAR = showSAR; fimaInputs.showMAFast = showMAFast; fimaInputs.showMASlow = showMASlow; fimaInputs.showMABand = showMABand; fimaInputs.showZigZag = showZigZag; fimaInputs.showFiboZone = showFiboZone; fimaInputs.startCalculationForLastBars = startCalculationForLastBars; fimaInputs.sarArrowCode = sarArrowCode; fimaInputs.peakArrowCode = peakArrowCode; fimaInputs.valeArrowCode = valeArrowCode; // // Instantiate Signaller ... // // XFIMA1 Signaller ... fima1Signaller = new XCXFIMAStrategy1Signaller( _Symbol, _Period, fimaInputs, eaProcessAllTicks, // Process All Ticks ... eaSignallerR2R, // Signaller Risk to Reward Ratio ... eaSignallerRiskInPoint, // Default Risk In Points ... eaSignallerVolume // Defaul Volume ... ); fima1Signaller.AddOnSignalEventHandler(OnSignalTriggered); // // XFIMA2 Signaller ... fima2Signaller = new XCXFIMAStrategy2Signaller( _Symbol, _Period, fimaInputs, eaProcessAllTicks, // Process All Ticks ... eaSignallerR2R, // Signaller Risk to Reward Ratio ... eaSignallerRiskInPoint, // Default Risk In Points ... eaSignallerVolume // Defaul Volume ... ); fima2Signaller.AddOnSignalEventHandler(OnSignalTriggered); // isInited = fima1Signaller.IsValid() && fima2Signaller.IsValid(); if (!isInited) { // Print(ShortName, ": Initialization Failed ..."); return INIT_FAILED; } // // Initialize Candle Timer Handler ... eaCTHandler = iCustom( _Symbol, _Period, "x-saherelm.x121.xct", // // Inputs ... barTimeFontSize, // Font Size ... barTimeFont, // Font ... barTimeColor, // Text Color ... barTimeCorner, // Text Position ... // // Presentation ... "", showBarTime // Show Candle Time // ); isInited = eaCTHandler != INVALID_HANDLE; if (!isInited) { // Print(ShortName, ": Initialization Failed ..."); return INIT_FAILED; } // // Initialize Bar Tracker ... isInited = eaBarTracker.Init( _Symbol, _Period // ); if (!isInited) { // Print(ShortName, ": Initialization Failed ..."); return INIT_FAILED; } // // Configure XFIMA POI Detector / Drawer ... detectorConfig.Default(); detectorConfig.FullDetect(); marketStructureDrawerConfig.FullDraw(); // Print(ShortName, ": Initialized Successfully ..."); 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 // // Destroy Timer ... eaExpert.HandleOnDeInit(); // // De Init Indicator ... IndicatorRelease(eaCTHandler); // eaBarTracker.Clean(); // delete fima1Signaller; ZeroMemory(fima1Signaller); // delete fima2Signaller; ZeroMemory(fima2Signaller); // delete eaExpert; ZeroMemory(eaExpert); } // // On Tick Handler ... void OnTick() { // eaIsNewBar = eaBarTracker.IsNewBar(); bool canProcess = eaProcessAllTicks ? true : eaIsNewBar; // eaExpert.HandleOnTick(); // if (!canProcess) { return; } // // Bar Index ... int barIndex = 1; // // fima1Signaller.OnTick(barIndex); fima2Signaller.OnTick(barIndex); // // AnalyseMarket(barIndex); } // // Handle On Trade Event ... void OnTrade() { eaExpert.HandleOnTrade(); } // // On Timer ... void OnTimer() { eaExpert.HandleOnTimer(); } // // Chart Event Handler ... void OnChartEvent( const int id, const long &lparam, const double &dparam, const string &sparam // ) { eaExpert.HandleOnChartEvent(id, lparam, dparam, sparam); } // // Custom Functions ... /** * Validate all Inputs of Expert Adviser ... * * @return ( bool ) */ bool ValidateInputs() { // bool result = false; // string errMessage = ""; // bool isCommonValid = ( // eaSlippage > 0 && eaMagicNumber > 0 && // // Indicator Inputs ... // // MA ... maFastLength >= 2 && maSlowLength >= 2 && maSlowLength > maFastLength && // // SAR ... sarMax > 0 && sarStep > 0 && sarMax > sarStep && // // CYCLES ... (IsValid(scMethod, scPeriod) && IsValid(mcMethod, mcPeriod) && IsValid(lcMethod, lcPeriod) && IsValid(hcMethod, hcPeriod)) && // // ZIGZAG ... zigzagDepth > 0 && zigzagDeviation > 0 && zigzagBackStep > 0 && // // Validate Upper Mode Detection ... IsXValid(zigzagUppersMode) && // // Validate Lower Mode Detection ... IsXValid(zigzagLowersMode) // ); if (!isCommonValid) { // errMessage += "common configurations error;" + "\n"; } // result = // // Common ... isCommonValid && // // Otere ... true // ; // if (!result) { // // Since here Logger not Initiallized, we Use Raw Print Command ... Print(ShortName + " Errors: \n", errMessage); } // return result; } /** * Initialize Timer ... * * @return ( bool ) */ bool InitTimer() { // bool result = false; // // TODO: Initialize Timer if necessary ... // result = EventSetTimer(1); // result = EventSetMillisecondTimer(100); result = true; // return result; } /** * Destroy Timer ... */ void DestroyTimer() { // // TODO: Use This ... // EventKillTimer(); } /** * Trigger OnSignal Event ... * * @param signal: XSignal */ void OnSignalTriggered(XSignal &signal) { // // Validate Signal ... if (!signal.IsValid()) { return; } // // TODO: Fix this ... // return; // // Draw Signal on Chart ... XCSignalObject *iSignalObj; bool has = fima2Signaller.poiDrawer.DrawSignal( signal, iSignalObj, 7 // ); // if (has) { // ENUM_X_SIGNAL_EXECUTION_RESULT result; eaExpert.eaTrader.ExecuteSignal( signal, result // ); Print("Signal Issued: ", signal.GetObjectID()); } // // Try to Execute Signal ... // // Draw Signal Vertical Line ... // // // CChartObjectVLine *iObj = new CChartObjectVLine(); // // // string iName = signal.GetObjectID(); // color iColor = IsLong(signal.type) ? clrLime : clrRed; // // // bool has = iObj.Create( // fima2Signaller.poiDrawer.ChartIdentification(), // iName, // fima2Signaller.poiDrawer.SubWindowIdentification(), // signal.time // // ); // if (has) // { // // // iObj.Width(2); // iObj.Color(iColor); // // // // eaDraws.Add(iObj); // } // // // // Alert Issued Signal ... // string message = signal.GetMessage(); // // int signalBarIndex = GetBarIndex( // signal.symbol, // signal.period, // signal.time // // ); // AnalyseMarket(signalBarIndex); } // // Trade Event Handlers ... /** * Handle StopLoss Triggered Positions ... * * @param deal: XDeal instance ... */ void OnStopLossTriggered(const XDeal &deal) { eaExpert.HandleOnStopLossTriggered(deal); } /** * Handle Take Profit Triggered Positions ... * * @param deal: XDeal instance ... */ void OnTakeProfitTriggered(const XDeal &deal) { eaExpert.HandleOnTakeProfitTriggered(deal); } /** * Handle Force Close a Position ... * * @param ticket: ULONG ... * @param position: XPosition instance ... * @param comment: String ... */ void OnPositionForceClosed( const ulong ticket, const XPosition &position, const string comment // ) { // eaExpert.HandleOnPositionForceClosed( ticket, position, comment // ); } /** * Handle Deals Changes ... * * @param count: Integer, Number of Changes ... */ void OnDealsChanged(int count) { eaExpert.HandleOnDealsChanged(count); } /** * Handle Orders Changes ... * * @param count: Integer, Number of Changes ... */ void OnOrdersChanged(int count) { eaExpert.HandleOnOrdersChanged(count); } /** * Handle Positions Changes ... * * @param count: Integer, Number of Changes ... */ void OnPositionsChanged(int count) { eaExpert.HandleOnPositionsChanged(count); } /** * Handle Position Modified ... * * @param ticket: ulong, Position Ticket ... * @param profit: double, Position Profit ... * @param comment: string, Comment ... */ void OnPositionModified( const ulong ticket, const double profit, const string comment // ) { // eaExpert.HandleOnPositionModified( ticket, profit, comment // ); } /** * Handle Position Partial Closed ... * * @param ticket: ulong, Position Ticket ... * @param profit: double, Position Profit ... * @param comment: string, Comment ... */ void OnPositionPartialClosed( const ulong ticket, const double profit, const string comment // ) { // eaExpert.HandleOnPositionPartialClosed( ticket, profit, comment // ); } /** * Handle Trade State Changed ... * * @param state: XOnTradeHandlerState instance ... */ void OnTradeStateChanged(const XOnTradeHandlerState &state) { eaExpert.HandleOnTradeStateChanged(state); } // void AnalyseMarket(int barIndex = 0) { // bool has = false; // barIndex = NormalizeInt(barIndex, 0); // string symbol = fima2Signaller.symbol; ENUM_TIMEFRAMES period = fima2Signaller.period; // // Retrieve Signal Bar ... XOHCL bar; has = bar.Init( symbol, period, barIndex // ); if (!has) { // bar.Clean(); return; } // // TODO: Remove this and add in OnInit() Method ... // // Configuring Detector ... // detectorConfig.detectOB = true; detectorConfig.detectFVG = true; // detectorConfig.detectSupport = true; detectorConfig.detectResistance = true; detectorConfig.detectSwingTrend = true; // detectorConfig.detectPinned = true; detectorConfig.detectMomentum = true; detectorConfig.detectEngulfed = true; detectorConfig.detectTrueGaped = true; // detectorConfig.detectStarPattern = true; detectorConfig.detectFlagPattern = true; detectorConfig.detectRisingPattern = true; detectorConfig.detectPiercingPattern = true; detectorConfig.detectSignalKeyBarPattern = true; // detectorConfig.analyseFIMAPVPivots = true; detectorConfig.analyseFIMASARPivots = false; detectorConfig.analyseFIMAZigZagPivots = true; // // Configure Drawer ... // marketStructureDrawerConfig.drawOB = false; marketStructureDrawerConfig.drawFVG = false; // marketStructureDrawerConfig.drawPinned = false; marketStructureDrawerConfig.drawEngulfed = true; marketStructureDrawerConfig.drawTrueGaped = false; marketStructureDrawerConfig.drawMomentum = false; marketStructureDrawerConfig.drawFlagPattern = false; marketStructureDrawerConfig.drawStarPattern = false; marketStructureDrawerConfig.drawRisingPattern = false; marketStructureDrawerConfig.drawPiercingPattern = false; marketStructureDrawerConfig.drawSignalKeyBarPattern = true; // // Recents ... marketStructureDrawerConfig.drawRecentPatterns = false; marketStructureDrawerConfig.drawFakeBreakedZone = false; marketStructureDrawerConfig.drawRecentlyTestedZones = false; marketStructureDrawerConfig.drawRecentlyBreakedZones = false; // // XPV ... marketStructureDrawerConfig.drawFIMAPVPivotsAnalysis = true; marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisZones = true; marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisTrends = true; marketStructureDrawerConfig.drawFIMAPVPivotsAnalysisPivots = true; // // XSAR ... marketStructureDrawerConfig.drawFIMASARPivotsAnalysis = false; marketStructureDrawerConfig.drawFIMASARPivotsAnalysisZones = false; marketStructureDrawerConfig.drawFIMASARPivotsAnalysisTrends = false; marketStructureDrawerConfig.drawFIMASARPivotsAnalysisPivots = false; // // XZigZag ... marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysis = true; marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisZones = true; marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisTrends = false; marketStructureDrawerConfig.drawFIMAZigZagPivotsAnalysisPivots = false; // // Analyse Market on Signalling Bar ... fima2Signaller.poiDetector.AnalyseMarket( bar, marketStructure, detectorConfig // ); // XFIMASIgballer2First(bar); // HandleLookupSignal(bar); // bar.Clean(); } // // Handle Signal Looking Up ... // Register it as XFIMA Signaller 2 ... void XFIMASIgballer2First(XOHCL &bar) { // bool has = bar.IsValid(); if (!has) { return; } // XBoxZone iZone; XSignal iSignal; string iName = NULL; XBoxZone supports[]; XBoxZone resistances[]; bool isBullish = false; int barIndex = bar.Index(); double iPrice = EMPTY_VALUE; ENUM_X_PRICE iPriceType = X_PRICE_NONE; ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; // // Check Required Pattern Exists ... bool hasPinnedBar = HasDirection(marketStructure.pinnedDir); bool hasEngulfedBar = HasDirection(marketStructure.engulfedDir); bool hasFlagPattern = HasDirection(marketStructure.flagPatternDir); bool hasStarPattern = HasDirection(marketStructure.starPatternDir); bool hasRisingPattern = HasDirection(marketStructure.risingPatternDir); bool hasPiercingPattern = HasDirection(marketStructure.piercingPatternDir); bool hasSignalKeyBar = HasDirection(marketStructure.signalKeyBarPatternDir); // // PV Trend Line ... string pvTrendName = "XPVTrend"; CChartObjectTrend *pvTrendLine = NULL; ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE; // // ZigZag Trend Line ... string zgTrendName = "XZGTrend"; CChartObjectTrend *zgTrendLine = NULL; ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE; // // Check PV Analysis ... bool hasPVAnalysis = marketStructure.pvAnalysis.IsValid(); if (hasPVAnalysis) { // // Support ... XBoxZone supportBox; XCBoxObject *iSupportObj; has = marketStructure.pvAnalysis.HasSupportBox(supportBox); if (has) { // supportBox.to = bar.time; AddIfNotExists( supportBox, supports // ); has = fima2Signaller.poiDrawer.DrawBox( supportBox, iSupportObj, true, // Ignore At ... supportBox.type // Name ... ); if (has) { // XPOIStyle iStyle; fima2Signaller.poiDrawer.GetBoxStyle( iStyle, supportBox.dir // ); fima2Signaller.poiDrawer.ApplyBoxStyle( iSupportObj, iStyle // ); iStyle.Clean(); } } // // Resistance ... XBoxZone resistanceBox; XCBoxObject *iResistanceObj; has = marketStructure.pvAnalysis.HasResistanceBox(resistanceBox); if (has) { // resistanceBox.to = bar.time; AddIfNotExists( resistanceBox, supports // ); has = fima2Signaller.poiDrawer.DrawBox( resistanceBox, iResistanceObj, true, // Ignore At ... resistanceBox.type // Name ... ); if (has) { // XPOIStyle iStyle; fima2Signaller.poiDrawer.GetBoxStyle( iStyle, resistanceBox.dir // ); fima2Signaller.poiDrawer.ApplyBoxStyle( iResistanceObj, iStyle // ); iStyle.Clean(); } } // // Pivots ... XPivot pivots[]; int pivotsCount = fima2Signaller.poiDetector.ExtractPVPivots( pivots, barIndex, 50 // ); has = IsValidSize(pivotsCount); // // Sort ... Sort( pivots, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Remove Newest ... ArrayRemove( pivots, 0, 1 // ); // // Check Trend ... if (has) { // XPivot highs[]; int highsCount = ExtractPivots( highs, pivots, X_PIVOT_TYPE_PEAK // ); Sort( highs, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // XPivot lows[]; int lowsCount = ExtractPivots( lows, pivots, X_PIVOT_TYPE_VALE // ); Sort( lows, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Check Highs and Lows ... has = IsValidSize(lowsCount) && IsValidSize(highsCount) && lowsCount >= 2 && highsCount >= 2; if (has) { // // Try to Get Market Strucutre ... // bool hasLowerHigh = highs[0].value < highs[1].value; bool hasLowerLow = lows[0].value < lows[1].value; // bool hasHigherHigh = highs[0].value > highs[1].value; bool hasHigherLow = lows[0].value > lows[1].value; // pvTrend = (hasHigherHigh && hasHigherLow) ? X_DIRECTION_BULLISH : (hasLowerHigh && hasLowerLow) ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; has = HasDirection(pvTrend); if (has) { // // Select Swings for Trend Line ... XOHCL tmpBar; int llIDX = -1; int hhIDX = -1; datetime toTime = NULL; datetime fromTime = NULL; double toPrice = EMPTY_VALUE; color trendColor = CLR_NONE; double fromPrice = EMPTY_VALUE; if (IsSpecifiedBullish(pvTrend)) { // llIDX = GetLowest(lows); hhIDX = GetHighest(lows); // trendColor = clrAqua; // toTime = lows[hhIDX].time; toPrice = lows[hhIDX].value; // fromTime = lows[llIDX].time; fromPrice = lows[llIDX].value; } else { // llIDX = GetLowest(highs); hhIDX = GetHighest(highs); // trendColor = clrMagenta; // toTime = highs[llIDX].time; toPrice = highs[llIDX].value; // fromTime = highs[hhIDX].time; fromPrice = highs[hhIDX].value; } // // Check Requirements for Trend ... has = NotEmptyZero(toPrice) && NotEmptyZero(fromPrice) && IsSpecifiedValid(toTime) && IsSpecifiedValid(fromTime); if (has) { // has = fima2Signaller.poiDrawer.DrawTrendLine( fromPrice, fromTime, toPrice, toTime, pvTrendLine, pvTrendName, true // Ray Right ... ); if (has) { pvTrendLine.Color(trendColor); } } // // Cleanup Resources ... tmpBar.Clean(); } // if (!has) { SpecifiedClean(pivots); } } // // Cleanup Resources ... SpecifiedClean(lows); SpecifiedClean(highs); } // // Draw Pivots ... has = HasChild(pivots); if (has) { // CArrayObj *drawnPivots = new CArrayObj(); pivotsCount = fima2Signaller.poiDrawer.DrawPivots( pivots, drawnPivots // ); } // // Cleanup Resources ... SpecifiedClean(pivots); } // // Check ZigZag Analysis ... bool hasZGAnalysis = marketStructure.zigzagAnalysis.IsValid(); if (hasZGAnalysis) { // // Support ... XBoxZone supportBox; XCBoxObject *iSupportObj; has = marketStructure.zigzagAnalysis.HasSupportBox(supportBox); if (has) { // supportBox.to = bar.time; AddIfNotExists( supportBox, supports // ); has = fima2Signaller.poiDrawer.DrawBox( supportBox, iSupportObj, true, // Ignore At ... supportBox.type // Name ... ); if (has) { // XPOIStyle iStyle; fima2Signaller.poiDrawer.GetBoxStyle( iStyle, supportBox.dir // ); fima2Signaller.poiDrawer.ApplyBoxStyle( iSupportObj, iStyle // ); iStyle.Clean(); } } // // Resistance ... XBoxZone resistanceBox; XCBoxObject *iResistanceObj; has = marketStructure.zigzagAnalysis.HasResistanceBox(resistanceBox); if (has) { // resistanceBox.to = bar.time; AddIfNotExists( resistanceBox, supports // ); has = fima2Signaller.poiDrawer.DrawBox( resistanceBox, iResistanceObj, true, // Ignore At ... resistanceBox.type // Name ... ); if (has) { // XPOIStyle iStyle; fima2Signaller.poiDrawer.GetBoxStyle( iStyle, resistanceBox.dir // ); fima2Signaller.poiDrawer.ApplyBoxStyle( iResistanceObj, iStyle // ); iStyle.Clean(); } } // // Pivots ... XPivot pivots[]; int pivotsCount = fima2Signaller.poiDetector.ExtractZigZagPivots( pivots, barIndex, 10 // ); has = IsValidSize(pivotsCount); // // Sort ... Sort( pivots, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Remove Newest ... ArrayRemove( pivots, 0, 1 // ); // // Check Trend ... if (has) { // XPivot highs[]; int highsCount = ExtractPivots( highs, pivots, X_PIVOT_TYPE_PEAK // ); Sort( highs, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // XPivot lows[]; int lowsCount = ExtractPivots( lows, pivots, X_PIVOT_TYPE_VALE // ); Sort( lows, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Check Highs and Lows ... has = IsValidSize(lowsCount) && IsValidSize(highsCount) && lowsCount >= 2 && highsCount >= 2; if (has) { // // Try to Get Market Strucutre ... // bool hasLowerHigh = highs[0].value < highs[1].value; bool hasLowerLow = lows[0].value < lows[1].value; // bool hasHigherHigh = highs[0].value > highs[1].value; bool hasHigherLow = lows[0].value > lows[1].value; // zgTrend = (hasHigherHigh && hasHigherLow) ? X_DIRECTION_BULLISH : (hasLowerHigh && hasLowerLow) ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; has = HasDirection(zgTrend); if (has) { // // Select Swings for Trend Line ... XOHCL tmpBar; int llIDX = -1; int hhIDX = -1; datetime toTime = NULL; datetime fromTime = NULL; double toPrice = EMPTY_VALUE; color trendColor = CLR_NONE; double fromPrice = EMPTY_VALUE; if (IsSpecifiedBullish(zgTrend)) { // llIDX = GetLowest(lows); hhIDX = GetHighest(lows); // trendColor = clrAqua; // toTime = lows[hhIDX].time; toPrice = lows[hhIDX].value; // fromTime = lows[llIDX].time; fromPrice = lows[llIDX].value; } else { // llIDX = GetLowest(highs); hhIDX = GetHighest(highs); // trendColor = clrMagenta; // toTime = highs[llIDX].time; toPrice = highs[llIDX].value; // fromTime = highs[hhIDX].time; fromPrice = highs[hhIDX].value; } // // Check Requirements for Trend ... has = NotEmptyZero(toPrice) && NotEmptyZero(fromPrice) && IsSpecifiedValid(toTime) && IsSpecifiedValid(fromTime); if (has) { // has = fima2Signaller.poiDrawer.DrawTrendLine( fromPrice, fromTime, toPrice, toTime, zgTrendLine, zgTrendName, true // Ray Right ... ); if (has) { zgTrendLine.Color(trendColor); } } // // Cleanup Resources ... tmpBar.Clean(); } // if (!has) { SpecifiedClean(pivots); } } // // Cleanup Resources ... SpecifiedClean(lows); SpecifiedClean(highs); } // // Draw Pivots ... has = HasChild(pivots); if (has) { // CArrayObj *drawnPivots = new CArrayObj(); pivotsCount = fima2Signaller.poiDrawer.DrawPivots( pivots, drawnPivots // ); } // // Cleanup Resources ... SpecifiedClean(pivots); } // // Support ... bool hasSupport = marketStructure.support.IsValid(); if (hasSupport) { // AddIfNotExists( marketStructure.support, supports // ); // XCBoxObject *iObj; has = fima2Signaller.poiDrawer.DrawBox( marketStructure.support, iObj); if (has) { } } // // Resistance ... bool hasResistance = marketStructure.resistance.IsValid(); if (hasResistance) { // AddIfNotExists( marketStructure.resistance, resistances // ); // XCBoxObject *iObj; has = fima2Signaller.poiDrawer.DrawBox( marketStructure.resistance, iObj); if (has) { } } // // Check Bar Pattern Exists ... has = hasPinnedBar || hasEngulfedBar || hasFlagPattern || hasStarPattern || hasSignalKeyBar || hasRisingPattern || hasPiercingPattern; // // Select Pattern Direction and Price and Price Type ... if (has) { // if (hasPinnedBar) { // iDir = marketStructure.pinnedDir; iName = "pinned" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasEngulfedBar) { // iDir = marketStructure.engulfedDir; iName = "engulfed" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasFlagPattern) { // iDir = marketStructure.flagPatternDir; iName = "flagPattern" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasStarPattern) { // iDir = marketStructure.starPatternDir; iName = "starPattern" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasSignalKeyBar) { // iDir = marketStructure.risingPatternDir; iName = "risingPattern" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasRisingPattern) { // iDir = marketStructure.piercingPatternDir; iName = "piercingPattern" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasPiercingPattern) { // iDir = marketStructure.signalKeyBarPatternDir; iName = "signalKeyBarPattern" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } // isBullish = IsSpecifiedBullish(iDir); // // Retrieve Price Type for Validate ... iPriceType = isBullish ? X_PRICE_LOW : X_PRICE_HIGH; iPrice = bar.GetPrice(iPriceType); // has = HasDirection(iDir); } // // Validate Patterns based on MA Band ... if (has) { // // Retrieve MA Band for Validation ... double iMABandUpper = fima2Signaller.fimaHelper.GetMABandUpper(barIndex); double iMABandLower = fima2Signaller.fimaHelper.GetMABandLower(barIndex); // // Validate ... has = isBullish ? iPrice < iMABandLower : iPrice > iMABandUpper; } // // Select a Zone which Price inside it ... // // Validate Happens in Zone ... int insideZoneIDX = -1; has = has && (isBullish ? HasInside( insideZoneIDX, bar, supports // ) : HasInside( insideZoneIDX, bar, resistances // )); // // Validate Selected Inside Zone ... // whith Bars Edge ... has = IsValidIndex(insideZoneIDX); if (has) { // if (isBullish) { iZone = supports[insideZoneIDX]; } else { iZone = resistances[insideZoneIDX]; } // has = isBullish ? bar.high > supports[insideZoneIDX].upper : bar.low < resistances[insideZoneIDX].lower; } // // Checking Liquidities ... // // Draw Selected and Validated Bar and Selected Zone ... if (has) { // int iWidth = 1; int iCode = 159; color iClr = isBullish ? clrYellow : clrDarkOrange; ENUM_ARROW_ANCHOR iAnchor = isBullish ? ANCHOR_TOP : ANCHOR_BOTTOM; // XCBoxObject *iZoneObj; XCBarArrowObject *iPatternObj; // has = fima2Signaller.poiDrawer.DrawBarArrow( bar, iPatternObj, iPriceType, iCode, iClr, iWidth, iAnchor, iName, true, // Ignore Bar Tag ... 10 // Threshold ... ); if (has) { } // has = fima2Signaller.poiDrawer.DrawBox( iZone, iZoneObj, true, // Ignore At ... iZone.type // Name ... ); if (has) { // XPOIStyle iStyle; fima2Signaller.poiDrawer.GetBoxStyle( iStyle, iZone.dir // ); iStyle.width = 2; iStyle.clr = iClr; fima2Signaller.poiDrawer.ApplyBoxStyle( iZoneObj, iStyle // ); } } // // Preparing Signal ... if (has) { // iSignal.time = bar.time; iSignal.provider = "XFima"; iSignal.symbol = bar.symbol; iSignal.period = bar.period; iSignal.mode = X_ORDER_MODE_MARKET; iSignal.entry = GetEntry(bar.symbol, iDir); iSignal.type = isBullish ? POSITION_TYPE_BUY : POSITION_TYPE_SELL; // iSignal.volume = 0.01; // double _r2r = 2.0; double _slDistanceInPoint = 5; double _point = GetPoints(iSignal.symbol); double _riskDistance = _slDistanceInPoint * _point; double _risk = _riskDistance + MathAbs((isBullish ? iZone.lower : iZone.upper) - iSignal.entry); double _reward = GetSpread(iSignal.symbol) + (_risk * _r2r); // double sl = isBullish ? iSignal.entry - _risk : iSignal.entry + _risk; double tp = isBullish ? iSignal.entry + _reward : iSignal.entry - _reward; // iSignal.sl = sl; iSignal.tp = tp; // has = iSignal.IsValid(); if (has) { // XCSignalObject *iSignalObj; has = fima2Signaller.poiDrawer.DrawSignal( iSignal, iSignalObj, 7 // ); } } // // For Logging ... if (has) { // ENUM_X_SIGNAL_EXECUTION_RESULT eResult; has = eaExpert.eaTrader.ExecuteSignal(iSignal, eResult); Print("Detect a Potential Place for Price Movement: ", ToXString(iDir), ", Time: ", bar.time); } // // Cleanup Resources ... iZone.Clean(); iSignal.Clean(); SpecifiedClean(supports); SpecifiedClean(resistances); } // void HandleLookupSignal(XOHCL &bar) { // bool has = bar.IsValid(); if (!has) { return; } // XBoxZone iZone; XSignal iSignal; string iName = NULL; bool isBullish = false; bool isBearish = false; int barIndex = bar.Index(); double iPrice = EMPTY_VALUE; XFIMAConditions fimaConditions; ENUM_X_PRICE iPriceType = X_PRICE_NONE; ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; // int cIDX = 0; int pIDX = cIDX + 1; // // Check for a Cross ... // // fima2Signaller.fimaHelper.Update(barIndex); has = fima2Signaller.fimaHelper.GetConditions( fimaConditions, barIndex, 5 // ); // double cSlowMA = fimaConditions.maSlowBuffer[cIDX]; double pSlowMA = fimaConditions.maSlowBuffer[pIDX]; // double cMAUpper = fimaConditions.maBandUpperBuffer[cIDX]; double cMALower = fimaConditions.maBandLowerBuffer[cIDX]; // double pMAUpper = fimaConditions.maBandUpperBuffer[pIDX]; double pMALower = fimaConditions.maBandLowerBuffer[pIDX]; // bool isCrossedOver = cSlowMA > cMALower && pSlowMA < pMALower; // bool isCrossedUnder = cSlowMA < cMAUpper && cSlowMA > pMAUpper; // has = isCrossedOver || isCrossedUnder; if (!has) { // isBullish = false; isBearish = false; iDir = X_DIRECTION_NONE; } // if (has) { // isBullish = isCrossedOver; isBearish = isCrossedUnder; } // iDir = (isBullish && !isBearish) ? X_DIRECTION_BULLISH : (isBearish && !isBullish) ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; has = HasDirection(iDir); if (has) { Print("Conditions Detected ..."); } // // Cleanup Resources ... fimaConditions.Clean(); } //