You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
346 lines
13 KiB
346 lines
13 KiB
from binance import OrderType, OrderStatus, OrderSide, RequestMethod,Interval
|
|
import requests
|
|
import time
|
|
import hmac
|
|
import hashlib
|
|
from threading import Thread, Lock
|
|
from datetime import datetime
|
|
|
|
class BinanceFutureHttp(object):
|
|
|
|
def __init__(self, api_key=None, secret=None, host=None, proxy_host="", proxy_port=0, timeout=5, try_counts=5):
|
|
self.key = api_key
|
|
self.secret = secret
|
|
self.host = host if host else "https://fapi.binance.com"
|
|
self.recv_window = 5000
|
|
self.timeout = timeout
|
|
self.order_count_lock = Lock()
|
|
self.order_count = 1_000_000
|
|
self.try_counts = try_counts # 失败尝试的次数.
|
|
self.proxy_host = proxy_host
|
|
self.proxy_port = proxy_port
|
|
|
|
@property
|
|
def proxies(self):
|
|
if self.proxy_host and self.proxy_port:
|
|
proxy = f"http://{self.proxy_host}:{self.proxy_port}"
|
|
return {"http": proxy, "https": proxy}
|
|
return {}
|
|
|
|
def build_parameters(self, params: dict):
|
|
keys = list(params.keys())
|
|
keys.sort()
|
|
return '&'.join([f"{key}={params[key]}" for key in params.keys()])
|
|
|
|
def request(self, req_method: RequestMethod, path: str, requery_dict=None, verify=False):
|
|
url = self.host + path
|
|
|
|
if verify:
|
|
query_str = self._sign(requery_dict)
|
|
url += '?' + query_str
|
|
elif requery_dict:
|
|
url += '?' + self.build_parameters(requery_dict)
|
|
headers = {"X-MBX-APIKEY": self.key}
|
|
|
|
for i in range(0, self.try_counts):
|
|
try:
|
|
response = requests.request(req_method.value, url=url, headers=headers, timeout=self.timeout, proxies=self.proxies)
|
|
if response.status_code == 200:
|
|
return response.json()
|
|
else:
|
|
print(f"请求没有成功: {response.status_code}, 继续尝试请求")
|
|
except Exception as error:
|
|
print(f"请求:{path}, 发生了错误: {error}, 时间: {datetime.now()}")
|
|
time.sleep(3)
|
|
|
|
def server_time(self):
|
|
path = '/fapi/v1/time'
|
|
return self.request(req_method=RequestMethod.GET, path=path)
|
|
|
|
def exchangeInfo(self):
|
|
|
|
"""
|
|
{'timezone': 'UTC', 'serverTime': 1570802268092, 'rateLimits':
|
|
[{'rateLimitType': 'REQUEST_WEIGHT', 'interval': 'MINUTE', 'intervalNum': 1, 'limit': 1200},
|
|
{'rateLimitType': 'ORDERS', 'interval': 'MINUTE', 'intervalNum': 1, 'limit': 1200}],
|
|
'exchangeFilters': [], 'symbols':
|
|
[{'symbol': 'BTCUSDT', 'status': 'TRADING', 'maintMarginPercent': '2.5000', 'requiredMarginPercent': '5.0000',
|
|
'baseAsset': 'BTC', 'quoteAsset': 'USDT', 'pricePrecision': 2, 'quantityPrecision': 3, 'baseAssetPrecision': 8,
|
|
'quotePrecision': 8,
|
|
'filters': [{'minPrice': '0.01', 'maxPrice': '100000', 'filterType': 'PRICE_FILTER', 'tickSize': '0.01'},
|
|
{'stepSize': '0.001', 'filterType': 'LOT_SIZE', 'maxQty': '1000', 'minQty': '0.001'},
|
|
{'stepSize': '0.001', 'filterType': 'MARKET_LOT_SIZE', 'maxQty': '1000', 'minQty': '0.001'},
|
|
{'limit': 200, 'filterType': 'MAX_NUM_ORDERS'},
|
|
{'multiplierDown': '0.8500', 'multiplierUp': '1.1500', 'multiplierDecimal': '4', 'filterType': 'PERCENT_PRICE'}],
|
|
'orderTypes': ['LIMIT', 'MARKET', 'STOP'], 'timeInForce': ['GTC', 'IOC', 'FOK', 'GTX']}]}
|
|
|
|
:return:
|
|
"""
|
|
|
|
path = '/fapi/v1/exchangeInfo'
|
|
return self.request(req_method=RequestMethod.GET, path=path)
|
|
|
|
def order_book(self, symbol, limit=5):
|
|
limits = [5, 10, 20, 50, 100, 500, 1000]
|
|
if limit not in limits:
|
|
limit = 5
|
|
|
|
path = "/fapi/v1/depth"
|
|
query_dict = {"symbol": symbol,
|
|
"limit": limit
|
|
}
|
|
|
|
return self.request(RequestMethod.GET, path, query_dict)
|
|
|
|
def get_kline(self, symbol, interval: Interval, start_time=None, end_time=None, limit=500, max_try_time=10):
|
|
"""
|
|
|
|
:param symbol:
|
|
:param interval:
|
|
:param start_time:
|
|
:param end_time:
|
|
:param limit:
|
|
:return:
|
|
[
|
|
1499040000000, // 开盘时间
|
|
"0.01634790", // 开盘价
|
|
"0.80000000", // 最高价
|
|
"0.01575800", // 最低价
|
|
"0.01577100", // 收盘价(当前K线未结束的即为最新价)
|
|
"148976.11427815", // 成交量
|
|
1499644799999, // 收盘时间
|
|
"2434.19055334", // 成交额
|
|
308, // 成交笔数
|
|
"1756.87402397", // 主动买入成交量
|
|
"28.46694368", // 主动买入成交额
|
|
"17928899.62484339" // 请忽略该参数
|
|
]
|
|
"""
|
|
path = "/fapi/v1/klines"
|
|
|
|
query_dict = {
|
|
"symbol": symbol,
|
|
"interval": interval.value,
|
|
"limit": limit
|
|
}
|
|
|
|
if start_time:
|
|
query_dict['startTime'] = start_time
|
|
|
|
if end_time:
|
|
query_dict['endTime'] = end_time
|
|
|
|
for i in range(max_try_time):
|
|
data = self.request(RequestMethod.GET, path, query_dict)
|
|
if isinstance(data, list) and len(data):
|
|
return data
|
|
|
|
def get_latest_price(self, symbol):
|
|
path = "/fapi/v1/ticker/price"
|
|
query_dict = {"symbol": symbol}
|
|
return self.request(RequestMethod.GET, path, query_dict)
|
|
|
|
def get_ticker(self, symbol):
|
|
path = "/fapi/v1/ticker/bookTicker"
|
|
query_dict = {"symbol": symbol}
|
|
return self.request(RequestMethod.GET, path, query_dict)
|
|
|
|
########################### the following request is for private data ########################
|
|
|
|
def _timestamp(self):
|
|
return int(time.time() * 1000)
|
|
|
|
def _sign(self, params):
|
|
|
|
requery_string = self.build_parameters(params)
|
|
hexdigest = hmac.new(self.secret.encode('utf8'), requery_string.encode("utf-8"), hashlib.sha256).hexdigest()
|
|
return requery_string + '&signature=' + str(hexdigest)
|
|
|
|
def get_client_order_id(self):
|
|
|
|
"""
|
|
generate the client_order_id for user.
|
|
:return: new client order id
|
|
"""
|
|
with self.order_count_lock:
|
|
self.order_count += 1
|
|
return "x-cLbi5uMH" + str(self._timestamp()) + str(self.order_count)
|
|
|
|
def place_order(self, symbol: str, order_side: OrderSide, order_type: OrderType, quantity, price,
|
|
time_inforce="GTC", client_order_id=None, recvWindow=5000, stop_price=0):
|
|
|
|
"""
|
|
下单..
|
|
:param symbol: BTCUSDT
|
|
:param side: BUY or SELL
|
|
:param type: LIMIT MARKET STOP
|
|
:param quantity: 数量.
|
|
:param price: 价格
|
|
:param stop_price: 停止单的价格.
|
|
:param time_inforce:
|
|
:param params: 其他参数
|
|
|
|
LIMIT : timeInForce, quantity, price
|
|
MARKET : quantity
|
|
STOP: quantity, price, stopPrice
|
|
:return:
|
|
|
|
"""
|
|
|
|
path = '/fapi/v1/order'
|
|
|
|
if client_order_id is None:
|
|
client_order_id = self.get_client_order_id()
|
|
|
|
params = {
|
|
"symbol": symbol,
|
|
"side": order_side.value,
|
|
"type": order_type.value,
|
|
"quantity": quantity,
|
|
"price": price,
|
|
"recvWindow": recvWindow,
|
|
"timeInForce": "GTC",
|
|
"timestamp": self._timestamp(),
|
|
"newClientOrderId": client_order_id
|
|
}
|
|
|
|
if order_type == OrderType.LIMIT:
|
|
params['timeInForce'] = time_inforce
|
|
|
|
if order_type == OrderType.MARKET:
|
|
if params.get('price'):
|
|
del params['price']
|
|
|
|
if order_type == OrderType.STOP:
|
|
if stop_price > 0:
|
|
params["stopPrice"] = stop_price
|
|
else:
|
|
raise ValueError("stopPrice must greater than 0")
|
|
# print(params)
|
|
return self.request(RequestMethod.POST, path=path, requery_dict=params, verify=True)
|
|
|
|
def get_order(self, symbol, client_order_id=None):
|
|
path = "/fapi/v1/order"
|
|
query_dict = {"symbol": symbol, "timestamp": self._timestamp()}
|
|
if client_order_id:
|
|
query_dict["origClientOrderId"] = client_order_id
|
|
|
|
return self.request(RequestMethod.GET, path, query_dict, verify=True)
|
|
|
|
def cancel_order(self, symbol, client_order_id=None):
|
|
path = "/fapi/v1/order"
|
|
params = {"symbol": symbol, "timestamp": self._timestamp()}
|
|
if client_order_id:
|
|
params["origClientOrderId"] = client_order_id
|
|
|
|
return self.request(RequestMethod.DELETE, path, params, verify=True)
|
|
|
|
def get_open_orders(self, symbol=None):
|
|
path = "/fapi/v1/openOrders"
|
|
|
|
params = {"timestamp": self._timestamp()}
|
|
if symbol:
|
|
params["symbol"] = symbol
|
|
|
|
return self.request(RequestMethod.GET, path, params, verify=True)
|
|
|
|
def cancel_open_orders(self, symbol):
|
|
"""
|
|
撤销某个交易对的所有挂单
|
|
:param symbol: symbol
|
|
:return: return a list of orders.
|
|
"""
|
|
path = "/fapi/v1/allOpenOrders"
|
|
|
|
params = {"timestamp": self._timestamp(),
|
|
"recvWindow": self.recv_window,
|
|
"symbol": symbol
|
|
}
|
|
|
|
return self.request(RequestMethod.DELETE, path, params, verify=True)
|
|
|
|
def get_balance(self):
|
|
"""
|
|
[{'accountId': 18396, 'asset': 'USDT', 'balance': '530.21334791', 'withdrawAvailable': '530.21334791', 'updateTime': 1570330854015}]
|
|
:return:
|
|
"""
|
|
path = "/fapi/v1/balance"
|
|
params = {"timestamp": self._timestamp()}
|
|
|
|
return self.request(RequestMethod.GET, path=path, requery_dict=params, verify=True)
|
|
|
|
def get_account_info(self):
|
|
"""
|
|
{'feeTier': 2, 'canTrade': True, 'canDeposit': True, 'canWithdraw': True, 'updateTime': 0, 'totalInitialMargin': '0.00000000',
|
|
'totalMaintMargin': '0.00000000', 'totalWalletBalance': '530.21334791', 'totalUnrealizedProfit': '0.00000000',
|
|
'totalMarginBalance': '530.21334791', 'totalPositionInitialMargin': '0.00000000', 'totalOpenOrderInitialMargin': '0.00000000',
|
|
'maxWithdrawAmount': '530.2133479100000', 'assets':
|
|
[{'asset': 'USDT', 'walletBalance': '530.21334791', 'unrealizedProfit': '0.00000000', 'marginBalance': '530.21334791',
|
|
'maintMargin': '0.00000000', 'initialMargin': '0.00000000', 'positionInitialMargin': '0.00000000', 'openOrderInitialMargin': '0.00000000',
|
|
'maxWithdrawAmount': '530.2133479100000'}]}
|
|
:return:
|
|
"""
|
|
path = "/fapi/v1/account"
|
|
params = {"timestamp": self._timestamp()}
|
|
return self.request(RequestMethod.GET, path, params, verify=True)
|
|
|
|
def get_position_info(self):
|
|
"""
|
|
[{'symbol': 'BTCUSDT', 'positionAmt': '0.000', 'entryPrice': '0.00000', 'markPrice': '8326.40833498', 'unRealizedProfit': '0.00000000', 'liquidationPrice': '0'}]
|
|
:return:
|
|
"""
|
|
path = "/fapi/v1/positionRisk"
|
|
params = {"timestamp": self._timestamp()}
|
|
return self.request(RequestMethod.GET, path, params, verify=True)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
# import pandas as pd
|
|
|
|
key = "xxxx"
|
|
secret = 'xxxx'
|
|
binance = BinanceFutureHttp(api_key=key, secret=secret)
|
|
|
|
# import datetime
|
|
# print(datetime.datetime.now())
|
|
|
|
data = binance.get_kline('BTCUSDT', Interval.HOUR_1, limit=100)
|
|
print(data)
|
|
print(isinstance(data, list))
|
|
|
|
exit()
|
|
# info = binance.exchangeInfo()
|
|
# print(info)
|
|
# exit()
|
|
# print(binance.order_book(symbol='BTCUSDT', limit=5))
|
|
# exit()
|
|
|
|
# print(binance.latest_price('BTCUSDT'))
|
|
# kline = binance.kline('BTCUSDT', interval='1m')
|
|
# print(pd.DataFrame(kline))
|
|
|
|
# print(binance.ticker("BTCUSDT"))
|
|
|
|
# print(binance.get_ticker('BTCUSDT'))
|
|
# {'symbol': 'BTCUSDT', 'side': 'SELL', 'type': 'LIMIT', 'quantity': 0.001, 'price': 8360.82, 'recvWindow': 5000, 'timestamp': 1570969995974, 'timeInForce': 'GTC'}
|
|
|
|
# data = binance.place_order(symbol="BTCUSDT", side=OrderSide.BUY, order_type=OrderType.MARKET, quantity=0.001, price=8250.82)
|
|
# print(data)
|
|
|
|
# cancel_order = binance.cancel_order("BTCUSDT", order_id="30714952")
|
|
# print(cancel_order)
|
|
|
|
# balance = binance.get_balance()
|
|
# print(balance)
|
|
|
|
# account_info = binance.get_account_info()
|
|
# print(account_info)
|
|
|
|
# account_info = binance.get_position_info()
|
|
# print(account_info)
|
|
|
|
"""
|
|
{'orderId': 30714952, 'symbol': 'BTCUSDT', 'accountId': 18396, 'status': 'NEW', 'clientOrderId': 'ZC3qSbzbODl0GId9idK9hM', 'price': '7900', 'origQty': '0.010', 'executedQty': '0', 'cumQty': '0', 'cumQuote': '0', 'timeInForce': 'GTC', 'type': 'LIMIT', 'reduceOnly': False, 'side': 'BUY', 'stopPrice': '0', 'updateTime': 1569658787083}
|
|
{'orderId': 30714952, 'symbol': 'BTCUSDT', 'accountId': 18396, 'status': 'NEW', 'clientOrderId': 'ZC3qSbzbODl0GId9idK9hM', 'price': '7900', 'origQty': '0.010', 'executedQty': '0', 'cumQty': '0', 'cumQuote': '0', 'timeInForce': 'GTC', 'type': 'LIMIT', 'reduceOnly': False, 'side': 'BUY', 'stopPrice': '0', 'updateTime': 1569658787083}
|
|
"""
|