Welcome to backtest’s documentation!

Getting Started

  1. Install the package to your machine and all its dependancies.

  2. Take a look at the Common Usage Pattern section to see how the package can be used to solve common questions or problems.

  3. Read through the backtest documentation as it explains The methodology used to run the backtest in greater detail.

Installation

  1. Open a bash shell. On Mac just open Terminal. On windows either download the Bash shell following these instructions: https://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/ or use the anaconda shell, which is Bash.

  2. Clone the backtest repo to your machine running the following command:

    git clone https://github.com/GTL-Capital/backtest.git
    
  3. Enter your Github username and password if prompted.

  4. Install the python package by running the following commands:

    cd backtest
    pip install .
    
  5. That’s it! Now you can use the backtest package in your scripts. Some examples:

    import backtest #import whole backtest package
    from backtest.backtest import Backtest #import just Backtest Class
    from backtest.market import Market #import just Market Class
    from backtest.position import Position, Spread #import Position & Spread Classes
    
  6. If you get any errors about missing package dependances, you can create a virtual env and install them there or install the dependances on your base by running pip install <package from error message>

Common Usage Patterns

'Will eventually include some sample code and usage patterns'

Indices and tables

backtest.py

This module contains the Backtest class, which is the primary way a user will interact with the backtest package.

class backtest.backtest.Backtest(strategy_trade_map: dict, uts_df, market, portfolio, general_opening_criteria: list, general_closing_criteria: list, strategy_opening_criteria: dict = {}, strategy_closing_criteria: dict = {})

Stores and implements rules and predictions in an event-based derivates backtest.

The Backtest object requires a large number of inputs to enable it to execute an event based backtest. These attributes are passed to an instance of a backtest object on initialization. First, read through and understand these attributes, and then we will talk about how they interact to power your backtest.

uts_df

This attribute is how you control the underlying securities the software will search for potential positions to open. The index should be of type pd.Timestamp with each row representing a trading day ascending from past to present. You can have as many columns as you’d like, but a common use case is to have a ‘shorts’ and ‘longs’ column. Within the columns, the cells should contain a list of underlying securities to search the spreads for a potential position. In the example, there are three symbols per cell, but you could have any arbitrary amount of symbols per cell.

Example

Underlying To Strategy DataFrame (uts_df)

date

shorts

longs

2020-10-19

[‘MANU’, ‘WBAI’, ‘DS’]

[‘CRBP’, ‘JE’, ‘WVE’]

2020-10-20

[‘DS’, ‘MANU’, ‘WBAI’]

[‘CRBP’, ‘HPR’, ‘JE’]

2020-10-21

[‘DS’, ‘WBAI’, ‘WWR’]

[‘CRBP’, ‘HPR’, ‘JE’]

2020-10-22

[‘DS’, ‘WBAI’, ‘MANU’]

[‘CRBP’, ‘HPR’, ‘JE’]

2020-10-23

[‘DS’, ‘WBAI’, ‘MANU’]

[‘CRBP’, ‘HPR’, ‘JE’]

This format is conveient for an ML approach where each column can represent the highest confidence underlyings for a given prediction.

Type

pandas.Dataframe

strategy_trade_map

The strategy_trade_map is a dictionary that maps the column names of the uts_df Dataframe to a perticular strategy definition. A strategy definition is an arbitrary number of nested lists that represent as desired contract as such:

['put/call', delta(float), daysToExpiration(int), quantity(int)]

Note: quantity will be negative for short positions.

You can combine a number of these definitions to create a desired strategy. A Put credit spread for example:[['put', .45, 35, -1], ['put', .15, 35, 1]].

Example

strategy_trade_map = {
    'longs': [['put', .45, 35, -1], ['put', .15, 35, 1]],
    'shorts': [['call', .45, 35, -1], ['call', .15, 35, 1]]
}
Type

dict

general_opening_criteria

The general_opening_criteria should be a list of functions. All functions in the list should accept a Position object as an input and return a bool. The idea is that you can write simple lambdas or even complex functions to determine if you want to open a position based on position attributes (see Position).

