bt Package

bt Package

algos Module

A collection of Algos used to create Strategy logic.

class bt.algos.CapitalFlow(amount)[source]

Bases: Algo

Used to model capital flows. Flows can either be inflows or outflows.

This Algo can be used to model capital flows. For example, a pension fund might have inflows every month or year due to contributions. This Algo will affect the capital of the target node without affecting returns for the node.

Since this is modeled as an adjustment, the capital will remain in the strategy until a re-allocation/rebalancement is made.

Args:
  • amount (float): Amount of adjustment

class bt.algos.CloseDead[source]

Bases: Algo

Closes all positions for which prices are equal to zero (we assume that these stocks are dead) and removes them from temp[‘weights’] if they enter it by any chance. To be called before Rebalance().

In a normal workflow it is not needed, as those securities will not be selected by SelectAll(include_no_data=False) or similar method, and Rebalance() closes positions that are not in temp[‘weights’] anyway. However in case when for some reasons include_no_data=False could not be used or some modified weighting method is used, CloseDead() will allow to avoid errors.

Requires:
  • weights

class bt.algos.ClosePositionsAfterDates(close_dates)[source]

Bases: Algo

Close positions on securities after a given date. This can be used to make sure positions on matured/redeemed securities are closed. It can also be used as part of a strategy to, i.e. make sure the strategy doesn’t hold any securities with time to maturity less than a year

Note that if placed after a RunPeriod algo in the stack, that the actual closing of positions will occur after the provided date. For this to work, the “price” of the security (even if matured) must exist up until that date. Alternatively, run this with the @run_always decorator to close the positions immediately.

Also note that this algo does not operate using temp[‘weights’] and Rebalance. This is so that hedges (which are excluded from that workflow) will also be closed as necessary.

Args:
  • close_dates (str): the name of a dataframe indexed by security name, with columns “date”: the date after which we want to close the position ASAP

Sets:
  • target.perm[‘closed’] : to keep track of which securities have already closed

class bt.algos.Debug(name=None)[source]

Bases: Algo

Utility Algo that calls pdb.set_trace when triggered.

In the debug session, ‘target’ is available and can be examined through the StrategyBase interface.

class bt.algos.HedgeRisks(measures, pseudo=False, strategy=None, throw_nan=True)[source]

Bases: Algo

Hedges risk measures with selected instruments.

Make sure that the UpdateRisk algo has been called beforehand.

Args:
  • measures (list): the names of the risk measures to hedge

  • pseudo (bool): whether to use the pseudo-inverse to compute the inverse Jacobian. If False, will fail if the number of selected instruments is not equal to the number of measures, or if the Jacobian is singular

  • strategy (StrategyBase): If provided, will hedge the risk from this strategy in addition to the risk from target. This is to allow separate tracking of hedged and unhedged performance. Note that risk_strategy must occur earlier than ‘target’ in a depth-first traversal of the children of the root, otherwise hedging will occur before positions of risk_strategy are updated.

  • throw_nan (bool): Whether to throw on nan hedge notionals, rather than simply not hedging.

Requires:
  • selected

class bt.algos.LimitDeltas(limit=0.1)[source]

Bases: Algo

Modifies temp[‘weights’] based on weight delta limits.

Basically, this can be used if we want to restrict how much a security’s target weight can change from day to day. Useful when we want to be more conservative about how much we could actually trade on a given day without affecting the market.

For example, if we have a strategy that is currently long 100% one security, and the weighing Algo sets the new weight to 0%, but we use this Algo with a limit of 0.1, the new target weight will be 90% instead of 0%.

Args:
  • limit (float, dict): Weight delta limit. If float, this will be a global limit for all securities. If dict, you may specify by-ticker limit.

Sets:
  • weights

Requires:
  • weights

class bt.algos.LimitWeights(limit=0.1)[source]

Bases: Algo

Modifies temp[‘weights’] based on weight limits.

This is an Algo wrapper around ffn’s limit_weights. The purpose of this Algo is to limit the weight of any one specifc asset. For example, some Algos will set some rather extreme weights that may not be acceptable. Therefore, we can use this Algo to limit the extreme weights. The excess weight is then redistributed to the other assets, proportionally to their current weights.

See ffn’s limit_weights for more information.

Args:
  • limit (float): Weight limit.

Sets:
  • weights

Requires:
  • weights

class bt.algos.Not(algo)[source]

Bases: Algo

Flow control Algo

It is usful for “inverting” other flow control algos, For example Not( RunAfterDate(…) ), Not( RunAfterDays(…) ), etc

Args:
  • list_of_algos (Algo): The algo to run and invert the return value of

class bt.algos.Or(list_of_algos)[source]

Bases: Algo

Flow control Algo

It useful for combining multiple signals into one signal. For example, we might want two different rebalance signals to work together:

runOnDateAlgo = bt.algos.RunOnDate(pdf.index[0]) # where pdf.index[0] is the first date in our time series runMonthlyAlgo = bt.algos.RunMonthly() orAlgo = Or([runMonthlyAlgo,runOnDateAlgo])

orAlgo will return True if it is the first date or if it is 1st of the month

Args:
  • list_of_algos: Iterable list of algos. Runs each algo and returns true if any algo returns true.

class bt.algos.PTE_Rebalance(PTE_volatility_cap, target_weights, lookback=<DateOffset: months=3>, lag=<DateOffset: days=0>, covar_method='standard', annualization_factor=252)[source]

Bases: Algo

Triggers a rebalance when PTE from static weights is past a level.

Args:
  • PTE_volatility_cap: annualized volatility to target

  • target_weights: dataframe of weights that needs to have the same index as the price dataframe

  • lookback (DateOffset): lookback period for estimating volatility

  • lag (DateOffset): amount of time to wait to calculate the covariance

  • covar_method: method of calculating volatility

  • annualization_factor: number of periods to annualize by. It is assumed that target volatility is already annualized by this factor.

class bt.algos.PrintDate(name=None)[source]

Bases: Algo

This Algo simply print’s the current date.

Can be useful for debugging purposes.

class bt.algos.PrintInfo(fmt_string='{name} {now}')[source]

Bases: Algo

Prints out info associated with the target strategy. Useful for debugging purposes.

Args:
  • fmt_string (str): A string that will later be formatted with the target object’s __dict__ attribute. Therefore, you should provide what you want to examine within curly braces ( { } )

Ex:

PrintInfo(‘Strategy {name} : {now}’)

This will print out the name and the date (now) on each call. Basically, you provide a string that will be formatted with target.__dict__

class bt.algos.PrintRisk(fmt_string='')[source]

Bases: Algo

This Algo prints the risk data.

Args:
  • fmt_string (str): A string that will later be formatted with the target object’s risk attributes. Therefore, you should provide what you want to examine within curly braces ( { } ) If not provided, will print the entire dictionary with no formatting.

class bt.algos.PrintTempData(fmt_string=None)[source]

Bases: Algo

This Algo prints the temp data.

Useful for debugging.

Args:
  • fmt_string (str): A string that will later be formatted with the target’s temp dict. Therefore, you should provide what you want to examine within curly braces ( { } )

class bt.algos.Rebalance[source]

Bases: Algo

Rebalances capital based on temp[‘weights’]

Rebalances capital based on temp[‘weights’]. Also closes positions if open but not in target_weights. This is typically the last Algo called once the target weights have been set.

