This is an example that shows that Cvxportfolio can work as well with
different asset classes, in this case a real estate portfolio. We use
the Case-Shiller index as proxy for the price of housing units in various
metropolitan areas in the USA. We impose realistic transaction costs, which
are comparable to the annual return on the asset, and we show
that multi-period optimization is useful to correctly balance transaction cost
and expected risk-adjusted return.
This example script is
available in the repository.
importosimportcvxportfolioascvximportnumpyasnpimportpandasaspdimportmatplotlib.pyplotasplt# We test the Multi-Period Optimization model on a real estate# portfolio for which the transaction cost are large with respect# to the typical returns.# We use the Case-Shiller indices as proxies for (residential) real# estate prices.# These are monthly time serieses of the Case-Shiller index for # a selection of US metropolitan areas. You can find them on the# website of FRED https://fred.stlouisfed.org/UNIVERSE=['SFXRSA',# San Francisco'LXXRSA',# Los Angeles'SEXRSA',# Seattle'DAXRSA',# Dallas'SDXRSA',# San Diego'MIXRSA',# Miami'PHXRSA',# Phoenix'NYXRSA',# New York'CHXRSA',# Chicago'ATXRSA',# Atlanta'LVXRSA',# Las Vegas'POXRSA',# Portland'WDXRSA',# Washington D.C.'TPXRSA',# Tampa'CRXRSA',# Charlotte'MNXRSA',# Minneapolis'DEXRSA',# Detroit'CEXRSA',# Cleveland'DNXRSA',# Denver'BOXRSA',# Boston]# we assume that the cost of transacting # residential real estate is about 5%LINEAR_TCOST=0.05simulator=cvx.MarketSimulator(universe=UNIVERSE,# we enabled the default data interface to download index# prices from FREDdatasource='Fred',costs=[cvx.TransactionCost(a=LINEAR_TCOST,b=None,# since we don't have market volumes, we can't use the# market impact term of the transaction cost model)])# let's see what a uniform allocation doesresult_uniform=simulator.backtest(cvx.Uniform())print('BACK-TEST RESULT OF UNIFORM (1/N) ALLOCATION')print(result_uniform)result_uniform.plot()if'CVXPORTFOLIO_SAVE_PLOTS'inos.environ:plt.savefig('case_shiller_uniform.png')# These are risk model coefficients. They don't seem to have# a strong effect on this example.NUM_FACTORS=5kappa=0.1# This is the multi-period planning horizon. We plan for 6 months # in the future.HORIZON=6policies=[]# sweep over risk aversionforgamma_riskinnp.logspace(0,3,10):policies.append(cvx.MultiPeriodOptimization(cvx.ReturnsForecast()-gamma_risk*(cvx.FactorModelCovariance(num_factors=NUM_FACTORS)+kappa*cvx.RiskForecastError())-cvx.TransactionCost(a=LINEAR_TCOST,b=None),[cvx.LongOnly(applies_to_cash=True)],planning_horizon=HORIZON,))results=simulator.backtest_many(policies)print('BACK-TEST RESULT OF MPO WITH HIGHEST (OUT-OF-SAMPLE) PROFIT')print(results[np.argmax([el.profitforelinresults])])results[np.argmax([el.profitforelinresults])].plot()if'CVXPORTFOLIO_SAVE_PLOTS'inos.environ:plt.savefig('case_shiller_highest_profit.png')# Plotfig=plt.figure()plt.plot([result.excess_returns.std()*np.sqrt(12)forresultinresults],[result.excess_returns.mean()*12forresultinresults],'r*-',label='Multi-period optimization frontier')plt.scatter([result_uniform.excess_returns.std()*np.sqrt(12)],[result_uniform.excess_returns.mean()*12],label='Uniform (1/n) allocation')plt.legend()plt.title('Back-Test Result (Out-Of-Sample) for Real Estate Portfolio')plt.xlabel('Excess risk (annualized)')plt.ylabel('Excess return (annualized)')if'CVXPORTFOLIO_SAVE_PLOTS'inos.environ:fig.savefig('case_shiller_frontier.png')else:plt.show()
This is the output printed to screen when executing this script. You can see
many statistics of the back-tests.