The general opening criteria will apply to all positions independent of the strategy. This is useful for ensuring that a backtest does not open a position where the potential gain is incredibly low relative to loss or to avoid other situations where opening a position doesnt make sense. All opening criteria needs to satisfied for the position to be added to the portfolio. If any are not, the position is discarded.

Example

general_opening_criteria = [
    lambda position: position.dte[-1] <= 40 and position.dte[-1] >=30,
    lambda position: len([c[0] for c in position.spread.data]) == len(list(np.unique([c[0] for c in position.spread.data])))
]
Type

list

general_closing_criteria

This attribute functions much in the same way that the general_opening_criteria list does. Instead of being checked to open positions, this is checked daily to see if it makes sense to close the positions. This can be used to define how to take losses or gains.

Example

general_closing_criteria = [
    lambda position: True if position.max_gain/3 < position.pl[-1] else False,
    lambda position: True if position.dte[-1] <= 10 else False
]
Type

list

strategy_opening_criteria

Maps strategies (columns from uts_df) to specific opening criteria. This functionality is useful when you want to apply additional contrastraints to a perticular strategy. You may, for example, want different rules to apply for risk defined vs undefined risk spreads.

This attribute is optional and is blank by default.

Example

strategy_opening_criteria = {
    'longs':[
        lambda position: True if position.delta[-1] >= 0 else False
    ],
    'shorts':[
        lambda position: True if position.delta[-1] <= 0 else False
    ]
}
Type

dict

strategy_closing_criteria

Just like the strategy_opening_criteria, it maps strategies to closing criteria.

This attribute is optional and is blank by default

Example

strategy_closing_criteria = {
    'longs':[
        lambda position: True if position.max_downside_loss/2 >= position.pl[-1] else False
    ]
}
Type

dict

__init__(strategy_trade_map: dict, uts_df, market, portfolio, general_opening_criteria: list, general_closing_criteria: list, strategy_opening_criteria: dict = {}, strategy_closing_criteria: dict = {})

Initialize self. See help(type(self)) for accurate signature.

run_backtest(start=Timestamp('1677-09-21 00:12:43.145225'), stop=Timestamp('2262-04-11 23:47:16.854775807'))

Runs backtest based on the instance configuration.

Parameters
  • start (pandas.Timestamp) – The date to start the backtest on. Must be contained within the index of the uts_df Dataframe.

  • stop (pandas.Timestamp) – The date to stop the backtest. Also must be contained within the index of uts_df.

position.py

Contains the Position and Spread classes.

class backtest.position.Position(initiation_date, spread: backtest.position.Spread, strategy=None)

A temporal representation of a spread, containing pricing information.

The Position class enables a more detailed analysis of collection of contracts. with the pricing data included, the Positon object contains many attributes that allow for a deep understanding of metrics such as max upside/downside gain/loss, aggregate greeks, bid/ask spread ect.

The Position object is the fundamental building block of the backtest engine as it simulates holding any arbitrary collection of options over time. It also comes pre- loaded with vizualization methods and functions to assist in “holding” or carrying forward the position into the future.

Note: It is most common to create a Position object from a helper function in the Market class as such:

from backtest.market import Market

market = Market()
spread = market.spread_from_dte_delta_search('JPM',
                                        '2021-01-04',
                                        ['Put', .2, 40, 1],
                                        ['pUt', .45, 40, -1],
                                        ['Call', .45, 40, -1],
                                        ['cALL', .2, 40, 1]
                                        )
position = market.open_position('2021-01-04', spread)
__init__(initiation_date, spread: backtest.position.Spread, strategy=None)

Initialization of a Position instance.

Requires an initation date and an backtest.position.Spread object to be passed.

Parameters
  • initiation_date (str) – The date to price the position on. Should be in the format ‘YYYY-MM-DD’. This date must be contained within the Spread.as_of_date_list attribute in the Spread instance passed.

  • spread (Spread) – The backtest.position.Spread to base the position on.