Requires:
  • weights

  • cash (optional): You can set a ‘cash’ value on temp. This should be a number between 0-1 and determines the amount of cash to set aside. For example, if cash=0.3, the strategy will allocate 70% of its value to the provided weights, and the remaining 30% will be kept in cash. If this value is not provided (default), the full value of the strategy is allocated to securities.

  • notional_value (optional): Required only for fixed_income targets. This is the base balue of total notional that will apply to the weights.

class bt.algos.RebalanceOverTime(n=10)[source]

Bases: Algo

Similar to Rebalance but rebalances to target weight over n periods.

Rebalances towards a target weight over a n periods. Splits up the weight delta over n periods.

This can be useful if we want to make more conservative rebalacing assumptions. Some strategies can produce large swings in allocations. It might not be reasonable to assume that this rebalancing can occur at the end of one specific period. Therefore, this algo can be used to simulate rebalancing over n periods.

This has typically been used in monthly strategies where we want to spread out the rebalancing over 5 or 10 days.

Note:

This Algo will require the run_always wrapper in the above case. For example, the RunMonthly will return True on the first day, and RebalanceOverTime will be ‘armed’. However, RunMonthly will return False the rest days of the month. Therefore, we must specify that we want to always run this algo.

Args:
  • n (int): number of periods over which rebalancing takes place.

Requires:
  • weights

class bt.algos.ReplayTransactions(transactions)[source]

Bases: Algo

Replay a list of transactions that were executed. This is useful for taking a blotter of actual trades that occurred, and measuring performance against hypothetical strategies. In particular, one can replay the outputs of backtest.Result.get_transactions

Note that this allows the timestamps and prices of the reported transactions to be completely arbitrary, so while the strategy may track performance on a daily basis, it will accurately account for the actual PNL of the trades based on where they actually traded, and the bidofferpaid attribute on the strategy will capture the “slippage” as measured against the daily prices.

Args:
  • transactions (str): name of a MultiIndex dataframe with format Date, Security | quantity, price. Note this schema follows the output of backtest.Result.get_transactions

class bt.algos.Require(pred, item, if_none=False)[source]

Bases: Algo

Flow control Algo.

This algo returns the value of a predicate on an temp entry. Useful for controlling flow.

For example, we might want to make sure we have some items selected. We could pass a lambda function that checks the len of ‘selected’:

pred=lambda x: len(x) == 0 item=’selected’

Args:
  • pred (Algo): Function that returns a Bool given the strategy. This is the definition of an Algo. However, this is typically used with a simple lambda function.

  • item (str): An item within temp.

  • if_none (bool): Result if the item required is not in temp or if it’s value if None

class bt.algos.ResolveOnTheRun(on_the_run, include_no_data=False, include_negative=False)[source]

Bases: Algo

Looks at securities set in temp[‘selected’] and searches for names that match the names of “aliases” for on-the-run securities in the provided data. Then replaces the alias with the name of the underlying security appropriate for the given date, and sets it back on temp[‘selected’]

Args:
  • on_the_run (str): Name of a Data frame with
    • columns set to “on the run” ticker names

    • index set to the timeline for the backtest

    • values are the actual security name to use for the given date

  • include_no_data (bool): Include securities that do not have data?

  • include_negative (bool): Include securities that have negative or zero prices?

Requires:
  • selected

Sets:
  • selected

class bt.algos.RollPositionsAfterDates(roll_data)[source]

Bases: Algo

Roll securities based on the provided map. This can be used for any securities which have “On-The-Run” and “Off-The-Run” versions (treasury bonds, index swaps, etc).

Also note that this algo does not operate using temp[‘weights’] and Rebalance. This is so that hedges (which are excluded from that workflow) will also be rolled as necessary.

Args:
  • roll_data (str): the name of a dataframe indexed by security name, with columns
    • “date”: the first date at which the roll can occur

    • “target”: the security name we are rolling into

    • “factor”: the conversion factor. One unit of the original security rolls into “factor” units of the new one.

Sets:
  • target.perm[‘rolled’] : to keep track of which securities have already rolled

class bt.algos.RunAfterDate(date)[source]

Bases: Algo

Returns True after a date has passed

Args:
  • date: Date after which to start trading

Note:

This is useful for algos that rely on trailing averages where you don’t want to start trading until some amount of data has been built up

class bt.algos.RunAfterDays(days)[source]

Bases: Algo

Returns True after a specific number of ‘warmup’ trading days have passed

Args:
  • days (int): Number of trading days to wait before starting

Note:

This is useful for algos that rely on trailing averages where you don’t want to start trading until some amount of data has been built up

class bt.algos.RunDaily(run_on_first_date=True, run_on_end_of_period=False, run_on_last_date=False)[source]

Bases: RunPeriod

Returns True on day change.

Args:
  • run_on_first_date (bool): determines if it runs the first time the algo is called

  • run_on_end_of_period (bool): determines if it should run at the end of the period or the beginning

  • run_on_last_date (bool): determines if it runs on the last time the algo is called

Returns True if the target.now’s day has changed compared to the last(or next if run_on_end_of_period) date, if not returns False. Useful for daily rebalancing strategies.

compare_dates(now, date_to_compare)[source]
class bt.algos.RunEveryNPeriods(n, offset=0)[source]

Bases: Algo

This algo runs every n periods.

Args:
  • n (int): Run each n periods

  • offset (int): Applies to the first run. If 0, this algo will run the first time it is called.

This Algo can be useful for the following type of strategy:

Each month, select the top 5 performers. Hold them for 3 months.

You could then create 3 strategies with different offsets and create a master strategy that would allocate equal amounts of capital to each.

class bt.algos.RunIfOutOfBounds(tolerance)[source]

Bases: Algo

This algo returns true if any of the target weights deviate by an amount greater than tolerance. For example, it will be run if the tolerance is set to 0.5 and a security grows from a target weight of 0.2 to greater than 0.3.

A strategy where rebalancing is performed quarterly or whenever any security’s weight deviates by more than 20% could be implemented by:

Or([runQuarterlyAlgo,runIfOutOfBoundsAlgo(0.2)])

Args:
  • tolerance (float): Allowed deviation of each security weight.

Requires:
  • Weights

class bt.algos.RunMonthly(run_on_first_date=True, run_on_end_of_period=False, run_on_last_date=False)[source]

Bases: RunPeriod

Returns True on month change.

Args:
  • run_on_first_date (bool): determines if it runs the first time the algo is called

  • run_on_end_of_period (bool): determines if it should run at the end of the period or the beginning

  • run_on_last_date (bool): determines if it runs on the last time the algo is called

Returns True if the target.now’s month has changed since relative to the last(or next) date, if not returns False. Useful for monthly rebalancing strategies.

compare_dates(now, date_to_compare)[source]
class bt.algos.RunOnDate(*dates)[source]

Bases: Algo

Returns True on a specific set of dates.

Args:
  • dates (list): List of dates to run Algo on.

class bt.algos.RunOnce[source]

Bases: Algo

Returns True on first run then returns False.

Args:
  • run_on_first_call: bool which determines if it runs the first time the algo is called

As the name says, the algo only runs once. Useful in situations where we want to run the logic once (buy and hold for example).

class bt.algos.RunPeriod(run_on_first_date=True, run_on_end_of_period=False, run_on_last_date=False)[source]

