Moneymanagement Tool as an indicator. How to get the information about the secondary currency?

 

Hi,

I would like to make an indicator which has two extern variables: risk (in %) and stop loss. The indicator should print the correct lotsize in the upper right corner of the chart. But there is one issue I can't solve. For example, my loss is larger when I lose 20 Pips with a EURGBP-trade than with a EURUSD-trade. Therefore the lotsize depends on the stoploss size and the currency-pair I want to trade. This indicator should work by receiving the currency-information from the chart. So when I determine the risk and stoploss size in pips, the indicator must show different lotsizes according to the currency.

And this is my problem. How can I receive the chart's secondary currency? I only know that I get the currency pair by using Symbol(). But how can I only get the secondary currency? Or is the only possibility to check for ALL symbols for example ending with "JPY"? Something like IF(CurrencyPair=="AUDJPY" || CurrencyPair=="CADJPY" || CurrencyPair=="EURJPY" || .....) ?

Or can I just say IF(CurrencyPair ending with "JPY") .... ? But I have no idea for the syntax, if this is generally possible.

This is what I have so far (I make it for a Euro based account, therefore I calculate everything to Euro):

int start()
  {
//----
   double MoneyRisk  = AccountBalance()*Risk*0.01;
   double PipValEUR  = MoneyRisk/StopLoss;
   double PipValUSD  = PipValEUR*iClose("EURUSD", PERIOD_M1, 0);
   double PipValCAD  = PipValEUR*iClose("EURCAD", PERIOD_M1, 0);
   double PipValJPY  = PipValEUR*iClose("EURJPY", PERIOD_M1, 0);
   double PipValGBP  = PipValEUR*iClose("EURGBP", PERIOD_M1, 0);
   double PipValCHF  = PipValEUR*iClose("EURCHF", PERIOD_M1, 0);
   double PipValNZD  = PipValEUR*iClose("EURNZD", PERIOD_M1, 0);
   double PipValAUD  = PipValEUR*iClose("EURAUD", PERIOD_M1, 0);
//----
   return(0);
  }
 

The formula I use is here.

Account_Balance*Risk*0.01/Stop__Loss/Pip_Value.

This is pretty close to yours, however we're calculating Pip_Values differently.

The way I think about it is, you have to get the value of the Tick. This is usually the value of a Point. But what you want is the value of a Pip. You cannot simply say Pip_Value = Tick_Value*10; Because this'll be good for 5_digits brokers but fail on 4_digits brokers. If you can determine a 5_digit broker vs a 4_digit broker then simply multiply the Tick_Value by 10 or 1 in-order to get the Pip_Value. If you look around the forum, you'll find different ways of doing it. Some people divide and others multiply. Use a method which is easier for you to remember.

Once you've got the correct lotsize from the above equation, then you'll need to drop-off any floating decimals to ensure it goes into the broker lot_steps perfectly. Example: MathFloor( myRiskLots / Symbol_Lot_Step) * Symbol_Lot_Step;

You get Tick_Values via the MarketInfo(); Example double Tick_Value=MarketInfo(Symbol(),MODE_TICKVALUE);

{Added} MarketInfo for Symbols outside the testing Symbol does not work in mt4 strategy tester.

 
Thanks, ubzen! I did not know that there is something like TICKVALUE. I try!
 

You DON'T use tickValue alone, only as a ratio
AccountBalance() * Percentage = Risk = (OrderOpenPrice() - OrderStopLoss())*DIR * OrderLotsize() * DeltaPerLot()

 

Done! Works on 4 and 5 Digit brokers. Your information about TICKVALUE helped me a lot. If you could have a look at the code? Is there anything to improve? The only thing I don't like is to use absolute values for OBJPROP_XDISTANCE. I would rather like to make it relative to the window. Monitors have different sizes and therefore absolute values are not the best solution...

//+------------------------------------------------------------------+
//|                                              Moneymanagement.mq4 |
//|                                               Copyright 2013, MR |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2013, MR"
#property link      ""