strategy

The strategy that the position represents. Will eventually be used for position managment.

Type

str

priced

Flag to determine if the position has been priced by a Market() instance.

Type

bool

closed

Flag that indicates if the position has been closed out. Is useful within the context of a portfolio.

Type

bool

initiation_date

The date the position was established. In the format ‘YYYY-MM-DD’

Type

str

initial_open_price

An estimate of the price at which a position could be established after accounting for crossing the bid/ask spread and paying commissions.

Type

float

net_adjustment_price

The net cost of any adustments made to the position over its lifetime. Is useful for keeping track of the financial impact of rolls and other trade managment tactics.

Type

float

parity_upper_bound

This is a utility attribute that helps vizualization methods determine a good upper bound for the parity P/L plot.

Type

float

parity_evaluated

A flag that indicates if the method that evaluates parity metrics has been run. This should take place after position pricing occurs.

Type

bool

parity_series

The Y axis series of the parity P/L plot.

Type

np.Array

max_loss

The maximum amount of money that could be lost. This can be -inf.

Type

float

max_upside_loss

The maximum amount of money that could be lost if the underlying price moves upward from its current level on the as_of_date.

Type

float

max_downside_loss

The maximum amount of money that could be lost if the underlying price moves downward from its current level on the as_of_date.

Type

float

max_gain

The maximum amount of money that could be gained. This can be inf.

Type

float

max_upside_gain

The maximum amount of money that could be gained if the underlying price moves upward from its current level on the as_of_date. Can be inf.

Type

float

max_downside_gain

The maximum amount of money that could be gained if the underlying price moves downward from its current level on the as_of_date. Can be inf.

Type

float

break_even_prices

A list of floats representing the prices that the position will have a P/L of 0 at expiration. An Iron Condor, for example, should have two values.

Type

list

profit_ranges

A list containing tuples that represent the price ranges for which the position will carry a positive P/L at expiration.

Type

list

spread

The Spread object that was passed to created the position.

Type

backtest.position.Spread

net_credit

Flag to determine if position was debit or credit.

Type

bool

max_as_of_date

The last day all of the options in a given position will exist.

Type

str

homogeneous_expire

Flag to determine if all of the contracts expire together.

Type

bool

strikes

Contains ints representing all of the strikes of the contracts.

Type

list

as_of_date

The current date for the position’s pricing. In the format “YYYY-MM-DD”

Type

str

expirations

The expiration dates that the contracts expire on.

Type

list

days_held

The number of trading days that the position has been held.

Type

int

holding_dates

Each day the position is held, the as_of_date is appended to this historical list.

Type

list

bid

Contains the historical bid values from the initiation_date to the current as_of_date. The current bid will always be Position.bid[-1].

Type

list

ask

Contains the historical ask values from the initiation_date to the current as_of_date. The current ask will always be Position.ask[-1].

Type

list

mark

Contains the historical mark values from the initiation_date to the current as_of_date. The current mark will always be Position.mark[-1].

Type

list

close_price

Contains the historical close_price values from the initiation_date to the current as_of_date. The current close_price will always be Position.close_price[-1].

Type

list

delta

Contains the historical delta values from the initiation_date to the current as_of_date. The current delta will always be Position.delta[-1].

Type

list

gamma

Contains the historical gamma values from the initiation_date to the current as_of_date. The current gamma will always be Position.gamma[-1].

Type

list

theta

Contains the historical theta values from the initiation_date to the current as_of_date. The current theta will always be Position.theta[-1].

Type

list

vega

Contains the historical vega values from the initiation_date to the current as_of_date. The current vega will always be Position.vega[-1].

Type

list

rho

Contains the historical rho values from the initiation_date to the current as_of_date. The current rho will always be Position.rho[-1].

Type

list

net_volatility

Contains the historical net_volatility values from the initiation_date to the current as_of_date. The current net_volatility will always be Position.net_volatility[-1].

