SPB Git forge

spb/hfmarketdata

Public

Open high-frequency market data platform — FirstRate full-history downloader, DuckDB/Parquet lake, open REST API and React docs platform (www.hfmarketdata.io)

127commits 1branches 0releases
24.7 MBsize
maindefault branch
11 days agolast push
JavaScript 53.7% Python 38.3% CSS 4.6% TypeScript 3.1%
5.8 KB · 21 lines markdown
Rendered Raw Blame History
1# hfmarketdata — conventions de travail (lues par tous les agents)23Plateforme : **www.hfmarketdata.io** — API FastAPI + DuckDB sur un lac Parquet (350 Go, FirstRate Data), site React/Vite servi par l'API. Plan complet : `docs/UPGRADE-PLAN.md` (lire en premier). Prod (**depuis le 2026-09-14**) : serveur OVH **BHS128** (`ssh BHS128`, ubuntu@51.161.112.69, Ubuntu 24.04, 12 threads / 128 Go) — `~/hfmarketdata` (venv **Python 3.14 via uv**, versions épinglées dans `requirements-prod-freeze.txt`), lac `~/firstratedata` (359 Go Parquet + `state/hfmd.db` + `edgar/`), Redis natif, PM2 sous systemd (`pm2-ubuntu`) avec `~/apps/pm2.hfmarketdata.config.cjs` généré depuis le manifeste mld par `~/apps/.manifests/gen-pm2.py` : `hfmarketdata-api` (uvicorn :8090, 2 workers), `edgar-incremental`, crons `frd-refresh` (lun 03:00), `contracts-backfill` (04:30), `edgar-reconcile` (dim 06:00) ; `edgar-backfill` et `rowgroups` à la main (`pm2 start … --only`). Route publique : BHS64 Caddy → wg1 10.67.0.60:8090 (`mlt add www.hfmarketdata.io BHS128:8090`), ufw ouvert sur wg1 depuis 10.67.0.1. **Hors `mld`** (retirée du registre ; l'ancienne copie M3U96b `~/hfmarketdata` + `~/firstratedata` + Redis a été **effacée le 2026-09-14** — BHS128 détient la seule copie du lac et de `state/hfmd.db` : prévoir une sauvegarde hors serveur ; manifeste mld sauvegardé sur le laptop `~/Desktop/Cluster/secrets/mld-manifests-retired-20260914/hfmarketdata.json`). Release : `rsync -a --exclude venv --exclude .git --exclude 'hfmarketdata/web/node_modules' --exclude 'hfmarketdata/web/dist' --exclude mcp/node_modules . BHS128:hfmarketdata/` puis `ssh BHS128 'cd hfmarketdata && ~/.local/bin/uv pip install --python venv/bin/python -r hfmarketdata/requirements.txt && (cd hfmarketdata/web && npm ci && npm run build) && pm2 restart hfmarketdata-api hfmarketdata-edgar-incremental && pm2 save'`. Dépôt de vérité : spbgit `gitsrv:srv/git/hfmarketdata.git` (branche `main`).45## Règles absolues6- **Aucun breaking change** : les endpoints `/v1/*` existants (main.py) gardent paths, paramètres, formes de réponse (`{"count","data"}`) et codes. Tout le neuf est additif sous `/v1/`.7- **Erreurs** : lever `core.errors.ApiError(status, CODE, message, type=…, details=…)` ; les codes vivent dans `core/errors.py::CODES` (en ajouter si besoin, jamais de code inconnu). Jamais de `HTTPException` dans le code v2.8- **Réponses v2** : `core.responses.frame_response(df, fmt, meta=…, request=…)` pour les tableaux (json/csv/parquet, enveloppe `{"data","meta"}`, `X-Row-Count`), `json_response(...)` pour le reste, `clamp_limit(...)` pour `limit`, curseurs via `encode_cursor/decode_cursor`. Timestamps UTC ISO 8601.9- **Données** : DuckDB via `core.duck.con()` (connexion par thread) + `core.duck.cached(key, builder)` pour les scans de répertoires. `settings.parquet` = racine du lac. **Jamais de valeur inventée** : absence → `null` + raison dans `coverage`.10- **Métadonnées** : SQLite via `core.db` (`Base`, `session()`, `get_session` dépendance FastAPI, `create_all()` idempotent au démarrage du module). Un module = un fichier `models.py`.11- **Config** : uniquement `core.config.settings` (variables `HFMD_*`). Secrets jamais en dur, jamais dans les exemples publics.12- **Structure** : `hfmarketdata/api/<module>/{routes.py,models.py,service.py,…}` ; `routes.py` expose `router` (APIRouter avec `prefix="/v1/…"`, `tags=[…]`) OU `install(app)` (middleware). `main.py` charge les modules listés dans `V2_MODULES` — ne pas éditer main.py au-delà de cette liste. Imports absolus depuis `hfmarketdata/api` (ex. `from core.errors import ApiError`).13- **Quota lignes** : toujours poser `X-Row-Count` (fait par `frame_response`). Endpoints coûteux : `request.state.request_cost = 2` (screener, frames). Bulk : `request.state.quota_exempt = True`.14- **Style** : Python 3.12+ typé, docstrings en anglais (le produit est en anglais), commentaires courts. Frontend : React 18 + Vite, dark par défaut, pas de framework CSS lourd (CSS modules / variables), composants dans `hfmarketdata/web/src`.15- **Tests** : pytest dans `tests/` (`pytest.ini` met `hfmarketdata/api` sur le path) ; lac synthétique `tests/fixtures/make_fixtures.py` (l'étendre si un module a besoin d'autres fichiers) ; Redis = `fakeredis` quand `HFMD_REDIS_URL=fakeredis://`. Chaque module livre ses tests unitaires + intégration (TestClient). `./.venv/bin/python -m pytest` doit rester vert.16- **OpenAPI 3.1** : chaque route a `summary`, `description` (markdown), `response_model` ou `responses={…}` avec exemples réels, et déclare ses erreurs possibles via `openapi_extra={"x-errors": ["CONTRACT_NOT_FOUND", …]}`. La doc du site est générée depuis `/openapi.json` : la qualité des descriptions EST la doc.17- **Git** : commits atomiques en français, préfixe du chantier (`futures:`, `accounts:`, `ratelimit:`, `fundamentals:`, `web:`, `mcp:`, `docs:`). Ne pas committer `.venv`, `node_modules`, `dist`, données.1819## Données réelles (référence, pas pour les tests)20Layout : `parquet/{stock|etf|crypto|index|fx}/{1min|5min|30min|1hour|1day}/{adj}/{TICKER}_{tf}.parquet` · `parquet/futures/{tf}/{contin_UNadj|contin_adj_ratio|contin_adj_absolute}/{ROOT}_{tf}.parquet` · `parquet/futures_contracts/{tf}/{archive|update}/{ROOT}_{MonthCode}{YY}_{tf}.parquet` (142 racines, ~15 000 contrats/tf, la colonne `ticker` = racine ; archive ≤ 2025, update ≥ 2025 avec chevauchement → dédupliquer sur `datetime`, priorité update) · `parquet/options/{yyyy}_{qN}/{TICKER}_month_option_chain.parquet` · `meta/futures/futures.csv` (Ticker, Name, First Date, Last Date). Colonnes barres : ticker, datetime (TIMESTAMP naïf, heure US/Eastern pour l'intraday), open, high, low, close, volume, open_interest (futures 1day). API publique pour vérifier : `https://www.hfmarketdata.io/v1/status`. Accès au nœud si indispensable : `ssh M3U96b` (lecture seule sur `~/firstratedata`).21