/////////////////////////////////////////////////////// // // SaherElm IT Center XMMA Signalling 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 description "SaherElm XMMA Signalling Librarie" #property strict // // Includes Logger library ... #include "../Libraries/x-saherelm.log.lib.mq4" // // Includes Models library ... #include "../Libraries/x-saherelm.xmma.models.lib.mq4" // // Includes Drawing library ... #include "../Libraries/x-saherelm.draw.lib.mq4" // // START Global Requirement Functions ... // static int totalSignals = 0; static int totalLongSignals = 0; static int totalShortSignals = 0; // static double initialBalance = 0; // XMMAState GetXMMAState( const int bar_index, const int mLen, // Market Length ... const int fShift, // Fast Shift ... const int sShift // Shift Shift ... ) { // // Temp Result ... XMMAState result = {}; // // Fast ... double fast = iCustom( _Symbol, _Period, xmmaIndicatorName, // // Inputs ... mLen, // Market Length ... fShift, // Fast Shift ... sShift, // Slow Shift ... // 0, // Buffer Index ... bar_index ); result.fast = fast; // // FastPrev ... double fastPrev = iCustom( _Symbol, _Period, xmmaIndicatorName, // // Inputs ... mLen, // Market Length ... fShift, // Fast Shift ... sShift, // Slow Shift ... // 0, // Buffer Index ... bar_index + 1 ); result.fastPrev = fastPrev; // // Slow ... double slow = iCustom( _Symbol, _Period, xmmaIndicatorName, // // Inputs ... mLen, // Market Length ... fShift, // Fast Shift ... sShift, // Slow Shift ... // 1, // Buffer Index ... bar_index ); result.slow = slow; // // SlowPrev ... double slowPrev = iCustom( _Symbol, _Period, xmmaIndicatorName, // // Inputs ... mLen, // Market Length ... fShift, // Fast Shift ... sShift, // Slow Shift ... // 1, // Buffer Index ... bar_index + 1 ); result.slowPrev = slowPrev; // // Mid ... double mid = iCustom( _Symbol, _Period, xmmaIndicatorName, // // Inputs ... mLen, // Market Length ... fShift, // Fast Shift ... sShift, // Slow Shift ... // 2, // Buffer Index ... bar_index ); result.mid = mid; // // LongSL ... double longSL = iCustom( _Symbol, _Period, xmmaIndicatorName, // // Inputs ... mLen, // Market Length ... fShift, // Fast Shift ... sShift, // Slow Shift ... // 3, // Buffer Index ... bar_index ); result.longSL = longSL; // // ShortSL ... double shortSL = iCustom( _Symbol, _Period, xmmaIndicatorName, // // Inputs ... mLen, // Market Length ... fShift, // Fast Shift ... sShift, // Slow Shift ... // 4, // Buffer Index ... bar_index ); result.shortSL = shortSL; // // Do Calculations ... // // Find Cross Points ... // bool isCrossOver = fast >= slow && !( fastPrev >= slowPrev ); result.isCrossOver = isCrossOver; // bool isCrossUnder = fast <= slow && !( fastPrev <= slowPrev ); result.isCrossUnder = isCrossUnder; // // Find Trending ... // bool isTrendUp = fast > slow && fast > fastPrev && slow > slowPrev; result.isTrendUp = isTrendUp; // bool isTrendDown = fast < slow && fast < fastPrev && slow < slowPrev; result.isTrendDown = isTrendDown; // return result; } // // END Global Requirement Functions ... // // // START Signal Related Functions ... // // // Convert To XSignal Model ... XSignal OrderToSignal() { // // Temp Result ... XSignal result = {}; result.type = X_NONE; // // Here we can get some usefull info based on selected order ... double swap = OrderSwap(); double lots = OrderLots(); int ticket = OrderTicket(); double profit = OrderProfit(); double stopLoss = OrderStopLoss(); double openPrice = OrderOpenPrice(); datetime openTime = OrderOpenTime(); int magicNumber = OrderMagicNumber(); double takeProfit = OrderTakeProfit(); // // find order type ... bool isLongOrder = OrderType() == OP_BUY; // // Conver Position to Signal ... result.sl = stopLoss; result.tp = takeProfit; result.time = openTime; result.symbol = _Symbol; result.id = magicNumber; result.entryPrice = openPrice; result.type = isLongOrder ? X_LONG : X_SHORT; // return result; } // // Calculate Signal ... // in this function we calculate a signal exists in // specific bar or not ... XSignalRequest CalculateSignal( const int bar_index, // // Inputs ... const int mLen, // Market Length ... const int fShift, // Fast Shift ... const int sShift // Shift Shift ... ) { // // create temp result ... XSignalRequest result = {}; result.hasSignal = false; result.type = X_NONE; // XSignal signal = {}; // // Define Price Related Variables ... double tp = 0; double sl = 0; double price = 0; datetime time = 0; double priceGap = 0; color clr = clrNONE; string comment = ""; double closePrice = 0; // // START Capturing Signal ... // // // START Retrieve Statets ... // // Reading Oscillator State ... XMMAState xmmaState = GetXMMAState( bar_index, mLen, fShift, sShift ); // // END Retrieve Statets ... // // // START States Calculations ... // // // START PRICE Calculations ... // // // LONG Prices ... double longEntryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double longClosePrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); double longPriceGap = longClosePrice - longEntryPrice; // // SHORT Prices ... double shortEntryPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID); double shortClosePrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double shortPriceGap = shortEntryPrice - shortClosePrice; // // END PRICE Calculations ... // // // END States Calculations ... // // // START LONG Signals ... // bool hasLongSignal = false; // hasLongSignal = xmmaState.isCrossOver && xmmaState.isTrendUp && !xmmaState.isCrossUnder && !xmmaState.isTrendDown ; // // END LONG Signals ... // // // START SHORT Signals ... // bool hasShortSignal = false; // hasShortSignal = xmmaState.isCrossUnder && xmmaState.isTrendDown && !xmmaState.isCrossOver && !xmmaState.isTrendUp ; // // END SHORT Signals ... // // // Check Signal Exists regardless of Long or Short ... bool hasSignal = hasLongSignal || hasShortSignal; // // Prevent from Going forward if there is not a Signal ... if (!hasSignal) { return result; } // // Price ... price = hasLongSignal ? longEntryPrice : shortEntryPrice; // // Close Price ... closePrice = hasLongSignal ? longClosePrice : shortClosePrice; // // Price Gap ... priceGap = hasLongSignal ? longPriceGap : shortPriceGap; // // Calculate Time ... time = iTime( _Symbol, _Period, bar_index ); // // Set TP ... tp = hasLongSignal ? // // Long ... longClosePrice * (150 * _Point) : // // Short ... shortClosePrice * (150 * _Point) ; // // Set SL ... sl = hasLongSignal ? // // Long ... xmmaState.longSL : // // Short ... xmmaState.shortSL ; // // Normalize Prices ... price = NormalizeDouble(price, _Digits); sl = NormalizeDouble(sl, _Digits); tp = NormalizeDouble(tp, _Digits); // // Generate Signal Structure ... signal.type = hasLongSignal ? X_LONG : X_SHORT; signal.tp = tp; signal.sl = sl; signal.time = time; signal.symbol = _Symbol; signal.entryPrice = price; // // END Capturing Signal ... // // // Retrieve Signal Verifications ... bool isSignalVerified = true && ( hasLongSignal ? price > xmmaState.fast : true ) ; // GetSignalVerifications( // signal, // fOSCLength, // fOSCMultiplier, // sOSCLength, // sOSCMultiplier, // minPOSC, // minVOSC, // zDev, // zBkStep, // swingLoopback, // slThrsh, // flowMul, // markMul, // fastMul, // slowMul // ); // // Apply Verifications ... hasSignal = hasSignal && isSignalVerified; // result.hasSignal = hasSignal; if (hasSignal) { // // Count Signals ... totalSignals++; if (hasLongSignal) { totalLongSignals++; } else { totalShortSignals++; } // signal.id = totalSignals; // result.signal = signal; result.type = signal.type; } // return result; } // // 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; } // // Retrieve Signal Bar Index ... int GetSignalBarIndex(XSignal &signal) { // // Temp Result ... int result = -1; // // Retriev Signal Bar Index ... result = iBarShift( _Symbol, _Period, signal.time ); // return result; } // // Draw Signal Shapes on Chart ... bool DrawSignal( 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 = shortSignalColor; // isLongSignal ? shortSignalColor : longSignalColor; color tpColor = longSignalColor; // isLongSignal ? shortSignalColor : longSignalColor; // datetime time1 = iTime( _Symbol, _Period, bar_index + 1 ); // // Draw Signal SL ... if (signal.sl > 0) { // result = DrawTrendLine( chartID, slLineName, subWindowID, time1, signal.sl, signal.time, signal.sl, slColor, STYLE_SOLID, 2 ); } // // Draw Signal TP ... if (signal.tp > 0) { //s result = DrawTrendLine( chartID, tpLineName, subWindowID, time1, signal.tp, signal.time, signal.tp, tpColor, 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; } // // Trade on Specific Signal ... bool TradeSignal( XSignal &signal, // string prefix, // double volumePercent, // // Long ... const string longSignalLabel, const color longSignalColor, // // Short ... const string shortSignalLabel, const color shortSignalColor ) { // // Temp Result ... bool result = false; // if (initialBalance == 0) { initialBalance = AccountInfoDouble(ACCOUNT_BALANCE); } // double balance = AccountInfoDouble(ACCOUNT_BALANCE); int openPositions = CountOpenPositions(); double volume = (volumePercent * initialBalance); // openPositions == 0 ? // (volumePercent * balance) : // (volumePercent * initialBalance); // if ( signal.type != X_LONG && signal.type != X_SHORT ) { return result; } // bool hasLongSignal = signal.type == X_LONG; // // Order Operation ... int operation = hasLongSignal ? OP_BUY : OP_SELL; // // Detect Trade Color ... color clr = hasLongSignal ? longSignalColor : shortSignalColor; // // Generate Signal Comment ... string label = hasLongSignal ? longSignalLabel : shortSignalLabel; // // Generate Signal Comment ... string comment = StringConcatenate( prefix, "_", signal.id, "_", label ); // // Placing Order ... int orderTicket = OrderSend( _Symbol, operation, volume, signal.entryPrice, 3, signal.sl, signal.tp, comment, signal.id, 0, clr ); // // Draw Signal Shape if Order Opened Successfully ... if (orderTicket >= 0) { // // Here i must to Draw Signal Shapes ... DrawSignal( signal, 0, 0, 50, prefix, // Signal Tag ... longSignalLabel, // Long Signal Label ... longSignalColor, shortSignalLabel, // Short Signal Label ... shortSignalColor ); // result = true; } // return result; } // // END Signal Related Functions ... // // // START Orders Related Functions ... // // // 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; } // // Count Open Long Positions ... int CountOpenLongPositions() { // 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 && OrderType() == OP_BUY ) { result++; } } } // // Return Result ... return result; } // // Count Open Short Positions ... int CountOpenShortPositions() { // 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 && OrderType() == OP_SELL ) { result++; } } } // // Return Result ... return result; } // // Close All Open Trades ... void CloseAllTrades() { // // Loop through all Positions ... for (int i = OrdersTotal(); i >= 0; i--) { // // Check Order Selected or not ... if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { // // Check Order Symbol is same as Current Symbol ... if (OrderSymbol() == _Symbol) { // double lots = OrderLots(); int ticket = OrderTicket(); // // find order type ... bool isLongOrder = OrderType() == OP_BUY; // // find close price ... double closePrice = isLongOrder ? SymbolInfoDouble(_Symbol, SYMBOL_BID) : SymbolInfoDouble(_Symbol, SYMBOL_ASK); // // Since because of equity ... // we have to ckose allpositions ... bool isOrderClosed = OrderClose( ticket, lots, closePrice, clrYellow ); } } } } // // Close All Open Trades ... void CloseAllLongTrades() { // // Loop through all Positions ... for (int i = OrdersTotal(); i >= 0; i--) { // // Check Order Selected or not ... if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { // // Check Order Symbol is same as Current Symbol ... if (OrderSymbol() == _Symbol) { // double lots = OrderLots(); int ticket = OrderTicket(); // // find order type ... bool isLongOrder = OrderType() == OP_BUY; if (isLongOrder) { // // find close price ... double closePrice = isLongOrder ? SymbolInfoDouble(_Symbol, SYMBOL_BID) : SymbolInfoDouble(_Symbol, SYMBOL_ASK); // // Since because of equity ... // we have to ckose allpositions ... bool isOrderClosed = OrderClose( ticket, lots, closePrice, clrYellow ); } } } } } // // Close All Open Trades ... void CloseAllShortTrades() { // // Loop through all Positions ... for (int i = OrdersTotal(); i >= 0; i--) { // // Check Order Selected or not ... if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { // // Check Order Symbol is same as Current Symbol ... if (OrderSymbol() == _Symbol) { // double lots = OrderLots(); int ticket = OrderTicket(); // // find order type ... bool isLongOrder = OrderType() == OP_BUY; if (!isLongOrder) { // // find close price ... double closePrice = isLongOrder ? SymbolInfoDouble(_Symbol, SYMBOL_BID) : SymbolInfoDouble(_Symbol, SYMBOL_ASK); // // Since because of equity ... // we have to ckose allpositions ... bool isOrderClosed = OrderClose( ticket, lots, closePrice, clrYellow ); } } } } } // // END Orders Related Functions ... //