Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions code/score_submission.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def qvar2(z, s0, s1): # define q-variance function, parameter is minimal vola
plt.xlim(-zmax, zmax)
plt.ylim(0.0, ymax)

plt.legend(fontsize=12)
plt.legend(fontsize=12, loc='upper right')
plt.grid(alpha=0.3)
plt.tight_layout()
##plt.savefig("figure_1_1.png", dpi=300, bbox_inches='tight')
Expand Down Expand Up @@ -152,12 +152,14 @@ def qvar2(z, s0, s1): # define q-variance function, parameter is minimal vola
ymax2 = 1.2
ax.axis([-zmax+delz/2, zmax-delz/2, 0, ymax2]) # uses ymax2 for ensemble plot


data = df_orig.copy()
# now plot q-variance for different periods T, check for period-depenedence
# plot with periods
TVEC = [5, 10, 20, 40, 80]

plt.figure(figsize=(9,7))
popt = [0.2586, 0.0214] # same as optimized fit to data # for competition score should fit original parabola
fitted = qvar(binned.z_mid, popt[0], popt[1]) # cols are z_bin, which is a range like (-0.601, -0.55], and qvar
#plt.plot(binned.z_mid, binned['var'], 'b-', lw=3,label='all T')
plt.plot(binned.z_mid, fitted, 'red', lw=3, label=f'σ₀ = {popt[0]:.3f}, zoff = {popt[1]:.3f}, R² = {r2:.3f}')

Expand All @@ -174,11 +176,13 @@ def qvar2(z, s0, s1): # define q-variance function, parameter is minimal vola
r2 = 1 - np.sum((binned["var"] - fitted)**2) / np.sum((binned["var"] - binned["var"].mean())**2)
print(f"T = {Tcur} σ₀ = {popt[0]:.4f} zoff = {popt[1]:.4f} R² = {r2:.4f}")
colcur = str(Tcur/100)
##plt.plot(binned.z_mid, binned['var'], c=colcur, lw=2,label=f'T = {Tcur/5:.0f}, R² = {r2:.3f}')
plt.plot(binned.z_mid, binned['var'], c=colcur, lw=2,label=f'T = {Tcur/5:.0f}')
plt.plot(binned.z_mid, binned['var'], c=colcur, lw=2,label=f'T = {Tcur/5:.0f}, R² = {r2:.3f}')
#plt.plot(binned.z_mid, binned['var'], c=colcur, lw=2,label=f'T = {Tcur/5:.0f}')

plt.xlabel('z (scaled log return)', fontsize=12)
plt.ylabel('Annualised variance', fontsize=12)
plt.legend(fontsize=10, loc='upper center')
plt.grid(alpha=0.3)
plt.title('All stocks T=2, 4, 8, 16 weeks – Q-Variance', fontsize=14)


Expand Down
Binary file modified submissions/tingjun2/Figure_1_100k.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified submissions/tingjun2/Figure_1_5M.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added submissions/tingjun2/Figure_2_100k.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added submissions/tingjun2/Figure_2_5M.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified submissions/tingjun2/Figure_3_100k.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified submissions/tingjun2/Figure_3_5M.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified submissions/tingjun2/Figure_4_100k.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified submissions/tingjun2/Figure_4_5M.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 39 additions & 17 deletions submissions/tingjun2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,46 @@
## Model Overview
The **GARCH(1,1) Volatility Model** (Generalized Autoregressive Conditional Heteroskedasticity) describes the evolution of a security price $S$ where the variance $V$ is a stochastic process exhibiting **Mean Reversion** and **Volatility Clustering**.

This implementation maps the discrete-time GARCH process to the theoretical **Q-Variance** relationship. By simulating millions of trading days, we demonstrate that the stochastic variance updates converge to a deterministic parabolic fit: $V(z) = \sigma_0^2 + \frac{(z - z_{off})^2}{2}$.
This implementation maps the discrete-time GARCH process to the theoretical **Q-Variance** relationship. By simulating millions of trading days, we demonstrate that the stochastic variance updates converge to a deterministic parabolic fit:
$$V(z) = \sigma_0^2 + \frac{(z - z_{off})^2}{2}$$



## Parameters & Mapping Logic
The model utilizes four parameters to control the GARCH dynamics and recover the theoretical geometry of the Q-variance parabola:

| Parameter | Value | Influence on Q-Variance Geometry |
| :--- | :--- | :--- |
| **Target Vol ($\sigma$)** | **0.095** | **Minimal Volatility ($\sigma_0$):** Sets the vertical baseline (the "floor" of the parabola). |
| **Annual Return ($\mu$)** | **0.0844** | **Z-Shift ($z_{off}$):** Controls the horizontal asymmetry (displacement from zero). |
| **Persistence ($\lambda$)** | **0.8** | **Curvature/Steepness:** Determines the quadratic coefficient; lower $\lambda$ makes the parabola **narrower** |
| **Mean Reversion ($\gamma$)** | **0.01** | **Stability:** The buffer ensures $\lambda + \alpha < 1$, allowing the process to converge to a stationary mean. |

