from bittrex.bittrex import Bittrex, API_V1_1, SELL_ORDERBOOK, BUY_ORDERBOOK
from decimal import Decimal
import datetime as dt
from .broker import BrokerBaseClass
from ..exchange import BittrexExchange
from ..database.executed_order import ExecutedOrder
import logging
[docs]class BittrexBroker(BrokerBaseClass):
"""
Inherits from alchemist_lib.broker.broker.BrokerBaseClass.
Website: https://bittrex.com/
Api documentation: https://bittrex.com/Home/Api
Api wrapper: https://github.com/ericsomdahl/python-bittrex
Attributes:
session (sqlalchemy.orm.session.Session): Database connection.
bittrex (bittrex.bittrex.Bittrex): Communication object.
"""
[docs] def __init__(self, api_key = None, secret_key = None):
"""
Costructor method.
Args:
api_key (str): The api key provided by Bittrex.
secret_key (str): The secret key provided by Bittrex.
Note:
https://bittrex.com/Manage#sectionApi
https://cryptocatbot.com/api-key-activation-exchanges/
"""
BrokerBaseClass.__init__(self)
self.bittrex = Bittrex(api_key = api_key, api_secret = secret_key, api_version = API_V1_1)
def get_best_rate(self, asset, amount, field):
"""
Bittrex doesnt allow to place market orders submitted via API so we need to get the best bid/ask price for every order.
Args:
asset (alchemist_lib.database.asset.Asset): The asset we want exchange for BTC.
amount (decimal.Decimal): The amount we want to exchange.
field (str): Must be "ask" or "bid".
Return:
price (decimal.Decimal): The best bid/ask, execute an order at this price is like execute a market order. If the book is too thin the return value is 0.
"""
amount = abs(amount)
pair = "BTC-{}".format(asset.ticker)
if field == "ask":
book = self.bittrex.get_orderbook(market = pair, depth_type = SELL_ORDERBOOK)
if book["success"] == False or book["result"] == None:
logging.debug("Bittrex api result is None or success is False. get_best_rate() method. Asset: {}".format(asset.ticker))
return Decimal(0)
else:
book = self.bittrex.get_orderbook(market = pair, depth_type = BUY_ORDERBOOK)
if book["success"] == False or book["result"] == None:
logging.debug("Bittrex api result is None or success is False. get_best_rate() method. Asset: {}".format(asset.ticker))
return Decimal(0)
values = book["result"]
orders_sum = Decimal(0)
for book_item in values:
orders_sum += Decimal(book_item["Quantity"])
if orders_sum > amount:
return Decimal(book_item["Rate"])
return Decimal(0)
[docs] def place_order(self, asset, amount, order_type):
"""
Method to place an order.
Args:
asset (alchemist_lib.database.asset.Asset): The asset we want exchange for BTC.
amount (decimal.Decimal): The amount we want to exchange.
order_type (str): Type of order.
Return:
order_id (str, int): The order identifier, if some error occurs returns int(-1).
"""
pair = "BTC-{}".format(asset.ticker)
min_order_size = BittrexExchange().get_min_order_size(asset = asset)
logging.debug("Min order size for {} is {}".format(asset, min_order_size))
if amount > min_order_size:
field = "ask"
operation = "buy"
elif amount < (min_order_size * (-1)):
field = "bid"
operation = "sell"
else:
return -1
if order_type == "MKT":
rate = self.get_best_rate(asset = asset, amount = abs(amount), field = field)
else:
logging.critical("Unknown order type. NotImplemented raised.")
raise NotImplemented
logging.debug("Order: Pair: {}. Amount: {}. Operation: {}".format(pair, amount, operation))
if operation == "buy":
order_return_dict = self.bittrex.buy_limit(market = pair, rate = rate, quantity = amount)
else:
order_return_dict = self.bittrex.sell_limit(market = pair, rate = rate, quantity = abs(amount))
if order_return_dict["result"] == None:
logging.warning("Bittrex api result is None or success is False. place_order() method. Order id will be -1. Asset: {}".format(asset.ticker))
return -1
order_id = str(order_return_dict["result"]["uuid"])
logging.info("{} order placed for {}. Amount: {}. Order id: {}.".format(operation.upper(), asset.ticker, amount, order_id))
order = ExecutedOrder(order_id = order_id,
order_datetime = dt.datetime.utcnow(),
ticker = asset.ticker,
instrument_id = asset.instrument_id,
amount = amount,
operation = operation,
order_type = order_type,
broker_name = "bittrex",
exchange_name = "bittrex"
)
self.session.add(order)
self.session.commit()
return order_id