Simulator#
This module implements cvxportfolio.MarketSimulator
and derived
classes.
These objects model the trading activity on a financial market. They simulate as accurately as possible what would have been the realized performance of a trading policy if it had been run in the market in the past. In financial jargon this is called back-testing.
- class cvxportfolio.MarketSimulator(universe=(), returns=None, volumes=None, prices=None, market_data=None, costs=(), round_trades=False, datasource='YahooFinance', cash_key='USDOLLAR', base_location=PosixPath('/home/docs/cvxportfolio_data'), min_history=Timedelta('365 days 05:45:36'), trading_frequency=None)#
This class is a generic financial market simulator.
It can either be initialized with an instance of a class derived from
cvxportfolio.data.MarketData
, like the two defaultscvxportfolio.DownloadedMarketData
andcvxportfolio.UserProvidedMarketData
, or with a selection of the arguments to the latter two.- Parameters:
universe (list) – List of names as understood by the data source used, e.g.,
['AAPL', 'GOOG']
if using the default Yahoo Finance data source. If provided, acvxportfolio.DownloadedMarketData
will be initialized.returns (pandas.DataFrame) – Historical open-to-open returns. The return at time \(t\) is \(r_t = p_{t+1}/p_t -1\) where \(p_t\) is the (open) price at time \(t\). Must have datetime index. If provided, a
cvxportfolio.UserProvidedMarketData
will be initialized. If universe is specified it is ignored. You can also include cash returns as its last column, and setcash_key
below to the last column’s name.volumes (pandas.DataFrame or None) – Historical market volumes, expressed in units of value (e.g., US dollars). If universe is specified it is ignored.
prices (pandas.DataFrame or None) – Historical open prices (e.g., used for rounding trades in the
cvxportfolio.MarketSimulator
). If universe is specified it is ignored.datasource (str or
cvxportfolio.data.SymbolData
class (not instance)) – The data source used, if providing a universe (forcvxportfolio.DownloadedMarketData
).cash_key (str) – Name of the cash account. Its returns are the risk-free rate. If it is the name of the last column of the provided returns, that will be used. Otherwise, the last column of the returns’ will be added by downloading the risk-free returns. In that case you should make sure your provided dataframes have a time-zone aware datetime index.
trading_frequency (str or None) – Instead of using frequency implied by the index of the returns, down-sample all dataframes. We implement
'weekly'
,'monthly'
,'quarterly'
and'annual'
. By default (None) don’t down-sample.min_history (pandas.Timedelta) – Minimum amount of time for which an asset must have returns that are not
nan
before it is included in a back-test. Default one year.market_data (
cvxportfolio.data.MarketData
instance or None) – An instance of acvxportfolio.data.MarketData
derived class. If provided, all previous arguments are ignored.base_location (pathlib.Path) – The location of the storage. By default it’s a directory named
cvxportfolio_data
in your home folder.costs (list of
cvxportfolio.costs.SimulatorCost
classes or instances) – List of costs that are applied at each time in a back-test.round_trades (bool) – If market prices are available, round trades to integer number of shares.
- backtest(policy, start_time=None, end_time=None, initial_value=1000000.0, h=None)#
Back-test a trading policy.
The default initial portfolio is all cash, or you can pass any portfolio with the
h
argument.- Parameters:
policy (
cvxportfolio.policies.Policy
) – Trading policy, see the Trading policies documentation page.start_time (str or pandas.Timestamp) – Start time of the back-test; if market is closed, the first trading day after it is selected.
end_time (str or pandas.Timestamp or None) – End time of the back-test, if market is closed the last trading day before it is selected.
initial_value (float) – Initial value in dollar of the portfolio, if not specifying
h
it is assumed the initial portfolio is all cash; ifh
is specified this is ignored. Default value one million.h (pandas.Series or None) – Initial portfolio
h
expressed in cash units. IfNone
an initial portfolio ofinitial_value
in cash is used.
- Returns:
Back-test result with all relevant data and metrics, logic to generate plots, ….
- Return type:
- run_backtest()#
Alias of
backtest()
, as it was defined originally in section 6.1 of the paper.
- backtest_many(policies, start_time=None, end_time=None, initial_value=1000000.0, h=None, parallel=True)#
Back-test many trading policies.
The default initial portfolio is all cash, or you can pass any portfolio with the
h
argument, or a list of those.- Parameters:
policies (list) – List of
cvxportfolio.policies.Policy
trading policies, see the Trading policies documentation page.start_time (str or pandas.Timestamp) – Start time of the backtests. If market is closed the first trading day after it is selected. Currently it is not possible to specify different start times for different policies, so the same is used for all.
end_time (str or pandas.Timestamp or None) – End time of the backtests. If market is closed the last trading day before it is selected. Currently it is not possible to specify different end times for different policies, so the same is used for all.
initial_value (float) – Initial value in dollar of the portfolio, if not specifying
h
it is assumed the initial portfolio is all cash; ifh
is specified this is ignored. Default value one million.h (list of pandas.Series or None) – Initial portfolio h expressed in dollar positions, or list of those. If passing a list it must have the same lenght as the policies. If this argument is specified,
initial_value
is ignored, otherwise the same portfolio ofinitial_value
all in cash is used as starting point for all backtests.parallel (bool) – Whether to run in parallel. If running in parallel you should must be careful at how you use this method. It is good practice to define the market simulator and execute this inside a
if __name__ == '__main__:'
clause, if in a script.
- Raises:
SyntaxError – If the lenghts of objects passed don’t match, ….
- Returns:
List of
cvxportfolio.BacktestResult
which have all relevant backtest data and logic to compute metrics, generate plots, ….- Return type:
list
- run_multiple_backtest()#
Alias of
backtest_many()
, as it was defined originally in section 6.1 of the paper.
- optimize_hyperparameters(policy, start_time=None, end_time=None, initial_value=1000000.0, h=None, objective='sharpe_ratio', parallel=True)#
Optimize hyperparameters to maximize back-test objective.
- Parameters:
policy (cvx.BaseTradingPolicy) – Trading policy with symbolic hyperparameters.
start_time (str or pandas.Timestamp) – Start time of the back-test on which we optimize; if market is closed, the first trading day after it is selected.
end_time (str or datetime or None) – End time of the back-test on which we optimize; if market is closed, the last trading day before it is selected.
initial_value (float) – Initial value in cash units of the portfolio, if not specifying
h
it is assumed the initial portfolio is all cash; ifh
is specified this is ignored. Default one million.h (pandas.Series or None) – Initial portfolio
h
expressed in cash units. IfNone
an initial portfolio ofinitial_value
in cash is used.objective (str) – Attribute of
cvxportfolio.BacktestResult
that is maximized. Default'sharpe_ratio'
.parallel (bool) – Whether to run in parallel. If running in parallel you should must be careful at how you use this method. It is good practice to define the market simulator and execute this inside a
if __name__ == '__main__:'
clause, if in a script.
- Returns:
The policy whose hyper-parameters now have optimal values. (The same object that was passed by the user.)
- Return type:
cvxportfolio.Policy
- class cvxportfolio.StockMarketSimulator(universe=(), costs=(<class 'cvxportfolio.costs.StocksTransactionCost'>, <class 'cvxportfolio.costs.StocksHoldingCost'>), round_trades=True, cash_key='USDOLLAR', base_location=PosixPath('/home/docs/cvxportfolio_data'), trading_frequency=None, **kwargs)#
This class implements a simulator of the stock market. It simplifies the interface of
MarketSimulator
and has (realistic) default costs.- Parameters:
universe (list) – List of Yahoo Finance stock names.
cash_key (str) – Name of the cash account. Its returns are the risk-free rate. Default
'USDOLLAR'
(currently the only one supported).trading_frequency (str or None) – Instead of using frequency implied by the index of the returns, down-sample all dataframes. We implement
'weekly'
,'monthly'
,'quarterly'
and'annual'
. By default (None) don’t down-sample.base_location (pathlib.Path) – The location of the storage. By default it’s a directory named
cvxportfolio_data
in your home folder.costs (list of
cvxportfolio.costs.SimulatorCost
classes or instances) – List of costs that are applied at each time in a back-test. By default we addcvxportfolio.StocksTransactionCost
andcvxportfolio.StocksHoldingCost
.round_trades (bool) – Round trades to integer number of shares. By default, True.
kwargs (dict) – You can add any other argument to pass to
MarketSimulator
’s initializer.
- backtest(policy, start_time=None, end_time=None, initial_value=1000000.0, h=None)#
Back-test a trading policy.
The default initial portfolio is all cash, or you can pass any portfolio with the
h
argument.- Parameters:
policy (
cvxportfolio.policies.Policy
) – Trading policy, see the Trading policies documentation page.start_time (str or pandas.Timestamp) – Start time of the back-test; if market is closed, the first trading day after it is selected.
end_time (str or pandas.Timestamp or None) – End time of the back-test, if market is closed the last trading day before it is selected.
initial_value (float) – Initial value in dollar of the portfolio, if not specifying
h
it is assumed the initial portfolio is all cash; ifh
is specified this is ignored. Default value one million.h (pandas.Series or None) – Initial portfolio
h
expressed in cash units. IfNone
an initial portfolio ofinitial_value
in cash is used.
- Returns:
Back-test result with all relevant data and metrics, logic to generate plots, ….
- Return type:
- run_backtest()#
Alias of
backtest()
, as it was defined originally in section 6.1 of the paper.
- backtest_many(policies, start_time=None, end_time=None, initial_value=1000000.0, h=None, parallel=True)#
Back-test many trading policies.
The default initial portfolio is all cash, or you can pass any portfolio with the
h
argument, or a list of those.- Parameters:
policies (list) – List of
cvxportfolio.policies.Policy
trading policies, see the Trading policies documentation page.start_time (str or pandas.Timestamp) – Start time of the backtests. If market is closed the first trading day after it is selected. Currently it is not possible to specify different start times for different policies, so the same is used for all.
end_time (str or pandas.Timestamp or None) – End time of the backtests. If market is closed the last trading day before it is selected. Currently it is not possible to specify different end times for different policies, so the same is used for all.
initial_value (float) – Initial value in dollar of the portfolio, if not specifying
h
it is assumed the initial portfolio is all cash; ifh
is specified this is ignored. Default value one million.h (list of pandas.Series or None) – Initial portfolio h expressed in dollar positions, or list of those. If passing a list it must have the same lenght as the policies. If this argument is specified,
initial_value
is ignored, otherwise the same portfolio ofinitial_value
all in cash is used as starting point for all backtests.parallel (bool) – Whether to run in parallel. If running in parallel you should must be careful at how you use this method. It is good practice to define the market simulator and execute this inside a
if __name__ == '__main__:'
clause, if in a script.
- Raises:
SyntaxError – If the lenghts of objects passed don’t match, ….
- Returns:
List of
cvxportfolio.BacktestResult
which have all relevant backtest data and logic to compute metrics, generate plots, ….- Return type:
list
- run_multiple_backtest()#
Alias of
backtest_many()
, as it was defined originally in section 6.1 of the paper.
- optimize_hyperparameters(policy, start_time=None, end_time=None, initial_value=1000000.0, h=None, objective='sharpe_ratio', parallel=True)#
Optimize hyperparameters to maximize back-test objective.
- Parameters:
policy (cvx.BaseTradingPolicy) – Trading policy with symbolic hyperparameters.
start_time (str or pandas.Timestamp) – Start time of the back-test on which we optimize; if market is closed, the first trading day after it is selected.
end_time (str or datetime or None) – End time of the back-test on which we optimize; if market is closed, the last trading day before it is selected.
initial_value (float) – Initial value in cash units of the portfolio, if not specifying
h
it is assumed the initial portfolio is all cash; ifh
is specified this is ignored. Default one million.h (pandas.Series or None) – Initial portfolio
h
expressed in cash units. IfNone
an initial portfolio ofinitial_value
in cash is used.objective (str) – Attribute of
cvxportfolio.BacktestResult
that is maximized. Default'sharpe_ratio'
.parallel (bool) – Whether to run in parallel. If running in parallel you should must be careful at how you use this method. It is good practice to define the market simulator and execute this inside a
if __name__ == '__main__:'
clause, if in a script.
- Returns:
The policy whose hyper-parameters now have optimal values. (The same object that was passed by the user.)
- Return type:
cvxportfolio.Policy