diff --git a/Experts/Nkanven/StarRiskCalculator.ex5 b/Experts/Nkanven/StarRiskCalculator.ex5 new file mode 100644 index 0000000..769e576 Binary files /dev/null and b/Experts/Nkanven/StarRiskCalculator.ex5 differ diff --git a/Experts/Nkanven/StarRiskCalculator.mq5 b/Experts/Nkanven/StarRiskCalculator.mq5 new file mode 100644 index 0000000..b353e6b --- /dev/null +++ b/Experts/Nkanven/StarRiskCalculator.mq5 @@ -0,0 +1,216 @@ +//+------------------------------------------------------------------+ +//| StarRiskCalculator.mq5 | +//| Copyright 2022, Nkondog Anselme Venceslas. | +//| https://www.linkedin.com/in/nkondog | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2022, Nkondog Anselme Venceslas." +#property link "https://www.linkedin.com/in/nkondog" +#property version "1.00" + + +//Parameters +MqlTick last_tick; +//Enumerative for the base used for risk calculation +enum ENUM_RISK_BASE + { + RISK_BASE_EQUITY=1, //EQUITY + RISK_BASE_BALANCE=2, //BALANCE + RISK_BASE_FREEMARGIN=3, //FREE MARGIN + RISK_BASE_INPUT=4, //INPUT BASE + }; + +//Enumerative for the default risk size +enum ENUM_RISK_DEFAULT_SIZE + { + RISK_DEFAULT_FIXED=1, //FIXED SIZE + RISK_DEFAULT_AUTO=2, //AUTOMATIC SIZE BASED ON RISK + }; + +input ENUM_RISK_DEFAULT_SIZE InpRiskDefaultSize=RISK_DEFAULT_AUTO; //Position Size Mode +input double InpBalance=10000.0; //Balance +input double InpMaxLossPercent=4.0; //Max Account Risk % +input int InpLifeCount=20; //Number of losses +double InpDefaultLotSize=0.01; //Position Size (if fixed or if no stop loss defined) +input ENUM_RISK_BASE InpRiskBase=RISK_BASE_BALANCE; //Risk Base +//input double InpMaxRiskPerTrade=0.5; //Percentage To Risk Each Trade +double InpMinLotSize=0.01; //Minimum Position Size Allowed +double InpMaxLotSize=100; //Maximum Position Size Allowed +double RiskBaseAmount=0; + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +string Symb = Symbol(); +string AccountCurr = AccountInfoString(ACCOUNT_CURRENCY); +double MaxRiskPerTrade=0.0; //Percentage To Risk Each Trade +double LotSize=InpDefaultLotSize; +double price=0.0; +double risk=0.0; +double StoplossPips=0.0; +double riskDiff=0.0; +double initialLoss=0.0; +double totalLoss=0.0; +double maxRiskPerLife=0.0; + +//TickValue is the value of the individual price increment for 1 lot of the instrument, expressed in the account currenty +double TickValue=SymbolInfoDouble(Symb,SYMBOL_TRADE_TICK_VALUE); + +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() + { +//--- + Print("The Expert Advisor with name ",MQLInfoString(MQL_PROGRAM_NAME)," is running"); +//--- enable object create events + ChartSetInteger(ChartID(),CHART_EVENT_OBJECT_CREATE,true); +//--- enable object delete events + ChartSetInteger(ChartID(),CHART_EVENT_OBJECT_DELETE,true); +//--- + return(INIT_SUCCEEDED); + } + + +//+------------------------------------------------------------------+ +//| | +//+------------------------------------------------------------------+ +void OnTick() + { + + LotSizeCalculate(price); + riskDiff = NormalizeDouble(RiskBaseAmount - InpBalance, 2); + initialLoss = (InpBalance * InpMaxLossPercent) / 100; + totalLoss = NormalizeDouble(riskDiff + initialLoss, 2); + maxRiskPerLife = NormalizeDouble(totalLoss /InpLifeCount, 2); + MaxRiskPerTrade = NormalizeDouble((maxRiskPerLife * 100) / RiskBaseAmount, 2); + + Comment("Star Risk Calculator \nRiskDiff: " + riskDiff + " " + AccountCurr +"\nInitialLoss: " + initialLoss + " " + AccountCurr +"\nTotalLoss: " + totalLoss + " " + AccountCurr +"\nMaxRiskPerLife: " + maxRiskPerLife + " " + AccountCurr + "\nMaxRiskPerTrade: " + MaxRiskPerTrade +"%"); + + +double StopAmount = StoplossPips * LotSize * TickValue; + + string text ="Lot size for "+ MaxRiskPerTrade +"% = " + DoubleToString(LotSize,2) + " lot (" + NormalizeDouble(StopAmount, 2) + " " + AccountCurr + ")"; + string name = "Lot"; + string name2 = "risk"; + ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0); + //ObjectSetText(name,text, 36, "Corbel Bold", YellowGreen); + ObjectSetInteger(0,name, OBJPROP_CORNER, CORNER_RIGHT_UPPER); + ObjectSetInteger(0,name, OBJPROP_XDISTANCE, 550); + ObjectSetInteger(0,name, OBJPROP_YDISTANCE, 10); + ObjectSetString(0,name,OBJPROP_TEXT,text); + ObjectSetString(0,name,OBJPROP_FONT,"Arial"); + ObjectSetInteger(0,name,OBJPROP_FONTSIZE,14); + ObjectSetInteger(0,name,OBJPROP_COLOR,clrYellowGreen); + //LabelDelete(0, name); + } +//+------------------------------------------------------------------+ +//| ChartEvent function | +//+------------------------------------------------------------------+ +void OnChartEvent(const int id, // Event identifier + const long& lparam, // Event parameter of long type + const double& dparam, // Event parameter of double type + const string& sparam) // Event parameter of string type + { +//--- the object has been deleted + if(id==CHARTEVENT_OBJECT_DELETE) + { + Print("The object with name ",sparam," has been deleted"); + } +//--- the object has been created + if(id==CHARTEVENT_OBJECT_CREATE) + { + Print("The object with name ",sparam," has been created"); + } + +//--- the object has been moved or its anchor point coordinates has been changed + if(id==CHARTEVENT_OBJECT_DRAG) + { + price = ObjectGetDouble(0, sparam, OBJPROP_PRICE, 0); + Print("The anchor point coordinates of the object with name ",sparam," has been changed. Price ", price); + } + } + + +//Lot Size Calculator +void LotSizeCalculate(double stopLoss) + { + SymbolInfoTick(_Symbol,last_tick); + double SL=0; + double PriceAsk=last_tick.ask; + double PriceBid=last_tick.bid; + + if(stopLoss < PriceAsk) + { + SL = (PriceAsk-stopLoss)/_Point; + } + if(stopLoss > PriceAsk) + { + SL = (stopLoss-PriceBid)/_Point; + } + Print("Stop loss distance ", SL); + +//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) + { + //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); + if(InpRiskBase==RISK_BASE_INPUT) + RiskBaseAmount=InpBalance; + + //Calculate the Position Size + //Print("RiskBaseAmount ", RiskBaseAmount, " MaxRiskPerTrade ", InpMaxRiskPerTrade, "Stop loss ", SL, " TickValue ", TickValue); + + LotSize=((RiskBaseAmount*MaxRiskPerTrade/100)/(SL*TickValue)); + StoplossPips = SL; + + } + //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(Symb,SYMBOL_VOLUME_STEP))*SymbolInfoDouble(Symb,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(Symb,SYMBOL_VOLUME_MAX)) + LotSize=SymbolInfoDouble(Symb,SYMBOL_VOLUME_MAX); + Print("Lot ", LotSize, " Max lot ", SymbolInfoDouble(Symb,SYMBOL_VOLUME_MAX)); +//If the lot size is too small then set it to 0 and don't trade + if(LotSize < SymbolInfoDouble(Symb,SYMBOL_VOLUME_MIN)) + { + LotSize=0; + Print("Lot size too small"); + } + } +//+------------------------------------------------------------------+ +//+------------------------------------------------------------------+ +//| Delete a text label | +//+------------------------------------------------------------------+ +bool LabelDelete(const long chart_ID=0, // chart's ID + const string name="Label") // label name + { +//--- reset the error value + ResetLastError(); +//--- delete the label + if(!ObjectDelete(chart_ID,name)) + { + Print(__FUNCTION__, + ": failed to delete a text label! Error code = ",GetLastError()); + return(false); + } +//--- successful execution + return(true); + } \ No newline at end of file