Tema 6: Métodos de simulación
Objetivos de aprendizaje
Después de completar este tema, debería poder:
- Explique la relación entre las distribuciones normal y lognormal y por qué se utiliza la distribución lognormal para modelar los precios de los activos cuando se utilizan rendimientos de activos compuestos continuamente
- Describa la simulación Monte Carlo y explique cómo se puede utilizar en aplicaciones de inversión
- Describa el uso del remuestreo bootstrap al realizar una simulación basada en datos observados en aplicaciones de inversión
Objetivo de aprendizaje 1: Distribuciones normales frente a lognormales
Concepto central: distribuciones estadísticas y modelado de activos
La relación entre las distribuciones normal y lognormal es fundamental para la modelización financiera, particularmente para comprender cómo se comportan de manera diferente los precios y los rendimientos de los activos. Este tema conecta las propiedades distributivas que estudiamos anteriormente con opciones prácticas de modelado. exam-focus
Propiedades de distribución normal
- Simétrica: Curva en forma de campana con igual probabilidad en ambos lados de la media
- Rango: Ilimitado (-∞ a +∞)
- Aplicaciones: Modela los rendimientos de los activos, especialmente los rendimientos compuestos continuamente.
- Parámetros: Media (μ) y desviación estándar (σ)
Propiedades de distribución lognormal
- Asimétrica: distribución sesgada a la derecha
- Rango: Limitado por debajo de cero (0 a +∞)
- Aplicaciones: Modela precios de activos (que no pueden ser negativos)
- Relación: Si X ~ N(μ, σ²), entonces e^X ~ Lognormal
¿Por qué Lognormal para los precios de los activos? exam-focus
Lógica Económica:
- No negatividad: los precios de los activos no pueden ser negativos
- Cambios porcentuales: los cambios de precios se modelan mejor como porcentajes que como cambios absolutos.
- Composición: la composición continua conduce naturalmente a distribuciones lognormales
Fundamentos Matemáticos: Si los rendimientos compuestos continuamente se distribuyen normalmente:
- Sea rt = ln(S_t/S{t-1}) ~ N(μ, σ²)
- Entonces St/S{t-1} = e^{r_t} ~ Lognormal
- Por lo tanto, los precios siguen una distribución lognormal.
Fórmulas y cálculos
Transformación entre normal y lognormal
De devoluciones normales a precios lognormales:
If r_t ~ N(μ, σ²), then:
S_t = S_0 × e^{(μ - σ²/2)t + σ√t × Z}
Where:
- S_t = price at time t
- S_0 = initial price
- μ = expected return
- σ = volatility
- Z ~ N(0,1) = standard normal random variable
- t = time period
Parámetros de distribución lognormal:
If S ~ Lognormal(μ, σ²), then:
- E[S] = e^{μ + σ²/2}
- Var[S] = e^{2μ + σ²}(e^{σ²} - 1)
- Median[S] = e^μ
Relaciones clave:
ln(S_t) ~ N(ln(S_0) + (μ - σ²/2)t, σ²t)
Ejemplos prácticos
Ejemplo 1: Evolución del precio de las acciones
Dado:
- Precio inicial de las acciones: $100
- Rentabilidad anual esperada: 12%
- Volatilidad anual: 20%
- Horizonte temporal: 1 año
Cálculo:
S_1 = 100 × e^{(0.12 - 0.20²/2)×1 + 0.20×√1×Z}
S_1 = 100 × e^{0.10 + 0.20×Z}
Where Z is a standard normal random variable
Distribución de precios:
- Precio medio: E[S_1] = 100 × e^{0,12 + 0,20²/2} = $112,75
- La distribución está sesgada a la derecha con mediana < media
Ejemplo 2: Fundación de fijación de precios de opciones
El modelo de Black-Scholes supone:
S_T = S_0 × e^{(r - σ²/2)T + σ√T×Z}
This lognormal assumption enables:
- Analytical option pricing formulas
- Risk-neutral valuation
- Delta hedging strategies
Aplicación DeFi: modelado de precios de tokens
Simulaciones de pérdidas no permanentesLa simulación de las trayectorias de los precios de los tokens utilizando el modelo lognormal es la base para estimar las distribuciones de pérdidas no permanentes para Uniswap y otros proveedores de liquidez de AMM. Al analizar miles de trayectorias de precios, los LP pueden comprender toda la gama de resultados potenciales, no sólo el caso esperado. defi-application
Contexto: Los proveedores de liquidez en los creadores de mercado automatizados (AMM) enfrentan pérdidas impermanentes cuando los precios de los tokens divergen.
Configuración del modelo:
# Pseudo-code for impermanent loss simulation
def simulate_impermanent_loss(initial_price_A, initial_price_B, mu_A, mu_B, sigma_A, sigma_B, correlation, time_horizon, n_simulations):
results = []
for i in range(n_simulations):
# Generate correlated normal returns
Z1 = random.normal(0, 1)
Z2 = correlation * Z1 + sqrt(1 - correlation²) * random.normal(0, 1)
# Calculate lognormal price evolution
price_A_final = initial_price_A * exp((mu_A - sigma_A²/2) * time_horizon + sigma_A * sqrt(time_horizon) * Z1)
price_B_final = initial_price_B * exp((mu_B - sigma_B²/2) * time_horizon + sigma_B * sqrt(time_horizon) * Z2)
# Calculate impermanent loss
price_ratio_final = price_A_final / price_B_final
price_ratio_initial = initial_price_A / initial_price_B
il = 2 * sqrt(price_ratio_final / price_ratio_initial) / (1 + price_ratio_final / price_ratio_initial) - 1
results.append(il)
return resultsAplicación: Esta simulación ayuda a los LP a comprender las pérdidas potenciales en diferentes escenarios de mercado y supuestos de correlación.
Objetivo de aprendizaje 2: Simulación de Montecarlo
Concepto central: modelado probabilístico mediante simulación
La simulación Monte Carlo es una técnica computacional que utiliza muestreo aleatorio para resolver problemas que podrían ser deterministas en principio pero demasiado complejos para soluciones analíticas. Extiende el marco de probabilidad desde escenarios discretos hasta distribuciones continuas con miles de rutas.
Principios clave
1. Muestreo aleatorio: Genera variables aleatorias según distribuciones de probabilidad especificadas. 2. Repetición: Realice muchas iteraciones para generar confianza estadística 3. Agregación: Combina resultados para estimar la cantidad de interés 4. Convergencia: A medida que aumenta el número de simulaciones, las estimaciones convergen a los valores reales
Marco del proceso de Montecarlo
Paso 1: Definición del problema
- Definir la cantidad a estimar (por ejemplo, valor de la opción, VaR de la cartera)
- Identificar variables aleatorias clave y sus distribuciones.
- Especificar la relación matemática entre entradas y salidas.
Paso 2: Especificación del modelo
- Elija distribuciones de probabilidad apropiadas
- Definir estructuras de correlación entre variables.
- Establecer condiciones de contorno y restricciones.
Paso 3: Ejecución de la simulación
- Generar muestras aleatorias a partir de distribuciones específicas.
- Calcular el resultado de cada ruta de simulación.
- Almacenar resultados para análisis estadístico.
Paso 4: Análisis de resultados
- Calcular estadísticas resumidas (media, desviación estándar, percentiles)
- Evaluar la convergencia y el error de simulación.
- Realizar análisis de sensibilidad.
Fórmulas y cálculos
Estimador básico de Monte Carlo formula
θ̂_MC = (1/n) × Σ(i=1 to n) f(X_i)
Where:
- θ̂_MC = Monte Carlo estimate
- n = number of simulations
- f(X_i) = function value for simulation i
- X_i = random input vector for simulation i
Error estándar de la estimación de Monte Carlo formula
SE(θ̂_MC) = σ̂/√n
Where:
- σ̂ = sample standard deviation of f(X_i)
- n = number of simulations
Intervalos de confianza
95% CI: θ̂_MC ± 1.96 × SE(θ̂_MC)
Técnicas de reducción de varianza
Variaciones antitéticas:
For each random variable Z, also use -Z
This reduces variance when f is monotonic
El control varía:
Use known analytical results for similar problems
θ̂_CV = θ̂_MC + c(θ_control_MC - θ_control_true)
Ejemplos prácticos
Ejemplo 1: Valoración de opciones europeas
Configuración:
- Precio de las acciones: $100
- Precio de ejercicio: $105
- Tasa libre de riesgo: 5%
- Volatilidad: 20%
- Tiempo hasta el vencimiento: 0,25 años
Proceso de simulación:
def monte_carlo_option_pricing(S0, K, r, sigma, T, n_simulations):
payoffs = []
for i in range(n_simulations):
# Generate random stock price at expiration
Z = random.normal(0, 1)
ST = S0 * exp((r - 0.5 * sigma**2) * T + sigma * sqrt(T) * Z)
# Calculate option payoff
payoff = max(ST - K, 0)
payoffs.append(payoff)
# Discount to present value
option_value = exp(-r * T) * mean(payoffs)
standard_error = std(payoffs) / sqrt(n_simulations)
return option_value, standard_errorEjemplo 2: Valor en riesgo (VaR) de la cartera
Monte Carlo VaR amplía el marco matemáticas de cartera simulando la distribución completa de resultados en lugar de confiar en la aproximación normal.
VaR de cartera multiactivo:
def portfolio_var_simulation(weights, expected_returns, covariance_matrix, initial_value, confidence_level, time_horizon, n_simulations):
portfolio_values = []
for i in range(n_simulations):
# Generate correlated asset returns
random_returns = multivariate_normal(expected_returns * time_horizon, covariance_matrix * time_horizon)
# Calculate portfolio return
portfolio_return = sum(weights * random_returns)
# Calculate portfolio value
portfolio_value = initial_value * (1 + portfolio_return)
portfolio_values.append(portfolio_value)
# Calculate VaR
portfolio_values.sort()
var_index = int((1 - confidence_level) * n_simulations)
var = initial_value - portfolio_values[var_index]
return varEjemplo 3: Derivadas dependientes de la ruta
Precio de la opción asiática:
def asian_option_monte_carlo(S0, K, r, sigma, T, n_steps, n_simulations):
dt = T / n_steps
payoffs = []
for i in range(n_simulations):
path_sum = 0
S = S0
# Generate price path
for j in range(n_steps):
Z = random.normal(0, 1)
S = S * exp((r - 0.5 * sigma**2) * dt + sigma * sqrt(dt) * Z)
path_sum += S
# Calculate average price
average_price = path_sum / n_steps
# Calculate payoff
payoff = max(average_price - K, 0)
payoffs.append(payoff)
option_value = exp(-r * T) * mean(payoffs)
return option_value
```### Aplicación DeFi: prueba de estrés de protocolo
#### Simulaciones de creadores de mercado automatizados (AMM)
**Dinámica del Fondo de Liquidez:**
```python
def simulate_amm_performance(initial_reserves_A, initial_reserves_B, fee_rate, price_process_params, trading_intensity, time_horizon, n_simulations):
results = []
for sim in range(n_simulations):
reserves_A = initial_reserves_A
reserves_B = initial_reserves_B
total_fees = 0
# Simulate price movements and trading
for t in range(time_horizon):
# Generate price movement
price_change = generate_price_movement(price_process_params)
# Simulate arbitrage trading
if abs(price_change) > 0:
trade_size = calculate_arbitrage_trade(reserves_A, reserves_B, price_change, trading_intensity)
if trade_size > 0:
# Execute trade and collect fees
new_reserves_A, new_reserves_B, fee_collected = execute_trade(reserves_A, reserves_B, trade_size, fee_rate)
reserves_A, reserves_B = new_reserves_A, new_reserves_B
total_fees += fee_collected
# Calculate final performance metrics
impermanent_loss = calculate_impermanent_loss(initial_reserves_A, initial_reserves_B, reserves_A, reserves_B)
net_return = total_fees - impermanent_loss
results.append({
'impermanent_loss': impermanent_loss,
'fees_earned': total_fees,
'net_return': net_return
})
return resultsPrevisión del precio del gas
def simulate_gas_prices(base_fee_params, priority_fee_params, network_congestion_model, time_steps, n_simulations):
gas_price_paths = []
for sim in range(n_simulations):
base_fees = []
priority_fees = []
for t in range(time_steps):
# Simulate network congestion
congestion_level = generate_congestion(network_congestion_model, t)
# Model base fee dynamics (EIP-1559)
if t == 0:
base_fee = base_fee_params['initial']
else:
utilization = congestion_level
if utilization > 0.5:
base_fee = base_fees[-1] * (1 + base_fee_params['increase_factor'] * (utilization - 0.5) * 2)
else:
base_fee = base_fees[-1] * (1 - base_fee_params['decrease_factor'] * (0.5 - utilization) * 2)
# Model priority fee
priority_fee = lognormal(priority_fee_params['mu'], priority_fee_params['sigma'])
base_fees.append(base_fee)
priority_fees.append(priority_fee)
gas_price_paths.append({
'base_fees': base_fees,
'priority_fees': priority_fees,
'total_fees': [b + p for b, p in zip(base_fees, priority_fees)]
})
return gas_price_pathsObjetivo de aprendizaje 3: remuestreo de Bootstrap
Concepto central: inferencia estadística no paramétrica
El remuestreo Bootstrap es un método estadístico no paramétrico que estima la distribución muestral de una estadística mediante un remuestreo con reemplazo de los datos originales. Se conecta con los conceptos de muestreo e inferencia que se tratan a continuación y es particularmente valioso cuando se desconocen las distribuciones teóricas o cuando los tamaños de muestra son pequeños.
Metodología Bootstrap
Principios clave:
- Distribución empírica: Utilice la muestra como una aproximación de la población.
- Remuestreo con reemplazo: Cree nuevas muestras extrayendo aleatoriamente de los datos originales.
- Inferencia estadística: Estimar intervalos de confianza y pruebas de hipótesis sin supuestos distributivos.
- Consistencia: Las estimaciones de Bootstrap convergen con los parámetros poblacionales reales a medida que aumenta el tamaño de la muestra.
Tipos de métodos Bootstrap
1. Bootstrap no paramétrico:
- Remuestrear directamente a partir de los datos observados.
- Sin supuestos distributivos
- Más común en aplicaciones financieras.
2. Arranque paramétrico:
- Ajustar un modelo paramétrico a los datos.
- Remuestreo de la distribución montada.
- Útil cuando se conoce la forma de distribución.
3. Bloqueo de arranque:
- Preservar la estructura de series temporales.
- Remuestrear bloques de observaciones consecutivas.
- Esencial para datos financieros dependientes.
Fórmulas y cálculos
Algoritmo básico de arranque
1. Original sample: X = {x₁, x₂, ..., xₙ}
2. For b = 1 to B bootstrap replications:
a. Draw random sample X*ᵦ = {x*₁, x*₂, ..., x*ₙ} with replacement from X
b. Calculate statistic θ*ᵦ = f(X*ᵦ)
3. Bootstrap distribution: {θ*₁, θ*₂, ..., θ*ᵦ}
Error estándar de arranque
SE_bootstrap(θ̂) = √[(1/(B-1)) × Σ(θ*ᵦ - θ̄*)²]
Where:
- θ̄* = (1/B) × Σθ*ᵦ (bootstrap mean)
- B = number of bootstrap replications
Intervalos de confianza de Bootstrap
Método percentil:
95% CI: [θ*₍₀.₀₂₅₎, θ*₍₀.₉₇₅₎]
Where θ*₍ₚ₎ is the p-th percentile of bootstrap distribution
Sesgo corregido y acelerado (BCa):
Adjusted percentiles: [θ*₍α₁₎, θ*₍α₂₎]
Where α₁ and α₂ are bias and skewness adjusted
Bloquear Bootstrap para series temporales
Block length: l
Number of blocks: k = ⌈n/l⌉
Resample k blocks with replacement
Concatenate to form bootstrap sample
Ejemplos prácticos
Ejemplo 1: Intervalo de confianza del índice de Sharpe
Problema: Estimar el intervalo de confianza para el índice de Sharpe de la cartera utilizando datos históricos limitados.
def bootstrap_sharpe_ratio(returns, risk_free_rate, n_bootstrap=1000):
n = len(returns)
original_sharpe = (mean(returns) - risk_free_rate) / std(returns)
bootstrap_sharpes = []
for b in range(n_bootstrap):
# Resample with replacement
bootstrap_sample = [returns[random.randint(0, n-1)] for _ in range(n)]
# Calculate bootstrap Sharpe ratio
bootstrap_mean = mean(bootstrap_sample)
bootstrap_std = std(bootstrap_sample)
bootstrap_sharpe = (bootstrap_mean - risk_free_rate) / bootstrap_std
bootstrap_sharpes.append(bootstrap_sharpe)
# Calculate confidence interval
bootstrap_sharpes.sort()
ci_lower = bootstrap_sharpes[int(0.025 * n_bootstrap)]
ci_upper = bootstrap_sharpes[int(0.975 * n_bootstrap)]
return {
'original_sharpe': original_sharpe,
'ci_lower': ci_lower,
'ci_upper': ci_upper,
'standard_error': std(bootstrap_sharpes)
}Ejemplo 2: Validación del modelo VaR
Backtesting de modelos VaR:
def bootstrap_var_backtest(returns, var_estimates, confidence_level, n_bootstrap=1000):
n = len(returns)
violations = [1 if returns[i] < -var_estimates[i] else 0 for i in range(n)]
actual_violation_rate = mean(violations)
expected_violation_rate = 1 - confidence_level
bootstrap_violation_rates = []
for b in range(n_bootstrap):
# Resample violation indicators
bootstrap_violations = [violations[random.randint(0, n-1)] for _ in range(n)]
bootstrap_rate = mean(bootstrap_violations)
bootstrap_violation_rates.append(bootstrap_rate)
# Test if actual rate is significantly different from expected
p_value = sum([1 for rate in bootstrap_violation_rates if abs(rate - expected_violation_rate) >= abs(actual_violation_rate - expected_violation_rate)]) / n_bootstrap
return {
'actual_violation_rate': actual_violation_rate,
'expected_violation_rate': expected_violation_rate,
'p_value': p_value,
'bootstrap_distribution': bootstrap_violation_rates
}Ejemplo 3: Simulación histórica vs VaR paramétrico
Comparación de métodos VaR:
def compare_var_methods(returns, confidence_level, n_bootstrap=1000):
n = len(returns)
# Historical Simulation VaR
returns_sorted = sorted(returns)
historical_var = -returns_sorted[int((1 - confidence_level) * n)]
# Parametric VaR (normal assumption)
mu = mean(returns)
sigma = std(returns)
parametric_var = -(mu + norm.ppf(1 - confidence_level) * sigma)
# Bootstrap confidence intervals for Historical VaR
bootstrap_historical_vars = []
for b in range(n_bootstrap):
bootstrap_sample = [returns[random.randint(0, n-1)] for _ in range(n)]
bootstrap_sample.sort()
bootstrap_var = -bootstrap_sample[int((1 - confidence_level) * n)]
bootstrap_historical_vars.append(bootstrap_var)
# Confidence interval for Historical VaR
bootstrap_historical_vars.sort()
hist_var_ci_lower = bootstrap_historical_vars[int(0.025 * n_bootstrap)]
hist_var_ci_upper = bootstrap_historical_vars[int(0.975 * n_bootstrap)]
return {
'historical_var': historical_var,
'parametric_var': parametric_var,
'historical_var_ci': [hist_var_ci_lower, hist_var_ci_upper],
'bootstrap_distribution': bootstrap_historical_vars
}Aplicación DeFi: MEV y análisis de liquidez
Análisis de oportunidades de valor máximo extraíble (MEV)
Problema: Analice la distribución de oportunidades MEV utilizando datos históricos limitados de transacciones de blockchain.
def bootstrap_mev_analysis(mev_opportunities, gas_costs, n_bootstrap=1000):
"""
Analyze MEV opportunity distribution using bootstrap resampling
mev_opportunities: list of observed MEV profits
gas_costs: corresponding gas costs for each opportunity
"""
n = len(mev_opportunities)
net_profits = [mev - gas for mev, gas in zip(mev_opportunities, gas_costs)]
# Original statistics
original_mean_profit = mean(net_profits)
original_profit_rate = sum([1 for profit in net_profits if profit > 0]) / n
original_max_profit = max(net_profits)
bootstrap_results = {
'mean_profits': [],
'profit_rates': [],
'max_profits': [],
'percentile_90': [],
'sharpe_ratios': []
}
for b in range(n_bootstrap):
# Resample MEV opportunities
indices = [random.randint(0, n-1) for _ in range(n)]
bootstrap_profits = [net_profits[i] for i in indices]
# Calculate bootstrap statistics
bootstrap_results['mean_profits'].append(mean(bootstrap_profits))
bootstrap_results['profit_rates'].append(sum([1 for p in bootstrap_profits if p > 0]) / n)
bootstrap_results['max_profits'].append(max(bootstrap_profits))
bootstrap_results['percentile_90'].append(percentile(bootstrap_profits, 90))
# MEV Sharpe ratio (profit/volatility)
if std(bootstrap_profits) > 0:
bootstrap_results['sharpe_ratios'].append(mean(bootstrap_profits) / std(bootstrap_profits))
# Calculate confidence intervals
confidence_intervals = {}
for metric in bootstrap_results:
sorted_values = sorted(bootstrap_results[metric])
confidence_intervals[metric] = [
sorted_values[int(0.025 * n_bootstrap)],
sorted_values[int(0.975 * n_bootstrap)]
]
return {
'original_statistics': {
'mean_profit': original_mean_profit,
'profit_rate': original_profit_rate,
'max_profit': original_max_profit
},
'bootstrap_distributions': bootstrap_results,
'confidence_intervals': confidence_intervals
}Simulación de crisis de liquidez
Bloquear Bootstrap para eventos de liquidez correlacionados:
def bootstrap_liquidity_crisis(price_data, volume_data, liquidity_metrics, block_length=5, n_bootstrap=1000):
"""
Use block bootstrap to preserve temporal dependencies in liquidity analysis
"""
n = len(price_data)
n_blocks = n // block_length
crisis_indicators = []
for b in range(n_bootstrap):
# Block bootstrap to preserve time series structure
bootstrap_indices = []
for _ in range(n_blocks):
start_idx = random.randint(0, n - block_length)
block_indices = list(range(start_idx, start_idx + block_length))
bootstrap_indices.extend(block_indices)
# Trim to original length
bootstrap_indices = bootstrap_indices[:n]
# Create bootstrap time series
bootstrap_prices = [price_data[i] for i in bootstrap_indices]
bootstrap_volumes = [volume_data[i] for i in bootstrap_indices]
bootstrap_liquidity = [liquidity_metrics[i] for i in bootstrap_indices]
# Identify liquidity crisis periods
crisis_periods = identify_liquidity_crisis(bootstrap_prices, bootstrap_volumes, bootstrap_liquidity)
crisis_indicators.append({
'crisis_frequency': len(crisis_periods) / n,
'average_crisis_duration': mean([period['duration'] for period in crisis_periods]) if crisis_periods else 0,
'max_price_impact': max([period['max_impact'] for period in crisis_periods]) if crisis_periods else 0
})
return crisis_indicators
def identify_liquidity_crisis(prices, volumes, liquidity_metrics, threshold_percentile=95):
"""
Identify periods of liquidity crisis based on multiple indicators
"""
# Calculate price volatility
price_changes = [abs(prices[i] - prices[i-1]) / prices[i-1] for i in range(1, len(prices))]
# Calculate liquidity stress indicators
volume_threshold = percentile(volumes, 100 - threshold_percentile) # Low volume
liquidity_threshold = percentile(liquidity_metrics, threshold_percentile) # High impact
volatility_threshold = percentile(price_changes, threshold_percentile) # High volatility
crisis_periods = []
in_crisis = False
crisis_start = None
for i in range(len(volumes)):
# Crisis conditions: low volume AND (high liquidity impact OR high volatility)
crisis_condition = (volumes[i] < volume_threshold and
(liquidity_metrics[i] > liquidity_threshold or
(i > 0 and price_changes[i-1] > volatility_threshold)))
if crisis_condition and not in_crisis:
# Start of crisis
in_crisis = True
crisis_start = i
elif not crisis_condition and in_crisis:
# End of crisis
in_crisis = False
crisis_periods.append({
'start': crisis_start,
'end': i,
'duration': i - crisis_start,
'max_impact': max(liquidity_metrics[crisis_start:i+1])
})
return crisis_periodsIntegración y Aplicaciones Avanzadas
Combinando métodos de simulación
Enfoque híbrido Monte Carlo-Bootstrap
def hybrid_simulation_var(historical_returns, portfolio_weights, confidence_level, monte_carlo_steps=1000, bootstrap_replications=500):
"""
Combine Monte Carlo simulation with bootstrap resampling for robust VaR estimation
"""
var_estimates = []
for b in range(bootstrap_replications):
# Bootstrap resample historical returns
n = len(historical_returns)
bootstrap_returns = [historical_returns[random.randint(0, n-1)] for _ in range(n)]
# Estimate parameters from bootstrap sample
mu = mean(bootstrap_returns)
sigma = std(bootstrap_returns)
# Monte Carlo simulation with bootstrap-estimated parameters
simulated_returns = []
for mc in range(monte_carlo_steps):
random_return = random.normal(mu, sigma)
portfolio_return = sum([w * random_return for w in portfolio_weights]) # Simplified single-asset case
simulated_returns.append(portfolio_return)
# Calculate VaR from simulated returns
simulated_returns.sort()
var = -simulated_returns[int((1 - confidence_level) * monte_carlo_steps)]
var_estimates.append(var)
# Analyze distribution of VaR estimates
final_var = mean(var_estimates)
var_confidence_interval = [
sorted(var_estimates)[int(0.025 * bootstrap_replications)],
sorted(var_estimates)[int(0.975 * bootstrap_replications)]
]
return {
'var_estimate': final_var,
'confidence_interval': var_confidence_interval,
'var_distribution': var_estimates
}Validación de modelos y análisis de sensibilidad
Marco de comparación de métodos de simulación
def compare_simulation_methods(asset_returns, option_params, var_confidence_level):
"""
Comprehensive comparison of different simulation approaches
"""
results = {}
# 1. Historical Simulation (Bootstrap-based)
results['historical_simulation'] = bootstrap_historical_var(asset_returns, var_confidence_level)
# 2. Parametric Monte Carlo
mu = mean(asset_returns)
sigma = std(asset_returns)
results['parametric_monte_carlo'] = monte_carlo_var(mu, sigma, var_confidence_level)
# 3. Bootstrap Monte Carlo Hybrid
results['hybrid_method'] = hybrid_simulation_var(asset_returns, [1.0], var_confidence_level)
# 4. Option Pricing Comparison
if option_params:
results['option_pricing'] = {
'monte_carlo': monte_carlo_option_pricing(**option_params),
'black_scholes': black_scholes_analytical(**option_params)
}
return resultsResumen y conclusiones clave
Relaciones críticas1. Conexión normal-lognormal: Rentabilidades continuamente compuestas (normal) → Precios de activos (lognormal)
- Jerarquía de simulación: simulación histórica ⊂ métodos Bootstrap ⊂ métodos Monte Carlo
- Aplicaciones DeFi: simulación financiera tradicional + factores específicos de Blockchain (gas, MEV, liquidez)
Mejores prácticas
- Validación del modelo: compare siempre los resultados de la simulación con las soluciones analíticas cuando estén disponibles
- Pruebas de convergencia: supervise la convergencia de la simulación y utilice tamaños de muestra adecuados
- Análisis de sensibilidad: Pruebe la solidez de diferentes supuestos de parámetros
- Dependencias de tiempo: utilice el arranque en bloque para datos de series de tiempo para preservar la estructura de correlación
Puntos de enfoque del examen exam-focus
- Comprender POR QUÉ se utilizan distribuciones lognormales para los precios de activos
- Conocer el proceso completo de simulación de Montecarlo
- Distinguir entre métodos de arranque paramétricos y no paramétricos.
- Aplicar métodos de simulación a problemas prácticos de inversión.
- Reconocer cuándo cada método es el más apropiado
Consideraciones específicas de DeFi
- Volatilidad del precio del gas: los modelos deben tener en cuenta la dinámica de congestión de la red
- Extracción MEV: los métodos Bootstrap ayudan a analizar datos limitados de oportunidades MEV
- Crisis de liquidez: el arranque en bloque preserva las dependencias temporales en los eventos de liquidez de DeFi
- Pruebas de estrés de protocolo: las simulaciones de Monte Carlo evalúan la resiliencia del protocolo en escenarios extremos
Este enfoque integral de los métodos de simulación proporciona la base para un análisis cuantitativo avanzado tanto en las finanzas tradicionales como en las aplicaciones DeFi emergentes.