mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-03 21:11:55 +08:00
Working on Bittrex implementation and unit tests
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
import base64
|
||||
import numpy as np
|
||||
import hashlib
|
||||
import hmac
|
||||
import json
|
||||
import re
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
import pytz
|
||||
import requests
|
||||
@@ -18,11 +18,9 @@ from catalyst.exchange.exchange import Exchange
|
||||
from catalyst.exchange.exchange_errors import (
|
||||
ExchangeRequestError,
|
||||
InvalidHistoryFrequencyError,
|
||||
InvalidOrderType)
|
||||
from catalyst.finance.execution import (MarketOrder,
|
||||
LimitOrder,
|
||||
StopOrder,
|
||||
StopLimitOrder)
|
||||
InvalidOrderStyle)
|
||||
from catalyst.exchange.exchange_execution import ExchangeLimitOrder, \
|
||||
ExchangeStopLimitOrder, ExchangeStopOrder
|
||||
from catalyst.finance.order import Order, ORDER_STATUS
|
||||
from catalyst.protocol import Account
|
||||
|
||||
@@ -368,14 +366,18 @@ class Bitfinex(Exchange):
|
||||
:return:
|
||||
"""
|
||||
exchange_symbol = self.get_symbol(asset)
|
||||
if isinstance(style, LimitOrder) or isinstance(style, StopLimitOrder):
|
||||
if isinstance(style, ExchangeLimitOrder) \
|
||||
or isinstance(style, ExchangeStopLimitOrder):
|
||||
price = style.get_limit_price(is_buy)
|
||||
order_type = 'limit'
|
||||
elif isinstance(style, StopOrder):
|
||||
|
||||
elif isinstance(style, ExchangeStopOrder):
|
||||
price = style.get_stop_price(is_buy)
|
||||
order_type = 'stop'
|
||||
|
||||
else:
|
||||
raise InvalidOrderType()
|
||||
raise InvalidOrderStyle(exchange=self.name,
|
||||
style=style.__class__.__name__)
|
||||
|
||||
req = dict(
|
||||
symbol=exchange_symbol,
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
from catalyst.exchange.exchange_errors import InvalidHistoryFrequencyError, \
|
||||
ExchangeRequestError
|
||||
import json
|
||||
|
||||
import pandas as pd
|
||||
from catalyst.assets._assets import TradingPair
|
||||
from logbook import Logger
|
||||
from six.moves import urllib
|
||||
import json
|
||||
import pandas as pd
|
||||
|
||||
from catalyst.exchange.exchange import Exchange
|
||||
from catalyst.exchange.bittrex.bittrex_api import Bittrex_api
|
||||
from catalyst.assets._assets import TradingPair
|
||||
from catalyst.exchange.exchange import Exchange
|
||||
from catalyst.exchange.exchange_errors import InvalidHistoryFrequencyError, \
|
||||
ExchangeRequestError, InvalidOrderStyle
|
||||
from catalyst.finance.execution import LimitOrder, StopLimitOrder
|
||||
|
||||
log = Logger('Bittrex')
|
||||
|
||||
@@ -16,8 +18,10 @@ URL2 = 'https://bittrex.com/Api/v2.0'
|
||||
|
||||
class Bittrex(Exchange):
|
||||
def __init__(self, key, secret, base_currency, portfolio=None):
|
||||
self.api = Bittrex_api(key=key, secret=secret)
|
||||
self.api = Bittrex_api(key=key, secret=secret.encode('UTF-8'))
|
||||
self.name = 'bittrex'
|
||||
self.base_currency = base_currency
|
||||
self._portfolio = portfolio
|
||||
|
||||
self.assets = dict()
|
||||
self.load_assets()
|
||||
@@ -78,7 +82,27 @@ class Bittrex(Exchange):
|
||||
|
||||
def create_order(self, asset, amount, is_buy, style):
|
||||
log.info('creating order')
|
||||
pass
|
||||
exchange_symbol = self.get_symbol(asset)
|
||||
if isinstance(style, LimitOrder) or isinstance(style, StopLimitOrder):
|
||||
if isinstance(style, StopLimitOrder):
|
||||
log.warn('{} will ignore the stop price'.format(self.name))
|
||||
|
||||
price = style.get_limit_price(is_buy)
|
||||
try:
|
||||
if is_buy:
|
||||
order = self.api.buylimit(exchange_symbol, amount, price)
|
||||
else:
|
||||
order = self.api.selllimit(exchange_symbol, amount, price)
|
||||
except Exception as e:
|
||||
raise ExchangeRequestError(error=e)
|
||||
|
||||
if 'uuid' in order:
|
||||
return order['uuid']
|
||||
else:
|
||||
raise ExchangeRequestError(error='Order uuid not found.')
|
||||
else:
|
||||
raise InvalidOrderStyle(exchange=self.name,
|
||||
style=style.__class__.__name__)
|
||||
|
||||
def get_open_orders(self, asset):
|
||||
pass
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import abc
|
||||
import random
|
||||
from time import sleep
|
||||
import collections
|
||||
import random
|
||||
from abc import ABCMeta, abstractmethod, abstractproperty
|
||||
from datetime import timedelta
|
||||
from time import sleep
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
@@ -14,15 +13,14 @@ from catalyst.data.data_portal import BASE_FIELDS
|
||||
from catalyst.errors import (
|
||||
SymbolNotFound,
|
||||
)
|
||||
from catalyst.exchange.exchange_errors import InvalidOrderType
|
||||
from catalyst.exchange.exchange_errors import MismatchingBaseCurrencies, \
|
||||
InvalidOrderStyle
|
||||
from catalyst.exchange.exchange_execution import ExchangeStopLimitOrder, \
|
||||
ExchangeLimitOrder, ExchangeStopOrder
|
||||
from catalyst.exchange.exchange_portfolio import ExchangePortfolio
|
||||
from catalyst.exchange.exchange_utils import get_exchange_symbols
|
||||
from catalyst.finance.order import ORDER_STATUS
|
||||
from catalyst.finance.transaction import Transaction
|
||||
from catalyst.exchange.exchange_utils import get_exchange_symbols
|
||||
from catalyst.exchange.exchange_portfolio import ExchangePortfolio
|
||||
from catalyst.finance.execution import (MarketOrder,
|
||||
LimitOrder,
|
||||
StopOrder,
|
||||
StopLimitOrder)
|
||||
|
||||
log = Logger('Exchange')
|
||||
|
||||
@@ -385,7 +383,8 @@ class Exchange:
|
||||
def create_order(self, asset, amount, is_buy, style):
|
||||
pass
|
||||
|
||||
def order(self, asset, amount, limit_price, stop_price, style=None):
|
||||
def order(self, asset, amount, limit_price=None, stop_price=None,
|
||||
style=None):
|
||||
"""Place an order.
|
||||
|
||||
Parameters
|
||||
@@ -430,21 +429,27 @@ class Exchange:
|
||||
return None
|
||||
|
||||
if asset.base_currency != self.base_currency.lower():
|
||||
raise NotImplementedError(
|
||||
'Currency pairs must share their base with the exchange.'
|
||||
raise MismatchingBaseCurrencies(
|
||||
base_currency=asset.base_currency,
|
||||
algo_currency=self.base_currency
|
||||
)
|
||||
|
||||
is_buy = (amount > 0)
|
||||
|
||||
if limit_price is not None and stop_price is not None:
|
||||
style = StopLimitOrder(limit_price, stop_price,
|
||||
exchange=self.name)
|
||||
style = ExchangeStopLimitOrder(limit_price, stop_price,
|
||||
exchange=self.name)
|
||||
elif limit_price is not None:
|
||||
style = LimitOrder(limit_price, exchange=self.name)
|
||||
style = ExchangeLimitOrder(limit_price, exchange=self.name)
|
||||
|
||||
elif stop_price is not None:
|
||||
style = StopOrder(stop_price, exchange=self.name)
|
||||
elif style is None:
|
||||
raise InvalidOrderType()
|
||||
style = ExchangeStopOrder(stop_price, exchange=self.name)
|
||||
|
||||
elif style is not None:
|
||||
raise InvalidOrderStyle(exchange=self.name,
|
||||
style=style.__class__.__name__)
|
||||
else:
|
||||
raise ValueError('Incomplete order data.')
|
||||
|
||||
display_price = limit_price if limit_price is not None else stop_price
|
||||
log.debug(
|
||||
|
||||
@@ -69,9 +69,9 @@ class InvalidSymbolError(ZiplineError):
|
||||
).strip()
|
||||
|
||||
|
||||
class InvalidOrderType(ZiplineError):
|
||||
class InvalidOrderStyle(ZiplineError):
|
||||
msg = (
|
||||
'Order type not found.'
|
||||
'Order style {style} not supported by exchange {exchange}.'
|
||||
).strip()
|
||||
|
||||
|
||||
@@ -79,3 +79,10 @@ class SidHashError(ZiplineError):
|
||||
msg = (
|
||||
'Unable to hash sid from symbol {symbol}.'
|
||||
).strip()
|
||||
|
||||
|
||||
class MismatchingBaseCurrencies(ZiplineError):
|
||||
msg = (
|
||||
'Unable to trade with base currency {base_currency} when the '
|
||||
'algorithm uses {algo_currency}.'
|
||||
).strip()
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
from catalyst.finance.execution import LimitOrder, StopOrder, StopLimitOrder
|
||||
|
||||
|
||||
class ExchangeLimitOrder(LimitOrder):
|
||||
def get_limit_price(self, is_buy):
|
||||
"""
|
||||
We may be trading Satoshis with 8 decimals, we cannot round numbers
|
||||
:param is_buy:
|
||||
:return:
|
||||
"""
|
||||
return self.limit_price
|
||||
|
||||
|
||||
class ExchangeStopOrder(StopOrder):
|
||||
def get_stop_price(self, is_buy):
|
||||
"""
|
||||
We may be trading Satoshis with 8 decimals, we cannot round numbers
|
||||
:param is_buy:
|
||||
:return:
|
||||
"""
|
||||
return self.stop_price
|
||||
|
||||
|
||||
class ExchangeStopLimitOrder(StopLimitOrder):
|
||||
def get_limit_price(self, is_buy):
|
||||
"""
|
||||
We may be trading Satoshis with 8 decimals, we cannot round numbers
|
||||
:param is_buy:
|
||||
:return:
|
||||
"""
|
||||
return self.limit_price
|
||||
|
||||
def get_stop_price(self, is_buy):
|
||||
"""
|
||||
We may be trading Satoshis with 8 decimals, we cannot round numbers
|
||||
:param is_buy:
|
||||
:return:
|
||||
"""
|
||||
return self.stop_price
|
||||
@@ -19,18 +19,16 @@ class BittrexTestCase(BaseExchangeTestCase):
|
||||
self.exchange = Bittrex(
|
||||
key=auth['key'],
|
||||
secret=auth['secret'],
|
||||
base_currency='usd'
|
||||
base_currency='btc'
|
||||
)
|
||||
|
||||
def test_order(self):
|
||||
log.info('creating order')
|
||||
asset = self.exchange.get_asset('neo_eth')
|
||||
asset = self.exchange.get_asset('neo_btc')
|
||||
order_id = self.exchange.order(
|
||||
asset=asset,
|
||||
style=LimitOrder(limit_price=200),
|
||||
limit_price=200,
|
||||
amount=0.5,
|
||||
stop_price=None
|
||||
limit_price=0.00055,
|
||||
amount=1,
|
||||
)
|
||||
log.info('order created {}'.format(order_id))
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user