Download MetaTrader 5

How does TICKVALUE work?

To add comments, please log in or register
brettosm8
241
brettosm8  

Hi there,

There is this code from http://www.earnforex.com/position-size-calculator. Is the function that calculate risk and position size from their indicator.

void CalculateRiskAndPositionSize()
{
   if (!UseMoneyInsteadOfPercentage) RiskMoney = Size * Risk / 100;
   else RiskMoney = MoneyRisk;
   ObjectSetText("RiskMoney", "Risk, money:  " + DoubleToStr(RiskMoney, 2), font_size, font_face, font_color);

   double UnitCost = MarketInfo(Symbol(), MODE_TICKVALUE);
   double TickSize = MarketInfo(Symbol(), MODE_TICKSIZE);
   
   if ((StopLoss != 0) && (UnitCost != 0) && (TickSize != 0)) PositionSize = RiskMoney / (StopLoss * UnitCost / TickSize);
   
   ObjectSetText("PositionSize", "Pos. Size:    " + DoubleToStr(PositionSize, 2), font_size + 1, font_face, ps_font_color);

}

Wlhat is the purpose of the TICKSIZE? On XXXJPY it returns .001 but on other pairs it returns 0. The help doco says it returns the tick size in the quote currency. I thought that'd mean it returns .001 or .0001. Is this not the case? If not, how is it being used above? I have attached the full .mq4 file just in case.

Thanks.

P.S. The full .mq4 file code is included below just in case.

//+------------------------------------------------------------------+
//|                                       PositionSizeCalculator.mq4 |
//|                             Copyright © 2012-2013, Andriy Moraru |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2012-2013, Andriy Moraru"
#property link      "http://www.earnforex.com"

/*
   Calculates position size based on account balance/equity,
   currency, currency pair, given entry level, stop-loss level
   and risk tolerance (set either in percentage points or in base currency).
*/

#property indicator_chart_window

extern double EntryLevel = 0;
extern double StopLossLevel = 0;
extern double TakeProfitLevel = 0; // Optional
extern double Risk = 1; // Risk tolerance in percentage points
extern double MoneyRisk = 0; // Risk tolerance in base currency
extern bool UseMoneyInsteadOfPercentage = false;
extern bool UseEquityInsteadOfBalance = false;
extern bool DeleteLines = false; // If true, will delete lines on deinitialization. Otherwise will leave lines, so levels can be restored.
extern bool UseAskBidForEntry = false; // If true, Entry level will be updated to current Ask/Bid price automatically.

extern color font_color = LightBlue;
extern color ps_font_color = Red;
extern int font_size = 12;
extern string font_face = "Courier";
extern int corner = 0; //0 - for top-left corner, 1 - top-right, 2 - bottom-left, 3 - bottom-right
extern int distance_x = 10;
extern int distance_y = 15;
extern color entry_line_color = Blue;
extern color stoploss_line_color = Lime;
extern color takeprofit_line_color = Yellow;