Type

list

dte

Contains the historical dte values from the initiation_date to the current as_of_date. The current dte will always be Position.dte[-1].

Type

list

pl

Contains the historical pl values from the initiation_date to the current as_of_date. The current pl will always be Position.pl[-1].

Type

list

stkPx

Contains the historical stkPx values from the initiation_date to the current as_of_date. The current stkPx will always be Position.stkPx[-1].

Type

list

_adjust_spread()

UNDEVELOPED. Adjusts the spread and position values to represent a change in the positions contracts

This will be a useful method once position adustments are supported. It will need to edit self.spread to contain the new contracts and probably document the changes one way or another such that its clear that changes were made when using analysis methods.

_evaluate_parity()

Evaluates the risk profile of the position at expiration.

Fills values for all of the parity metrics which are:

self.parity_upper_bound, self.parity_evaluated,
self.parity_series, self.max_loss,
self.max_upside_loss, self.max_downside_loss,
self.max_gain, self.max_upside_gain,
self.max_downside_gain, self.break_even_prices,
self.profit_ranges

These values should be calculated after using the _update_position() method to fill out pricing information. Using the Market methods step_position() and open_position() will call this method correctly for the user.

_evaluate_position()
_step_as_of_date()

Updates the self.as_of_date to the next as of date in the self.as_of_date list variable and returns the new as of date. Will no longer modify self.as_of_date when the maximum as of date is reached.

Returns

The next as_of_date in the as_of_date_list after the current as_of_date.

Return type

str

_update_position(spread_values: dict)

Updates the position’s pricing based on a dictionary called spread_values.

The correct spread_values dictionary can be obtained from the Market class method price_spread() which returns the spread_values dict. Once again, the step_position() and open_position() will take care of this handoff between classes for you.

Parameters

spread_values (dict) –

A dictionary that contains the pricing values for a perticular spread.

Example

spread_values = {
'bid': bid,
'ask': ask,
'mark': mark,
'open_price': open_price,
'net_credit': net_credit,
'close_price': close_price,
'delta': delta,
'gamma': gamma,
'theta': theta,
'vega': vega,
'rho': rho,
'homogeneous_expire': homogeneous_expire,
"net_volatility": net_volatility,
'expirations': list(numpy.unique(expiration)),
'strikes': strikes,
'dte': min_dte,
'stkPx': stkPx
}

close_position()

Sets the Position.closed flag to True

plot_expiration_metrics()

Plots the PL vs the Underlying Price at expiration

Allows the user to vizually inspect the risk profile of the position in the popular parity plot format. Will print a chart.

plot_position_time_series(plot_last_day=False)

Plots the value of the position and greeks over time.

Generates 3 sub plots that track the position greeks, PL, and bid ask spread. Prints the plot after the method is called.

Parameters

plot_last_day (bool) – Sometimes the final day of a position held to expiration is quite noisy for pricing metrics and greeks. Thus for positions that were held to expiration it can be beneficial to not chart the last day. False is the default action.

to_pandas()

Creates a date indexed pandas dataframe from a position object.

Dataframe columns are as follows: [‘date’: as_of_date_list,’bid’, ‘ask’,’mark’,’close_price’,’delta’,’gamma’,’theta’,’vega’,’rho’, ‘net_volatility’,’days_to_expiration’,’PL’,’stkPx’]

Returns

Dataframe based on positon values over the course of the position holding period.

Return type

pandas.Dataframe

class backtest.position.Spread(type='Custom Spread')

A non-temporal representation of a collection of options.

Unlike the Position object, the Spread does not hold a trade value or make an attempt to price the collection of options contracts. The purpose of a spread is to find the collection of contracts that satisfy conditions set forth such as delta, days to expiration, number of contracts, long/short, ect. Methods in the backtest.market.Market() object can assist in these searches.

__init__(type='Custom Spread')

Initialization of a Spread object.

Parameters

type (str) –

