diff --git a/catalyst/exchange/exchange_bundle.py b/catalyst/exchange/exchange_bundle.py index a7aa3643..7aab5dc6 100644 --- a/catalyst/exchange/exchange_bundle.py +++ b/catalyst/exchange/exchange_bundle.py @@ -24,7 +24,7 @@ from catalyst.utils.paths import ensure_directory log = Logger('exchange_bundle', level=LOG_LEVEL) -BUNDLE_NAME_TEMPLATE = '{root}/{frequency}_bundle' +BUNDLE_NAME_TEMPLATE = os.path.join('{root}','{frequency}_bundle') def _cachpath(symbol, type_): return '-'.join([symbol, type_]) @@ -171,7 +171,7 @@ class ExchangeBundle: invalid_data_behavior='raise' ) except BcolzMinuteOverlappingData as e: - log.warn('chunk already exists: {}'.format(e)) + log.debug('chunk already exists: {}'.format(e)) except Exception as e: log.warn('error when writing data: {}, trying again'.format(e)) @@ -318,6 +318,9 @@ class ExchangeBundle: except NoDataAvailableOnExchange: continue + start_dt = max(start_dt, self.calendar.first_trading_session) + start_dt = max(start_dt, asset_start) + # Aligning start / end dates with the daily calendar sessions = get_periods_range(start_dt, end_dt, data_frequency) \ if data_frequency == 'minute' \ diff --git a/catalyst/exchange/exchange_errors.py b/catalyst/exchange/exchange_errors.py index a34d5bfa..c5baadec 100644 --- a/catalyst/exchange/exchange_errors.py +++ b/catalyst/exchange/exchange_errors.py @@ -6,7 +6,8 @@ from catalyst.errors import ZiplineError def silent_except_hook(exctype, excvalue, exctraceback): if exctype in [PricingDataBeforeTradingError, PricingDataNotLoadedError, - SymbolNotFoundOnExchange, NoDataAvailableOnExchange, ]: + SymbolNotFoundOnExchange, NoDataAvailableOnExchange, + ExchangeAuthEmpty ]: fn = traceback.extract_tb(exctraceback)[-1][0] ln = traceback.extract_tb(exctraceback)[-1][1] print "Error traceback: {1} (line {2})\n" \ @@ -65,6 +66,13 @@ class ExchangeAuthNotFound(ZiplineError): ).strip() +class ExchangeAuthEmpty(ZiplineError): + msg = ( + 'Please enter your API token key and secret for exchange {exchange} ' + 'in the following file: {filename}' + ).strip() + + class ExchangeSymbolsNotFound(ZiplineError): msg = ( 'Unable to download or find a local copy of symbols.json for exchange ' diff --git a/catalyst/exchange/exchange_utils.py b/catalyst/exchange/exchange_utils.py index 23220afc..b9e6cf21 100644 --- a/catalyst/exchange/exchange_utils.py +++ b/catalyst/exchange/exchange_utils.py @@ -65,11 +65,10 @@ def get_exchange_auth(exchange_name, environ=None): data = json.load(data_file) return data else: - raise ExchangeAuthNotFound( - exchange=exchange_name, - filename=filename - ) - + data = dict(name=exchange_name, key='', secret='') + with open(filename, 'w') as f: + json.dump(data, f, sort_keys=False, indent=2, separators=(',', ':')) + return data def get_algo_folder(algo_name, environ=None): if not environ: diff --git a/catalyst/utils/run_algo.py b/catalyst/utils/run_algo.py index 5cff0afe..a5293ac5 100644 --- a/catalyst/utils/run_algo.py +++ b/catalyst/utils/run_algo.py @@ -36,11 +36,11 @@ from catalyst.exchange.data_portal_exchange import DataPortalExchangeLive, \ from catalyst.exchange.asset_finder_exchange import AssetFinderExchange from catalyst.exchange.exchange_portfolio import ExchangePortfolio from catalyst.exchange.exchange_errors import ( - ExchangeRequestError, + ExchangeRequestError, ExchangeAuthEmpty, ExchangeRequestErrorTooManyAttempts, BaseCurrencyNotFoundError, ExchangeNotFoundError) from catalyst.exchange.exchange_utils import get_exchange_auth, \ - get_algo_object + get_algo_object, get_exchange_folder from logbook import Logger from catalyst.constants import LOG_LEVEL @@ -166,6 +166,12 @@ def _run(handle_data, # This corresponds to the json file containing api token info exchange_auth = get_exchange_auth(exchange_name) + + if live and (exchange_auth['key'] == '' or exchange_auth['secret'] == ''): + raise ExchangeAuthEmpty( + exchange=exchange_name.title(), + filename=os.path.join(get_exchange_folder(exchange_name, environ), 'auth.json') ) + if exchange_name == 'bitfinex': exchanges[exchange_name] = Bitfinex( key=exchange_auth['key'],