Welcome to backtest’s documentation!¶
Getting Started¶
Install the package to your machine and all its dependancies.
Take a look at the Common Usage Pattern section to see how the package can be used to solve common questions or problems.
Read through the
backtest
documentation as it explains The methodology used to run the backtest in greater detail.
Installation¶
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.
Clone the backtest repo to your machine running the following command:
git clone https://github.com/GTL-Capital/backtest.git
Enter your Github username and password if prompted.
Install the python package by running the following commands:
cd backtest pip install .
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
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.
-
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 theMarket
methodsstep_position()
andopen_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 methodprice_spread()
which returns the spread_values dict. Once again, thestep_position()
andopen_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 thevalue
.- 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__()
. Whenmarkup
is set to 0.00, the method will return an open and close price at the mark. When themarkup
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.
-
dte_delta_search
(symbol: str, initiation_date: str, putCall: str, desiredDelta: float, desiredDaysToExpiration: int, quantity: int)¶ 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.
-
spread_from_dte_delta_search
(symbol, as_of_date, *args)¶ 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)¶