Bases: Algo

abstract compare_dates(now, date_to_compare)[source]
class bt.algos.RunQuarterly(run_on_first_date=True, run_on_end_of_period=False, run_on_last_date=False)[source]

Bases: RunPeriod

Returns True on quarter change.

Args:
  • run_on_first_date (bool): determines if it runs the first time the algo is called

  • run_on_end_of_period (bool): determines if it should run at the end of the period or the beginning

  • run_on_last_date (bool): determines if it runs on the last time the algo is called

Returns True if the target.now’s quarter has changed since relative to the last(or next) date, if not returns False. Useful for quarterly rebalancing strategies.

compare_dates(now, date_to_compare)[source]
class bt.algos.RunWeekly(run_on_first_date=True, run_on_end_of_period=False, run_on_last_date=False)[source]

Bases: RunPeriod

Returns True on week change.

Args:
  • run_on_first_date (bool): determines if it runs the first time the algo is called

  • run_on_end_of_period (bool): determines if it should run at the end of the period or the beginning

  • run_on_last_date (bool): determines if it runs on the last time the algo is called

Returns True if the target.now’s week has changed since relative to the last(or next) date, if not returns False. Useful for weekly rebalancing strategies.

compare_dates(now, date_to_compare)[source]
class bt.algos.RunYearly(run_on_first_date=True, run_on_end_of_period=False, run_on_last_date=False)[source]

Bases: RunPeriod

Returns True on year change.

Args:
  • run_on_first_date (bool): determines if it runs the first time the algo is called

  • run_on_end_of_period (bool): determines if it should run at the end of the period or the beginning

  • run_on_last_date (bool): determines if it runs on the last time the algo is called

Returns True if the target.now’s year has changed since relative to the last(or next) date, if not returns False. Useful for yearly rebalancing strategies.

compare_dates(now, date_to_compare)[source]
class bt.algos.ScaleWeights(scale)[source]

Bases: Algo

Sets temp[‘weights’] based on a scaled version of itself. Useful for going short, or scaling up/down when using FixedIncomeStrategy.

Args:
  • scale (float): the scaling factor

Sets:
  • weights

Requires:
  • weights

class bt.algos.SelectActive(name=None)[source]

Bases: Algo

Sets temp[‘selected’] based on filtering temp[‘selected’] to exclude those securities that have been closed or rolled after a certain date using ClosePositionsAfterDates or RollPositionsAfterDates. This makes sure not to select them again for weighting (even if they have prices).

Requires:
  • selected

  • perm[‘closed’] or perm[‘rolled’]

Sets:
  • selected

class bt.algos.SelectAll(include_no_data=False, include_negative=False)[source]

Bases: Algo

Sets temp[‘selected’] with all securities (based on universe).

Selects all the securities and saves them in temp[‘selected’]. By default, SelectAll does not include securities that have no data (nan) on current date or those whose price is zero or negative.

Args:
  • include_no_data (bool): Include securities that do not have data?

  • include_negative (bool): Include securities that have negative or zero prices?

Sets:
  • selected

class bt.algos.SelectHasData(lookback=<DateOffset: months=3>, min_count=None, include_no_data=False, include_negative=False)[source]

Bases: Algo

Sets temp[‘selected’] based on all items in universe that meet data requirements.

This is a more advanced version of SelectAll. Useful for selecting tickers that need a certain amount of data for future algos to run properly.

For example, if we need the items with 3 months of data or more, we could use this Algo with a lookback period of 3 months.

When providing a lookback period, it is also wise to provide a min_count. This is basically the number of data points needed within the lookback period for a series to be considered valid. For example, in our 3 month lookback above, we might want to specify the min_count as being 57 -> a typical trading month has give or take 20 trading days. If we factor in some holidays, we can use 57 or 58. It’s really up to you.

If you don’t specify min_count, min_count will default to ffn’s get_num_days_required.

Args:
  • lookback (DateOffset): A DateOffset that determines the lookback period.

  • min_count (int): Minimum number of days required for a series to be considered valid. If not provided, ffn’s get_num_days_required is used to estimate the number of points required.

  • include_no_data (bool): Include securities that do not have data?

  • include_negative (bool): Include securities that have negative or zero prices?

Sets:
  • selected

class bt.algos.SelectMomentum(n, lookback=<DateOffset: months=3>, lag=<DateOffset: days=0>, sort_descending=True, all_or_none=False)[source]

Bases: AlgoStack

Sets temp[‘selected’] based on a simple momentum filter.

Selects the top n securities based on the total return over a given lookback period. This is just a wrapper around an AlgoStack with two algos: StatTotalReturn and SelectN.

Note, that SelectAll() or similar should be called before SelectMomentum(), as StatTotalReturn uses values of temp[‘selected’]

Args:
  • n (int): select first N elements

  • lookback (DateOffset): lookback period for total return calculation

  • lag (DateOffset): Lag interval for total return calculation

  • sort_descending (bool): Sort descending (highest return is best)

  • all_or_none (bool): If true, only populates temp[‘selected’] if we have n items. If we have less than n, then temp[‘selected’] = [].

Sets:
  • selected

Requires:
  • selected

class bt.algos.SelectN(n, sort_descending=True, all_or_none=False, filter_selected=False)[source]

Bases: Algo

Sets temp[‘selected’] based on ranking temp[‘stat’].

Selects the top or botton N items based on temp[‘stat’]. This is usually some kind of metric that will be computed in a previous Algo and will be used for ranking purposes. Can select top or bottom N based on sort_descending parameter.

Args:
  • n (int): select top n items.

  • sort_descending (bool): Should the stat be sorted in descending order before selecting the first n items?

  • all_or_none (bool): If true, only populates temp[‘selected’] if we have n items. If we have less than n, then temp[‘selected’] = [].

  • filter_selected (bool): If True, will only select from the existing ‘selected’ list.

Sets:
  • selected

Requires:
  • stat

class bt.algos.SelectRandomly(n=None, include_no_data=False, include_negative=False)[source]

Bases: AlgoStack

Sets temp[‘selected’] based on a random subset of the items currently in temp[‘selected’].

Selects n random elements from the list stored in temp[‘selected’]. This is useful for benchmarking against a strategy where we believe the selection algorithm is adding value.

For example, if we are testing a momentum strategy and we want to see if selecting securities based on momentum is better than just selecting securities randomly, we could use this Algo to create a random Strategy used for random benchmarking.

Note:

Another selection algorithm should be use prior to this Algo to populate temp[‘selected’]. This will typically be SelectAll.

Args:
  • n (int): Select N elements randomly.

  • include_no_data (bool): Include securities that do not have data?

  • include_negative (bool): Include securities that have negative or zero prices?

Sets:
  • selected

Requires:
  • selected

class bt.algos.SelectRegex(regex)[source]

Bases: Algo

Sets temp[‘selected’] based on a regex on their names. Useful when working with a large universe of different kinds of securities

Args:
  • regex (str): regular expression on the name

Sets:
  • selected

Requires:
  • selected

class bt.algos.SelectThese(tickers, include_no_data=False, include_negative=False)[source]

Bases: Algo

Sets temp[‘selected’] with a set list of tickers.

Args:
  • ticker (list): List of tickers to select.

  • include_no_data (bool): Include securities that do not have data?

  • include_negative (bool): Include securities that have negative or zero prices?

