Spaces:
Sleeping
Sleeping
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 filesprune_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>
- app.py +19 -0
- 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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1038 |
with _conn() as conn:
|
| 1039 |
cur = conn.execute(
|
| 1040 |
-
"DELETE FROM prediction_snapshots
|
|
|
|
|
|
|
|
|
|
| 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 |
|