string SizeText;
double Size, RiskMoney;
double PositionSize;
double StopLoss;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   if (ObjectFind("EntryLine") > -1) EntryLevel = ObjectGet("EntryLine", OBJPROP_PRICE1);
   if (ObjectFind("StopLossLine") > -1) StopLossLevel = ObjectGet("StopLossLine", OBJPROP_PRICE1);
   if (ObjectFind("TakeProfitLine") > -1) TakeProfitLevel = ObjectGet("TakeProfitLine", OBJPROP_PRICE1);
   
   if ((EntryLevel == 0) && (StopLossLevel == 0))
   {
      Print(Symbol() + ": Entry and Stop-Loss levels not given. Using local values.");
      EntryLevel = High[0];
      StopLossLevel = Low[0];
      if (EntryLevel == StopLossLevel) StopLossLevel -= Point;
   }
   if (EntryLevel - StopLossLevel == 0)
   {
      Alert("Entry and Stop-Loss levels should be different and non-zero.");
      return(-1);
   }

   if (UseAskBidForEntry)
   {
      RefreshRates();
      if ((Ask > 0) && (Bid > 0))
      {
         // Long entry
         if (StopLossLevel < Bid) EntryLevel = Ask;
         // Short entry
         else if (StopLossLevel > Ask) EntryLevel = Bid;
      }
   }

   ObjectCreate("EntryLevel", OBJ_LABEL, 0, 0, 0);
   ObjectSet("EntryLevel", OBJPROP_CORNER, corner);
   ObjectSet("EntryLevel", OBJPROP_XDISTANCE, distance_x);
   ObjectSet("EntryLevel", OBJPROP_YDISTANCE, distance_y);
   ObjectSetText("EntryLevel", "Entry Lvl:    " + DoubleToStr(EntryLevel, Digits), font_size, font_face, font_color);

   if (ObjectFind("EntryLine") == -1) 
   {
      ObjectCreate("EntryLine", OBJ_HLINE, 0, Time[0], EntryLevel);
      ObjectSet("EntryLine", OBJPROP_STYLE, STYLE_SOLID);
      ObjectSet("EntryLine", OBJPROP_COLOR, entry_line_color);
      ObjectSet("EntryLine", OBJPROP_WIDTH, 1);
   }

   ObjectCreate("StopLoss", OBJ_LABEL, 0, 0, 0);
   ObjectSet("StopLoss", OBJPROP_CORNER, corner);
   ObjectSet("StopLoss", OBJPROP_XDISTANCE, distance_x);
   ObjectSet("StopLoss", OBJPROP_YDISTANCE, distance_y + 15);
   ObjectSetText("StopLoss", "Stop-Loss:    " + DoubleToStr(StopLossLevel, Digits), font_size, font_face, font_color);
      
   if (ObjectFind("StopLossLine") == -1)
   {
      ObjectCreate("StopLossLine", OBJ_HLINE, 0, Time[0], StopLossLevel);
      ObjectSet("StopLossLine", OBJPROP_STYLE, STYLE_SOLID);
      ObjectSet("StopLossLine", OBJPROP_COLOR, stoploss_line_color);
      ObjectSet("StopLossLine", OBJPROP_WIDTH, 1);
   }
   StopLoss = MathAbs(EntryLevel - StopLossLevel);
   
   if (!UseMoneyInsteadOfPercentage)
   {
      ObjectCreate("Risk", OBJ_LABEL, 0, 0, 0);
      ObjectSet("Risk", OBJPROP_CORNER, corner);
      ObjectSet("Risk", OBJPROP_XDISTANCE, distance_x);
      ObjectSet("Risk", OBJPROP_YDISTANCE, distance_y + 30);
      ObjectSetText("Risk", "Risk:         " + DoubleToStr(Risk, 2) + "%", font_size, font_face, font_color);
   }
   
   if (UseEquityInsteadOfBalance)
   {
      SizeText = "Equity";
      Size = AccountEquity();
   }
   else
   {
      SizeText = "Balance";
      Size = AccountBalance();
   }
   ObjectCreate("AccountSize", OBJ_LABEL, 0, 0, 0);
   ObjectSet("AccountSize", OBJPROP_CORNER, corner);
   ObjectSet("AccountSize", OBJPROP_XDISTANCE, distance_x);
   ObjectSet("AccountSize", OBJPROP_YDISTANCE, distance_y + 45);
   ObjectSetText("AccountSize", "Acc. " + SizeText + ": " + DoubleToStr(Size, 2), font_size, font_face, font_color);
   
   ObjectCreate("RiskMoney", OBJ_LABEL, 0, 0, 0);
   ObjectSet("RiskMoney", OBJPROP_CORNER, corner);
   ObjectSet("RiskMoney", OBJPROP_XDISTANCE, distance_x);
   ObjectSet("RiskMoney", OBJPROP_YDISTANCE, distance_y + 60);

   ObjectCreate("PositionSize", OBJ_LABEL, 0, 0, 0);
   ObjectSet("PositionSize", OBJPROP_CORNER, corner);
   ObjectSet("PositionSize", OBJPROP_XDISTANCE, distance_x);
   ObjectSet("PositionSize", OBJPROP_YDISTANCE, distance_y + 75);

   if (TakeProfitLevel > 0) // Show TP line and RR ratio only if TakeProfitLevel input parameter is set by user or found via chart object.
   {
      ObjectCreate("TakeProfit", OBJ_LABEL, 0, 0, 0);
      ObjectSet("TakeProfit", OBJPROP_CORNER, corner);
      ObjectSet("TakeProfit", OBJPROP_XDISTANCE, distance_x);
      ObjectSet("TakeProfit", OBJPROP_YDISTANCE, distance_y + 90);
      ObjectSetText("TakeProfit", "Take-Profit:  " + DoubleToStr(TakeProfitLevel, Digits), font_size, font_face, font_color);

      if (ObjectFind("TakeProfitLine") == -1) 
      {
         ObjectCreate("TakeProfitLine", OBJ_HLINE, 0, Time[0], TakeProfitLevel);
         ObjectSet("TakeProfitLine", OBJPROP_STYLE, STYLE_SOLID);
         ObjectSet("TakeProfitLine", OBJPROP_COLOR, takeprofit_line_color);
         ObjectSet("TakeProfitLine", OBJPROP_WIDTH, 1);
      }
   
      ObjectCreate("RR", OBJ_LABEL, 0, 0, 0);
      ObjectSet("RR", OBJPROP_CORNER, corner);
      ObjectSet("RR", OBJPROP_XDISTANCE, distance_x);
      ObjectSet("RR", OBJPROP_YDISTANCE, distance_y + 105);
      ObjectSetText("RR", "Reward/Risk:  " + DoubleToStr(MathAbs((TakeProfitLevel - EntryLevel) / (EntryLevel - TakeProfitLevel)), 1), font_size, font_face, takeprofit_line_color);
   }
   
   CalculateRiskAndPositionSize();

   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
   ObjectDelete("EntryLevel");
   if (DeleteLines) ObjectDelete("EntryLine");
   ObjectDelete("StopLoss");
   if (DeleteLines) ObjectDelete("StopLossLine");
   if (!UseMoneyInsteadOfPercentage) ObjectDelete("Risk"); // Otherwise wasn't created.
   ObjectDelete("AccountSize");
   ObjectDelete("RiskMoney");
   ObjectDelete("PositionSize");
   if (TakeProfitLevel > 0)
   {
      ObjectDelete("TakeProfit");
      if (DeleteLines) ObjectDelete("TakeProfitLine");
      ObjectDelete("RR");
   }
   return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   double tEntryLevel, tStopLossLevel, tTakeProfitLevel;
   // Update Entry to Ask/Bid if needed.
   if (UseAskBidForEntry)
   {
      RefreshRates();
      if ((Ask > 0) && (Bid > 0))
      {
         tStopLossLevel = ObjectGet("StopLossLine", OBJPROP_PRICE1);
         // Long entry
         if (tStopLossLevel < Bid) tEntryLevel = Ask;
         // Short entry
         else if (tStopLossLevel > Ask) tEntryLevel = Bid;
         ObjectSet("EntryLine", OBJPROP_PRICE1, tEntryLevel);
      }
   }
   
   if (EntryLevel - StopLossLevel == 0) return(0);

   // If could not find account currency, probably not connected.
   if (AccountCurrency() == "") return(0);

   tEntryLevel = ObjectGet("EntryLine", OBJPROP_PRICE1);
   tStopLossLevel = ObjectGet("StopLossLine", OBJPROP_PRICE1);
   tTakeProfitLevel = ObjectGet("TakeProfitLine", OBJPROP_PRICE1);
   ObjectSetText("EntryLevel", "Entry Lvl:    " + DoubleToStr(tEntryLevel, Digits), font_size, font_face, font_color);
   ObjectSetText("StopLoss", "Stop-Loss:    " + DoubleToStr(tStopLossLevel, Digits), font_size, font_face, font_color);
   if (tTakeProfitLevel > 0) ObjectSetText("TakeProfit", "Take-Profit:  " + DoubleToStr(tTakeProfitLevel, Digits), font_size, font_face, font_color);

   StopLoss = MathAbs(tEntryLevel - tStopLossLevel);

   if (tTakeProfitLevel > 0)
   {
      string RR;
      // Have valid take-profit level that is above entry for SL below entry, or below entry for SL above entry.
      if (((tTakeProfitLevel > tEntryLevel) && (tEntryLevel > tStopLossLevel)) || ((tTakeProfitLevel < tEntryLevel) && (tEntryLevel < tStopLossLevel)))
         RR = DoubleToStr(MathAbs((tTakeProfitLevel - tEntryLevel) / StopLoss), 1);
      else RR = "Invalid TP.";
      ObjectSetText("RR", "Reward/Risk:  " + RR, font_size, font_face, takeprofit_line_color);
   }
   
   if (UseEquityInsteadOfBalance) Size = AccountEquity();
   else Size = AccountBalance();
   ObjectSetText("AccountSize", "Acc. " + SizeText + ": " + DoubleToStr(Size, 2), font_size, font_face, font_color);

   CalculateRiskAndPositionSize();

   return(0);
}