Sets:
  • selected

class bt.algos.SelectTypes(include_types=(<class 'bt.core.Node'>, ), exclude_types=())[source]

Bases: Algo

Sets temp[‘selected’] based on node type. If temp[‘selected’] is already set, it will filter the existing selection.

Args:
  • include_types (list): Types of nodes to include

  • exclude_types (list): Types of nodes to exclude

Sets:
  • selected

class bt.algos.SelectWhere(signal, include_no_data=False, include_negative=False)[source]

Bases: Algo

Selects securities based on an indicator DataFrame.

Selects securities where the value is True on the current date (target.now) only if current date is present in signal DataFrame.

For example, this could be the result of a pandas boolean comparison such as data > 100.

Args:
  • signal (str|DataFrame): Boolean DataFrame containing selection logic. If a string is passed, frame is accessed using target.get_data This is the preferred way of using the algo.

  • include_no_data (bool): Include securities that do not have data?

  • include_negative (bool): Include securities that have negative or zero prices?

Sets:
  • selected

class bt.algos.SetNotional(notional_value)[source]

Bases: Algo

Sets the notional_value to use as the base for rebalancing for FixedIncomeStrategy targets

Args:
  • notional_value (str): Name of a pd.Series object containing the target notional values of the strategy over time.

Sets:
  • notional_value

class bt.algos.SetStat(stat)[source]

Bases: Algo

Sets temp[‘stat’] for use by downstream algos (such as SelectN).

Args:
  • stat (str|DataFrame): A dataframe of the same dimension as target.universe If a string is passed, frame is accessed using target.get_data This is the preferred way of using the algo.

Sets:
  • stat

class bt.algos.SimulateRFQTransactions(rfqs, model)[source]

Bases: Algo

An algo that simulates the outcomes from RFQs (Request for Quote) using a “model” that determines which ones becomes transactions and at what price those transactions happen. This can be used from the perspective of the sender of the RFQ or the receiver.

Args:
  • rfqs (str): name of a dataframe with columns Date, Security | quantity, *additional columns as required by model

  • model (object): a function/callable object with arguments
    • rfqs : data frame of rfqs to respond to

    • target : the strategy object, for access to position and value data

    and which returns a set of transactions, a MultiIndex DataFrame with:

    Date, Security | quantity, price

class bt.algos.StatTotalReturn(lookback=<DateOffset: months=3>, lag=<DateOffset: days=0>)[source]

Bases: Algo

Sets temp[‘stat’] with total returns over a given period.

Sets the ‘stat’ based on the total return of each element in temp[‘selected’] over a given lookback period. The total return is determined by ffn’s calc_total_return.

Args:
  • lookback (DateOffset): lookback period.

  • lag (DateOffset): Lag interval. Total return is calculated in the inteval [now - lookback - lag, now - lag]

Sets:
  • stat

Requires:
  • selected

class bt.algos.TargetVol(target_volatility, lookback=<DateOffset: months=3>, lag=<DateOffset: days=0>, covar_method='standard', annualization_factor=252)[source]

Bases: Algo

Updates temp[‘weights’] based on the target annualized volatility desired.

Args:
  • target_volatility: annualized volatility to target

  • lookback (DateOffset): lookback period for estimating volatility

  • lag (DateOffset): amount of time to wait to calculate the covariance

  • covar_method: method of calculating volatility

  • annualization_factor: number of periods to annualize by. It is assumed that target volatility is already annualized by this factor.

Updates:
  • weights

Requires:
  • temp[‘weights’]

class bt.algos.UpdateRisk(measure, history=0)[source]

Bases: Algo

Tracks a risk measure on all nodes of the strategy. To use this node, the additional_data argument on Backtest must have a “unit_risk” key. The value should be a dictionary, keyed by risk measure, of DataFrames with a column per security that is sensitive to that measure.

Args:
  • name (str): the name of the risk measure (IR01, PVBP, IsIndustials, etc). The name must coincide with the keys of the dictionary passed to additional_data as the “unit_risk” argument.

  • history (int): The level of depth in the tree at which to track the time series of risk numbers. i.e. 0=no tracking, 1=first level only, etc. More levels is more expensive.

Modifies:
  • The “risk” attribute on the target and all its children

  • If history==True, the “risks” attribute on the target and all its children

class bt.algos.WeighERC(lookback=<DateOffset: months=3>, initial_weights=None, risk_weights=None, covar_method='ledoit-wolf', risk_parity_method='ccd', maximum_iterations=100, tolerance=1e-08, lag=<DateOffset: days=0>)[source]

Bases: Algo

Sets temp[‘weights’] based on equal risk contribution algorithm.

Sets the target weights based on ffn’s calc_erc_weights. This is an extension of the inverse volatility risk parity portfolio in which the correlation of asset returns is incorporated into the calculation of risk contribution of each asset.

The resulting portfolio is similar to a minimum variance portfolio subject to a diversification constraint on the weights of its components and its volatility is located between those of the minimum variance and equally-weighted portfolios (Maillard 2008).

See:

https://en.wikipedia.org/wiki/Risk_parity

Args:
  • lookback (DateOffset): lookback period for estimating covariance

  • initial_weights (list): Starting asset weights [default inverse vol].

  • risk_weights (list): Risk target weights [default equal weight].

  • covar_method (str): method used to estimate the covariance. See ffn’s calc_erc_weights for more details. (default ledoit-wolf).

  • risk_parity_method (str): Risk parity estimation method. see ffn’s calc_erc_weights for more details. (default ccd).

  • maximum_iterations (int): Maximum iterations in iterative solutions (default 100).

  • tolerance (float): Tolerance level in iterative solutions (default 1E-8).

Sets:
  • weights

Requires:
  • selected

class bt.algos.WeighEqually[source]

Bases: Algo

Sets temp[‘weights’] by calculating equal weights for all items in selected.

Equal weight Algo. Sets the ‘weights’ to 1/n for each item in ‘selected’.

Sets:
  • weights

Requires:
  • selected

class bt.algos.WeighInvVol(lookback=<DateOffset: months=3>, lag=<DateOffset: days=0>)[source]

Bases: Algo

Sets temp[‘weights’] based on the inverse volatility Algo.

Sets the target weights based on ffn’s calc_inv_vol_weights. This is a commonly used technique for risk parity portfolios. The least volatile elements receive the highest weight under this scheme. Weights are proportional to the inverse of their volatility.

Args:
  • lookback (DateOffset): lookback period for estimating volatility

Sets:
  • weights

Requires:
  • selected

class bt.algos.WeighMeanVar(lookback=<DateOffset: months=3>, bounds=(0.0, 1.0), covar_method='ledoit-wolf', rf=0.0, lag=<DateOffset: days=0>)[source]

Bases: Algo

Sets temp[‘weights’] based on mean-variance optimization.

Sets the target weights based on ffn’s calc_mean_var_weights. This is a Python implementation of Markowitz’s mean-variance optimization.

See:

http://en.wikipedia.org/wiki/Modern_portfolio_theory#The_efficient_frontier_with_no_risk-free_asset

Args:
  • lookback (DateOffset): lookback period for estimating volatility

  • bounds ((min, max)): tuple specifying the min and max weights for each asset in the optimization.

  • covar_method (str): method used to estimate the covariance. See ffn’s calc_mean_var_weights for more details.

  • rf (float): risk-free rate used in optimization.

