From 3b10a59572216431e48990e4a4c5fe59c6979a78 Mon Sep 17 00:00:00 2001 From: Caio Oliveira Date: Sat, 30 Dec 2017 13:53:48 -0200 Subject: [PATCH 1/6] refactoring `_run`: first iteration Split the juggernaut function into smaller functions and commented about some possible issues --- catalyst/utils/run_algo.py | 422 ++++++++++++++++++++----------------- 1 file changed, 228 insertions(+), 194 deletions(-) diff --git a/catalyst/utils/run_algo.py b/catalyst/utils/run_algo.py index 015f91e4..a5fb873a 100644 --- a/catalyst/utils/run_algo.py +++ b/catalyst/utils/run_algo.py @@ -70,36 +70,7 @@ class _RunAlgoError(click.ClickException, ValueError): return self.pyfunc_msg -def _run(handle_data, - initialize, - before_trading_start, - analyze, - algofile, - algotext, - defines, - data_frequency, - capital_base, - data, - bundle, - bundle_timestamp, - start, - end, - output, - print_algo, - local_namespace, - environ, - live, - exchange, - algo_namespace, - base_currency, - live_graph, - analyze_live, - simulate_orders, - stats_output): - """Run a backtest for the given algorithm. - - This is shared between the cli and :func:`catalyst.run_algo`. - """ +def _build_namespace(algotext, local_namespace, defines): if algotext is not None: if local_namespace: ip = get_ipython() # noqa @@ -130,155 +101,221 @@ def _run(handle_data, ) else: namespace = {} - if algofile is not None: - algotext = algofile.read() - if print_algo: - if PYGMENTS: - highlight( - algotext, - PythonLexer(), - TerminalFormatter(), - outfile=sys.stdout, - ) - else: - click.echo(algotext) + return namespace - mode = 'paper-trading' if simulate_orders else 'live-trading' \ - if live else 'backtest' - log.info('running algo in {mode} mode'.format(mode=mode)) +def _mode(simulate_orders, live): + if not live: + return 'backtest' + elif simulate_orders: + return 'paper-trading' + else: + return 'live-trading' + + +def _build_exchanges_dict(exchange, live, simulate_orders, base_currency): exchange_name = exchange if exchange_name is None: raise ValueError('Please specify at least one exchange.') exchange_list = [x.strip().lower() for x in exchange.split(',')] - exchanges = dict() - for exchange_name in exchange_list: - exchanges[exchange_name] = get_exchange( - exchange_name=exchange_name, - base_currency=base_currency, - must_authenticate=(live and not simulate_orders), - skip_init=True, + exchanges = {exchange_name: get_exchange( + exchange_name=exchange_name, + base_currency=base_currency, + must_authenticate=(live and not simulate_orders), + skip_init=True) + for exchange_name in exchange_list} + + return exchanges + + +def _pretty_print_code(algotext): + if PYGMENTS: + highlight( + algotext, + PythonLexer(), + TerminalFormatter(), + outfile=sys.stdout, ) + else: + click.echo(algotext) + + +def _choose_loader(data_frequency, column): + bound_cols = TradingPairPricing.columns + if column in bound_cols: + return ExchangePricingLoader(data_frequency) + raise ValueError( + "No PipelineLoader registered for column %s." % column + ) + + +def _get_live_time_range(): + start = pd.Timestamp.utcnow() + # TODO: fix the end data. + end = start + timedelta(hours=8760) + return start, end + + +def _data_for_live_trading(sim_params, exchanges, env, open_calendar): + data = DataPortalExchangeLive( + exchanges=exchanges, + asset_finder=env.asset_finder, + trading_calendar=open_calendar, + first_trading_day=pd.to_datetime('today', utc=True)) + + return data + + +# TODO use proper retry here +def _fetch_capital_base(base_currency, exchange_name, exchange, + attempt_index=0): + """ + Fetch the base currency amount required to bootstrap + the algorithm against the exchange. + + The algorithm cannot continue without this value. + + :param exchange: the targeted exchange + :param attempt_index: + :return capital_base: the amount of base currency available for + trading + """ + try: + log.debug('retrieving capital base in {} to bootstrap ' + 'exchange {}'.format(base_currency, exchange_name)) + balances = exchange.get_balances() + except ExchangeRequestError as e: + if attempt_index < 20: + log.warn( + 'could not retrieve balances on {}: {}'.format( + exchange.name, e + ) + ) + sleep(5) + return _fetch_capital_base(base_currency, exchange_name, exchange, + attempt_index + 1) + + else: + raise ExchangeRequestErrorTooManyAttempts( + attempts=attempt_index, + error=e) + + if base_currency in balances: + base_currency_available = balances[base_currency]['free'] + log.info( + 'base currency available in the account: {} {}'.format( + base_currency_available, base_currency)) + + return base_currency_available + else: + raise BaseCurrencyNotFoundError( + base_currency=base_currency, + exchange=exchange_name) + + +def _algorithm_class_for_live(algo_namespace, live_graph, stats_output, + analyze_live, base_currency, simulate_orders, + exchanges, capital_base): + if not simulate_orders: + for exchange_name in exchanges: + exchange = exchanges[exchange_name] + balance = _fetch_capital_base(base_currency, exchange_name, + exchange) + + if balance < capital_base: + raise NotEnoughCapitalError( + exchange=exchange_name, + base_currency=base_currency, + balance=balance, + capital_base=capital_base) + + algorithm_class = partial( + ExchangeTradingAlgorithmLive, + exchanges=exchanges, + algo_namespace=algo_namespace, + live_graph=live_graph, + simulate_orders=simulate_orders, + stats_output=stats_output, + analyze_live=analyze_live, + ) + + return algorithm_class + + +def _bundle_trading_environment(bundle_data, environ): + prefix, connstr = re.split( + r'sqlite:///', + str(bundle_data.asset_finder.engine.url), + maxsplit=1, + ) + if prefix: + raise ValueError( + "invalid url %r, must begin with 'sqlite:///'" % + str(bundle_data.asset_finder.engine.url), + ) + + return TradingEnvironment(asset_db_path=connstr, environ=environ) + + +def _build_algo_and_data(handle_data, initialize, before_trading_start, + analyze, algofile, algotext, defines, data_frequency, + capital_base, data, bundle, bundle_timestamp, start, + end, output, print_algo, local_namespace, environ, + live, exchange, algo_namespace, base_currency, + live_graph, analyze_live, simulate_orders, + stats_output): + namespace = _build_namespace(algotext, local_namespace, defines) + if algotext is not None: + algotext = algofile.read() + + if print_algo: + _pretty_print_code(algotext) + + mode = _mode(simulate_orders, live) + log.info('running algo in {mode} mode'.format(mode=mode)) + + exchanges = _build_exchanges_dict(exchange, live, simulate_orders, + base_currency) open_calendar = get_calendar('OPEN') env = TradingEnvironment( - load=partial( - load_crypto_market_data, - environ=environ, - start_dt=start, - end_dt=end - ), + load=partial(load_crypto_market_data, environ=environ, start_dt=start, + end_dt=end), environ=environ, exchange_tz='UTC', asset_db_path=None # We don't need an asset db, we have exchanges ) env.asset_finder = ExchangeAssetFinder(exchanges=exchanges) - def choose_loader(column): - bound_cols = TradingPairPricing.columns - if column in bound_cols: - return ExchangePricingLoader(data_frequency) - raise ValueError( - "No PipelineLoader registered for column %s." % column - ) + choose_loader = partial(_choose_loader, data_frequency) if live: - start = pd.Timestamp.utcnow() + start, end = _get_live_time_range() + # TODO double check if this is the desired behavior + data_frequency = 'minute' - # TODO: fix the end data. - end = start + timedelta(hours=8760) - - data = DataPortalExchangeLive( - exchanges=exchanges, - asset_finder=env.asset_finder, - trading_calendar=open_calendar, - first_trading_day=pd.to_datetime('today', utc=True) - ) - - def fetch_capital_base(exchange, attempt_index=0): - """ - Fetch the base currency amount required to bootstrap - the algorithm against the exchange. - - The algorithm cannot continue without this value. - - :param exchange: the targeted exchange - :param attempt_index: - :return capital_base: the amount of base currency available for - trading - """ - try: - log.debug('retrieving capital base in {} to bootstrap ' - 'exchange {}'.format(base_currency, exchange_name)) - balances = exchange.get_balances() - except ExchangeRequestError as e: - if attempt_index < 20: - log.warn( - 'could not retrieve balances on {}: {}'.format( - exchange.name, e - ) - ) - sleep(5) - return fetch_capital_base(exchange, attempt_index + 1) - - else: - raise ExchangeRequestErrorTooManyAttempts( - attempts=attempt_index, - error=e - ) - - if base_currency in balances: - base_currency_available = balances[base_currency]['free'] - log.info( - 'base currency available in the account: {} {}'.format( - base_currency_available, base_currency - ) - ) - - return base_currency_available - else: - raise BaseCurrencyNotFoundError( - base_currency=base_currency, - exchange=exchange_name - ) - - if not simulate_orders: - for exchange_name in exchanges: - exchange = exchanges[exchange_name] - balance = fetch_capital_base(exchange) - - if balance < capital_base: - raise NotEnoughCapitalError( - exchange=exchange_name, - base_currency=base_currency, - balance=balance, - capital_base=capital_base, - ) - - sim_params = create_simulation_parameters( - start=start, - end=end, - capital_base=capital_base, - emission_rate='minute', - data_frequency='minute' - ) + sim_params = create_simulation_parameters( + start=start, + end=end, + capital_base=capital_base, + emission_rate=data_frequency, + data_frequency=data_frequency) + if live: # TODO: use the constructor instead sim_params._arena = 'live' - algorithm_class = partial( - ExchangeTradingAlgorithmLive, - exchanges=exchanges, - algo_namespace=algo_namespace, - live_graph=live_graph, - simulate_orders=simulate_orders, - stats_output=stats_output, - analyze_live=analyze_live, - ) + data = _data_for_live_trading( + exchanges, env, open_calendar, simulate_orders, + algo_namespace, capital_base) + + algorithm_class = _algorithm_class_for_live( + algo_namespace, live_graph, stats_output, analyze_live, + base_currency, simulate_orders, exchanges, capital_base) elif exchanges: # Removed the existing Poloniex fork to keep things simple # We can add back the complexity if required. @@ -293,41 +330,19 @@ def _run(handle_data, asset_finder=None, trading_calendar=open_calendar, first_trading_day=start, - last_available_session=end - ) - - sim_params = create_simulation_parameters( - start=start, - end=end, - capital_base=capital_base, - data_frequency=data_frequency, - emission_rate=data_frequency, - ) + last_available_session=end) algorithm_class = partial( ExchangeTradingAlgorithmBacktest, - exchanges=exchanges - ) - + exchanges=exchanges) elif bundle is not None: - bundle_data = load( - bundle, - environ, - bundle_timestamp, - ) + # TODO This branch should probably be removed or fixed: it doesn't even + # build `algorithm_class`, so it will break when trying to instantiate + # it. + bundle_data = load(bundle, environ, bundle_timestamp) - prefix, connstr = re.split( - r'sqlite:///', - str(bundle_data.asset_finder.engine.url), - maxsplit=1, - ) - if prefix: - raise ValueError( - "invalid url %r, must begin with 'sqlite:///'" % - str(bundle_data.asset_finder.engine.url), - ) + env = _bundle_trading_environment(bundle_data, environ) - env = TradingEnvironment(asset_db_path=connstr, environ=environ) first_trading_day = \ bundle_data.equity_minute_bar_reader.first_trading_day @@ -336,24 +351,43 @@ def _run(handle_data, first_trading_day=first_trading_day, equity_minute_reader=bundle_data.equity_minute_bar_reader, equity_daily_reader=bundle_data.equity_daily_bar_reader, - adjustment_reader=bundle_data.adjustment_reader, - ) + adjustment_reader=bundle_data.adjustment_reader,) - perf = algorithm_class( + if algotext is None: + algorithm_class_kwargs = {'initialize': initialize, + 'handle_data': handle_data, + 'before_trading_start': before_trading_start, + 'analyze': analyze} + else: + algorithm_class_kwargs = {'algo_filename': getattr(algofile, 'name', + ''), + 'script': algotext} + return data, algorithm_class( namespace=namespace, env=env, get_pipeline_loader=choose_loader, sim_params=sim_params, - **{ - 'initialize': initialize, - 'handle_data': handle_data, - 'before_trading_start': before_trading_start, - 'analyze': analyze, - } if algotext is None else { - 'algo_filename': getattr(algofile, 'name', ''), - 'script': algotext, - } - ).run( + **algorithm_class_kwargs) + + +def _run(handle_data, initialize, before_trading_start, analyze, algofile, + algotext, defines, data_frequency, capital_base, data, bundle, + bundle_timestamp, start, end, output, print_algo, local_namespace, + environ, live, exchange, algo_namespace, base_currency, live_graph, + analyze_live, simulate_orders, stats_output): + """Run an algorithm in backtest, + paper-trading or live-trading mode. + + This is shared between the cli and :func:`catalyst.run_algo`. + """ + + data, algorithm = _build_algo_and_data( + handle_data, initialize, before_trading_start, analyze, algofile, + algotext, defines, data_frequency, capital_base, data, bundle, + bundle_timestamp, start, end, output, print_algo, local_namespace, + environ, live, exchange, algo_namespace, base_currency, live_graph, + analyze_live, simulate_orders, stats_output) + perf = algorithm.run( data, overwrite_sim_params=False, ) From cf89e01a510c433dac144cf61f885c5cc6e25ff0 Mon Sep 17 00:00:00 2001 From: Caio Oliveira Date: Sat, 30 Dec 2017 14:05:21 -0200 Subject: [PATCH 2/6] further splitting big functions --- catalyst/utils/run_algo.py | 139 ++++++++++++++++++++++--------------- 1 file changed, 83 insertions(+), 56 deletions(-) diff --git a/catalyst/utils/run_algo.py b/catalyst/utils/run_algo.py index a5fb873a..9265a349 100644 --- a/catalyst/utils/run_algo.py +++ b/catalyst/utils/run_algo.py @@ -260,6 +260,77 @@ def _bundle_trading_environment(bundle_data, environ): return TradingEnvironment(asset_db_path=connstr, environ=environ) +def _build_live_algo_and_data(sim_params, exchanges, env, open_calendar, + simulate_orders, algo_namespace, capital_base, + live_graph, stats_output, analyze_live, + base_currency, namespace, choose_loader, + algorithm_class_kwargs): + sim_params._arena = 'live' # TODO: use the constructor instead + + data = _data_for_live_trading( + exchanges, env, open_calendar, simulate_orders, + algo_namespace, capital_base) + + algorithm_class = _algorithm_class_for_live( + algo_namespace, live_graph, stats_output, analyze_live, + base_currency, simulate_orders, exchanges, capital_base) + + return data, algorithm_class( + namespace=namespace, + env=env, + get_pipeline_loader=choose_loader, + sim_params=sim_params, + **algorithm_class_kwargs) + + +def _build_backtest_algo_and_data( + exchanges, bundle, environ, bundle_timestamp, open_calendar, start, + end, namespace, choose_loader, sim_params, algorithm_class_kwargs): + if exchanges: + # Removed the existing Poloniex fork to keep things simple + # We can add back the complexity if required. + + # I don't think that we should have arbitrary price data bundles + # Instead, we should center this data around exchanges. + # We still need to support bundles for other misc data, but we + # can handle this later. + + data = DataPortalExchangeBacktest( + exchange_names=[exchange_name for exchange_name in exchanges], + asset_finder=None, + trading_calendar=open_calendar, + first_trading_day=start, + last_available_session=end) + + algorithm_class = partial( + ExchangeTradingAlgorithmBacktest, + exchanges=exchanges) + elif bundle is not None: + # TODO This branch should probably be removed or fixed: it doesn't even + # build `algorithm_class`, so it will break when trying to instantiate + # it. + bundle_data = load(bundle, environ, bundle_timestamp) + + env = _bundle_trading_environment(bundle_data, environ) + + first_trading_day = \ + bundle_data.equity_minute_bar_reader.first_trading_day + + data = DataPortal( + env.asset_finder, open_calendar, + first_trading_day=first_trading_day, + equity_minute_reader=bundle_data.equity_minute_bar_reader, + equity_daily_reader=bundle_data.equity_daily_bar_reader, + adjustment_reader=bundle_data.adjustment_reader) + + return data, algorithm_class( + namespace=namespace, + env=env, + get_pipeline_loader=choose_loader, + sim_params=sim_params, + **algorithm_class_kwargs) + + def _build_algo_and_data(handle_data, initialize, before_trading_start, analyze, algofile, algotext, defines, data_frequency, capital_base, data, bundle, bundle_timestamp, start, @@ -295,8 +366,7 @@ def _build_algo_and_data(handle_data, initialize, before_trading_start, if live: start, end = _get_live_time_range() - # TODO double check if this is the desired behavior - data_frequency = 'minute' + data_frequency = 'minute' # TODO double check if this is the desired behavior sim_params = create_simulation_parameters( start=start, @@ -305,54 +375,6 @@ def _build_algo_and_data(handle_data, initialize, before_trading_start, emission_rate=data_frequency, data_frequency=data_frequency) - if live: - # TODO: use the constructor instead - sim_params._arena = 'live' - - data = _data_for_live_trading( - exchanges, env, open_calendar, simulate_orders, - algo_namespace, capital_base) - - algorithm_class = _algorithm_class_for_live( - algo_namespace, live_graph, stats_output, analyze_live, - base_currency, simulate_orders, exchanges, capital_base) - elif exchanges: - # Removed the existing Poloniex fork to keep things simple - # We can add back the complexity if required. - - # I don't think that we should have arbitrary price data bundles - # Instead, we should center this data around exchanges. - # We still need to support bundles for other misc data, but we - # can handle this later. - - data = DataPortalExchangeBacktest( - exchange_names=[exchange_name for exchange_name in exchanges], - asset_finder=None, - trading_calendar=open_calendar, - first_trading_day=start, - last_available_session=end) - - algorithm_class = partial( - ExchangeTradingAlgorithmBacktest, - exchanges=exchanges) - elif bundle is not None: - # TODO This branch should probably be removed or fixed: it doesn't even - # build `algorithm_class`, so it will break when trying to instantiate - # it. - bundle_data = load(bundle, environ, bundle_timestamp) - - env = _bundle_trading_environment(bundle_data, environ) - - first_trading_day = \ - bundle_data.equity_minute_bar_reader.first_trading_day - - data = DataPortal( - env.asset_finder, open_calendar, - first_trading_day=first_trading_day, - equity_minute_reader=bundle_data.equity_minute_bar_reader, - equity_daily_reader=bundle_data.equity_daily_bar_reader, - adjustment_reader=bundle_data.adjustment_reader,) - if algotext is None: algorithm_class_kwargs = {'initialize': initialize, 'handle_data': handle_data, @@ -362,12 +384,17 @@ def _build_algo_and_data(handle_data, initialize, before_trading_start, algorithm_class_kwargs = {'algo_filename': getattr(algofile, 'name', ''), 'script': algotext} - return data, algorithm_class( - namespace=namespace, - env=env, - get_pipeline_loader=choose_loader, - sim_params=sim_params, - **algorithm_class_kwargs) + + if live: + return _build_live_algo_and_data( + sim_params, exchanges, env, open_calendar, simulate_orders, + algo_namespace, capital_base, live_graph, stats_output, + analyze_live, base_currency, namespace, choose_loader, + algorithm_class_kwargs) + else: + return _build_backtest_algo_and_data( + exchanges, bundle, environ, bundle_timestamp, open_calendar, start, + end, namespace, choose_loader, sim_params, algorithm_class_kwargs) def _run(handle_data, initialize, before_trading_start, analyze, algofile, From 8a1d914ed9bf310e8aef899389e5cff7a4a7ea5c Mon Sep 17 00:00:00 2001 From: Caio Oliveira Date: Sat, 30 Dec 2017 14:09:13 -0200 Subject: [PATCH 3/6] :nail_care: --- catalyst/utils/run_algo.py | 53 +++++++++++++------------------------- 1 file changed, 18 insertions(+), 35 deletions(-) diff --git a/catalyst/utils/run_algo.py b/catalyst/utils/run_algo.py index 9265a349..04061b38 100644 --- a/catalyst/utils/run_algo.py +++ b/catalyst/utils/run_algo.py @@ -84,21 +84,18 @@ def _build_namespace(algotext, local_namespace, defines): except ValueError: raise ValueError( 'invalid define %r, should be of the form name=value' % - assign, - ) + assign) try: # evaluate in the same namespace so names may refer to # eachother namespace[name] = eval(value, namespace) except Exception as e: raise ValueError( - 'failed to execute definition for name %r: %s' % (name, e), - ) + 'failed to execute definition for name %r: %s' % (name, e)) elif defines: raise _RunAlgoError( 'cannot pass define without `algotext`', - "cannot pass '-D' / '--define' without '-t' / '--algotext'", - ) + "cannot pass '-D' / '--define' without '-t' / '--algotext'") else: namespace = {} @@ -137,8 +134,7 @@ def _pretty_print_code(algotext): algotext, PythonLexer(), TerminalFormatter(), - outfile=sys.stdout, - ) + outfile=sys.stdout) else: click.echo(algotext) @@ -148,8 +144,7 @@ def _choose_loader(data_frequency, column): if column in bound_cols: return ExchangePricingLoader(data_frequency) raise ValueError( - "No PipelineLoader registered for column %s." % column - ) + "No PipelineLoader registered for column %s." % column) def _get_live_time_range(): @@ -191,9 +186,7 @@ def _fetch_capital_base(base_currency, exchange_name, exchange, if attempt_index < 20: log.warn( 'could not retrieve balances on {}: {}'.format( - exchange.name, e - ) - ) + exchange.name, e)) sleep(5) return _fetch_capital_base(base_currency, exchange_name, exchange, attempt_index + 1) @@ -239,8 +232,7 @@ def _algorithm_class_for_live(algo_namespace, live_graph, stats_output, live_graph=live_graph, simulate_orders=simulate_orders, stats_output=stats_output, - analyze_live=analyze_live, - ) + analyze_live=analyze_live,) return algorithm_class @@ -249,13 +241,11 @@ def _bundle_trading_environment(bundle_data, environ): prefix, connstr = re.split( r'sqlite:///', str(bundle_data.asset_finder.engine.url), - maxsplit=1, - ) + maxsplit=1) if prefix: raise ValueError( "invalid url %r, must begin with 'sqlite:///'" % - str(bundle_data.asset_finder.engine.url), - ) + str(bundle_data.asset_finder.engine.url)) return TradingEnvironment(asset_db_path=connstr, environ=environ) @@ -358,8 +348,8 @@ def _build_algo_and_data(handle_data, initialize, before_trading_start, end_dt=end), environ=environ, exchange_tz='UTC', - asset_db_path=None # We don't need an asset db, we have exchanges - ) + asset_db_path=None) # We don't need an asset db, we have exchanges + env.asset_finder = ExchangeAssetFinder(exchanges=exchanges) choose_loader = partial(_choose_loader, data_frequency) @@ -416,8 +406,7 @@ def _run(handle_data, initialize, before_trading_start, analyze, algofile, analyze_live, simulate_orders, stats_output) perf = algorithm.run( data, - overwrite_sim_params=False, - ) + overwrite_sim_params=False) if output == '-': click.echo(str(perf)) @@ -474,8 +463,7 @@ def load_extensions(default, extensions, strict, environ, reload=False): # without `strict` we should just log the failure warnings.warn( 'Failed to load extension: %r\n%s' % (ext, e), - stacklevel=2 - ) + stacklevel=2) else: _loaded_extensions.add(ext) @@ -574,8 +562,7 @@ def run_algorithm(initialize, catalyst.data.bundles.bundles : The available data bundles. """ load_extensions( - default_extension, extensions, strict_extensions, environ - ) + default_extension, extensions, strict_extensions, environ) if capital_base is None: raise ValueError( @@ -583,8 +570,7 @@ def run_algorithm(initialize, 'amount of base currency available for trading. For example, ' 'if the `capital_base` is 5ETH, the ' '`order_target_percent(asset, 1)` command will order 5ETH worth ' - 'of the specified asset.' - ) + 'of the specified asset.') # I'm not sure that we need this since the modified DataPortal # does not require extensions to be explicitly loaded. @@ -602,13 +588,11 @@ def run_algorithm(initialize, elif len(non_none_data) != 1: raise ValueError( 'must specify one of `data`, `data_portal`, or `bundle`,' - ' got: %r' % non_none_data, - ) + ' got: %r' % non_none_data) elif 'bundle' not in non_none_data and bundle_timestamp is not None: raise ValueError( - 'cannot specify `bundle_timestamp` without passing `bundle`', - ) + 'cannot specify `bundle_timestamp` without passing `bundle`') return _run( handle_data=handle_data, initialize=initialize, @@ -635,5 +619,4 @@ def run_algorithm(initialize, live_graph=live_graph, analyze_live=analyze_live, simulate_orders=simulate_orders, - stats_output=stats_output - ) + stats_output=stats_output) From 0a946e4200e40b0ce7f3dded88d3eb62d249492d Mon Sep 17 00:00:00 2001 From: Caio Oliveira Date: Sun, 31 Dec 2017 14:25:46 -0200 Subject: [PATCH 4/6] bugfix on run algo --- catalyst/utils/run_algo.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/catalyst/utils/run_algo.py b/catalyst/utils/run_algo.py index 04061b38..7591603e 100644 --- a/catalyst/utils/run_algo.py +++ b/catalyst/utils/run_algo.py @@ -257,9 +257,7 @@ def _build_live_algo_and_data(sim_params, exchanges, env, open_calendar, algorithm_class_kwargs): sim_params._arena = 'live' # TODO: use the constructor instead - data = _data_for_live_trading( - exchanges, env, open_calendar, simulate_orders, - algo_namespace, capital_base) + data = _data_for_live_trading(sim_params, exchanges, env, open_calendar) algorithm_class = _algorithm_class_for_live( algo_namespace, live_graph, stats_output, analyze_live, From 81eaa6426a4f7131a4f8c4a2411f14fd236de2ab Mon Sep 17 00:00:00 2001 From: Caio Oliveira Date: Sun, 31 Dec 2017 13:26:41 -0200 Subject: [PATCH 5/6] remove `skip init` no idea what's the downside, but should fix #124 --- catalyst/utils/run_algo.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/catalyst/utils/run_algo.py b/catalyst/utils/run_algo.py index 7591603e..32bd801e 100644 --- a/catalyst/utils/run_algo.py +++ b/catalyst/utils/run_algo.py @@ -121,8 +121,7 @@ def _build_exchanges_dict(exchange, live, simulate_orders, base_currency): exchanges = {exchange_name: get_exchange( exchange_name=exchange_name, base_currency=base_currency, - must_authenticate=(live and not simulate_orders), - skip_init=True) + must_authenticate=(live and not simulate_orders)) for exchange_name in exchange_list} return exchanges From e8c4a3636adef13c88aae7f5cfb680d1cc183bed Mon Sep 17 00:00:00 2001 From: Caio Oliveira Date: Sun, 31 Dec 2017 15:07:41 -0200 Subject: [PATCH 6/6] Forgot one arg --- catalyst/utils/run_algo.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/catalyst/utils/run_algo.py b/catalyst/utils/run_algo.py index 32bd801e..d0129f28 100644 --- a/catalyst/utils/run_algo.py +++ b/catalyst/utils/run_algo.py @@ -271,8 +271,9 @@ def _build_live_algo_and_data(sim_params, exchanges, env, open_calendar, def _build_backtest_algo_and_data( - exchanges, bundle, environ, bundle_timestamp, open_calendar, start, - end, namespace, choose_loader, sim_params, algorithm_class_kwargs): + exchanges, bundle, env, environ, bundle_timestamp, open_calendar, + start, end, namespace, choose_loader, sim_params, + algorithm_class_kwargs): if exchanges: # Removed the existing Poloniex fork to keep things simple # We can add back the complexity if required. @@ -380,8 +381,9 @@ def _build_algo_and_data(handle_data, initialize, before_trading_start, algorithm_class_kwargs) else: return _build_backtest_algo_and_data( - exchanges, bundle, environ, bundle_timestamp, open_calendar, start, - end, namespace, choose_loader, sim_params, algorithm_class_kwargs) + exchanges, bundle, env, environ, bundle_timestamp, open_calendar, + start, end, namespace, choose_loader, sim_params, + algorithm_class_kwargs) def _run(handle_data, initialize, before_trading_start, analyze, algofile,