diff --git a/.gitignore b/.gitignore index 1af6b03..b294858 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,9 @@ Thumbs.db *.mov *.wmv +# VS folder + .vscode/ + # MT4/MT5 files Files/ @@ -62,3 +65,17 @@ Services/ Shared Projets/ *.dat +Experts/Advisors/ +Experts/Examples/ +Include/A* +Include/C* +Include/E* +Include/F* +Include/G* +Include/I +Include/M* +Include/O* +Include/S* +Include/T* +Include/W* +Include/V* diff --git a/Experts/Nkanven/Framework EA/Grid/GridEA.ex5 b/Experts/Nkanven/Framework EA/Grid/GridEA.ex5 index 68f797d..8f29a4e 100644 Binary files a/Experts/Nkanven/Framework EA/Grid/GridEA.ex5 and b/Experts/Nkanven/Framework EA/Grid/GridEA.ex5 differ diff --git a/Experts/Nkanven/Framework EA/Grid/GridEA.mq5 b/Experts/Nkanven/Framework EA/Grid/GridEA.mq5 index 922913b..b55e18d 100644 --- a/Experts/Nkanven/Framework EA/Grid/GridEA.mq5 +++ b/Experts/Nkanven/Framework EA/Grid/GridEA.mq5 @@ -5,7 +5,7 @@ //+------------------------------------------------------------------+ #property copyright "Copyright 2021, Nkondog Anselme Venceslas" #property link "https://www.mql5.com" -#property version "1.00" +#property version "1.01" #include @@ -19,7 +19,7 @@ input string Comment_strategy="=========="; //Entry And //Add in this section the parameters for the indicators used in your entry and exit //General input parameters -input string Comment_0="=========="; //Risk Management Settings +input string Comment_0="=========="; //Risk Management Settings input ENUM_RISK_DEFAULT_SIZE InpRiskDefaultSize=RISK_DEFAULT_AUTO; //Position Size Mode input double InpDefaultLotSize=1; //Position Size (if fixed or if no stop loss defined) input ENUM_RISK_BASE InpRiskBase=RISK_BASE_BALANCE; //Risk Base @@ -28,23 +28,23 @@ input double InpMinLotSize=0.01; //Min Lo input double InpMaxLotSize=100; //Max Lot Size -input string Comment_1="=========="; //Trading Hours Settings +input string Comment_1="=========="; //Trading Hours Settings input bool InpUseTradingHours=false; //Activate Trading Hours input string InpTradingHourStart="01"; //Trading Start Hour (Broker Server Hour) input string InpTradingStartMin="30"; //Trading Start minute input string InpTradingHourEnd="23"; //Trading End Hour (Broker Server Hour) input string InpTradingEndMin="00"; //Trading End minute input bool InpUseTradingSession=true; -input ENUM_TRADING_SESSION InpTradingSession = LONDON_SESSION; //Trading session +input ENUM_TRADING_SESSION InpTradingSession = LONDON_SESSION; //Trading session -input string Comment_2="=========="; //Trading Hours Settings +input string Comment_2="=========="; //Trading Hours Settings input int InpGridGap = 1000; -input double InpVolume = 0.01; // Default order size -input string InpComment = __FILE__; // Default trade comment -input int InpMagicNumber = 20200701; // Magic Number -input int InpBrokerTimeZoneGMT = 2; //Broker timezone from GMT -input int InpSlippage = 2; +input double InpVolume = 0.01; //Default order size +input string InpComment = __FILE__; //Default trade comment +input int InpMagicNumber = 20200701; //Magic Number +input int InpBrokerTimeZoneGMT = 2; //Broker timezone from GMT +input int InpSlippage = 2; //Slippage int londonSession[] = {7, 17}; diff --git a/Include/Nkanven/Frameworks/Extensions/Signals/SignalGrid.mqh b/Include/Nkanven/Frameworks/Extensions/Signals/SignalGrid.mqh index bbdce02..efa2d05 100644 --- a/Include/Nkanven/Frameworks/Extensions/Signals/SignalGrid.mqh +++ b/Include/Nkanven/Frameworks/Extensions/Signals/SignalGrid.mqh @@ -83,14 +83,13 @@ void CSignalGrid::UpdateSignal() // 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, realOCountSell; + int realOCountBuy = 0, realOCountSell = 0; ulong ticket; SetSignal(OFX_ENTRY_SIGNAL, OFX_SIGNAL_NONE); //If there're many positions and account balance is negative - Print("There is ", PositionsTotal(), " opened positions"); if(PositionsTotal() > 0) { //Count the opened positions by type @@ -107,7 +106,6 @@ void CSignalGrid::UpdateSignal() pCountBuy += 1; } - Print("POSITION_SYMBOL ", PositionGetString(POSITION_SYMBOL), " = ", mSymbol, " POSITION_TYPE ",PositionGetInteger(POSITION_TYPE), " = ", POSITION_TYPE_SELL, " Magic ", PositionGetInteger(POSITION_MAGIC), " = ",m_magic); if(PositionGetString(POSITION_SYMBOL)==mSymbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL && PositionGetInteger(POSITION_MAGIC)==m_magic) { @@ -124,7 +122,7 @@ void CSignalGrid::UpdateSignal() //Count the orders by type int cntO = OrdersTotal(); - Print("Total pending orders ", cntO); + for(int i = cntO-1; i>=0; i--) { ticket = OrderGetTicket(i); @@ -147,67 +145,57 @@ void CSignalGrid::UpdateSignal() } else { - Print(GetLastError()); + Print("Last error code ", GetLastError()); } } - Print("openedBuyPositionPrice ", openedBuyPositionPrice, " openedSellPositionPrice ", openedSellPositionPrice); - - Print("lastBuyOrderPrice ", lastBuyOrderPrice, " lastSellOrderPrice ", lastSellOrderPrice); double floatingProfitPercent = ((AccountInfoDouble(ACCOUNT_EQUITY) - AccountInfoDouble(ACCOUNT_BALANCE))*100)/AccountInfoDouble(ACCOUNT_BALANCE); // Check if profit is at least the mMaxRiskPerTrade - Print(" MaxRiskPerTrade ",mMaxRiskPerTrade, " Floating profit percent ", floatingProfitPercent, " Account equity ", AccountInfoDouble(ACCOUNT_EQUITY), " Account balance ", AccountInfoDouble(ACCOUNT_BALANCE)); - //The number of buy pending order should be twice the opened sell positions; and vice versa realOCountBuy = pCountSell+1; - realOCountSell = pCountBuy*2; + realOCountSell = pCountBuy+1; totalBuy = pCountBuy+oCountBuy; totalSell = pCountSell+oCountSell; realTotalBuy = pCountSell+1; realTotalSell = pCountBuy+1; - - Print("Sell order (", oCountSell, ") Real (", realOCountSell, ")"); - Print("Buy order (", oCountBuy, ") Real (", realOCountBuy, ")", " Opened sell ", pCountSell); - - - Print("oCountSell ", oCountSell, " < ", " realOCountSell ", realOCountSell, " && ", " pCountBuy ", pCountBuy," > 0"); if(OrdersTotal() == 0 && PositionsTotal() == 0) { - SetSignal(OFX_ENTRY_SIGNAL, OFX_SIGNAL_BOTH); + 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("Exit if no opened position"); + 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("Exit on profit target"); + SetSignal(OFX_EXIT_SIGNAL, OFX_SIGNAL_ALL); + Print("3 - Exit on profit target"); } else { - Print("realTotalSell ", realTotalSell, " <= ", " totalSell ", totalSell ," && ", " pCountBuy ",pCountBuy ," > 0"); + Print("realTotalSell ", realTotalSell, " > ", " totalSell ", totalSell," && ", " pCountBuy ",pCountBuy," > 0"); if(realTotalSell > totalSell && pCountBuy > 0) { - SetSignal(OFX_ENTRY_SIGNAL, OFX_SIGNAL_SELL); - Print("Sell order (", oCountSell, ") is less than it should be (", realOCountSell, ")"); + 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); + SetSignal(OFX_ENTRY_SIGNAL, OFX_SIGNAL_BUY); //mEntrySignals[0].SetSignal(OFX_ENTRY_SIGNAL, OFX_SIGNAL_BUY); - Print("Buy order (", oCountBuy, ") is less than it should be (", realOCountBuy, ")"); + Print("5 - Buy order (", oCountBuy, ") is less than it should be (", realOCountBuy, ")"); } } } diff --git a/Include/Nkanven/Frameworks/GridEA/ExpertBase.mqh b/Include/Nkanven/Frameworks/GridEA/ExpertBase.mqh index 1934a16..4268d36 100644 --- a/Include/Nkanven/Frameworks/GridEA/ExpertBase.mqh +++ b/Include/Nkanven/Frameworks/GridEA/ExpertBase.mqh @@ -266,7 +266,7 @@ void CExpertBase::OnTick(void) bool firstTime = (mLastBarTime==0); bool newBar = (mBarTime!=mLastBarTime); - //TradeWatcher(); +//TradeWatcher(); if(LoopMain(newBar, firstTime)) { mLastBarTime = mBarTime; @@ -297,94 +297,40 @@ bool CExpertBase::LoopMain(bool newBar,bool firstTime) ////Changed ENUM_OFX_SIGNAL_DIRECTION entrySignal = GetCurrentSignal(mEntrySignals, OFX_ENTRY_SIGNAL); ENUM_OFX_SIGNAL_DIRECTION exitSignal = GetCurrentSignal(mExitSignals, OFX_EXIT_SIGNAL); - - + + Print("entrySignal ", entrySignal); - /*if(mEntrySignals[0]!=NULL) - mEntrySignals[0].UpdateSignal(); - if(mEntrySignals[0]!=mExitSignals[0]) - { - if(mEntrySignals[0]!=NULL) - mEntrySignals[0].UpdateSignal(); - }*/ - -// -// Should any trades be closed -// -////Changed -/* - if(exitSignal==OFX_SIGNAL_BOTH) - { - Trade.PositionCloseByType(mSymbol, POSITION_TYPE_BUY); - Trade.PositionCloseByType(mSymbol, POSITION_TYPE_SELL); - } - else - if(exitSignal==OFX_SIGNAL_BUY) - { - Trade.PositionCloseByType(mSymbol, POSITION_TYPE_BUY); - } - else - if(exitSignal==OFX_SIGNAL_SELL) - { - Trade.PositionCloseByType(mSymbol, POSITION_TYPE_SELL); - } - if(exitSignal==OFX_SIGNAL_ALL) - { - Trade.PositionCloseAll(); - - Trade.OrderCloseAll(); - } -*/ -////if (mExitSignal!=NULL) { -//// if (mExitSignal.ExitSignal()==OFX_SIGNAL_BOTH) { -//// Trade.PositionCloseByType(mSymbol, POSITION_TYPE_BUY); -//// Trade.PositionCloseByType(mSymbol, POSITION_TYPE_SELL); -//// } else -//// if (mExitSignal.ExitSignal()==OFX_SIGNAL_BUY) { -//// Trade.PositionCloseByType(mSymbol, POSITION_TYPE_BUY); -//// } else -//// if (mExitSignal.ExitSignal()==OFX_SIGNAL_SELL) { -//// Trade.PositionCloseByType(mSymbol, POSITION_TYPE_SELL); -//// } -////} // // Should a trade be opened // MqlTradeRequest request = {}; // Just initialising - double buyPrice, sellPrice, SLPoints=0; + double sellPrice, SLPoints=0; int GripPips = mGridGap; double TakeProfitPoint = GripPips*_Point; LotSize(GripPips); -////Changed - - Print("Entry signal for Both ", OFX_SIGNAL_BOTH, " Entry for OFX_SIGNAL_BUY ", OFX_SIGNAL_BUY, " Actual ", entrySignal); if(entrySignal==OFX_SIGNAL_BOTH) { double AskPrice = SymbolInfoDouble(Symbol(),SYMBOL_ASK); double BidPrice = SymbolInfoDouble(Symbol(),SYMBOL_BID); - Print("m Grid pip ", GripPips, " Point ", _Point, " TP point ", TakeProfitPoint); - buyPrice = AskPrice + TakeProfitPoint; - sellPrice = BidPrice - TakeProfitPoint; - - Print("m Grid pip ", GripPips, " Point ", _Point); - - Print(" Buy price ", buyPrice, " TP normalized ", NormalizeDouble(buyPrice + TakeProfitPoint, mDigits)); - //SLPoints=MathCeil(buyPrice-GripPips); - - //GetMarketPrices(ORDER_TYPE_SELL, request); - //Trade.Sell(mVolume, mSymbol, request.price, request.sl, request.tp); GetMarketPrices(ORDER_TYPE_BUY, request); - request.tp = NormalizeDouble(request.price + TakeProfitPoint, mDigits); - Trade.Buy(mVolume, mSymbol, request.price, request.sl); + + if(Trade.Buy(mVolume, mSymbol)) + { + GetMarketPrices(ORDER_TYPE_SELL_STOP, request); + sellPrice = BidPrice - TakeProfitPoint; + request.price = NormalizeDouble(sellPrice, mDigits); + + Trade.SellStop(mVolume, request.price, mSymbol, request.sl, request.tp); + } + else + { + Print("Get last error code ", GetLastError()); + } - GetMarketPrices(ORDER_TYPE_SELL_STOP, request); - request.price = sellPrice; - request.tp = NormalizeDouble(sellPrice - TakeProfitPoint, mDigits); - Trade.SellStop(mVolume, request.price, mSymbol, request.sl); } else @@ -392,25 +338,18 @@ bool CExpertBase::LoopMain(bool newBar,bool firstTime) { //If there's a pending order, get the last order's price else get the position price Print("Trying to open a buy"); - buyPrice = mEntrySignals[0].getLastBuyOrderPrice()?mEntrySignals[0].getLastBuyOrderPrice():mEntrySignals[0].getOpenedBuyPositionPrice(); - request.price = buyPrice+TakeProfitPoint; - request.sl = 0.0; - request.tp = NormalizeDouble(buyPrice + TakeProfitPoint, mDigits); + GetMarketPrices(ORDER_TYPE_BUY_STOP, request); - Trade.BuyStop(mVolume, request.price, mSymbol, request.sl); + Trade.BuyStop(mVolume, request.price, mSymbol, request.sl, request.tp); } else if(entrySignal==OFX_SIGNAL_SELL) { Print("Trying to open a sell"); - - sellPrice = mEntrySignals[0].getLastSellOrderPrice()?mEntrySignals[0].getLastSellOrderPrice():mEntrySignals[0].getOpenedSellPositionPrice(); - request.price = sellPrice-TakeProfitPoint; - request.sl = 0.0; - request.tp = NormalizeDouble(sellPrice - TakeProfitPoint, mDigits); + GetMarketPrices(ORDER_TYPE_SELL_STOP, request); - Trade.SellStop(mVolume, request.price, mSymbol, request.sl); + Trade.SellStop(mVolume, request.price, mSymbol, request.sl, request.tp); } if(exitSignal==OFX_SIGNAL_ALL) @@ -418,32 +357,6 @@ bool CExpertBase::LoopMain(bool newBar,bool firstTime) Trade.OrderCloseAll(); Trade.PositionCloseAll(); } -//// if (mEntrySignal!=NULL) { -//// if (mEntrySignal.EntrySignal()==OFX_SIGNAL_BOTH) { -//// -//// GetMarketPrices(ORDER_TYPE_BUY, request); -//// Trade.Buy(mVolume, mSymbol, request.price, request.sl, request.tp); -//// -//// GetMarketPrices(ORDER_TYPE_SELL, request); -//// Trade.Sell(mVolume, mSymbol, request.price, request.sl, request.tp); -//// -//// } else -//// if (mEntrySignal.EntrySignal()==OFX_SIGNAL_BUY) { -//// -//// GetMarketPrices(ORDER_TYPE_BUY, request); -//// Trade.Buy(mVolume, mSymbol, request.price, request.sl, request.tp); -//// -//// } else -//// if (mEntrySignal.EntrySignal()==OFX_SIGNAL_SELL) { -//// -//// GetMarketPrices(ORDER_TYPE_SELL, request); -//// Trade.Sell(mVolume, mSymbol, request.price, request.sl, request.tp); -//// -//// } -//// } - -//mEntrySignals[0].SetSignal(OFX_ENTRY_SIGNAL, OFX_SIGNAL_NONE); -//mEntrySignals[0].SetSignal(OFX_EXIT_SIGNAL, OFX_SIGNAL_NONE); return(true); @@ -457,19 +370,39 @@ void CExpertBase::GetMarketPrices(ENUM_ORDER_TYPE orderType, MqlTradeRequest &r double sl = (mStopLossObj==NULL) ? mStopLossValue : mStopLossObj.GetStopLoss(); double tp = (mTakeProfitObj==NULL) ? mTakeProfitValue : mTakeProfitObj.GetTakeProfit(); + double sellPrice, buyPrice; + Trade.SetExpertMagicNumber(mMagicNumber); if(orderType==ORDER_TYPE_BUY) { - if(request.price==0.0) - request.price = SymbolInfoDouble(mSymbol, SYMBOL_ASK); + request.price = SymbolInfoDouble(mSymbol, SYMBOL_ASK); request.tp = (tp==0.0) ? 0.0 : NormalizeDouble(request.price+tp, mDigits); request.sl = (sl==0.0) ? 0.0 : NormalizeDouble(request.price-sl, mDigits); } if(orderType==ORDER_TYPE_SELL) { - if(request.price==0.0) - request.price = SymbolInfoDouble(mSymbol, SYMBOL_BID); + request.price = SymbolInfoDouble(mSymbol, SYMBOL_BID); + request.tp = (tp==0.0) ? 0.0 : NormalizeDouble(request.price-tp, mDigits); + request.sl = (sl==0.0) ? 0.0 : NormalizeDouble(request.price+sl, mDigits); + } + + if(orderType==ORDER_TYPE_SELL_STOP) + { + sellPrice = mEntrySignals[0].getLastSellOrderPrice()?mEntrySignals[0].getLastSellOrderPrice():mEntrySignals[0].getOpenedSellPositionPrice(); + sellPrice = (sellPrice==0.0)?SymbolInfoDouble(mSymbol, SYMBOL_BID):sellPrice; + + request.price = sellPrice-(mGridGap*_Point); + + request.tp = (tp==0.0) ? 0.0 : NormalizeDouble(request.price-tp, mDigits); + request.sl = (sl==0.0) ? 0.0 : NormalizeDouble(request.price+sl, mDigits); + } + + if(orderType==ORDER_TYPE_BUY_STOP) + { + buyPrice = mEntrySignals[0].getLastBuyOrderPrice()?mEntrySignals[0].getLastBuyOrderPrice():mEntrySignals[0].getOpenedBuyPositionPrice(); + buyPrice = (buyPrice==0.0)?SymbolInfoDouble(mSymbol, SYMBOL_ASK):buyPrice; + request.price = buyPrice+(mGridGap*_Point); request.tp = (tp==0.0) ? 0.0 : NormalizeDouble(request.price-tp, mDigits); request.sl = (sl==0.0) ? 0.0 : NormalizeDouble(request.price+sl, mDigits); } @@ -750,7 +683,7 @@ void CExpertBase::TradeWatcher(void) totalSell = pCountSell+oCountSell; realTotalBuy = pCountSell+1; realTotalSell = pCountBuy+1; - + Print("Sell order (", oCountSell, ") Real (", realOCountSell, ")"); Print("Buy order (", oCountBuy, ") Real (", realOCountBuy, ")", " Opened sell ", pCountSell);