From ac560ff454152d1ed840487ea401e7c37eb1537f Mon Sep 17 00:00:00 2001 From: Nkondog Anselme Date: Mon, 15 Nov 2021 02:41:27 +0100 Subject: [PATCH] Update gitignore --- .gitignore | 4 +- Include/E_CheckHistory.mqh | Bin 0 -> 4886 bytes Include/E_ClosePositions.mqh | 81 +++++++ Include/E_EntriesManagement.mqh | Bin 0 -> 20382 bytes Include/E_Parameters.mqh | Bin 0 -> 20632 bytes Include/E_ScanPositions.mqh | 49 ++++ Include/E_TradeManagement.mqh | 57 +++++ Include/ExpertBase.mqh | 380 ++++++++++++++++++++++++++++++++ Include/Framework.mqh | 21 ++ 9 files changed, 590 insertions(+), 2 deletions(-) create mode 100644 Include/E_CheckHistory.mqh create mode 100644 Include/E_ClosePositions.mqh create mode 100644 Include/E_EntriesManagement.mqh create mode 100644 Include/E_Parameters.mqh create mode 100644 Include/E_ScanPositions.mqh create mode 100644 Include/E_TradeManagement.mqh create mode 100644 Include/ExpertBase.mqh create mode 100644 Include/Framework.mqh diff --git a/.gitignore b/.gitignore index 29bd3c9..9119e28 100644 --- a/.gitignore +++ b/.gitignore @@ -69,8 +69,8 @@ Experts/Advisors/ Experts/Examples/ Include/Arrays/ Include/C* -Include/E* -Include/F* +Include/Expert/ +Include/Files/ Include/G* Include/I Include/M* diff --git a/Include/E_CheckHistory.mqh b/Include/E_CheckHistory.mqh new file mode 100644 index 0000000000000000000000000000000000000000..aa967ff0957a7cbffdf4a11b375ae5b73ff64be2 GIT binary patch literal 4886 zcmd5=T~8B16ur+T{)e$9rVW)36JJC~lvX7HA-0(CL@F%USSWV4ng;#9@+Z`D=JqIzMZSppr=uxHvL){&kz@HFucRxf zWYU*`jAU8PB(c<9mD4HoIQ(#pZl`5 zZ-yK=Z*egj6(HcYb5!w&nPx!`IJiL0<2+P6F6N1~%3ah-JpoEjy?;b&?BV~q50$z| zNHq3XB%A&RyUv&O#mw0!a6%WX>`MDXRcgM<>E+e0J10Z%G#Q<2t|Nma_Ll@Kv;pp4 zk5-fShw={JknK5?wOB`4VPyw1l+hjc2D^*pv464G1pO(P?;INX&=IdJTIulR2-=h1 ztYSZ+j?s7>(XE!Bpg&Ewu!Z@KXJLm3IBAc4*n;l^43)`|=&r^pSxU?%8SB zBU7p3T~pr3w(Lm*-MfK4TFY6S@8bNLu|0+bRs1w|!JhgITk>*;KC0~BHn>xuUp@Gg z*V=$a&Zm%WYv^4Ze^wxKkjbvc3~jr_Oc&n{po4K*%YCu$W5VcHr4mVYh>YrU-bROh z67OUjR&%cr>@`b5?oMIJ0CIzu-7!`v^J(<$IwW0>ZWt`vc50v7R-r3_aaSWtD)r4bRbWl_++OfZGFP zlP5KvVCVUw1q*gCoIJoVj?i6zlY3s%D$ZPGjHGca<0XCDgC)!O+5RE!#Pde10Y+f7 zEK(|Y@@l$tN1@#;&ogxGq#}%RS;~CB4q+L3b$C`C0T15WjNwL^Lxn>jdM3^z8 zp^g!?IpT}R}&&|%#*NL9Y$QNhBv)+*h7U`7q6A8y}DgXcg literal 0 HcmV?d00001 diff --git a/Include/E_ClosePositions.mqh b/Include/E_ClosePositions.mqh new file mode 100644 index 0000000..7b061e4 --- /dev/null +++ b/Include/E_ClosePositions.mqh @@ -0,0 +1,81 @@ +//+------------------------------------------------------------------+ +//| E_ClosePositions.mqh | +//| Copyright 2021, Nkondog Anselme Venceslas | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2021, Nkondog Anselme Venceslas" +#property link "https://www.mql5.com" +CTrade trade; + +// We declare a function CloseOpenPositions of type int and we want to return +// the number of positions that are closed. +void CloseOpenPositions() + { + + int TotalClose=0; // We want to count how many orders have been closed. + int c_slippage = Slippage; +Print("Close position status ", ClosePosition); +// Normalization of the slippage. + if(_Digits==3 || _Digits==5) + { + c_slippage=c_slippage*10; + } + +// We scan all the orders backwards. +// This is required as if we start from the first order, we will have problems with the counters and the loop. + for(int i=PositionsTotal()-1; i>=0; i--) + { + + ulong ticket = PositionGetTicket(i); + + Print("Position profit is ", PositionGetDouble(POSITION_PROFIT)); + PositionProfit = PositionGetDouble(POSITION_PROFIT); + if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && iClose(Symb, PERIOD_CURRENT, 1) < Senkouspanb && iClose(Symb, PERIOD_CURRENT, 1) < Senkouspana) + { + // We select the order of index i, selecting by position and from the pool of market/pending trades. + //If the selection is successful we try to close the order. + if(trade.PositionClose(ticket, c_slippage)) + { + TotalClose++; + } + else + { + // If the order fails to be closed, we print the error. + Print("Order failed to close with error - ",GetLastError()); + } + } + + if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && iClose(Symb, PERIOD_CURRENT, 1) > Senkouspanb && iClose(Symb, PERIOD_CURRENT, 1) > Senkouspana) + { + // We select the order of index i, selecting by position and from the pool of market/pending trades. + //If the selection is successful we try to close the order. + if(trade.PositionClose(ticket, c_slippage)) + { + TotalClose++; + } + else + { + // If the order fails to be closed, we print the error. + Print("Order failed to close with error - ",GetLastError()); + } + } + + if(ClosePosition) + { + if(trade.PositionClose(ticket, c_slippage)) + { + TotalClose++; + ClosePosition = false; + } + else + { + // If the order fails to be closed, we print the error. + Print("Order failed to close with error - ",GetLastError()); + } + } + // We can use a delay if the execution is too fast. + // Sleep() will wait X milliseconds before proceeding with the code. + // Sleep(300); + } + } +//+------------------------------------------------------------------+ diff --git a/Include/E_EntriesManagement.mqh b/Include/E_EntriesManagement.mqh new file mode 100644 index 0000000000000000000000000000000000000000..d69973d97d3cdc9ef5640bd721ceb171be5e4681 GIT binary patch literal 20382 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 F@L#s;__F{2 literal 0 HcmV?d00001 diff --git a/Include/E_ScanPositions.mqh b/Include/E_ScanPositions.mqh new file mode 100644 index 0000000..53f5789 --- /dev/null +++ b/Include/E_ScanPositions.mqh @@ -0,0 +1,49 @@ +//+------------------------------------------------------------------+ +//| E_ScanPositions.mqh | +//| Copyright 2021, Nkondog Anselme Venceslas | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2021, Nkondog Anselme Venceslas" +#property link "https://www.mql5.com" + +//Scan all positions to find the ones submitted by the EA +//NOTE This function is defined as bool because we want to return true if it is successful and false if it fails +bool ScanPositions() + { + +//Scan all the orders, retrieving some of the details + TotalOpenOrders = 0; + TotalOpenBuy = 0; + TotalOpenSell = 0; + for(int i=0; iLastBarTraded || LastBarTraded==0) + LastBarTraded=(datetime)PositionGetInteger(POSITION_TIME); + } + Print("Total positions ", TotalOpenOrders, " - Total buys ", TotalOpenBuy, " - Total sells ", TotalOpenSell); + return true; + } \ No newline at end of file diff --git a/Include/E_TradeManagement.mqh b/Include/E_TradeManagement.mqh new file mode 100644 index 0000000..9b95978 --- /dev/null +++ b/Include/E_TradeManagement.mqh @@ -0,0 +1,57 @@ +//+------------------------------------------------------------------+ +//| E_TradeManagement.mqh | +//| Copyright 2021, Nkondog Anselme Venceslas | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2021, Nkondog Anselme Venceslas" +#property link "https://www.mql5.com" + +//Done for the day after a profitable trade +//If closed trade was opened the day before, look for trade opportunities +double minProfitAllow = AccountInfoDouble(ACCOUNT_BALANCE)*(Breakevent/100); +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +void TradeManager() + { + CanSell = true; + CanBuy = true; + + if(lt.time == TimeToString(TimeCurrent(), TIME_DATE)) + { + if(lt.type == DEAL_TYPE_BUY && lt.profit < 0) + { + CanBuy = false; + } + if(lt.type = DEAL_TYPE_SELL && lt.profit < 0) + { + CanSell = false; + } + } + } +//+------------------------------------------------------------------+ + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +void ProfitRunner() + { + Print("Min acceptablbe profit ", minProfitAllow); + ClosePosition = false; + if(PositionProfit > minProfitAllow) + FollowProfit=true; + + if(FollowProfit) + { + if(Kijunsen > iClose(Symb, _Period, 1) && TotalOpenBuy > 0) + { + ClosePosition = true; + } + if(Kijunsen < iClose(Symb, _Period, 1) && TotalOpenSell > 0) + { + ClosePosition = true; + } + } + Print("Looking to close this position ", ClosePosition, " Follow profit ", FollowProfit); + } +//+------------------------------------------------------------------+ diff --git a/Include/ExpertBase.mqh b/Include/ExpertBase.mqh new file mode 100644 index 0000000..e5afc1d --- /dev/null +++ b/Include/ExpertBase.mqh @@ -0,0 +1,380 @@ +/* + ExpertBase.mqh + + Copyright 2013-2020, Orchard Forex + https://www.orchardforex.com + +*/ + + +#include "CommonBase.mqh" +#include "SignalBase.mqh" +#include "TPSLBase.mqh" +#include "Trade/Trade.mqh" + +class CExpertBase : public CCommonBase { + +protected: + + int mMagicNumber; + string mTradeComment; + + double mVolume; + + datetime mLastBarTime; + datetime mBarTime; + + ////Changed + // Arrays to hold the signal objects + CSignalBase *mEntrySignals[]; + CSignalBase *mExitSignals[]; + ////CSignalBase *mEntrySignal; + ////CSignalBase *mExitSignal; + + double mTakeProfitValue; + double mStopLossValue; + CTPSLBase *mTakeProfitObj; + CTPSLBase *mStopLossObj; + + CTradeCustom Trade; + +private: + +protected: + + virtual bool LoopMain(bool newBar, bool firstTime); + +protected: + + int Init(int magicNumber, string tradeComment); + +public: + + // + // Constructors + // + CExpertBase() : CCommonBase() + { Init(0, ""); } + CExpertBase(string symbol, int timeframe, int magicNumber, string tradeComment) + : CCommonBase(symbol, timeframe) + { Init(magicNumber, tradeComment); } + CExpertBase(string symbol, ENUM_TIMEFRAMES timeframe, int magicNumber, string tradeComment) + : CCommonBase(symbol, timeframe) + { Init(magicNumber, tradeComment); } + CExpertBase(int magicNumber, string tradeComment) + : CCommonBase() + { Init(magicNumber, tradeComment); } + + // + // Destructors + // + ~CExpertBase(); + +public: // Default properties + + // + // Assign the default values to the expert + // + virtual void SetVolume(double volume) { mVolume = volume; } + + virtual void SetTakeProfitValue(int takeProfitPoints) + { mTakeProfitValue = PointsToDouble(takeProfitPoints); } + virtual void SetTakeProfitObj(CTPSLBase *takeProfitObj) + { mTakeProfitObj = takeProfitObj; } + + virtual void SetStopLossValue(int stopLossPoints) + { mStopLossValue = PointsToDouble(stopLossPoints); } + virtual void SetStopLossObj(CTPSLBase *stopLossObj) + { mStopLossObj = stopLossObj; } + + virtual void SetTradeComment(string comment) { mTradeComment = comment; } + virtual void SetMagic(int magicNumber) { mMagicNumber = magicNumber; + Trade.SetExpertMagicNumber(magicNumber); } + +public: // Setup + + ////Changed + virtual void AddEntrySignal(CSignalBase *signal) { AddSignal(signal, mEntrySignals); } + virtual void AddExitSignal(CSignalBase *signal) { AddSignal(signal, mExitSignals); } + virtual void AddSignal(CSignalBase *signal, CSignalBase* &signals[]); + ////virtual void AddEntrySignal(CSignalBase *signal) { mEntrySignal=signal; } + ////virtual void AddExitSignal(CSignalBase *signal) { mExitSignal=signal; } + +public: // Event handlers + + virtual int OnInit(); + virtual void OnTick(); + virtual void OnTimer() { return; } + virtual double OnTester() { return(0.0); } + virtual void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) {}; + +#ifdef __MQL5__ + virtual void OnTrade() { return; } + virtual void OnTradeTransaction(const MqlTradeTransaction& trans, + const MqlTradeRequest& request, + const MqlTradeResult& result) + { return; } + virtual int OnTesterInit() { return(INIT_SUCCEEDED); } + virtual void OnTesterPass() { return; } + virtual void OnTesterDeinit() { return; } + virtual void OnBookEvent() { return; } +#endif + +public: // Functions + + virtual void GetMarketPrices(ENUM_ORDER_TYPE orderType, MqlTradeRequest &request); + ////New + virtual ENUM_OFX_SIGNAL_DIRECTION GetCurrentSignal(CSignalBase* &signals[], + ENUM_OFX_SIGNAL_TYPE signalType); + +}; + +CExpertBase::~CExpertBase() { + +} + +int CExpertBase::OnInit() { + + int i = 0; + for (i=ArraySize(mEntrySignals)-1; i>=0; i--) { + if (mEntrySignals[i].InitResult()!=INIT_SUCCEEDED) return(mEntrySignals[i].InitResult()); + } + for (i=ArraySize(mExitSignals)-1; i>=0; i--) { + if (mExitSignals[i].InitResult()!=INIT_SUCCEEDED) return(mExitSignals[i].InitResult()); + } + if (mTakeProfitObj!=NULL) { + if (mTakeProfitObj.InitResult()!=INIT_SUCCEEDED) return(mTakeProfitObj.InitResult()); + } + if (mStopLossObj!=NULL) { + if (mStopLossObj.InitResult()!=INIT_SUCCEEDED) return(mStopLossObj.InitResult()); + } + + return(INIT_SUCCEEDED); + +} + +int CExpertBase::Init(int magicNumber, string tradeComment) { + + if (mInitResult!=INIT_SUCCEEDED) return(mInitResult); + + mTradeComment = tradeComment; + SetMagic(magicNumber); + + mTakeProfitValue = 0.0; + mStopLossValue = 0.0; + + mLastBarTime = 0; + + ////New + ArrayResize(mEntrySignals, 0); // Just make sure these are initialised + ArrayResize(mExitSignals, 0); + + return(INIT_SUCCEEDED); + +} + +void CExpertBase::OnTick(void) { + + if (!TradeAllowed()) return; + + mBarTime = iTime(mSymbol, mTimeframe, 0); + + bool firstTime = (mLastBarTime==0); + bool newBar = (mBarTime!=mLastBarTime); + + if (LoopMain(newBar, firstTime)) { + mLastBarTime = mBarTime; + } + + return; + +} + +bool CExpertBase::LoopMain(bool newBar,bool firstTime) { + + // + // To start I will only trade on a new bar + // and not on the first bar after start + // + if (!newBar) return(true); + if (firstTime) return(true); + + // + // Update the signals + // + ////Changed + ENUM_OFX_SIGNAL_DIRECTION entrySignal = GetCurrentSignal(mEntrySignals, OFX_ENTRY_SIGNAL); + ENUM_OFX_SIGNAL_DIRECTION exitSignal = GetCurrentSignal(mExitSignals, OFX_EXIT_SIGNAL); + ////if (mEntrySignal!=NULL) mEntrySignal.UpdateSignal(); + ////if (mEntrySignal!=mExitSignal) { + //// if (mExitSignal!=NULL) mExitSignal.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 (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 + ////Changed + if (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 (entrySignal==OFX_SIGNAL_BUY) { + + GetMarketPrices(ORDER_TYPE_BUY, request); + Trade.Buy(mVolume, mSymbol, request.price, request.sl, request.tp); + + } else + if (entrySignal==OFX_SIGNAL_SELL) { + + GetMarketPrices(ORDER_TYPE_SELL, request); + Trade.Sell(mVolume, mSymbol, request.price, request.sl, request.tp); + + } +//// 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); +//// +//// } +//// } + + return(true); + +} + +void CExpertBase::GetMarketPrices(ENUM_ORDER_TYPE orderType, MqlTradeRequest &request) { + + double sl = (mStopLossObj==NULL) ? mStopLossValue : mStopLossObj.GetStopLoss(); + double tp = (mTakeProfitObj==NULL) ? mTakeProfitValue : mTakeProfitObj.GetTakeProfit(); + + if (orderType==ORDER_TYPE_BUY) { + if (request.price==0.0) 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.tp = (tp==0.0) ? 0.0 : NormalizeDouble(request.price-tp, mDigits); + request.sl = (sl==0.0) ? 0.0 : NormalizeDouble(request.price+sl, mDigits); + } + + return; + +} + +////New +void CExpertBase::AddSignal(CSignalBase *signal, CSignalBase* &signals[]) { + + int index = ArraySize(signals); + ArrayResize(signals, index+1); + signals[index] = signal; + +} + +////New +ENUM_OFX_SIGNAL_DIRECTION CExpertBase::GetCurrentSignal(CSignalBase* &signals[], + ENUM_OFX_SIGNAL_TYPE signalType) { + + ENUM_OFX_SIGNAL_DIRECTION result = OFX_SIGNAL_NONE; + ENUM_OFX_SIGNAL_DIRECTION r2 = OFX_SIGNAL_NONE; // Just working value + int index = ArraySize(signals); + + if (index<=0) { + + return(result); + + } else { + + signals[0].UpdateSignal(); + result = signals[0].GetSignal(signalType); + + // I have chosen to update all signals in case there is some + // behavour that needs it. The penalty is some performance + // If performance is an issue just add an exit inside the loop + // as the commented line + for (int i = 1; i