Investment Horizon#

This tutorial explores the difference between the general procedure using different investment horizon and the simplified procedure as explained in data preparation.

Prices#

We load the S&P 500 dataset composed of the daily prices of 20 assets from the S&P 500 Index composition starting from 1990-01-02 up to 2022-12-28:

from plotly.io import show

from skfolio import PerfMeasure, Population, RiskMeasure
from skfolio.datasets import load_sp500_dataset
from skfolio.optimization import MeanRisk
from skfolio.preprocessing import prices_to_returns
from skfolio.prior import EmpiricalPrior

prices = load_sp500_dataset()
prices.head()
AAPL AMD BAC BBY CVX GE HD JNJ JPM KO LLY MRK MSFT PEP PFE PG RRC UNH WMT XOM
Date
1990-01-02 0.264 4.125 4.599 0.144 4.991 14.391 1.117 3.438 3.394 2.235 6.658 4.215 0.384 4.738 1.021 3.860 3.322 0.310 3.653 4.068
1990-01-03 0.266 4.000 4.636 0.161 4.910 14.364 1.121 3.452 3.508 2.203 6.658 4.282 0.386 4.692 1.024 3.853 3.322 0.304 3.653 4.027
1990-01-04 0.267 3.938 4.537 0.159 4.847 14.283 1.128 3.459 3.522 2.192 6.621 4.215 0.397 4.646 1.041 3.777 3.322 0.301 3.634 3.987
1990-01-05 0.268 3.812 4.438 0.159 4.775 14.148 1.113 3.423 3.536 2.174 6.549 4.128 0.387 4.581 1.032 3.709 3.322 0.288 3.595 3.966
1990-01-08 0.269 3.812 4.463 0.147 4.820 14.229 1.102 3.481 3.536 2.220 6.549 4.181 0.393 4.664 1.023 3.777 3.322 0.282 3.644 4.027


Linear Returns#

We transform the daily prices into daily linear returns:

X = prices_to_returns(prices)

Model#

We first create a Mean-Variance model using the simplified procedure:

population = Population([])

model = MeanRisk(
    risk_measure=RiskMeasure.VARIANCE,
    efficient_frontier_size=30,
    portfolio_params=dict(name="Simplified", tag="Simplified"),
)
population.extend(model.fit_predict(X))

for tag, investment_horizon in [
    ("3M", 252 / 4),
    ("1Y", 252),
    ("10Y", 10 * 252),
]:
    model = MeanRisk(
        risk_measure=RiskMeasure.VARIANCE,
        efficient_frontier_size=30,
        prior_estimator=EmpiricalPrior(
            is_log_normal=True, investment_horizon=investment_horizon
        ),
        portfolio_params=dict(name=f"General - {tag}", tag=f"General - {tag}"),
    )
    population.extend(model.fit_predict(X))

Let’s plot the efficient frontier:

fig = population.plot_measures(
    x=RiskMeasure.ANNUALIZED_VARIANCE,
    y=PerfMeasure.ANNUALIZED_MEAN,
)
show(fig)

Let’s plot the portfolios compositions:

population.plot_composition()


We can see that the simplified procedure only start to diverge from the general one for investment horizons longer than one year.

Total running time of the script: (0 minutes 0.814 seconds)

Gallery generated by Sphinx-Gallery