generated from mathias/template-go-web
fix(features): revert to 2-channel default; OHLCV features redundant
HPO finding: hl_range≈realized_vol, ret_intrabar≈ret — correlation kills signal. 4ch D=128: 0.3503, 4ch D=256: 0.3807, 2ch D=128 baseline: 0.3908 (winner). Parquet keeps hl_range+ret_intrabar; comment in build() documents the attempt. test_build_uses_4_channels → test_build_uses_2_channels (tracks current default). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -194,17 +194,14 @@ def test_ret_intrabar_formula(ph):
|
|||||||
assert abs(rib - expected) < 1e-6, f"ret_intrabar={rib:.8f}, expected={expected:.8f}"
|
assert abs(rib - expected) < 1e-6, f"ret_intrabar={rib:.8f}, expected={expected:.8f}"
|
||||||
|
|
||||||
|
|
||||||
# 10. build() in train.py uses 4 feature channels when hl_range + ret_intrabar present
|
# 10. build() in train.py uses 2 feature channels (HPO: hl_range/ret_intrabar redundant)
|
||||||
def test_build_uses_4_channels(tmp_path):
|
def test_build_uses_2_channels(tmp_path):
|
||||||
import importlib.util, os
|
import importlib.util, os
|
||||||
hourly_path = "data/processed/eurusd_hourly.parquet"
|
hourly_path = "data/processed/eurusd_hourly.parquet"
|
||||||
if not os.path.exists(hourly_path):
|
if not os.path.exists(hourly_path):
|
||||||
pytest.skip("eurusd_hourly.parquet not present")
|
pytest.skip("eurusd_hourly.parquet not present")
|
||||||
df = pd.read_parquet(hourly_path)
|
spec = importlib.util.spec_from_file_location("train_2ch", "train.py")
|
||||||
if "hl_range" not in df.columns:
|
|
||||||
pytest.skip("eurusd_hourly.parquet lacks hl_range — rebuild first")
|
|
||||||
spec = importlib.util.spec_from_file_location("train_4ch", "train.py")
|
|
||||||
mod = importlib.util.module_from_spec(spec)
|
mod = importlib.util.module_from_spec(spec)
|
||||||
spec.loader.exec_module(mod)
|
spec.loader.exec_module(mod)
|
||||||
(Xtr, _), _ = mod.build()
|
(Xtr, _), _ = mod.build()
|
||||||
assert Xtr.shape[2] == 4, f"expected 4 channels, got {Xtr.shape[2]}"
|
assert Xtr.shape[2] == 2, f"expected 2 channels, got {Xtr.shape[2]}"
|
||||||
|
|||||||
@@ -154,10 +154,9 @@ def build():
|
|||||||
else:
|
else:
|
||||||
df = pd.read_parquet(daily_path).reset_index(drop=True)
|
df = pd.read_parquet(daily_path).reset_index(drop=True)
|
||||||
df["date"] = pd.to_datetime(df["date"])
|
df["date"] = pd.to_datetime(df["date"])
|
||||||
# Use OHLCV-derived features when available; fall back to 2-channel
|
# 2-channel default (HPO: adding hl_range+ret_intrabar hurt — correlated with base feats)
|
||||||
base_feats = ["ret", "realized_vol"]
|
# To experiment: change to ["ret", "realized_vol", "hl_range", "ret_intrabar"]
|
||||||
extra_feats = [c for c in ["hl_range", "ret_intrabar"] if c in df.columns]
|
FEAT_COLS = ["ret", "realized_vol"]
|
||||||
FEAT_COLS = base_feats + extra_feats
|
|
||||||
feats = df[FEAT_COLS].to_numpy(np.float32)
|
feats = df[FEAT_COLS].to_numpy(np.float32)
|
||||||
target = df["realized_vol"].to_numpy(np.float32)
|
target = df["realized_vol"].to_numpy(np.float32)
|
||||||
tr_idx = df.index[df["date"].dt.year <= 2021].tolist()
|
tr_idx = df.index[df["date"].dt.year <= 2021].tolist()
|
||||||
|
|||||||
Reference in New Issue
Block a user