Spaces:
Running
Running
Upload runtime.py
Browse files- runtime.py +85 -6
runtime.py
CHANGED
|
@@ -664,6 +664,21 @@ def _archive_tomorrow_latest_to_history() -> None:
|
|
| 664 |
pass
|
| 665 |
|
| 666 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 667 |
def _find_tomorrow_prediction_for_target(target_day: date) -> dict[str, Any] | None:
|
| 668 |
"""Return the Tomorrow prediction that targets ``target_day``."""
|
| 669 |
target_iso = target_day.isoformat()
|
|
@@ -1307,13 +1322,19 @@ def build_prediction_track_record(
|
|
| 1307 |
{"source": entry.get("source", "live")},
|
| 1308 |
)
|
| 1309 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1310 |
records: list[dict[str, Any]] = []
|
| 1311 |
for _, row in daily_rows.tail(20).iterrows():
|
| 1312 |
day = row["date"].date().isoformat()
|
| 1313 |
-
day_open = float(row["open"])
|
| 1314 |
day_close = float(row["close"])
|
| 1315 |
-
actual_move = (
|
| 1316 |
-
|
|
|
|
| 1317 |
pred = predictions_by_date.get(day)
|
| 1318 |
prediction = pred.get("prediction") if pred else None
|
| 1319 |
if prediction is None:
|
|
@@ -1622,6 +1643,43 @@ def _record_prediction_history(path: Path, row: dict[str, Any], subset: list[str
|
|
| 1622 |
append_prediction_history(path, row, subset)
|
| 1623 |
|
| 1624 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1625 |
def ensure_completed_sessions_scored(
|
| 1626 |
now: datetime | None = None,
|
| 1627 |
ledger: dict[str, Any] | None = None,
|
|
@@ -1633,6 +1691,19 @@ def ensure_completed_sessions_scored(
|
|
| 1633 |
return ledger or load_live_accuracy()
|
| 1634 |
|
| 1635 |
ledger = ledger or load_live_accuracy()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1636 |
logged_tom = {e["date"] for e in ledger.get("tomorrow", {}).get("entries", [])}
|
| 1637 |
if completed.isoformat() in logged_tom:
|
| 1638 |
return ledger
|
|
@@ -1703,12 +1774,18 @@ def update_live_accuracy(session_date: date) -> dict[str, Any]:
|
|
| 1703 |
except Exception:
|
| 1704 |
pass
|
| 1705 |
|
| 1706 |
-
# --- Tomorrow:
|
| 1707 |
logged_tom = {e["date"] for e in ledger["tomorrow"]["entries"]}
|
| 1708 |
if session_iso not in logged_tom:
|
| 1709 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1710 |
tom_row = _find_tomorrow_prediction_for_target(session_date)
|
| 1711 |
-
if tom_row:
|
| 1712 |
try:
|
| 1713 |
pred = str(tom_row.get("prediction", "")).upper()
|
| 1714 |
if pred in ("UP", "DOWN"):
|
|
@@ -1761,6 +1838,8 @@ def update_live_accuracy(session_date: date) -> dict[str, Any]:
|
|
| 1761 |
except Exception:
|
| 1762 |
pass
|
| 1763 |
|
|
|
|
|
|
|
| 1764 |
# Recompute summary stats
|
| 1765 |
for model_id in ("t5", "tomorrow", "tplus1"):
|
| 1766 |
entries = ledger[model_id]["entries"]
|
|
|
|
| 664 |
pass
|
| 665 |
|
| 666 |
|
| 667 |
+
def _tomorrow_actual_outcome(
|
| 668 |
+
target_day: date,
|
| 669 |
+
day_close: float,
|
| 670 |
+
closes_by_date: dict[date, float],
|
| 671 |
+
) -> tuple[float | None, str | None]:
|
| 672 |
+
"""Return (move, direction) for Tomorrow scoring: close vs previous session close."""
|
| 673 |
+
prev_day = previous_trading_day(target_day - timedelta(days=1))
|
| 674 |
+
prev_close = closes_by_date.get(prev_day)
|
| 675 |
+
if prev_close is None or not np.isfinite(prev_close) or prev_close == 0:
|
| 676 |
+
return None, None
|
| 677 |
+
actual_move = (day_close - prev_close) / prev_close
|
| 678 |
+
actual_direction = "UP" if day_close > prev_close else "DOWN"
|
| 679 |
+
return actual_move, actual_direction
|
| 680 |
+
|
| 681 |
+
|
| 682 |
def _find_tomorrow_prediction_for_target(target_day: date) -> dict[str, Any] | None:
|
| 683 |
"""Return the Tomorrow prediction that targets ``target_day``."""
|
| 684 |
target_iso = target_day.isoformat()
|
|
|
|
| 1322 |
{"source": entry.get("source", "live")},
|
| 1323 |
)
|
| 1324 |
|
| 1325 |
+
closes_by_date = {
|
| 1326 |
+
row["date"].date(): float(row["close"])
|
| 1327 |
+
for _, row in daily_rows.iterrows()
|
| 1328 |
+
if pd.notna(row["close"]) and np.isfinite(float(row["close"]))
|
| 1329 |
+
}
|
| 1330 |
+
|
| 1331 |
records: list[dict[str, Any]] = []
|
| 1332 |
for _, row in daily_rows.tail(20).iterrows():
|
| 1333 |
day = row["date"].date().isoformat()
|
|
|
|
| 1334 |
day_close = float(row["close"])
|
| 1335 |
+
actual_move, actual_direction = _tomorrow_actual_outcome(row["date"].date(), day_close, closes_by_date)
|
| 1336 |
+
if actual_direction is None:
|
| 1337 |
+
continue
|
| 1338 |
pred = predictions_by_date.get(day)
|
| 1339 |
prediction = pred.get("prediction") if pred else None
|
| 1340 |
if prediction is None:
|
|
|
|
| 1643 |
append_prediction_history(path, row, subset)
|
| 1644 |
|
| 1645 |
|
| 1646 |
+
def _rescore_tomorrow_live_ledger(ledger: dict[str, Any]) -> bool:
|
| 1647 |
+
"""Fix live Tomorrow ledger entries to use close vs previous close. Returns True if modified."""
|
| 1648 |
+
daily = pd.read_parquet(NIFTY_1D_PATH)
|
| 1649 |
+
daily["_date"] = pd.to_datetime(daily["date"], errors="coerce").dt.normalize()
|
| 1650 |
+
closes_by_date: dict[date, float] = {}
|
| 1651 |
+
for _, row in daily.iterrows():
|
| 1652 |
+
if pd.isna(row["_date"]):
|
| 1653 |
+
continue
|
| 1654 |
+
close = row.get("close")
|
| 1655 |
+
if pd.notna(close) and np.isfinite(float(close)):
|
| 1656 |
+
closes_by_date[row["_date"].date()] = float(close)
|
| 1657 |
+
|
| 1658 |
+
changed = False
|
| 1659 |
+
for entry in ledger.get("tomorrow", {}).get("entries", []):
|
| 1660 |
+
if str(entry.get("source", "backtest")).lower() == "backtest":
|
| 1661 |
+
continue
|
| 1662 |
+
try:
|
| 1663 |
+
day = date.fromisoformat(str(entry.get("date", ""))[:10])
|
| 1664 |
+
except Exception:
|
| 1665 |
+
continue
|
| 1666 |
+
day_close = closes_by_date.get(day)
|
| 1667 |
+
if day_close is None:
|
| 1668 |
+
continue
|
| 1669 |
+
_, actual_direction = _tomorrow_actual_outcome(day, day_close, closes_by_date)
|
| 1670 |
+
if actual_direction is None:
|
| 1671 |
+
continue
|
| 1672 |
+
pred = str(entry.get("prediction", "")).upper()
|
| 1673 |
+
if pred not in {"UP", "DOWN"}:
|
| 1674 |
+
continue
|
| 1675 |
+
new_correct = pred == actual_direction
|
| 1676 |
+
if entry.get("actual") != actual_direction or entry.get("correct") != new_correct:
|
| 1677 |
+
entry["actual"] = actual_direction
|
| 1678 |
+
entry["correct"] = new_correct
|
| 1679 |
+
changed = True
|
| 1680 |
+
return changed
|
| 1681 |
+
|
| 1682 |
+
|
| 1683 |
def ensure_completed_sessions_scored(
|
| 1684 |
now: datetime | None = None,
|
| 1685 |
ledger: dict[str, Any] | None = None,
|
|
|
|
| 1691 |
return ledger or load_live_accuracy()
|
| 1692 |
|
| 1693 |
ledger = ledger or load_live_accuracy()
|
| 1694 |
+
if _rescore_tomorrow_live_ledger(ledger):
|
| 1695 |
+
for model_id in ("tomorrow",):
|
| 1696 |
+
entries = ledger[model_id]["entries"]
|
| 1697 |
+
total = len(entries)
|
| 1698 |
+
correct = sum(1 for e in entries if e.get("correct"))
|
| 1699 |
+
backtest_count = sum(1 for e in entries if str(e.get("source", "backtest")).lower() == "backtest")
|
| 1700 |
+
ledger[model_id]["total"] = total
|
| 1701 |
+
ledger[model_id]["correct_count"] = correct
|
| 1702 |
+
ledger[model_id]["backtest_count"] = backtest_count
|
| 1703 |
+
ledger[model_id]["live_count"] = total - backtest_count
|
| 1704 |
+
ledger[model_id]["accuracy"] = correct / total if total > 0 else None
|
| 1705 |
+
save_live_accuracy(ledger)
|
| 1706 |
+
clear_dashboard_payload_cache()
|
| 1707 |
logged_tom = {e["date"] for e in ledger.get("tomorrow", {}).get("entries", [])}
|
| 1708 |
if completed.isoformat() in logged_tom:
|
| 1709 |
return ledger
|
|
|
|
| 1774 |
except Exception:
|
| 1775 |
pass
|
| 1776 |
|
| 1777 |
+
# --- Tomorrow: prior close vs today's close (matches forecaster target) ---
|
| 1778 |
logged_tom = {e["date"] for e in ledger["tomorrow"]["entries"]}
|
| 1779 |
if session_iso not in logged_tom:
|
| 1780 |
+
prev_day = previous_trading_day(session_date - timedelta(days=1))
|
| 1781 |
+
prev_rows = daily[daily["_date"].dt.date == prev_day]
|
| 1782 |
+
actual_tomorrow = None
|
| 1783 |
+
if not prev_rows.empty:
|
| 1784 |
+
prev_close = float(prev_rows.iloc[-1]["close"])
|
| 1785 |
+
if np.isfinite(prev_close) and prev_close != 0:
|
| 1786 |
+
actual_tomorrow = "UP" if day_close > prev_close else "DOWN"
|
| 1787 |
tom_row = _find_tomorrow_prediction_for_target(session_date)
|
| 1788 |
+
if tom_row and actual_tomorrow is not None:
|
| 1789 |
try:
|
| 1790 |
pred = str(tom_row.get("prediction", "")).upper()
|
| 1791 |
if pred in ("UP", "DOWN"):
|
|
|
|
| 1838 |
except Exception:
|
| 1839 |
pass
|
| 1840 |
|
| 1841 |
+
_rescore_tomorrow_live_ledger(ledger)
|
| 1842 |
+
|
| 1843 |
# Recompute summary stats
|
| 1844 |
for model_id in ("t5", "tomorrow", "tplus1"):
|
| 1845 |
entries = ledger[model_id]["entries"]
|