//+------------------------------------------------------------------+
//| Calculates risk size and position size. Sets object values.      |
//+------------------------------------------------------------------+
void CalculateRiskAndPositionSize()
{
   if (!UseMoneyInsteadOfPercentage) RiskMoney = Size * Risk / 100;
   else RiskMoney = MoneyRisk;
   ObjectSetText("RiskMoney", "Risk, money:  " + DoubleToStr(RiskMoney, 2), font_size, font_face, font_color);

   double UnitCost = MarketInfo(Symbol(), MODE_TICKVALUE);
   double TickSize = MarketInfo(Symbol(), MODE_TICKSIZE);
   
   if ((StopLoss != 0) && (UnitCost != 0) && (TickSize != 0)) PositionSize = RiskMoney / (StopLoss * UnitCost / TickSize);
   
   ObjectSetText("PositionSize", "Pos. Size:    " + DoubleToStr(PositionSize, 2), font_size + 1, font_face, ps_font_color);

}
//+------------------------------------------------------------------+
Keith Watford
Moderator
10566
Keith Watford  
brad:

Hi there,

There is this code from http://www.earnforex.com/position-size-calculator. Is the function that calculate risk and position size from their indicator.

Wlhat is the purpose of the TICKSIZE? On XXXJPY it returns .001 but on other pairs it returns 0. The help doco says it returns the tick size in the quote currency. I thought that'd mean it returns .001 or .0001. Is this not the case? If not, how is it being used above? I have attached the full .mq4 file just in case.

