簡體   English   中英

使用 Python 與 Binance API 進行交易的問題

[英]Issues Placing a Trade with Binance API using Python

我正在嘗試在不使用外部庫的情況下對美國版 Binance API 進行交易。

我可以使用 GET 請求和urllib成功獲取價格並顯示我的帳戶余額。 第一個示例代碼有效,我可以毫無問題地傳遞我的API_KEYSECRET_KEY (這些值是私有的,它們不會顯示在此處,並且位於settings.py )。

進行交易需要 POST,我不確定我哪里出錯了,我的 POST 請求不起作用,但 GET 請求可以正常工作。 根據我對發出 POST 請求的文檔的理解,我應該使用urllib.parse.urlencode()對參數進行編碼並將其傳遞給urllib.request.Request()中的data參數。

這樣做不會引發錯誤,但是當我嘗試使用urllib.request.urlopen()打開請求時出現錯誤:

Traceback (most recent call last):  
File "C:\Users\user\PycharmProjects\test\test.py", line 80, in <module>   place_trade(symbol='BTCUSD', side='BUY', order_type='MARKET', quantity=1)
File "C:\Users\user\PycharmProjects\test\test.py", line 73, in place_trade   response = urllib.request.urlopen(req)
File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\urllib\request.py", line 214, in urlopen   return opener.open(url, data, timeout)
File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\urllib\request.py", line 523, in open   response = meth(req, response)
File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\urllib\request.py", line 632, in http_response   response = self.parent.error(
File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\urllib\request.py", line 561, in error   return self._call_chain(*args)
File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\urllib\request.py", line 494, in _call_chain   result = func(*args)
File "C:\Users\user\AppData\Local\Programs\Python\Python39\lib\urllib\request.py", line 641, in http_error_default   raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 500: Internal Server Error

HTTP 返回代碼state:

HTTP 5XX 返回碼用於內部錯誤; 問題在幣安這邊。 重要的是不要將此視為失敗操作; 執行狀態為 UNKNOWN,可能已經成功。

但是我不認為是這種情況,因為我可以毫無問題地運行其他代碼的 function get_account_balance() 我不確定我做錯了什么,除了發出 GET 和 POST 請求外,兩個代碼幾乎相同。

獲取帳戶余額的代碼 - 工作正常:

import json
import time
import hmac
import settings
import hashlib
import urllib.parse
import urllib.request


def get_account_balance():

    # Setup header with API_KEY
    headers = {'X-MBX-APIKEY': settings.API_KEY}

    # Params requires timestamp in MS
    params = {'timestamp': int(time.time() * 1000)}

    # Encode params into url
    url = 'https://api.binance.us/api/v3/account?' + urllib.parse.urlencode(params)

    # Create a HMAC SHA256 signature
    secret = bytes(settings.SECRET_KEY.encode('utf-8'))
    signature = hmac.new(secret, urllib.parse.urlencode(params).encode('utf-8'), hashlib.sha256).hexdigest()

    # Add signature to url
    url += f'&signature={signature}'

    # Make a request
    req = urllib.request.Request(url, headers=headers)
    
    # Read and decode response
    response = urllib.request.urlopen(req).read().decode('utf-8')
    
    # Convert to json
    response_json = json.loads(response)

    # Print balances for all coins not at 0
    for entry in response_json['balances']:
        if entry['free'] == '0.00000000':
            continue
        print(entry)


get_account_balance()

進行交易的代碼 - 不起作用:

import json
import time
import hmac
import settings
import hashlib
import urllib.parse
import urllib.request


def place_trade(symbol, side, order_type, quantity):

    # Setup header with API_KEY
    headers = {'X-MBX-APIKEY': settings.API_KEY}

    # Params require symbol, side, type, quantity and timestamp (for market orders)
    params = {
        'symbol': symbol,
        'side': side,
        'type': order_type,
        'quantity': quantity,
        'timestamp': int(time.time() * 1000)
    }

    # Encode params into url
    url = 'https://api.binance.us/api/v3/order/test?' + urllib.parse.urlencode(params)

    # Create a HMAC SHA256 signature
    secret = bytes(settings.SECRET_KEY.encode('utf-8'))
    signature = hmac.new(secret, urllib.parse.urlencode(params).encode('utf-8'), hashlib.sha256).hexdigest()

    # Add signature to url
    url += f'&signature={signature}'

    # Encode params
    data = urllib.parse.urlencode(params).encode('ascii')

    # Make a POST request
    req = urllib.request.Request(url, data, headers)

    # Open request and convert to string and then to json
    response = urllib.request.urlopen(req)                         # <- line with error
    response_str = response.read().decode('utf-8')
    response_json = json.loads(response_str)

    print(response_json)


place_trade(symbol='BTCUSD', side='BUY', order_type='MARKET', quantity=1)

參考

示例中使用了此端點,但兩個端點 function 相同並且具有相同的錯誤

我還查看了庫python-binance的示例

編輯

我可以使用requests庫成功下訂單。 我瀏覽了庫的源代碼,但不知道如何使用urllib正確格式化 POST 請求

使用requests庫進行交易的代碼 - 有效:

import hmac
import time
import hashlib
import requests
import settings
import urllib.parse

session = requests.session()
session.headers.update({'X-MBX-APIKEY': settings.API_KEY})


url = 'https://api.binance.us/api/v3/order/test'


params = {
        'symbol': 'BTCUSD',
        'side': 'BUY',
        'type': 'MARKET',
        'quantity': 1,
        'timestamp': int(time.time() * 1000)
    }

secret = bytes(settings.SECRET_KEY.encode('utf-8'))
signature = hmac.new(secret, urllib.parse.urlencode(params).encode('utf-8'), hashlib.sha256).hexdigest()

params['signature'] = signature

result = session.post(url, params)

print(result)
print(result.text)

問題出在以下幾行:

# Encode params into url
url = 'https://api.binance.us/api/v3/order/test?' + urllib.parse.urlencode(params)

# Add signature to url
url += f'&signature={signature}'

顯然,當使用urllib GET 請求有效負載時,必須將其編碼到 url 本身,但是 POST 請求需要您將它們傳遞到data參數中:

data = urllib.parse.urlencode(params).encode('ascii')
req = urllib.request.Request(url, data=data, headers=headers)

在我的問題中,我通過 url 和data參數傳遞了我的有效負載。 刪除 url 有效負載可解決此問題。 任何偶然發現此問題的人的旁注,打個問號? 在 url 之后對於 POST 請求是可選的,但在使用urllib時不是 GET 請求

在沒有外部庫的情況下發布交易的工作代碼:

import json
import time
import hmac
import hashlib
import settings
import urllib.parse
import urllib.request

params = {
        'symbol': 'BTCUSD',
        'side': 'BUY',
        'type': 'MARKET',
        'quantity': 1,
        'timestamp': int(time.time() * 1000)
}

secret = bytes(settings.SECRET_KEY.encode('utf-8'))
signature = hmac.new(secret, urllib.parse.urlencode(params).encode('utf-8'), hashlib.sha256).hexdigest()

params['signature'] = signature

url = 'https://api.binance.us/api/v3/order/test'
headers = {'X-MBX-APIKEY': settings.API_KEY}

data = urllib.parse.urlencode(params).encode('ascii')
req = urllib.request.Request(url, data=data, headers=headers)

response = urllib.request.urlopen(req)
response_str = response.read().decode('utf-8')
response_json = json.loads(response_str)

print(response_json)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM