-
Notifications
You must be signed in to change notification settings - Fork 134
Decimal support? #138
Comments
Is decimal support necessary? There's not really any math that's done in this library at all at the moment. It just makes requests and (at the moment) returns the raw response. So most of the time the results are returned as strings # Example response json
{'bid': '18629.0',
'timestamp': '1513589744.5260189',
'ask': '18630.0',
'mid': '18629.5',
'low': '18010'} |
@lhl: we are discussing it right now in the implementation of the new |
@bebosudo I tried to implement # r is a request.Response
result = r.json()
# eg. result = {'bid': 0.001} Note that 'bid' value is not a string!
decimal_bid = Decimal(result['bid'])
print(decimal_bid)
# 0.0009999999999999999999999999993 To fix this you would need to replace the The benefits of from decimal import Decimal
print(Decimal('0.01'))
print(Decimal(0.01))
print(Decimal(0.01)/Decimal('0.01')-1) # error
print((Decimal(0.01)/Decimal('0.01')-1)*100) # error as %
f = float(0)
for i in range(10000000): # 10 million operations
f += 0.01
true_result = Decimal('10000000')*Decimal('0.01')
float_result = Decimal(f)
error = (true_result-float_result)/true_result
print(true_result)
print(float_result)
print(error)
# Output
# 0.01
# 0.01000000000000000020816681711721685132943093776702880859375
# 2.0816681712E-17
# 2.081668171200E-15
# 100000.00
# 99999.999986309689120389521121978759765625
# 1.369031087961047887802124023E-10 Even if you do 10 million additions, the error on floats is still 1 in 1e10. That's 1 tenth of a billionth. |
The solution is passing the
(BTW, which exchange does send data as float numbers?)
Well, if I'm dealing with my money, I care of it.
You don't need to go to millions to understand why floats are bad. Even if we produce an error in the order of 10^(-17) when dealing with something that can be really small such as cryptocurrencies, the overall result can be catastrophic for an end user using this library. |
Using |
@bebosudo Ok, a fair point. I still don't think the error from floats is a huge problem unless you're doing accounting and keeping track of peoples real money. I agree that decimal would be better, though I think there are some complications that would need to be resolved before we could use it. Take a look at this {'success': True,
'result': [{'Ask': 0.01664998,
'BaseVolume': 2772.17956679,
'MarketName': 'BTC-LTC',
'OpenSellOrders': 9647,
'Low': 0.01589002,
'Created': '2014-02-13T00:00:00',
'OpenBuyOrders': 7846,
'Bid': 0.01663114,
'PrevDay': 0.01613444,
'High': 0.0171071,
'Volume': 168102.39042146,
'TimeStamp': '2017-12-18T09:42:47.75',
'Last': 0.01663114}],
'message': ''} Other exchanges that do this are: CCEX, CoinCheck, Cryptopia, TheRockTrading. This is a potential problem with some of the new formatting code we're adding to the library at the moment. When we call response.json(parse_float=str, parse_int=str) or like this from decimal import Decimal
response.json(parse_float=Decimal, parse_int=Decimal) otherwise we're returning the results converted to floats, which are ever so slightly wrong. It could be convenient to switch to Decimal at some point in the future depending on what the library is used for. It would save users having to pass formatted results through an extra function before they could use it in calculations. |
IMHO the best thing would be to return a |
I was looking at various API libs and noticed that bitex doesn't seem to use decimal.Decimal() anywhere. How is math done accurately or is that something that's being punted on completely? (eg a quick search shows that balances simply get returned as string key/values?)
The text was updated successfully, but these errors were encountered: