Khanna, Videh Rakesh Rakesh Claude Sonnet 4.6 commited on
Commit
8dab0cd
·
1 Parent(s): ce2e595

fix: validation history wiped after execute + today's OHLCV fallback

Browse files

prune_validated_snapshots now keeps the last 14 days instead of deleting
all VALIDATED rows — the old behaviour cleared every validated record
immediately after each execute run, leaving the history tab and hit-rate
stat cards empty on the next page load.

For same-day (1D/3D/5D) predictions whose target_date == today, the six
daily OHLCV sources only carry yesterday's close (today's bar is published
hours after session end). Added two extra fallback layers in _fetch_window:
1. _fetch_intraday_window_capped with 15:30 IST cutoff (yfinance 15m bars,
available right after the session)
2. fetch_live_price (NSE→BSE→jugaad→Yahoo chain) for actual_price when
even intraday bars are unavailable

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Files changed (2) hide show
  1. app.py +19 -0
  2. database.py +11 -3
app.py CHANGED
@@ -2309,6 +2309,8 @@ def validation_execute():
2309
  continue
2310
  actionable.append(snap)
2311
 
 
 
2312
  def _fetch_window(snap):
2313
  """Return (snap, window_high, window_low, actual_price) — None prices on failure."""
2314
  timeframe = (snap.get("timeframe") or "").upper()
@@ -2323,6 +2325,23 @@ def validation_execute():
2323
  except ValueError:
2324
  ws = target_date_str
2325
  wh, wl, ap = _fetch_price_window(snap["ticker"], ws, target_date_str)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2326
  return snap, wh, wl, ap
2327
  except Exception as e:
2328
  logging.warning(f"_fetch_window({snap.get('ticker')}): {e}")
 
2309
  continue
2310
  actionable.append(snap)
2311
 
2312
+ today_str = today_ist.isoformat()
2313
+
2314
  def _fetch_window(snap):
2315
  """Return (snap, window_high, window_low, actual_price) — None prices on failure."""
2316
  timeframe = (snap.get("timeframe") or "").upper()
 
2325
  except ValueError:
2326
  ws = target_date_str
2327
  wh, wl, ap = _fetch_price_window(snap["ticker"], ws, target_date_str)
2328
+ # Fallback: for today's target date, all 6 daily OHLCV sources may only
2329
+ # carry yesterday's close (today's bar is published hours after session
2330
+ # end, sometimes not until next morning). Try intraday 15m bars first
2331
+ # (yfinance — only source for sub-daily NSE data), then fall back to
2332
+ # fetch_live_price which has its own NSE→BSE→jugaad→Yahoo chain.
2333
+ if ap is None and target_date_str == today_str:
2334
+ wh, wl, ap = _fetch_intraday_window_capped(
2335
+ snap["ticker"], target_date_str,
2336
+ cutoff_hour=15, cutoff_minute=30,
2337
+ )
2338
+ if ap is None:
2339
+ from data_sources import fetch_live_price
2340
+ live = fetch_live_price(snap["ticker"], allow_delayed=True)
2341
+ if live and live > 0:
2342
+ ap = live
2343
+ wh = wh if wh is not None else live
2344
+ wl = wl if wl is not None else live
2345
  return snap, wh, wl, ap
2346
  except Exception as e:
2347
  logging.warning(f"_fetch_window({snap.get('ticker')}): {e}")
database.py CHANGED
@@ -1033,11 +1033,19 @@ def get_validation_history(timeframe: Optional[str] = None, limit: int = 100) ->
1033
  return [dict(r) for r in rows]
1034
 
1035
 
1036
- def prune_validated_snapshots() -> int:
1037
- """Delete all VALIDATED prediction_snapshots. Called after learnings.json is written."""
 
 
 
 
 
1038
  with _conn() as conn:
1039
  cur = conn.execute(
1040
- "DELETE FROM prediction_snapshots WHERE validation_status = 'VALIDATED'"
 
 
 
1041
  )
1042
  return cur.rowcount
1043
 
 
1033
  return [dict(r) for r in rows]
1034
 
1035
 
1036
+ def prune_validated_snapshots(keep_days: int = 14) -> int:
1037
+ """Delete VALIDATED prediction_snapshots older than keep_days.
1038
+
1039
+ Keeps recent validations in the DB so the history tab and hit-rate stat cards
1040
+ remain populated after a validation run. Self-learning already captures the
1041
+ key insights in learnings.json, so the older rows are safe to remove.
1042
+ """
1043
  with _conn() as conn:
1044
  cur = conn.execute(
1045
+ "DELETE FROM prediction_snapshots "
1046
+ "WHERE validation_status = 'VALIDATED' "
1047
+ "AND datetime(validated_at) < datetime('now', ?)",
1048
+ (f"-{int(keep_days)} days",),
1049
  )
1050
  return cur.rowcount
1051