Order price has more digits than symbol allows. Allowed 3 digits
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.
Replies
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
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
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