#property indicator_chart_window
//--- input parameters
extern int  Risk=5;
extern int  StopLoss=15;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   for(int iObj = ObjectsTotal() - 1; iObj >= 0; iObj--)
   {
      string name = ObjectName(iObj);
      ObjectDelete(name);
   }
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
//----
   double MoneyRisk  = AccountBalance()*Risk*0.01;
   double PipValue   = MoneyRisk/StopLoss;
   if (Digits==5 || Digits ==3)
   {
      PipValue = PipValue/(MarketInfo(Symbol(), MODE_TICKVALUE)*10);
   }
   else
   {
       PipValue = PipValue/MarketInfo(Symbol(), MODE_TICKVALUE);
   }
   if (ObjectFind("Acc") == -1)
   {
      ObjectCreate("Acc", OBJ_LABEL, 0, 0, 0);
      ObjectSet("Acc", OBJPROP_XDISTANCE, 1350);
      ObjectSet("Acc", OBJPROP_YDISTANCE, 0);
      ObjectSetText("Acc", "Account: "+ DoubleToStr(AccountBalance(), 2)+" "+AccountCurrency(), 10, "Verdana", White);
   }
   if (ObjectFind("RiskP") == -1)
   {
      ObjectCreate("RiskP", OBJ_LABEL, 0, 0, 0);
      ObjectSet("RiskP", OBJPROP_XDISTANCE, 1350);
      ObjectSet("RiskP", OBJPROP_YDISTANCE, 15);
      ObjectSetText("RiskP", "Risk in %: "+ Risk, 10, "Verdana", White);
   }
   if (ObjectFind("RiskA") == -1)
   {
      ObjectCreate("RiskA", OBJ_LABEL, 0, 0, 0);
      ObjectSet("RiskA", OBJPROP_XDISTANCE, 1350);
      ObjectSet("RiskA", OBJPROP_YDISTANCE, 30);
      ObjectSetText("RiskA", "Risk in "+AccountCurrency()+": "+ DoubleToStr(MoneyRisk,2), 10, "Verdana", White);
   }
   if (ObjectFind("StopLoss") == -1)
   {
      ObjectCreate("StopLoss", OBJ_LABEL, 0, 0, 0);
      ObjectSet("StopLoss", OBJPROP_XDISTANCE, 1350);
      ObjectSet("StopLoss", OBJPROP_YDISTANCE, 45);
      ObjectSetText("StopLoss", "Stop Loss: "+ StopLoss+ " Pips", 10, "Verdana", White);
   }
   if (ObjectFind("Lotsize") == -1)
   {
      ObjectCreate("Lotsize", OBJ_LABEL, 0, 0, 0);
      ObjectSet("Lotsize", OBJPROP_XDISTANCE, 1350);
      ObjectSet("Lotsize", OBJPROP_YDISTANCE, 60);
      ObjectSetText("Lotsize", "Lots: "+DoubleToStr(PipValue, 2), 10, "Verdana", White);
   }
//----
   return(0);
  }
//+------------------------------------------------------------------+
 
Sorry William, I don't get the point.. What do you mean with "only as a ratio"? Your code is way too complex for a beginner like me to understand. Is there anything wrong with my code? I don't see problems right now.
 
mar: Done! Works on 4 and 5 Digit brokers. Your information about TICKVALUE helped me a lot. If you could have a look at the code? Is there anything to improve? The only thing I don't like is to use absolute values for OBJPROP_XDISTANCE. I would rather like to make it relative to the window. Monitors have different sizes and therefore absolute values are not the best solution...

I think Window_Corner would be your best bet. Example: https://www.mql5.com/en/code/10842. I do-not think there's any function which returns the maximum_XDistance, but I could be wrong.

mar: Sorry William, I don't get the point.. What do you mean with "only as a ratio"? Your code is way too complex for a beginner like me to understand. Is there anything wrong with my code? I don't see problems right now.

He's talking about this post Here:https://www.mql5.com/en/forum/127584. The poster is saying that sometimes the broker changes the "definition of a tick". Imagine a 4_Digit broker who changed the Tick on EurUsd from 0.0001 to 0.0002. Your current formula expects a Tick_Value of $10 ($10 for a Pip on Standard_Lot of 1). However the Tick_Value you get is $20. This causes you to take a Smaller LotSize for the same Distance.

If you're confused, don't worry, allot of people including me gets tripped-up by these money-management calculations. If you look at my codes, I do use the ratio (just to be safe), however, I leave it out the first time to avoid complexity.

 
mar: Sorry William, I don't get the point.. What do you mean with "only as a ratio"? Your code is way too complex
As in the code provided
    return(  MarketInfo(pair, MODE_TICKVALUE)
           / MarketInfo(pair, MODE_TICKSIZE) ); // Not Point.
That is too hard for you? Or is calling the function too hard?
 

Ok, now there is a little bit of light in the dark. I didn't know that a broker can change the tick value. Therefore I had no idea why this ratio is important.

So I better change the calculation for my pip value.

@William: both ;) but with the knowledge about changing tick values it all makes sense to me.

 

ubzen, I used your advice with OBJPROP_CORNER. That exactly what I was looking for, works fine! But now there is one question left. I don't know if that is even possible. Maybe you had this problem before and have an idea. I print some labels at the right top corner. Although I use the chart shift there is the problem that the chart reaches into the labels sometimes. Is it somehow possible to locate the chart within the chart-window? For example when the chart is in the upper 50% of the window, I would print the labels at the lower right corner.

Checking the highest high or lowest low of the last 10 bars would not help me because I don't know where they are located in relation to the whole chart window.

Maybe you have an idea?

 
Found something! WindowPriceMa()x and WindowPriceMin() could be what I need...
Reason: