simple_back package

A backtester with minimal setup and sensible defaults.

simple_back is a backtester providing easy ways to test trading strategies, often ones that use external data, with minimal amount of code, while avoiding time leaks.

Submodules

simple_back.backtester module

class simple_back.backtester.Backtester[source]

Bases: object

The Backtester object is yielded alongside the current day and event (open or close) when it is called with a date range, which can be of the following forms. The Backtester object stores information about the backtest after it has completed.

Examples

Initialize with dates as strings:

bt['2010-1-1','2020-1-1'].run()
# or
for day, event, b in bt['2010-1-1','2020-1-1']:
    ...

Initialize with dates as datetime.date objects:

bt[datetime.date(2010,1,1),datetime.date(2020,1,1)]

Initialize with dates as int:

bt[-100:] # backtest 100 days into the past
add_line(**kwargs)[source]

Adds a vertical line on the plot on the current date + event.

add_metric(key, value)[source]

Called inside the backtest, adds a metric that is visually tracked.

Parameters
  • key (str) – the metric name

  • value (float) – the numerical value of the metric

property balance

Get the current or starting balance.

Examples

Get the current balance:

bt.balance.current

Get the starting balance:

bt.balance.start
Return type

Balance

log(text)[source]

Adds a log text on the current day and event that can be accessed using logs after the backtest has completed.

Parameters

text (str) – text to log

property logs

Returns a pd.DataFrame for logs collected during the backtest.

Return type

DataFrame

long(symbol, **kwargs)[source]

Enter a long position of the given symbol.

Parameters
  • symbol (str) – the ticker to buy

  • kwargs – one of either “percent” as a percentage of total value (cash + positions), “absolute” as an absolute value, “percent_available” as a percentage of remaining funds (excluding positions) “nshares” as a number of shares

property metrics

Get a dataframe of all metrics collected during the backtest(s).

Return type

DataFrame

property pf

Shorthand for portfolio, returns the backtesters portfolio.

Return type

Portfolio

price(symbol)[source]

Get the current price of a given symbol.

Parameters

symbol (str) – the ticker

Return type

float

run()[source]

Run the backtesters strategies without using an iterator. This is only possible if strategies have been set using BacktesterBuilder.strategies().

short(symbol, **kwargs)[source]

Enter a short position of the given symbol.

Parameters
  • symbol (str) – the ticker to short

  • kwargs – one of either “percent” as a percentage of total value (cash + positions), “absolute” as an absolute value, “percent_available” as a percentage of remaining funds (excluding positions) “nshares” as a number of shares

show(start=None, end=None)[source]

Show the backtester as a plot.

Parameters
  • start – the start date

  • end – the end date

property strategies

Provides access to sub-strategies, returning a StrategySequence.

property summary

Get a dataframe showing the last and overall values of all metrics collected during the backtest. This can be helpful for comparing backtests at a glance.

Return type

DataFrame

property timestamp

Returns the current timestamp, which includes the correct open/close time, depending on the calendar that was set using BacktesterBuilder.calendar()

class simple_back.backtester.BacktesterBuilder[source]

Bases: object

Used to configure a Backtester and then creating it with build()

Example

Create a new Backtester with 10,000 starting balance which runs on days the NYSE is open:

bt = BacktesterBuilder().balance(10_000).calendar('NYSE').build()
balance(amount)[source]

Required, set the starting balance for all Strategy objects run with the Backtester

Parameters

amount (int) – The starting balance.

Return type

BacktesterBuilder

build()[source]

Build a Backtester given the previous configuration.

Return type

Backtester

calendar(calendar)[source]

Optional, set a pandas market calendar to be used. If not called, “NYSE” is used.

Parameters

calendar (str) – the calendar identifier

Return type

BacktesterBuilder

clear_metrics()[source]

Optional, remove all default metrics, except PortfolioValue, which is needed internally.

Return type

BacktesterBuilder

compare(strategies)[source]

Optional, alias for BacktesterBuilder.strategies(), should be used when comparing to BuyAndHold of a ticker instead of other strategies.

Parameters

strategies (List[Union[Callable[[date, str, Backtester], None], Strategy, str]]) – should be the string of the ticker to compare to, but Strategy objects can be passed as well

data(data)[source]

Optional, add a DataProvider to use external data without time leaks.

Parameters

data (DataProvider) – The data provider.

Return type

BacktesterBuilder

live_metrics(every=10)[source]

Optional, shows all metrics live in output. This can be useful when running simple-back from terminal.

Parameters
  • every (int) – how often metrics should be updated

  • events ((in) –

  • 10 = 5 days) (e.g.) –

Return type

BacktesterBuilder

live_plot(every=None, metric='Total Value', figsize=None, min_y=0, blocking=False)[source]

Optional, shows the backtest results live using matplotlib. Can only be used in notebooks.

Parameters
  • every (Optional[int]) – how often metrics should be updated (in events, e.g. 10 = 5 days) the regular default is 10, blocking default is 100

  • metric (str) – which metric to plot

  • figsize (Optional[Tuple[float, float]]) – size of the plot

  • min_y (int) – minimum value on the y axis, set to None for no lower limit

  • blocking (bool) – will disable threading for plots and allow live plotting in terminal, this will slow down the backtester significantly

Return type

BacktesterBuilder

live_progress(every=10)[source]

Optional, shows a live progress bar using tqdm, either as port of a plot or as text output.

Return type

BacktesterBuilder

metrics(metrics)[source]

Optional, set additional Metric objects to be used.

Parameters

metrics (Union[Metric, List[Metric]]) – one or more Metric objects

Return type

BacktesterBuilder

name(name)[source]

Optional, name will be set to “Backtest 0” if not specified.

Set the name of the strategy run using the Backtester iterator.

Parameters

name (str) – The strategy name.

Return type

BacktesterBuilder

no_live_metrics()[source]

Disables showing live metrics.

Return type

BacktesterBuilder

no_live_plot()[source]

Disables showing live plots.

Return type

BacktesterBuilder

no_live_progress()[source]

Disables the live progress bar.

Return type

BacktesterBuilder

prices(prices)[source]

Optional, set the DailyPriceProvider used to get prices during a backtest. If this is not called, YahooPriceProvider is used.

Parameters

prices (DailyPriceProvider) – The price provider.

Return type

BacktesterBuilder

slippage(slippage=0.0005)[source]

Optional, sets slippage which will create a (lower bound) strategy. The orginial strategies will run without slippage.

Parameters

slippage (int) – the slippage in percent of the base price, default is equivalent to quantopian default for US Equities

strategies(strategies)[source]

Optional, sets Strategy objects to run.

Parameters

strategies (List[Union[Callable[[date, str, Backtester], None], Strategy, str]]) – list of Strategy objects or tickers to BuyAndHold

Return type

BacktesterBuilder

trade_cost(trade_cost)[source]

Optional, set a Fee to be applied when buying shares. When not set, NoFee is used.

Parameters

trade_cost (Union[Fee, Callable[[float, float], Tuple[float, int]]]) – one ore more Fee objects or callables.

Return type

BacktesterBuilder

class simple_back.backtester.Portfolio(bt, positions=[])[source]

Bases: collections.abc.MutableSequence

A portfolio is a collection of Position objects, and can be used to liquidate() a subset of them.

attr(attribute)[source]

Get a list of values for a certain value for all posititions

Parameters

attribute (str) – String name of the attribute to get. Can be any attribute of Position.

Return type

List

property df
Return type

DataFrame

filter(func)[source]

Filters positions using any :class`.Callable`

Parameters

func (Callable[[Position], bool]) – The function/callable to do the filtering.

Return type

Portfolio

insert(index, value)[source]

S.insert(index, value) – insert value before index

Return type

None

liquidate(nshares=- 1, _bt=None)[source]

Liquidate all positions in the current “view” of the portfolio. If no view is given using [‘some_ticker’], filter(), Portfolio.long() or Portfolio.short(), an attempt to liquidate all positions is made.

Parameters

nshares (int) – The number of shares to be liquidated. This should only be used when a ticker is selected using [‘some_ticker’].

Examples

Select all MSFT positions and liquidate them:

bt.portfolio['MSFT'].liquidate()

Liquidate 10 MSFT shares:

bt.portfolio['MSFT'].liquidate(nshares=10)

Liquidate all long positions:

bt.portfolio.long.liquidate()

Liquidate all positions that have lost more than 5% in value. We can either use filter() or the dataframe as indexer (in this case in combination with the pf shorthand):

bt.pf[bt.pf.df['profit_loss_pct'] < -0.05].liquidate()
# or
bt.pf.filter(lambda x: x.profit_loss_pct < -0.05)
property long

Returns a view of the portfolio (which can be treated as its own Portfolio) containing all long positions.

Return type

Portfolio

property short

Returns a view of the portfolio (which can be treated as its own Portfolio) containing all short positions.

Return type

Portfolio

property total_value

Returns the total value of the portfolio.

Return type

float

class simple_back.backtester.Position(bt, symbol, date, event, nshares, uid, fee, slippage=None)[source]

Bases: object

Tracks a single position in a portfolio or trade history.

property initial_value

Returns the initial value of the position, including fees.

Return type

float

property nshares

Returns the number of shares in the position.

Return type

int

property order_type

Returns “long” or “short” based on the position type.

Return type

str

property price

Returns the current price if the position is held in a portfolio. Returns the last price if the position was liquidated and is part of a trade history.

Return type

float

property profit_loss_abs

Returns the profit/loss associated with the position (not including commission) in absolute terms.

Return type

float

property profit_loss_pct

Returns the profit/loss associated with the position (not including commission) in relative terms.

Return type

float

property value

Returns the current market value of the position.

Return type

float

property value_pershare

Returns the value of the position per share.

Return type

float

class simple_back.backtester.StrategySequence(bt)[source]

Bases: object

A sequence of strategies than can be accessed by name or int index. Returned by Backtester.strategies and should not be used elsewhere.

Examples

Access by str:

bt.strategies['Some Strategy Name']

Access by int:

bt.strategies[0]

Use as iterator:

for strategy in bt.strategies:
    # do something
simple_back.backtester.display_side_by_side(bts)[source]

simple_back.data_providers module

class simple_back.data_providers.CachedProvider(debug=False)[source]

Bases: abc.ABC

clear_cache()[source]
get_cache(key)[source]
get_key(key)[source]
Return type

str

in_cache(key)[source]
Return type

bool

abstract property name
rem_cache(key)[source]
set_cache(key, val, expire_days=None)[source]
class simple_back.data_providers.DailyDataProvider(debug=False)[source]

Bases: simple_back.data_providers.CachedProvider

abstract property columns
Return type

List[str]

abstract property columns_order
Return type

List[int]

abstract get(symbol, date, event)[source]
Return type

DataFrame

set_date_event(date, event)[source]
class simple_back.data_providers.DailyPriceProvider(highlow=True, debug=False)[source]

Bases: simple_back.data_providers.DailyDataProvider

property columns
property columns_order
abstract get(symbol, date, event)[source]
Return type

DataFrame

class simple_back.data_providers.DataProvider(debug=False)[source]

Bases: simple_back.data_providers.CachedProvider

abstract dates(symbol)[source]
abstract get(datetime, symbol=None)[source]
abstract property name
class simple_back.data_providers.SpProvider(debug=False)[source]

Bases: simple_back.data_providers.WikipediaProvider

property name
process_html(html, symbol)[source]
transform_symbol(symbol)[source]
class simple_back.data_providers.WikipediaProvider(debug=False)[source]

Bases: simple_back.data_providers.DataProvider

dates(symbol)[source]
get(datetime, symbol)[source]
get_revisions(title)[source]
property name
abstract process_html(html, symbol)[source]
transform_symbol(symbol)[source]
class simple_back.data_providers.YahooFinanceProvider(highlow=False, adjust_prices=True, debug=False)[source]

Bases: simple_back.data_providers.DailyPriceProvider

get(symbol, date, event)[source]
Return type

DataFrame

property name

simple_back.exceptions module

exception simple_back.exceptions.BacktestRunError(message)[source]

Bases: Exception

exception simple_back.exceptions.InsufficientCapitalError(message)[source]

Bases: Exception

exception simple_back.exceptions.LongShortLiquidationError(message)[source]

Bases: Exception

exception simple_back.exceptions.MissingMetricsError(metrics, message)[source]

Bases: Exception

exception simple_back.exceptions.NegativeValueError(message)[source]

Bases: Exception

exception simple_back.exceptions.PriceUnavailableError(symbol, requested_date, message)[source]

Bases: Exception

exception simple_back.exceptions.TimeLeakError(current_date, requested_date, message)[source]

Bases: Exception

simple_back.fees module

class simple_back.fees.Fee[source]

Bases: abc.ABC

Abstract Callable that calculates the total cost and number of shares given an asset price and the capital to be allocated to it. It returns the total cost and the number of shares aquired for that cost.

abstract cost(price, nshares)[source]
abstract nshares(price, capital)[source]
class simple_back.fees.FlatPerShare(fee)[source]

Bases: simple_back.fees.Fee

cost(price, nshares)[source]
nshares(price, capital)[source]
class simple_back.fees.FlatPerTrade(fee)[source]

Bases: simple_back.fees.Fee

cost(price, nshares)[source]
nshares(price, capital)[source]
class simple_back.fees.NoFee[source]

Bases: simple_back.fees.Fee

Returns the number of shares possible to buy with given capital, and calculates to total cost of buying said shares.

Example

How many shares of an asset costing 10 can be bought using 415, and what is the total cost:

>>> NoFee(10, 415)
41, 410
cost(price, nshares)[source]
nshares(price, capital)[source]

simple_back.metrics module

class simple_back.metrics.AnnualReturn(name=None)[source]

Bases: simple_back.metrics.SingleMetric

get_value(bt)[source]
property name
property requires
class simple_back.metrics.DailyProfitLoss(name=None)[source]

Bases: simple_back.metrics.SeriesMetric

get_value(bt)[source]
property name
property requires
class simple_back.metrics.DailyProfitLossPct(name=None)[source]

Bases: simple_back.metrics.SeriesMetric

get_value(bt)[source]
property name
property requires
class simple_back.metrics.MaxDrawdown(name=None)[source]

Bases: simple_back.metrics.SingleMetric

get_value(bt)[source]
property name
class simple_back.metrics.Metric[source]

Bases: abc.ABC

abstract get_value(bt)[source]
abstract property name
Return type

str

property requires
Return type

Optional[List[type]]

set_values(bt)[source]
class simple_back.metrics.PortfolioValue(name=None)[source]

Bases: simple_back.metrics.SeriesMetric

get_value(bt)[source]
property name
class simple_back.metrics.SeriesMetric(name=None)[source]

Bases: simple_back.metrics.Metric

property df
abstract get_value(bt)[source]
abstract property name
property values
class simple_back.metrics.SharpeRatio(risk_free_rate=0.0445)[source]

Bases: simple_back.metrics.SingleMetric

get_value(bt)[source]
property name
property requires
class simple_back.metrics.SingleMetric(name=None)[source]

Bases: simple_back.metrics.Metric

abstract get_value(bt)[source]
abstract property name
class simple_back.metrics.TotalReturn(name=None)[source]

Bases: simple_back.metrics.SeriesMetric

get_value(bt)[source]
property name
property requires
class simple_back.metrics.TotalValue(name=None)[source]

Bases: simple_back.metrics.SeriesMetric

get_value(bt)[source]
property name
property requires
class simple_back.metrics.Volatility(name=None)[source]

Bases: simple_back.metrics.SingleMetric

get_value(bt)[source]
property name
property requires

simple_back.strategy module

class simple_back.strategy.BuyAndHold(ticker)[source]

Bases: simple_back.strategy.Strategy

property name
run(day, event, bt)[source]
class simple_back.strategy.SellAndHold(ticker)[source]

Bases: simple_back.strategy.Strategy

property name
run(day, event, bt)[source]
class simple_back.strategy.Strategy[source]

Bases: abc.ABC

abstract property name
abstract run(day, event, bt)[source]

simple_back.utils module

simple_back.utils.is_notebook()[source]