Esempio n. 1
0
def run_algorithm(initialize,
                  capital_base=None,
                  start=None,
                  end=None,
                  handle_data=None,
                  before_trading_start=None,
                  analyze=None,
                  data_frequency='daily',
                  data=None,
                  bundle=None,
                  bundle_timestamp=None,
                  default_extension=True,
                  extensions=(),
                  strict_extensions=True,
                  environ=os.environ,
                  live=False,
                  remote=False,
                  mail=None,
                  exchange_name=None,
                  quote_currency=None,
                  algo_namespace=None,
                  live_graph=False,
                  analyze_live=None,
                  simulate_orders=True,
                  auth_aliases=None,
                  stats_output=None,
                  output=os.devnull):
    """
    Run a trading algorithm.

    Parameters
    ----------
    capital_base : float
        The starting capital for the backtest.
    start : datetime
        The start date of the backtest.
    end : datetime
        The end date of the backtest..
    initialize : callable[context -> None]
        The initialize function to use for the algorithm. This is called once
        at the very beginning of the run and should be used to set up
        any state needed by the algorithm.
    handle_data : callable[(context, BarData) -> None], optional
        The handle_data function to use for the algorithm. This is called
        every minute when ``data_frequency == 'minute'`` or every day
        when ``data_frequency == 'daily'``.
    before_trading_start : callable[(context, BarData) -> None], optional
        The before_trading_start function for the algorithm. This is called
        once before each trading day (after initialize on the first day).
    analyze : callable[(context, pd.DataFrame) -> None], optional
        The analyze function to use for the algorithm. This function is called
        once at the end of the backtest/live run and is passed the
        context and the performance data.
    data_frequency : {'daily', 'minute'}, optional
        The data frequency to run the algorithm at.
        At backtest both modes are supported, at live mode only
        the minute mode is supported.
    data : pd.DataFrame, pd.Panel, or DataPortal, optional
        The ohlcv data to run the backtest with.
        This argument is mutually exclusive with:
        ``bundle``
        ``bundle_timestamp``
    bundle : str, optional
        The name of the data bundle to use to load the data to run the backtest
        with.
        This argument is mutually exclusive with ``data``.
    bundle_timestamp : datetime, optional
        The datetime to lookup the bundle data for. This defaults to the
        current time.
        This argument is mutually exclusive with ``data``.
    default_extension : bool, optional
        Should the default catalyst extension be loaded. This is found at
        ``$CATALYST_ROOT/extension.py``
    extensions : iterable[str], optional
        The names of any other extensions to load. Each element may either be
        a dotted module path like ``a.b.c`` or a path to a python file ending
        in ``.py`` like ``a/b/c.py``.
    strict_extensions : bool, optional
        Should the run fail if any extensions fail to load. If this is false,
        a warning will be raised instead.
    environ : mapping[str -> str], optional
        The os environment to use. Many extensions use this to get parameters.
        This defaults to ``os.environ``.
    live : bool, optional
        Should the algorithm be executed in live trading mode.
    remote : bool, optional
        Should the algorithm run on a remote server.
        currently, available only on backtest mode.
    mail : str, optional- if running with remote=True then, mandatory.
        to which email address shall the server send the results to.

    exchange_name: str
        The name of the exchange to be used in the backtest/live run.
    quote_currency: str
        The base currency to be used in the backtest/live run.
    algo_namespace: str
        The namespace of the algorithm.
    live_graph: bool, optional
        Should the live graph clock be used instead of the regular clock.
    analyze_live: callable[(context, pd.DataFrame) -> None], optional
        The interactive analyze function to be used with
        the live graph clock in every tick.
    simulate_orders: bool, optional
        Should paper trading mode be applied.
    auth_aliases: str, optional
        Rewrite the auth file name. It should contain an even list
        of comma-delimited values. For example: "binance,auth2,bittrex,auth2"
    stats_output: str, optional
        The URI of the S3 bucket to which to upload the performance stats.
    output: str, optional
        The output file path to which the algorithm performance
        is serialized.

    Returns
    -------
    perf : pd.DataFrame
        The daily performance of the algorithm.
    """

    load_extensions(
        default_extension, extensions, strict_extensions, environ
    )

    if capital_base is None:
        raise ValueError(
            'Please specify a `capital_base` parameter which is the maximum '
            '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.'
        )
    # I'm not sure that we need this since the modified DataPortal
    # does not require extensions to be explicitly loaded.

    # This will be useful for arbitrary non-pricing bundles but we may
    # need to modify the logic.
    if not live:
        non_none_data = valfilter(bool, {
            'data': data is not None,
            'bundle': bundle is not None,
        })
        if not non_none_data:
            # if neither data nor bundle are passed use 'quantopian-quandl'
            bundle = 'quantopian-quandl'

        elif len(non_none_data) != 1:
            raise ValueError(
                'must specify one of `data`, `data_portal`, or `bundle`,'
                ' 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`',
            )
    if remote:
        if mail is None or not re.match(r"[^@]+@[^@]+\.[^@]+", mail):
            raise ValueError("Please specify a 'mail' parameter which "
                             "is a valid email address, in order to "
                             "send you back the results")
        return remote_backtest(
            handle_data=handle_data,
            initialize=initialize,
            before_trading_start=before_trading_start,
            analyze=None,
            algofile=None,
            algotext=None,
            defines=(),
            data_frequency=data_frequency,
            capital_base=capital_base,
            data=data,
            bundle=bundle,
            bundle_timestamp=bundle_timestamp,
            start=start,
            end=end,
            output='--',
            print_algo=False,
            local_namespace=False,
            environ=environ,
            live=False,
            exchange=exchange_name,
            algo_namespace=algo_namespace,
            quote_currency=quote_currency,
            live_graph=live_graph,
            analyze_live=analyze_live,
            simulate_orders=simulate_orders,
            auth_aliases=auth_aliases,
            stats_output=stats_output,
            mail=mail
        )

    return _run(
        handle_data=handle_data,
        initialize=initialize,
        before_trading_start=before_trading_start,
        analyze=analyze,
        algofile=None,
        algotext=None,
        defines=(),
        data_frequency=data_frequency,
        capital_base=capital_base,
        data=data,
        bundle=bundle,
        bundle_timestamp=bundle_timestamp,
        start=start,
        end=end,
        output=output,
        print_algo=False,
        local_namespace=False,
        environ=environ,
        live=live,
        exchange=exchange_name,
        algo_namespace=algo_namespace,
        quote_currency=quote_currency,
        live_graph=live_graph,
        analyze_live=analyze_live,
        simulate_orders=simulate_orders,
        auth_aliases=auth_aliases,
        stats_output=stats_output
    )
