Calculations With Symbol.PipValue

Created at 23 Jul 2024, 15:17
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
AN

Andrelein

Joined 23.07.2024

Calculations With Symbol.PipValue
23 Jul 2024, 15:17


Hi,

I am trying to calculate the lot size depending on the given stop loss distance in pips and the given stop loss value in €.

 

Here I am setting up the given parameters and a default value for the lot size:

[Parameter("Stop Loss (Pips)", Group = "Protection", DefaultValue = 10.0)]
public double SLPips { get; set; }

[Parameter("Stop Loss (EUR)", Group = "Protection", DefaultValue = 50.0)]
public double SLEUR { get; set; }

[Parameter("Position Size", Group = "Protection", DefaultValue = 0.01)]
public double PosSize { get; set; }

 

In the following function I want to calculate the position size:

protected void CalculatePositionSize()
{
   double totalPips = SLPips + Symbol.Spread;
   
   PosSize = Math.Round(SLEUR / (Symbol.PipValue * totalPips),2);
}

 

When I use messageboxes to display the values behind these variables, they return this:

SLEUR = 50
totalPips = 10
Symbol.PipValue = 9,12

 

According to my calculations, the result should be something around 0.54 lot. However, when I use the messagebox to show the result it returns this:

PosSize = 54242

 

When I remove Symbol.PipValue from the calculation and replace it with 9.12 it returns the result 0.54 as expected. I created a new double variable, assigned Symbol.PipValue to it and used the new double variable in that calculation. It led to the same problem as using Sympol.PipValue directly. I even converted Symbol.PipValue to a string (because the messagebox returned 9,12 as expected) and converted that string back to a double to use this double in my calculations. Which also led to the same result as using Symbol.PipValue directly.

It seems like I am missing a very important piece of the puzzle. I would appreciate some ideas to try.

Thank you very  much.


@Andrelein
Replies

PanagiotisCharalampous
24 Jul 2024, 06:32

Hi there,

The result of the method is units, which is what you need as an input for all the order methods of the API. There is no reason to convert it to lots and then back to units. But if you need to convert it to Lots, you can use the Symbol.VolumeToQuantity() method.

Best regards,

Panagiotis


@PanagiotisCharalampous

Andrelein
24 Jul 2024, 06:50 ( Updated at: 24 Jul 2024, 10:44 )

RE: Calculations With Symbol.PipValue

PanagiotisCharalampous said: 

Hi there,

The result of the method is units, which is what you need as an input for all the order methods of the API. There is no reason to convert it to lots and then back to units. But if you need to convert it to Lots, you can use the Symbol.VolumeToQuantity() method.

Best regards,

Panagiotis

 

Thank you very much for this information. It is well appreciated. I will try that function. I also noticed that I was very ignorant regarding the messagebox respond. It actually has an E-05 at the end of the number, which basically means 0,0000912. But for some reason I ignored that fact.

 

When I tried to use the result in form of units, the following error occured:

24/07/2024 07:10:09.957 | → Order OID0 is REJECTED with error "Order volume 54217.50 must be multiple of stepVolume=1000.00."

 

I solved this problem by converting it back and forth with Math.Round()

PosSizeUnits = Math.Round(SLEUR / (Symbol.PipValue * totalPips), 2);
PosSizeLot = Math.Round(Symbol.VolumeInUnitsToQuantity(PosSizeUnits), 2);
PosSizeUnits = Symbol.QuantityToVolumeInUnits(PosSizeLot);

 

But I noticed that depending on the symbol the order volume has to be multiple of different step volumes. The code above will not work for US30 for example.

24/07/2024 09:01:56.395 | → Order OID0 is REJECTED with error "Order volume 4.25 must be multiple of stepVolume=1.00."

 

I decided to solve this problem this way:

if (Symbol.Name != "US30")
{
   PosSizeUnits = Math.Round(SLEUR / (Symbol.PipValue * totalPips), 2);
   PosSizeLot = Math.Round(Symbol.VolumeInUnitsToQuantity(PosSizeUnits), 2);
   PosSizeUnits = Symbol.QuantityToVolumeInUnits(PosSizeLot);
}
else
{
   PosSizeUnits = Math.Round(SLEUR / (Symbol.PipValue * totalPips), 2);
   PosSizeLot = Math.Round(Symbol.VolumeInUnitsToQuantity(PosSizeUnits), 0);
   PosSizeUnits = Symbol.QuantityToVolumeInUnits(PosSizeLot);
}

 

A more clean and universal approach would be nice, but this temporary solution does work.

Best regards


@Andrelein