Sets:
  • weights

Requires:
  • selected

class bt.algos.WeighRandomly(bounds=(0.0, 1.0), weight_sum=1)[source]

Bases: Algo

Sets temp[‘weights’] based on a random weight vector.

Sets random target weights for each security in ‘selected’. This is useful for benchmarking against a strategy where we believe the weighing algorithm is adding value.

For example, if we are testing a low-vol strategy and we want to see if our weighing strategy is better than just weighing securities randomly, we could use this Algo to create a random Strategy used for random benchmarking.

This is an Algo wrapper around ffn’s random_weights function.

Args:
  • bounds ((low, high)): Tuple including low and high bounds for each security

  • weight_sum (float): What should the weights sum up to?

Sets:
  • weights

Requires:
  • selected

class bt.algos.WeighSpecified(**weights)[source]

Bases: Algo

Sets temp[‘weights’] based on a provided dict of ticker:weights.

Sets the weights based on pre-specified targets.

Args:
  • weights (dict): target weights -> ticker: weight

Sets:
  • weights

class bt.algos.WeighTarget(weights)[source]

Bases: Algo

Sets target weights based on a target weight DataFrame.

If the target weight dataFrame is of same dimension as the target.universe, the portfolio will effectively be rebalanced on each period. For example, if we have daily data and the target DataFrame is of the same shape, we will have daily rebalancing.

However, if we provide a target weight dataframe that has only month end dates, then rebalancing only occurs monthly.

Basically, if a weight is provided on a given date, the target weights are set and the algo moves on (presumably to a Rebalance algo). If not, not target weights are set.

Args:
  • weights (str|DataFrame): DataFrame containing the target weights If a string is passed, frame is accessed using target.get_data This is the preferred way of using the algo.

Sets:
  • weights

bt.algos.run_always(f)[source]

Run always decorator to be used with Algo to ensure stack runs the decorated Algo on each pass, regardless of failures in the stack.

backtest Module

Contains backtesting logic and objects.

class bt.backtest.Backtest(strategy, data, name=None, initial_capital=1000000.0, commissions=None, integer_positions=True, progress_bar=False, additional_data=None)[source]

Bases: object

A Backtest combines a Strategy with data to produce a Result.

A backtest is basically testing a strategy over a data set.

Note:

The Strategy will be deepcopied so it is re-usable in other backtests. To access the backtested strategy, simply access the strategy attribute.

Args:
  • strategy (Strategy, Node, StrategyBase): The Strategy to be tested.

  • data (DataFrame): DataFrame containing data used in backtest. This will be the Strategy’s “universe”.

  • name (str): Backtest name - defaults to strategy name

  • initial_capital (float): Initial amount of capital passed to Strategy.

  • commissions (fn(quantity, price)): The commission function to be used. Ex: commissions=lambda q, p: max(1, abs(q) * 0.01)

  • integer_positions (bool): Whether to use integer positions for securities in the backtest. This can have unintended consequences when prices are high relative to the amount of capital (i.e. though split-adjusted prices, or too-low of a capital amount), causing allocated positions to round to zero. While the default is True, try setting to False for more robust behavior.

  • progress_bar (Bool): Display progress bar while running backtest

  • additional_data (dict): Additional kwargs passed to StrategyBase.setup, after preprocessing This data can be retrieved by Algos using StrategyBase.get_data. The data may also be used by the Strategy itself, i.e.

    • bidoffer: A DataFrame with the same format as ‘data’, will be used by the strategy for transaction cost modeling

    • coupons: A DataFrame with the same format as ‘data’, will by used by CouponPayingSecurity to determine cashflows.

    • cost_long/cost_short: A DataFrame with the same format as ‘data’, will by used by CouponPayingSecurity to calculate asymmetric holding cost of long (or short) positions.

Attributes:
  • strategy (Strategy): The Backtest’s Strategy. This will be a deepcopy of the Strategy that was passed in.

  • data (DataFrame): Data passed in

  • dates (DateTimeIndex): Data’s index

  • initial_capital (float): Initial capital

  • name (str): Backtest name

  • stats (ffn.PerformanceStats): Performance statistics

  • has_run (bool): Run flag

  • weights (DataFrame): Weights of each component over time

  • security_weights (DataFrame): Weights of each security as a percentage of the whole portfolio over time

  • additional_data (dict): Additional data passed at construction

property herfindahl_index

Calculate Herfindahl-Hirschman Index (HHI) for the portfolio. For each given day, HHI is defined as a sum of squared weights of securities in a portfolio; and varies from 1/N to 1. Value of 1/N would correspond to an equally weighted portfolio and value of 1 corresponds to an extreme case when all amount is invested in a single asset.

1 / HHI is often considered as “an effective number of assets” in a given portfolio

property positions

DataFrame of each component’s position over time

run()[source]

Runs the Backtest.

property security_weights

DataFrame containing weights of each security as a percentage of the whole portfolio over time

property turnover

Calculate the turnover for the backtest.

This function will calculate the turnover for the strategy. Turnover is defined as the lesser of positive or negative outlays divided by NAV

property weights

DataFrame of each component’s weight over time

class bt.backtest.RandomBenchmarkResult(*backtests)[source]

Bases: Result

RandomBenchmarkResult expands on Result to add methods specific to random strategy benchmarking.

Args:
  • backtests (list): List of backtests

Attributes:
  • base_name (str): Name of backtest being benchmarked

  • r_stats (Result): Stats for random strategies

  • b_stats (Result): Stats for benchmarked strategy

plot_histogram(statistic='monthly_sharpe', figsize=(15, 5), title=None, bins=20, **kwargs)[source]

Plots the distribution of a given statistic. The histogram represents the distribution of the random strategies’ statistic and the vertical line is the value of the benchmarked strategy’s statistic.

This helps you determine if your strategy is statistically ‘better’ than the random versions.

Args:
  • statistic (str): Statistic - any numeric statistic in Result is valid.

  • figsize ((x, y)): Figure size

  • title (str): Chart title

  • bins (int): Number of bins

  • kwargs (dict): Passed to pandas hist function.

class bt.backtest.RenormalizedFixedIncomeResult(normalizing_value, *backtests)[source]

Bases: Result

A new result type to help compare results generated from FixedIncomeStrategy. Recall that in a fixed income strategy, the normalized prices are computed using additive returns expressed as a percentage of current outstanding notional (i.e. fixed-notional equivalent). In strategies where the notional is varying, this may lead to counter- intuitive results because the different terms in the sum are being scaled by different notionals in the denominator (i.e. price could be below par, but overall change in value is positive).

This class provides a way to “renormalize” the results with a different denominator value or series, i.e. using max or average notional exposure, or the risk exposure of the strategy.

Args:
  • normalizing_value: pd.Series, float or dict thereof(by strategy name)

  • backtests (list): List of backtests (i.e. from Result.backtest_list)

class bt.backtest.Result(*backtests)[source]

Bases: GroupStats

Based on ffn’s GroupStats with a few extra helper methods.

Args:
  • backtests (list): List of backtests

Attributes:
  • backtest_list (list): List of bactests in the same order as provided

  • backtests (dict): Dict of backtests by name

display_monthly_returns(backtest=0)[source]

Display monthly returns for a specific backtest.

Args:
  • backtest (str, int): Backtest. Can be either a index (int) or the

    name (str)