The type of strategy the spread represents. This defaults to ‘Custom Spread’. The _evaluate_type() method can infer the type based on its characteristics.

Examples: ‘Iron Condor’, ‘Butterfly’, ‘Vertical’, ect.

data

Contains tuples of the contract symbol and quantity. ex.) [(AAPL_061821P380, -1), (AAPL_061821P370, 1)].

Type

list

as_of_date_list

Holds an ordered list of all of the trade dates that this spread could potentially be held on.

Type

list

type

The type of strategy that the spread represents. ex.) A ‘Put Credit’ would be [(AAPL_061821P380, -1), (AAPL_061821P370, 1)].

Type

str

symbols

The distinct underlying symbols in the spread. Will only have multiple symbols for pairs trades.

Type

list

expirations

The distinct expiration dates of the collection of contracts. A calendar ,for example, would have two dates, where as an Iron Condor would only have one expiration date in the list.

Type

list

putCallCount

Has two keys, 'PUT' and 'CALL', which map to an integer counting the number of puts or calls in a spread.

Type

dict

_evaluate_type()

UNDER-DEVELOPED. Determines the strategy type implicitly.

Method will assess the type of spread that is being initiated implicitly with a rules based algoritm based on the contracts stored in self.data will use the contract_info_from_symbol function to parse the contracts stored in self.data. Should be called every time add_contract is called.

Returns

The inffered strategy type as a string. Default return is ‘Custom Spread’

Return type

str

add_contract(contract: str, quantity: int)

Adds a new contract to the Spread object.

Method will add a new contract to an instance of the Spread object. It currently does not check to ensure that the contract string exists, so this must be done prior to making this method call.

Parameters
  • contract (str) – The contract symbol to add to the Spread. Ex.) An apple put expiring on June 18th 2021 at a 380 dollar strike would be AAPL_061821P380.

  • quantity (int) – The number of contracts to add. Negative quantities represent short positions.

market.py

Contains the Market object

class backtest.market.Market(symbols=None, markup: float = 0.3, commission: float = 0.65, pricing_method: str = 'standard', max_date_cached: int = 5)

Acts as an API with the duel purpose of 1.) Converting abstract strategy ideas into concrete spreads with matching contracts. 2.) Pricing spreads based on historical data and market micro-structure assumptions such as slippage and commisions.

The Market object interacts with data sources to pull derivative quotes and then manipulates the data to inform analysis on positions or to power a backtest engine. Market() can be initialized without any information. However, you can load pricing data into memory by passing a list of symbols on creation or by running the self.add_underlyings method after initialization (currently in development). This is useful to do in a situation where you are interested in working with a specific symbol exclusivly or know that many trades will be constructed on said symbol and thus caching data reduces calculation time by storing data in memeory. This can create memory problems if used carelessly. In the absence of loading a symbol Market() will pull information from data sources as needed.

__init__(symbols=None, markup: float = 0.3, commission: float = 0.65, pricing_method: str = 'standard', max_date_cached: int = 5)

The initialization of an instance of the market class.

Parameters
  • symbols (str) – DEPRECIATED. The old functionality of this param is currently under development. Do not use until this changes.

  • markup (float) – This is used to account for crossing the bid ask spread. It should be a float between 0.00 and 1.00 The markup moves your opening or closing price of the position a percentage between the mark and either the bid or the ask depending on whether you are looking to take a credit or a debit with the trade. Essentially, markup will move your pricing in an unfavorable direction, so a markup of 1 would be a very conservative assumption. A markup of 1.00 would mean that you are purchasing contracts at the ask and selling at the bid. A markup of 0.00 would mean that you are buying and selling contracts at the mark.

  • pricing_method (str) – UNDEVELOPED. This param will eventually allow for us to impliment more intricate slippage models, but currently has no functionality. Just leave the default value of ‘standard’.

  • max_date_cached (int) – Determines how many days will be cached for each symbol in the pricing_data dictionary. This param has some memory implications. If your machine is running out of memory running backtests, lowering this param could help. Otherwise, dont worry about it. One situation where this might be helpful to set higher is if you are running a small backtest and want to cache all of the spread data. In that situation you might want to set param to several hundred. This will allow follow on runs of your backtest to be super fast since your Market() object will already have all the data loaded.

