diff --git a/Experts/Nkanven/TheChallenger.ex5 b/Experts/Nkanven/TheChallenger.ex5 new file mode 100644 index 0000000..5f66dbf Binary files /dev/null and b/Experts/Nkanven/TheChallenger.ex5 differ diff --git a/Experts/Nkanven/TheChallenger.mq5 b/Experts/Nkanven/TheChallenger.mq5 new file mode 100644 index 0000000..42edbe7 --- /dev/null +++ b/Experts/Nkanven/TheChallenger.mq5 @@ -0,0 +1,76 @@ +//+------------------------------------------------------------------+ +//| TheChallenger.mq5 | +//| Copyright 2022, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2022, MetaQuotes Ltd." +#property link "https://www.mql5.com" +#property version "1.00" + +#include //EA paramters +#include //Trading hours checks +#include //Trading conditions checks +#include //Trading conditions checks +#include //Lot size calculator +#include //Lot size calculator +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ + +#include +#include +CiMA* ma; +CiATR* atr; + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +int OnInit() + { +//--- + ma = new CiMA(); + ma.Create(gSymbol, PERIOD_CURRENT, InpPeriods, InpAppliedPrice, InpMethod, PRICE_CLOSE); + + atr = new CiATR(); + atr.Create(gSymbol, PERIOD_CURRENT, InpAtrPeriod); +//--- + return(INIT_SUCCEEDED); + } +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) + { +//--- + + } +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() + { +//--- + TimeCurrent(dt); + + SymbolInfoTick(_Symbol,last_tick); + + CheckOperationHours(); + CheckPreChecks(); + ScanPositions(); +//Get technical indicators values + ma.Refresh(-1); + gMa = ma.Main(1); + + atr.Refresh(-1); + gAtr = atr.Main(1); + + Print("ATR ", gAtr); + + if(!gIsPreChecksOk) + return; + + Print("Good for trading..."); + getSignal(); + ExecuteEntry(); + } +//+------------------------------------------------------------------+ diff --git a/Include/Nkanven/TheChallenger/CheckHistory.mqh b/Include/Nkanven/TheChallenger/CheckHistory.mqh new file mode 100644 index 0000000..8c5f1b0 --- /dev/null +++ b/Include/Nkanven/TheChallenger/CheckHistory.mqh @@ -0,0 +1,27 @@ +//+------------------------------------------------------------------+ +//| CheckHistory.mqh | +//| Copyright 2021, Nkondog Anselme Venceslas | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2021, Nkondog Anselme Venceslas" +#property link "https://www.mql5.com" +//+------------------------------------------------------------------+ +//| defines | +//+------------------------------------------------------------------+ +// #define MacrosHello "Hello, world!" +// #define MacrosYear 2010 +//+------------------------------------------------------------------+ +//| DLL imports | +//+------------------------------------------------------------------+ +// #import "user32.dll" +// int SendMessageA(int hWnd,int Msg,int wParam,int lParam); +// #import "my_expert.dll" +// int ExpertRecalculate(int wParam,int lParam); +// #import +//+------------------------------------------------------------------+ +//| EX5 imports | +//+------------------------------------------------------------------+ +// #import "stdlib.ex5" +// string ErrorDescription(int error_code); +// #import +//+------------------------------------------------------------------+ diff --git a/Include/Nkanven/TheChallenger/CloseTransactions.mqh b/Include/Nkanven/TheChallenger/CloseTransactions.mqh new file mode 100644 index 0000000..ed3bd1b --- /dev/null +++ b/Include/Nkanven/TheChallenger/CloseTransactions.mqh @@ -0,0 +1,94 @@ +//+------------------------------------------------------------------+ +//| CloseTransactions.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; + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +void CloseTransactions(ENUM_SIGNAL_EXIT tType) + { + bool result = true; + int cnt = OrdersTotal(); + int cts = PositionsTotal(); + if(cnt > 0) + { + + + for(int i = cnt-1; i>=0; i--) + { + ulong ticket = OrderGetTicket(i); + if(OrderSelect(ticket)) + { + if(tType==SIGNAL_EXIT_BUY && (OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT || OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP) && OrderGetInteger(ORDER_MAGIC)==InpMagicNumber) + { + if(!trade.OrderDelete(ticket)) + Print("Error (", GetLastError(), ") while deleting all buy orders"); + } + else + { + if(tType==SIGNAL_EXIT_SELL && (OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT || OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP) && OrderGetInteger(ORDER_MAGIC)==InpMagicNumber) + { + if(!trade.OrderDelete(ticket)) + Print("Error (", GetLastError(), ") while deleting all sell orders"); + } + else + { + if(tType==SIGNAL_EXIT_ALL) + { + if(!trade.OrderDelete(ticket)) + Print("Error (", GetLastError(), ") while deleting all orders"); + } + } + } + } + else + { + Print("Error (", GetLastError(), ") while selecting order's ticket"); + } + } + } + + if(cts > 0) + { + for(int i = cts-1; i>=0; i--) + { + ulong ticket = PositionGetTicket(i); + if(PositionSelectByTicket(ticket)) + { + if(tType==SIGNAL_EXIT_BUY && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && PositionGetInteger(POSITION_MAGIC)==InpMagicNumber) + { + if(!trade.PositionClose(ticket)) + Print("Error (", GetLastError(), ") while deleting all buy positions"); + } + else + { + if(tType==SIGNAL_EXIT_SELL && PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && PositionGetInteger(POSITION_MAGIC)==InpMagicNumber) + { + if(!trade.PositionClose(ticket)) + Print("Error (", GetLastError(), ") while deleting all sell positions"); + } + else + { + if(tType==SIGNAL_EXIT_ALL) + { + if(!trade.PositionClose(ticket)) + Print("Error (", GetLastError(), ") while deleting all positions"); + } + } + } + + } + else + { + Print("Error (", GetLastError(), ") while selecting position by ticket"); + } + } + } + } +//+------------------------------------------------------------------+ diff --git a/Include/Nkanven/TheChallenger/EntriesManager.mqh b/Include/Nkanven/TheChallenger/EntriesManager.mqh new file mode 100644 index 0000000..d9d98d5 Binary files /dev/null and b/Include/Nkanven/TheChallenger/EntriesManager.mqh differ diff --git a/Include/Nkanven/TheChallenger/LotSizeCal.mqh b/Include/Nkanven/TheChallenger/LotSizeCal.mqh new file mode 100644 index 0000000..5ff8fc3 --- /dev/null +++ b/Include/Nkanven/TheChallenger/LotSizeCal.mqh @@ -0,0 +1,56 @@ +//+------------------------------------------------------------------+ +//| LotSizeCal.mqh | +//| Copyright 2021, Nkondog Anselme Venceslas | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2021, Nkondog Anselme Venceslas" +#property link "https://www.mql5.com" + + +//Lot Size Calculator +void LotSizeCalculate(double SL=0) + { +//If the position size is dynamic + if(InpRiskDefaultSize==RISK_DEFAULT_AUTO) + { + //If the stop loss is not zero then calculate the lot size + if(SL!=0) + { + double RiskBaseAmount=0; + + //TickValue is the value of the individual price increment for 1 lot of the instrument, expressed in the account currenty + double TickValue=SymbolInfoDouble(gSymbol,SYMBOL_TRADE_TICK_VALUE); + //Define the base for the risk calculation depending on the parameter chosen + if(InpRiskBase==RISK_BASE_BALANCE) + RiskBaseAmount=AccountInfoDouble(ACCOUNT_BALANCE); + if(InpRiskBase==RISK_BASE_EQUITY) + RiskBaseAmount=AccountInfoDouble(ACCOUNT_EQUITY); + if(InpRiskBase==RISK_BASE_FREEMARGIN) + RiskBaseAmount=AccountInfoDouble(ACCOUNT_FREEMARGIN); + + //Calculate the Position Size + LotSize=((RiskBaseAmount*InpMaxRiskPerTrade/100)/(SL*TickValue)); + } + //If the stop loss is zero then the lot size is the default one + if(SL==0) + { + LotSize=InpDefaultLotSize; + } + } +//Normalize the Lot Size to satisfy the allowed lot increment and minimum and maximum position size + LotSize=MathFloor(LotSize/SymbolInfoDouble(gSymbol,SYMBOL_VOLUME_STEP))*SymbolInfoDouble(gSymbol,SYMBOL_VOLUME_STEP); + +//Limit the lot size in case it is greater than the maximum allowed by the user + if(LotSize>InpMaxLotSize) + LotSize=InpMaxLotSize; +//Limit the lot size in case it is greater than the maximum allowed by the broker + if(LotSize>SymbolInfoDouble(gSymbol,SYMBOL_VOLUME_MAX)) + LotSize=SymbolInfoDouble(gSymbol,SYMBOL_VOLUME_MAX); + Print("Lot ", LotSize, " Max lot ", SymbolInfoDouble(gSymbol,SYMBOL_VOLUME_MAX)); +//If the lot size is too small then set it to 0 and don't trade + if(LotSizeInpMaxStopLoss) + { + gIsPreChecksOk=false; + Print("Default Stop Loss must be between Minimum and Maximum Stop Loss Allowed"); + return; + } +//Check if the default take profit you are setting in above the minimum and below the maximum + if(InpDefaultTakeProfitInpMaxTakeProfit) + { + gIsPreChecksOk=false; + Print("Default Take Profit must be between Minimum and Maximum Take Profit Allowed"); + return; + } +//Check if the Lot Size is between the minimum and maximum + if(InpDefaultLotSizeInpMaxLotSize) + { + gIsPreChecksOk=false; + Print("Default Lot Size must be between Minimum and Maximum Lot Size Allowed"); + return; + } +//Slippage must be >= 0 + if(InpSlippage<0) + { + gIsPreChecksOk=false; + Print("Slippage must be a positive value"); + return; + } +//MaxSpread must be >= 0 + if(InpMaxSpread<0) + { + gIsPreChecksOk=false; + Print("Maximum Spread must be a positive value"); + return; + } +//MaxRiskPerTrade is a % between 0 and 100 + if(InpMaxRiskPerTrade<0 || InpMaxRiskPerTrade>100) + { + gIsPreChecksOk=false; + Print("Maximum Risk Per Trade must be a percentage between 0 and 100"); + return; + } +//Spread is acceptable + long SpreadCurr=(int)Spread; + Print("Spread ", Spread); + if(SpreadCurr>InpMaxSpread) + { + gIsPreChecksOk=false; + Print("Spread is higher than Max acceptable spread"); + return; + } + } +//+------------------------------------------------------------------+ diff --git a/Include/Nkanven/TheChallenger/ScanPositions.mqh b/Include/Nkanven/TheChallenger/ScanPositions.mqh new file mode 100644 index 0000000..02076cf --- /dev/null +++ b/Include/Nkanven/TheChallenger/ScanPositions.mqh @@ -0,0 +1,45 @@ +//+------------------------------------------------------------------+ +//| 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 +void ScanPositions() + { + +//Scan all the orders, retrieving some of the details + gTotalPositions = PositionsTotal(); + gTotalBuyPositions = 0; + gTotalSellPositions = 0; + + for(int i=0; i= InpDayTradingHourStart ", InpDayTradingHourStart ," ", dt.hour >= InpDayTradingHourStart); + Print("dt.hour ", dt.hour," <= InpDayTradingHourEnd ", InpDayTradingHourEnd ," ", dt.hour <= InpDayTradingHourEnd); + + //Check day trading hours + if(dt.hour >= InpDayTradingHourStart && dt.hour <= InpDayTradingHourEnd) + { + day_trading = true; + gIsOperatingHours=true; + Print("Day period trading"); + return; + } + + } +Print("InpTradingPeriods == NIGHT_TRADING ", InpTradingPeriods == NIGHT_TRADING); + if(InpTradingPeriods == NIGHT_TRADING) + { + //Check night trading hours + if(dt.hour >= InpNightTradingHourStart && dt.hour <= InpNightTradingHourEnd) + { + night_trading = true; + gIsOperatingHours=true; + Print("Night period trading"); + return; + } + } + + if(InpTradingPeriods == DAY_NIGHT_TRADING) + { + //Check night trading hours + if(day_trading || night_trading) + { + gIsOperatingHours=true; + Print("Day and night periods trading"); + return; + } + } + } +//+------------------------------------------------------------------+