Closes #ISSUE-027-REGIME-UI - Implement regime indicator badge and dynamic meta-learner threshold

This commit is contained in:
Antigravity Agent
2026-06-17 19:59:37 +02:00
parent dcb59c17f0
commit 1dc637aaf6
11 changed files with 103 additions and 26 deletions

View File

@@ -484,7 +484,7 @@ def train_and_forecast():
"""
if not ML_LIBRARIES_AVAILABLE:
print("Scikit-learn not available. Skipping model fitting.")
return get_mock_predictions()
return get_mock_predictions(), 0
# Load data
csv_path = os.path.join('backend', 'data', 'BTC-USD.csv')
@@ -572,11 +572,28 @@ def train_and_forecast():
X_train_selected = X_train_scaled
X_test_selected = X_test_scaled
try:
high_alpha_cols = {
'v_supply', 'asopr', 'sth_sopr', 'lth_sopr', 'theta', 'squeeze_risk',
'd_liq', 'f_comp', 'z_f', 'z_f_squeeze_trigger', 'cvd_inst', 'cvd_ret',
'div_cvd', 'lambda_kyle'
}
# Identify indices of high-alpha features that are present in X_train
high_alpha_indices = [
i for i, col in enumerate(X_train.columns)
if col in high_alpha_cols
]
# Fit selector classifier (Random Forest)
selector_clf = RandomForestClassifier(n_estimators=30, max_depth=4, random_state=42)
# Boruta shadow model sweep
boruta_idx = boruta_shadow_pruning(X_train_scaled, y_train)
# Ensure high-alpha indices are retained in Boruta output
for idx in high_alpha_indices:
if idx not in boruta_idx:
boruta_idx.append(idx)
X_train_boruta = X_train_scaled[:, boruta_idx]
# PIMP permutation feature filter
@@ -584,6 +601,12 @@ def train_and_forecast():
# Map back to original indices
selected_feature_indices = [boruta_idx[i] for i in pimp_idx]
# Ensure high-alpha indices are retained in the final selection
for idx in high_alpha_indices:
if idx not in selected_feature_indices:
selected_feature_indices.append(idx)
X_train_selected = X_train_scaled[:, selected_feature_indices]
X_test_selected = X_test_scaled[:, selected_feature_indices]
print(f"Boruta & PIMP Selection ({h_label}): Reduced features from {X_train_scaled.shape[1]} to {X_train_selected.shape[1]}")
@@ -618,10 +641,16 @@ def train_and_forecast():
meta_clf.fit(X_train_micro, y_reliability)
# Compute confidence score r_hat on test sample
r_pred = float(meta_clf.predict_proba(X_test_micro)[0][1])
if len(meta_clf.classes_) >= 2:
r_pred = float(meta_clf.predict_proba(X_test_micro)[0][1])
train_r_probs = meta_clf.predict_proba(X_train_micro)[:, 1]
else:
r_pred = float(meta_clf.classes_[0])
train_r_probs = np.full(len(X_train_micro), float(meta_clf.classes_[0]))
# 3. Apply Ironclad Execution Rule: Execute ONLY if confidence exceeds threshold theta_conf = 0.55
theta_conf = 0.55
theta_conf = float(np.mean(train_r_probs))
# 3. Apply Ironclad Execution Rule: Execute ONLY if confidence exceeds threshold theta_conf
if r_pred >= theta_conf:
# Retrieve expected direction probability
classes = list(clf.classes_)
@@ -644,7 +673,7 @@ def train_and_forecast():
print(f"Model {name} failed on horizon {h_label}: {e}")
predictions[name][h_label] = 0.5
return predictions
return predictions, active_regime
def get_mock_predictions():
@@ -769,7 +798,7 @@ def main():
# Ingest live data first
fetch_real_data()
preds = train_and_forecast()
preds, active_regime = train_and_forecast()
output_dir = os.path.join('public', 'data')
os.makedirs(output_dir, exist_ok=True)
@@ -778,6 +807,7 @@ def main():
payload = {
"isShieldActive": not (ML_LIBRARIES_AVAILABLE and os.path.exists(os.path.join('backend', 'data', 'BTC-USD.csv'))),
"activeRegime": int(active_regime) + 1,
"predictions": {
"BTC": preds,
"ETH": {

View File

@@ -729,4 +729,4 @@ Date,Open,High,Low,Close,Volume
2026-06-14,64420.16796875,65749.78125,63634.0234375,65710.3984375,21572226975
2026-06-15,65711.109375,67248.1328125,65315.8359375,66289.5,32927321950
2026-06-16,66289.4609375,66928.609375,65315.0703125,65600.640625,25063963967
2026-06-17,65710.09375,65849.53125,65333.8984375,65853.6796875,23256606720
2026-06-17,65710.09375,65849.53125,65333.8984375,65996.8203125,23256606720
1 Date Open High Low Close Volume
729 2026-06-14 64420.16796875 65749.78125 63634.0234375 65710.3984375 21572226975
730 2026-06-15 65711.109375 67248.1328125 65315.8359375 66289.5 32927321950
731 2026-06-16 66289.4609375 66928.609375 65315.0703125 65600.640625 25063963967
732 2026-06-17 65710.09375 65849.53125 65333.8984375 65853.6796875 65996.8203125 23256606720

View File

@@ -502,4 +502,4 @@ Date,Open,High,Low,Close,Volume
2026-06-12,4208.2998046875,4225.2998046875,4173.2001953125,4215.0,1167
2026-06-15,4271.2001953125,4362.0,4269.10009765625,4328.0,1666
2026-06-16,4309.5,4345.7998046875,4309.5,4330.89990234375,1666
2026-06-17,4352.60009765625,4402.7998046875,4335.60009765625,4391.2001953125,74623
2026-06-17,4352.60009765625,4402.7998046875,4335.60009765625,4394.7998046875,76633
1 Date Open High Low Close Volume
502 2026-06-12 4208.2998046875 4225.2998046875 4173.2001953125 4215.0 1167
503 2026-06-15 4271.2001953125 4362.0 4269.10009765625 4328.0 1666
504 2026-06-16 4309.5 4345.7998046875 4309.5 4330.89990234375 1666
505 2026-06-17 4352.60009765625 4402.7998046875 4335.60009765625 4391.2001953125 4394.7998046875 74623 76633

View File

@@ -500,4 +500,4 @@ Date,Open,High,Low,Close,Volume
2026-06-12,25783.359375,26010.310546875,25599.939453125,25888.83984375,10337400000
2026-06-15,26447.23046875,26687.560546875,26438.76953125,26683.939453125,10590270000
2026-06-16,26649.970703125,26788.619140625,26369.390625,26376.33984375,11132830000
2026-06-17,26493.82421875,26511.5546875,26255.1640625,26378.064453125,6450463000
2026-06-17,26493.82421875,26511.5546875,26255.1640625,26412.5859375,6597073000
1 Date Open High Low Close Volume
500 2026-06-12 25783.359375 26010.310546875 25599.939453125 25888.83984375 10337400000
501 2026-06-15 26447.23046875 26687.560546875 26438.76953125 26683.939453125 10590270000
502 2026-06-16 26649.970703125 26788.619140625 26369.390625 26376.33984375 11132830000
503 2026-06-17 26493.82421875 26511.5546875 26255.1640625 26378.064453125 26412.5859375 6450463000 6597073000

View File

@@ -501,4 +501,4 @@ Date,Open,High,Low,Close,Volume
2026-06-12,19.510000228881836,19.850000381469727,17.59000015258789,17.68000030517578,0
2026-06-15,16.780000686645508,16.850000381469727,15.979999542236328,16.200000762939453,0
2026-06-16,16.200000762939453,16.440000534057617,15.770000457763672,16.40999984741211,0
2026-06-17,16.079999923706055,17.079999923706055,16.020000457763672,16.899999618530273,0
2026-06-17,16.079999923706055,17.079999923706055,16.020000457763672,16.84000015258789,0
1 Date Open High Low Close Volume
501 2026-06-12 19.510000228881836 19.850000381469727 17.59000015258789 17.68000030517578 0
502 2026-06-15 16.780000686645508 16.850000381469727 15.979999542236328 16.200000762939453 0
503 2026-06-16 16.200000762939453 16.440000534057617 15.770000457763672 16.40999984741211 0
504 2026-06-17 16.079999923706055 17.079999923706055 16.020000457763672 16.899999618530273 16.84000015258789 0