static _find_nearest(array, value)

Searches an array for the nearest numeric value in the array to value inputed.

arraylist-like

A list like or array object that contains numeric values.

valuefloat

The value to search the array for the closest match to.

Returns

Returns the closest match found in the array to the value.

Return type

numeric

_get_symbol_trade_dates(symbol, start_date, end_date)

Finds the option trading dates for a given symbol and returns a slice of that list based on the start_date and end_date.

Note for Future Development: Currently this function just refeferences the assest/trade_dates.npy file; however, this will be an inadequite approach once data is stored in s3. One thought here is to create a small datastore that contains this list so that a query against the larger file system isnt required. Another approach might be to just store the data under a symbol/options/date.parquet structure such that you would just need to read in the parquet file name and not the larger file.

Parameters
  • symbol (str) – The symbol of the underlying to find all days in which the system can provide option quotes.

  • start_date (str) – Start date of the slice of the self.trading_dates[symbol] list. It typically the position as_of_date.

  • end_date (str) – End date of the slice of the self.trading_dates[symbol]

Returns

List of dates that options were traded for a symbol with in the start_date and end_date window (if specified).

Return type

list

_query_contract_on_day(contract_symbol, date)

~UNDERDEVELOPED FUNCTION~

Placeholder function kept here in-case it makes sense at some point to create a function that targets specific contracts rather than pulling the whole spread for a symbol on a given day. If speed becomes more important, some Athena s3 or Dynamo db configuration could be effective.

However, the current speeds to search for a single contract in the very underpreformant RDS market.options table is similar to pulling the whole spread making that the more logical thing to do, especially with many spreads containing several contracts that will be priced in sequence.

_query_spread_on_day(symbol, date)

DEPRECIATED. Calls on data stored in AWS RDS. Options quotes data is being migrated to s3 where load times are quicker.

Params symbol

The underlying symbol to get the spread for. Could also be a list of symbols to get multiple spreads on a date

Params date

The date in string format (YYYY-MM-DD) to get the spread on.

Returns

A nested dict of contract values where the date is the key at

the highest level and then the contract symbol is the key one level down.

_scale_contract_quantity(symbol: str, initiation_date, contract_symbol: str, quantity: int, scale_to_real=True) → dict

Prices a contract based on the quantity purchased or sold.

A negative quantity indicates that the contract was sold thus bid, ask, mark, ect. will be negative reflecting taking in a credit.

Parameters
  • symbol (str) – The underlying symbol of the contract. This param is probably superfulous since this information is contained in the contract symbol string.

  • initiation_date (str) – The date the contract should be priced on. Date should be a string and conform to the format ‘YYYY-MM-DD’.

  • contract_symbol (str) – The contract symbol to be priced. Ex.) MANU_20201120C14.0

  • quantity (int) – The number of contracts to be bought/sold. A negative sign indicates a sale while a positive indicates a purchase. Must be an int.

  • scale_to_real (bool) – It is convention to record contract values in terms of the per stock value, however contracts are traded in multiples of 100. Default behavior is to scales to the 100x real trade values. Bool: True or False.

Returns

A dict containing pricing information on the contract, quanitity and side of the position.

Return type

dict

_slippage_cost(bid, ask, mark, number_contracts)

Impliments assumptions about the market micro-structure.

Enforces assumptions about prices that you can open or close a position at. This impliments the logic that leverages the self.markup attribute configured at __init__(). When markup is set to 0.00, the method will return an open and close price at the mark. When the markup is set to 1.00 the open price will be set at the ask and the close at the bid.

This method also incorporates self.commission into the returned opening and closing prices. self.commission is also set at __init__()

