//+------------------------------------------------------------------+ //| SignalGrid.mqh | //| Copyright 2021, Nkondog Anselme Venceslas | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2021, Nkondog Anselme Venceslas" #property link "https://www.mql5.com" // Next line assumes this file is located in .../Frameworks/Extensions/someFolder #include "../../GridFramework.mqh" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CSignalGrid : public CSignalBase { private: protected: // member variables // Place any required member variables here int m_magic; double lastBuyOrderPrice; double lastSellOrderPrice; double openedBuyPositionPrice; double openedSellPositionPrice; public: // constructors // Add any required constructor arguments // e.g. CSignalXYZ(int periods, double multiplier) CSignalGrid() : CSignalBase() { Init(); } // Same constructor with symbol and timeframe added CSignalGrid(string symbol, ENUM_TIMEFRAMES timeframe) : CSignalBase(symbol, timeframe) { Init(); } ~CSignalGrid() { } // Include all arguments to match the constructor int Init(); public: // Add this line to override the same function from the parent class virtual void UpdateSignal(); virtual void setMmagic(int magic) {m_magic = magic;} virtual double getLastBuyOrderPrice() {return lastBuyOrderPrice;} virtual double getLastSellOrderPrice() {return lastSellOrderPrice;} virtual double getOpenedBuyPositionPrice() {return openedBuyPositionPrice;} virtual double getOpenedSellPositionPrice() {return openedSellPositionPrice;} }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int CSignalGrid::Init() { // Checks if init has been set to fail by any parent class already if(InitResult()!=INIT_SUCCEEDED) return(InitResult()); // Assign variables and do any other initialisation here return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CSignalGrid::UpdateSignal() { // Just gather data from the indicators and // decide on a trade direction // This is the trade decision logic //CSignalBase signal = new CSignalBase(); // Check the account balance equity for profit int pCountBuy = 0, pCountSell = 0, oCountBuy = 0, oCountSell = 0, totalBuy = 0, totalSell = 0, realTotalBuy = 0, realTotalSell = 0; int realOCountBuy = 0, realOCountSell = 0; ulong ticket; SetSignal(OFX_ENTRY_SIGNAL, OFX_SIGNAL_NONE); //If there're many positions and account balance is negative if(PositionsTotal() > 0) { //Count the opened positions by type int cntP = PositionsTotal(); for(int i = cntP-1; i>=0; i--) { ticket = PositionGetTicket(i); if(PositionSelectByTicket(ticket)) { if(PositionGetString(POSITION_SYMBOL)==mSymbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY && PositionGetInteger(POSITION_MAGIC)==m_magic) { openedBuyPositionPrice = PositionGetDouble(POSITION_PRICE_OPEN); pCountBuy += 1; } if(PositionGetString(POSITION_SYMBOL)==mSymbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL && PositionGetInteger(POSITION_MAGIC)==m_magic) { openedSellPositionPrice = PositionGetDouble(POSITION_PRICE_OPEN); pCountSell += 1; } } else { Print(GetLastError()); } } } //Count the orders by type int cntO = OrdersTotal(); for(int i = cntO-1; i>=0; i--) { ticket = OrderGetTicket(i); if(OrderSelect(ticket)) { if(OrderGetString(ORDER_SYMBOL)==mSymbol && OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_BUY_STOP && OrderGetInteger(ORDER_MAGIC)==m_magic) { oCountBuy += 1; lastBuyOrderPrice = OrderGetDouble(ORDER_PRICE_OPEN); } Print("ORDER_SYMBOL ", OrderGetString(ORDER_SYMBOL), " Real symbol ", mSymbol, " ORDER_TYPE ", OrderGetInteger(ORDER_TYPE), " Real type ", ORDER_TYPE_SELL_STOP, " Magic ", OrderGetInteger(ORDER_MAGIC), " Real magic ", m_magic); if(OrderGetString(ORDER_SYMBOL)==mSymbol && OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_SELL_STOP && OrderGetInteger(ORDER_MAGIC)==m_magic) { oCountSell += 1; lastSellOrderPrice = OrderGetDouble(ORDER_PRICE_OPEN); } } else { Print("Last error code ", GetLastError()); } } double floatingProfitPercent = ((AccountInfoDouble(ACCOUNT_EQUITY) - AccountInfoDouble(ACCOUNT_BALANCE))*100)/AccountInfoDouble(ACCOUNT_BALANCE); // Check if profit is at least the mMaxRiskPerTrade //The number of buy pending order should be twice the opened sell positions; and vice versa realOCountBuy = pCountSell+1; realOCountSell = pCountBuy+1; totalBuy = pCountBuy+oCountBuy; totalSell = pCountSell+oCountSell; realTotalBuy = pCountSell+1; realTotalSell = pCountBuy+1; Print("Signal conditions ........................................................................"); if(OrdersTotal() == 0 && PositionsTotal() == 0) { SetSignal(OFX_ENTRY_SIGNAL, OFX_SIGNAL_BOTH); Print("1 - Open both position"); } else { //If there's only one pending order left, close it. if(OrdersTotal() >= 1 && PositionsTotal() == 0) { SetSignal(OFX_EXIT_SIGNAL, OFX_SIGNAL_ALL); Print("2 - Exit if no opened position"); } else { //When there are multiple positions, check is the account is making enough profit if(floatingProfitPercent > mMaxRiskPerTrade) { SetSignal(OFX_EXIT_SIGNAL, OFX_SIGNAL_ALL); Print("3 - Exit on profit target"); } else { Print("realTotalSell ", realTotalSell, " > ", " totalSell ", totalSell," && ", " pCountBuy ",pCountBuy," > 0"); if(realTotalSell > totalSell && pCountBuy > 0) { SetSignal(OFX_ENTRY_SIGNAL, OFX_SIGNAL_SELL); Print("4 - Sell order (", oCountSell, ") is less than it should be (", realOCountSell, ")"); } else { if(realTotalBuy > totalBuy && pCountSell > 0) { SetSignal(OFX_ENTRY_SIGNAL, OFX_SIGNAL_BUY); //mEntrySignals[0].SetSignal(OFX_ENTRY_SIGNAL, OFX_SIGNAL_BUY); Print("5 - Buy order (", oCountBuy, ") is less than it should be (", realOCountBuy, ")"); } } } } } } //+------------------------------------------------------------------+