/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class Library // ---------------------------------------------- // Name: XSCX121EA // Description: an Expert Class which // used X121 Setup ... // // // 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 Import and Inclused requirements ... // // // Includes ... #include "../Classes/x-saherelm.xea.class.mq5" #include "../Libraries/x-saherelm.x121.draw.lib.mq5" #include "../Classes/x-saherelm.x121.provider.class.mq5" // // END Import and Inclused requirements ... // // // START Definitions ... // // // END Definitions ... // // // START Overrides ... // // // END Overrides ... // // // an Expert Advisor Class by X121Provider ... class XSCX121EA : public XSCBaseEA { // // Public ... public: // // Props ... // // Constructor ... void XSCX121EA( string symbol, // Trading Symbol ENUM_TIMEFRAMES period, // Trading Time Frame ulong magic, // Magic Number int slippage, // Slippgae double maxAllowedSpread = 0, // Max Allowed Spread to Execute Signal int maxAllowedPositions = 0, // Maximum Allowed Same Time Position double minProfitPerTrade = 0, // Min Profit Per Trade based On Volume Factor (Hedge) double minProfitPerVolumeFactor = 0, // Min Volume Factor for Calculating Profit (Hedge) double maxAllowedDrawDownFactor = 0, // Max Allowed Drawdown factor for Open New Positions TOnStopLoss onStopLossTriggered = NULL, // On StopLoass Triggered Event Handler TOnTakeProfit onTakeProfitTriggered = NULL, // On TakeProfit Triggered Event Handler TOnDealsChanged onDealsChangedHandler = NULL, // On Deals Changed Event Handler TOnOrdersChanged onOrdersChangedHandler = NULL, // On Orders Changed Event Handler TOnPositionsChanged onPositionsChangedHandler = NULL, // On Positions Changed Event Handler TOnTradeStateChanged onTradeStateChangedHandler = NULL, // On Trade State Changed Event Handler // int minAgeForDoSupport = 0, // Minimum Position Age for Do Supporting int minAgeForUpdateSupports = 0, // Minimum Age for Update Untriggered Support Orders TOnSignalConditions onSignalConditions = NULL // On SignalConditions Event Handler ) : XSCBaseEA(symbol, period, magic, slippage, maxAllowedSpread, maxAllowedPositions, minProfitPerTrade, minProfitPerVolumeFactor, maxAllowedDrawDownFactor, onStopLossTriggered, onTakeProfitTriggered, onDealsChangedHandler, onOrdersChangedHandler, onPositionsChangedHandler, onTradeStateChangedHandler) { // mOnSignalConditions = onSignalConditions; mMinAgeForDoSupport = minAgeForDoSupport; mMinAgeForUpdateSupports = minAgeForUpdateSupports; } // // DeConstructor ... void ~XSCX121EA() { // // Delete All Registered Providers ... int providersCount = ArraySize(mProviders); if (providersCount > 0) { // for (int i = 0; i < providersCount; i++) { // X121SignalProvider iProvider = mProviders[i]; // delete iProvider.provider; } } } // // START Properties ... // // // Min Profit Per Trade ... // bool MinProfitPerTrade(double value) { // bool result = false; // if (value <= 0) { return result; } // result = value > 0; if (value == mMinProfitPerTrade) { return result; } // mMinProfitPerTrade = value; // return result; } // double MinProfitPerTrade() { return mMinProfitPerTrade; } // // Min Profit Per Volume Factor ... // bool MinProfitPerVolumeFactor(double value) { // bool result = false; // if (value <= 0) { return result; } // result = value > 0; if (value == mMinProfitPerVolumeFactor) { return result; } // mMinProfitPerVolumeFactor = value; // return result; } // double MinProfitPerVolumeFactor() { return mMinProfitPerVolumeFactor; } // // Add Provider ... bool AddProvider( X121SignalProvider &provider // Specific Provider ... ) { // bool result = false; // // Validate Provider ... if (provider.symbol == NULL || provider.period == NULL || provider.riskAmount <= 0 || StringLen(provider.symbol) == 0 || ArraySize(provider.providers) == 0) { return result; } // // Check Exists or not ... int idx = GetProviderIndex( provider.symbol, provider.period); if (idx >= 0) { return result; } // PrepareProviderConfig(); // // Make Instance of X121Provider Class ... provider.provider = new XSCX121Provider( provider.symbol, provider.period, true // Ignore Ticks after Recieved a Signal Till new Candle ... ); // // Attach Event Listener ... if (mOnSignalConditions != NULL) { // // Attach Event Handlers ... provider.provider.AddOnSignalConditionEventHandler(mOnSignalConditions); } // // Set Signallers to Provider Class ... result = provider.provider.SetSignallers(provider.providers); if (!result) { return result; } // // Initialize Provider ... result = provider.provider.SetConfig(mProviderConfig); // // Add Prepared Provider to Providers ... Add( provider, mProviders); // return result; } // // Add Providers ... int AddProviders( X121SignalProvider &providers[] // Specific Providers ... ) { // int result = 0; // int providersCount = ArraySize(providers); if (providersCount <= 0) { return result; } // for (int i = 0; i < providersCount; i++) { // X121SignalProvider iProvider = providers[i]; // bool isAdded = AddProvider(iProvider); if (isAdded) { result++; } } // return result; } // // END Properties ... // // // START Overrides ... // // void OnPositionsChangedHandler(int count) { } // // Handle TakeProfit Event ... void OnTakeProfitTriggered(const XDeal &deal) { // // Since we Use Hedge in Min Profit ... // Some times a Position Modified and SL Trails ... // this Position closed through sl Event ... // here we Must Close positions's Pack Orders ... // // So We Have to Get Positions Pack ... XPositionPack dealPack; bool hasPack = mTrader.GetDealPack( deal, dealPack); if (hasPack) { HandleClosePack(dealPack); } // CancelAllEQMOrders(); } // // Handle StopLoss Event ... void OnStopLossTriggered(const XDeal &deal) { // // Since we Use Hedge in Min Profit ... // Some times a Position Modified and SL Trails ... // this Position closed through sl Event ... // here we Must Close positions's Pack Orders ... // // So We Have to Get Positions Pack ... XPositionPack dealPack; bool hasPack = mTrader.GetDealPack( deal, dealPack); if (hasPack) { HandleClosePack(dealPack); } // CancelAllEQMOrders(); } // // END Overrides ... // // // START Inheritance Functions ... // // void PrepareTag() { mTag = "X121EA:" + mSymbol + "," + ToString(mPeriod) + (string)mMagic; } // // Check Providers Guard States ... bool CheckGuard(XGuard &guards[]) { // bool result = false; // Clean(guards); // // Positions Management ... // HandlePositionManagement(); // int providersCount = ArraySize(mProviders); if (providersCount <= 0) { return result; } // for (int i = 0; i < providersCount; i++) { // X121SignalProvider iProvider = mProviders[i]; // XGuard iGuards[]; bool iHasGuard = iProvider.provider.GuardCheck(iGuards); if (iHasGuard) { // Copy( iGuards, guards, false); } } // // Here we Can Implement Custom Guards Senario ... // // Do Management Equity ... XSignal signals[]; HandleEQM(signals); // result = ArraySize(guards) > 0; // return result; } // // Check Providers for Signals ... bool SignalCheck(XSignal &signals[]) { // bool result = false; // Clean(signals); // // Since We may have Custom Supporting Senarios for Positions // if there is no Equity or Positions Count Passed ... // we Clear Account Policies Check here and do it after // recieveing Signals ... // // Check Providers Count ... int providersCount = ArraySize(mProviders); if (providersCount <= 0) { return result; } // // Here we proccess all Exists Registered Providers and get // probably signals and add them signals Array ... // // Loop through Providers to Recieve Market Sence based on each them ... for (int i = 0; i < providersCount; i++) { // // Get provider Descriptor Struct ... X121SignalProvider iProvider = mProviders[i]; // // Check Provider Pivot Point Ready ... int iFoundedPivots = iProvider.provider.CountPivots(); int iReuiredPivots = iProvider.provider.GetMinPivots(); if (iFoundedPivots < iReuiredPivots) { // // Start Retrieveing Pivot Points ... iProvider.provider.ProccessPivotPoints(); // // ignore Calculating Signals since Pivot Points recieved ... continue; } // // Retrieve Market Consitions from Specified Provider ... X121MarketConditions iConditions; bool iHasSignal = iProvider.provider.ProcessTick(iConditions); // // Check there is Signal or not ... if (iHasSignal && iConditions.hasSignal) { // // Check Signalling is Enabled by Signal type ... bool isiSignalLong = IsLong(iConditions.signal.type); if ((isiSignalLong && !mEnableLongs) || (!isiSignalLong && !mEnableShorts)) { continue; } // // Add Signal to Retrieved Signals Collection ... Add( iConditions.signal, signals); } } // // Check Signals Exists for Processing ... result = ArraySize(signals) > 0; // return result; } // // Before Base EA Class Execute Signals ... // this Action Run to Implement Custom Management ... void BeforeSignalExecution( XSignal &signals[] // Base EA Checked Signals ... ) { // // Implement Custom Signal Executing Senario Here ... HandleEQM(signals); // // Here we force Signaller Signals must be in Profit ... CheckSignalsProviderState(signals); } // // END Inheritance Functions ... // // // START Provided Actions ... // // // END Provided Actions ... // // // EQM Props ... // // int MinAgeForDoSupport() { return mMinAgeForDoSupport; } // void MinAgeForDoSupport(int value) { // if (value <= 0) { value = 0; } // if (value == mMinAgeForDoSupport) { return; } // mMinAgeForDoSupport = value; } // int MinAgeForUpdateSupports() { return mMinAgeForUpdateSupports; } // void MinAgeForUpdateSupports(int value) { // if (value <= 0) { value = 0; } // if (value == mMinAgeForUpdateSupports) { return; } // mMinAgeForUpdateSupports = value; } // // Protected ... protected: // // Private ... private: // // Props ... X121SignalProvider mProviders[]; X121ProviderInputs mProviderConfig; TOnSignalConditions mOnSignalConditions; // // Actions ... // // EQM ... // // int mMinAgeForDoSupport; int mMinAgeForUpdateSupports; // bool ExecuteEQMSignal( const XSignal &signal, // Source Signal ... ENUM_X_SIGNAL_EXECUTION_FAILED &reason, // Provides Error Reason ... bool checkPoliciese = true // Check Account Policies Before Execute Signal ... ) { // bool result = false; reason = X_NOTHING; // // Check Account Policies ... if (checkPoliciese) { // // First Check Equity ... result = CheckEquityForTrade(); if (!result) { // reason = X_FAILED_REASON_EQUITY; return result; } // // Check Positions Count ... result = ChecPositionsForTrade(); if (!result) { // reason = X_FAILED_REASON_MAX_REACHED; return result; } // // Check Spread ... result = IsSpreadOkForSignalExecution(signal); if (!result) { // reason = X_FAILED_REASON_SPREAD; return result; } } // XSignal tmpSignal = signal; PrepareSignal(tmpSignal); // // Generate Provider Comment ... string comment = GenerateXEQMSupportComment(); // result = mTrader .ExecuteSignal( tmpSignal, comment // ); if (!result) { reason = X_UNKNOWN; } // return result; } // // Execute Specific Signals by Checking Spreads ... // if provided ... int ExecuteEQMSignals( const XSignal &signals[], // Signals Collection ... ENUM_X_SIGNAL_EXECUTION_FAILED &reasons[], // Provides Error Reason ... bool checkPoliciese = true // Check Account Policies Before Execute Signal ... ) { // int result = 0; // Clean(reasons); // int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return result; } // // Here we Have to Check Account Policies // and Execute Signals base on them ... // for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; // ENUM_X_SIGNAL_EXECUTION_FAILED iReason = X_NOTHING; // bool isExecuted = ExecuteEQMSignal( iSignal, iReason, checkPoliciese // ); if (isExecuted) { result++; } // Add( iReason, reasons); } // return result; } // // Retrieve All EQM Placed Support Orders ... int GetEQMOrders( XOrder &orders[] // Hold Result ) { // int result = 0; // XOrder allOrders[]; int allOrdersCount = GetOrders(allOrders); if (allOrdersCount <= 0) { return result; } // // Extract EQM Orders ... result = GetEQMSupportOrders( orders, allOrders); // return result; } // // Retrieve All EQM Support Positions ... int GetEQMPositions( XPosition &positions[] // Hold Result ) { // int result = 0; // XPosition allPositions[]; int allPositionsCount = GetPositions(allPositions); if (allPositionsCount <= 0) { return result; } // // Extract EQM Positions ... result = GetEQMSupportPositions( positions, allPositions); // return result; } // // Count all open Positions Volume for supports ... double GetEQMSupportVolume( bool ignoreEQM = true // Ignore EQM Positions ) { // double result = 0; // // TODO: // add to Props ... double maxEQMSupportVolume = 0.3; // // Retrieve Positions ... XPosition positions[]; int positionsCount = GetPositions(positions); if (positionsCount <= 0) { return result; } // for (int i = 0; i < positionsCount; i++) { // XPosition iPosition = positions[i]; // // Check Current Position is EQM Position Or Not ... bool isEQM = IsEQMSupport(iPosition.comment); if (isEQM && ignoreEQM) { continue; } // result += iPosition.volume; } // // Multiply Volume Summary ... // TODO: Make it Configurable ... result *= 1; if (result > maxEQMSupportVolume) { result = maxEQMSupportVolume; } // return result; } // // Cancel all EQM Placed Support Orders ... bool CancelAllEQMOrders() { // bool result = false; // XOrder eqmOrders[]; int eqmOrdersCount = GetEQMOrders(eqmOrders); if (eqmOrdersCount <= 0) { return result; } // result = mTrader.CancelOrders(eqmOrders); // return result; } // // Add Support Signals based on EQM Algo ... void DoEQMSupport( const XSignal &signals[], // this used when signallers call EQM ... const XPosition &positions[] // positions for supporting using EQM ... ) { // // Check EQM is Enabled Or Not ... bool isEQMEnable = mMinAgeForDoSupport > 0 && mMinAgeForUpdateSupports > 0; if (!isEQMEnable) { return; } // bool doSupportPivots = false; bool doSupportByFibos = true; bool doSupportBySignals = true; // int signalsCount = ArraySize(signals); int positionsCount = ArraySize(positions); // if (positionsCount <= 0) { // // We can Ignore this when // we need to Support Positions Only ... // for Other Reasons ... return; } // // NOTE: // we Have to Check Previously Supported Signals ... // and Extract Longest Age ... // then if the Age is Long enough for Updating, Cncell All EQM Orders ... // other wise we have to waits untill Market Decide what to do ... XOrder orders[]; int ordersCount = GetEQMOrders(orders); if (ordersCount > 0) { // XOrder oldestOrder; int oldestOrderAge = GetOldest( oldestOrder, orders); // if (oldestOrderAge <= 0) { return; } // bool isOldEnoughForCancel = oldestOrderAge >= mMinAgeForUpdateSupports; if (!isOldEnoughForCancel) { // // There are Enabled EQM Orders ... // so we have to wait for them ... return; } else { // // Here we Cancel Pending Orders ... CancelAllEQMOrders(); } } // // All Support Signals from // each Senario collect into this // and then Executed Once ... XSignal supports[]; // double volume = GetEQMSupportVolume( false // doesnt ignore eqm position volumes for supporting ); // // SENARIO: // // IND: (in drawdown) // - Find Min Profit of InD Positions ... // - Find Max Profit of InD Positions ... // // INP: (in profit) // - Find Min Profit of InD Positions ... // - Find Max Profit of InD Positions ... // XPosition inDPositions[]; XPosition inPPositions[]; ExtractPositionsBasedOnProfits( positions, inDPositions, inPPositions // ); // double maxP = 0; double minP = 0; int maxInPPositionIDX = -1; int minInPPositionIDX = -1; int inPPositionsCount = ArraySize(inPPositions); if (inPPositionsCount > 0) { // // Find Min and Max ... for (int i = 0; i < inPPositionsCount; i++) { // XPosition iPosition = inPPositions[i]; // maxP = maxP == 0 || maxP < iPosition.profit ? iPosition.profit : maxP; if (maxP == iPosition.profit) { maxInPPositionIDX = i; } // minP = minP == 0 || minP > iPosition.profit ? iPosition.profit : minP; if (minP == iPosition.profit) { minInPPositionIDX = i; } } } // double maxD = 0; double minD = 0; int maxInDPositionIDX = -1; int minInDPositionIDX = -1; int inDPositionsCount = ArraySize(inDPositions); if (inDPositionsCount > 0) { // // Find Min and Max ... for (int i = 0; i < inDPositionsCount; i++) { // XPosition iPosition = inDPositions[i]; // maxD = maxD == 0 || maxD < iPosition.profit ? iPosition.profit : maxD; if (maxD == iPosition.profit) { maxInDPositionIDX = i; } // minD = minD == 0 || minD > iPosition.profit ? iPosition.profit : minD; if (minD == iPosition.profit) { minInDPositionIDX = i; } } } // // For InDPositions: // it is so Better for US to Follow In Profit Positions for Supporting ... // if they aren't any in profit Position then start Supporting In DrawDown Positions ... bool canSupportInDPositions = maxInPPositionIDX == -1 && minInPPositionIDX == -1; // // Here we have all we want ... // Next step is to Implement EQM Supporting Senarios ... // // SENARIO: // - Using Pivots (Support and Resistances); // ---> find pivots on it's side and place support: // - Using Fibonacci; // - Using Provided Signals; // // Using Pivots For Supporting ... if (doSupportPivots) { // // this must be contains all available pivots ... double price; string symbol; double pivots[]; XOHCLSupRes supRes; double rateStep = 15; ENUM_TIMEFRAMES period; // // here we have to loop through all available providers and retrieve pivots // then add them to our pivots if their not Exists ... int providersCount = CountProviders(); for (int i = 0; i < providersCount; i++) { // X121SignalProvider iSignalProvider = mProviders[i]; // // Extract iSignalProvider's Pivots ... double iPivots[]; int iPivotsCount = iSignalProvider .provider .FillPivotPoints(iPivots); if (iPivotsCount <= 0) { continue; } // // Fill their Values to Main Array ... // if they are not exists ... AddsIfNotExists( iPivots, pivots); } // int pivotsCount = ArraySize(pivots); if (pivotsCount > 0) { // // Here we Can Do EQM Support based on Pivots ... // // TODO: Make these Configurable ... bool placeTP = false; bool placeSL = false; bool useBoundaryForTPSL = true; int numberOfPivotsAroundPrice = 5; // if (maxInPPositionIDX >= 0 && false) { // // this means we have max in profit Position ... // and this is much better to guard it ... // symbol = inPPositions[maxInPPositionIDX].symbol; price = GetEntry( symbol, inPPositions[maxInPPositionIDX].type // ); period = inPPositions[maxInPPositionIDX].period; rateStep = PointToPrice( symbol, rateStep // ); // // Extract Required Number of Pivots ... supRes = ExtractSupportAndResistance( price, pivots, numberOfPivotsAroundPrice, rateStep // ); // // now we have to Generate Support Signals based on // retrieve XOHCLSupRes ... GenerateSupportAndResistanceSignals( supports, // Result ... supRes, // Support and Resistance Model ... symbol, period, price, volume, placeSL, placeTP, useBoundaryForTPSL // ); } // if (minInPPositionIDX >= 0 && false) { // // this means we have max in profit Position ... // and this is much better to guard it ... // symbol = inPPositions[minInPPositionIDX].symbol; price = GetEntry( symbol, inPPositions[minInPPositionIDX].type // ); period = inPPositions[minInPPositionIDX].period; rateStep = PointToPrice( symbol, rateStep // ); // // Extract Required Number of Pivots ... supRes = ExtractSupportAndResistance( price, pivots, numberOfPivotsAroundPrice, rateStep // ); // // now we have to Generate Support Signals based on // retrieve XOHCLSupRes ... GenerateSupportAndResistanceSignals( supports, // Result ... supRes, // Support and Resistance Model ... symbol, period, price, volume, placeSL, placeTP, useBoundaryForTPSL // ); } // // For InDPositions: if (canSupportInDPositions) { // if (maxInDPositionIDX >= 0 && false) { // // Extract Required Number of Pivots ... // symbol = inDPositions[maxInDPositionIDX].symbol; price = GetEntry( symbol, inDPositions[maxInDPositionIDX].type // ); period = inDPositions[maxInDPositionIDX].period; rateStep = PointToPrice( symbol, rateStep // ); // // Extract Required Number of Pivots ... supRes = ExtractSupportAndResistance( price, pivots, numberOfPivotsAroundPrice, rateStep // ); // // now we have to Generate Support Signals based on // retrieve XOHCLSupRes ... GenerateSupportAndResistanceSignals( supports, // Result ... supRes, // Support and Resistance Model ... symbol, period, price, volume, placeSL, placeTP, useBoundaryForTPSL // ); } // if (minInDPositionIDX >= 0 && false) { // // Extract Required Number of Pivots ... // symbol = inDPositions[minInDPositionIDX].symbol; price = GetEntry( symbol, inDPositions[minInDPositionIDX].type // ); period = inDPositions[minInDPositionIDX].period; rateStep = PointToPrice( symbol, rateStep // ); // // Extract Required Number of Pivots ... supRes = ExtractSupportAndResistance( price, pivots, numberOfPivotsAroundPrice, rateStep // ); // // now we have to Generate Support Signals based on // retrieve XOHCLSupRes ... GenerateSupportAndResistanceSignals( supports, // Result ... supRes, // Support and Resistance Model ... symbol, period, price, volume, placeSL, placeTP, useBoundaryForTPSL // ); } } } } // // Support using Provided Signals ... if (doSupportBySignals && signalsCount > 0) { // // Change Signals Volume to Support Volume ... for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = signals[i]; iSignal.sl = 0; // iSignal.volume = volume; // Add( iSignal, supports); } } // // Support Using Fibos ... if (doSupportByFibos) { // int providersCount = CountProviders(); for (int i = 0; i < providersCount; i++) { // X121SignalProvider iSignalProvider = mProviders[i]; // // Extract iSignalProvider's Pivots ... X121MarketConditions iConditions = iSignalProvider .provider .GetMarketConditions(0); // double pivots[] = { // iConditions.xmanInfo.peaks[0], // iConditions.xmanInfo.fibLevel1s[0], iConditions.xmanInfo.fibLevel2s[0], iConditions.xmanInfo.fibLevel3s[0], iConditions.xmanInfo.fibLevel4s[0], iConditions.xmanInfo.fibLevel5s[0], // iConditions.xmanInfo.vales[0]}; // bool placeTP = false; bool placeSL = false; bool useBoundaryForTPSL = false; double price = GetEntry( iConditions.symbol, POSITION_TYPE_BUY); // XSignal fibSignals[]; int fibSignalsCount = GenerateSequentialSignals( fibSignals, pivots, iConditions.symbol, iConditions.period, price, volume, placeSL, placeTP, useBoundaryForTPSL // ); if (fibSignalsCount > 0) { // Copy( fibSignals, supports, false); } } } // // Here we Must Execute Support Signals ... int supportsCount = ArraySize(supports); if (supportsCount <= 0) { return; } // ENUM_X_SIGNAL_EXECUTION_FAILED reasons[]; int supported = ExecuteEQMSignals( supports, reasons, false // Since these are Support Signals, we Ignore Accont Policies Check ... ); } // // All available Equity Actions Implemented here ... void HandleEQM( const XSignal &signals[] // this used when signallers call EQM ... ) { // XPosition positions[]; int positionsCount = GetPositions(positions); if (positionsCount <= 1) { return; } // // Used Signals when EQM required ... int signalsCount = ArraySize(signals); // double profit = CalculatePositionsProfit(positions); if (profit > 0) { // double requiredProfit = CalculateRequiredProfitForHedge(positions); bool canHedge = profit > requiredProfit; if (canHedge) { // string comment = "EQM Hedge ..."; bool isHedged = mTrader.ClosePositions( positions, comment); if (isHedged) { // string message = "EQM Hedged (" + ToString(positionsCount) + ") in Profit: " + ToString(profit); // LogMessage(message); } } // return; } // // Check Positions Count ... bool isPositionsReady = ChecPositionsForTrade(); if (!isPositionsReady) { // // TODO: // Implement what is must to do when Max Positions Reached ... // signals can Used ... return; } // // Check Equity For Trade ... bool isEquityReady = CheckEquityForTrade(); if (!isEquityReady) { // // Implement EQM Support Of Account here ... // signals can Used ... DoEQMSupport( signals, positions); return; } // // TODO: Implement other Management Senarios if required here ... } // // PROVIDERS ... // // // Count Attached Providers ... int CountProviders() { return ArraySize(mProviders); } // // Find Specific Provider Index by using give symbol and period ... int GetProviderIndex( string symbol, // Trading Symbol ... ENUM_TIMEFRAMES period // Trading Time frame ... ) { // int result = -1; // // Validate Args ... if (period == NULL || symbol == NULL || StringLen(symbol) == 0) { return result; } // int providersCount = ArraySize(mProviders); if (providersCount <= 0) { return result; } // for (int i = 0; i < providersCount; i++) { // X121SignalProvider iProvider = mProviders[i]; // if (iProvider.symbol == symbol && iProvider.period == period) { // result = i; break; } } // return result; } // // Prepare Default Configurations for X121Provider Setup ... void PrepareProviderConfig() { // // Set Default X121 Provider Configurations ... // // XMAN ... // // Candle Timer ... mProviderConfig.xmanConfig.candleTimerColor = clrGold; mProviderConfig.xmanConfig.candleTimerCorner = CORNER_RIGHT_UPPER; // // Chart Style ... mProviderConfig.xmanConfig.upColor = clrLime; mProviderConfig.xmanConfig.downColor = clrRed; mProviderConfig.xmanConfig.lineColor = clrLime; mProviderConfig.xmanConfig.bearishColor = clrRed; mProviderConfig.xmanConfig.bullishColor = clrLime; mProviderConfig.xmanConfig.volumesColor = clrGreen; mProviderConfig.xmanConfig.chartMode = CHART_CANDLES; // // Market Cycles ... // // Level 1 ... mProviderConfig.xmanConfig.l1Method = X_PERIOD_AUTO; mProviderConfig.xmanConfig.l1Period = NULL; // // Level 1 ... mProviderConfig.xmanConfig.l2Method = X_PERIOD_AUTO; mProviderConfig.xmanConfig.l2Period = NULL; // // Level 1 ... mProviderConfig.xmanConfig.l3Method = X_PERIOD_AUTO; mProviderConfig.xmanConfig.l3Period = NULL; // // Level 1 ... mProviderConfig.xmanConfig.l4Method = X_PERIOD_AUTO; mProviderConfig.xmanConfig.l4Period = NULL; // // Fibonacci ... mProviderConfig.xmanConfig.fiboLevel1 = 0.236; mProviderConfig.xmanConfig.fiboLevel2 = 0.382; mProviderConfig.xmanConfig.fiboLevel3 = 0.5; mProviderConfig.xmanConfig.fiboLevel4 = 0.618; mProviderConfig.xmanConfig.fiboLevel5 = 0.764; // // Boundary Detection Modes ... mProviderConfig.xmanConfig.hhMode = MODE_HIGH; mProviderConfig.xmanConfig.llMode = MODE_LOW; // // Trend Detection ... mProviderConfig.xmanConfig.trendMultiplier = 3.5; mProviderConfig.xmanConfig.trendPriceAppliedTo = PRICE_MEDIAN; // // Ribbon Detection ... mProviderConfig.xmanConfig.ribbonMode = X_MA_SMMA; // // Hull Trend Detection ... mProviderConfig.xmanConfig.hullDivisor = 2.0; mProviderConfig.xmanConfig.hullUpAppliedTo = PRICE_HIGH; mProviderConfig.xmanConfig.hullDownAppliedTo = PRICE_LOW; // // SSL Channel ... mProviderConfig.xmanConfig.sslcMode = X_MA_SMA; mProviderConfig.xmanConfig.sslcUpAppliedTo = PRICE_HIGH; mProviderConfig.xmanConfig.sslcDownAppliedTo = PRICE_LOW; // // Presentation ... // NOTE: Since we Configure Presentation on PreDefine Section ... // here we turn of all Presentations as Default ... mProviderConfig.xmanConfig.showCandleTimer = false; mProviderConfig.xmanConfig.showCandles = false; mProviderConfig.xmanConfig.showHKCandles = false; mProviderConfig.xmanConfig.showSMHKCandles = false; mProviderConfig.xmanConfig.showPeaksAndVales = false; mProviderConfig.xmanConfig.showTrends = false; mProviderConfig.xmanConfig.fillTrends = false; mProviderConfig.xmanConfig.showLevels = false; mProviderConfig.xmanConfig.showConsolidations = false; mProviderConfig.xmanConfig.showRibbons = false; mProviderConfig.xmanConfig.showHull = false; mProviderConfig.xmanConfig.showSSLChannel = false; mProviderConfig.xmanConfig.showFibo1Levels = false; mProviderConfig.xmanConfig.showFibo2Levels = false; mProviderConfig.xmanConfig.showFibo3Levels = false; mProviderConfig.xmanConfig.showFibo4Levels = false; mProviderConfig.xmanConfig.showFibo5Levels = false; // PreDefineProviderConfig(); } // // Config Representation of X121 Provider Setup ... // for Specified Strategies ... void PreDefineProviderConfig() { // // Here we have to Name or Predefined Styles ... bool x786Config = true; // // by default we need to Show Candles and also Candle Timer ... mProviderConfig.xmanConfig.showCandles = true; mProviderConfig.xmanConfig.showCandleTimer = true; // // now we act based on Predefined Variables ... if (x786Config) { // bool showHK = false; bool showPVs = true; bool showFibo = true; bool showSMHK = false; bool showHull = false; bool showSSLC = false; bool showTrend = true; bool showRibbon = true; bool showPVLevels = false; bool showPVLevelConsolidations = false; // mProviderConfig.xmanConfig.showCandles = !showHK; mProviderConfig.xmanConfig.showHKCandles = showHK; mProviderConfig.xmanConfig.showSMHKCandles = showSMHK; // mProviderConfig.xmanConfig.showHull = showHull; mProviderConfig.xmanConfig.showTrends = showTrend; mProviderConfig.xmanConfig.showRibbons = showRibbon; mProviderConfig.xmanConfig.showSSLChannel = showSSLC; // mProviderConfig.xmanConfig.showFibo1Levels = showFibo; mProviderConfig.xmanConfig.showFibo2Levels = showFibo; mProviderConfig.xmanConfig.showFibo3Levels = showFibo; mProviderConfig.xmanConfig.showFibo4Levels = showFibo; mProviderConfig.xmanConfig.showFibo5Levels = showFibo; // mProviderConfig.xmanConfig.showPeaksAndVales = showPVs; // mProviderConfig.xmanConfig.showLevels = showPVLevels; mProviderConfig.xmanConfig.showConsolidations = showPVLevelConsolidations; } } // // Check Signallers ... // when recieved signals we have to check each signal // based on it's signaller ... // if there isn't any open Position from it's signaller or // there was open positions and all of them in profit we accept new recieved signal ... // in this way we can handle balance between signallers and their positions and also // we prevent big losses ... int CheckSignalsProviderState(XSignal &signals[]) { // int result = 0; // int signalsCount = ArraySize(signals); if (signalsCount <= 0) { return result; } // XSignal tmp[]; Copy( signals, tmp); Clean(signals); // // Loop through Signals ... for (int i = 0; i < signalsCount; i++) { // XSignal iSignal = tmp[i]; // int providersCount = ArraySize(iSignal.providers); if (providersCount <= 0) { continue; } // string iSignaller = iSignal.providers[0]; // // Retrieve Signaller's Open Positions ... XPosition iSignallerPositions[]; int iSignallerPositionsCount = GetPositions( iSignallerPositions, iSignal.symbol, iSignal.type, iSignal.period, iSignaller); if (iSignallerPositionsCount <= 0) { // // this means we can accept Signal without Checking anything ... Add( iSignal, signals // ); // // TODO: Here we can Provide Support Signals for First Arrived Signal ... // continue; } else { // // TODO: Remove this ... // Only One Signal ... // continue; } // // here we have to check Signallers open Positions Profit ... double iSignallerPositionsProfit = CalculatePositionsProfit(iSignallerPositions); bool isInProfit = iSignallerPositionsProfit > 0; if (!isInProfit) { // TODO: Remove this ... // continue; } // // Check Signal Entry ... // in Compare with nearest Signaller Position ... // // Find Youngest Signaller Position ... XPosition iSignallerYoungestPosition; int iSignallerYoungestPositionAge = GetYoungest( iSignallerYoungestPosition, iSignallerPositions); if (iSignallerYoungestPositionAge < 0) { // TODO: Remove this ... // continue; } // bool isEntryOk = IsLong(iSignal.type) && iSignal.type == iSignallerYoungestPosition.type ? iSignal.entry > iSignallerYoungestPosition.entry : iSignal.entry < iSignallerYoungestPosition.entry; if (!isEntryOk) { // TODO: Remove this ... // continue; } // // this means all Signaller Open Positions in Profit ... // so we Accept Signal ... Add( iSignal, signals // ); } // Clean(tmp); // result = ArraySize(signals); // if (result > 0) { // // This means Signallers provide In Profits Positions Before ... // the Best thing is make them Risk Free at current Signals Minimum Entry ... // TODO: Complete This ... } // return result; } }; // // START Usefull Functions ... // // // END Usefull Functions ... //