mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-11 09:08:25 +08:00
BLD: some refactoring to simplify the integration logic and tested several algos
This commit is contained in:
@@ -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):
|
||||
"""
|
||||
|
||||
@@ -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]:
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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']
|
||||
|
||||
|
||||
Reference in New Issue
Block a user