//+------------------------------------------------------------------+
//| MoneyManagement.mq4 |
//| Copyright 2013, Vladimir Kjahrenov |
//| info@tarkvaratehas.ee |
//| |
//| Money Management / Risk Management visualiser |
//| This indicator uses 3 horizontal line to calculate lot size for |
//| next order. You can visually drag lines for better position, |
//| after draging all values are recalculated. |
//| This indicator is independent part but it is |
//| a part of an HurtLocker EA. |
//+------------------------------------------------------------------+
#property copyright "Copyright 2013, Vladimir Kjahrenov"
#property indicator_chart_window
extern int RiskPerOrder = 2; // risk per order
string slName = "sl";
string tpName = "tp";
string oName = "order";
extern color slColor = Red;
extern color tpColor = SpringGreen;
extern color oColor = Yellow;
int labelFontSize = 7;
int BrokerDigitsMultiplier = 1;
string comment = "";
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
// check is broker have 5 or 4 digits
if (MarketInfo(Symbol(), MODE_DIGITS) == 5 || MarketInfo(Symbol(), MODE_DIGITS) == 3){
BrokerDigitsMultiplier = 10;
}
string ObjName = "_panel_1";
if (ObjectFind(ObjName) == -1) {
ObjectCreate(ObjName, OBJ_LABEL, 0, 0, 0, 0, 0);
ObjectSetText (ObjName,"g",150, "Webdings", LightSteelBlue);
ObjectSet (ObjName, OBJPROP_CORNER,0);
ObjectSet (ObjName, OBJPROP_XDISTANCE, 0);
ObjectSet (ObjName, OBJPROP_YDISTANCE, 10);
ObjectSet (ObjName, OBJPROP_BACK, false);
}
string _symbol = Symbol();
slName = _symbol + "_" + slName;
tpName = _symbol + "_" + tpName;
oName = _symbol + "_" + oName;
// delete current currency global variables
GlobalVariableDel(oName);
GlobalVariableDel(slName);
GlobalVariableDel(tpName);
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
Comment("");
// delete lines
ObjectDelete(slName);
ObjectDelete(tpName);
ObjectDelete(oName);
// delete labels
ObjectDelete(Symbol() + "_lbl_StopLoss");
ObjectDelete(Symbol() + "_lbl_TakeProfit");
ObjectDelete(Symbol() + "_lbl_Order");
// delete panel
ObjectDelete("_panel_1");
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
comment = "";
// draw three lines automatically
DrawLines();
string lblNameO = "", lblNameTP = "", lblNameSL = "";
string lblCommentSL = "", lblCommentTP = "", lblCommentO = "";
double StopLossPrice = 0, TakeProfitPrice = 0, OrderPrice = 0;
double StopLossPips = 0, TakeProfitPips = 0;
int seconds = 0;
switch(Period()){
case 5:
seconds = 5 * 60;
break;
case 15:
seconds = 15 * 60;
break;
case 30:
seconds = 30 * 60;
break;
case 60:
seconds = 60 * 60;
break;
case 240:
seconds = 240 * 60;
break;
case 1440:
seconds = 1440 * 60;
break;
}
// check if no lines added with specified names
//
// STOPLOSS LINE
//
if (ObjectFind(slName) == -1){
comment = comment + "Add HORISONTAL LINE for StopLoss and name it as 'sl' \n";
} else {
StopLossPrice = NormalizeDouble(ObjectGet(slName, OBJPROP_PRICE1), Digits * BrokerDigitsMultiplier);
GlobalVariableSet(slName, StopLossPrice);
// change line style
ObjectSet(slName, OBJPROP_STYLE, STYLE_DASH);
ObjectSet(slName, OBJPROP_COLOR, slColor);
// add label
lblCommentSL = StringConcatenate("StopLoss: ", StopLossPrice);
lblNameSL = Symbol() + "_lbl_StopLoss";
if (ObjectFind(lblNameSL) == -1){
ObjectCreate(lblNameSL, OBJ_TEXT, 0, Time[0] + seconds * 20, StopLossPrice);
ObjectSetText(lblNameSL, lblCommentSL, labelFontSize, "Arial", slColor);
ObjectSet(lblNameSL, OBJPROP_BACK, true);
} else {
ObjectMove(lblNameSL, 0, Time[0] + seconds * 20, StopLossPrice);
ObjectSetText(lblNameSL, lblCommentSL, labelFontSize, "Arial", slColor);
}
}
//
// TAKEPROFIT LINE
//
if (ObjectFind(tpName) == -1){
comment = comment + "Add HORISONTAL LINE for TakeProfit and name it as 'tp' \n";
} else {
TakeProfitPrice = NormalizeDouble(ObjectGet(tpName, OBJPROP_PRICE1), Digits * BrokerDigitsMultiplier);
GlobalVariableSet(tpName, TakeProfitPrice);
// change line style
ObjectSet(tpName, OBJPROP_STYLE, STYLE_DASH);
ObjectSet(tpName, OBJPROP_COLOR, tpColor);
// add label
lblCommentTP = StringConcatenate("TakeProfit: ", TakeProfitPrice);
lblNameTP = Symbol() + "_lbl_TakeProfit";
if (ObjectFind(lblNameTP) == -1){
ObjectCreate(lblNameTP, OBJ_TEXT, 0, Time[0] + seconds * 20, TakeProfitPrice);
ObjectSetText(lblNameTP, lblCommentTP, labelFontSize, "Arial", tpColor);
ObjectSet(lblNameTP, OBJPROP_BACK, true);
} else {
ObjectMove(lblNameTP, 0, Time[0] + seconds * 20, TakeProfitPrice);
ObjectSetText(lblNameTP, lblCommentTP, labelFontSize, "Arial", tpColor);
}
}
//
// ORDER LINE
//
if (ObjectFind(oName) == -1){
comment = comment + "Add HORISONTAL LINE for Order and name it as 'order' \n";
} else {
// change line style
OrderPrice = NormalizeDouble(ObjectGet(oName, OBJPROP_PRICE1), Digits * BrokerDigitsMultiplier);
GlobalVariableSet(oName, OrderPrice);
ObjectSet(oName, OBJPROP_COLOR, oColor);
// add label
lblCommentO = StringConcatenate("Order: ", OrderPrice);
lblNameO = Symbol() + "_lbl_Order";
if (ObjectFind(lblNameO) == -1){
ObjectCreate(lblNameO, OBJ_TEXT, 0, Time[0] + seconds * 20, OrderPrice);
ObjectSetText(lblNameO, lblCommentO, labelFontSize, "Arial", oColor);
ObjectSet(lblNameO, OBJPROP_BACK, true);
} else {
ObjectMove(lblNameO, 0, Time[0] + seconds * 20, OrderPrice);
ObjectSetText(lblNameO, lblCommentO, labelFontSize, "Arial", oColor);
}
}
if ( (StopLossPrice > OrderPrice && TakeProfitPrice > OrderPrice) ||
(TakeProfitPrice < OrderPrice && StopLossPrice < OrderPrice)){
Comment ("WRONG LINES POSITION");
return (0);
}
// check for objects IF all lines are current then start to calculate
if (ObjectFind(slName) != -1 && ObjectFind(tpName) != -1 && ObjectFind(oName) != -1) {
//
// FIND STOPLOSS AND TAKEPROFIT FROM LINES OPTIONS
//
if (OrderPrice > StopLossPrice && OrderPrice < TakeProfitPrice){
StopLossPips = ((OrderPrice - StopLossPrice) / Point) / BrokerDigitsMultiplier;
TakeProfitPips = ((TakeProfitPrice - OrderPrice) / Point) / BrokerDigitsMultiplier;
}
if (OrderPrice < StopLossPrice && OrderPrice > TakeProfitPrice){
StopLossPips = ((StopLossPrice - OrderPrice) / Point) / BrokerDigitsMultiplier;
TakeProfitPips = ((OrderPrice - TakeProfitPrice) / Point) / BrokerDigitsMultiplier;
}
// calculate your risk in currency
double RiskInMoney = NormalizeDouble( (AccountEquity() * RiskPerOrder) / 100, 2);
// calculate optimal lot size
double LotSize = NormalizeDouble(RiskInMoney / StopLossPips / (GetPriceByVolume(1.0) * BrokerDigitsMultiplier), 2);
comment = comment + "----------------------------------------------------------------\n";
comment = comment + "RISK MANAGEMENT (LOT SIZE: " + DoubleToStr(LotSize, 2)+ ")\n";
comment = comment + "----------------------------------------------------------------\n";
comment = comment + "Your RISK: " + RiskPerOrder + "% (" + DoubleToStr(RiskInMoney, 2) + " " + AccountCurrency() + ")\n";
comment = comment + "Current StopLoss: " + DoubleToStr(StopLossPips, 1) + "p. (" + DoubleToStr(StopLossPips * GetPriceByVolume(LotSize) * BrokerDigitsMultiplier, 2) + " " + AccountCurrency() + ")\n";
//
// calculate TakePRofit
//
comment = comment + "Current TakeProfit: " + DoubleToStr(TakeProfitPips, 1)+ "p.(" + DoubleToStr(TakeProfitPips * GetPriceByVolume(LotSize) * BrokerDigitsMultiplier, 2) + " " + AccountCurrency() + ")\n";
//
// calculate Risk / Reward
//
double RiskReward = NormalizeDouble(TakeProfitPips / StopLossPips, 1);
string slResult = "";
if (RiskReward <= 0.9){
slResult = "BAD";
} else if (RiskReward >= 1 && RiskReward <= 1.5){
slResult = "poor";
} else if (RiskReward >= 1.6 && RiskReward <= 2.5 ){
slResult = "normal";
} else if (RiskReward >= 2.6 && RiskReward <= 3.5) {
slResult = "good";
}else if (RiskReward >= 3.6) {
slResult = "excelent";
}
if (slResult == "BAD"){
comment = comment + "Risk/Reward RATIO MUST BE AT LEAST 1/1 ! \n";
} else {
comment = comment + "Risk/Reward: 1 / " + DoubleToStr(RiskReward, 1) + " (" + slResult + ")\n";
}
comment = comment + "----------------------------------------------------------------\n";
comment = comment + "MONEY MANAGEMENT \n";
comment = comment + "----------------------------------------------------------------\n";
comment = comment + "RECOMENDED LOT SIZE: " + DoubleToStr(LotSize, 2) + " ( " + DoubleToStr(GetPriceByVolume(LotSize) * BrokerDigitsMultiplier, 2) + " " + AccountCurrency() + ")\n";
comment = comment + "\n";
comment = comment + Symbol() + " spread: " + DoubleToStr(MarketInfo(Symbol(), MODE_SPREAD) / BrokerDigitsMultiplier, 1) + "\n";
// comment = comment + "Lot price (0.01): " + DoubleToStr(GetPriceByVolume(0.01) * BrokerDigitsMultiplier, 4) + "\n";
// comment = comment + "Lot price (0.1): " + DoubleToStr(GetPriceByVolume(0.1) * BrokerDigitsMultiplier, 4) + "\n";
// comment = comment + "Lot price (1.0): " + DoubleToStr(GetPriceByVolume(1.0) * BrokerDigitsMultiplier, 4) + "\n";
comment = comment + "Leverage: 1:" + AccountLeverage() + "\n";
comment = comment + "Balance: " + DoubleToStr(AccountBalance(), 2) + " (Equity: " + DoubleToStr(AccountEquity(), 2) + ")\n";
}
Comment(comment);
return(0);
}
//+------------------------------------------------------------------+
void DrawLines(){
double openPrice = 0;
if (ObjectFind("s") != -1){
openPrice = NormalizeDouble(ObjectGet("s", OBJPROP_PRICE1), Digits * BrokerDigitsMultiplier);
ObjectCreate(slName, OBJ_HLINE, 0, 0, openPrice - 20 * BrokerDigitsMultiplier * Point);
ObjectSet(slName, OBJPROP_BACK, true);
ObjectCreate(tpName, OBJ_HLINE, 0, 0, openPrice + 40 * BrokerDigitsMultiplier * Point);
ObjectSet(tpName, OBJPROP_BACK, true);
ObjectCreate(oName, OBJ_HLINE, 0, 0, openPrice);
ObjectSet(oName, OBJPROP_BACK, true);
ObjectDelete("s");
// delete current currency global variables
GlobalVariableDel(oName);
GlobalVariableDel(slName);
GlobalVariableDel(tpName);
} else if (ObjectFind("s") == -1 && GlobalVariableCheck(oName) == true){
ObjectCreate(slName, OBJ_HLINE, 0, 0, GlobalVariableGet(slName));
ObjectSet(slName, OBJPROP_BACK, true);
ObjectCreate(tpName, OBJ_HLINE, 0, 0, GlobalVariableGet(tpName));
ObjectSet(tpName, OBJPROP_BACK, true);
ObjectCreate(oName, OBJ_HLINE, 0, 0, GlobalVariableGet(oName));
ObjectSet(oName, OBJPROP_BACK, true);
}
}
double GetPriceByVolume(double OrderVolume){
double tickPrice = MarketInfo(Symbol(), MODE_TICKVALUE);
double price = NormalizeDouble((OrderVolume * tickPrice) / 1.0, 2);
//debug ("Price of ", OrderVolume + " is " + DoubleToStr(price, 2));
return (price);
}
Comments