/////////////////////////////////////////////////////// // // SaherElm IT Center MQL4 Signal Draw Global Library // --------------------------------------------------- // saherelm useful tools and definitions ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://www.saherelm.ir" #property version "1.00" #property strict // // Includes Logger library ... #include "../Libraries/x-saherelm.log.lib.mq4" // // Includes Models library ... #include "../Libraries/x-saherelm.models.lib.mq4" // // Includes Drawing library ... #include "../Libraries/x-saherelm.draw.lib.mq4" // // Start Signal Functions ... // // // Generate a Unique ID for Signal ... string GenerateSignalTAG( const XSignal &signal, const string tag = "", const string longSignalLabel = "", const string shortSignalLabel = "" ) { // // Generate Propper Label for Signal ... string label = signal.type == X_LONG ? longSignalLabel : signal.type == X_SHORT ? shortSignalLabel : "UN_KNOWN"; // // Generate Unique String Identifier for Signal ... string result = tag + "_[ID:" + IntegerToString(signal.id) + "]" + "_[" + label + "]" + "_[" + signal.symbol + "]" + "_[Time:" + TimeToStr(signal.time) + "]" + "_[TP:" + DoubleToString(signal.tp) + "]" + "_[SL:" + DoubleToString(signal.sl) + "]"; // return result; } // // Logging a Signal ... void LogSignal( const XSignal &signal, const string tag = "", const string longSignalLabel = "", const string shortSignalLabel = "" ) { // // Generate Message ... string signalMessage = GenerateSignalTAG( signal, tag, longSignalLabel, shortSignalLabel ); // LogMessage(signalMessage); } // // Retrieve Price Action Candlestick Type ... double GetPCandleType(const int bar_index) { // double result = iCustom( _Symbol, _Period, pcrtIndicatorName, 0, bar_index ); // return result; } // // Retrieve OSC Snapshot State ... XOSCState GetOSCState(const int bar_index) { // // Temp Result ... XOSCState result = {}; // // Start Extract Data from Oscillator ... // // // Fast OSC ... double fastOSC = iCustom( _Symbol, _Period, oscIndicatorName, fastOSCLength, fastOSCMultiplier, slowOSCLength, slowOSCMultiplier, 0, // Fast OSC Buffer Index ... bar_index ); result.fastOSC = fastOSC; // // Prev FastOSC ... double fastOSCPrev = iCustom( _Symbol, _Period, oscIndicatorName, fastOSCLength, fastOSCMultiplier, slowOSCLength, slowOSCMultiplier, 0, // Fast OSC Buffer Index ... bar_index + 1 ); result.fastOSCPrev = fastOSCPrev; // // Slow OSC ... double slowOSC = iCustom( _Symbol, _Period, oscIndicatorName, fastOSCLength, fastOSCMultiplier, slowOSCLength, slowOSCMultiplier, 1, // Slow OSC Buffer Index ... bar_index ); result.slowOSC = slowOSC; // // Prev Slow OSC ... double slowOSCPrev = iCustom( _Symbol, _Period, oscIndicatorName, fastOSCLength, fastOSCMultiplier, slowOSCLength, slowOSCMultiplier, 1, // Slow OSC Buffer Index ... bar_index + 1 ); result.slowOSCPrev = slowOSCPrev; // // Power OSC ... double powerOSC = iCustom( _Symbol, _Period, oscIndicatorName, fastOSCLength, fastOSCMultiplier, slowOSCLength, slowOSCMultiplier, 2, // Power OSC Buffer Index ... bar_index ); result.powerOSC = powerOSC; // double powerOSCPrev = iCustom( _Symbol, _Period, oscIndicatorName, fastOSCLength, fastOSCMultiplier, slowOSCLength, slowOSCMultiplier, 2, // Power OSC Buffer Index ... bar_index + 1 ); result.powerOSCPrev = powerOSCPrev; // // Var OSC ... double varOSC = iCustom( _Symbol, _Period, oscIndicatorName, fastOSCLength, fastOSCMultiplier, slowOSCLength, slowOSCMultiplier, 3, // Var OSC Buffer Index ... bar_index ); result.varOSC = varOSC; // double varOSCPrev = iCustom( _Symbol, _Period, oscIndicatorName, fastOSCLength, fastOSCMultiplier, slowOSCLength, slowOSCMultiplier, 3, // Var OSC Buffer Index ... bar_index + 1 ); result.varOSCPrev = varOSCPrev; // // Tan FS OSC ... double tanFSOSC = iCustom( _Symbol, _Period, oscIndicatorName, fastOSCLength, fastOSCMultiplier, slowOSCLength, slowOSCMultiplier, 4, // Tan F/S OSC Buffer Index ... bar_index ); result.tanFSOSC = tanFSOSC; // // End Extract Data from Oscillator ... // // return result; } // // Retrieve Ma Snapshot State ... XMaState GetMaState( const int bar_index, int fastMaPeriod = 20, ENUM_MA_METHOD fastMaMethod = MODE_EMA, ENUM_APPLIED_PRICE fastMaAppliedPrice = PRICE_CLOSE, int slowMaPeriod = 50, ENUM_MA_METHOD slowMaMethod = MODE_EMA, ENUM_APPLIED_PRICE slowMaAppliedPrice = PRICE_CLOSE ) { // XMaState result = {}; // double fastMa = iCustom( _Symbol, _Period, maIndicatorName, fastMaPeriod, fastMaMethod, fastMaAppliedPrice, slowMaPeriod, slowMaMethod, slowMaAppliedPrice, 0, bar_index ); result.fastMa = fastMa; // double fastMaPrev = iCustom( _Symbol, _Period, maIndicatorName, fastMaPeriod, fastMaMethod, fastMaAppliedPrice, slowMaPeriod, slowMaMethod, slowMaAppliedPrice, 0, bar_index + 1 ); result.fastMaPrev = fastMaPrev; // double slowMa = iCustom( _Symbol, _Period, maIndicatorName, fastMaPeriod, fastMaMethod, fastMaAppliedPrice, slowMaPeriod, slowMaMethod, slowMaAppliedPrice, 1, bar_index ); result.slowMa = slowMa; // double slowMaPrev = iCustom( _Symbol, _Period, maIndicatorName, fastMaPeriod, fastMaMethod, fastMaAppliedPrice, slowMaPeriod, slowMaMethod, slowMaAppliedPrice, 1, bar_index + 1 ); result.slowMaPrev = slowMaPrev; // Print(fastMa, slowMa, fastMaPrev, slowMaPrev); // return result; } // // Retrieve MACD info ... XMACDState GetMACDState() { // XMACDState result = {}; // // TODO: Complete this later ... // return result; } // // Check OSC Has Signal ... // default Method ... XSignalInfo OSCHasSignal( const XOSCState &oscState, const double &minimumSignalPower, const double &minimumVarPower ) { // // Genrate Temp Result ... XSignalInfo result = {}; // bool isCrossedOver = oscState.fastOSC > oscState.slowOSC && !(oscState.fastOSCPrev > oscState.slowOSCPrev); bool hasLongSignal = isCrossedOver && oscState.powerOSC >= minimumSignalPower; result.hasLongSignal = hasLongSignal; // bool isCrossedUnder = oscState.fastOSC < oscState.slowOSC && !(oscState.fastOSCPrev < oscState.slowOSCPrev); bool hasShortSignal = isCrossedUnder && oscState.powerOSC >= minimumSignalPower; result.hasShortSignal = hasShortSignal; // bool hasSignal = hasLongSignal || hasShortSignal; result.hasSignal = hasSignal; // return result; } // // Check OSC Has Signal ... // Method 1 ... XSignalInfo OSCHasSignal_1( const XOSCState &oscState, const double &minimumSignalPower, const double &minimumVarPower ) { // static bool canSignalLong = true; static bool canSignalShort = true; // // Genrate Temp Result ... XSignalInfo result = {}; //return result; // // bool hasLongSignal = false; bool isCrossedOver = oscState.fastOSC > oscState.slowOSC && !(oscState.fastOSCPrev > oscState.slowOSCPrev); bool hasLongSignal = isCrossedOver && oscState.powerOSC >= minimumSignalPower && oscState.varOSC >= minimumVarPower; result.hasLongSignal = hasLongSignal; // if (hasLongSignal) { // canSignalLong = false; // } // // bool hasShortSignal = false; bool isCrossedUnder = oscState.fastOSC < oscState.slowOSC && !(oscState.fastOSCPrev < oscState.slowOSCPrev); bool hasShortSignal = isCrossedUnder && oscState.powerOSC >= minimumSignalPower && oscState.varOSC >= minimumVarPower; result.hasShortSignal = hasShortSignal; // if (hasShortSignal) { // canSignalShort = false; // } // bool hasSignal = hasLongSignal || hasShortSignal; result.hasSignal = hasSignal; // // Fix can Signal Long ... //if (oscState.fastOSC >= 0 && !canSignalLong) { // canSignalLong = true; //} // // Fix can Signal Short ... //if (oscState.fastOSC <= 1 && !canSignalShort) { // canSignalShort = true; //} // return result; } // // Check OSC Has Signal ... // Method 2 ... XSignalInfo OSCHasSignal_2( const XOSCState &oscState, const int &bar_index ) { // static bool canSignalLong = true; static bool canSignalShort = true; // // Genrate Temp Result ... XSignalInfo result = {}; //return result; // // bool hasLongSignal = false; bool isCrossedOver = oscState.fastOSC > oscState.slowOSC && !(oscState.fastOSCPrev > oscState.slowOSCPrev); // // Get Prev Price Action Candle Type ... int pCandleType = (int) GetPCandleType(bar_index + 1); bool hasLongSignal = isCrossedOver && oscState.slowOSC > 0.5 && oscState.varOSC > 0; // && oscState.powerOSC >= 0.006 // && oscState.powerOSC - oscState.powerOSCPrev > 0 // && oscState.tanFSOSC >= 0.06 // && ( // pCandleType == X_CT_HAMMER || // pCandleType == X_CT_BULLISH_BELT || // pCandleType == X_CT_MORNING_STAR || // pCandleType == X_CT_BULLISH_KICKER || // pCandleType == X_CT_BULLISH_HARAMI || // pCandleType == X_CT_INVERTED_HAMMER || // pCandleType == X_CT_BULLISH_ENGULFING || // pCandleType == 0 // ) result.hasLongSignal = hasLongSignal; if (hasLongSignal) { // // Print("Tan: " + oscState.tanFSOSC); } // if (hasLongSignal) { // canSignalLong = false; // } // // bool hasShortSignal = false; bool isCrossedUnder = oscState.fastOSC < oscState.slowOSC && !(oscState.fastOSCPrev < oscState.slowOSCPrev); bool hasShortSignal = false; result.hasShortSignal = hasShortSignal; // if (hasShortSignal) { // canSignalShort = false; // } // bool hasSignal = hasLongSignal || hasShortSignal; result.hasSignal = hasSignal; // // Fix can Signal Long ... //if (oscState.fastOSC >= 0 && !canSignalLong) { // canSignalLong = true; //} // // Fix can Signal Short ... //if (oscState.fastOSC <= 1 && !canSignalShort) { // canSignalShort = true; //} // return result; } // // Check Ma Has Signal ... XSignalInfo MaHasSignal( const XMaState &maState, const int &bar_index ) { // XSignalInfo result = {}; result.hasSignal = false; // // Long ... bool isFastCrossOverSlow = maState.fastMa > maState.slowMa && !(maState.fastMaPrev > maState.slowMaPrev); bool hasLongSignal = isFastCrossOverSlow; result.hasLongSignal = hasLongSignal; // // Short ... bool isFastCrossUnderSlow = maState.fastMa < maState.slowMa && !(maState.fastMaPrev < maState.slowMaPrev); bool hasShortSignal = isFastCrossUnderSlow; result.hasShortSignal = hasShortSignal; // bool hasSignal = hasLongSignal || hasShortSignal; result.hasSignal = hasSignal; // return result; } // // Reading Swing SL ... XSLInfo GetSwngSL(const int &bar_index) { // // Temp result ... XSLInfo result = {}; // // Start Reading SL ... // // // Long SL ... double longSL = iCustom( _Symbol, _Period, slIndicatorName, slLoopback, // SL IND Inputs ... slThrshold, // SL IND Inputs ... 0, // Long SL Buffer Index ... bar_index ); longSL = NormalizeDouble(longSL, _Digits); result.longSL = longSL; // // Short SL ... double shortSL = iCustom( _Symbol, _Period, slIndicatorName, slLoopback, // SL IND Inputs ... slThrshold, // SL IND Inputs ... 1, // Short SL Buffer Index ... bar_index ); shortSL = NormalizeDouble(shortSL, _Digits); result.shortSL = shortSL; // // End Reading SL ... // // return result; } // // Reading TP based on SwingSL ... XTPInfo GetTP(const int &bar_index) { // // Temp result ... XTPInfo result = {}; // // Start Reading TP ... // // // Long TP ... double longTP = iCustom( _Symbol, _Period, tpIndicatorName, slLoopback, // TP IND Inputs ... slThrshold, // SL IND Inputs ... riskToRewardRatio, // TP IND Inputs ... 0, // Long TP Buffer Index ... bar_index ); longTP = NormalizeDouble(longTP, _Digits); result.longTP = longTP; // // Short TP ... double shortTP = iCustom( _Symbol, _Period, tpIndicatorName, slLoopback, // TP IND Inputs ... slThrshold, // SL IND Inputs ... riskToRewardRatio, // TP IND Inputs ... 1, // Short TP Buffer Index ... bar_index ); shortTP = NormalizeDouble(shortTP, _Digits); result.shortTP = shortTP; // // End Reading TP ... // // return result; } // // Calculate Signal ... // Default Method ... XSignalRequest CalculateOSCSignal( const int bar_index, const double minimumSignalPower = 0.03, const double minimumVarPower = 0.01 ) { // XSignalRequest result = {}; result.hasSignal = false; result.type = X_NONE; // // Reading Oscillator State ... XOSCState oscState = GetOSCState(bar_index); // // Generate Signals From OSC ... XSignalInfo signalInfo = OSCHasSignal( oscState, minimumSignalPower, minimumVarPower ); // result.hasSignal = signalInfo.hasSignal; if (!signalInfo.hasSignal) { return result; } // // increase signal count ... signalCount++; // // increase long/short signal count ... if (signalInfo.hasLongSignal) { longSignalCount++; } else if (signalInfo.hasShortSignal) { shortSignalCount++; } // // Retrieve Open Price ... double openPrice = iOpen(_Symbol, _Period, bar_index); openPrice = NormalizeDouble(openPrice, _Digits); // // Signal Entry Price ... double signalEntryPrice = signalInfo.hasLongSignal ? Ask : Bid; signalEntryPrice = NormalizeDouble(signalEntryPrice, _Digits); // // Signal Time ... datetime signalTime = iTime(_Symbol, _Period, bar_index); // // Signal Type ... X_SIGNAL_TYPE signalType = signalInfo.hasLongSignal ? X_LONG : X_SHORT; result.type = signalType; // // Reading SL ... XSLInfo slInfo = GetSwngSL(bar_index); // // Reading TP ... XTPInfo tpInfo = GetTP(bar_index); // // Generate Signal SL ... double signalSL = signalInfo.hasLongSignal ? slInfo.longSL : slInfo.shortSL; // // Generate Signal TP ... double signalTP = signalInfo.hasLongSignal ? tpInfo.longTP : tpInfo.shortTP; // // Generate XSignal Instance based on received Data ... XSignal signal = {}; signal.id = signalCount; signal.sl = signalSL; signal.tp = signalTP; signal.time = signalTime; signal.type = signalType; signal.symbol = _Symbol; // signal.openPrice = openPrice; // signal.entryPrice = signalEntryPrice; // result.signal = signal; // return result; } // // Calculate Signal ... // Method 1 ... XSignalRequest CalculateSignal_1( const int bar_index, const double minimumSignalPower = 0.03, const double minimumVarPower = 0.01 ) { // XSignalRequest result = {}; result.hasSignal = false; result.type = X_NONE; // // Reading Oscillator State ... XOSCState oscState = GetOSCState(bar_index); // // Retrieve Price Action Theory based Candlestick Type ... int pCandleType = (int) GetPCandleType(bar_index); // // Generate Signals From OSC ... XSignalInfo signalInfo = OSCHasSignal_1( oscState, minimumSignalPower, minimumVarPower ); // result.hasSignal = signalInfo.hasSignal; if (!signalInfo.hasSignal) { return result; } // // Get Price Action Candlestick Verification on Long Signals ... if (signalInfo.hasLongSignal) { // // Check current Candle Type based on Price Action Theory ... if (pCandleType == X_P_CT_BEARISH) { // result.hasSignal = false; return result; } else if (pCandleType == X_P_CT_NEUTRAL) { // // Here we must loop through back bar indexes until find a // candle which no NEUTRAL ... int barCounter = bar_index + 1; int prevUnNeutralPCandleType = -1; while( barCounter <= Bars && prevUnNeutralPCandleType == -1 ) { // int cPCType = (int) GetPCandleType(barCounter); if (cPCType != X_P_CT_NEUTRAL) { prevUnNeutralPCandleType = cPCType; } else { barCounter++; } } // result.hasSignal = false; if (prevUnNeutralPCandleType != X_P_CT_BULLISH) { return result; } // result.hasSignal = true; } } // // Get Price Action Candlestick Verification on Short Signals ... if (signalInfo.hasShortSignal) { // // Check current Candle Type based on Price Action Theory ... if (pCandleType == X_P_CT_BULLISH) { // result.hasSignal = false; return result; } else if (pCandleType == X_P_CT_NEUTRAL) { // // Here we must loop through back bar indexes until find a // candle which no NEUTRAL ... int barCounter = bar_index + 1; int prevUnNeutralPCandleType = -1; while( barCounter <= Bars && prevUnNeutralPCandleType == -1 ) { // int cPCType = (int) GetPCandleType(barCounter); if (cPCType != X_P_CT_NEUTRAL) { prevUnNeutralPCandleType = cPCType; } else { barCounter++; } } // result.hasSignal = false; if (prevUnNeutralPCandleType != X_P_CT_BEARISH) { return result; } // result.hasSignal = true; } } // // increase signal count ... signalCount++; // // increase long/short signal count ... if (signalInfo.hasLongSignal) { longSignalCount++; } else if (signalInfo.hasShortSignal) { shortSignalCount++; } // // Retrieve Open Price ... double openPrice = iOpen(_Symbol, _Period, bar_index); openPrice = NormalizeDouble(openPrice, _Digits); // // Signal Entry Price ... RefreshRates(); double signalEntryPrice = signalInfo.hasLongSignal ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID); // signalInfo.hasLongSignal ? SymbolInfoDouble(_Symbol, SYMBOL_ASK) : SymbolInfoDouble(_Symbol, SYMBOL_BID); signalEntryPrice = NormalizeDouble(signalEntryPrice, _Digits); // // Signal Time ... datetime signalTime = iTime(_Symbol, _Period, bar_index); // // Signal Type ... X_SIGNAL_TYPE signalType = signalInfo.hasLongSignal ? X_LONG : X_SHORT; result.type = signalType; // // Reading SL ... XSLInfo slInfo = GetSwngSL(bar_index); // // Reading TP ... XTPInfo tpInfo = GetTP(bar_index); // // Generate Signal SL ... double signalSL = signalInfo.hasLongSignal ? slInfo.longSL : slInfo.shortSL; // // Generate Signal TP ... double signalTP = signalInfo.hasLongSignal ? tpInfo.longTP : slInfo.longSL; // tpInfo.shortTP; // // Generate XSignal Instance based on received Data ... XSignal signal = {}; signal.id = signalCount; signal.sl = signalSL; signal.tp = signalTP; signal.time = signalTime; signal.type = signalType; signal.symbol = _Symbol; // signal.openPrice = openPrice; // signal.entryPrice = signalEntryPrice; // result.signal = signal; // return result; } // // Calculate Signal ... // Method 2 ... XSignalRequest CalculateSignal_2(const int bar_index) { // XSignalRequest result = {}; result.hasSignal = false; result.type = X_NONE; // // Reading Oscillator State ... XOSCState oscState = GetOSCState(bar_index); // // Generate Signals From OSC ... XSignalInfo signalInfo = OSCHasSignal_2( oscState, bar_index ); // result.hasSignal = signalInfo.hasSignal; if (!signalInfo.hasSignal) { return result; } // // increase signal count ... signalCount++; // // increase long/short signal count ... if (signalInfo.hasLongSignal) { longSignalCount++; } else if (signalInfo.hasShortSignal) { shortSignalCount++; } // // Signal Time ... datetime signalTime = iTime(_Symbol, _Period, bar_index); // // Signal Type ... X_SIGNAL_TYPE signalType = signalInfo.hasLongSignal ? X_LONG : X_SHORT; result.type = signalType; // // Reading SL ... XSLInfo slInfo = GetSwngSL(bar_index); // // Reading TP ... XTPInfo tpInfo = GetTP(bar_index); // // Generate Signal SL ... double signalSL = signalInfo.hasLongSignal ? slInfo.longSL : slInfo.shortSL; // // Generate Signal TP ... double signalTP = signalInfo.hasLongSignal ? tpInfo.longTP : tpInfo.shortTP; // // Generate XSignal Instance based on received Data ... XSignal signal = {}; signal.id = signalCount; signal.sl = signalSL; signal.tp = signalTP; signal.time = signalTime; signal.type = signalType; signal.symbol = _Symbol; // result.signal = signal; // return result; } // // Calculate Signal ... // Using Ma ... XSignalRequest CalculateMaSignal(const int bar_index) { // XSignalRequest result = {}; result.hasSignal = false; result.type = X_NONE; // // Reading Moving Average State ... XMaState maState = GetMaState(bar_index); // // Generate Signals From OSC ... XSignalInfo signalInfo = MaHasSignal( maState, bar_index ); Print("Ma HasSignal: ", signalInfo.hasSignal); // result.hasSignal = signalInfo.hasSignal; if (!signalInfo.hasSignal) { return result; } // // increase signal count ... signalCount++; // // increase long/short signal count ... if (signalInfo.hasLongSignal) { longSignalCount++; } else if (signalInfo.hasShortSignal) { shortSignalCount++; } // // Signal Time ... datetime signalTime = iTime(_Symbol, _Period, bar_index); // // Signal Type ... X_SIGNAL_TYPE signalType = signalInfo.hasLongSignal ? X_LONG : X_SHORT; result.type = signalType; // // Reading SL ... XSLInfo slInfo = GetSwngSL(bar_index); // // Reading TP ... XTPInfo tpInfo = GetTP(bar_index); // // Generate Signal SL ... double signalSL = signalInfo.hasLongSignal ? slInfo.longSL : slInfo.shortSL; // // Generate Signal TP ... double signalTP = signalInfo.hasLongSignal ? tpInfo.longTP : tpInfo.shortTP; // // Generate XSignal Instance based on received Data ... XSignal signal = {}; signal.id = signalCount; signal.sl = signalSL; signal.tp = signalTP; signal.time = signalTime; signal.type = signalType; signal.symbol = _Symbol; // result.signal = signal; // return result; } // // Count Open Positions ... int CountOpenPositions() { // int result = 0; // // Loop through Orders ... for (int i = 0; i < OrdersTotal(); i++) { // // Select indexed Order ... if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { // // Check Order ... if (OrderSymbol() == _Symbol) { result++; } } } // // Return Result ... return result; } // // Handle Trading On Signals ... void TradeOnSignal( const XSignal &signal, double tradeVolume = 0.1, string signalTag = "X-Signal", string longSignalLabel = "X-Long", color longSignalColor = clrLime, string shortSignalLabel = "X-Short", color shortSignalColor = clrRed ) { // // Start Genearting required data ... // // // START implementing Money Management ... // if (tradeCount == 0) { // initialBalance = AccountBalance(); // string msg = StringConcatenate("Initial Account Balance: ", initialBalance); LogMessage(msg); } // // Retrieve current Account balance double currentBalance = AccountBalance(); if (currentBalance < initialBalance / 2) { // string msg = StringConcatenate("Account Balance less than minimum allowed, trading off ..."); LogMessage(msg); // return; } // // END implementing Money Management ... // // // Detect Trade is Long or Short ... bool isLongSignal = signal.type == X_LONG; // // Generate Trade Comment ... string tradeComment = GenerateSignalTAG( signal, signalTag, longSignalLabel, shortSignalLabel ); // // Detect Trade Operation ... int tradeOperation = isLongSignal ? OP_BUY : OP_SELL; // // Detect Trade Color ... color tradeColor = isLongSignal ? longSignalColor : shortSignalColor; // // End Genearting required data ... // // double price = 0; double closePrice = 0; double priceGap = 0; double tp = 0; double sl = 0; // RefreshRates(); // // Calculating Open, SL, TP for Positions ... if (isLongSignal) { // // Long Positions ... // // Prices ... price = SymbolInfoDouble(_Symbol, SYMBOL_ASK); closePrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); // priceGap = closePrice - price; // // SL ... if (signal.sl > 0) { sl = signal.sl + priceGap; } // // TP ... if (signal.tp > 0) { tp = signal.tp - priceGap; } } else { // // Short Positions ... // // Prices ... price = SymbolInfoDouble(_Symbol, SYMBOL_BID); closePrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK); // // SL ... if (signal.sl > 0) { sl = signal.sl - priceGap; } // // TP ... if (signal.tp > 0) { tp = signal.tp + priceGap; } } // // Ignore last TP and SL Calculation and Use Default ... // sl = signal.sl; // tp = signal.tp; // // Normalize Prices ... price = NormalizeDouble(price, _Digits); sl = NormalizeDouble(sl, _Digits); tp = NormalizeDouble(tp, _Digits); // // Define Trade Variables ... double slGap = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point; // // Price Check ... if (price == 0) { return; } // // Prevent Open Trading when price doesn't fill slGap ...' if (signal.sl > 0 && signal.sl < slGap) { return; } // // Prevent Open Trading when price doesn't fill slGap ...' if (signal.tp > 0 && signal.tp < slGap) { return; } // // Fix Signal SL and Price Same issue ... if (price == sl || MathAbs(price - sl) <= slGap) { // // string msg = StringConcatenate("id: ", signal.id , ", Price: ", price, ", sl: ", sl); // LogMessage(msg); // return; } // // Placing Order ... int orderTicket = OrderSend( signal.symbol, tradeOperation, tradeVolume, price, 3, sl, tp, tradeComment, (int)signal.id, 0, tradeColor ); // if (orderTicket >= 0) { tradeCount++; } } // // Draw Signal Shapes on Chart ... bool DrawSignalShape( const XSignal &signal, long chartID = 0, int subWindowID = 0, const double positionThresholdFactor = 10, string signalTag = "X-Signal", string longSignalLabel = "X-Long", color longSignalColor = clrAqua, string shortSignalLabel = "X-Short", color shortSignalColor = clrFuchsia ) { // // Generate isLongSignal Var ... bool isLongSignal = signal.type == X_LONG; // // Signal Bar Index ... int bar_index = iBarShift( _Symbol, _Period, signal.time ); // // START Draw Signal Arrow ... // // // Arrow Shape Name ... string arrowName = StringConcatenate(signalTag, "_Arrow_", signal.id); // // Arrow Price ... double arrowPrice = 0; if (isLongSignal) { // arrowPrice = iLow( _Symbol, _Period, bar_index ); // arrowPrice = arrowPrice - (positionThresholdFactor * _Point); } else { // arrowPrice = iHigh( _Symbol, _Period, bar_index ); // arrowPrice = arrowPrice + (positionThresholdFactor * _Point); } // // Arrow Code ... uchar arrowCode = isLongSignal ? SYMBOL_ARROWUP : SYMBOL_ARROWDOWN; // // Arrow Anchor Point ... ENUM_ARROW_ANCHOR arrowAnchorPoint = isLongSignal ? ANCHOR_BOTTOM : ANCHOR_TOP; // // Arrow Color ... color arrowColor = isLongSignal ? longSignalColor : shortSignalColor; // // Draw Signal Arrow Shape ... bool result = DrawArrow( chartID, arrowName, subWindowID, signal.time, arrowPrice, arrowCode, arrowAnchorPoint, arrowColor, STYLE_SOLID, 3, false, false, false, 0 ); // // END Draw Signal Arrow ... // // // START Draw Signal SL/TP ... // string slLineName = StringConcatenate(signalTag, "_SL_", signal.id); string tpLineName = StringConcatenate(signalTag, "_TP_", signal.id); // color slColor = isLongSignal ? shortSignalColor : longSignalColor; // datetime time1 = iTime( _Symbol, _Period, bar_index + 1 ); // // Draw Signal SL ... result = DrawTrendLine( chartID, slLineName, subWindowID, time1, signal.sl, signal.time, signal.sl, slColor, STYLE_SOLID, 2 ); // // Draw Signal TP ... result = DrawTrendLine( chartID, tpLineName, subWindowID, time1, signal.tp, signal.time, signal.tp, arrowColor, STYLE_SOLID, 2 ); // // END Draw Signal SL/TP ... // // // Start Draw Signal Label ... // // string labelName = StringConcatenate(signalTag, "_Label_", signal.id); // double labelPrice = isLongSignal ? arrowPrice - (positionThresholdFactor * _Point) : arrowPrice + (positionThresholdFactor * _Point); // string labelText = isLongSignal ? longSignalLabel : shortSignalLabel; // result = DrawText( chartID, labelName, subWindowID, signal.time, labelPrice, labelText, "Arial", 10, arrowColor, 0, ANCHOR_CENTER ); // // End Draw Signal Label ... // // return result; } // // End Signal Functions ... //