ifieryarrows commited on
Commit
622298f
Β·
verified Β·
1 Parent(s): a2401cb

Sync from GitHub (tests passed)

Browse files
Files changed (1) hide show
  1. deep_learning/models/tft_copper.py +12 -39
deep_learning/models/tft_copper.py CHANGED
@@ -262,44 +262,17 @@ def format_prediction(
262
  baseline_price,
263
  )
264
 
265
- # Two-stage magnitude control:
266
- # Stage 1 – Soft dampening: smoothly attenuates returns that exceed a
267
- # "comfort zone" (β‰ˆ 1 daily Οƒ for copper). Within the zone the raw
268
- # model output passes through unchanged, preserving the model's edge
269
- # on small moves. Beyond the zone, excess magnitude is compressed with
270
- # a square-root taper so direction and rank order are maintained but
271
- # extreme outliers are pulled toward more realistic levels.
272
- # This is intentionally looser than XGBoost's direct clamp; TFT's
273
- # quantile structure already captures uncertainty.
274
- # Stage 2 – Hard clamp: absolute backstop at Β±3 % (β‰ˆ1.25 Γ— actual daily Οƒ).
275
- # Only activates on genuinely runaway predictions (model VR >> 1).
276
- _SOFT_ZONE = 0.010 # pass-through zone: Β±1 % unchanged
277
- _SOFT_MAX = 0.020 # compress between 1 % and 2 %; beyond β†’ stage 2
278
- _MAX_DAILY_RET = 0.030 # hard clamp backstop
279
-
280
- def _dampen(r: float) -> float:
281
- """Soft-then-hard attenuation of daily return r."""
282
- sign = 1.0 if r >= 0 else -1.0
283
- abs_r = abs(r)
284
- if abs_r <= _SOFT_ZONE: # pass-through zone
285
- return r
286
- if abs_r <= _SOFT_MAX: # soft zone: linear taper to 70 %
287
- # interpolate attenuation from 100 % β†’ 70 % as abs_r goes from
288
- # _SOFT_ZONE to _SOFT_MAX
289
- t = (abs_r - _SOFT_ZONE) / (_SOFT_MAX - _SOFT_ZONE) # 0 β†’ 1
290
- scale = 1.0 - 0.30 * t
291
- return sign * abs_r * scale
292
- if abs_r <= _MAX_DAILY_RET: # extended zone: sqrt compression
293
- # At _SOFT_MAX the value is 70 % of _SOFT_MAX.
294
- # Beyond that, sqrt-taper ensures diminishing returns.
295
- base = _SOFT_MAX * 0.70
296
- excess = abs_r - _SOFT_MAX
297
- budget = _MAX_DAILY_RET - _SOFT_MAX
298
- compressed = base + excess ** 0.5 * budget ** 0.5 * 0.5
299
- return sign * min(compressed, _MAX_DAILY_RET)
300
- return sign * _MAX_DAILY_RET # hard clamp backstop
301
-
302
- med_0 = _dampen(float(pred[0, median_idx]))
303
  _raw_med_0 = float(pred[0, median_idx])
304
  spread_q10 = np.clip(float(pred[0, 1]) - _raw_med_0, -_MAX_DAILY_RET, 0) if len(quantiles) > 2 else 0.0
305
  spread_q90 = np.clip(float(pred[0, -2]) - _raw_med_0, 0, _MAX_DAILY_RET) if len(quantiles) > 2 else 0.0
@@ -310,7 +283,7 @@ def format_prediction(
310
  cum_price_med = baseline_price
311
 
312
  for d in range(n_days):
313
- med = _dampen(float(pred[d, median_idx]))
314
  cum_price_med *= (1 + med)
315
  cum_return = (cum_price_med / baseline_price) - 1.0
316
 
 
262
  baseline_price,
263
  )
264
 
265
+ # Hard clamp: prevents overconfident models (VR >> 1) from producing
266
+ # absurd compound prices. Copper's actual daily Οƒ β‰ˆ 0.024; capping at
267
+ # ~1.25Οƒ keeps the 5-day compound under β‰ˆ16 %. The clamp is inactive
268
+ # once the model is retrained with a healthy VR (0.5–1.5).
269
+ _MAX_DAILY_RET = 0.03
270
+
271
+ # T+1 quantile spreads (return-space distance from median).
272
+ # Used as the base width for confidence bands; scaled by sqrt(d) for
273
+ # later days so uncertainty grows realistically instead of compounding
274
+ # tail quantiles exponentially (which would produce absurd bands).
275
+ med_0 = float(np.clip(pred[0, median_idx], -_MAX_DAILY_RET, _MAX_DAILY_RET))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
  _raw_med_0 = float(pred[0, median_idx])
277
  spread_q10 = np.clip(float(pred[0, 1]) - _raw_med_0, -_MAX_DAILY_RET, 0) if len(quantiles) > 2 else 0.0
278
  spread_q90 = np.clip(float(pred[0, -2]) - _raw_med_0, 0, _MAX_DAILY_RET) if len(quantiles) > 2 else 0.0
 
283
  cum_price_med = baseline_price
284
 
285
  for d in range(n_days):
286
+ med = float(np.clip(pred[d, median_idx], -_MAX_DAILY_RET, _MAX_DAILY_RET))
287
  cum_price_med *= (1 + med)
288
  cum_return = (cum_price_med / baseline_price) - 1.0
289