Simulating stock market returns using Monte Carlo › 4. Computing Final Portfolio Values

Michael BrenndoerferJuly 19, 20252 min read
Simulating stock market returns using Monte Carlo › 4. Computing Final Portfolio ValuesOne section · Sections in this article5 / 8 ↓
Reading tools Definitions & inline links

Toggle tooltip visibility. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

The Compound Growth Formula

The fundamental principle of compound growth is applied to calculate how the investment grows over time. The mathematical formula is:

Future Value=Initial Investment×∏t=1T(1+rt)\text{Future Value} = \text{Initial Investment} \times \prod_{t=1}^{T}(1 + r_t)

Where:

  • ∏\prod (capital Pi) means "product of" - multiply all terms together
  • rtr_t is the return in year tt
  • (1+rt)(1 + r_t) converts a return percentage to a growth factor

Why This Works

  • A 10% return means money grows by a factor of 1.10
  • A -5% loss means money is multiplied by 0.95
  • Over multiple years, all these factors are multiplied together

Example Calculation

If returns of [8%, -2%, 15%] occur over 3 years:

  • Growth factors: [1.08, 0.98, 1.15]
  • Total growth: 1.08 × 0.98 × 1.15 = 1.217
  • 100becomes:100 becomes: 100 × 1.217 = $121.70
In[4]:
Code
# Converting annual returns to growth factors (1 + return)
growth_factors_matrix = 1 + annual_returns

# Calculating cumulative growth by multiplying across years (axis=1)
# This gives the total growth factor for each 10-year scenario
cumulative_growth_factors = growth_factors_matrix.prod(axis=1)

# Applying compound growth to get final portfolio values
final_portfolio_values = INITIAL_INVESTMENT * cumulative_growth_factors

print("Example Compound Growth Calculations:")
print(f"   Scenario 1 returns: {annual_returns[0, :].round(3)}")
print(f"   Growth factors: {growth_factors_matrix[0, :].round(3)}")
print(f"   Cumulative growth: {cumulative_growth_factors[0]:.3f}")
print(f"   Final value: ${final_portfolio_values[0]:.2f}")
print(f"\nSummary Statistics:")
print(f"   Number of scenarios calculated: {len(final_portfolio_values):,}")
print(f"   Minimum final value: ${final_portfolio_values.min():.2f}")
print(f"   Maximum final value: ${final_portfolio_values.max():.2f}")
print(f"   Average final value: ${final_portfolio_values.mean():.2f}")
Out[4]:
Console
Example Compound Growth Calculations:
   Scenario 1 returns: [ 0.126 -0.076  0.193  0.221 -0.213 -0.115  0.099  0.033  0.077 -0.048]
   Growth factors: [1.126 0.924 1.193 1.221 0.787 0.885 1.099 1.033 1.077 0.952]
   Cumulative growth: 1.228
   Final value: $122.84

Summary Statistics:
   Number of scenarios calculated: 10,000
   Minimum final value: $33.48
   Maximum final value: $1165.34
   Average final value: $214.67
In[5]:
Code
# Creating comprehensive statistical summary
portfolio_summary = (pd.Series(final_portfolio_values, name='Final Portfolio Value ($)')
                     .describe(percentiles=[.05, .25, .5, .75, .95])
                     .round(2))

# Reordering for better presentation and adding meaningful labels
risk_metrics = portfolio_summary.loc[['min', '5%', '25%', '50%', 'mean', '75%', '95%', 'max']]
risk_metrics.index = ['Worst Case', '5th Percentile (VaR)', '25th Percentile', 
                     'Median', 'Expected Value', '75th Percentile', 
                     '95th Percentile', 'Best Case']

# Calculating additional useful metrics
prob_loss = (final_portfolio_values < INITIAL_INVESTMENT).mean() * 100
prob_double = (final_portfolio_values >= 2 * INITIAL_INVESTMENT).mean() * 100
expected_return_annualized = (risk_metrics['Expected Value'] / INITIAL_INVESTMENT) ** (1/YEARS) - 1

print("Portfolio Value Distribution After 10 Years")
print("=" * 50)
print(risk_metrics.to_string())
print(f"\nRisk Analysis:")
print(f"   Probability of losing money: {prob_loss:.1f}%")
print(f"   Probability of doubling investment: {prob_double:.1f}%")
print(f"   Expected annualized return: {expected_return_annualized:.1%}")
print(f"   Range of outcomes: ${risk_metrics['Worst Case']:.2f} - ${risk_metrics['Best Case']:.2f}")
Out[5]:
Console
Portfolio Value Distribution After 10 Years
==================================================
Worst Case                33.48
5th Percentile (VaR)      91.25
25th Percentile          144.07
Median                   195.04
Expected Value           214.67
75th Percentile          264.35
95th Percentile          404.81
Best Case               1165.34

Risk Analysis:
   Probability of losing money: 7.6%
   Probability of doubling investment: 48.0%
   Expected annualized return: 7.9%
   Range of outcomes: $33.48 - $1165.34