BLD: some refactoring to simplify the integration logic and tested several algos

This commit is contained in:
fredfortier
2017-12-02 21:27:03 -05:00
parent a3838fc00f
commit f995f451a7
4 changed files with 153 additions and 43 deletions
+3 -3
View File
@@ -516,7 +516,7 @@ cdef class TradingPair(Asset):
symbol = symbol.lower()
try:
self.base_currency,self.quote_currency = symbol.split('_')
self.base_currency, self.quote_currency = symbol.split('_')
except Exception as e:
raise InvalidSymbolError(symbol=symbol, error=e)
@@ -600,8 +600,8 @@ cdef class TradingPair(Asset):
-------
boolean: whether the asset's exchange is open at the given minute.
"""
#TODO: consider implementing to spot holds
return self.trading_state > 0
#TODO: make more dymanic to catch holds
return True
cpdef __reduce__(self):
"""
+83 -5
View File
@@ -84,6 +84,19 @@ class CCXT(Exchange):
return None
def get_market(self, symbol):
"""
The CCXT market.
Parameters
----------
symbol:
The CCXT symbol.
Returns
-------
dict[str, Object]
"""
s = self.get_symbol(symbol)
market = next(
(market for market in self.markets if market['symbol'] == s),
@@ -92,6 +105,17 @@ class CCXT(Exchange):
return market
def get_symbol(self, asset_or_symbol):
"""
The CCXT symbol.
Parameters
----------
asset_or_symbol
Returns
-------
"""
symbol = asset_or_symbol if isinstance(
asset_or_symbol, string_types
) else asset_or_symbol.symbol
@@ -100,6 +124,17 @@ class CCXT(Exchange):
return '{}/{}'.format(parts[0].upper(), parts[1].upper())
def get_catalyst_symbol(self, market_or_symbol):
"""
The Catalyst symbol.
Parameters
----------
market_or_symbol
Returns
-------
"""
if isinstance(market_or_symbol, string_types):
parts = market_or_symbol.split('/')
return '{}_{}'.format(parts[0].lower(), parts[1].lower())
@@ -111,6 +146,19 @@ class CCXT(Exchange):
)
def get_timeframe(self, freq):
"""
The CCXT timeframe from the Catalyst frequency.
Parameters
----------
freq: str
The Catalyst frequency (Pandas convention)
Returns
-------
str
"""
freq_match = re.match(r'([0-9].*)?(m|M|d|D|h|H|T)', freq, re.M | re.I)
if freq_match:
candle_size = int(freq_match.group(1)) \
@@ -168,16 +216,47 @@ class CCXT(Exchange):
except ExchangeSymbolsNotFound:
return None
def fetch_asset_defs(self, market):
def get_asset_defs(self, market):
"""
The local and Catalyst definitions of the specified market.
Parameters
----------
market: dict[str, Object]
The CCXT market dicts.
Returns
-------
dict[str, Object]
The asset definition.
"""
asset_defs = []
for is_local in (False, True):
asset_def = self.fetch_asset_def(market, is_local)
asset_def = self.get_asset_def(market, is_local)
asset_defs.append((asset_def, is_local))
return asset_defs
def fetch_asset_def(self, market, is_local=False):
def get_asset_def(self, market, is_local=False):
"""
The asset definition (in symbols.json files) corresponding
to the the specified market.
Parameters
----------
market: dict[str, Object]
The CCXT market dict.
is_local
Whether to search in local or Catalyst asset definitions.
Returns
-------
dict[str, Object]
The asset definition.
"""
exchange_symbol = market['id']
symbol_map = self._fetch_symbol_map(is_local)
@@ -250,8 +329,7 @@ class CCXT(Exchange):
self.assets = []
for market in self.markets:
log.debug('fetching asset for market: {}'.format(market['id']))
asset_defs = self.fetch_asset_defs(market)
asset_defs = self.get_asset_defs(market)
for asset_def in asset_defs:
if asset_def[0] is not None or not asset_defs[1]:
+66 -34
View File
@@ -175,71 +175,102 @@ class Exchange:
return symbols
def get_assets(self, symbols=None, data_frequency=None):
def get_assets(self, symbols=None, data_frequency=None,
is_exchange_symbol=False,
is_local=None):
"""
The list of markets for the specified symbols.
Parameters
----------
symbols: list[str]
data_frequency: str
is_exchange_symbol: bool
is_local: bool
Returns
-------
list[TradingPair]
A list of asset objects.
Notes
-----
See get_asset for details of each parameter.
"""
if symbols is None:
# Make a distinct list of all symbols
symbols = list(set([asset.symbol for asset in self.assets]))
is_exchange_symbol = False
if symbols is not None:
assets = []
for symbol in symbols:
asset = self.get_asset(symbol, data_frequency)
assets.append(asset)
return assets
else:
return self.assets
assets = []
for symbol in symbols:
asset = self.get_asset(
symbol, data_frequency, is_exchange_symbol, is_local
)
assets.append(asset)
return assets
def _find_asset(self, asset, symbol, data_frequency, is_exchange_symbol,
is_local=False):
for a in self.assets:
has_data = (data_frequency == 'minute'
and a.end_minute is not None) \
or (data_frequency == 'daily'
and a.end_daily is not None)
symbol_attr = a.exchange_symbol if is_exchange_symbol else a.symbol
if not asset and symbol_attr.lower() == symbol.lower() \
and (not data_frequency or has_data):
asset = a
return asset
def get_asset(self, symbol, data_frequency=None, is_exchange_symbol=False):
def get_asset(self, symbol, data_frequency=None, is_exchange_symbol=False,
is_local=None):
"""
The market for the specified symbol.
Parameters
----------
symbol: str
The Catalyst or exchange symbol.
data_frequency: str
Check for asset corresponding to the specified data_frequency.
The same asset might exist in the Catalyst repository or
locally (following a CSV ingestion). Filtering by
data_frequency picks the right asset.
is_exchange_symbol: bool
Whether the symbol uses the Catalyst or exchange convention.
is_local: bool
For the local or Catalyst asset.
Returns
-------
TradingPair
The asset object.
"""
asset = None
log.debug('searching asset {} on the server'.format(symbol))
asset = self._find_asset(
asset, symbol, data_frequency, is_exchange_symbol, False
log.debug(
'searching assets for: {} {}'.format(
self.name, symbol
)
)
for a in self.assets:
if asset is not None:
break
log.debug('asset {} not found on the server, searching local '
'assets'.format(symbol))
asset = self._find_asset(
asset, symbol, data_frequency, is_exchange_symbol, True
)
if is_local is not None:
data_source = 'local' if is_local else 'catalyst'
applies = (a.data_source == data_source)
elif data_frequency is not None:
applies = (
(data_frequency == 'minute' and a.end_minute is not None)
or (data_frequency == 'daily' and a.end_daily is not None)
)
else:
applies = True
# The symbol provided may use the Catalyst or the exchange
# convention
key = a.exchange_symbol if is_exchange_symbol else a.symbol
if not asset and key.lower() == symbol.lower() and applies:
asset = a
if asset is None:
if not asset:
supported_symbols = sorted([
asset.symbol for asset in self.assets
])
@@ -250,6 +281,7 @@ class Exchange:
supported_symbols=supported_symbols
)
log.debug('found asset: {}'.format(asset))
return asset
def fetch_symbol_map(self, is_local=False):
+1 -1
View File
@@ -715,7 +715,7 @@ class ExchangeBundle:
)
mixin_market_params(self.exchange_name, params, market)
asset_def = self.exchange.fetch_asset_def(market, True)
asset_def = self.exchange.get_asset_def(market, True)
if asset_def is not None:
params['symbol'] = asset_def['symbol']