liqui: rounding in amountToPrecision() leads to InsufficientFunds exception
See original GitHub issueBasically, createLimitSellOrder('BTC/USDT', 0.00206404549, 10000)
results in InsufficientFunds
exception as amountToPrecision
rounds amount up to 0.00206405.
The following in the base class fixes the issue:
this.amountToPrecision = function (symbol, amount) {
//return parseFloat (amount).toFixed (this.markets[symbol].precision.amount)
return this.truncate(amount, this.markets[symbol].precision.amount)
}
At the same time I’m a bit unsure to submit a PR because I’m bothered with the following questions:
-
I see several places in code where
feeToPrecision()
andcostToPrecision()
were overridden in a child’s class with a similar fix. At the same time, it looks more natural to me if the base class contains the code with truncation so there is no need to override. Why it’s not the case? -
What’s the convention for passing
amount
? Those overrides doparseFloat(amount)
before truncation. Is it expected thatamount
might be a String as well? I see thattruncate
convertsamount
to a String anyway down the road.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:1
- Comments:5 (5 by maintainers)
Top GitHub Comments
Hi, @mkutny !
Thx for opening this issue!
In general, we need proper values for these entities:
Unfortunately, some exchanges round these values and some exchanges truncate them inside their engines. So, any of those values upon any stage of fee calculation can be either truncated or rounded by the exchange. And we don’t know beforehand what an exchange will do, because those guys never document their exact formulas for calculating fee precisions. This is very frustrating, because they make millions on traders, and they don’t even bother to document their engines in a financially-sound way.
So we had to reverse-engineer it. We did that by placing market-making orders (to guarantee the exact price for which an order is closed). Then we waited for the order to close. And after that we did calculations on our side based on expected fees and rounding/truncation rules and compared the balance differences. If a balance difference was the same as expected, we carried that we have the calculation done right and fees were applied in correct amounts to correct sides. The balance difference has to be compared with respect to truncation or rounding of amount/price/cost and fee.
There’s even more to it: some exchanges apply fees to this or that side of your balance (base or quote currency of the pair), depending on the side of your trade (Poloniex), whereas other exchanges always apply fees to quote side (Bittrex, Liqui), or always to the base side of the pair. And some of them allow to specify the desired fee side (Kraken).
So, we had to test all cases, namely both sell and buy orders to compare balances in all these cases. We did that for several exchanges, and Liqui was among them. This is why some exchanges use the rounding in *toPrecision methods (like bittrex and Liqui) and the other use truncation (like Kraken).
As the user might pass a string, we do the parsing/type-conversion as well. That is, until we obtain a fixed-point solution.
I hope it does answer your question… Let us know what you think of it, plz.
The source of the test is:
The above code snippet may be missing some non-copied methods, but the general structure of it should be clear. Standing by to hear more from you on this.