|
|
|
@ -1,3 +1,5 @@
|
|
|
|
|
from abc import ABC, abstractmethod
|
|
|
|
|
|
|
|
|
|
from alpaca.common.exceptions import APIError
|
|
|
|
|
from glom import glom
|
|
|
|
|
from oandapyV20.exceptions import V20Error
|
|
|
|
@ -61,7 +63,7 @@ def snake_to_camel(word):
|
|
|
|
|
return "".join(x.capitalize() or "_" for x in word.split("_"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BaseExchange(object):
|
|
|
|
|
class BaseExchange(ABC):
|
|
|
|
|
def __init__(self, account):
|
|
|
|
|
name = self.__class__.__name__
|
|
|
|
|
self.name = name.replace("Exchange", "").lower()
|
|
|
|
@ -70,8 +72,9 @@ class BaseExchange(object):
|
|
|
|
|
|
|
|
|
|
self.connect()
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
def connect(self):
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def schema(self):
|
|
|
|
@ -128,6 +131,7 @@ class BaseExchange(object):
|
|
|
|
|
def validate_response(self, response, method):
|
|
|
|
|
schema = self.get_schema(method)
|
|
|
|
|
# Return a dict of the validated response
|
|
|
|
|
print("RESP", response)
|
|
|
|
|
response_valid = schema(**response).dict()
|
|
|
|
|
return response_valid
|
|
|
|
|
|
|
|
|
@ -161,8 +165,9 @@ class BaseExchange(object):
|
|
|
|
|
# log.error(f"Error calling method: {e}")
|
|
|
|
|
# raise GenericAPIError(e)
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
def get_account(self):
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def extract_instrument(self, instruments, instrument):
|
|
|
|
|
for x in instruments["itemlist"]:
|
|
|
|
@ -170,38 +175,50 @@ class BaseExchange(object):
|
|
|
|
|
return x
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
def get_currencies(self, symbols):
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
def get_instruments(self):
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
def get_supported_assets(self):
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
def get_balance(self):
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
def get_market_value(self, symbol):
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
def post_trade(self, trade):
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
def get_trade(self, trade_id):
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
def update_trade(self, trade):
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
def cancel_trade(self, trade_id):
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
def get_position_info(self, symbol):
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
def get_all_positions(self):
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
|
def close_all_positions(self):
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
pass
|
|
|
|
|