<jupyter_start><jupyter_text>Pairs trading model based on stochastic optimal control The model computes the optimal asset allocation $h_{t}^{*}$ by maximizing terminal payoff of the strategy:$h_{t}^{*} := \underset{h(t)}{sup} \ \mathbb{E}\left[ \frac{1}{\gamma}V(T)^{\gamma}\right]$subject to:$dX_{t} = \kappa (\theta - X_t)dt + \eta dW_{t}^{x}$and$dV_{t} = \left[h_t \left(\kappa (\theta - X_t)+ \frac{1}{2}\eta^{2}+\rho \sigma \eta \right) + r \right]V_t dt + h_tV_t \eta dW_{t}^{x} $<jupyter_code>from src.simulation.simulate_cointegrated_assets import simulate_ou_spread

B_0     = 100
X_0     = 0.0
mu      = 0.05
kappa   = 5.5
theta   = 0.0
eta     = 0.15
sigma_B = 0.15

N_sim   = 1
N_steps = 500
T = 2.0
dt = T / N_steps

A,B,X = simulate_ou_spread(N_sim, N_steps, B_0, X_0, kappa, theta, eta, mu, sigma_B, dt)


import matplotlib.pyplot as plt

kws_A = {'label':'A','color':'blue' ,'alpha':0.75, 'lw': 2}
kws_B = {'label':'B','color':'black','alpha':0.75, 'lw': 2}
kws_X = {'label':'X','color':'black','alpha':0.75, 'lw': 2}

fig,ax = plt.subplots(2,1,figsize=(10,7))

ax[0].plot(A[:,0],**kws_A)
ax[0].plot(B[:,0],**kws_B)
ax[0].set_ylabel('Prices',fontsize=12)
ax[0].legend()

ax[1].plot(X[:,0],**kws_X)
ax[1].set_ylabel('Spread',fontsize=12)
ax[1].legend()

plt.show()<jupyter_output><empty_output><jupyter_text>Parameter estimationThe strategy is dependent on the parameters $(\kappa, \theta, \eta, \rho )$ which describe the behavior of the spread:$dX_{t} = \kappa (\theta - X_t)dt + \eta dW_{t}^{x}$These parameters may be estimated using OLS.<jupyter_code>from src.optimal_controls.ou_params import OrnsteinUhlenbeckProcessParameters
from src.optimal_controls.ou_spread_model_parameters import OUSpreadModelStrategyParameters

# Estimate spread parameters
try:
    ou_params = OrnsteinUhlenbeckProcessParameters.ols_parameter_estimation(A, B, dt)
    print('OLS estimates are \n {}'.format(ou_params))
except Exception as exn:
    print('Failed to estimate model parameters!')
    raise(exn)

# Create trading model parameters
nominal  = 1000000
symbol_A = 'A'
symbol_B = 'B'
horizon  = 1.0
risk_tol = -float(100)
max_leverage = 1

model_params = OUSpreadModelStrategyParameters(nominal, symbol_A, symbol_B, horizon, risk_tol, max_leverage)<jupyter_output>OLS estimates are 
 Ornstein-Uhlenbeck Parameters: Kappa = 4.81, Theta = -0.01, Rho = -0.01, Eta = 0.15<jupyter_text>Behavior of the strategy:We solve the optimal allocation over $(t , X_t)$ grid in order to see how the model allocates capital on asset $A$ (allocation in asset $B$ is negative of the optimal allocation in asset $A$).<jupyter_code>from utils.plot_utils import plot_optimal_solution

plot_optimal_solution(X, ou_params, model_params, 200)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1560798548094374, 'fraction_numerical': 0.033030852994555354, 'mean_word_length': 5.484705882352941, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '178657', 'license': 'MIT', 'n_tokens_mistral': 1115, 'n_tokens_neox': 1030, 'n_words': 248, 'path': 'Pairs_Trading_Strategy_Notes.ipynb', 'repo_name': 'PontusHultkrantz/statarb', 'size': '2755'}