get_security_weights(backtest=0, filter=None)[source]
Parameters
  • backtest – (str, int) Backtest can be either a index (int) or the name (str)

  • filter – (list, str) filter columns for specific columns. Filter is simply passed as is to DataFrame[filter], so use something that makes sense with a DataFrame.

Returns

(pd.DataFrame) DataFrame of security weights

get_transactions(strategy_name=None)[source]

Helper function that returns the transactions in the following format:

Date, Security | quantity, price

The result is a MultiIndex DataFrame.

Args:
  • strategy_name (str): If none, it will take the first backtest’s strategy (self.backtest_list[0].name)

get_weights(backtest=0, filter=None)[source]
Parameters
  • backtest – (str, int) Backtest can be either a index (int) or the name (str)

  • filter – (list, str) filter columns for specific columns. Filter is simply passed as is to DataFrame[filter], so use something that makes sense with a DataFrame.

Returns

(pd.DataFrame) DataFrame of weights

plot_histogram(backtest=0, **kwds)[source]

Plots the return histogram of a given backtest over time.

Args:
  • backtest (str, int): Backtest. Can be either a index (int) or the

    name (str)

  • kwds (dict): Keywords passed to plot_histogram

plot_security_weights(backtest=0, filter=None, figsize=(15, 5), **kwds)[source]

Plots the security weights of a given backtest over time.

Args:
  • backtest (str, int): Backtest. Can be either a index (int) or the

    name (str)

  • filter (list, str): filter columns for specific columns. Filter

    is simply passed as is to DataFrame[filter], so use something that makes sense with a DataFrame.

  • figsize ((width, height)): figure size

  • kwds (dict): Keywords passed to plot

plot_weights(backtest=0, filter=None, figsize=(15, 5), **kwds)[source]

Plots the weights of a given backtest over time.

Args:
  • backtest (str, int): Backtest can be either a index (int) or the name (str)

  • filter (list, str): filter columns for specific columns. Filter is simply passed as is to DataFrame[filter], so use something that makes sense with a DataFrame.

  • figsize ((width, height)): figure size

  • kwds (dict): Keywords passed to plot

bt.backtest.benchmark_random(backtest, random_strategy, nsim=100)[source]

Given a backtest and a random strategy, compare backtest to a number of random portfolios.

The idea here is to benchmark your strategy vs a bunch of random strategies that have a similar structure but execute some part of the logic randomly - basically you are trying to determine if your strategy has any merit - does it beat randomly picking weight? Or randomly picking the selected securities?

Args:
  • backtest (Backtest): A backtest you want to benchmark

  • random_strategy (Strategy): A strategy you want to benchmark against. The strategy should have a random component to emulate skilless behavior.

  • nsim (int): number of random strategies to create.

Returns:

RandomBenchmarkResult

bt.backtest.run(*backtests)[source]

Runs a series of backtests and returns a Result object containing the results of the backtests.

Args:
  • backtest (*list): List of backtests.

Returns:

Result

core Module

Contains the core building blocks of the framework.

class bt.core.Algo(name=None)[source]

Bases: object

Algos are used to modularize strategy logic so that strategy logic becomes modular, composable, more testable and less error prone. Basically, the Algo should follow the unix philosophy - do one thing well.

In practice, algos are simply a function that receives one argument, the Strategy (referred to as target) and are expected to return a bool.

When some state preservation is necessary between calls, the Algo object can be used (this object). The __call___ method should be implemented and logic defined therein to mimic a function call. A simple function may also be used if no state preservation is necessary.

Args:
  • name (str): Algo name

property name

Algo name.

class bt.core.AlgoStack(*algos)[source]

Bases: Algo

An AlgoStack derives from Algo runs multiple Algos until a failure is encountered.

The purpose of an AlgoStack is to group a logic set of Algos together. Each Algo in the stack is run. Execution stops if one Algo returns False.

Args:
  • algos (list): List of algos.

class bt.core.CouponPayingHedgeSecurity(name, multiplier=1, fixed_income=True, lazy_add=False)[source]

Bases: CouponPayingSecurity

CouponPayingHedgeSecurity is a CouponPayingSecurity where the notional value is set to zero, and thus does not count towards the notional value of the strategy. It is intended for use in fixed income strategies.

For example in a corporate bond strategy, the notional value might refer to the size of the corporate bond portfolio, and exclude the notional of treasury bonds or interest rate swaps used as hedges.

update(date, data=None, inow=None)[source]

Update security with a given date and optionally, some data. This will update price, value, weight, etc.

class bt.core.CouponPayingSecurity(name, multiplier=1, fixed_income=True, lazy_add=False)[source]

Bases: FixedIncomeSecurity

CouponPayingSecurity expands on SecurityBase to handle securities which pay (possibly irregular) coupons (or other forms of cash disbursement). More generally, this can include instruments with any sort of carry, including (potentially asymmetric) holding costs.

Args:
  • name (str): Security name

  • multiplier (float): security multiplier - typically used for derivatives.

  • fixed_income (bool): Flag to control whether notional_value is based only on quantity, or on market value (like an equity). Defaults to notional weighting for coupon paying instruments.

  • lazy_add (bool): Flag to control whether instrument should be added to strategy children lazily, i.e. only when there is a transaction on the instrument. This improves performance of strategies which transact on a sparse set of children.

Attributes:
  • SecurityBase attributes

  • coupon (float): Current coupon payment (quantity).

  • holding_cost (float): Current holding cost (quantity).

Represents a coupon-paying security, where coupon payments adjust the capital of the parent. Coupons and costs must be passed in during setup.

property coupon

Current coupon payment (scaled by position)

property coupons

TimeSeries of coupons paid (scaled by position)

property holding_cost

Current holding cost (scaled by position)

property holding_costs

TimeSeries of coupons paid (scaled by position)

setup(universe, **kwargs)[source]

Setup Security with universe and coupon data. Speeds up future runs.

Args:
  • universe (DataFrame): DataFrame of prices with security’s name as one of the columns.

  • coupons (DataFrame): Manatory DataFrame of coupon/carry amount with the same schema as universe.

  • cost_long (DataFrame): Optional DataFrame containing the cost of holding a unit long position in the security (i.e. funding).

  • cost_short (DataFrame): Optional DataFrame containing the cost of holding a unit short position in the security (i.e. repo).

  • kwargs (dict): Dictionary of additional information needed by the strategy. In particular, often takes the form of a DataFrame of security level information (i.e. signals, risk, etc).

update(date, data=None, inow=None)[source]

Update security with a given date and optionally, some data. This will update price, value, weight, etc.

class bt.core.FixedIncomeSecurity(name, multiplier=1, lazy_add=False)[source]

Bases: SecurityBase

A Fixed Income Security is a security where notional value is measured only based on the quantity (par value) of the security. Only relevant when using FixedIncomeStrategy.

update(date, data=None, inow=None)[source]

Update security with a given date and optionally, some data. This will update price, value, weight, etc.

class bt.core.FixedIncomeStrategy(name, algos=None, children=None)[source]

Bases: Strategy

FixedIncomeStrategy is an alias for Strategy where the fixed_income flag is set to True.