Thanks.

P.S. The full .mq4 file code is included below just in case.

The help doco says it returns the tick size in the quote currency.

No it doesn't

You are confusing TickSize and TickValue

Keith Watford
Moderator
10566
Keith Watford  
brad:

Hi there,

There is this code from http://www.earnforex.com/position-size-calculator. Is the function that calculate risk and position size from their indicator.

Wlhat is the purpose of the TICKSIZE? On XXXJPY it returns .001 but on other pairs it returns 0. The help doco says it returns the tick size in the quote currency. I thought that'd mean it returns .001 or .0001. Is this not the case? If not, how is it being used above? I have attached the full .mq4 file just in case.

Thanks.

P.S. The full .mq4 file code is included below just in case.


Show your code that returns a value for ticksize

If it only prints to 4 digits, what would 0.00001 return?

brettosm8
241
brettosm8  

Hi there,

This is what my code returns for tick size. Note: I had to update my build due to new release from broker.

The doco says tick size is "Tick size in points".

For YEN pairs it is .001 and for others it is different as shown below.

Can someone please tell me this is used to calculate position size in the first post? As I'm not a programmer am having difficult getting my head around this..

2014.03.18 23:56:43.527 MyScript EURJPY,Daily: Pair: EURJPY
2014.03.18 23:56:43.527 MyScript EURJPY,Daily: Tick size: 0.001
2014.03.18 23:56:43.527 MyScript EURJPY,Daily: Tick value: 1.080660499697415
        
2014.03.18 23:56:30.202 MyScript USDJPY,Daily: Pair: USDJPY
2014.03.18 23:56:30.202 MyScript USDJPY,Daily: Tick size: 0.001
2014.03.18 23:56:30.202 MyScript USDJPY,Daily: Tick value: 1.080788975952445
        
