{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "# Fundamentals meet a scored prediction panel\n### Join point-in-time factors to realised forward returns — honestly\n\nThe same API also serves our **resolved signal panel**: every prediction our models ever published, timestamped before the outcome, scored win **and** loss. That makes it a ready-made panel of *realised forward returns* to test factors against.\n\n*Runs as-is on the `demo` key (signals are ~90-day-delayed on free — they're history, not tips).*"
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": "import json, urllib.request, urllib.parse\n\nBASE = \"https://www.tradingagentapp.com/api/v1\"\nKEY = \"demo\"  # public demo key: 25 flagship tickers, FULL fields & history, no signup\n             # paid keys unlock every ticker -> https://www.tradingagentapp.com/fundamentals\n\ndef api(path, **params):\n    qs = urllib.parse.urlencode({k: v for k, v in params.items() if v is not None})\n    req = urllib.request.Request(f\"{BASE}{path}?{qs}\",\n                                 headers={\"Authorization\": f\"Bearer {KEY}\"})\n    with urllib.request.urlopen(req, timeout=60) as r:\n        return json.loads(r.read().decode())\n\nprint(\"ready — or `pip install pit-fundamentals` for the packaged client\")"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## 1 · A tiny cross-section: ROE (known at the time) vs realised return"
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": "TICKERS = [\"AAPL\", \"MSFT\", \"NVDA\", \"JPM\", \"V\", \"WMT\", \"XOM\", \"PG\", \"KO\", \"COST\"]\n\npanel = api(\"/signals\", market=\"US\", horizon=\"7d\", limit=5000)[\"data\"]\npanel = [p for p in panel if p[\"ticker\"] in TICKERS and p.get(\"actual_pct\") is not None]\nprint(f\"{len(panel)} resolved observations across {len(set(p['ticker'] for p in panel))} tickers\")"
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": "pairs = []\ncache = {}\nfor p in panel[:400]:  # keep the demo quick\n    t, d = p[\"ticker\"], p[\"date\"][:10]\n    if (t, d[:7]) not in cache:  # one PIT snapshot per ticker-month is plenty here\n        cache[(t, d[:7])] = api(\"/fundamentals\", ticker=t, as_of=d, view=\"latest\")[\"data\"]\n    roe = cache[(t, d[:7])].get(\"roe\")\n    if roe:\n        pairs.append((roe[\"value\"], p[\"actual_pct\"]))\nprint(f\"{len(pairs)} (ROE_as_of, realised_return) pairs — zero look-ahead by construction\")"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## 2 · Is there anything there? (rank correlation, no libraries)"
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": "def rank(xs):\n    order = sorted(range(len(xs)), key=lambda i: xs[i])\n    r = [0.0] * len(xs)\n    for pos, i in enumerate(order):\n        r[i] = pos\n    return r\n\na = rank([p[0] for p in pairs]); b = rank([p[1] for p in pairs])\nn = len(a)\nma, mb = sum(a)/n, sum(b)/n\ncov = sum((x-ma)*(y-mb) for x, y in zip(a, b))\nsa = (sum((x-ma)**2 for x in a))**0.5; sb = (sum((y-mb)**2 for y in b))**0.5\nrho = cov/(sa*sb) if sa and sb else float(\"nan\")\nprint(f\"Spearman rho (ROE -> next-7d realised return): {rho:+.3f}  (n={n})\")\nprint(\"10 mega-caps is a toy universe — the POINT is the plumbing: PIT factor,\")\nprint(\"timestamped outcome, zero leakage. Scale it with the full universe.\")"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": "## 3 · Why this panel is unusual\nMost vendors sell you *inputs* and leave outcomes to you. This panel is **pre-registered history**: predictions were published and timestamped *before* resolution, losses included (blended accuracy is near a coin flip, and we publish that too — it's a dataset, not a promise).\n\n---\nFull universe + bulk files → <https://www.tradingagentapp.com/fundamentals> · field docs → <https://www.tradingagentapp.com/developers>"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}