DOW30 Example#
This example script is available in the repository. See the docstring below for its explanation.
"""Example of long-only portfolio among DOW-30 components.
Monthly rebalance, backtest spans from the start of data of the
components of the current index (in the 60s) and the other stocks
enter the backtest as times goes on. It ends today.
This uses an explicit loop to create Multi Period Optimization
policies with a grid of values for the risk term multiplier
and the transaction cost term multiplier. (We don't use the
holding cost term because the portfolio is long-only.)
All result objects are collected, and then the one with
largest Sharpe ratio, and the one with largest growth rate,
are shown.
Finally, we show the effect of using symbolic hyper-parameters,
:class:`cvxportfolio.Gamma`, as multipliers of the risk and transaction
cost terms. We can optimize on those explicitely, by finding the values
that maximize some back-test metric (in this case, profit).
"""
# Uncomment the logging lines to get online information
# from the parallel backtest routines
# import logging
# logging.basicConfig(level=logging.INFO)
# log=logging.getLogger('=>')
import os
import cvxportfolio as cvx
import matplotlib.pyplot as plt
import numpy as np
UNIVERSE = ['MMM', 'AXP', 'AMGN', 'AAPL', 'BA', 'CAT', 'CVX', 'CSCO', 'KO', 'DIS', 'DOW',
'GS', 'HD', 'HON', 'IBM','INTC', 'JNJ',
'JPM','MCD', 'MRK', 'MSFT', 'NKE', 'PG', 'CRM', 'TRV', 'VZ', 'V', 'WBA', 'WMT']
sim = cvx.StockMarketSimulator(UNIVERSE, trading_frequency='monthly')
def make_policy(gamma_trade, gamma_risk):
return cvx.MultiPeriodOptimization(cvx.ReturnsForecast()
- gamma_risk * cvx.FactorModelCovariance(num_factors=10)
- gamma_trade * cvx.StocksTransactionCost(),
[cvx.LongOnly(), cvx.LeverageLimit(1)],
planning_horizon=6, solver='ECOS')
keys = [(gamma_trade, gamma_risk) for gamma_trade in np.array(range(10))/10 for gamma_risk in [.5, 1, 2, 5, 10]]
ress = sim.backtest_many([make_policy(*key) for key in keys])
print('\n\nLARGEST SHARPE RATIO')
idx = np.argmax([el.sharpe_ratio for el in ress])
print('gamma_trade and gamma_risk')
print(keys[idx])
print('result')
print(ress[idx])
ress[idx].plot()
# we use this to save plots for the documentation
if 'CVXPORTFOLIO_SAVE_PLOTS' in os.environ:
plt.savefig('dow30_largest_sharpe_ratio.png')
print('\n\nLARGEST GROWTH RATE')
idx = np.argmax([el.growth_rates.mean() for el in ress])
print('gamma_trade and gamma_risk')
print(keys[idx])
print('result')
print(ress[idx])
ress[idx].plot()
if 'CVXPORTFOLIO_SAVE_PLOTS' in os.environ:
plt.savefig('dow30_largest_growth_rate.png')
print('\n\nUNIFORM (1/N) ALLOCATION FOR COMPARISON')
result_uniform = sim.backtest(cvx.Uniform())
print('result_uniform')
print(result_uniform)
result_uniform.plot()
if 'CVXPORTFOLIO_SAVE_PLOTS' in os.environ:
plt.savefig('dow30_uniform.png')
print('\n\nHYPER-PARAMETER OPTIMIZATION')
policy = cvx.MultiPeriodOptimization(cvx.ReturnsForecast()
- cvx.Gamma() * cvx.FactorModelCovariance(num_factors=10)
- cvx.Gamma() * cvx.StocksTransactionCost(),
[cvx.LongOnly(), cvx.LeverageLimit(1)],
planning_horizon=6, solver='ECOS')
sim.optimize_hyperparameters(policy, objective='profit')
result_hyperparameter_optimized = sim.backtest(policy)
print('result_hyperparameter_optimized')
print(result_hyperparameter_optimized)
result_hyperparameter_optimized.plot()
if 'CVXPORTFOLIO_SAVE_PLOTS' in os.environ:
plt.savefig('dow30_hyperparameter_optimized.png')
else:
plt.show()
This is the output printed to screen when executing this script. You can see many statistics of the back-tests.
Updating data.............................
LARGEST SHARPE RATIO
gamma_trade and gamma_risk
(0.6, 5)
result
###########################################################
Universe size 30
Initial timestamp 1963-02-01 14:30:00
Final timestamp 2023-11-01 13:30:00
Number of periods 730
Initial value (USDOLLAR) 1.000e+06
Final value (USDOLLAR) 1.467e+09
Profit (USDOLLAR) 1.466e+09
Avg. return (annualized) 12.7%
Volatility (annualized) 11.5%
Avg. excess return (annualized) 8.0%
Avg. active return (annualized) 8.0%
Excess volatility (annualized) 11.6%
Active volatility (annualized) 11.6%
Avg. growth rate (annualized) 12.0%
Avg. excess growth rate (annualized) 7.3%
Avg. active growth rate (annualized) 7.3%
Avg. StocksTransactionCost 2bp
Max. StocksTransactionCost 138bp
Avg. StocksHoldingCost 0bp
Max. StocksHoldingCost 0bp
Sharpe ratio 0.69
Information ratio 0.69
Avg. drawdown -5.9%
Min. drawdown -43.7%
Avg. leverage 57.9%
Max. leverage 100.1%
Avg. turnover 1.6%
Max. turnover 41.2%
Avg. policy time 0.044s
Avg. simulator time 0.005s
Total time 35.144s
###########################################################
LARGEST GROWTH RATE
gamma_trade and gamma_risk
(0.3, 1)
result
###########################################################
Universe size 30
Initial timestamp 1963-02-01 14:30:00
Final timestamp 2023-11-01 13:30:00
Number of periods 730
Initial value (USDOLLAR) 1.000e+06
Final value (USDOLLAR) 7.223e+10
Profit (USDOLLAR) 7.223e+10
Avg. return (annualized) 23.2%
Volatility (annualized) 30.1%
Avg. excess return (annualized) 18.4%
Avg. active return (annualized) 18.4%
Excess volatility (annualized) 30.1%
Active volatility (annualized) 30.1%
Avg. growth rate (annualized) 18.4%
Avg. excess growth rate (annualized) 13.7%
Avg. active growth rate (annualized) 13.7%
Avg. StocksTransactionCost 9bp
Max. StocksTransactionCost 787bp
Avg. StocksHoldingCost 0bp
Max. StocksHoldingCost 0bp
Sharpe ratio 0.61
Information ratio 0.61
Avg. drawdown -27.7%
Min. drawdown -82.5%
Avg. leverage 97.8%
Max. leverage 106.8%
Avg. turnover 2.4%
Max. turnover 71.1%
Avg. policy time 0.045s
Avg. simulator time 0.005s
Total time 36.697s
###########################################################
UNIFORM (1/N) ALLOCATION FOR COMPARISON
result_uniform
###########################################################
Universe size 30
Initial timestamp 1963-02-01 14:30:00
Final timestamp 2023-11-01 13:30:00
Number of periods 730
Initial value (USDOLLAR) 1.000e+06
Final value (USDOLLAR) 6.204e+09
Profit (USDOLLAR) 6.203e+09
Avg. return (annualized) 15.9%
Volatility (annualized) 16.7%
Avg. excess return (annualized) 11.1%
Excess volatility (annualized) 16.8%
Avg. growth rate (annualized) 14.4%
Avg. excess growth rate (annualized) 9.7%
Avg. StocksTransactionCost 4bp
Max. StocksTransactionCost 234bp
Avg. StocksHoldingCost 0bp
Max. StocksHoldingCost 0bp
Sharpe ratio 0.66
Avg. drawdown -4.9%
Min. drawdown -49.5%
Avg. leverage 99.9%
Max. leverage 102.5%
Avg. turnover 2.5%
Max. turnover 50.0%
Avg. policy time 0.000s
Avg. simulator time 0.003s
Total time 1.950s
###########################################################
HYPER-PARAMETER OPTIMIZATION
iteration 0
Current objective:
49262708163.666725
iteration 1
Current objective:
54281879700.21155
iteration 2
Current objective:
58058328523.323006
iteration 3
Current objective:
60955786424.61437
iteration 4
Current objective:
63051214100.27364
iteration 5
Current objective:
64737096341.63388
iteration 6
Current objective:
66039921194.24338
iteration 7
Current objective:
67329996388.34948
iteration 8
Current objective:
68450495985.06613
iteration 9
Current objective:
69296724983.65472
iteration 10
Current objective:
70102723365.48186
iteration 11
Current objective:
71251150787.6262
iteration 12
Current objective:
72192309617.03737
iteration 13
Current objective:
72882238726.47371
iteration 14
Current objective:
73227637485.88083
iteration 15
Current objective:
73299378411.02371
result_hyperparameter_optimized
###########################################################
Universe size 30
Initial timestamp 1963-02-01 14:30:00
Final timestamp 2023-11-01 13:30:00
Number of periods 730
Initial value (USDOLLAR) 1.000e+06
Final value (USDOLLAR) 7.330e+10
Profit (USDOLLAR) 7.330e+10
Avg. return (annualized) 23.5%
Volatility (annualized) 31.0%
Avg. excess return (annualized) 18.8%
Avg. active return (annualized) 18.8%
Excess volatility (annualized) 31.0%
Active volatility (annualized) 31.0%
Avg. growth rate (annualized) 18.4%
Avg. excess growth rate (annualized) 13.7%
Avg. active growth rate (annualized) 13.7%
Avg. StocksTransactionCost 9bp
Max. StocksTransactionCost 855bp
Avg. StocksHoldingCost 0bp
Max. StocksHoldingCost 0bp
Sharpe ratio 0.61
Information ratio 0.61
Avg. drawdown -28.6%
Min. drawdown -83.6%
Avg. leverage 98.1%
Max. leverage 107.5%
Avg. turnover 2.4%
Max. turnover 73.8%
Avg. policy time 0.036s
Avg. simulator time 0.003s
Total time 28.409s
###########################################################
And these are the figure that are plotted.
The result of the cvxportfolio.MultiPeriodOptimization
policy
that has the largest out-of-sample Sharpe ratio:
The result of the cvxportfolio.MultiPeriodOptimization
policy
that has the largest out-of-sample growth rate:
The result of the cvxportfolio.Uniform
policy, which allocates equal
weight to all non-cash assets:
Finally, the result of the cvxportfolio.MultiPeriodOptimization
policy
obtained by automatic hyper-parameter optimization to have largest profit: