Backtest
Backtesting utils
Strategy
- class ml_investment.backtest.strategy.Strategy[source]
Bases:
object
Base class for strategy backtesting. It contains overrideble method
step
for defining user strategy. This class incapsulate backtesting and metrics calculation process and also contains information about orders.- backtest(data_loader, date_col: str, price_col: str, return_col: str, return_format: str, step_dates: Optional[List[numpy.timedelta64]] = None, cash: float = 100000, comission: float = 0.00025, latency: numpy.timedelta64 = numpy.timedelta64(0, 'h'), allow_short: bool = False, metrics=None, preload: bool = False, verbose: bool = True)[source]
Backtest strategy on provided data and other parameters. It will create and execute orders and calculate resulted equity and metrics.
- Parameters
data_loader – class implementing
load(index) -> pd.DataFrame
interface. index in this case is list of tickers to load market data for.date_col – name of column containing date (time) information in market data provided by
data_loader
.price_col – name of column containing price information in market data provided by
data_loader
.return_col – name of column containing total return information in data provided by
data_loader
. It may be differ from price due to dividends, stock splits and etc.return_format – format of data provided by
return_col
column. Ifreturn_format = 'ratio'
than column should contain ratio between previous and current adjusted price. E.g. 1.2 means growth by 20% from the previous step. Ifreturn_format = 'price'
than column should contain adjusted price (price, including dividends and etc.) Ifreturn_format = 'change'
than column should contain relative change between current and previous step. E.g. 0.2 means growth by 20% from the previous step.step_dates – dates in which all actions can be taken. Include new market prices receiving, order creation and executing.
step
method will iterate over all those dates. If None than all possible dates, provided bydate_col
column indata_loader
will be used. Possible only ifpreload = True
anddata_loader
haveexisting_index(index) -> List
interface.cash – initial amount of cash
comission – commission charged for each trade (in percent of order value)
latency – time between current step date and actual order posting. It emulates delays during
step
logic and in the Internet connection with the exchange.allow_short – allow short positions or not
preload – load all data provided from
data_loader
to ram or notverbose – show progress or not
- post_order(ticker: str, direction: int, size: float, order_type: int = 0, lifetime: numpy.timedelta64 = numpy.timedelta64(300, 'D'), allow_partial: bool = True)[source]
Post new order to backtest. It may be used inside your strategy overriden
step
method.- Parameters
ticker – ticker of company to post order for
direction – one of
Order.BUY
(1),Order.SELL
(-1)size – size of order in pieces
order_type – one of
Order.MARKET
(0),Order.LIMIT
(1)lifetime – amount of time before order closing if it can not be executed (e.g. if unsatisfactory price lasts a long time)
allow_partial – may order be executed with not full size or not
- post_order_value(ticker: str, direction: int, value: float, order_type: int = 0, lifetime: numpy.timedelta64 = numpy.timedelta64(300, 'D'), allow_partial: bool = True)[source]
Post new order by value (instead of size) to backtest. It may be used inside your strategy overriden
step
method.- Parameters
ticker – ticker of company to post order for
direction – one of
Order.BUY
(1),Order.SELL
(-1)value – value of order in money
order_type – one of
Order.MARKET
(0),Order.LIMIT
(1)lifetime – amount of time before order closing if it can not be executed (e.g. if unsatisfactory price lasts a long time)
allow_partial – may order be executed with not full size or not
- post_portfolio_part(ticker: str, part: float, lifetime: numpy.timedelta64 = numpy.timedelta64(300, 'D'), allow_partial: bool = True)[source]
Post order to backtest to have desired part in portfolio. It will calculate difference between current and desired part to create appropriate order. It may be used inside your strategy overriden
step
method.- Parameters
ticker – ticker of company to post order for
part – desired part in all equity including other stocks and cash in portfolio (value between 0 and 1)
lifetime – amount of time before order closing if it can not be executed (e.g. if unsatisfactory price lasts a long time)
allow_partial – may order be executed with not full size or not
- post_portfolio_size(ticker: str, size: int, lifetime: numpy.timedelta64 = numpy.timedelta64(300, 'D'), allow_partial: bool = True)[source]
Post order to backtest to have desired size in portfolio. It will calculate difference between current and desired size to create appropriate order. It may be used inside your strategy overriden
step
method.- Parameters
ticker – ticker of company to post order for
size – desired size in portfolio (in pieces)
lifetime – amount of time before order closing if it can not be executed (e.g. if unsatisfactory price lasts a long time)
allow_partial – may order be executed with not full size or not
- post_portfolio_value(ticker: str, value: float, lifetime: numpy.timedelta64 = numpy.timedelta64(300, 'D'), allow_partial: bool = True)[source]
Post order to backtest to have desired value in portfolio. It will calculate difference between current and desired value to create appropriate order. It may be used inside your strategy overriden
step
method.- Parameters
ticker – ticker of company to post order for
value – desired value in portfolio (in money)
lifetime – amount of time before order closing if it can not be executed (e.g. if unsatisfactory price lasts a long time)
allow_partial – may order be executed with not full size or not