M

MarketFish

Méthodologie

Méthodologie du Track Record public

Ce document explique exactement comment chaque chiffre est calculé. Aucun secret, aucun arrondi favorable, aucun cherry-picking. Si tu trouves une erreur ou un biais dans ce texte, dis-le : on corrigera et on documentera la correction.

1. Comment les scénarios sont émis

Chaque jour ouvré (lundi→vendredi) à 07:00 UTC, un cron job sur notre VPS exécute scripts/emit_daily_scenarios.py --mode assets. Ce script :

Modèle ML

LogisticRegression (lbfgs) + CalibratedClassifierCV (Platt scaling, cv=3)
Features : 25 colonnes (9 MQ-equivalent + 7 geometry + 6 OHLC technique + 4 asset one-hot)
Training : TimeSeriesSplit 5-fold sur 128 sessions historiques (février→avril 2026)
Out-of-fold metrics : hit_top 58.6%, hit_any 88.3%, Brier 0.169

2. Comment une session est résolue

À chaque session, on attend la close US réelle. Le script score_session.py pull l'OHLC du jour via yfinance, puis pour chaque scénario émis calcule s'il a "joué" :

Un scénario peut jouer ou ne pas jouer — c'est binaire. Les flags played_A, played_B, played_C sont écrits dans la table session_outcomes après résolution. top_played = 1 si le scénario avec la plus forte probabilité est celui qui a joué, 0 sinon.

3. Les métriques calculées

Hit rate (top scénario)

hit_top = count(top_played == 1) / count(sessions résolues)

C'est la métrique la plus intuitive. Sur N sessions, combien de fois notre scénario le plus probable a-t-il joué ? Baseline aléatoire sur 3 scénarios ≈ 33%. Nous visons > 52%.

Hit rate (any scénario)

hit_any = count(played_A ∨ played_B ∨ played_C) / count(sessions)

Combien de fois au moins l'un de nos 3 scénarios a-t-il joué. Mesure la couverture : si hit_any est proche de 100%, nos 3 scénarios englobent correctement l'espace des possibilités. Cible : > 85%.

Brier score (multi-classe)

brier(session) = (pA − yA)² + (pB − yB)² + (pC − yC)²
où yX = 1 si le scénario X a joué, 0 sinon.
brier_mean = moyenne sur les sessions résolues.

Mesure de l'erreur quadratique des probabilités. Plus bas = mieux. Baseline aléatoire (1/3 partout) ≈ 0.667. Baseline "toujours miser sur A" ≈ 0.5. Un moteur calibré vise < 0.22.

Log-loss

log_loss(session) = −log(p_played)
où p_played est la probabilité annoncée du scénario qui a effectivement joué.
log_loss_mean = moyenne sur les sessions.

Pénalise plus fortement les prédictions très confiantes mais fausses. Baseline aléatoire ≈ 1.098. Un bon moteur est sous 0.9.

Courbe de calibration

On empile toutes les prédictions (3 par session × N sessions) et on les répartit en 10 tranches de probabilité [0-10%, 10-20%, …, 90-100%]. Pour chaque tranche :

predicted_mean = moyenne des probabilités annoncées dans la tranche
actual_frequency = fraction des scénarios de cette tranche qui ont joué
n = nombre de points dans la tranche

Si le moteur est parfaitement calibré, actual_frequency ≈ predicted_mean dans chaque tranche (points alignés sur la diagonale). Un point à (0.6, 0.4) signifie que "quand on a dit 60%, ça s'est produit seulement 40% du temps" — le moteur est sur-confiant sur cette plage.

4. Fenêtres temporelles

Les cinq fenêtres publiées :

5. Ce qui N'EST PAS mesuré

Honnêteté intellectuelle : cette méthodologie mesure la qualité prédictive brute du moteur de scénarios. Elle ne mesure PAS :

6. Anti-cherry-picking

Append-only. La table scenario_emissions a une contrainte d'unicité (session_date, asset). Une émission peut être ré-écrite uniquement avant résolution. Après résolution, toute tentative de ré-écriture lève une exception.

CSV public. Tu peux télécharger le ledger complet en CSV brut et refaire tous les calculs toi-même. Si nos chiffres diffèrent, signale-nous le bug — on corrigera publiquement.

Horodatage UTC. Toutes les dates sont en UTC pour éviter la tentation des "fenêtres glissantes avantageuses".

7. Limites connues

8. Historique des changements méthodologiques

Chaque modification de la méthodologie est datée publiquement et, si elle affecte la comparabilité des résultats, le ledger est reset pour éviter de mélanger deux régimes de mesure. Aucune session n'est supprimée silencieusement : les ledgers archivés restent disponibles sur demande.

Dernière mise à jour du document : 2026-04-20. Source du code de scoring : scripts/score_session.py et engine/live/track_record.py.