{
  "markdown": "# Triptych\n\n**Triptych** is a local-first factor-timing dashboard for cross-country equity analysis. It turns the multi-sheet `T2 Master.xlsx` workbook (58 factor sheets × 34 markets × monthly since 2000) into an interactive web app, packaged as a clickable macOS application with automatic data refresh.\n\n## What it does\n\nTwo views in one app:\n\n1. **Triptych Deep-Dive** — the core workflow. For one factor and one market:\n   - **Top panel**: the factor signal (raw, expanding z-score vs own history, or cross-sectional z vs peers)\n   - **Middle panel**: cumulative return (absolute, or relative to the all-country average), rebased at the start of the selected window; x-axis aligned with the top panel, with a synchronized crosshair\n   - **Bottom panel**: average N-month forward return by signal bucket (deciles/quintiles/terciles), current bucket highlighted\n   - **Cross-Market Snapshot**: every market's *current* bucket for the selected factor vs its own history\n   - **Bucket statistics table**: observations, average/median forward return, hit rate, best/worst, overlap-adjusted t-stats, top-minus-bottom spread\n   - **Bucket × Horizon matrix**: average forward return heatmap across 1/3/6/12/24/36-month horizons, with the Spearman IC per horizon\n   - **Headline stat cards**: latest signal, current bucket, bucket average forward return, hit rate, IC\n   - **Exports**: tables → xlsx, charts → PDF\n\n2. **Factor Visualizer** — a multi-series charting workbench: any combination of sheets and markets, five axis modes, command-style queries (\"India Trailing PE\"), per-series visibility manager, undo, shareable URLs.\n\n### Methodology notes\n- Bucket thresholds come in two modes: **Full-sample** (descriptive; uses the entire history, so it has look-ahead) and **Point-in-time** (expanding thresholds with a 36-month warm-up; an honest backtest).\n- t-stats and the IC t-stat use an effective sample size of n / horizon to adjust for overlapping forward returns.\n- Forward returns use nearest-date matching (±15 days) so month-start vs month-end grids both work.\n\n## Repository layout\n\n```text\n.\n├── README.md                      # This file\n├── Triptych.app/                  # macOS launcher bundle (gitignored; rebuild with gen_icon.py + the files below)\n└── app/\n    ├── triptych.html              # App shell (both tabs)\n    ├── index.html                 # Redirect to triptych.html\n    ├── README.md                  # App-level usage documentation\n    ├── docs/PROGRAM.md            # Technical architecture reference\n    ├── assets/\n    │   ├── triptych.js            # Deep-Dive tab logic (analytics, charts, refresh, exports)\n    │   ├── app.js                 # Visualizer tab logic\n    │   ├── triptych.css           # Light-mode stylesheet (both tabs)\n    │   ├── styles.css             # (legacy, unused by triptych.html)\n    │   ├── favicon.svg            # Browser tab icon\n    │   ├── icon-1024.png          # Master app icon image\n    │   └── vendor/                # Chart.js, SheetJS, jsPDF (offline, no CDN)\n    ├── scripts/\n    │   ├── extract_t2_master.py   # Excel → columnar JSON (format v2)\n    │   ├── serve_triptych.py      # Local server + /api/status + /api/refresh\n    │   └── gen_icon.py            # Regenerates the .icns app icon\n    └── data/\n        ├── t2_master.json         # Generated dataset (compact columnar JSON)\n        └── backups/               # Timestamped gzipped backups (auto, keeps 10)\n```\n\n## How to launch\n\n**Double-click `Triptych.app`** (at the repo root). It:\n1. Starts the local server (`serve_triptych.py --port 8123 --auto-refresh`) if not already running\n2. If the source workbook is newer than the dataset, re-extracts it in the background (the UI shows \"Refreshing dataset…\" and reloads when done)\n3. Opens the UI in a chromeless Google Chrome app window\n\nServer logs go to `~/Library/Logs/Triptych.log`.\n\n### Manual launch (terminal)\n\n```bash\ncd \"/Users/arjundivecha/Dropbox/AAA Backup/A Working/Triptych/app/scripts\"\npython3 serve_triptych.py --auto-refresh\n# open http://127.0.0.1:8123/triptych.html\n```\n\n## Data pipeline\n\n- **Source workbook**: `/Users/arjundivecha/Dropbox/AAA Backup/A Complete/T2 Factor Timing Fuzzy/T2 Master.xlsx`\n  (row 1 = country headers, column A = dates, one sheet per factor)\n- **Extractor**: `app/scripts/extract_t2_master.py` → `app/data/t2_master.json` (columnar format v2, ~6 MB; ~1.6 s)\n- **Refresh paths** (all run the same extract):\n  1. Auto on launch — `--auto-refresh` compares the workbook mtime to the dataset's recorded `source_mtime`\n  2. The **Refresh Data** button in the UI header (POST `/api/refresh`)\n  3. Manually: `python3 app/scripts/extract_t2_master.py`\n- Every refresh first writes a gzipped, timestamped backup of the previous JSON to `app/data/backups/` (10 most recent kept) and replaces the dataset atomically.\n- The header chip shows the data vintage (\"Data through … · extracted …\") and warns when the source workbook is newer.\n\n## Requirements\n\n- macOS with Google Chrome (falls back to the default browser with a notice)\n- python3 with `openpyxl` (the launcher checks homebrew, /usr/local, and system python and fails loudly if none has it)\n- No other dependencies; all JS libraries are vendored locally and the app works offline\n\n## Related repositories\n\n- **Asado** (`/Users/arjundivecha/Dropbox/AAA Backup/A Working/Asado`) — the data platform whose monthly/daily pipelines update T2 workbooks. Its refresh architecture (status endpoint, timestamped backups, stdlib HTTP server) is the model for Triptych's updater.\n",
  "bytes": 5556,
  "sha": "e3c64c33b46f5cd5dce8400af4cc296e9c7661bfc077cb3dbf90f657654744b2",
  "repo_slug": "arjundivecha/triptych",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/okf_arjundivecha_triptych_openwiki_index_md_3ffcc00b/readme"
}