stable/freqtrade/exchange/bittrex.py

140 lines
4.7 KiB
Python
Raw Normal View History

2017-10-06 10:22:04 +00:00
import logging
from typing import List, Dict
2017-10-06 10:22:04 +00:00
2017-11-11 16:14:55 +00:00
from bittrex.bittrex import Bittrex as _Bittrex, API_V2_0, API_V1_1
2017-10-06 10:22:04 +00:00
from freqtrade.exchange.interface import Exchange
2017-10-06 10:22:04 +00:00
logger = logging.getLogger(__name__)
_API: _Bittrex = None
2017-11-11 16:14:55 +00:00
_API_V2: _Bittrex = None
2017-10-06 10:22:04 +00:00
_EXCHANGE_CONF: dict = {}
class Bittrex(Exchange):
"""
Bittrex API wrapper.
"""
# Base URL and API endpoints
BASE_URL: str = 'https://www.bittrex.com'
PAIR_DETAIL_METHOD: str = BASE_URL + '/Market/Index'
def __init__(self, config: dict) -> None:
2017-11-11 16:14:55 +00:00
global _API, _API_V2, _EXCHANGE_CONF
2017-10-06 10:22:04 +00:00
_EXCHANGE_CONF.update(config)
2017-11-08 23:31:53 +00:00
_API = _Bittrex(
api_key=_EXCHANGE_CONF['key'],
api_secret=_EXCHANGE_CONF['secret'],
2017-11-11 14:29:31 +00:00
calls_per_second=3,
2017-11-11 16:14:55 +00:00
api_version=API_V1_1,
)
_API_V2 = _Bittrex(
api_key=_EXCHANGE_CONF['key'],
api_secret=_EXCHANGE_CONF['secret'],
calls_per_second=3,
api_version=API_V2_0,
2017-11-08 23:31:53 +00:00
)
2017-10-06 10:22:04 +00:00
@property
def fee(self) -> float:
# See https://bittrex.com/fees
return 0.0025
2017-10-06 10:22:04 +00:00
def buy(self, pair: str, rate: float, amount: float) -> str:
data = _API.buy_limit(pair.replace('_', '-'), amount, rate)
if not data['success']:
2017-11-05 21:47:55 +00:00
raise RuntimeError('{message} params=({pair}, {rate}, {amount})'.format(
message=data['message'],
pair=pair,
rate=rate,
amount=amount))
2017-10-06 10:22:04 +00:00
return data['result']['uuid']
def sell(self, pair: str, rate: float, amount: float) -> str:
data = _API.sell_limit(pair.replace('_', '-'), amount, rate)
if not data['success']:
2017-11-05 21:47:55 +00:00
raise RuntimeError('{message} params=({pair}, {rate}, {amount})'.format(
message=data['message'],
pair=pair,
rate=rate,
amount=amount))
2017-10-06 10:22:04 +00:00
return data['result']['uuid']
def get_balance(self, currency: str) -> float:
data = _API.get_balance(currency)
if not data['success']:
2017-11-05 21:47:55 +00:00
raise RuntimeError('{message} params=({currency})'.format(
message=data['message'],
currency=currency))
2017-10-06 10:22:04 +00:00
return float(data['result']['Balance'] or 0.0)
def get_balances(self):
data = _API.get_balances()
if not data['success']:
2017-11-05 21:47:55 +00:00
raise RuntimeError('{message}'.format(message=data['message']))
return data['result']
2017-11-04 17:55:41 +00:00
2017-10-06 10:22:04 +00:00
def get_ticker(self, pair: str) -> dict:
data = _API.get_ticker(pair.replace('_', '-'))
if not data['success']:
2017-11-05 21:47:55 +00:00
raise RuntimeError('{message} params=({pair})'.format(
message=data['message'],
pair=pair))
2017-10-06 10:22:04 +00:00
return {
'bid': float(data['result']['Bid']),
'ask': float(data['result']['Ask']),
'last': float(data['result']['Last']),
}
def get_ticker_history(self, pair: str, tick_interval: int):
if tick_interval == 1:
interval = 'oneMin'
elif tick_interval == 5:
interval = 'fiveMin'
else:
raise ValueError('Cannot parse tick_interval: {}'.format(tick_interval))
2017-11-11 16:14:55 +00:00
data = _API_V2.get_candles(pair.replace('_', '-'), interval)
2017-10-06 10:22:04 +00:00
if not data['success']:
raise RuntimeError('{message} params=({pair})'.format(
2017-11-05 21:47:55 +00:00
message=data['message'],
pair=pair))
return data['result']
2017-10-06 10:22:04 +00:00
def get_order(self, order_id: str) -> Dict:
data = _API.get_order(order_id)
2017-10-06 10:22:04 +00:00
if not data['success']:
2017-11-05 21:47:55 +00:00
raise RuntimeError('{message} params=({order_id})'.format(
message=data['message'],
order_id=order_id))
data = data['result']
return {
'id': data['OrderUuid'],
'type': data['Type'],
'pair': data['Exchange'].replace('-', '_'),
'opened': data['Opened'],
'rate': data['PricePerUnit'],
'amount': data['Quantity'],
'remaining': data['QuantityRemaining'],
'closed': data['Closed'],
}
2017-10-06 10:22:04 +00:00
def cancel_order(self, order_id: str) -> None:
data = _API.cancel(order_id)
2017-10-06 10:22:04 +00:00
if not data['success']:
2017-11-05 21:47:55 +00:00
raise RuntimeError('{message} params=({order_id})'.format(
message=data['message'],
order_id=order_id))
2017-10-06 10:22:04 +00:00
def get_pair_detail_url(self, pair: str) -> str:
return self.PAIR_DETAIL_METHOD + '?MarketName={}'.format(pair.replace('_', '-'))
def get_markets(self) -> List[str]:
data = _API.get_markets()
if not data['success']:
2017-11-05 21:47:55 +00:00
raise RuntimeError('{message}'.format(message=data['message']))
2017-10-06 10:22:04 +00:00
return [m['MarketName'].replace('-', '_') for m in data['result']]