Back-test result¶
This module defines BacktestResult
.
This is the object that is returned by the
cvxportfolio.MarketSimulator.backtest()
method, and also by the same method in derived classes of
cvxportfolio.MarketSimulator
.
It contains all relevant information from a back-test and implements the logic
to compute various performance metrics, in addition to the
BacktestResult.plot()
method for producing plots
and __repr__
magic method, which is invoked when the user
prints an instance.
Added in version 1.1.0: The BacktestResult.log
property, which returns the logs produced
during the back-test, at level INFO
or higher. It works also for
back-tests run in parallel!
- class cvxportfolio.result.BacktestResult(universe, trading_calendar, costs)View on GitHub¶
Store the data from a back-test and produce metrics and plots.
Additionally, record all logs produced by the simulator, market data server, and policy object during the back-test. These are stored in the
logs
attribute as a newline separated string. This is done in a multi-process safe manner, so that if you run parallel back-tests withcvxportfolio.MarketSimulator.backtest_many()
, only the logs from the right process are recorded.- Parameters:
universe (pandas.Index) – Best initial guess of the trading universe.
trading_calendar (pd.DateTimeIndex) – Trading calendar. Can be a best guess, but the first timestamp must be the actual.
costs (list) – Simulator cost objects whose value is logged. Note: we use only the classes’ names here.
Note
The initializer of this class is still experimental, we might still change its signature without the guarantee of semantic versioning.
- plot(show=True, how_many_weights=7)View on GitHub¶
Make plot and show it.
- Parameters:
show (bool) – if True, call
matplotlib.Figure.show
, helpful when running in the interpreter.how_many_weights (int) – How many assets’ weights are shown in the weights plots. The ones with largest average absolute value are chosen.
- Returns:
Resulting matplotlib figure.
- Return type:
matplotlib.figure.Figure
- times_plot(show=True)View on GitHub¶
Plot all execution times of the back-test.
- Parameters:
show (bool) – if True, call
matplotlib.Figure.show
, helpful when running in the interpreter.- Returns:
Resulting matplotlib figure.
- Return type:
matplotlib.figure.Figure
- property logsView on GitHub¶
Logs from the policy, simulator, market data server, ….
- Returns:
Logs produced during the back-test, newline separated.
- Return type:
str
- property cash_keyView on GitHub¶
The name of the cash unit used (e.g., USDOLLAR).
- Returns:
Name of the cash accounting unit.
- Return type:
str
- property periods_per_yearView on GitHub¶
Average trading periods per year in this backtest (rounded).
- Returns:
Average periods per year.
- Return type:
int
- property vView on GitHub¶
The total value (or NAV) of the portfolio at each period.
- Returns:
Total value at each period.
- Return type:
pandas.Series
- property profitView on GitHub¶
The total profit (PnL) in this backtest.
- Returns:
Total profit.
- Return type:
float
- property wView on GitHub¶
The weights of the portfolio at each period.
- Returns:
Portfolio weights at each period.
- Return type:
pandas.DataFrame
- property h_plusView on GitHub¶
The post-trade portfolio (holdings) at each period.
- Returns:
Post-trade holdings at each period.
- Return type:
pandas.DataFrame
- property w_plusView on GitHub¶
The post-trade weights of the portfolio at each period.
- Returns:
Post-trade weights at each period.
- Return type:
pandas.DataFrame
- property leverageView on GitHub¶
Leverage of the portfolio at each period.
This is defined as:
\[\| {(h_t)}_{1:n} \|_1 / v_t,\]where \(h_t\) is the portfolio (the holdings) at time \(t\), we exclude the cash account from the \(\ell_1\) norm, and \(v_t\) is the total value (NAV) of the portfolio at time \(t\).
- Returns:
Leverage at each period.
- Return type:
pandas.Series
- property turnoverView on GitHub¶
The turnover of the portfolio at each period.
This is defined as:
\[\| {(u_t)}_{1:n} \|_1 / (2 v_t),\]where \(u_t\) are the portfolio trades at time \(t\), we exclude the cash account from the \(\ell_1\) norm, and \(v_t\) is the total value (NAV) of the portfolio at time \(t\).
- Returns:
Turnover at each period.
- Return type:
pandas.Series
- property returnsView on GitHub¶
The portfolio returns at each period.
This is defined as:
\[R_t^\text{p} = \frac{v_{t+1} - v_t}{v_t}\]in terms of the portfolio value (NAV).
- Returns:
Portfolio returns at each period.
- Return type:
pandas.Series
- property average_returnView on GitHub¶
The average realized return \(\overline{R^\text{p}}\).
- Returns:
Average portfolio return.
- Return type:
float
- property annualized_average_returnView on GitHub¶
The average realized return, annualized.
- Returns:
Average portfolio return, annualized.
- Return type:
float
- property growth_ratesView on GitHub¶
The growth rate (or log-return) of the portfolio at each period.
This is defined as:
\[G^\text{p}_t = \log (v_{t+1} / v_t) = \log(1 + R^\text{p}_t).\]- Returns:
Growth rate of the portfolio value at each period.
- Return type:
pandas.Series
- property average_growth_rateView on GitHub¶
The average portfolio growth rate \(\overline{G^\text{p}}\).
- Returns:
Average growth rate.
- Return type:
float
- property annualized_average_growth_rateView on GitHub¶
The average portfolio growth rate, annualized.
- Returns:
Average growth rate, annualized.
- Return type:
float
- property volatilityView on GitHub¶
Realized volatility (standard deviation of the portfolio returns).
- Returns:
Volatility.
- Return type:
float
- property annualized_volatilityView on GitHub¶
Realized volatility, annualized.
- Returns:
Volatility, annualized.
- Return type:
float
- property quadratic_riskView on GitHub¶
Quadratic risk, square of the realized volatility.
- Returns:
Quadratic risk.
- Return type:
float
- property annualized_quadratic_riskView on GitHub¶
Quadratic risk, annualized.
- Returns:
Quadratic risk, annualized.
- Return type:
float
- property excess_returnsView on GitHub¶
Excess portfolio returns with respect to the cash returns.
- Returns:
Excess returns at each period.
- Return type:
pandas.Series
- property excess_volatilityView on GitHub¶
Excess volatility (standard deviation of the excess returns).
- Returns:
Average excess volatility.
- Return type:
float
- property average_excess_returnView on GitHub¶
The average excess return \(\overline{R^\text{e}}\).
- Returns:
Average excess portfolio return.
- Return type:
float
- property annualized_average_excess_returnView on GitHub¶
The average excess return, annualized.
- Returns:
Average excess portfolio return, annualized.
- Return type:
float
- property annualized_excess_volatilityView on GitHub¶
Annualized excess volatility.
- Returns:
Average excess volatility, annualized.
- Return type:
float
- property active_returnsView on GitHub¶
Portfolio returns minus benchmark returns (if defined by policy).
- Returns:
Active returns at each period if benchmark is defined, else
nan
.- Return type:
pandas.Series
- property active_volatilityView on GitHub¶
Active volatility (standard deviation of the active returns).
- Returns:
Average active volatility if benchmark is defined, else
nan
.- Return type:
float
- property average_active_returnView on GitHub¶
The average active return \(\overline{R^\text{a}}\).
- Returns:
Average active portfolio return if benchmark is defined, else
nan
.- Return type:
float
- property annualized_average_active_returnView on GitHub¶
The average active return, annualized.
- Returns:
Average active portfolio return, annualized. If benchmark is not defined,
nan
.- Return type:
float
- property annualized_active_volatilityView on GitHub¶
Annualized active volatility.
- Returns:
Average active volatility, annualized. If benchmark is not defined,
nan
.- Return type:
float
- property sharpe_ratioView on GitHub¶
Sharpe ratio (using annualized excess portfolio returns).
This is defined as
\[\text{SR} = \overline{R^\text{e}}/\sigma^\text{e}\]where \(\overline{R^\text{e}}\) is the average excess portfolio return and \(\sigma^\text{e}\) its standard deviation. Both are annualized.
- Returns:
Sharpe Ratio.
- Return type:
float
- property information_ratioView on GitHub¶
Information ratio (using annualized active portfolio returns).
This is defined as
\[\text{IR} = \overline{R^\text{a}}/\sigma^\text{a}\]where \(\overline{R^\text{a}}\) is the average active portfolio return and \(\sigma^\text{a}\) its standard deviation. Both are annualized.
- Returns:
Information Ratio,
nan
if benchmark is not defined.- Return type:
float
- property excess_growth_ratesView on GitHub¶
The growth rate of the portfolio, relative to cash.
This is defined as:
\[G^\text{e}_t = \log(1 + R^\text{e}_t)\]where \(R^\text{e}_t\) are the excess portfolio returns.
- Returns:
Excess growth rates at each period.
- Return type:
pandas.Series
- property average_excess_growth_rateView on GitHub¶
The average excess growth rate \(\overline{G^\text{e}}\).
- Returns:
Average excess portfolio growth rates.
- Return type:
float
- property annualized_average_excess_growth_rateView on GitHub¶
The average excess growth rate, annualized.
- Returns:
Average excess portfolio growth rates, annualized.
- Return type:
float
- property active_growth_ratesView on GitHub¶
The growth rate of the portfolio, relative to benchmark.
This is defined as:
\[G^\text{a}_t = \log(1 + R^\text{a}_t)\]where \(R^\text{a}_t\) are the active portfolio returns.
- Returns:
Active growth rates at each period. If benchmark is not defined,
nan
.- Return type:
pandas.Series
- property average_active_growth_rateView on GitHub¶
The average active growth rate \(\overline{G^\text{a}}\).
- Returns:
Average active portfolio growth rates. If benchmark is not defined,
nan
.- Return type:
float
- property annualized_average_active_growth_rateView on GitHub¶
The average active growth rate, annualized.
- Returns:
Average active portfolio growth rates, annualized. If benchmark is not defined,
nan
.- Return type:
float
- property drawdownView on GitHub¶
The drawdown of the portfolio value over time.
- Returns:
Drawdown of portfolio value at each period.
- Return type:
pandas.Series
- property policy_timesView on GitHub¶
The computation time of the policy object at each period.
- Returns:
Policy time in seconds at each period.
- Return type:
pandas.Series
- property simulator_timesView on GitHub¶
The computation time of the simulator object at each period.
- Returns:
Simulator time in seconds at each period.
- Return type:
pandas.Series
- property market_data_timesView on GitHub¶
The computation time of the market data server at each period.
This is already included in
simulator_times
!- Returns:
Market data server time in seconds at each period.
- Return type:
pandas.Series
- property result_timesView on GitHub¶
The computation time of the back-test result (this) at each period.
This is already included in
simulator_times
!- Returns:
Back-test result time in seconds at each period.
- Return type:
pandas.Series
Interface methods with the market simulator¶
- class cvxportfolio.result.BacktestResult(universe, trading_calendar, costs)View on GitHub
Store the data from a back-test and produce metrics and plots.
Additionally, record all logs produced by the simulator, market data server, and policy object during the back-test. These are stored in the
logs
attribute as a newline separated string. This is done in a multi-process safe manner, so that if you run parallel back-tests withcvxportfolio.MarketSimulator.backtest_many()
, only the logs from the right process are recorded.- Parameters:
universe (pandas.Index) – Best initial guess of the trading universe.
trading_calendar (pd.DateTimeIndex) – Trading calendar. Can be a best guess, but the first timestamp must be the actual.
costs (list) – Simulator cost objects whose value is logged. Note: we use only the classes’ names here.
Note
The initializer of this class is still experimental, we might still change its signature without the guarantee of semantic versioning.
- log_trading(t: pd.Timestamp, h: pd.Series[float], u: pd.Series[float], z: pd.Series[float], costs: Dict[str, float], cash_return: float, benchmark_return: float or None, policy_time: float, simulator_time: float, market_data_time: float)View on GitHub¶
Log one trading period.
- Parameters:
t (pd.Timestamp) – Timestamp of execution.
h (pd.Series) – Initial holdings.
u (pd.Series) – Trade vectors in (e.g.) dollars.
z (pd.Series) – Trade weight vectors requested by the policy. Can be different from the actual trades because of rounding or any other filtering applied by the simulator. They are recorded but not used in accounting.
costs (dict) – Dictionary indexed by the cost class names with the current values of each. They are recorded but not used for accounting, that is done directly in the simulator and already included in the computed holdings.
cash_return (float) – Current return of the cash account (interest rate), used for excess metrics (e.g., Sharpe ratio).
benchmark_return (float or None) – Current return of the benchmark, if defined, otherwise None.
policy_time (float) – Time spent inside the policy object in this period.
simulator_time (float) – Time spent to back-test this period outside of the policy object.
market_data_time (float) – Time spent inside
cvxportfolio.data.MarketData()
for this period (also already included insimulator_time
).
Note
This method is still experimental, we might change its signature without the guarantee of semantic versioning.
- log_final(t, t_next, h, extra_simulator_time)View on GitHub¶
Log final elements and (if necessary) clean up.
Also clean up if the back-test finishes before it was expected to (e.g., bankruptcy).
- Parameters:
t (pd.Timestamp) – Last execution time.
t_next (pd.Timestamp) – Next execution time, at which we don’t run the policy but we do record the holdings.
h (pd.Series) – Last value of the holdings, at time
t_next
.extra_simulator_time (float) – Any extra time, in seconds, spent in the simulator to propagate the holdings from t to t_next (other times are already accounted for).
Note
This method is still experimental, we might change its signature without the guarantee of semantic versioning.