code: 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,
      quote_currency,
      live_graph,
      analyze_live,
      simulate_orders,
      auth_aliases,
      stats_output,
  ):
      """Run a backtest for the given algorithm.
  
      This is shared between the cli and :func:`catalyst.run_algo`.
      """
      # TODO: refactor for more granularity
      if algotext is not None:
          if local_namespace:
              ip = get_ipython()  # noqa
              namespace = ip.user_ns
          else:
              namespace = {}
  
          for assign in defines:
              try:
                  name, value = assign.split("=", 2)
              except ValueError:
                  raise ValueError(
                      "invalid define %r, should be of the form name=value"
                      % 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),
                  )
      elif defines:
          raise _RunAlgoError(
              "cannot pass define without `algotext`",
              "cannot pass '-D' / '--define' without '-t' / '--algotext'",
          )
      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)
  
      log.info("Catalyst version {}".format(catalyst.__version__))
      if not DISABLE_ALPHA_WARNING:
          log.warn(ALPHA_WARNING_MESSAGE)
          sleep(3)
  
      if live:
          if simulate_orders:
              mode = "paper-trading"
          else:
              mode = "live-trading"
      else:
          mode = "backtest"
  
      log.info("running algo in {mode} mode".format(mode=mode))
  
      exchange_name = exchange
      if exchange_name is None:
          raise ValueError("Please specify at least one exchange.")
  
      if isinstance(auth_aliases, string_types):
          aliases = auth_aliases.split(",")
          if len(aliases) < 2 or len(aliases) % 2 != 0:
              raise ValueError(
                  "the `auth_aliases` parameter must contain an even list "
                  "of comma-delimited values. For example, "
                  '"binance,auth2" or "binance,auth2,bittrex,auth2".'
              )
  
          auth_aliases = dict(zip(aliases[::2], aliases[1::2]))
  
      exchange_list = [x.strip().lower() for x in exchange.split(",")]
      exchanges = dict()
      for name in exchange_list:
          if auth_aliases is not None and name in auth_aliases:
              auth_alias = auth_aliases[name]
          else:
              auth_alias = None
  
          exchanges[name] = get_exchange(
              exchange_name=name,
              quote_currency=quote_currency,
              must_authenticate=(live and not simulate_orders),
              skip_init=True,
              auth_alias=auth_alias,
          )
  
      open_calendar = get_calendar("OPEN")
  
      env = TradingEnvironment(
          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
          )
  
      if live:
          # TODO: fix the start data.
          # is_start checks if a start date was specified by user
          # needed for live clock
          is_start = True
  
          if start is None:
              start = pd.Timestamp.utcnow()
              is_start = False
          elif start:
              assert (
                  pd.Timestamp.utcnow() <= start
              ), "specified start date is in the past."
          elif start and end:
              assert start < end, "start date is later than end date."
  
          # TODO: fix the end data.
          # is_end checks if an end date was specified by user
          # needed for live clock
          is_end = True
  
          if end is None:
              end = start + timedelta(hours=8760)
              is_end = False
  
          data = DataPortalExchangeLive(
              exchanges=exchanges,
              asset_finder=env.asset_finder,
              trading_calendar=open_calendar,
              first_trading_day=pd.to_datetime("today", utc=True),
          )
  
          sim_params = create_simulation_parameters(
              start=start,
              end=end,
              capital_base=capital_base,
              emission_rate="minute",
              data_frequency="minute",
          )
  
          # 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,
              start=start,
              is_start=is_start,
              end=end,
              is_end=is_end,
          )
      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.
  
          if (start and start != pd.tslib.normalize_date(start)) or (
              end and end != pd.tslib.normalize_date(end)
          ):
              # todo: add to Sim_Params the option to
              # start & end at specific times
              log.warn(
                  "Catalyst currently starts and ends on the start and "
                  "end of the dates specified, respectively. We hope to "
                  "Modify this and support specific times in a future release."
              )
  
          data = DataPortalExchangeBacktest(
              exchange_names=[ex_name for ex_name in exchanges],
              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,
          )
  
          algorithm_class = partial(
              ExchangeTradingAlgorithmBacktest, exchanges=exchanges
          )
  
      elif bundle is not None:
          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 = TradingEnvironment(
              asset_db_path=connstr, environ=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,
          )
  
      perf = 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", "<algorithm>"),
              "script": algotext,
          },
      ).run(
          data,
          overwrite_sim_params=False,
      )
  
      if output == "-":
          click.echo(str(perf))
      elif (
          output != os.devnull
      ):  # make the catalyst magic not write any data
          perf.to_pickle(output)
  
      return perf
  
imports: import os
  import re
  import sys
  import warnings
  from datetime import timedelta
  from runpy import run_path
  from time import sleep
  import click
  import pandas
  from six import string_types
  import catalyst
  from catalyst.data.bundles import load
  from catalyst.data.data_portal import DataPortal
  from catalyst.exchange.exchange_pricing_loader import ExchangePricingLoader, TradingPairPricing
  from catalyst.exchange.utils.factory import get_exchange
  from logbook import Logger
  from toolz import valfilter, concatv
  from functools import partial
  from catalyst.finance.trading import TradingEnvironment
  from catalyst.utils.calendars import get_calendar
  from catalyst.utils.factory import create_simulation_parameters
  from catalyst.data.loader import load_crypto_market_data
  import catalyst.utils.paths
  from catalyst.utils.remote import remote_backtest
  from catalyst.exchange.exchange_algorithm import ExchangeTradingAlgorithmLive, ExchangeTradingAlgorithmBacktest
  from catalyst.exchange.exchange_data_portal import DataPortalExchangeLive, DataPortalExchangeBacktest
  from catalyst.exchange.exchange_asset_finder import ExchangeAssetFinder
  from catalyst.constants import LOG_LEVEL, ALPHA_WARNING_MESSAGE, DISABLE_ALPHA_WARNING
label_desc: Use image node_id 1 for calling a global function with example usage: _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, quote_currency, live_graph, analyze_live, simulate_orders, auth_aliases, stats_output) and returns: perf, ExchangePricingLoader