python-bittrex icon indicating copy to clipboard operation
python-bittrex copied to clipboard

BUG FIX: decimal vs float. And timestamp issue!

Open JosephMRally opened this issue 7 years ago • 2 comments

HELLO, I am writing to share a bug and it's fix i found in the program. Issue is that '.json' converts string numbers to floats. Float's should NOT be used within financial applications! IEEE 754 is not for exact numerical representation but for approximate representation by representation numbers on a fractional base 2. Decimal should be used when exact representation is necessary. https://docs.python.org/2/library/decimal.html

Not using decimal over float can cause a situation when your balances or market value come back incorrect causing a failed trade. Note: decimals cannot be constructed correctly using .from_float method. float vs decimal...

floats:

 0.1*3
 answer: 0.30000000000000004 # incorrect

decimal:

Decimal("0.1") * Decimal("3")
answer: Decimal('0.3') # correct


BUG FIX:

 from decimal import Decimal
 ...
def using_requests(request_url, apisign):
    def dec(s): return Decimal(str(s)) # BUG FIX

    response = requests.get(
        request_url,
        headers={"apisign": apisign}
    ).json(parse_float=dec) # BUG FIX
    return response

JosephMRally avatar Dec 17 '17 18:12 JosephMRally

thanks for pointing this out. This seems like a good candidate for a pull request

ericsomdahl avatar Dec 18 '17 18:12 ericsomdahl

I have found another issue that I feel belongs in this library. two issues: (1) the library should convert timestamps -> datetime's. (2) bittrex returns an incorrect timestamp when milliseconds are all zero's. I am doing a sloppy recursive search for key names because bittrex documents are horrible and i don't know all the places across methods this occurs on. Attached is the code I am using to fix these issues...

# write own method to use against other datasources
def using_requests(request_url, apisign):
    def dec(s): return Decimal(str(s))

    response = requests.get( #timeout issue?
        request_url,
        headers={"apisign": apisign}
    ).json(parse_float=dec)

    # region fix and cast datetime fields
    # recursively search for specific keys to fix
    def fix_datetime(s):
        if s.find('.') == -1:
            s = s + ".000"  # BITTREX BUG FIX: they will strip out .000, add it back so we can process and keep consistent
        s = datetime.datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f')
        return s

    def datetime_fix_fx(node):
        datetime_fields = ['Created', 'TimeStamp'] # might be more?
        if isinstance(node, dict):
            for k,v in node.items():
                if isinstance(v, list):
                    for _ in v:
                        datetime_fix_fx(_)
                if isinstance(v, dict):
                    datetime_fix_fx(v) # call recursively
                elif isinstance(v, str) and k in datetime_fields:
                    node[k] = fix_datetime(v)

    datetime_fix_fx(response)
    # endregion

    return response

JosephMRally avatar Dec 28 '17 04:12 JosephMRally