Parameters
  • bid (float) – The bid price for the contract.

  • ask (float) – The ask price for the contract.

  • mark (float) – The mark price for the contract.

  • number_of_contracts (int) – A non-zero integer representing the quanity. Negative values represent short positions.

Returns

Returns a tuple of (open_price, close_price)

Return type

tuple

static _to_list(sym) → list

Allows a list of strings or a string to be passed as a parameter.

Parameters

sym (list or str) – A list or string to be converted or remain as a list.

Returns

Return type

A list equivalent to the list or string passed in a single value list.

_update_trade_dates_array()
add_underlyings(symbols)

Function that adds underlying option contract pricing data to the pricing object. Modifies the self.pricing_data object inplace.

Parameters

symbols – A list or string of underlying symbols. Symbols should be capitalized.

Return none

clean_pricing_data(date, offset=0)

Deletes Pricing data that occurs before a certain date. Proper use of this function keeps the memory footprint of the market object low.

Searches the spread of an underlying to find matching contracts on a given day.

The function is a useful way to search for a specific contract using general hyper-params like days to expiration and delta. The closest expiration date to the desiredDaysToExpiration will be found first and then the nearest delta within that spread will be found second. If there are multiple contracts that have the same delta within an expiration date, the strike will be selected based on the type of position. Short positions will seek to mitigate risk, selecting the highest (call) or lowest (put) strikes while long positions will select the lowest (call) or highest (put) to maximize profits. The key assumption with the strike selection is that similar deltas have similar prices but potentially different payouts.

Parameters
  • symbol – A key value associated with pricing information stored in self.pricing_data. If symbol is not in the PricingData object initiate it with self.add_underlyings.

  • initiation_date – The date on which the contract should be looked for. equivalent to the created_at date in the gtlcapital db. Format should be ‘YYYY-MM-DD’.

  • putCall – Determines if the contract search will return a put or call.

  • desiredDelta – The delta at which the contract should be closest too. Is a float between 0 and 1.

  • desiredDaysToExpiration – The days to expiration which the contract should be closest to.

  • quantity – The number of contracts to be contained in the desired return. Negative quantity values indicate that the contract will be sold short, thus delta, price,

Returns

get_contract_quote(contract_symbol, date)

Extracts the contract pricing dictionary from the spread_dict returned by the get_spread_on_day() function. Using the get_spread_on_day() function is useful since it ensure that data is retrieved if it is not currently cached. This speeds up subsequent contract pricing inquries, which is importat as multiple queries against a single spread is very common.

Params contract_symbol

The symbol of the contract in question. Contract symbols follow the convention of ‘<underlying_symbol>_<YYMMDD><P/C><strike>’.

Params date

The date on which to quote the contract pricing. Should be in the format ‘YYYY-MM-DD’.

Returns dict

Returns the contract quotes associated with the symbol and the date.

get_spread_on_day(symbol, date, verbose=False) → dict

**DEV NOTE

Currently this function only supports a single symbol being passed at a time, while the _query_spread_on_day() funciton now has compatibility with querying multiple symbol spreads. This still makes sense since this function is used to return information from the in memory datastore or add the info if it doesnt exist. What we should also have is a scheduler that allow for loading multiple underlyings on a single day. Similar to how the add_underlyings() function allows a user to add all RDS quotes for a stock that exist. add_underlyings() could in and of itself use a facelift that allows a user to preload all quotes in a df from an Athena query across the whole s3 bucket.

**DEV NOTE *

Function to get the spread values of an underlying symbol on a given date. It will first search the in memory data store at self.pricing_data to see if the result has been cached from a previous query or a full underlying load (see self.add_underlyings()). If no data is cached, the function will write a query to the gtlcapital database to retrieve the data.

Params symbol

The underlying symbol of a stock ex.) ‘AAPL’.

Params date

The date to get the spread of an underlying for. The date should be a string in the format ‘YYYY-MM-DD’.

load_multi_spreads_on_day(tickers: list, date)

