ccxt: Error using ccxt for testnet.bitmex.com private functions.

I’ve tried to use following code.

import ccxt exchanges = {‘bitmex’: ccxt.bitmex()} btmx = ccxt.bitmex({ ‘apiKey’: ‘bzHFktf887ap1OCtmAHPADGV’, ‘secret’:‘9rzLlTMjirx_Gh6OwaCDcpKFaxWJ3aEQiYuvUT4Z8LpHe_qB’, }) if ‘test’ in btmx.urls: btmx.urls[‘api’]=btmx.urls[‘test’] exchanges[‘bitmex’].urls[‘api’] = exchanges[‘bitmex’].urls[‘test’] print(btmx.fetch_balance())

But got following errors.

Traceback (most recent call last): File “C:\Python37\lib\site-packages\ccxt\base\exchange.py”, line 539, in fetch response.raise_for_status() File “C:\Python37\lib\site-packages\requests\models.py”, line 940, in raise_for_status raise HTTPError(http_error_msg, response=self) requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://testnet.bitmex.com/api/v1/instrument/activeAndIndices

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File “E:\python_work\bitmex_init_.py”, line 11, in <module> print(btmx.fetch_balance()) File “C:\Python37\lib\site-packages\ccxt\bitmex.py”, line 251, in fetch_balance self.load_markets() File “C:\Python37\lib\site-packages\ccxt\base\exchange.py”, line 1234, in load_markets markets = self.fetch_markets(params) File “C:\Python37\lib\site-packages\ccxt\bitmex.py”, line 171, in fetch_markets response = self.publicGetInstrumentActiveAndIndices(params) File “C:\Python37\lib\site-packages\ccxt\base\exchange.py”, line 435, in inner return entry(_self, **inner_kwargs) File “C:\Python37\lib\site-packages\ccxt\base\exchange.py”, line 458, in request return self.fetch2(path, api, method, params, headers, body) File “C:\Python37\lib\site-packages\ccxt\base\exchange.py”, line 454, in fetch2 return self.fetch(request[‘url’], request[‘method’], request[‘headers’], request[‘body’]) File “C:\Python37\lib\site-packages\ccxt\base\exchange.py”, line 551, in fetch self.handle_errors(http_status_code, http_status_text, url, method, headers, http_response, json_response, request_headers, request_body) File “C:\Python37\lib\site-packages\ccxt\bitmex.py”, line 1154, in handle_errors raise BadRequest(feedback) ccxt.base.errors.BadRequest: bitmex {“error”:{“message”:“This request has expired - expires is in the past. Current time: 1568479326”,“name”:“HTTPError”}}

  • OS: windows 10
  • Programming Language version: python 3.7.3
  • CCXT version: installed just now
  • Exchange: bitmex
  • Method: fetch_balance()

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 23 (11 by maintainers)

Most upvoted comments

@xinglong717

Your local time differs from BitMEX by -21 seconds

↑ This is self-explaining. Please, read this for more details: https://github.com/ccxt/ccxt/issues/4789

This should work:

import ccxt
exchange = ccxt.bitmex({
    'apiKey': 'YOUR_API_KEY',  # ←------------- EDIT HERE FOR YOUR KEYS
    'secret':'YOUR_SECRET',
    'enableRateLimit': True,
    'options': {
        # ↓ ADD THIS OPTION OR SYNCHRONIZE YOUR TIME
        # default value is 5 seconds, your time drifts by 21 seconds or more        
        'api-expires': 60, 
    },
})

if 'test' in exchange.urls:
    exchange.urls['api'] = exchange.urls['test']

print(exchange.fetch_balance())

↑ Does it work?

@xinglong717 ok, cool! Thx for reporting back! Cheers!

@xinglong717

# EXPLANATION

import ccxt
exchange = ccxt.bitmex({
    'apiKey': 'YOUR_API_KEY',  # ←------------- EDIT HERE FOR YOUR KEYS
    'secret':'YOUR_SECRET',
    'enableRateLimit': True,
})

if 'test' in exchange.urls:
    exchange.urls['api'] = exchange.urls['test']

try:
    exchange.load_markets ()
except Exception as e:
    error_message = str(e)
    print(error_message)
    if 'This request has expired' in error_message:
        bitmex_timestamp = int(''.join([s for s in error_message if s.isdigit()]))
        local_timestamp = exchange.seconds()
        print('BitMEX exchange time UTC: ', exchange.iso8601(bitmex_timestamp * 1000))
        print('Your Python time UTC: ', exchange.iso8601(local_timestamp * 1000))
        print('Your local time differs from BitMEX by ', local_timestamp - bitmex_timestamp, 'seconds')

↑ What does it say?

If I have proxy problem, how can this c# code working?

That C# code is working, because it has nothing to do with the problem that you have in Python.

It’s a problem accessing a different resource, not the /user/margin endpoint. You’ve posted it initially in your code, however, you’ve removed it later for some reason, but anyways ))

When you create an exchange instance, and then call any unified method, CCXT will load markets first and will cache those. The process is explained here:

That means it will first issue a different request to a different endpoint, different from the one you’re comparing to. That makes the comparison to the above C# code a bit irrelevant to the actual cause of the problem.

From your own output above you can see that when you call fetch_balance the first time – CCXT will first load those markets from this endpoint:

BitMEX replies with a 400 Bad Request, despite that it does open ok in your browser.

requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://testnet.bitmex.com/api/v1/instrument/activeAndIndices

And the details are:

