83 lines
3.2 KiB
Python
83 lines
3.2 KiB
Python
|
|
# -*- coding: utf-8 -*-
|
||
|
|
"""Diagnosa fit GARCH pada return padat-train XAUUSD M15."""
|
||
|
|
import os
|
||
|
|
import sys
|
||
|
|
import numpy as np
|
||
|
|
import datetime as dt
|
||
|
|
|
||
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
||
|
|
SRC = os.path.normpath(os.path.join(HERE, "..", "..", "SniperGold_ML"))
|
||
|
|
sys.path.insert(0, SRC)
|
||
|
|
import train_regime as TR
|
||
|
|
|
||
|
|
BASE = os.path.normpath(os.path.join(HERE, "..", "..", "..", "Files", "AlgoForge", "Data"))
|
||
|
|
z = np.load(os.path.join(BASE, "XAUUSD_M15.npz"))
|
||
|
|
t = z["time"].astype(np.int64)
|
||
|
|
c = z["close"].astype(np.float64)
|
||
|
|
r = np.zeros(len(c))
|
||
|
|
r[1:] = np.log(np.maximum(c[1:], 1e-12) / np.maximum(c[:-1], 1e-12))
|
||
|
|
|
||
|
|
# window padat-train: 2018-01-01 .. 2024-07-30
|
||
|
|
lo = int(np.argmax(t >= dt.datetime(2018, 1, 1).timestamp()))
|
||
|
|
hi = int(np.argmax(t > dt.datetime(2024, 7, 30).timestamp()))
|
||
|
|
rr = r[lo:hi]
|
||
|
|
print(f"fit window: n={len(rr)} | {dt.datetime.fromtimestamp(int(t[lo]), dt.timezone.utc)} "
|
||
|
|
f".. {dt.datetime.fromtimestamp(int(t[hi-1]), dt.timezone.utc)}")
|
||
|
|
print(f"std={rr.std():.6f} | nol-return: {int((rr == 0).sum())} "
|
||
|
|
f"({100*(rr == 0).mean():.2f}%) | |r|max={np.abs(rr).max():.4f}")
|
||
|
|
for lag in (1, 2, 5, 10, 24):
|
||
|
|
ac = np.corrcoef(rr[lag:] ** 2, rr[:-lag] ** 2)[0, 1]
|
||
|
|
print(f" ac(r^2, lag={lag:2d}) = {ac:+.4f}")
|
||
|
|
|
||
|
|
print("\nfit default (bounds train_regime):")
|
||
|
|
try:
|
||
|
|
w, a, b, nu = TR.fit_garch_t(rr)
|
||
|
|
print(f" omega={w:.3e} alpha={a:.4f} beta={b:.4f} persist={a+b:.4f} nu={nu:.2f}")
|
||
|
|
except Exception as e:
|
||
|
|
print(" GAGAL:", e)
|
||
|
|
|
||
|
|
print("\nfit dgn bounds longgar + init lain:")
|
||
|
|
from scipy.optimize import minimize
|
||
|
|
import math
|
||
|
|
rl = [float(x) for x in rr]
|
||
|
|
n = len(rl)
|
||
|
|
var0 = float(np.var(rr) + 1e-12)
|
||
|
|
|
||
|
|
def negll_p(p, init_s2=None):
|
||
|
|
w, a, b, nu = p
|
||
|
|
if w <= 0 or a < 0 or b < 0 or a + b >= 0.999 or nu <= 2.05:
|
||
|
|
return 1e12
|
||
|
|
l1 = math.log(math.pi * (nu - 2.0))
|
||
|
|
l2 = 2.0 * math.lgamma(nu / 2.0) - 2.0 * math.lgamma((nu + 1.0) / 2.0)
|
||
|
|
s2 = var0 if init_s2 is None else init_s2
|
||
|
|
ll = 0.0
|
||
|
|
for rv in rl:
|
||
|
|
s2 = w + a * rv * rv + b * s2
|
||
|
|
if s2 < 1e-12:
|
||
|
|
s2 = 1e-12
|
||
|
|
e2 = rv * rv / s2
|
||
|
|
ll += math.log(s2) + (nu + 1.0) * math.log1p(e2 / (nu - 2.0))
|
||
|
|
return 0.5 * (ll + n * (l1 + l2))
|
||
|
|
|
||
|
|
for tag, x0, bnd in [
|
||
|
|
("init klasik (0.06/0.92/7)", [1e-7, 0.06, 0.92, 7.0],
|
||
|
|
[(1e-12, 1e-4), (0.001, 0.5), (0.40, 0.995), (2.1, 50.0)]),
|
||
|
|
("init netral (0.1/0.85/10)", [1e-7, 0.10, 0.85, 10.0],
|
||
|
|
[(1e-12, 1e-4), (0.001, 0.5), (0.40, 0.995), (2.1, 50.0)]),
|
||
|
|
("init ekstrem-vol (0.05/0.9/5)", [1e-7, 0.05, 0.90, 5.0],
|
||
|
|
[(1e-12, 1e-4), (0.001, 0.5), (0.40, 0.995), (2.1, 50.0)]),
|
||
|
|
]:
|
||
|
|
res = minimize(negll_p, x0, method="L-BFGS-B", bounds=bnd,
|
||
|
|
options=dict(maxiter=3000))
|
||
|
|
w, a, b, nu = res.x
|
||
|
|
print(f" [{tag}] omega={w:.3e} alpha={a:.4f} beta={b:.4f} "
|
||
|
|
f"persist={a+b:.4f} nu={nu:.2f} nfev={res.nfev} fun={res.fun:.1f}")
|
||
|
|
|
||
|
|
# subset 2018-2020 (periode vol lebih tenang) sbg kontrol
|
||
|
|
lo2 = int(np.argmax(t >= dt.datetime(2018, 1, 1).timestamp()))
|
||
|
|
hi2 = int(np.argmax(t > dt.datetime(2020, 12, 31).timestamp()))
|
||
|
|
rr2 = r[lo2:hi2]
|
||
|
|
print(f"\nkontrol subset 2018-2020: n={len(rr2)} std={rr2.std():.6f}")
|
||
|
|
w, a, b, nu = TR.fit_garch_t(rr2)
|
||
|
|
print(f" fit default: omega={w:.3e} alpha={a:.4f} beta={b:.4f} "
|
||
|
|
f"persist={a+b:.4f} nu={nu:.2f}")
|