Order price has more digits than symbol allows. Allowed 3 digits

Created at 13 Oct 2021, 12:56
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!
douglascvas's avatar

douglascvas

Joined 02.01.2018

Order price has more digits than symbol allows. Allowed 3 digits
13 Oct 2021, 12:56


Hi, I'm trying to open a pending order via OpenAPI using the ProtoOANewOrderReq but the request is failing with this error:

Order price = 131.07400024414062 has more digits than symbol allows. Allowed 3 digits

What does that mean? The ProtoOANewOrderReq object in Java expects a "double" as the type for the StopPrice, how am I supposed to specify how many digits it will send to the API? Also where does this amount of digits come from? I can't even find anything related in the documentation.

I really appreciate any help.

 


@douglascvas
Replies

amusleh
13 Oct 2021, 14:30

Hi,

The decimal places of your stop price must much with symbol digits.

You can get the symbol digits from ProtoOASymbol.


@amusleh

douglascvas
15 Oct 2021, 10:54 ( Updated at: 15 Oct 2021, 10:56 )

RE:

 amusleh said:

Hi,

The decimal places of your stop price must much with symbol digits.

You can get the symbol digits from ProtoOASymbol.

As I said, that's weird because the value is a double, so I don't understand why I need to round it before sending. Anyway, using bigdecimal fixes that one problem:

request.setStopPrice(BigDecimal.valueOf(order.getTargetPrice())
                    .setScale(symbol.getDigits(), RoundingMode.HALF_UP)
                    .doubleValue());

 

Now I get another one in the relative price. And that one I can't see how to fix

request.setRelativeStopLoss((long) (stopLossPips * symbol.getPipSize() * 100000));

That gives me this error:

Error:Relative stop loss has invalid precision

How can that be if the field is a Long? There is absolutely no way to set decimal precision. I don't understand what is going on.

The .proto file states this:

optional int64 relativeTakeProfit = 20; // Relative Take Profit that can be specified instead of the absolute one. Specified in 1/100000 of unit of a price. For BUY takeProfit = entryPrice + relativeTakeProfit, for SELL takeProfit = entryPrice - relativeTakeProfit.​

 


@douglascvas

amusleh
15 Oct 2021, 13:07

RE: RE:

douglascvas said:

 amusleh said:

Hi,

The decimal places of your stop price must much with symbol digits.

You can get the symbol digits from ProtoOASymbol.

As I said, that's weird because the value is a double, so I don't understand why I need to round it before sending. Anyway, using bigdecimal fixes that one problem:

request.setStopPrice(BigDecimal.valueOf(order.getTargetPrice())
                    .setScale(symbol.getDigits(), RoundingMode.HALF_UP)
                    .doubleValue());

 

Now I get another one in the relative price. And that one I can't see how to fix

request.setRelativeStopLoss((long) (stopLossPips * symbol.getPipSize() * 100000));

That gives me this error:

Error:Relative stop loss has invalid precision

How can that be if the field is a Long? There is absolutely no way to set decimal precision. I don't understand what is going on.

The .proto file states this:

optional int64 relativeTakeProfit = 20; // Relative Take Profit that can be specified instead of the absolute one. Specified in 1/100000 of unit of a price. For BUY takeProfit = entryPrice + relativeTakeProfit, for SELL takeProfit = entryPrice - relativeTakeProfit.​

 

Hi,

You should round the multiplication result before converting it back to long, ex:

        public static long GetRelativeFromPips(this ProtoOASymbol symbol, double pips)
        {
            var pipsInPrice = pips * symbol.GetPipSize();

            return (long)Math.Round(pipsInPrice * 100000, symbol.Digits);
        }

If you pass 10 pips for above method it will first multiply it by symbol pip size, for example EURUSD pip size is 0.0001, then it will multiply it to 100000 and then it rounds the multiplication result back to symbol digits.


@amusleh

douglascvas
19 Oct 2021, 01:02

RE: RE: RE:

amusleh said:

douglascvas said:

 amusleh said:

Hi,

The decimal places of your stop price must much with symbol digits.

You can get the symbol digits from ProtoOASymbol.

As I said, that's weird because the value is a double, so I don't understand why I need to round it before sending. Anyway, using bigdecimal fixes that one problem:

request.setStopPrice(BigDecimal.valueOf(order.getTargetPrice())
                    .setScale(symbol.getDigits(), RoundingMode.HALF_UP)
                    .doubleValue());

 

Now I get another one in the relative price. And that one I can't see how to fix

request.setRelativeStopLoss((long) (stopLossPips * symbol.getPipSize() * 100000));

That gives me this error:

Error:Relative stop loss has invalid precision

How can that be if the field is a Long? There is absolutely no way to set decimal precision. I don't understand what is going on.

The .proto file states this:

optional int64 relativeTakeProfit = 20; // Relative Take Profit that can be specified instead of the absolute one. Specified in 1/100000 of unit of a price. For BUY takeProfit = entryPrice + relativeTakeProfit, for SELL takeProfit = entryPrice - relativeTakeProfit.​

 

Hi,

You should round the multiplication result before converting it back to long, ex:

        public static long GetRelativeFromPips(this ProtoOASymbol symbol, double pips)
        {
            var pipsInPrice = pips * symbol.GetPipSize();

            return (long)Math.Round(pipsInPrice * 100000, symbol.Digits);
        }

If you pass 10 pips for above method it will first multiply it by symbol pip size, for example EURUSD pip size is 0.0001, then it will multiply it to 100000 and then it rounds the multiplication result back to symbol digits.

I tried that, but it did not work. Same problem. And it does not make sense to work anyway because the value is rounded when we convert to long.

I don't get though how can it complain about invalid precision on a int64/long number.


@douglascvas

amusleh
19 Oct 2021, 09:47

Hi,

Can you post the logs of what you sent to server? Maybe something is wrong with the data you are sending to server.

Post all the parameters that you sent for creating order, and which broker you were using?


@amusleh

douglascvas
20 Oct 2021, 13:26

RE:

amusleh said:

Hi,

Can you post the logs of what you sent to server? Maybe something is wrong with the data you are sending to server.

Post all the parameters that you sent for creating order, and which broker you were using?

 

Ahh I think I found the problem.

This is the payload that is being sent to the server:

com.xtrader.protocol.openapi.v2.ProtoOANewOrderReq
symbolId: 3   (EURJPY)
orderType: STOP
tradeSide: SELL
volume: 3100000
stopPrice: 132.874
timeInForce: GOOD_TILL_DATE
expirationTimestamp: 1800000
comment: "0||0||2b6a0cd8389d74b1660f70d509a103e4ebb7b238|59ca75e7-e503-4ba1-bbdd-758489b2d2e5"
label: "a83ffb14-5731-4ccc-894f-ae35c0b898f0"
relativeStopLoss: 434977
relativeTakeProfit: 9167142
guaranteedStopLoss: false
stopTriggerMethod: TRADE

 

-------

I noticed that if I send 434.977 it does not work, but if I send 434.9 it does. The problem is that I was multiplying by 100000 before rounding. But it looks like the server is only happy if I multiply after the rounding (what kinda makes sense).

pipSize = 0.01

symbolDigits = 3

stopLossPips = 434.977

pipSizeInPrice = 0.01 * 434.977 = 4.34977

 

Before:

round(4.34977 * 100000, 3) = 434977

 

After:

round(4.34977, 3) * 100000 = 4349

 

Thank you, @amusleh

 

 


@douglascvas