For this type of strategy:
  • capital allocations are not necessary, and initial capital is not used

  • bankruptcy is disabled (and should be modeled explicitly via an Algo)

  • weights are based off notional_value rather than value

  • strategy price is computed from additive PNL returns per unit of current notional_value, with a reference price of PAR. RenormalizedFixedIncomeResult can be used to re-calculate the price-based performance statistics using different normalization schemes on total pnl.

  • “transact” assumes the role of “allocate”, in order to buy/sell children on a weighted notional basis

  • “rebalance” adjusts notionals rather than capital allocations based on weights

class bt.core.HedgeSecurity(name, multiplier=1, lazy_add=False)[source]

Bases: SecurityBase

HedgeSecurity is a SecurityBase where the notional value is set to zero, and thus does not count towards the notional value of the strategy. It is intended for use in fixed income strategies.

For example in a corporate bond strategy, the notional value might refer to the size of the corporate bond portfolio, and exclude the notional of treasury bonds or interest rate swaps used as hedges.

update(date, data=None, inow=None)[source]

Update security with a given date and optionally, some data. This will update price, value, weight, etc.

class bt.core.Node(name, parent=None, children=None)[source]

Bases: object

The Node is the main building block in bt’s tree structure design. Both StrategyBase and SecurityBase inherit Node. It contains the core functionality of a tree node.

Args:
  • name (str): The Node name

  • parent (Node): The parent Node

  • children (dict, list): A collection of children. If dict, the format is {name: child}, if list then list of children. Children can be any type of Node or str. String values correspond to children which will be lazily created with that name when needed.

Attributes:
  • name (str): Node name

  • parent (Node): Node parent

  • root (Node): Root node of the tree (topmost node)

  • children (dict): Node’s children

  • now (datetime): Used when backtesting to store current date

  • stale (bool): Flag used to determine if Node is stale and need updating

  • prices (TimeSeries): Prices of the Node. Prices for a security will be the security’s price, for a strategy it will be an index that reflects the value of the strategy over time.

  • price (float): last price

  • value (float): last value

  • notional_value (float): last notional value. Notional value is used when fixed_income=True. It is always positive for strategies, but is signed for securities (and typically set to either market value, position, or zero).

  • weight (float): weight in parent

  • full_name (str): Name including parents’ names

  • members (list): Current Node + node’s children

  • fixed_income (bool): Whether the node corresponds to a fixed income component, which would use notional-weighting instead of market value weighing. See also FixedIncomeStrategy for more details.

adjust(amount, update=True, flow=True)[source]

Adjust Node value by amount.

allocate(amount, update=True)[source]

Allocate capital to Node.

property fixed_income

Whether the node is a fixed income node (using notional weighting).

property full_name
property members

Node members. Members include current node as well as Node’s children.

property notional_value

Current notional value of the Node

property price

Current price of the Node

property prices

A TimeSeries of the Node’s price.

setup(universe, **kwargs)[source]

Setup method used to initialize a Node with a universe, and potentially other information.

to_dot(root=True)[source]

Represent the node structure in DOT format.

update(date, data=None, inow=None)[source]

Update Node with latest date, and optionally some data.

use_integer_positions(integer_positions)[source]

Set indicator to use (or not) integer positions for a given strategy or security.

By default all positions in number of stocks should be integer. However this may lead to unexpected results when working with adjusted prices of stocks. Because of series of reverse splits of stocks, the adjusted prices back in time might be high. Thus rounding of desired amount of stocks to buy may lead to having 0, and thus ignoring this stock from backtesting.

property value

Current value of the Node

property weight

Current weight of the Node (with respect to the parent).

class bt.core.Security(name, multiplier=1, lazy_add=False)[source]

Bases: SecurityBase

A standard security with no special features, and where notional value is measured based on market value (notional times price). It exists to be able to identify standard securities from nonstandard ones via isinstance, i.e. isinstance( sec, Security ) would only return True for a vanilla security, whereas SecurityBase would return True for all securities.

class bt.core.SecurityBase(name, multiplier=1, lazy_add=False)[source]

Bases: Node

Security Node. Used to define a security within a tree. A Security’s has no children. It simply models an asset that can be bought or sold.

Args:
  • name (str): Security name

  • multiplier (float): security multiplier - typically used for derivatives or to trade in lots. The quantity of the Security will always be multiplied by this to determine the underlying amount.

  • lazy_add (bool): Flag to control whether instrument should be added to strategy children lazily, i.e. only when there is a transaction on the instrument. This improves performance of strategies which transact on a sparse set of children.

Attributes:
  • name (str): Security name

  • parent (Security): Security parent

  • root (Security): Root node of the tree (topmost node)

  • now (datetime): Used when backtesting to store current date

  • stale (bool): Flag used to determine if Security is stale and need updating

  • prices (TimeSeries): Security prices.

  • price (float): last price

  • outlays (TimeSeries): Series of outlays. Positive outlays mean capital was allocated to security and security consumed that amount. Negative outlays are the opposite. This can be useful for calculating turnover at the strategy level.

  • value (float): last value - basically position * price * multiplier

  • weight (float): weight in parent

  • full_name (str): Name including parents’ names

  • members (list): Current Security + strategy’s children

  • position (float): Current position (quantity).

  • bidoffer (float): Current bid/offer spread

  • bidoffers (TimeSeries): Series of bid/offer spreads

  • bidoffer_paid (TimeSeries): Series of bid/offer paid on transactions

allocate(amount, update=True)[source]

This allocates capital to the Security. This is the method used to buy/sell the security.

A given amount of shares will be determined on the current price, a commission will be calculated based on the parent’s commission fn, and any remaining capital will be passed back up to parent as an adjustment.

Args:
  • amount (float): Amount of adjustment.

  • update (bool): Force update?

property bidoffer

Current bid/offer spread.

property bidoffer_paid

TimeSeries of bid/offer spread paid on transactions in the current step

property bidoffers

TimeSeries of bid/offer spread

property bidoffers_paid

TimeSeries of bid/offer spread paid on transactions in the current step

commission(q, p)[source]

Calculates the commission (transaction fee) based on quantity and price. Uses the parent’s commission_fn.

Args:
  • q (float): quantity

  • p (float): price

multiplier = 0.0
property notional_values

TimeSeries of notional values.

outlay(q, p=None)[source]

Determines the complete cash outlay (including commission) necessary given a quantity q. Second returning parameter is a commission itself.

Args:
  • q (float): quantity

  • p (float): price override

property outlays

TimeSeries of outlays. Positive outlays (buys) mean this security received and consumed capital (capital was allocated to it). Negative outlays are the opposite (the security close/sold, and returned capital to parent).

property position

Current position

property positions

TimeSeries of positions.

property price

Current price.

property prices

TimeSeries of prices.

run()[source]

Does nothing - securities have nothing to do on run.

setup(universe, **kwargs)[source]

Setup Security with universe. Speeds up future runs.

Args:
  • universe (DataFrame): DataFrame of prices with security’s name as one of the columns.

  • bidoffer (DataFrame): Optional argument that represents the bid/offer spread on each security across time. If provided, the strategy will account for these costs when rebalancing.

  • kwargs (dict): Dictionary of additional information needed by the strategy. In particular, often takes the form of a DataFrame of security level information (i.e. signals, risk, etc).

transact(q, update=True, update_self=True, price=None)[source]

This transacts the Security. This is the method used to buy/sell the security for a given quantity.

The amount of shares is explicitly provided, a commission will be calculated based on the parent’s commission fn, and any remaining capital will be passed back up to parent as an adjustment.

