Вступление
Биржа binance, как и многие другие биржи, предоставляет API - программный интерфейс для автоматизации торговли. В этой статье рассмотрены методы и приведены примеры кода для работы с ними.
Официальное описание API (на английском) - здесь. Бот для Binance - здесь. Как получить API ключи - тут.
Вводная информация
В отличии от многих других бирж, Binance лимитирует не только количество запросов к API, но и "вес" запросов. Причем, это не какие-то фиксированные единицы, но целый комплекс (как они заявляют, англ). Например, если вы постоянно запрашиваете свечи но не торгуете, то ваш вес накапливается и вас могут забанить. И вообще они суровые - если вы постоянно перебиваете лучшую цену на минимальную ставку, или создаете/отменяете ордера но не покупаете и продаете и т.п. то вас настигнут санкции. Так что будьте аккуратны при тестировании ботов. Впрочем, пока я тестировал, ничего плохого не случилось, хотя я порой и жестил.
Если биржа захочет вам намекнуть, что пора бы снизить пыл, она вернет 429 ответ сервера. Если вы будете игнорировать этот ответ и ломиться в закрытую дверь, то вас забанят по IP на срок от 2 минут до 3 дней.
Подключение к API биржи идет через https://api.binance.com, для авторизованных запросов нужно отправлять ключ в заголовке X-MBX-APIKEY, и подписывать тело запроса SHA256.
Что бы вы не заморачивались с этим, я написал код, который позволяет все указанные запросы выполнять. Для его работы нужно установить Python версии 3.6+ с официального сайта, потом в командной строке выполнить pip install requests. Создайте папку (для удобства), создайте новый файл binance_api.py, и вставьте туда этот код:
import ssl
import time
import json
import urllib
import hmac, hashlib
import requests
from urllib.parse import urlparse, urlencode
from urllib.request import Request, urlopen
class Binance():
methods = {
# public methods
'ping': {'url':'api/v1/ping', 'method': 'GET', 'private': False},
'time': {'url':'api/v1/time', 'method': 'GET', 'private': False},
'exchangeInfo': {'url':'api/v1/exchangeInfo', 'method': 'GET', 'private': False},
'depth': {'url': 'api/v1/depth', 'method': 'GET', 'private': False},
'trades': {'url': 'api/v1/trades', 'method': 'GET', 'private': False},
'historicalTrades': {'url': 'api/v1/historicalTrades', 'method': 'GET', 'private': False},
'aggTrades': {'url': 'api/v1/aggTrades', 'method': 'GET', 'private': False},
'klines': {'url': 'api/v1/klines', 'method': 'GET', 'private': False},
'ticker24hr': {'url': 'api/v1/ticker/24hr', 'method': 'GET', 'private': False},
'tickerPrice': {'url': 'api/v3/ticker/price', 'method': 'GET', 'private': False},
'tickerBookTicker': {'url': 'api/v3/ticker/bookTicker', 'method': 'GET', 'private': False},
# private methods
'createOrder': {'url': 'api/v3/order', 'method': 'POST', 'private': True},
'testOrder': {'url': 'api/v3/order/test', 'method': 'POST', 'private': True},
'orderInfo': {'url': 'api/v3/order', 'method': 'GET', 'private': True},
'cancelOrder': {'url': 'api/v3/order', 'method': 'DELETE', 'private': True},
'openOrders': {'url': 'api/v3/openOrders', 'method': 'GET', 'private': True},
'allOrders': {'url': 'api/v3/allOrders', 'method': 'GET', 'private': True},
'account': {'url': 'api/v3/account', 'method': 'GET', 'private': True},
'myTrades': {'url': 'api/v3/myTrades', 'method': 'GET', 'private': True},
# wapi
'depositAddress': {'url': 'wapi/v3/depositAddress.html', 'method':'GET', 'private':True},
'withdraw': {'url': 'wapi/v3/withdraw.html', 'method':'POST', 'private':True},
'depositHistory': {'url': 'wapi/v3/depositHistory.html', 'method':'GET', 'private':True},
'withdrawHistory': {'url': 'wapi/v3/withdrawHistory.html', 'method':'GET', 'private':True},
'assetDetail': {'url': 'wapi/v3/assetDetail.html', 'method':'GET', 'private':True},
'tradeFee': {'url': 'wapi/v3/tradeFee.html', 'method':'GET', 'private':True},
'accountStatus': {'url': 'wapi/v3/accountStatus.html', 'method':'GET', 'private':True},
'systemStatus': {'url': 'wapi/v3/systemStatus.html', 'method':'GET', 'private':True},
'assetDust': {'url': 'sapi/v1/asset/dust', 'method':'POST', 'private':True},
'dustLog': {'url': 'wapi/v3/userAssetDribbletLog.html', 'method':'GET', 'private':True},
'assetAssetDividend': {'url': 'sapi/v1/asset/assetDividend', 'method':'GET', 'private':True},
#sapi
'marginTransfer': {'url': 'sapi/v1/margin/transfer', 'method': 'POST', 'private':True},
'marginLoan': {'url': 'sapi/v1/margin/loan', 'method': 'POST', 'private': True},
'marginLoanGet': {'url': 'sapi/v1/margin/loan', 'method': 'GET', 'private': True},
'marginRepay': {'url': 'sapi/v1/margin/repay', 'method': 'POST', 'private': True},
'marginRepayGet': {'url': 'sapi/v1/margin/repay', 'method': 'GET', 'private': True},
'marginCreateOrder': {'url': 'sapi/v1/margin/order', 'method': 'POST', 'private':True},
'marginCancelOrder': {'url': 'sapi/v1/margin/order', 'method': 'DELETE', 'private':True},
'marginOrderInfo': {'url': 'sapi/v1/margin/order', 'method': 'GET', 'private':True},
'marginAccount': {'url': 'sapi/v1/margin/account', 'method': 'POST', 'private':True},
'marginOpenOrders': {'url': 'sapi/v1/margin/openOrders', 'method': 'GET', 'private':True},
'marginAllOrders': {'url': 'sapi/v1/margin/allOrders', 'method': 'GET', 'private':True},
'marginAsset': {'url': 'sapi/v1/margin/asset', 'method': 'POST', 'private':True},
'marginPair': {'url': 'sapi/v1/margin/pair', 'method': 'POST', 'private':True},
'marginPriceIndex': {'url': 'sapi/v1/margin/priceIndex', 'method': 'POST', 'private':True},
'marginMyTrades': {'url': 'sapi/v1/margin/myTrades', 'method': 'GET', 'private':True},
'marginMaxBorrowable': {'url': 'sapi/v1/margin/maxBorrowable', 'method': 'GET', 'private':True},
'marginmaxTransferable': {'url': 'sapi/v1/margin/maxTransferable', 'method': 'GET', 'private':True},
#futures
'futuresExchangeInfo': {'url': 'fapi/v1/exchangeInfo', 'method': 'GET', 'private': False, 'futures': True},
'futuresKlines': {'url': 'fapi/v1/klines', 'method': 'GET', 'private': False, 'futures': True},
'futuresCreateOrder': {'url': 'fapi/v1/order', 'method': 'POST', 'private': True, 'futures': True},
'futuresAccount': {'url': 'fapi/v1/account', 'method': 'POST', 'private': True, 'futures': True},
'futuresBalance': {'url': 'fapi/v1/balance', 'method': 'GET', 'private': True, 'futures': True},
'futuresSymbolPriceTicker': {'url': 'fapi/v1/ticker/price', 'method': 'GET', 'private': True, 'futures': True},
'futuresOrderInfo': {'url': 'fapi/v1/order', 'method': 'GET', 'private': True, 'futures': True},
'futuresCancelOrder': {'url': 'fapi/v1/order', 'method': 'DELETE', 'private': True, 'futures': True},
}
def __init__(self, API_KEY, API_SECRET):
self.API_KEY = API_KEY
self.API_SECRET = bytearray(API_SECRET, encoding='utf-8')
self.shift_seconds = 0
def __getattr__(self, name):
def wrapper(*args, **kwargs):
kwargs.update(command=name)
return self.call_api(**kwargs)
return wrapper
def set_shift_seconds(self, seconds):
self.shift_seconds = seconds
def call_api(self, **kwargs):
command = kwargs.pop('command')
base_url ='https://api.binance.com/'
if self.methods[command].get('futures'):
base_url = 'https://fapi.binance.com/'
api_url = base_url + self.methods[command]['url']
payload = kwargs
headers = {}
payload_str = urllib.parse.urlencode(payload)
if self.methods[command]['private']:
payload.update({'timestamp': int(time.time() + self.shift_seconds - 1) * 1000})
payload_str = urllib.parse.urlencode(payload).encode('utf-8')
sign = hmac.new(
key=self.API_SECRET,
msg=payload_str,
digestmod=hashlib.sha256
).hexdigest()
payload_str = payload_str.decode("utf-8") + "&signature="+str(sign)
headers = {"X-MBX-APIKEY": self.API_KEY, "Content-Type":"application/x-www-form-urlencoded"}
if self.methods[command]['method'] == 'GET' or self.methods[command]['url'].startswith('sapi'):
api_url += '?' + payload_str
response = requests.request(method=self.methods[command]['method'], url=api_url, data="" if self.methods[command]['method'] == 'GET' else payload_str, headers=headers)
if 'code' in response.text:
raise Exception(response.text)
return response.json()
Для тестирования методов, создайте в этой же папке второй файл, например, binance_test.py, туда вставьте вот такой код (подставьте свои API ключи):
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
print('account', bot.account())
(Или возьмите с гитхаба)
После этого код можно запускать. К примеру, если вы только установили Python и не знаете, что делать, найдите редактор Idle (он устанавливается вместе с питоном), в нем File -> Open, откройте файл binance_test.py и нажмите F5. Код, представленный выше, вернет информацию по вашему аккаунту - подробности ниже.
Еще немного общей информации: практически во всех подписанных запросах необходимо указывать параметр timestamp - это текущее unix-время в милиосекундах. Но, так как некоторые сети бывают перегружены, то ваш запрос может заблудиться и придти позже. Поэтому биржа предоставляет вам временное окно (по умолчанию 5000 милисекунд). Если у вас запросы не успевают придти в это окно, вы можете его расширить с помощью параметра recvWindow. Но, думаю, это мало кому понадобится.
Публичные запросы
Проверка связи - /api/v1/ping
Метод для проверки работы API.
Возвращает пустой словарь
{}
Ссылка для просмотра в браузере https://api.binance.com/api/v1/ping.
Вес - 1
Код для проверки:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
print(bot.ping())
Получение времени биржи - /api/v1/time
Ссылка для просмотра в браузере https://api.binance.com/api/v1/time
Вес - 1
Возвращает словарь с текущим временем:
{
"serverTime": 1499827319559
}
Код для проверки:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
print(bot.time())
Настройки и лимиты биржи - /api/v1/exchangeInfo
Ссылка для просмотра в браузере https://api.binance.com/api/v1/exchangeInfo
Вес - 1
Возвращает структуру данных:
{
"timezone": "UTC",
"serverTime": 1508631584636,
"rateLimits": [{
"rateLimitType": "REQUESTS",
"interval": "MINUTE",
"limit": 1200
},
{
"rateLimitType": "ORDERS",
"interval": "SECOND",
"limit": 10
},
{
"rateLimitType": "ORDERS",
"interval": "DAY",
"limit": 100000
}
],
"exchangeFilters": [],
"symbols": [{
"symbol": "ETHBTC",
"status": "TRADING",
"baseAsset": "ETH",
"baseAssetPrecision": 8,
"quoteAsset": "BTC",
"quotePrecision": 8,
"orderTypes": ["LIMIT", "MARKET"],
"icebergAllowed": false,
"filters": [{
"filterType": "PRICE_FILTER",
"minPrice": "0.00000100",
"maxPrice": "100000.00000000",
"tickSize": "0.00000100"
}, {
"filterType": "LOT_SIZE",
"minQty": "0.00100000",
"maxQty": "100000.00000000",
"stepSize": "0.00100000"
}, {
"filterType": "MIN_NOTIONAL",
"minNotional": "0.00100000"
}]
}]
}
Ключ rateLimits ведет на массив с лимитами - сколько запросов в секунду/минуту/день можно делать.
Ключ symbols содержит настройки для каждой пары - рассмотрим одну, ETHBTC
{
"symbol": "ETHBTC",
"status": "TRADING",
"baseAsset": "ETH",
"baseAssetPrecision": 8,
"quoteAsset": "BTC",
"quotePrecision": 8,
"orderTypes": [
"LIMIT",
"LIMIT_MAKER",
"MARKET",
"STOP_LOSS_LIMIT",
"TAKE_PROFIT_LIMIT"
],
"icebergAllowed": true,
"filters": [
{
"filterType": "PRICE_FILTER",
"minPrice": "0.00000100",
"maxPrice": "100000.00000000",
"tickSize": "0.00000100"
},
{
"filterType": "LOT_SIZE",
"minQty": "0.00100000",
"maxQty": "100000.00000000",
"stepSize": "0.00100000"
},
{
"filterType": "MIN_NOTIONAL",
"minNotional": "0.00100000"
}
]
}
symbol - непосредственно пара
status - TRADING -разрешена торговля
baseAsset - базовая валюта
baseAssetPrecision - требуемое количество символов базовой валюты после запятой при создании ордера (для цены и количества)
quoteAsset - квотируемая валюта
quotePrecision - требуемое количество символов квотируемой валюты после запятой при создании ордера (для цены и количества)
"orderTypes": [
"LIMIT",
"LIMIT_MAKER",
"MARKET",
"STOP_LOSS_LIMIT",
"TAKE_PROFIT_LIMIT"
] - допустимые виды ордеров по паре
icebergAllowed - разрешено ли создание айсбергов (ордеров с невидимой частью)
filters - ограничение ордеров
PRICE_FILTER - ограничение цены создаваемого ордера. Цена ордера должна быть в диапазоне min_price и max_price, и шаг торговли должен быть кратен tickSize. Да да, тут нельзя ставить ордера с произвольной ценой.
LOT_SIZE - ограничение объема создаваемого ордера. Объем должен быть в диапазоне minQty и maxQty, и быть кратен stepSize.
MIN_NOTIONAL - итоговая сумма ордера (объем*цена) должна быть выше minNotional.
Код для проверки:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
print(bot.exchangeInfo())
Открытые ордера на бирже - /api/v1/depth
Метод позволяет получить книгу ордеров.
Принимает параметры:
Обязательные:
symbol - пара
Необязательные:
limit - кол-во возвращаемых записей от 5 до 1000 (по умолчанию 100). Допустимые значения: 5, 10, 20, 50, 100, 500, 1000. Еще можно указать 0, но он может вернуть большое кол-во данных.
Вес зависит от параметра limit. При лимите от 5 до 100 вес будет равен 1. Для параметра 500 вес составит 5. Для параметра 1000 вес будет 10.
Ссылка для просмотра в браузере: https://api.binance.com/api/v1/depth?symbol=ETHBTC
Возвращает значения:
{
"lastUpdateId": 1027024,
"bids": [
[
"4.00000000", // PRICE
"431.00000000", // QTY
[] // Ignore.
]
],
"asks": [
[
"4.00000200",
"12.00000000",
[]
]
]
}
bids - это списки цен/объемов на покупку, asks - на продажу.
Пример кода:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
print('depth', bot.depth(
symbol='BNBBTC',
limit=5
))
Последние (чужие) сделки - /api/v1/trades
Принимает параметры:
Обязательные:
symbol - пара
Необязательные:
limit - кол-во возвращаемых записей (максимум 500, по умолчанию 500).
Вес - 1
Ссылка для просмотра в браузере: https://api.binance.com/api/v1/trades?symbol=ETHBTC
Пример ответа:
[
{
"id": 28457,
"price": "4.00000100",
"qty": "12.00000000",
"time": 1499865549590,
"isBuyerMaker": true,
"isBestMatch": true
}
]
id - id сделки
price - цена
qty - количество
time - время сделки
isBuyerMaker - была ли покупка по указанной покупателем цене,
isBestMatch - была ли встречная сделка
Пример кода:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
print('trades', bot.trades(
symbol='BNBBTC',
limit=1
))
Сжатая история сделок - /api/v1/aggTrades
Метод позволяет получить суммарную историю сделок. Сделки, выполненные в одно время по одному ордеру и по одной цене будут представлены одной строкой с объединенным количеством.
Вес - 1
Ссылка для просмотра в браузере: https://api.binance.com/api/v1/aggTrades?symbol=ETHBTC
Принимает параметры:
Обязательные:
symbol - пара
Необязательные:
fromID - показывать начиная со сделки № (включительно)
startTime - начиная с какого времени (включительно)
endTime - заканчивая каким временем (включительно)
limit - Кол-во записей (максимум 500, по умолчанию 500)
Возвращает данные:
[
{
"a": 26129, // tradeId строки
"p": "0.01633102", // Цена
"q": "4.70443515", // Количество
"f": 27781, // Первая tradeId
"l": 27781, // Последняя tradeId
"T": 1498793709153, // Время
"m": true, // Was the buyer the maker?
"M": true // Was the trade the best price match?
}
]
Пример кода:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
print('aggTrades', bot.aggTrades(
symbol='BNBBTC',
limit=1
))
Данные по свечам – /api/v1/klines
Вес – 1
Ссылка для просмотра в браузере https://api.binance.com/api/v1/klines?symbol=LTCBTC&interval=5m
Параметры:
Обязательные:
symbol – пара
interval – период свечи
Допустимые интервалы:
• 1m // 1 минута
• 3m // 3 минуты
• 5m // 5 минут
• 15m // 15 минут
• 30m // 30 минут
• 1h // 1 час
• 2h // 2 часа
• 4h // 4 часа
• 6h // 6 часов
• 8h // 8 часов
• 12h // 12 часов
• 1d // 1 день
• 3d // 3 дня
• 1w // 1 неделя
• 1M // 1 месяц
Необязательные:
limit – кол-во свечей (максимум 500, по умолчанию 500)
startTime – время начала построения
endTime – окончание периода
Если не указаны параметры startTime и endTime, то возвращаются самые последние свечи.
Пример ответа:
[
[
1499040000000, // Время открытия
"0.01634790", // Цена открытия (Open)
"0.80000000", // Максимальная цена (High)
"0.01575800", // Минимальная цена (Low)
"0.01577100", // Цена закрытия (Close)
"148976.11427815", // Объем
1499644799999, // Время закрытия
"2434.19055334", // Объем квотируемой валюты
308, // Кол-во сделок
"1756.87402397", // Taker buy base asset volume
"28.46694368", // Taker buy quote asset volume
"17928899.62484339" // Ignore
]
]
Пример кода:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
print('klines', bot.klines(
symbol='BNBBTC',
interval='5m',
limit=1
))
Статистика за 24 часа - /api/v1/ticker/24hr
Вес – 1, если указана пара, иначе вес равен (количеству всех торгуемых пар)/2.
Ссылка для просмотра в браузере: https://api.binance.com/api/v1/ticker/24hr?symbol=BNBBTC
Параметры:
Необязательные:
symbol – пара
Если symbol не указан, возвращаются данные по всем парам. В этом случае, считается, что вы сделали столько запросов к бирже, сколько вернулось пар.
Пример ответа:
{
"symbol": "BNBBTC", // пара
"priceChange": "-94.99999800", // изменение цены за сутки
"priceChangePercent": "-95.960", // изменение цены за сутки %
"weightedAvgPrice": "0.29628482", //Средневзвешенная цена
"prevClosePrice": "0.10002000", // Предыдущая цена закрытия
"lastPrice": "4.00000200", // Последняя цена
"lastQty": "200.00000000", // Последний объем
"bidPrice": "4.00000000", // Цена покупки
"askPrice": "4.00000200", // Цена продажи
"openPrice": "99.00000000", // Цена открытия
"highPrice": "100.00000000", // Самая высокая цена
"lowPrice": "0.10000000", // Самая низкая цена
"volume": "8913.30000000", // Объем торгов базовой валюты
"quoteVolume": "15.30000000", // Объем торгов квотируемой
"openTime": 1499783499040, // Время открытия
"closeTime": 1499869899040, // Время закрытия
"fristId": 28385, // Id первой сделки
"lastId": 28460, // Id последней сделки
"count": 76 // Кол-во сделок
}
Если пар несколько, то такие словари вкладываются в массив, вот так:
[
{
"symbol": "BNBBTC",
…
},
{
"symbol": "LTCBTC",
…
},
]
Пример кода:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
print('ticker/24hr', bot.ticker24hr(
symbol='BNBBTC'
))
Последняя цена по паре (или парам) - /api/v3/ticker/price
Вес - 1
Параметры:
Необязательные:
symbol – пара
Если параметр symbol не указан, то возвращаются цены по всем парам.
Ссылка для просмотра в браузере: https://api.binance.com/api/v3/ticker/price?symbol=BNBBTC
Пример ответа:
{
"symbol": "LTCBTC",
"price": "4.00000200"
}
Или (если не указан параметр)
[
{
"symbol": "LTCBTC",
"price": "4.00000200"
},
{
"symbol": "ETHBTC",
"price": "0.07946600"
}
]
Пример кода:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
print('ticker/price', bot.tickerPrice(
symbol='BNBBTC'
))
Лучшие цены покупки/продажи - /api/v3/ticker/bookTicker
Вес 1
Параметры:
Необязательные:
symbol – пара
Если параметр symbol не указан, возвращаются данные по всем парам.
Ссылка для просмотра в браузере: https://api.binance.com/api/v3/ticker/bookTicker?symbol=BNBBTC
Пример ответа:
{
"symbol": "LTCBTC",
"bidPrice": "4.00000000", //Лучшая цена покупки
"bidQty": "431.00000000", // Кол-во к покупке
"askPrice": "4.00000200", // Лучшая цена продажи
"askQty": "9.00000000" // Кол-во к продаже
}
Или (если не указан параметр):
[
{
"symbol": "LTCBTC",
"bidPrice": "4.00000000",
"bidQty": "431.00000000",
"askPrice": "4.00000200",
"askQty": "9.00000000"
},
{
"symbol": "ETHBTC",
"bidPrice": "0.07946700",
"bidQty": "9.00000000",
"askPrice": "100000.00000000",
"askQty": "1000.00000000"
}
]
Пример кода:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
print('ticker/bookTicker', bot.tickerBookTicker(
symbol='BNBBTC'
))
Авторизованные запросы:
Создание ордера - /api/v3/order
Вес – 1
Метод: POST
Параметры:
Обязательные:
symbol – пара
side – тип ордера (BUY либо SELL)
type – тип ордера (LIMIT, MARKET, STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, TAKE_PROFIT_LIMIT, LIMIT_MAKER)
quantity – количество к покупке
timestamp – текущее время в миллисекундах (в коде, выложенном здесь, проставляется автоматически, указывать не надо.
Необязательные:
timeInForce – (GTC, IOC, FOK). По умолчанию GTC. Расшифрую.
GTC (Good Till Cancelled) – ордер будет висеть до тех пор, пока его не отменят.
IOC (Immediate Or Cancel) – Будет куплено то количество, которое можно купить немедленно. Все, что не удалось купить, будет отменено.
FOK (Fill-Or-Kill) – Либо будет куплено все указанное количество немедленно, либо не будет куплено вообще ничего, ордер отменится.
price – цена
newClientOrderId – Идентификатор ордера, который вы сами придумаете (строка). Если не указан, генерится автоматически.
stopPrice – стоп-цена, можно указывать если тип ордера STOP_LOSS, STOP_LOSS_LIMIT, TAKE_PROFIT, или TAKE_PROFIT_LIMIT.
icebergQty – кол-во для ордера-айсберга, можно указывать, если тип ордера LIMIT, STOP_LOSS_LIMIT, and TAKE_PROFIT_LIMIT
recvWindow – кол-во миллисекунд, которое прибавляется к timestamp и формирует окно действия запроса (см. выше). По умолчанию 5000.
newOrderRespType –какую информацию возвращать, если удалось создать ордер. Допустимые значения ACK, RESULT, или FULL, по умолчанию RESULT. Подробности ниже.
В зависимости от типа ордера, некоторые поля становятся обязательными:
Тип ордера Обязательные поля
LIMIT timeInForce, quantity, price
MARKET quantity
STOP_LOSS quantity, stopPrice
STOP_LOSS_LIMIT timeInForce, quantity, price, stopPrice
TAKE_PROFIT quantity, stopPrice
TAKE_PROFIT_LIMIT timeInForce, quantity, price, stopPrice
LIMIT_MAKER quantity, price
Ордера типа LIMIT_MAKER – это ордера типа обычного LIMIT, но они отклонятся, если ордер при выставлении может выполниться по рынку. Другими словами, вы никогда не будете тейкером, ордер либо выставится выше/ниже рынка, либо не выставится вовсе.
Ордера типа STOP_LOSS и TAKE_PROFIT исполнятся по рынку (ордер типа MARKET), как только будет достигнута цена stopPrice.
Любые ордера LIMIT или LIMIT_MAKER могут формировать ордер-айсберг, установив параметр icebergQty.
Если установлен параметр icebergQty, то параметр timeInForce ОБЯЗАТЕЛЬНО должен иметь значение GTC.
Для того, что бы выставлять цены, противоположные текущим для ордеров типов MARKET и LIMIT:
Цена выше рыночной: STOP_LOSS BUY, TAKE_PROFIT SELL
Цена ниже рыночной: STOP_LOSS SELL, TAKE_PROFIT BUY
При создании ордера вернется ответ, в зависимости от параметра newOrderRespType:
newOrderRespType == ACK:
{
"symbol": "BTCUSDT",
"orderId": 28,
"clientOrderId": "6gCrw2kRUAF9CvJDGP16IP",
"transactTime": 1507725176595
}
newOrderRespType == RESULT:
{
"symbol": "BTCUSDT",
"orderId": 28,
"clientOrderId": "6gCrw2kRUAF9CvJDGP16IP",
"transactTime": 1507725176595,
"price": "0.00000000",
"origQty": "10.00000000",
"executedQty": "10.00000000",
"status": "FILLED",
"timeInForce": "GTC",
"type": "MARKET",
"side": "SELL"
}
newOrderRespType == FULL:
{
"symbol": "BTCUSDT",
"orderId": 28,
"clientOrderId": "6gCrw2kRUAF9CvJDGP16IP",
"transactTime": 1507725176595,
"price": "0.00000000",
"origQty": "10.00000000",
"executedQty": "10.00000000",
"status": "FILLED",
"timeInForce": "GTC",
"type": "MARKET",
"side": "SELL",
"fills": [
{
"price": "4000.00000000",
"qty": "1.00000000",
"commission": "4.00000000",
"commissionAsset": "USDT"
},
{
"price": "3999.00000000",
"qty": "5.00000000",
"commission": "19.99500000",
"commissionAsset": "USDT"
},
{
"price": "3998.00000000",
"qty": "2.00000000",
"commission": "7.99600000",
"commissionAsset": "USDT"
},
{
"price": "3997.00000000",
"qty": "1.00000000",
"commission": "3.99700000",
"commissionAsset": "USDT"
},
{
"price": "3995.00000000",
"qty": "1.00000000",
"commission": "3.99500000",
"commissionAsset": "USDT"
}
]
}
Пример кода:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
# Создать отложенный ордер на покупку 0.1 LTC за BTC
# По курсу 0.1
print('createOrder', bot.createOrder(
symbol='LTCBTC',
recvWindow=5000,
side='BUY',
type='LIMIT',
timeInForce='GTC',
quantity=0.1,
price=0.1
))
Тестирование создания ордера: /api/v3/order/test
Вес: 1
Метод: POST
Метод позволяет протестировать создание ордера – например, проверить, правильно ли настроены временные рамки. По факту такой ордер никогда не будет исполнен, и средства на его создание затрачены не будут.
Параметры такие же, как при создании ордера.
Возвращает пустой словарь:
{}
Пример кода:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
# Протестировать отложенный ордер на покупку 0.1 LTC за BTC
# По курсу 0.1
print('testOrder', bot.testOrder(
symbol='LTCBTC',
recvWindow=5000,
side='BUY',
type='LIMIT',
timeInForce='GTC',
quantity=0.1,
price=0.1
))
Получить информацию по созданному ордеру - /api/v3/order
Вес – 1
Метод – GET
Параметры:
Обязательные:
symbol – пара
orderId – ID ордера, назначенный биржей
ИЛИ origClientOrderId – ID ордера, назначенный пользователем или сгенерированный (см. создание ордера)
Либо orderId либо origClientOrderId необходимо предоставить.
timestamp – текущее время (в представленном коде проставляется автоматически, указывать не надо)
Необязательные:
recvWindow – окно валидности запроса.
Возвращаемое значение:
{
"symbol": "LTCBTC",
"orderId": 1,
"clientOrderId": "myOrder1",
"price": "0.1",
"origQty": "1.0", // исходное указанное кол-во на покупку/продажу
"executedQty": "0.0", // текущее исполненное кол-во
"status": "NEW",
"timeInForce": "GTC",
"type": "LIMIT",
"side": "BUY",
"stopPrice": "0.0",
"icebergQty": "0.0",
"time": 1499827319559,
"isWorking": true
}
Пример кода:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
print('orderInfo', bot.orderInfo(
orderId=123123,
symbol='LTCBTC',
))
Отмена ордера - /api/v3/order
Вес – 1
Метод – DELETE
Параметры:
Обязательные:
symbol – пара
orderId – ID ордера, назначенный биржей
ИЛИ origClientOrderId – ID ордера, назначенный пользователем или сгенерированный (см. создание ордера)
Либо orderId либо origClientOrderId необходимо предоставить.
timestamp – текущее время (в представленном коде проставляется автоматически, указывать не надо)
Не обязательные:
newClientOrderId – позволяет однозначно определить отмену, если не указано, генерируется автоматически
recvWindow – окно валидности запроса.
Возвращает:
{
"symbol": "LTCBTC",
"origClientOrderId": "myOrder1",
"orderId": 1,
"clientOrderId": "cancelMyOrder1"
}
Пример кода:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
print('cancelOrder', bot.cancelOrder(
orderId=123123,
symbol='LTCBTC',
))
Текущие открытые пользователем ордера - /api/v3/openOrders
Вес – 1 если указана пара, либо (количество всех открытых для торгов пар) / 2.
Метод – GET
Параметры:
Обязательные:
timestamp – текущее время (в представленном коде проставляется автоматически, указывать не надо)
Не обязательные:
Не обязательные:
symbol – пара
recvWindow – окно валидности запроса.
Если параметр symbol не указан, возвращаются все открытые ордера по всем парам в массиве. В этом случае количество запросов к API считается равным количеству открытых для торговли пар.
Возвращает:
[
{
"symbol": "LTCBTC",
"orderId": 1,
"clientOrderId": "myOrder1",
"price": "0.1",
"origQty": "1.0",
"executedQty": "0.0",
"status": "NEW",
"timeInForce": "GTC",
"type": "LIMIT",
"side": "BUY",
"stopPrice": "0.0",
"icebergQty": "0.0",
"time": 1499827319559,
"isWorking": trueO
}
]
Пример кода:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
# Все открытые ордера по паре
print('openOrders', bot.openOrders(
symbol='LTCBTC',
))
# Все открытые ордера по всем парам
print('openOrders', bot.openOrders())
Все ордера пользователя вообще - /api/v3/allOrders
Метод позволяет получить вообще все ордера пользователя – открытые, исполненные или отмененные.
Вес – 5
Метод – GET
Параметры:
Обязательные:
symbol – пара
timestamp – текущее время (в представленном коде проставляется автоматически, указывать не надо)
Не обязательные:
orderId – Если указан, то вернутся все ордера, которые >= указанному. Если не указан, вернутся самые последние.
limit – кол-во возвращаемых ордеров (максимум 500, по умолчанию 500)
recvWindow – окно валидности запроса.
Возвращает:
[
{
"symbol": "LTCBTC",
"orderId": 1,
"clientOrderId": "myOrder1",
"price": "0.1",
"origQty": "1.0",
"executedQty": "0.0",
"status": "NEW",
"timeInForce": "GTC",
"type": "LIMIT",
"side": "BUY",
"stopPrice": "0.0",
"icebergQty": "0.0",
"time": 1499827319559,
"isWorking": true
}
]
Пример кода:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
# Все ордера по паре
print('allOrders', bot.allOrders(
symbol='LTCBTC',
))
Информация по аккаунту - /api/v3/account
Вес – 5
Метод – GET
Параметры:
Обязательные:
timestamp – текущее время (в представленном коде проставляется автоматически, указывать не надо)
Не обязательные:
recvWindow – окно валидности запроса.
Возвращает:
{
"makerCommission": 15,
"takerCommission": 15,
"buyerCommission": 0,
"sellerCommission": 0,
"canTrade": true,
"canWithdraw": true,
"canDeposit": true,
"updateTime": 123456789,
"balances": [
{
"asset": "BTC",
"free": "4723846.89208129",
"locked": "0.00000000"
},
{
"asset": "LTC",
"free": "4763368.68006011",
"locked": "0.00000000"
}
]
}
Пример кода:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
print('account', bot.account())
Список сделок пользователя - /api/v3/myTrades
Метод позволяет получить историю торгов авторизованного пользователя по указанной паре.
Вес – 5.
Параметры:
Обязательные:
symbol – пара
timestamp – текущее время (в представленном коде проставляется автоматически, указывать не надо)
Не обязательные:
limit – кол-во возвращаемых сделок (максимум 500, по умолчанию 500)
fromId – с какой сделки начинать вывод. По умолчанию выводятся самые последние.
recvWindow – окно валидности запроса.
Возвращает:
[
{
"id": 28457,
"orderId": 100234,
"price": "4.00000100",
"qty": "12.00000000",
"commission": "10.10000000",
"commissionAsset": "BNB",
"time": 1499865549590,
"isBuyer": true,
"isMaker": false,
"isBestMatch": true
}
]
Пример кода:
from binance_api import Binance
bot = Binance(
API_KEY='D7...Ejj',
API_SECRET='gwQ...u3A'
)
print('myTrades', bot.myTrades(
symbol='LTCBTC'
))
WAPI
Ввод и вывод средств
Подробное описание будет чуть позже, пока что примеры с комментариями
from binance_api import Binance
bot = Binance(
API_KEY='D7F...Ejj',
API_SECRET='gwQ...u3A'
)
# Получение адреса для депозита
print(bot.depositAddress(asset='BTC'))
# Вывод средств
print(bot.withdraw(asset='XRP', address='1wsdsr234234242', amount=12))
# История пополнений
print(bot.depositHistory(asset='BTC'))
print(bot.depositHistory())
# История выводов
print(bot.withdrawHistory())
print(bot.withdrawHistory(asset='ETH'))
# Узнать комиссию за вывод
print(bot.withdrawFee(asset='BTC'))
# Состояние аккаунта
print(bot.accountStatus())
# Состояние биржи
print(bot.systemStatus())
Проверьте свой код - такая ошибка говорит о том, что какой-то параметр не распознался, возможно написан с опечаткой
Это ограничение бинанса?
Есть вариант обойти?
Я изменил код в статье, можно дальше пользоваться
Ещё вопросик проясните пожалуйста-
можно ли публичные запросы (depth, например) сделать на несколько пар одновременно?
например на Yobite: Depth: https://yobit.net/api/3/depth/ltc_btc-nmc_btc
а то как бы не нарушить их лимиты, при обновлении цен на все пары...(интересует при сравнении бирж - 30-40 пар обычно)
Нужно настроить синхронизацию времени на вашем устройстве, боты сейчас работают, я проверил
имел ввиду, конечно, отображение на бирже ... спасибо за ответ
Есть вопрос - не могу найти информацию по купленным и проданным ордерам за единицу времени, например за последнюю секунду (имею ввиду не пользователя а вообще по бирже по определённому токену). Знаю что бинанс предоставляет эту информацию, но не могу найти как это сделать, Вы не интересовались этим вопросом?
Посмотрите метод aggTrades - можно указать период с разницей в секунду, получите до 500 сделок
Так же можно просто trades - последние 500 сделок, но там придется самому время выбирать из полученных данных
Боюсь, что именно придется собирать самому (или обращаться к тем, кто уже собирает)
ограничения идут на IP или на 1 ключ? если я например сделаю бота в котором будет несколько людей торговать
и если вылетает 429 ответ, он вылетает на IP или на аккаунт
Я бы советовал после получения 429 использовать замедление с увеличением - т.е. грубо говоря на 1 сек сделать паузу, если опять вернулось 429 то уже паузу на 3 сек, потом на 9 например.. При получении 418 сразу минут на 5 тормозить.
Прокси могут помочь, но до этого проще не доводить, все же 1200 запросов в минуту допускается, причем можно всякие курсы и свечи получать по сокетам без ограничений вообще - остается только управлять выставлением ордеров. Более того, по сокетам можно и обновления по своим ордерам получать. В общем, при грамотной архитектуре взаимодейтсвия бана не будет и при сотне клиентов с одного IP
Скачайте обновленную версию бота
Тогда получаем один последний трейд, который предшествует моему startTime и берем его Aggregate tradeId. А потом получаем все трейды после нашего Aggregate tradeId.
Только я не понял причем тут First tradeId? Если я правильно понимаю, то это ссылка на обычные (не агрегированные) трейды. Мне они не нужны. Или не так?
Я ответил вот на эти вопросы
>>> Как в таком случае получить все данные, допустим, за месяц? Особенно, если хочется получать их в порядке от startTime, до endTime?
Я правильно понимаю следующие?
StopLoss купит\продаст, когда цена упадет до\ниже stopPrice? Т.е. stopPrice должен быть меньше текущей цены (иначе сразу сработает).
TakeProfit купит\продаст, когда цена поднимется до\выше stopPrice? Т.е. stopPrice должен быть выше текущей цены (иначе сразу сработает).
Спасибо
Уберите его и будет работать
А если не будет, то нужно синхронизировать своё время с мировым
Но тем не менее спасибо, информация важная
Не знаю как сюда выложить этот кусок кода, фото тоже не вставляет. Вобщем, вот ссыль:
https://skr.sh/s1ea2bqpGuv?a