Checks self.pricing_data to see if the tickers already have data, for those that dont,the function will bulk load the tickers into the pricing data dictionary for faster calculation in situations where you know you will need to pull the spread of many tickers on a given date. This is often the case when testing a strategy.

open_position(initiation_date, spread: backtest.position.Spread, strategy=None) → backtest.position.Position

Creates a Position() object populated with market values based on the Spread object passed in. Takes into market micro structure into account with slippage and commission factored into the cost to open and close a position.

Returns Position

Creates a Position() object with

price_spread(as_of_date, spread: backtest.position.Spread)

A utility function that takes pricing data from the market and evaluates the costs that would be associated with opening a position. Currently only supports mono-underlying spreads.

Parameters
  • as_of_date – Date to assess the spread on.

  • symbol – Underlying symbol or the symbol associated with the target dataset.

  • spread – An instance of the Spread object. A Spread can be initialized with functions in the Market class.

Returns dict

Returns a dictionary that contains aggregated trade values for multiple contracts.

Method creates a Spread object from a symbol on an as_of_date based on a dte, delta search.

Parameters
  • symbol – The symbol the spread data should come from.

  • as_of_date – The date to create the spread on.

  • args – A series of lists that specify the dte delta search hyper-parameters. Each list represents a single contract in the spread and should follow this format: [putCall, desiredDelta, desiredDaysToExpiration, quantity] where putCall is ‘put’ or ‘call, desiredDelta is between 0 and 1, desiredDaysToExpiration is > 0 and quantity is an int wholes sign directs if the position is long or short and cannot be zero.

Returns Spread

Returns a Spread() object that can be used to create a Position() object. Spreads can be thought of as a trade idea whereas the Position object takes the additional steps to cross the bid ask spread and establish a position based on the spread.

step_position(position: backtest.position.Position, dte=None)

Modifies position in place to contain the next days values. Will step the position object passed one day into the future as s default behavior. However, if dte is passed an int less than the postion.dte, the function will recursivly call itself to step the position to the desired days to expiration (dte).

Parameters
  • postion – A position object created by the Market().open_position method.

  • dte – The days to expiration to step the position to. Since a position will not trade every day, the function will step the position to the nearest dte past the integer provided.

Returns None

None, modifies Position object inplace.

portolio.py

Contains the Portfolio object.

class backtest.portfolio.Portfolio(optimization='equalWeight')

A wrapper around a list of positions and methods to extract info from the position list.

__init__(optimization='equalWeight')

Initialization of a Portfolio object.

Holds a list of positions under the self.positions attribute. Also has methods to extract data from the list of positions.

Parameters

optimization (str) – Default is ‘equalWeight’. Eventually this will indicated the type of portfolio optimization that will be used to balance the positions out.

positions

Is a list of positions held over the life time of the portfolio. Includes both closed and open positions.

Type

list

optimization

Stores the optimization param passed upon initiation.

Type

str

add_position(position: backtest.position.Position)

Appends the passed position to the self.positions attribute.

Parameters

position (Position) – The position to append to the portfolio instance.

step_open_positions()

UNDEVELOPED. Steps all open positions one day forward.

to_pandas(agg=True)

Creates a dataframe from the positions list.

Parameters

agg (bool) – Flag that determines the type of data frame returned. If agg == True, the function will return a dataframe aggregated by date so that all the posiitons held on a given day are abstrated to portfolio level metrics.

Returns

Dataframe will be aggregated to the trading date by default. Setting agg to False returns the disaggregated dataset of all the positions for each day they are active.

Return type

pandas.Dataframe

utils.py

Contains helper functions for the backtest package.

backtest.utils.contract_info_from_symbol(contract_symbol: str)
backtest.utils.date_add(date: str, days: int, format: str = '%Y-%m-%d') → str

Accepts a date string in the form YYYY-MM-DD and adds a number of days to it returning the new date string. This is useful for date string related keys.

Returns tuple

Returns a tuple in the format (underlying_symbol, PUT/CALL, expiration_date, strike_price)

backtest.utils.parity(x, putCall, strike, quantity)