Args:
  • amount (float): Amount of adjustment.

  • update (bool): Force update on parent due to transaction proceeds

  • update_self (bool): Check for update on self

  • price (float): Optional price if the transaction happens at a bespoke level

update(date, data=None, inow=None)[source]

Update security with a given date and optionally, some data. This will update price, value, weight, etc.

property values

TimeSeries of values.

class bt.core.Strategy(name, algos=None, children=None, parent=None)[source]

Bases: StrategyBase

Strategy expands on the StrategyBase and incorporates Algos.

Basically, a Strategy is built by passing in a set of algos. These algos will be placed in an Algo stack and the run function will call the stack.

Furthermore, two class attributes are created to pass data between algos. perm for permanent data, temp for temporary data.

Args:
  • name (str): Strategy name

  • algos (list): List of Algos to be passed into an AlgoStack

  • children (dict, list): Children - useful when you want to create strategies of strategies Children can be any type of Node or str. String values correspond to children which will be lazily created with that name when needed.

  • parent (Node): The parent Node

Attributes:
  • stack (AlgoStack): The stack

  • temp (dict): A dict containing temporary data - cleared on each call to run. This can be used to pass info to other algos.

  • perm (dict): Permanent data used to pass info from one algo to another. Not cleared on each pass.

run()[source]

This is the main logic method. Override this method to provide some algorithm to execute on each date change. This method is called by backtester.

class bt.core.StrategyBase(name, children=None, parent=None)[source]

Bases: Node

Strategy Node. Used to define strategy logic within a tree. A Strategy’s role is to allocate capital to it’s children based on a function.

Args:
  • name (str): Strategy name

  • children (dict, list): A collection of children. If dict, the format is {name: child}, if list then list of children. Children can be any type of Node or str. String values correspond to children which will be lazily created with that name when needed.

  • parent (Node): The parent Node

Attributes:
  • name (str): Strategy name

  • parent (Strategy): Strategy parent

  • root (Strategy): Root node of the tree (topmost node)

  • children (dict): Strategy’s children

  • now (datetime): Used when backtesting to store current date

  • stale (bool): Flag used to determine if Strategy is stale and need updating

  • prices (TimeSeries): Prices of the Strategy - basically an index that reflects the value of the strategy over time.

  • outlays (DataFrame): Outlays for each SecurityBase child

  • price (float): last price

  • value (float): last value

  • notional_value (float): last notional value

  • weight (float): weight in parent

  • full_name (str): Name including parents’ names

  • members (list): Current Strategy + strategy’s children

  • securities (list): List of strategy children that are of type SecurityBase

  • commission_fn (fn(quantity, price)): A function used to determine the commission (transaction fee) amount. Could be used to model slippage (implementation shortfall). Note that often fees are symmetric for buy and sell and absolute value of quantity should be used for calculation.

  • capital (float): Capital amount in Strategy - cash

  • universe (DataFrame): Data universe available at the current time. Universe contains the data passed in when creating a Backtest. Use this data to determine strategy logic.

adjust(amount, update=True, flow=True, fee=0.0)[source]

Adjust capital - used to inject capital to a Strategy. This injection of capital will have no effect on the children.

Args:
  • amount (float): Amount to adjust by.

  • update (bool): Force update?

  • flow (bool): Is this adjustment a flow? A flow will not have an impact on the performance (price index). Example of flows are simply capital injections (say a monthly contribution to a portfolio). This should not be reflected in the returns. A non-flow (flow=False) does impact performance. A good example of this is a commission, or a dividend.

allocate(amount, child=None, update=True)[source]

Allocate capital to Strategy. By default, capital is allocated recursively down the children, proportionally to the children’s weights. If a child is specified, capital will be allocated to that specific child.

Allocation also have a side-effect. They will deduct the same amount from the parent’s “account” to offset the allocation. If there is remaining capital after allocation, it will remain in Strategy.

Args:
  • amount (float): Amount to allocate.

  • child (str): If specified, allocation will be directed to child only. Specified by name.

  • update (bool): Force update.

bankrupt = False
property bidoffer_paid

Bid/offer spread paid on transactions in the current step

property bidoffers_paid

TimeSeries of bid/offer spread paid on transactions in each step

property capital

Current capital - amount of unallocated capital left in strategy.

property cash

TimeSeries of unallocated capital.

close(child, update=True)[source]

Close a child position - alias for rebalance(0, child). This will also flatten (close out all) the child’s children.

Args:
  • child (str): Child, specified by name.

property fees

TimeSeries of fees.

flatten()[source]

Close all child positions.

property flows

TimeSeries of flows.

get_data(key)[source]

Returns additional data that was passed to the setup function via kwargs, for use in the algos. This allows algos to reference data sources “by name”, where the binding of the data to the name happens at Backtest creation time rather than at Strategy definition time, allowing the same strategies to be run against different data sets more easily.

get_transactions()[source]

Helper function that returns the transactions in the following format:

Date, Security | quantity, price

The result is a MultiIndex DataFrame.

property notional_values

TimeSeries of notional values.

property outlays

Returns a DataFrame of outlays for each child SecurityBase

property positions

TimeSeries of positions.

property price

Current price.

property prices

TimeSeries of prices.

rebalance(weight, child, base=nan, update=True)[source]

Rebalance a child to a given weight.

This is a helper method to simplify code logic. This method is used when we want to see the weight of a particular child to a set amount. It is similar to allocate, but it calculates the appropriate allocation based on the current weight. For fixed income strategies, it uses transact to rebalance based on notional value instead of capital.

Args:
  • weight (float): The target weight. Usually between -1.0 and 1.0.

  • child (str): child to allocate to - specified by name.

  • base (float): If specified, this is the base amount all weight delta calculations will be based off of. This is useful when we determine a set of weights and want to rebalance each child given these new weights. However, as we iterate through each child and call this method, the base (which is by default the current value) will change. Therefore, we can set this base to the original value before the iteration to ensure the proper allocations are made.

  • update (bool): Force update?

run()[source]

This is the main logic method. Override this method to provide some algorithm to execute on each date change. This method is called by backtester.

property securities

Returns a list of children that are of type SecurityBase

set_commissions(fn)[source]

Set commission (transaction fee) function.

Args:

fn (fn(quantity, price)): Function used to determine commission amount.

setup(universe, **kwargs)[source]

Setup strategy with universe. This will speed up future calculations and updates.

setup_from_parent(**kwargs)[source]

Setup a strategy from the parent. Used when dynamically creating child strategies.

Args:
  • kwargs: additional arguments that will be passed to setup

    (potentially overriding those from the parent)

transact(q, child=None, update=True)[source]

Transact a notional amount q in the Strategy. By default, it is allocated recursively down the children, proportionally to the children’s weights. Recursive allocation only works for fixed income strategies. If a child is specified, notional will be allocated to that specific child.

Args:
  • q (float): Notional quantity to allocate.

  • child (str): If specified, allocation will be directed to child only. Specified by name.

  • update (bool): Force update.

property universe

Data universe available at the current time. Universe contains the data passed in when creating a Backtest. Use this data to determine strategy logic.

update(date, data=None, inow=None)[source]

Update strategy. Updates prices, values, weight, etc.

property values

TimeSeries of values.

bt.core.is_zero(x)[source]

Test for zero that is robust against floating point precision errors