| **Target Vol ($\sigma$)** | **0.425** | **Minimal Volatility ($\sigma_0$):** Sets the vertical baseline (the "floor" of the parabola). |
| **Annual Return ($\mu$)** | **0.06** | **Z-Shift ($z_{off}$):** Controls the horizontal asymmetry (displacement from zero). |
| **Persistence ($\beta$)** | **0.8** | **Curvature/Steepness:** Determines the rate of decay; higher $\beta$ maintains "memory" of past volatility. |
| **Shock Weight ($\alpha$)** | **0.19** | **Sensitivity:** Controls the reaction to market shocks. Fixed such that $\alpha + \beta = 0.99$. |

> **Note:** The "Mean Reversion" strength is implicitly defined as $\gamma = 1 - (\alpha + \beta) = 0.01$.

## Simulation Methodology
The simulation generates a synthetic price history using independent paths of **2,500 trading days** each. To eliminate "local path luck" and ensure statistical smoothing, we utilize **2,000 samples** to create a total dataset of **5,000,000 trading days**.
The simulation generates a synthetic price history using independent paths of **2,500 trading days** each. To eliminate "local path luck" and ensure statistical smoothing, we utilized **2,000 samples** to create a total dataset of **5,000,000 trading days**.

### Discrete-Time Updates

- **Variance Update (GARCH Logic):**
The variance at step $i$ is driven by the weighted average of the long-run variance (Variance Targeting), the previous variance, and the most recent market percentage-return shock ($\epsilon_{i-1}$):

$$V_i = \omega + \alpha \cdot \epsilon_{i-1}^2 + \beta \cdot V_{i-1}$$

Where:
- $\epsilon_{i-1} = \frac{S_{i-1} - S_{i-2}}{S_{i-2}}$
- $\omega = \frac{\sigma^{2}}{252} \cdot 0.01$ (Targeting a long-run annual volatility $\sigma$)
- $\alpha = 0.99 - \beta$

$$
V_i = \omega + \lambda V_{i-1} + (1 - \lambda - \gamma) \cdot \left( \frac{S_{i-1} - S_{i-2}}{S_{i-2}} \right)^2
$$

Where $\omega = \frac{\sigma^{2}}{252} \cdot (1 - \lambda)$.

- **Price Update:**
The price follows a Geometric Brownian Motion (GBM) step, adjusted for the current stochastic variance $V_i$:

$$
S_i = S_{i-1} \exp\left( \frac{\mu}{252} - \frac{V_i}{2} + \sqrt{V_i} \epsilon \right)
$$
$$S_i = S_{i-1} \exp\left( \frac{\mu}{252} - \frac{V_i}{2} + \sqrt{V_i} Z \right)$$

where $\epsilon \sim \mathcal{N}(0,1)$.
where $Z \sim \mathcal{N}(0,1)$.

---

Expand All @@ -47,12 +53,14 @@ The model was optimized using the 5M-day horizon to achieve a high-fidelity fit
### Optimized Model Performance
| Total Days | $\sigma_0$ (Target) | $z_{off}$ (Target) | $R^2$ | Notes |
| :--- | :--- | :--- | :--- | :--- |
| **5,000,000** | 0.2586 | 0.0214 | **0.9967** | High-fidelity structural convergence. |
| **100,000** | 0.2586 | 0.0214 | **0.9701** | Lower $R^2$ due to idiosyncratic noise. |
| **5,000,000** | 0.2586 | 0.0214 | **0.997** | High-fidelity structural convergence. |
| **100,000** | 0.2586 | 0.0214 | **0.966** | Lower $R^2$ due to idiosyncratic noise. |

### Comparative Visualizations
The transition from 100k days to 5M days shows the "clearing" of statistical noise. In the large sample, the stochastic variance updates converge almost perfectly to the theoretical parabola.



#### **100,000 Day Sample (Noise-Dominant)**
<div style="display: flex; justify-content: space-around;">
<img src="Figure_1_100k.png" width="32%">
Expand All @@ -78,6 +86,20 @@ By plotting $R^2$ as a function of total simulated days, we identified a clear t
![Convergence Analysis](convergence_analysis.png)
Figure: $R^2$ score vs. Total Days. The 0.995 threshold is maintained after the 1M-day mark.

---
## Acknowledgments & Version History

> **Version 2.0 Update**
> An earlier version of this model utilized an incorrect definition of the intercept term ($\omega$), which led to a scaling mismatch in the long-run variance. Special thanks to **@Orrell** for pointing out this discrepancy.

In this current version, I have:
* **Fixed the $\omega$ definition:** Implemented proper **Variance Targeting** logic, where $\omega = V_{target} \cdot \gamma$.
* **Standardized Nomenclature:** Renamed parameters to follow standard GARCH(1,1) conventions ($\alpha$ for the shock component and $\beta$ for the persistence component).
* **Re-optimized Parameters:** Recalibrated the parameter set specifically for the 5M-day horizon to ensure maximum fit.

Despite these structural corrections, the results remain consistent with previous findings, further confirming the original hypothesis of **Q-variance emergence** in GARCH-governed systems.

---

## Project Structure
- [price_generator2.ipynb](price_generator2.ipynb): Vectorized simulation and optimization logic.
Expand Down
Binary file modified submissions/tingjun2/convergence_analysis.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified submissions/tingjun2/dataset_part1.parquet
Binary file not shown.
Binary file modified submissions/tingjun2/dataset_part2.parquet
Binary file not shown.
Binary file modified submissions/tingjun2/dataset_part3.parquet
Binary file not shown.
534 changes: 349 additions & 185 deletions submissions/tingjun2/price_generator2.ipynb

Large diffs are not rendered by default.

Loading
Loading