//////////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 XTM Signal Provider Library // -------------------------------------------------------- // Name: XTMSignalProvider // Description: XTM based signal provider ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://www.saherelm.ir" #property version "1.00" #property strict // // Include Models Library ... #include "..\Libraries\x-saherelm.models.lib.mq5"; // // START Inputs ... #include "..\Libraries\x-saherelm.xtm.provider.inputs.mq5"; // // Include Common Library ... #include "x-saherelm.common.lib.mq5"; // // Include Logger Library ... #include "x-saherelm.log.lib.mq5"; // // Include Alert Library ... #include "x-saherelm.alert.lib.mq5"; // // Include Draw Library ... #include "x-saherelm.draw.lib.mq5"; // // Include Class Libraries ... #include "x-saherelm.class.lib.mq5"; // // START Global Definitions: Variables, Properties and etc ... // // XCTrade *xTMTrader; XCAccountInfo xTMAccountInfo; // // Defined Indicator/Oscillator Handlers ... // // XTM Indicator ... int xTMHandler = INVALID_HANDLE; double xTMMaBuffer[]; double xTMStateBuffer[]; // // XOBD Indicator ... int xOBDHandler = INVALID_HANDLE; double xOBDSwingsBuffer[]; // // XTD Oscillator ... int xTDHandler = INVALID_HANDLE; double xTDBullishBuffer[]; double xTDBearishBuffer[]; double xTDStateBuffer[]; // // XTPD Oscillator ... int xTPDHandler = INVALID_HANDLE; double xTPDBullishPowerBuffer[]; double xTPDBearishPowerBuffer[]; double xTPDStateBuffer[]; // // XCHMA Oscillator ... int xCHMAHandler = INVALID_HANDLE; double xCHMALcFastBuffer[]; double xCHMALcSlowBuffer[]; double xCHMALcStateBuffer[]; double xCHMAMcFastBuffer[]; double xCHMAMcSlowBuffer[]; double xCHMAMcStateBuffer[]; double xCHMAScFastBuffer[]; double xCHMAScSlowBuffer[]; double xCHMAScStateBuffer[]; double xCHMAHotStateBuffer[]; // // this is an important Variable which // when it is true, all calculations paused ... bool xTMPauseTrading = false; // // END Global Definitions: Variables, Properties and etc ... // // // START Provided Functions ... // // // Initial Library if required ... bool OnInInitXTMSignalProviderLibrary() { // bool result = false; // // Check Risk Management ... if (xTMUseDynamicVolume) { // if (xTMBalanceIncreasedFactor <= 0 || xTMVolumeIncreasedFactor <= 0) { // LogMessage("invalid volume increased factors ..."); // return result; } } else { // double maxAvailableVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); double minAvailableVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); // if (xTMStaticVolume > maxAvailableVolume || xTMStaticVolume < minAvailableVolume) { // LogMessage("invalid static volume ..."); // return result; } } // // Define Handlers ... ResetLastError(); // // XTM Handler ... xTMHandler = iCustom( _Symbol, _Period, "x-saherelm.xtm.indicator", // // Inputs ... xTMMaPeriod, xTMMaShift, xTMMaMethod, xTMMaAppliedTo); if (xTMHandler == INVALID_HANDLE) { // LogMessage("XTM Provider => error initializing XTM Indicator: " + (string)GetLastError()); return result; } // // XTD Handler ... xTDHandler = iCustom( _Symbol, _Period, "x-saherelm.xtd.oscillator", // // Inputs ... xTDLength, xTDDrawCrosses, xTDBullishArrowCode, xTDBullishArrowColor, xTDBearishArrowCode, xTDBearishArrowColor); if (xTDHandler == INVALID_HANDLE) { // LogMessage("XTM Provider => error initializing XTD Oscillator: " + (string)GetLastError()); return result; } // // XOBD Handler ... xOBDHandler = iCustom( _Symbol, _Period, "x-saherelm.xobd.indicator", // // Inputs ... xOBDLength, xOBDArrowDistanceFromPrice, xOBDSwingHighArrowCode, xOBDSwingHighArrowColor, xOBDSwingLowArrowCode, xOBDSwingLowArrowColor); if (xOBDHandler == INVALID_HANDLE) { // LogMessage("XTM Provider => error initializing XOBD Indicator: " + (string)GetLastError()); return result; } // // XTPD Handler ... xTPDHandler = iCustom( _Symbol, _Period, "x-saherelm.xtpd.oscillator", // // Inputs ... xTPDLength); if (xTPDHandler == INVALID_HANDLE) { // LogMessage("XTM Provider => error initializing XTPD Oscillator: " + (string)GetLastError()); return result; } // // XCHMA Handler ... xCHMAHandler = iCustom( _Symbol, _Period, "x-saherelm.xchma.oscillator", // // Inputs ... "", xCHMADrawHotAreas, xCHMAHotBullishArrowCode, xCHMAHotBullishArrowColor, xCHMAHotBearishArrowCode, xCHMAHotBearishArrowColor, // // Long Cycle ... "", "", xCHMALcFastLength, xCHMALcSlowLength, xCHMALcMethod, xCHMALcAppliedTo, "", xCHMALcDrawWidth, xCHMALcDrawType, xCHMALcDrawStyle, xCHMALcFastColor, xCHMALcSlowColor, "", xCHMALcDrawFast, xCHMALcDrawSlow, xCHMALcDrawCrosses, // // Medium Cycle ... "", "", xCHMAMcFastLength, xCHMAMcSlowLength, xCHMAMcMethod, xCHMAMcAppliedTo, "", xCHMAMcDrawWidth, xCHMAMcDrawType, xCHMAMcDrawStyle, xCHMAMcFastColor, xCHMAMcSlowColor, "", xCHMAMcDrawFast, xCHMAMcDrawSlow, xCHMAMcDrawCrosses, // // Short Cycle ... "", "", xCHMAScFastLength, xCHMAScSlowLength, xCHMAScMethod, xCHMAScAppliedTo, "", xCHMAScDrawWidth, xCHMAScDrawType, xCHMAScDrawStyle, xCHMAScFastColor, xCHMAScSlowColor, "", xCHMAScDrawFast, xCHMAScDrawSlow, xCHMAScDrawCrosses); if (xCHMAHandler == INVALID_HANDLE) { // LogMessage("XTM Provider => error initializing XCHMA Oscillator: " + (string)GetLastError()); return result; } // // Define Buffer States ... ArraySetAsSeries(xTMMaBuffer, true); ArraySetAsSeries(xTMStateBuffer, true); ArraySetAsSeries(xTDBullishBuffer, true); ArraySetAsSeries(xTDBearishBuffer, true); ArraySetAsSeries(xTDStateBuffer, true); ArraySetAsSeries(xOBDSwingsBuffer, true); ArraySetAsSeries(xTPDBullishPowerBuffer, true); ArraySetAsSeries(xTPDBearishPowerBuffer, true); ArraySetAsSeries(xTPDStateBuffer, true); ArraySetAsSeries(xCHMALcFastBuffer, true); ArraySetAsSeries(xCHMALcSlowBuffer, true); ArraySetAsSeries(xCHMALcStateBuffer, true); ArraySetAsSeries(xCHMAMcFastBuffer, true); ArraySetAsSeries(xCHMAMcSlowBuffer, true); ArraySetAsSeries(xCHMAMcStateBuffer, true); ArraySetAsSeries(xCHMAScFastBuffer, true); ArraySetAsSeries(xCHMAScSlowBuffer, true); ArraySetAsSeries(xCHMAScStateBuffer, true); ArraySetAsSeries(xCHMAHotStateBuffer, true); // // Make XCTrader instance ... xTMTrader = new XCTrade( _Symbol, xTMSlippage, xTMMagicNumber); // result = true; // // Logging State ... string message = "Initializion of (" + "XTM Provider" + " _ " + _Symbol + " _ " + EnumToString(_Period) + ") Succeeded ..."; LogMessage(message); // return result; } // // DeInitial Library if required ... void OnDeinitXTMSignalProviderLibrary() { // // Logging State ... string message = "De Initializion of (" + "XTM Provider" + ") Succeeded ..."; LogMessage(message); } // // this is a Globally Function which do all of // checkings and positions handling ... void HandleXTMSignalProviderTick() { // if (xTMPauseTrading) { return; } // // Copy required Buffers for handle processing and check Market Conditions ... XTMReadingBuffers(); // // Handle Open Trades ... XTMHandleOpenTrades(); // // Handle Close Trades ... XTMHandleCloseTrades(); } // // Reading all required data from indicator/oscillator(s) Buffers ... void XTMReadingBuffers() { // // XTM Lines ... CopyBuffer( xTMHandler, X_XTM_MA_LINE, 0, xTMNumberOfItemsPerTick, xTMMaBuffer); CopyBuffer( xTMHandler, X_XTM_STATE_LINE, 0, xTMNumberOfItemsPerTick, xTMStateBuffer); // // XTD Lines ... CopyBuffer( xTDHandler, X_XTD_BULLISH_POWER_LINE, 0, xTMNumberOfItemsPerTick, xTDBullishBuffer); CopyBuffer( xTDHandler, X_XTD_BEARISH_POWER_LINE, 0, xTMNumberOfItemsPerTick, xTDBearishBuffer); CopyBuffer( xTDHandler, X_XTD_TREND_STATE_LINE, 0, xTMNumberOfItemsPerTick, xTDStateBuffer); // // XOBD Lines ... CopyBuffer( xOBDHandler, 0, 0, xTMNumberOfItemsPerTick, xOBDSwingsBuffer); // // XTPD Lines ... CopyBuffer( xTPDHandler, X_XTPD_BULLISH_POWER_LINE, 0, xTMNumberOfItemsPerTick, xTPDBullishPowerBuffer); CopyBuffer( xTPDHandler, X_XTPD_BEARISH_POWER_LINE, 0, xTMNumberOfItemsPerTick, xTPDBearishPowerBuffer); CopyBuffer( xTPDHandler, X_XTPD_STATE_LINE, 0, xTMNumberOfItemsPerTick, xTPDStateBuffer); // // XCHMA Buffer Readings ... CopyBuffer( xCHMAHandler, X_XCHMA_LC_FAST_LINE, 0, xTMNumberOfItemsPerTick, xCHMALcFastBuffer); CopyBuffer( xCHMAHandler, X_XCHMA_LC_SLOW_LINE, 0, xTMNumberOfItemsPerTick, xCHMALcSlowBuffer); CopyBuffer( xCHMAHandler, X_XCHMA_LC_STATE_LINE, 0, xTMNumberOfItemsPerTick, xCHMALcStateBuffer); CopyBuffer( xCHMAHandler, X_XCHMA_MC_FAST_LINE, 0, xTMNumberOfItemsPerTick, xCHMAMcFastBuffer); CopyBuffer( xCHMAHandler, X_XCHMA_MC_SLOW_LINE, 0, xTMNumberOfItemsPerTick, xCHMAMcSlowBuffer); CopyBuffer( xCHMAHandler, X_XCHMA_MC_STATE_LINE, 0, xTMNumberOfItemsPerTick, xCHMAMcStateBuffer); CopyBuffer( xCHMAHandler, X_XCHMA_SC_FAST_LINE, 0, xTMNumberOfItemsPerTick, xCHMAScFastBuffer); CopyBuffer( xCHMAHandler, X_XCHMA_SC_SLOW_LINE, 0, xTMNumberOfItemsPerTick, xCHMAScSlowBuffer); CopyBuffer( xCHMAHandler, X_XCHMA_SC_STATE_LINE, 0, xTMNumberOfItemsPerTick, xCHMAScStateBuffer); CopyBuffer( xCHMAHandler, X_XCHMA_HOT_STATE_LINE, 0, xTMNumberOfItemsPerTick, xCHMAHotStateBuffer); } // // Check Market Conditions to find Long Primary Signals ... bool XTMHasPrimaryLongSignal() { // bool result = false; // // Check MArket Conditions Based On XCHMA Oscillator for Long Signals ... // METHOD: we have to read HotStateBuffer and LCStateBuffer ... // // Check Hot Bullish State ... bool isXCHMAHotBullishState = xCHMAHotStateBuffer[1] == X_XCHMA_HOT_BULLISH && xCHMAHotStateBuffer[2] != X_XCHMA_HOT_BULLISH; // // Check Hot Bearish State ... bool isXCHMAHotBearishState = xCHMAHotStateBuffer[1] == X_XCHMA_HOT_BEARISH && xCHMAHotStateBuffer[2] != X_XCHMA_HOT_BEARISH; // // Check LC Fast Cross Over Slow ... bool isXCHMALCFastCrossedOverSlow = xCHMALcStateBuffer[1] == X_XCHMA_FAST_CROSSED_OVER_SLOW && xCHMALcStateBuffer[2] != X_XCHMA_FAST_CROSSED_OVER_SLOW; // // Check LC Fast Cross Under Slow ... bool isXCHMALCFastCrossedUnderSlow = xCHMALcStateBuffer[1] == X_XCHMA_FAST_CROSSED_UNDER_SLOW && xCHMALcStateBuffer[2] != X_XCHMA_FAST_CROSSED_UNDER_SLOW; // // Check Buy/Long Conditions ... result = xTMAllowLongTrades && isXCHMAHotBullishState && isXCHMALCFastCrossedOverSlow; // return result; } // // Check Market Conditions to find Short Primary Signals ... bool XTMHasPrimaryShortSignal() { // bool result = false; // // Check Sell/Short Conditions ... result = xTMAllowShortTrades && xTDStateBuffer[1] == X_XTD_BULLISH_CROSSED_UNDER_BEARISH && xTDStateBuffer[2] != X_XTD_BULLISH_CROSSED_UNDER_BEARISH; // return result; } // // Check Market Conditions for Grid Long Signals ... bool XTMHasGridLongSignal() { // bool result = false; // // XCHMA ... bool isXCHMAPassed = xCHMAScFastBuffer[1] < xCHMAScSlowBuffer[1] && xCHMAScFastBuffer[1] < xCHMAMcFastBuffer[1] && xCHMAScFastBuffer[1] < xCHMAMcSlowBuffer[1] && xCHMAScFastBuffer[1] < xCHMALcFastBuffer[1] && xCHMAScFastBuffer[1] < xCHMALcSlowBuffer[1] && xCHMAScFastBuffer[1] > xCHMAScFastBuffer[2]; // // XCMA Medium Cycle ... // bool isXCHMAMCPassed = xCHMAMcStateBuffer[1] == X_XCHMA_FAST_CROSSED_OVER_SLOW && xCHMAMcStateBuffer[2] != X_XCHMA_FAST_CROSSED_OVER_SLOW; // // XTD ... // bool isXTDPassed = xTDStateBuffer[1] == X_XTD_BULLISH_CROSSED_OVER_BEARISH && xTDStateBuffer[2] != X_XTD_BULLISH_CROSSED_OVER_BEARISH; // // Check Market Conditions for Long Entry Grid Trades ... result = // isXTDPassed || isXCHMAPassed // || // isXCHMAMCPassed ; // return result; } // // Check Market Conditions for Grid Short Signals ... bool XTMHasGridShortSignal() { // bool result = false; // return result; } // // Check Market Conditions for closing Long Trades ... bool XTMCanCloseLongTrades() { // bool result = false; // // result = (xTDStateBuffer[1] != X_XTD_BULLISH_OVER_BEARISH && xTDStateBuffer[1] != X_XTD_BULLISH_CROSSED_OVER_BEARISH) && xTDStateBuffer[2] == X_XTD_BULLISH_OVER_BEARISH; // // We Want to Close Long Trades When all XCHMA's is Down ... // Hot Bearish Area ... // result = xCHMAHotStateBuffer[1] == X_XCHMA_HOT_BEARISH; // return result; } // // Check Market Conditions for closing Short Trades ... bool XTMCanCloseShortTrades() { // bool result = false; // return result; } // // Handle Long/Buy for Primary Trades... bool XTMHandlePrimaryLong( XSignal &signal, // return structure if signal founded bool doTrade = true // do trade on signal ) { // bool result = false; // if (!xTMAllowLongTrades) { return result; } // ResetLastError(); // // && xTMTrader.CountLongs() == 0 if (XTMHasPrimaryLongSignal()) { // double entry = GetAsk(); double volume = XTMCalculateVolume(); // bool canDoTrade = !xTMPauseTrading && XTMIsReadyForPrimaryTrades(); // XTPSL mTpSl = XTMCalculateTPSL(X_SIGNAL_LONG, entry); if (IsValid(mTpSl)) { // signal.tp = mTpSl.tp; signal.sl = 0; // mTpSl.sl; } // signal.entry = entry; signal.volume = volume; signal.symbol = _Symbol; signal.type = X_SIGNAL_LONG; signal.magicNumber = xTMMagicNumber; signal.time = iTime(_Symbol, _Period, 0); signal.comment = "Primary_XTM_Long"; // if (enableXTMProvider && xTMAllowLongTrades && doTrade && canDoTrade) { // // Execute Signal ... result = xTMTrader.ExecuteSignal(signal); // // Since this means an error happens, we have to log this error ... if (!result) { string errMessage = "failed to execute Long signal: " + (string)GetLastError(); LogMessage(errMessage); } } else { result = false; } } // // Handle Alerts ... if (result) { // if (xTMEnableAlerts) { SendAlert(signal, true); } else { LogExecutedSignal(signal); } } // return result; } // // Handle Short/Sell for Primary Trades... bool XTMHandlePrimaryShort( XSignal &signal, // return structure if signal founded bool doTrade = true // do trade on signal ) { // bool result = false; // if (!xTMAllowShortTrades) { return result; } // ResetLastError(); // if (XTMHasPrimaryShortSignal() && xTMTrader.CountShorts() == 0) { // double entry = GetBid(); double volume = XTMCalculateVolume(); // bool canDoTrade = !xTMPauseTrading && XTMIsReadyForPrimaryTrades(); // XTPSL mTpSl = XTMCalculateTPSL(X_SIGNAL_SHORT, entry); if (IsValid(mTpSl)) { // signal.tp = mTpSl.tp; signal.sl = mTpSl.sl; } // signal.entry = entry; signal.volume = volume; signal.symbol = _Symbol; signal.type = X_SIGNAL_SHORT; signal.magicNumber = xTMMagicNumber; signal.time = iTime(_Symbol, _Period, 0); signal.comment = "Primary_XTM_Short"; // if (enableXTMProvider && xTMAllowShortTrades && doTrade && canDoTrade) { // // Execute Signal ... result = xTMTrader.ExecuteSignal(signal); // // Since this means an error happens, we have to log this error ... if (!result) { string errMessage = "failed to execute Short signal: " + (string)GetLastError(); LogMessage(errMessage); } } else { result = false; } } // // Handle Alerts ... if (result) { // if (xTMEnableAlerts) { SendAlert(signal, true); } else { LogExecutedSignal(signal); } } // return result; } // // Handle Grid Long Trades ... void XTMHandleGridLong() { // if (!enableXTMProvider || !xTMAllowLongTrades || !xTMEnableGridTrades) { return; } // XSignal primaryLongs[]; XTMRetrievePrimaryTradesOfType( X_SIGNAL_LONG, primaryLongs); int count = ArraySize(primaryLongs); if (count == 0) { return; } // double price = GetAsk(); double spread = GetSpread(); double lastPrice = 0; double lastVolume = 0; // // Calculate Price Distance ... double priceDiff = PipsToPrice(xTMGridDistanceInPips); // // Primary Long Loop ... for (int i = 0; i < count; i++) { // XSignal primary = primaryLongs[i]; if (!XTMIsPrimaryTrade(primary)) { continue; } // // Retrieve Last Price for Grid Entry ... XSignal latestGridSignal = XTMRetrieveLastGridTradesOfPrimary(primary); if ( !XTMIsGridTrade(latestGridSignal) || latestGridSignal.type != primary.type || !IsValid(latestGridSignal, xTMMagicNumber)) { // lastPrice = primary.entry; lastVolume = primary.volume; } else { // lastPrice = latestGridSignal.entry; lastVolume = latestGridSignal.volume; } // // Check Market Conditions for Grid Long Signals ... bool canDoGridTrade = XTMHasGridLongSignal() && price <= lastPrice - priceDiff; if (canDoGridTrade) { // // Open a Long Grid Position ... double volumeMultiplier = (primary.entry - price) / priceDiff; double volume = NormalizeDouble(lastVolume * (volumeMultiplier * xTMGridVolumeMultiplier), 2); // NormalizeDouble(lastVolume * xTMGridVolumeMultiplier, 2); string comment = "Grid_XTM_Long_" + XTMGenerateTicketTitle(primary.ticket); // XSignal gridLong = {}; // gridLong.entry = price; gridLong.volume = volume; gridLong.symbol = _Symbol; gridLong.type = X_SIGNAL_LONG; gridLong.magicNumber = xTMMagicNumber; gridLong.time = iTime(_Symbol, _Period, 0); gridLong.comment = comment; // XTPSL mTpSl = XTMCalculateTPSL(X_SIGNAL_LONG, price); if (IsValid(mTpSl)) { // gridLong.tp = price + (100 * _Point) + spread; gridLong.sl = 0; } // // Execute Signal ... bool isExecuted = xTMTrader.ExecuteSignal(gridLong); if (isExecuted) { // // Handle Alert and Log ... if (xTMEnableAlerts) { SendAlert(gridLong, true); } else { LogExecutedSignal(gridLong); } } } } } // // Handle Open Trades ... void XTMHandleOpenTrades() { // // Check Provider is Enable ... if (!enableXTMProvider) { return; } // // Primary Long Trade ... if (xTMAllowLongTrades) { // XSignal primaryLongSignal = {}; bool isPrimaryLongSignalExecuted = XTMHandlePrimaryLong(primaryLongSignal); // // Handle Grid Trades ... if (xTMEnableGridTrades) { XTMHandleGridLong(); } } // // Primary Short Trade ... if (xTMAllowShortTrades) { // XSignal primaryShortSignal = {}; bool isPrimaryShortSignalExecuted = XTMHandlePrimaryShort(primaryShortSignal); } } // // Handle Close Trades ... void XTMHandleCloseTrades() { // // Close Conditional Long Trades ... if (xTMAllowLongTrades) { // // Handle Long/Buy Close ... if (xTMTrader.CountLongs() > 0 && XTMCanCloseLongTrades()) { // xTMTrader.CloseLongPositions(); // string message = "XTM Closing Long Trades ..."; // if (xTMEnableAlerts) { SendAlert(message); } else { LogMessage(message); } } } // // Close Conditional Short Trades ... if (xTMAllowShortTrades) { // // Handle Short/Sell Close ... if (xTMTrader.CountShorts() > 0 && XTMCanCloseShortTrades()) { // xTMTrader.CloseShortPositions(); // string message = "XTM Closing Short Trades ..."; // if (xTMEnableAlerts) { SendAlert(message); } else { LogMessage(message); } } } // // Close Long Time Trades ... if (xTMMaximumTradeLife > 0) { // bool hasLongTimeTradeClosed = xTMTrader.CloseLongTimeTrades( xTMMaximumTradeLife, _Period); if (hasLongTimeTradeClosed) { // string message = "Close Long Time Trades ..."; if (xTMEnableAlerts) { SendAlert(message); } else { LogMessage(message); } } } // // Close MAximum DrawDown Trades ... if (xTMMaximumAllowedDrawDownFactorPerTrade > 0) { // // Calculate Max Available DrawDown per Trade ... double deposit = xTMAccountInfo.GetInitialBalance(); double maxAllowedDrawDown = xTMMaximumAllowedDrawDownFactorPerTrade * deposit; // // Try To Find and Close In Max DrawDown Trades ... bool hasInDrawDownTradeClosed = xTMTrader.CloseInDrawDownTrades(maxAllowedDrawDown); if (hasInDrawDownTradeClosed) { // string message = "Close Max DrawDown Trades ..."; if (xTMEnableAlerts) { SendAlert(message); } else { LogMessage(message); } } } } // // Calculating Volume for Tradings ... double XTMCalculateVolume() { // double result = xTMStaticVolume; if (!xTMUseDynamicVolume) { return result; } // double balance = xTMAccountInfo.GetBalance(); double deposit = xTMAccountInfo.GetInitialBalance(); double balanceIncreasedRate = xTMBalanceIncreasedFactor * deposit; double volumeIncreasedRate = xTMVolumeIncreasedFactor; // // result = (volumeIncreased * accountBalance) / balanceIncreased; result = (balance / balanceIncreasedRate) * volumeIncreasedRate; // // Normalize Volume ... result = NormalizeDouble(result, 2); // double maxAvailableVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); double minAvailableVolume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); // // Validate Result ... if (result > maxAvailableVolume) { result = maxAvailableVolume; } else if (result < minAvailableVolume) { result = minAvailableVolume; } // return result; } // // Find MIN Swing Low ... double XTMGetMinSwingLow() { // double result = EMPTY_VALUE; // double xOBDSwings[]; ArraySetAsSeries(xOBDSwings, true); // XTMReadingSwings(50, xOBDSwings); // // Loopp through retrieved Swings ... int count = 0; int swingsCountForResult = 3; for (int i = 0; i < ArraySize(xOBDSwings) && count < swingsCountForResult; i++) { // if (xOBDSwings[i] == X_SWING_LOW) { // count++; // XOHCL candle = GetCandle(i + 4); // result = result == EMPTY_VALUE ? candle.low : MathMin(result, candle.low); } } // // Free Array ... ArrayFree(xOBDSwings); // return result; } // // Reading Swing Buffers from XOBD Indicator ... void XTMReadingSwings( int count, double &result[]) { // CopyBuffer( xOBDHandler, 0, 0, count, result); } // // Check Provider Ready for Primary Trades ... bool XTMIsReadyForPrimaryTrades() { // bool result = false; // bool isEquityPassed = XTMCheckAccountEquity(); bool isBalancePassed = XTMCheckAccountBalance(); bool isTradesCountPassed = XTMCheckMaxOpenTrades(); // result = isEquityPassed && isBalancePassed && isTradesCountPassed; // return result; } // // Check Provider Ready for Grid Trades ... bool XTMIsReadyForGridTrades() { // bool result = false; // bool isBalancePassed = XTMCheckAccountBalance(); // result = isBalancePassed; // return result; } // // Check Max Open Trades is Valid or not ... bool XTMCheckMaxOpenTrades() { // bool result = false; // if (xTMMaxOpenTrades <= 0) { // result = true; return result; } // // Count Long Open Trades ... int totalLongTrades = xTMTrader.CountLongs(); // // Count Short Open Trades ... int totalShortTrades = xTMTrader.CountShorts(); // // Count all Open Positions ... int totalTrades = xTMTrader.Count(); // // Check Total Longs and Shorts Below or Equals to Max Open Trade Value ... result = totalTrades < xTMMaxOpenTrades; // totalLongTrades <= xTMMaxOpenTrades && totalShortTrades <= xTMMaxOpenTrades; // return result; } // // Check Max Equity for Trades ... bool XTMCheckAccountEquity() { // bool result = false; // if (xTMMaximumEquityFactorForTrade <= 0) { // result = true; return result; } // double equity = xTMAccountInfo.GetEquity(); double balance = xTMAccountInfo.GetBalance(); double initialBalance = xTMAccountInfo.GetInitialBalance(); // double maxAvailableEquity = balance - (xTMMaximumEquityFactorForTrade * initialBalance); // result = equity > maxAvailableEquity; // return result; } // // Check Account Balance For Trades ... bool XTMCheckAccountBalance() { // bool result = false; // if (xTMMinimumBalanceFactorForTrade <= 0) { // result = true; return result; } // double balance = xTMAccountInfo.GetBalance(); double initialBalance = xTMAccountInfo.GetInitialBalance(); // double minRequiredBalance = initialBalance * xTMMinimumBalanceFactorForTrade; // // Check Balance Bigger than Minimum Required ... result = balance > minRequiredBalance; // return result; } // // Calculate TP and SL ... XTPSL XTMCalculateTPSL( ENUM_X_SIGNAL_TYPE type, // Which Type to Calculate TP and SL double entry // Signal Entry Price ) { // XTPSL result = {}; result.type = X_SIGNAL_UNKNOWN; result.tp = 0; result.sl = 0; result.r2r = 0; result.entry = 0; // // // if (!xTMUseTPSL) // { // return result; // } // // Validate Args ... if (entry <= 0 || type == X_SIGNAL_UNKNOWN) { return result; } // result.type = type; result.r2r = xTMR2r; result.entry = entry; // bool isLong = type == X_SIGNAL_LONG; // // Retrieve Market Highest High and Lowest Low ... double hh = GetHighestHigh( xTMLoopback, 0); double ll = GetLowestLow( xTMLoopback, 0); // // // double maxRisk = xTMMaxRiskPerTrade * _Point; // double minRisk = xTMMinRiskPerTrade * _Point; // // Calculate Long SL ... double longSwingSL = XTMGetMinSwingLow(); longSwingSL = NormalizeDouble(longSwingSL, _Digits); // // Calculate and Normalize risk ... double risk = isLong ? entry - ll : hh - entry; // if (risk > maxRisk) // { // risk = maxRisk; // } // else if (risk < minRisk) // { // risk = minRisk; // } // double reward = risk * xTMR2r; // 30 * _Point; // risk * xTMR2r; // double tp = isLong ? entry + reward : entry - reward; double sl = isLong ? entry - risk : entry + risk; // swingSL; // isLong ? entry - risk : entry + risk; // tp = NormalizeDouble(tp, _Digits); sl = NormalizeDouble(sl, _Digits); // result.tp = tp; result.sl = isLong ? longSwingSL : 0; // swingSL; // sl; // return result; } // // Generate Ticket Title for Signal ... string XTMGenerateTicketTitle(ulong ticket) { // string result = "Ticket(" + (string)ticket + ")"; // return result; } // // Determines a Signal is Primary or not ... bool XTMIsPrimaryTrade( XSignal &signal) { // bool result = false; // int titlePosition = StringFind( signal.comment, "Primary"); result = titlePosition >= 0; // return result; } // // Determines a Signal is Grid or not ... bool XTMIsGridTrade( XSignal &signal) { // bool result = false; // int titlePosition = StringFind( signal.comment, "Grid"); result = titlePosition >= 0; // return result; } // // Check a Signal Comment Contains Specific Ticket ... bool XTMIsSignalContainsTicketComment( ulong ticket, // specified ticket which going to check ... XSignal &signal // the signal object which going to compare ... ) { // bool result = false; // // Generate Ticket Title ... string title = XTMGenerateTicketTitle(ticket); int titlePosition = StringFind(signal.comment, title); result = titlePosition >= 0; // return result; } // // Retrieve All Primary Trades ... void XTMRetrievePrimaryTrades(XSignal &result[]) { // ArrayFree(result); ArrayResize(result, 0); // XSignal allSignals[]; xTMTrader.GetAllPositions(allSignals); // if (ArraySize(allSignals) <= 0) { return; } // // Loop Through all Positions and Extract Primary Trades ... for (int i = 0; i < ArraySize(allSignals); i++) { // XSignal signal = allSignals[i]; // bool isPrimary = XTMIsPrimaryTrade(signal); if (!isPrimary) { continue; } // ArrayResize( result, ArraySize(result) + 1); result[ArraySize(result) - 1] = signal; } } // // Retrieve All Primary Spcified Type Trades ... void XTMRetrievePrimaryTradesOfType( ENUM_X_SIGNAL_TYPE type, // Specify Signal Type ... XSignal &result[] // hold results ... ) { // ArrayFree(result); ArrayResize(result, 0); // XSignal allSignals[]; XTMRetrievePrimaryTrades(allSignals); // if (ArraySize(allSignals) <= 0) { return; } // // Loop Through all Positions and Extract Primary Trades ... for (int i = 0; i < ArraySize(allSignals); i++) { // XSignal signal = allSignals[i]; // if (signal.type != type) { continue; } // ArrayResize( result, ArraySize(result) + 1); result[ArraySize(result) - 1] = signal; } } // // Retrieve All Grid Trades ... void XTMRetrieveGridTrades(XSignal &result[]) { // ArrayFree(result); ArrayResize(result, 0); // XSignal allSignals[]; xTMTrader.GetAllPositions(allSignals); // if (ArraySize(allSignals) <= 0) { return; } // // Loop Through all Positions and Extract Grid Trades ... for (int i = 0; i < ArraySize(allSignals); i++) { // XSignal signal = allSignals[i]; // bool isGrid = XTMIsGridTrade(signal); if (!isGrid) { continue; } // ArrayResize( result, ArraySize(result) + 1); result[ArraySize(result) - 1] = signal; } } // // Retrieve All Grid Specific Type Trades ... void XTMRetrieveGridTradesOfType( ENUM_X_SIGNAL_TYPE type, // Specify Signal Type ... XSignal &result[] // hold results ... ) { // ArrayFree(result); ArrayResize(result, 0); // XSignal allSignals[]; XTMRetrieveGridTrades(allSignals); // if (ArraySize(allSignals) <= 0) { return; } // // Loop Through all Positions and Extract Primary Trades ... for (int i = 0; i < ArraySize(allSignals); i++) { // XSignal signal = allSignals[i]; // if (signal.type != type) { continue; } // ArrayResize( result, ArraySize(result) + 1); result[ArraySize(result) - 1] = signal; } } // // Retrieve an Specific Primary Trade's Related Grid Trades ... void XTMRetrieveGridTradesOfPrimary( XSignal &primary, // Primary Trade which looking for it's Grid Trades ... XSignal &result[] // Hold Result ... ) { // // Free Result ... ArrayFree(result); ArrayResize(result, 0); // // Validate Args ... bool isPrimary = XTMIsPrimaryTrade(primary); if (!isPrimary) { return; } // XSignal gridSignals[]; XTMRetrieveGridTrades(gridSignals); int gridCount = ArraySize(gridSignals); if (gridCount == 0) { return; } // // Loop Through Grid Signals for Finding Primary Grid Trades ... for (int i = 0; i < gridCount; i++) { // XSignal signal = gridSignals[i]; bool isSignalContainsTicket = XTMIsSignalContainsTicketComment(primary.ticket, signal); if (!isSignalContainsTicket) { continue; } // if (signal.type != primary.type) { continue; } // ArrayResize( result, ArraySize(result) + 1); result[ArraySize(result) - 1] = signal; } } // // Retrieve Most Down Grid Trades of Primary ... XSignal XTMRetrieveLastGridTradesOfPrimary( XSignal &primary // Primary Trade which looking for it's Grid Trades ... ) { // XSignal result = {}; // XSignal gridSignals[]; XTMRetrieveGridTradesOfPrimary(primary, gridSignals); int gridCount = ArraySize(gridSignals); if (gridCount == 0) { return result; } // // Loop Throug a Primary Grids to Find Smallest Entry Price ... for (int i = 0; i < gridCount; i++) { // XSignal grid = gridSignals[i]; // if (!IsValid(result, xTMMagicNumber)) { result = grid; } else if (primary.type == X_SIGNAL_LONG) { if (grid.entry < result.entry) { result = grid; } } else if (primary.type == X_SIGNAL_SHORT) { if (grid.entry > result.entry) { result = grid; } } } // return result; } // // Draw TPSL Object ... void XTMDrawTPSL( XTPSL &model // an instance of XTPS structure ) { // // Validate Args ... if (!IsValid(model)) { return; } // string entryName = "T_" + EnumToString(model.type) + "_Entry_" + (string)model.entry; string slName = entryName + "_SL_" + (string)model.sl; string tpName = entryName + "_TP_" + (string)model.tp; datetime time1 = iTime(_Symbol, _Period, 2); datetime time2 = iTime(_Symbol, _Period, 0); color tpColor = xTDBullishArrowColor; color slColor = xTDBearishArrowColor; // // Draw Entry ... DrawTrendLine( 0, entryName, 0, time1, model.entry, time2, model.entry, clrYellow); // // Draw TP ... if (model.tp > 0) { // DrawTrendLine( 0, tpName, 0, time1, model.tp, time2, model.tp, tpColor); } // // Draw SL ... if (model.sl > 0) { // DrawTrendLine( 0, slName, 0, time1, model.sl, time2, model.sl, slColor); } } // // END Provided Functions ... //