mirror of
https://github.com/rithsila/MT5-EA-Sniper-Strategy.git
synced 2026-08-18 21:28:13 +00:00
216 lines
8.8 KiB
Plaintext
216 lines
8.8 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| 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);
|
|
} |