ccxt.base.errors.BadRequest: bitmex {"error":{"message":"This request has expired - expires is in the past. Current time: 1568479326","name":"HTTPError"}}

In general, CCXT should not send that api-expires header for public requests, and this is an issue in CCXT that I’m going to fix shortly. However, that issue would not have caused this specific problen, if your eclipse/python environment was in timesync with BitMEX. Because, it’s obviously not, since BitMEX message says "This request has expired - expires is in the past. Current time: 1568479326". This is explained here:

If BitMEX says the api-expires header has expired, then it really means it. Your keys do work on my side with bitmex testnet and with the code I posted above. So, it’s something system-specific or configuration-specific. And this is very hard to debug, especially, not having the access to your system. In order to find the cause and to fix it we should take smallest steps possible, one at a time. So, I will upload a fix to BitMEX so that public requests get sent without a signature. However, the expectation is that it will not fully resolve the problem, because the api-expires issue will still come up later upon a subsequent call to the private balance endpoint. After that we will need you to update your version of CCXT and report back or confirm the expectation. If the error persists as expected, we will continue narrowing it down. I will get back to you shortly on this matter.

@xinglong717

following error occured.

The error occurred because you’ve copypasted the code blindly without reading it – you can’t copypaste it wiithout editing, you should use your own set of proxies there, and you should not mix CORS proxy with HTTPS/SOCKS proxies. This is documented in the Manual. Also, in the comments in the code snippet I’ve posted above it’s noted that those proxies won’t work – they’re just an example of how you should fill up your proxy settings for a HTTPS/SOCKS proxy, but you should put the IP addresses and ports of your own proxy there.

I’ve used C# raw code or java xChange library for bitmex private api connect. There is no any problem till now.

Can you post a short snippet of your c# code or your code that uses xChange, for comparison?

How can I use proxy for python ccxt request ?

Yep, you need to use exchange.proxy with a CORS type proxy or exchange.proxies if you use a HTTPS proxy or SOCKS, as described here:

import ccxt
exchange = ccxt.bitmex({
    'proxies': {
        'http': 'http://10.10.1.10:3128',  # these proxies won't work for you, they are here for example
        'https': 'https://10.10.1.10:1080',
    },
    'enableRateLimit': True,
    # other properties and options...
})

Let me know if that does not help.

@xinglong717 does this work with a CORS proxy:

import ccxt
btmx = ccxt.bitmex({
   'apiKey': 'bzHFktf887ap1OCtmAHPADGV',
   'secret':'9rzLlTMjirx_Gh6OwaCDcpKFaxWJ3aEQiYuvUT4Z8LpHe_qB',
   'enableRateLimit': True,
   'proxy': 'https://cors-anywhere.herokuapp.com/',
   'origin': 'bitmex',
})

if 'test' in btmx.urls:
    btmx.urls['api']=btmx.urls['test']
    btmx.urls['api'] = btmx.urls['test']

print(btmx.fetch_balance())

?

@xinglong717 can you verify it against a non-windows system to make sure that everything is ok? Also, are you sure that

And of course timezone is UTC.

?

Can you post your verbose request/response output, as described here:

?

import ccxt
btmx = ccxt.bitmex({
   'apiKey': 'bzHFktf887ap1OCtmAHPADGV',
   'secret':'9rzLlTMjirx_Gh6OwaCDcpKFaxWJ3aEQiYuvUT4Z8LpHe_qB',
   'enableRateLimit': True,
   'verbose': True,
})

if 'test' in btmx.urls:
    btmx.urls['api']=btmx.urls['test']
    btmx.urls['api'] = btmx.urls['test']

print('Current time:', btmx.iso8601(btmx.milliseconds())
print(btmx.fetch_balance())
print('Current time:', btmx.iso8601(btmx.milliseconds())
  • Are you located in China?
  • Have you tried with a proxy or a CORS proxy?

@xinglong717

When using ccxt, must config python for ccxt?

In general – nope, but it may be a bug related to a windows python build…

Is this URL accessible from your browser:

https://testnet.bitmex.com/api/v1/instrument/activeAndIndices

?

@xinglong717 it works on my side:

import ccxt
btmx = ccxt.bitmex({
   'apiKey': 'bzHFktf887ap1OCtmAHPADGV',
   'secret':'9rzLlTMjirx_Gh6OwaCDcpKFaxWJ3aEQiYuvUT4Z8LpHe_qB',
   'enableRateLimit': True,
})

if 'test' in btmx.urls:
    btmx.urls['api'] = btmx.urls['test']

print(btmx.fetch_balance())
Screen Shot 2019-09-14 at 20 22 27

What’s your version of CCXT?

@xinglong717 have you tried anything from here:

If you have, which particular steps have you tried already?

In your example you seem to be ignoring the enableRateLimit which is mandatory, as explained here:

import ccxt
btmx = ccxt.bitmex({
   'apiKey': 'bzHFktf887ap1OCtmAHPADGV',
   'secret':'9rzLlTMjirx_Gh6OwaCDcpKFaxWJ3aEQiYuvUT4Z8LpHe_qB',
   'enableRateLimit': True,
})

if 'test' in btmx.urls:
    btmx.urls['api']=btmx.urls['test']
    btmx.urls['api'] = btmx.urls['test']

print(btmx.fetch_balance())

Also, make sure you don’t use testnet api keys with the live system and vice versa – those keys are not interchangeable, you should create a testnet API keypair in order to be able to use BitMEX testnet.

And you need to check your timezone settings on your local machine, it has to be UTC.

Let us know if that does not help.