2014.03.18 23:56:08.416 MyScript AUDUSD,Daily: Pair: AUDUSD
2014.03.18 23:56:08.416 MyScript AUDUSD,Daily: Tick size: 1e-005.0
2014.03.18 23:56:08.416 MyScript AUDUSD,Daily: Tick value: 1.097441863017307
        
2014.03.18 23:55:52.910 MyScript EURGBP,Daily: Pair: EURGBP
2014.03.18 23:55:52.910 MyScript EURGBP,Daily: Tick size: 1e-005.0
2014.03.18 23:55:52.910 MyScript EURGBP,Daily: Tick value: 1.81942
        
2014.03.18 23:50:20.682 MyScript EURUSD,Daily: Pair: EURUSD
2014.03.18 23:50:20.682 MyScript EURUSD,Daily: Tick size: 1e-005.0
2014.03.18 23:50:20.682 MyScript EURUSD,Daily: Tick value: 1.097815347458558

Thanks!

James Hodges
4375
James Hodges  

If you just try to print the ticksize variable with the print function you will get the 1e-005.0

However if you will print it using DoubleToString(TickSize,digits) you will get the 0.00001.

This is the yen

brettosm8
241
brettosm8  

Jimdandy, haven't I watched youtube vids of yours?!

I've updated the TICKSIZE with DoubletoStr.

When I drop the script on EURUSD this is the output.

"AUDUSD:" should read "AUDUSD Ask Price".

