The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
Monte Carlo simulations are a common use case for parallel computing. This example demonstrates running 10,000 portfolio simulations to estimate risk metrics.
Use Case: Portfolio risk analysis, Value at Risk (VaR) calculations, stress testing
Computational Pattern: Embarrassingly parallel - each simulation is independent
You need to simulate 10,000 different portfolio scenarios to estimate: - Expected portfolio value - Value at Risk (VaR) at 95% confidence - Sharpe ratio distribution - Probability of loss scenarios
Each simulation involves 252 trading days (one year) with correlated asset returns.
Define a function that simulates one portfolio trajectory:
simulate_portfolio <- function(seed) {
set.seed(seed)
# Portfolio parameters
n_days <- 252
initial_value <- 1000000 # $1M portfolio
# Asset allocation (60/40 stocks/bonds)
stock_weight <- 0.6
bond_weight <- 0.4
# Expected returns (annualized)
stock_return <- 0.10 / 252 # 10% annual
bond_return <- 0.04 / 252 # 4% annual
# Volatility (annualized)
stock_vol <- 0.20 / sqrt(252) # 20% annual
bond_vol <- 0.05 / sqrt(252) # 5% annual
# Correlation
correlation <- 0.3
# Generate correlated returns
stock_returns <- rnorm(n_days, mean = stock_return, sd = stock_vol)
bond_noise <- rnorm(n_days)
bond_returns <- rnorm(n_days, mean = bond_return, sd = bond_vol)
bond_returns <- correlation * stock_returns +
sqrt(1 - correlation^2) * bond_returns
# Portfolio returns
portfolio_returns <- stock_weight * stock_returns +
bond_weight * bond_returns
# Cumulative value
portfolio_values <- initial_value * cumprod(1 + portfolio_returns)
# Calculate metrics
final_value <- portfolio_values[n_days]
max_drawdown <- max((cummax(portfolio_values) - portfolio_values) /
cummax(portfolio_values))
sharpe_ratio <- mean(portfolio_returns) / sd(portfolio_returns) * sqrt(252)
list(
final_value = final_value,
return_pct = (final_value - initial_value) / initial_value * 100,
max_drawdown = max_drawdown,
sharpe_ratio = sharpe_ratio,
min_value = min(portfolio_values),
max_value = max(portfolio_values)
)
}Run a smaller test locally:
# Test with 100 simulations
set.seed(123)
local_start <- Sys.time()
local_results <- lapply(1:100, simulate_portfolio)
local_time <- as.numeric(difftime(Sys.time(), local_start, units = "secs"))
cat(sprintf("100 simulations completed in %.1f seconds\n", local_time))
cat(sprintf("Estimated time for 10,000: %.1f minutes\n",
local_time * 100 / 60))Typical output:
100 simulations completed in 2.3 seconds
Estimated time for 10,000: 3.8 minutes
For 10,000 simulations locally: ~3.8 minutes
Run all 10,000 simulations on AWS:
# Run 10,000 simulations on 50 workers
results <- starburst_map(
1:10000,
simulate_portfolio,
workers = 50,
cpu = 2,
memory = "4GB"
)Typical output:
🚀 Starting starburst cluster with 50 workers
💰 Estimated cost: ~$2.80/hour
📊 Processing 10000 items with 50 workers
📦 Created 50 chunks (avg 200 items per chunk)
🚀 Submitting tasks...
✓ Submitted 50 tasks
⏳ Progress: 50/50 tasks (1.2 minutes elapsed)
✓ Completed in 1.2 minutes
💰 Actual cost: $0.06
Extract and analyze the results:
# Extract metrics
final_values <- sapply(results, function(x) x$final_value)
returns <- sapply(results, function(x) x$return_pct)
sharpe_ratios <- sapply(results, function(x) x$sharpe_ratio)
max_drawdowns <- sapply(results, function(x) x$max_drawdown)
# Summary statistics
cat("\n=== Portfolio Simulation Results (10,000 scenarios) ===\n")
cat(sprintf("Mean final value: $%.0f\n", mean(final_values)))
cat(sprintf("Median final value: $%.0f\n", median(final_values)))
cat(sprintf("\nMean return: %.2f%%\n", mean(returns)))
cat(sprintf("Std dev of returns: %.2f%%\n", sd(returns)))
cat(sprintf("\nValue at Risk (5%%): $%.0f\n",
quantile(final_values, 0.05)))
cat(sprintf("Expected Shortfall (5%%): $%.0f\n",
mean(final_values[final_values <= quantile(final_values, 0.05)])))
cat(sprintf("\nMean Sharpe Ratio: %.2f\n", mean(sharpe_ratios)))
cat(sprintf("Mean Max Drawdown: %.2f%%\n", mean(max_drawdowns) * 100))
cat(sprintf("\nProbability of loss: %.2f%%\n",
mean(returns < 0) * 100))
# Distribution plot
hist(final_values / 1000,
breaks = 50,
main = "Distribution of Portfolio Final Values",
xlab = "Final Value ($1000s)",
col = "lightblue",
border = "white")
abline(v = 1000, col = "red", lwd = 2, lty = 2)
abline(v = quantile(final_values / 1000, 0.05), col = "orange", lwd = 2, lty = 2)
legend("topright",
c("Initial Value", "VaR (5%)"),
col = c("red", "orange"),
lwd = 2, lty = 2)Typical output:
=== Portfolio Simulation Results (10,000 scenarios) ===
Mean final value: $1,102,450
Median final value: $1,097,230
Mean return: 10.24%
Std dev of returns: 12.83%
Value at Risk (5%): $892,340
Expected Shortfall (5%): $845,120
Mean Sharpe Ratio: 0.82
Mean Max Drawdown: 8.45%
Probability of loss: 18.34%
| Method | Workers | Time | Cost | Speedup |
|---|---|---|---|---|
| Local | 1 | 3.8 min | $0 | 1x |
| staRburst | 10 | 0.6 min | $0.03 | 6.3x |
| staRburst | 25 | 0.3 min | $0.04 | 12.7x |
| staRburst | 50 | 0.2 min | $0.06 | 19x |
Key Insights: - Near-linear scaling up to 50 workers - Cost remains minimal ($0.06) even with 50 workers - Sweet spot: 25-50 workers for this workload - Total iteration time: <2 minutes from start to results
Good fit: - Each iteration is independent - Computational time > 0.1 seconds per iteration - Total iterations > 1,000 - Results can be easily aggregated
Not ideal: - Very fast iterations (< 0.01 seconds) - High data transfer per iteration - Strong sequential dependencies
The complete runnable script is available at:
Run it with:
Related examples: - Bootstrap Confidence Intervals - Another Monte Carlo application - Financial Risk Modeling - Advanced portfolio analysis
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.