Portfolio research & risk analytics

Yahoo Finance via yfinance · CAD · 03 Jan 2019 to 31 Aug 2026

Open research notebook · Download notebook

4Research portfolios
19,575Validated price records
0Missing prices
10 bpsCost per traded dollar

Portfolio comparison

Growth emphasizes technology. Income emphasizes banks, energy and utilities. Balanced diversifies across these equity sectors. Low volatility uses inverse historical volatility weights. All four remain equity portfolios.

Portfolio Id Cumulative Return Annualized Return Volatility Sharpe Max Drawdown Total Cost Excess Annualized Return
Balanced 279.82% 19.12% 16.29% 0.97 -28.73% $776.61 2.90%
Benchmark 214.75% 16.22% 16.37% 0.82 -37.21% $0.00 0.00%
Growth 549.20% 27.80% 28.60% 0.90 -48.72% $1,856.88 11.57%
Income 212.94% 16.13% 16.06% 0.83 -33.06% $395.51 -0.09%
Low volatility 243.59% 17.57% 15.29% 0.94 -29.71% $573.68 1.34%

How much could the investment lose?

The lower fan boundary is a 5th-percentile cutoff: 5% of simulated ending balances lie below it. The average of that worst 5% describes the tail beyond the cutoff. Values below the initial CAD 100,000 represent losses of principal.

Adverse ending balances compared with the initial investment
Same dollar scale across all portfolios. This view focuses on downside without compression from the large upside range.
Portfolio 1st percentile 5th percentile Worst-5% average Finish below initial capital Ever lose over 20% of initial capital
Balanced $102,851 $131,665 $114,217 0.72% 8.80%
Benchmark $77,753 $106,182 $88,261 3.92% 16.12%
Growth $74,185 $114,708 $90,947 3.08% 24.24%
Income $92,131 $119,698 $103,301 1.56% 12.16%
Low volatility $103,037 $129,046 $112,975 0.84% 9.22%

Growth versus Balanced in the same market scenarios

Subtract Balanced's ending value from Growth's in each shared simulated market sequence. Growth finishes below Balanced in 19.32% of paths. The median difference is $+91,045; the 5th-percentile difference is $-50,893. These are conditional simulation results.

Subtracting the portfolios' separate 5th percentiles does not give the 5th percentile of their difference. Their individual adverse outcomes need not occur in the same path. The paired shortfall is not a maximum loss.

What can happen before year five?

Median and severe simulated maximum drawdown for each portfolio
Each path's largest fall from a prior peak, including the initial balance. A peak can be above starting capital. Larger bars mean deeper losses.

Does the conclusion survive different sampling assumptions?

All comparisons use 5,000 paths, seed 42, equal capital and the same completed history. Longer moving blocks retain longer sequences but underweight dates near the sample boundaries. Circular blocks wrap the end to the beginning, reducing that weighting effect while introducing artificial joins. The choice affects both dependence and sampled returns. No variant is selected because it produces a preferred ranking.

Sampling assumption Portfolio 5th percentile Median final value Finish below initial capital
Published model Balanced $131,665 $235,938 0.72%
Published model Growth $114,708 $329,002 3.08%
126-session moving blocks Balanced $140,104 $217,691 0.30%
126-session moving blocks Growth $90,882 $283,667 6.22%
252-session moving blocks Balanced $139,163 $211,997 0.18%
252-session moving blocks Growth $91,528 $283,126 6.44%
126-session circular blocks Balanced $152,114 $244,540 0.18%
126-session circular blocks Growth $111,727 $360,857 3.60%
252-session circular blocks Balanced $152,584 $241,209 0.04%
252-session circular blocks Growth $106,308 $358,141 4.08%

Research finding: Growth's historical return advantage makes its median attractive under these assumptions, while several measures show greater downside than Balanced. A positive 5th percentile does not rule out principal losses. Higher volatility alone does not require every lower percentile to rank worst. The future return distribution remains unvalidated, and changing sampling assumptions can change the conclusion.

The bootstrap can generate worse compounded outcomes than any observed historical path by repeating adverse blocks. It cannot establish probabilities for risks absent from the sample. The separate volatility-model holdout does not validate these five-year return scenarios.

Download downside metrics · Download paired comparisons · Download sampling sensitivity

Full percentile ranges
Five portfolios starting at CAD 100,000 on identical dollar scales, showing median and percentile ranges
Conditional simulation ranges, not guaranteed bounds. Outcomes outside the shaded ranges remain possible.
Historical wealth continuation (unequal balances)

This secondary view carries forward each historical ending balance. The primary comparison and scenario table use equal investments.

Five-year comparison: equal CAD 100,000 investments

Every portfolio and XIC starts with CAD 100,000 after the final completed backtest date. The table, primary chart and exports all use this equal-capital basis. The secondary historical continuation rescales scenarios to each past ending balance. The engine resamples consecutive 20-session blocks of each portfolio's completed net returns, including modeled rebalancing costs, across 5,000 paths. This preserves some short-run return clustering while showing a distribution of plausible outcomes rather than a single expected-value promise.