The Position Size Calculator online (http://www.earnforex.com/position-size-calculator) where I got the code from outputs:

The position size in my output is .003 whereas online it's .274.

The code I used to generate my results are below:

double RiskPercent=.03;
double RiskPips=50;
double RiskMoney=5000*RiskPercent;

double TickSize=0;
double UnitCost=0;
double PositionSize=0;

void CalculatePositionSize()
   {    
    UnitCost=MarketInfo(Symbol(),MODE_TICKVALUE);
    TickSize=MarketInfo(Symbol(),MODE_TICKSIZE);
    PositionSize = (RiskMoney / (RiskPips * UnitCost / TickSize))*100;//Multiplied by 100 to move decimal to left 2 places.
    Print("Pair: ",Symbol());
    Print("Tick value: ", DoubleToStr(UnitCost,Digits));
    Print("Tick size: ",DoubleToStr(TickSize,Digits));
    Print("AUDUSD: ",MarketInfo("AUDUSD",MODE_ASK));
    Print("PositionSize: ", DoubleToStr(PositionSize,3));
    //where RiskMoney = The amount of money being risked on the trade.
    //StopLoss = RiskPips i.e. The number of pips between the EntryLevel and stop-loss level.
    //UnitCost = The tick value in the deposit currenty
    //TickSize = The tick size in points.
      
   }//End CalculatePositionSize

Can you please explain why my position size is not right i.e. the same as the online calculator?

Simon Gniadkowski
Moderator
18042
Simon Gniadkowski  
brad:

Jimdandy, haven't I watched youtube vids of yours?!

I've updated the TICKSIZE with DoubletoStr.

When I drop the script on EURUSD this is the output.

"AUDUSD:" should read "AUDUSD Ask Price".

The Position Size Calculator online (http://www.earnforex.com/position-size-calculator) where I got the code from outputs:

The position size in my output is .003 whereas online it's .274.

The code I used to generate my results are below:

Can you please explain why my position size is not right i.e. the same as the online calculator?

Shouldn't you be using TickValue instead of TickSize ?
whroeder1
16324
whroeder1  
  1. RaptorUK: Shouldn't you be using TickValue instead of TickSize ?
    No you must use BOTH value and size as a ratio
  2. PositionSize = (RiskMoney / (RiskPips * UnitCost / TickSize))*100;//Multiplied by 100 to move decimal to left 2 places.

    Don't hard code numbers (100 = 1/pips2dbl on JPY)

    RiskMoney = (AccountBalance * percent) = risk = RiskPips * pips2dbl * UnitCost / TickSize * lotsize

    RiskPips must include the spread because OrderOpenPrice - OrderStopLoss does.

    Solve for lotsize and normalize properly

Keith Watford
Moderator
10566
Keith Watford  
brad:

Jimdandy, haven't I watched youtube vids of yours?!

I've updated the TICKSIZE with DoubletoStr.

When I drop the script on EURUSD this is the output.

"AUDUSD:" should read "AUDUSD Ask Price".

The Position Size Calculator online (http://www.earnforex.com/position-size-calculator) where I got the code from outputs:

The position size in my output is .003 whereas online it's .274.

The code I used to generate my results are below:

Can you please explain why my position size is not right i.e. the same as the online calculator?


      UnitCost=MarketInfo(Symbol(),MODE_TICKVALUE);
      TickSize=MarketInfo(Symbol(),MODE_TICKSIZE);
      PositionSize=(RiskMoney)//Multiplied by 100 to move decimal to left 2 places.
      //What are we risking here? RiskMoney=5000*RiskPercent so 150
      PositionSize=(150/(RiskPips*UnitCost);
      //UnitCost=MarketInfo(Symbol(),MODE_TICKVALUE) which is the value of a 1 tick move in the account currency
      //RiskPips =50 so we now have
      PositionSize=(150/(50*1 tick move));
      //Hang on - a 1 tick move is not the same as a 1 pip move as the symbol has 5 digits. so we now have
      PositionSize=(150/(5*1 pip move);
      //So we obviously have to multip[ly this value by 10
      PositionSize=(150/(5*1 pip move/TickSize)*100;
      //TickSize is 0.00001, divide 5 by 0.00001 and you end up with 500,000
      //Multiply by 100 and you are now at 5,000
      PositionSize=(150/(5,000*1 pip move);
      //You intended to work out the position size for a 50 pip move, but calculated for a 5,000 pip move
      //100 times bigger so your calculations will arrive at the online calculator's vaue/100
      
brettosm8
241
brettosm8  
WHRoeder:
  1. RaptorUK: Shouldn't you be using TickValue instead of TickSize ?
    No you must use BOTH value and size as a ratio
  2. PositionSize = (RiskMoney / (RiskPips * UnitCost / TickSize))*100;//Multiplied by 100 to move decimal to left 2 places.

    Don't hard code numbers (100 = 1/pips2dbl on JPY)

    RiskMoney = (AccountBalance * percent) = risk = RiskPips * pips2dbl * UnitCost / TickSize * lotsize

    RiskPips must include the spread because OrderOpenPrice - OrderStopLoss does.

    Solve for lotsize and normalize properly

Are you saying the code should look like this?

double RiskPercent=.03;
double RiskPips=50;
double RiskMoney=5000*RiskPercent;

double TickSize=0;
double UnitCost=0;
double PositionSize=0;
double pips2dbl = 10;

UnitCost=MarketInfo(Symbol(),MODE_TICKVALUE);
TickSize=MarketInfo(Symbol(),MODE_TICKSIZE);
PositionSize = (RiskMoney / (RiskPips * UnitCost * pips2dbl / TickSize));

This produced the following results:

Or this?

double RiskPercent=.03;
double RiskPips=50;
double RiskMoney=5000*RiskPercent;

double TickSize=0;
double UnitCost=0;
double PositionSize=0;
double pips2dbl = 10;

UnitCost=MarketInfo(Symbol(),MODE_TICKVALUE);
TickSize=MarketInfo(Symbol(),MODE_TICKSIZE);
PositionSize = (RiskPips * UnitCost * pips2dbl / TickSize * RiskMoney);

Which produces..

Thanks.

whroeder1
16324
whroeder1  
brad:

Are you saying the code should look like this?

PositionSize = (RiskMoney / (RiskPips * UnitCost * pips2dbl / TickSize));

Or this?

PositionSize = (RiskPips * UnitCost * pips2dbl / TickSize * RiskMoney);

  1. I said solve for lotsize
    RiskMoney = (AccountBalance * percent) = risk = RiskPips * pips2dbl * UnitCost / TickSize * lotsize
    Doesn't that result in:
    lotsize = RiskMoney / (RiskPips * pips2dbl * UnitCost / Ticksize)
  2. double pips2dbl = 10;
    pips2dbl is not 10. On a 3/5 digit broker it is 10 * Point. Didn't you follow the link previously posted?
12
To add comments, please log in or register