Open fnoor1 opened 1 year ago
import numpy as np from scipy.stats import norm from sobol_seq import i4_sobol_generate
def heston_call_price_quasi_monte_carlo(S, K, T, r, sigma, kappa, theta, rho, v0, num_simulations=100000, steps=100): dt = T / steps S_t = np.zeros(num_simulations) v_t = np.zeros(num_simulations)
# Generate Sobol sequences for the two Brownian motions
sobol_points = i4_sobol_generate(2 * steps, num_simulations)
for i in range(num_simulations):
S_prev = S
v_prev = v0
for t in range(steps):
# Convert Sobol points to standard normal using the inverse CDF
W_S = norm.ppf(sobol_points[i, 2*t])
W_v = norm.ppf(sobol_points[i, 2*t + 1])
# Scale the normal variates to match the desired covariance structure
W_S *= np.sqrt(dt)
W_v = W_v * np.sqrt(dt) * rho + W_S * np.sqrt(1 - rho**2)
S_prev = S_prev * np.exp((r - 0.5 * v_prev) * dt + np.sqrt(v_prev) * W_S)
v_prev = v_prev + kappa * (theta - v_prev) * dt + sigma * np.sqrt(v_prev) * W_v
v_prev = max(v_prev, 0) # Apply truncation or reflection to prevent negative variance
S_t[i] = S_prev
v_t[i] = v_prev
# Calculate the call option prices
call_payoffs = np.maximum(S_t - K, 0)
call_price = np.exp(-r * T) * np.mean(call_payoffs)
return call_price
import numpy as np from scipy.stats import norm from scipy.optimize import least_squares import pyswarms as ps
Black-Scholes Model
def black_scholes(S, K, T, r, sigma): d1 = (np.log(S / K) + (r + 0.5 * sigma * 2) T) / (sigma np.sqrt(T)) d2 = d1 - sigma np.sqrt(T) call_price = S norm.cdf(d1) - K np.exp(-r T) norm.cdf(d2) return call_price
Binomial Tree Model
def binomial_tree(S, K, T, r, sigma, steps): dt = T / steps u = np.exp(sigma np.sqrt(dt)) d = 1 / u p = (np.exp(r dt) - d) / (u - d)
Heston Model
def heston_call_price(S, K, T, r, sigma, kappa, theta, rho, v0, num_simulations=100000):
Implement the Heston model for option pricing using Monte Carlo simulations
def heston_call_price(S, K, T, r, sigma, kappa, theta, rho, v0, num_simulations=100000, num_steps=100): np.random.seed(42) dt = T / num_steps prices = np.zeros(num_simulations)
Heston Model Calibration
def heston_squared_errors(params, S, K, T, r, market_prices): kappa, theta, rho, v0 = params errors = np.zeros_like(market_prices) for i, K_i in enumerate(K): estimated_price = heston_call_price(S, K_i, T, r, sigma, kappa, theta, rho, v0) errors[i] = (estimated_price - market_prices[i]) ** 2 return errors
Custom Model Calibration
def custom_model_weights(weights, S, K, T, r, sigma, steps, kappa, theta, rho, v0, num_simulations=100000): weight_bs, weight_bt, weight_heston = weights price_bs = black_scholes(S, K, T, r, sigma) price_bt = binomial_tree(S, K, T, r, sigma, steps) price_heston = heston_call_price(S, K, T, r, sigma, kappa, theta, rho, v0, num_simulations) return weight_bs price_bs + weight_bt price_bt + weight_heston * price_heston
Objective function for Particle Swarm Optimization (PSO)
def pso_objective_function(params, S, K, T, r, sigma, steps, market_prices, num_simulations=100000): weights, heston_params = np.split(params, [3]) kappa, theta, rho, v0 = heston_params errors = np.zeros_like(market_prices) for i, K_i in enumerate(K): estimated_price = custom_model_weights(weights, S, K_i, T, r, sigma, steps, kappa, theta, rho, v0, num_simulations) errors[i] = (estimated_price - market_prices[i]) ** 2 return np.sum(errors)
def fars_custom_algo(S, K, T, r, sigma, steps, observed_strike_prices, observed_market_prices):
Particle Swarm Optimization (PSO) for calibration
if name == "main":
Replace these variables with your own data