Esempio n. 2
0
def remote_run(ctx, algofile, algotext, define, data_frequency, capital_base,
               bundle, bundle_timestamp, start, end, mail, print_algo,
               local_namespace, exchange_name, algo_namespace, quote_currency):
    """Run a backtest for the given algorithm on the cloud.
    """

    if (algotext is not None) == (algofile is not None):
        ctx.fail(
            "must specify exactly one of '-f' / '--algofile' or"
            " '-t' / '--algotext'", )

    # check that the start and end dates are passed correctly
    if start is None and end is None:
        # check both at the same time to avoid the case where a user
        # does not pass either of these and then passes the first only
        # to be told they need to pass the second argument also
        ctx.fail(
            "must specify dates with '-s' / '--start' and '-e' / '--end'"
            " in backtest mode", )
    if start is None:
        ctx.fail("must specify a start date with '-s' / '--start'"
                 " in backtest mode")
    if end is None:
        ctx.fail("must specify an end date with '-e' / '--end'"
                 " in backtest mode")

    if exchange_name is None:
        ctx.fail("must specify an exchange name '-x'")

    if quote_currency is None:
        ctx.fail("must specify a quote currency with '-c' in backtest mode")

    if capital_base is None:
        ctx.fail("must specify a capital base with '--capital-base'")

    if mail is None or not re.match(r"[^@]+@[^@]+\.[^@]+", mail):
        ctx.fail("must specify a valid email with '--mail'")

    algo_id = remote_backtest(
        initialize=None,
        handle_data=None,
        before_trading_start=None,
        analyze=None,
        algofile=algofile,
        algotext=algotext,
        defines=define,
        data_frequency=data_frequency,
        capital_base=capital_base,
        data=None,
        bundle=bundle,
        bundle_timestamp=bundle_timestamp,
        start=start,
        end=end,
        output='--',
        print_algo=print_algo,
        local_namespace=local_namespace,
        environ=os.environ,
        live=False,
        exchange=exchange_name,
        algo_namespace=algo_namespace,
        quote_currency=quote_currency,
        analyze_live=None,
        live_graph=False,
        simulate_orders=True,
        auth_aliases=None,
        stats_output=None,
        mail=mail,
    )
    print(algo_id)
    return algo_id