These are conditional historical scenarios. All portfolios and XIC use the same sampled 20-session periods. The chart includes the initial value and ends exactly five calendar years later; 252 modeled sessions per year are mapped to that horizon, not to an exchange holiday calendar. Resampled net returns carry historical costs; future trades are not recomputed. Strong historical returns and today's selected securities can make projections optimistic. Bands omit parameter uncertainty and unseen market regimes. They use no returns after the projection start date and do not claim the historical sample will repeat.

Portfolio Historical end Starting value 5th percentile terminal value Median terminal value 95th percentile terminal value Probability of loss after horizon Median maximum drawdown Paths Years Block days
Balanced 31 Aug 2026 $100,000 $131,665 $235,938 $394,953 0.7% -20.3% 5000 5 20
Benchmark 31 Aug 2026 $100,000 $106,182 $213,678 $360,350 3.9% -24.2% 5000 5 20
Growth 31 Aug 2026 $100,000 $114,708 $329,002 $872,362 3.1% -33.5% 5000 5 20
Income 31 Aug 2026 $100,000 $119,698 $211,349 $341,758 1.6% -22.1% 5000 5 20
Low volatility 31 Aug 2026 $100,000 $129,046 $222,660 $355,250 0.8% -19.4% 5000 5 20

Forecast validation

Models predict the next 20 sessions' realized annualized volatility. Selection uses training-period cross-validation only. The last 20% is held out, with a 20-session gap to exclude overlapping training labels. A negative R² means the model is worse than predicting the test mean. Compare RMSE with persistence before concluding that machine learning helps.

portfolio_id model rmse r2 selected_by_cv
Balanced Linear regression 0.0432 -0.088 False
Balanced Ridge 0.0418 -0.020 True
Balanced Lasso 0.0418 -0.020 False
Balanced ElasticNet 0.0421 -0.033 False
Balanced Persistence baseline 0.0498 -0.449 False
Growth Linear regression 0.0999 -0.058 False
Growth Ridge 0.0993 -0.045 True
Growth Lasso 0.0997 -0.054 False
Growth ElasticNet 0.0997 -0.055 False
Growth Persistence baseline 0.1314 -0.830 False
Income Linear regression 0.0358 -0.383 False
Income Ridge 0.0351 -0.332 True
Income Lasso 0.0352 -0.339 False
Income ElasticNet 0.0353 -0.345 False
Income Persistence baseline 0.0312 -0.049 False
Low volatility Linear regression 0.0370 -0.210 False
Low volatility Ridge 0.0360 -0.145 True
Low volatility Lasso 0.0360 -0.143 False
Low volatility ElasticNet 0.0362 -0.153 False
Low volatility Persistence baseline 0.0398 -0.396 False
Methodology and limitations

Adjusted closes approximate reinvested total returns. Position units are synthetic adjusted-price units, not broker share balances. Portfolios begin after a 252-session calibration period and rebalance at the close of each month's first trading session. The benchmark is XIC.TO, a broad Canadian equity ETF held without rebalancing. Returns use previous-close weights and deduct 10 bps on total absolute traded weight. Initial entry costs, taxes and additional market impact are excluded.

Backtest timing and look-ahead controls. The Low Volatility target weights are calibrated once using only the first 252 completed sessions; subsequent prices cannot affect those weights. On each later date, the portfolio return is calculated from the weights held at the previous close. A monthly rebalance occurs only after that day's return and transaction cost have been booked, so it applies to future returns rather than the same day's already-known move. The forecast models use features available through date t and labels composed only of returns from t+1 onward. The final 20% is held out, and a 20-session purge separates the last training label from the test period. Scaling and parameter selection occur within training folds only.

Sharpe uses arithmetic mean daily excess return divided by daily standard deviation, annualized with √252. Annualized return uses compound growth. The constant annual risk-free assumption is 3.0%. Income is a sector allocation label: dividend yield and cash distributions are not modeled separately. Today's chosen security universe creates selection and survivorship bias. Low-volatility weights are calibrated once and need not deliver the lowest future risk. Overlapping forecast targets mean test errors are dependent; no statistical significance or trading profitability is claimed.

Forecasts are a separate research experiment and do not drive portfolio allocations. Forward scenarios start after the final backtest date and resample only completed portfolio returns; they are not an out-of-sample forecast of returns. Financial data and model outputs remain reviewable in the SQL mart and exported CSV files.

Run configuration and provenance
{
  "configuration": {
    "start": "2018-01-01",
    "end": "2026-09-01",
    "benchmark": "XIC.TO",
    "initial_capital": 100000,
    "risk_free_rate": 0.03,
    "transaction_cost_bps": 10,
    "warmup_days": 252,
    "forecast_days": 20,
    "test_fraction": 0.2,
    "simulation_years": 5,
    "simulation_paths": 5000,
    "bootstrap_block_days": 20,
    "trading_days": 252,
    "seed": 42
  },
  "provenance": {
    "source": "Yahoo Finance via yfinance",
    "retrieved_at": "2026-09-09T05:52:46.940726+00:00",
    "sha256": "b44f2f6710ea5c813e3c598cd6594adab2596f9a5bf8c00f4734f6ccca092bb4",
    "start": "2018-01-01",
    "end_exclusive": "2026-09-01",
    "price_basis": "Dividend/split adjusted close; CAD"
  },
  "validation": {
    "exact_duplicates_removed": 0,
    "missing_prices": 0,
    "price_records": 19575,
    "securities": 9,
    "dates": 2175
  }
}