Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@
"source": [
"### Calcul des Returns\n",
"\n",
"Calculons les returns journaliers et cumulatifs. Deux lignes pandas : `pct_change()` pour le return journalier, puis le cumulatif par produit (`(1 + r).cumprod()`) -- la composition geometrique, qui repond a \"que vaut 1 dollar investi au depart ?\". La sortie affiche les dernieres lignes : un cumulatif final autour de 1.24, soit +24 % sur l'annee. A noter dans cette meme sortie : le `SettingWithCopyWarning` de pandas -- `df_spy` est une vue extraite par `.loc`, et pandas rappelle qu'ecrire dedans peut ne pas faire ce qu'on croit ; le notebook vit avec (les ecritures passent), mais le pattern propre serait `.copy()` a l'extraction. Ce warning ressortira a chaque ajout de colonne -- le reconnaitre vaut mieux que le craindre.\n"
"Calculons les returns journaliers et cumulatifs : `pct_change()` pour le return journalier, puis le cumulatif par produit (`(1 + r).cumprod()`) -- la composition geometrique, qui repond a \"que vaut 1 dollar investi au depart ?\". La sortie affiche les dernieres lignes : un cumulatif final autour de 1.24, soit +24 % sur l'annee. A noter dans cette meme sortie : le `SettingWithCopyWarning` de pandas -- `df_spy` est une vue extraite par `.loc`, et pandas rappelle qu'ecrire dedans peut ne pas faire ce qu'on croit ; le notebook vit avec (les ecritures passent), mais le pattern propre serait `.copy()` a l'extraction. Ce warning ressortira a chaque ajout de colonne -- le reconnaitre vaut mieux que le craindre.\n"
]
},
{
Expand Down Expand Up @@ -813,7 +813,7 @@
"source": [
"### Generation des Signaux\n",
"\n",
"Generons les signaux de trading bases sur le croisement. La regle SMA est d'une ligne pandas : signal = 1 quand `sma_50 > sma_200` (golden cross, tendance haussiere), 0 sinon (death cross). La sortie montrera les dernieres lignes -- signal constant a 1 et position 1.0 en fin de periode, la tendance etant restee haussiere. La **position** est une colonne distincte du signal, et le `.shift(1)` entre les deux n'est pas decoratif : c'est le garde-fou anti-lookahead que la cellule d'apres explique en detail.\n"
"Generons les signaux de trading bases sur le croisement. La regle SMA : signal = 1 quand `sma_50 > sma_200` (golden cross, tendance haussiere), 0 sinon (death cross). La sortie montrera les dernieres lignes -- signal constant a 1 et position 1.0 en fin de periode, la tendance etant restee haussiere. La **position** est une colonne distincte du signal, et le `.shift(1)` entre les deux n'est pas decoratif : c'est le garde-fou anti-lookahead que la cellule d'apres explique en detail.\n"
]
},
{
Expand Down Expand Up @@ -865,7 +865,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"> **Point Crucial** : Le `.shift(1)` sur la position est essentiel pour eviter le **lookahead bias** -- le defaut qui fait paraitre bonne une strategie qui ne l'est pas. L'erreur a eviter : calculer le return du jour avec le signal decide **sur les donnees du meme jour** -- or le signal de fin de jour j (SMA calculees au close de j) ne peut gouverner le return que de j+1. Sans `shift(1)`, chaque croisement capte le retour du jour du croisement, une information que le trader reel n'avait pas encore. C'est LE bug classique du backtest vectorise -- invisible dans le code (une ligne de moins) et massif dans les resultats (des Sharpe fabriques de toutes pieces).\n"
"> **Point Crucial** : Le `.shift(1)` sur la position est essentiel pour eviter le **lookahead bias** -- le defaut qui fait paraitre bonne une strategie qui ne l'est pas. L'erreur a eviter : calculer le return du jour avec le signal decide **sur les donnees du meme jour** -- or le signal de fin de jour j (SMA calculees au close de j) ne peut gouverner le return que de j+1. Sans `shift(1)`, chaque croisement capte le retour du jour du croisement, une information que le trader reel n'avait pas encore. C'est LE bug classique du backtest vectorise -- invisible dans le code et massif dans les resultats (des Sharpe fabriques de toutes pieces).\n"
]
},
{
Expand Down Expand Up @@ -1108,7 +1108,7 @@
"\n",
"### Importer les Helpers\n",
"\n",
"Le repository embarque ses propres helpers standardises (`shared/features.py`, `shared/backtest_helpers.py`) -- le meme code de calcul pour toute la serie, plutot que des reimplementations locales qui divergent. La cellule gere les **deux layouts** : en local, `shared/` est un dossier parent (`sys.path` vers `../shared`) ; sur QC Cloud, le repository est clone a cote (`./shared`). La sortie confirmera `Helpers importes avec succes` -- et les trois fonctions qui suivent (`calculate_returns`, `add_technical_features`, `calculate_metrics`) demontreront le gain : une ligne d'appel pour des calculs qui, faits a la main dans la section 3, ont pris chacun une cellule.\n"
"Le repository embarque ses propres helpers standardises (`shared/features.py`, `shared/backtest_helpers.py`) -- le meme code de calcul pour toute la serie, plutot que des reimplementations locales qui divergent. La cellule gere les **deux layouts** : en local, `shared/` est un dossier parent (`sys.path` vers `../shared`) ; sur QC Cloud, le repository est clone a cote (`./shared`). La sortie confirmera `Helpers importes avec succes` -- et les trois fonctions qui suivent (`calculate_returns`, `add_technical_features`, `calculate_metrics`) demontreront le gain : un simple appel pour des calculs qui, faits a la main dans la section 3, occupaient chacun leur propre cellule.\n"
]
},
{
Expand Down Expand Up @@ -1617,7 +1617,7 @@
"source": [
"### Creer Labels (Classification Binaire)\n",
"\n",
"Creons des labels pour predire la direction du prix. Le label binaire se construit en une ligne conceptuelle : `1` si le return futur a 5 jours est positif, `0` sinon -- la colonne `future_returns_5d` (deja croisee en section 5) devient la cible, pas une feature. La sortie affichera les dernieres lignes du DataFrame labellise, avec les NaN de bord (les 5 derniers jours n'ont pas de futur connu) que le nettoyage suivant retirera. Question a garder en tete pour l'interpretation : la repartition des classes -- un label 90 % positif rend l'accuracy trompeuse (un modele constant \"hausse\" atteint 90 % sans rien predire).\n"
"Creons des labels pour predire la direction du prix. Le label binaire se construit ainsi : `1` si le return futur a 5 jours est positif, `0` sinon -- la colonne `future_returns_5d` (deja croisee en section 5) devient la cible, pas une feature. La sortie affichera les dernieres lignes du DataFrame labellise, avec les NaN de bord (les 5 derniers jours n'ont pas de futur connu) que le nettoyage suivant retirera. Question a garder en tete pour l'interpretation : la repartition des classes -- un label 90 % positif rend l'accuracy trompeuse (un modele constant \"hausse\" atteint 90 % sans rien predire).\n"
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"3. §3 Forex — pips, mini/micro lots, P&L par pip\n",
"5. §5 Stratégie Donchian (Donchian 20/10, off-by-one) — exemple complet\n",
"\n",
"**Exercices** : 3 cellules stub (Exercice #7, #12, #16) :\n",
"**Exercices** : cellules stub (Exercice #7, #12, #16) :\n",
"- **Exercice 1** : sélection personnalisée de contrats Futures\n",
"- **Exercice 2** : stratégie de couverture Forex\n",
"- **Exercice 3** : position size multi-devises\n",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"5. Combinaison Sentiment + Technique (20 min)\n",
"6. Stratégie Complete (20 min)\n",
"\n",
"> **Note de conception** : Ce notebook contient du code de référence à copier dans QuantConnect Lab (main.py) — ces blocs définissent le code QC en chaîne Python. Les cellules d'analyse locale (TextBlob, VADER, simulations) s'exécutent dans le notebook ; seules les 3 cellules d'exercice restent à compléter (stubs étudiant).\n"
"> **Note de conception** : Ce notebook contient du code de référence à copier dans QuantConnect Lab (main.py) — ces blocs définissent le code QC en chaîne Python. Les cellules d'analyse locale (TextBlob, VADER, simulations) s'exécutent dans le notebook ; seules les cellules d'exercice restent à compléter (stubs étudiant).\n"
]
},
{
Expand Down Expand Up @@ -88,10 +88,10 @@
"#40, #44) est un *bloc à coller* dans `main.py`. L'utilisateur\n",
"construit l'algorithme en assemblant : `SentimentData` (cellule #23)\n",
"+ `SentimentAlphaModel` (cellule #28) + `SentimentTradingAlgorithm`\n",
"(cellule #25). Le tout fait ~150 lignes à intégrer dans un projet\n",
"(cellule #25). Le tout s'intègre dans un projet\n",
"QC.\n",
"\n",
"**Backtests disponibles** : deux cellules affichent des résultats\n",
"**Backtests disponibles** : des cellules affichent des résultats\n",
"QC Cloud pré-calculés :\n",
"- Cellule #26 : `SentimentTradingAlgorithm` (2015-2024)\n",
"- Cellule #45 : `NewsSentimentStrategy` (2023)\n",
Expand Down Expand Up @@ -665,12 +665,12 @@
"\n",
"TextBlob est base sur un dictionnaire de mots pre-annotes et utilise des règles pour calculer le sentiment.\n",
"\n",
"**Section TextBlob** : Pattern-based, ~15K lignes de code, bien\n",
"**Section TextBlob** : Pattern-based, bien\n",
"maintenu. Sortie simple : `polarity` (sentiment) + `subjectivity`\n",
"(objectivité perçue). Force : simplicité. Faiblesse : pas de\n",
"lexique financier spécifique.\n",
"\n",
"**Section VADER** : rule-based, ~3K lignes de code, lexique\n",
"**Section VADER** : rule-based, lexique\n",
"annoté manuellement (~7500 mots). Force : lexique financier.\n",
"Faiblesse : pas de désambiguïsation contextuelle.\n",
"\n",
Expand Down Expand Up @@ -1248,7 +1248,7 @@
"\n",
"**Pourquoi ce stub** : le lexique de base VADER couvre le\n",
"*langage général*. Un pipeline trading sérieux doit *spécialiser*\n",
"le lexique. C'est ~30 lignes de code, 1-2 heures de travail.\n"
"le lexique. C'est 1-2 heures de travail.\n"
]
},
{
Expand Down Expand Up @@ -4338,7 +4338,7 @@
"\n",
"Cette approche multicouche réduit les faux signaux en exigeant une confirmation de trois sources indépendantes.\n",
"\n",
"**Architecture résumée** : le notebook expose 5 briques :\n",
"**Architecture résumée** : le notebook expose les briques suivantes :\n",
"\n",
"| Composant | Rôle | Cellule |\n",
"|---|---|---|\n",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1397,7 +1397,7 @@
"\n",
"### Sortie attendue\n",
"\n",
"La cellule affiche un tableau avec 24 lignes (une par slot), montrant pour chaque slot la longueur, le nombre de mots dans le domaine avant et apres AC-3, et le nombre de mots retires. La derniere ligne resume l'espace combinatoire avant et apres (1.7×10³¹ -> 2.56×10²)."
"La cellule affiche un tableau (une ligne par slot), montrant pour chaque slot la longueur, le nombre de mots dans le domaine avant et apres AC-3, et le nombre de mots retires. La derniere ligne resume l'espace combinatoire avant et apres (1.7×10³¹ -> 2.56×10²)."
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1727,7 +1727,7 @@
"| `->` (implication) | `only_enforce_if` | Implication logique |\n",
"| `solve minimize f` | `model.minimize(f)` | Objectif |\n",
"\n",
"**Avantage principal** : le modèle MiniZinc est **beaucoup plus concis**. La contrainte C3 (pas de double reservation) s'ecrit en 3 lignes contre ~8 en CP-SAT.\n",
"**Avantage principal** : le modèle MiniZinc est **beaucoup plus concis**. La contrainte C3 (pas de double reservation) s'ecrit de façon plus compacte qu'en CP-SAT.\n",
"\n",
"> **Pour aller plus loin** : voir [App-8 MiniZinc](../CSP/App-8-MiniZinc.ipynb) pour une introduction complete au langage MiniZinc avec des exemples progressifs."
]
Expand Down Expand Up @@ -1838,7 +1838,7 @@
"\n",
"| Critere | CP-SAT (Python) | MiniZinc | Commentaire |\n",
"|---------|-----------------|----------|-------------|\n",
"| Lignes de modèle | ~80 | ~40 | MiniZinc 2x plus concis |\n",
"| Concision du modèle | Plus de code | Plus compact | MiniZinc plus concis que CP-SAT |\n",
"| Lisibilite | Bonne (Python) | Excellente (math-like) | MiniZinc plus proche de la specification |\n",
"| Performance | Très bon | Variable selon solveur | CP-SAT souvent plus rapide |\n",
"| Integration Python | Native | Via package minizinc | CP-SAT plus simple a integrer |\n",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@
"On commence par un **système d'équations** simple : deux inconnues `x` et `y` dans `[1..10]` telles que `x + y = 10` ET `x * y = 21`. C'est l'exemple le plus minimal du paradigme déclaratif : on **décrit** les contraintes (la somme et le produit), on n'écrit **aucun** algorithme de résolution.\n",
"\n",
"Deux points de syntaxe méritent d'être soulignés :\n",
"- **MiniZinc** (twin Python) l'exprime en **5 lignes** : déclaration des variables (`var 1..10: x`), des contraintes (`constraint x + y = 10`), puis `solve satisfy`. Laconique et mathématique.\n",
"- **MiniZinc** (twin Python) l'exprime ainsi : déclaration des variables (`var 1..10: x`), des contraintes (`constraint x + y = 10`), puis `solve satisfy`. Laconique et mathématique.\n",
"- **CP-SAT C#** ajoute la **création explicite** des variables (`model.NewIntVar(1, 10, \"x\")`) et, pour le produit non-linéaire, une **variable intermédiaire** `produit` liée par `AddMultiplicationEquality`. C'est plus verbeux mais donne le contrôle fin typique d'une API procédurale."
]
},
Expand Down Expand Up @@ -425,9 +425,9 @@
"source": [
"## 3. Contraintes globales\n",
"\n",
"Les contraintes **globales** (`alldifferent`, `cumulative`, `circuit`, `element`) capturent des structures récurrentes qui apparaissent dans une grande variété de problèmes. Plutôt que d'écrire une à une les contraintes binaires élémentaires, on invoque une contrainte globale qui **encode la structure entière** en une ligne — et, crucial, que le solveur sait **propager** efficacement grâce à des algorithmes dédiés (filtres de bornes, cohérence d'arc).\n",
"Les contraintes **globales** (`alldifferent`, `cumulative`, `circuit`, `element`) capturent des structures récurrentes qui apparaissent dans une grande variété de problèmes. Plutôt que d'écrire une à une les contraintes binaires élémentaires, on invoque une contrainte globale qui **encode la structure entière** — et, crucial, que le solveur sait **propager** efficacement grâce à des algorithmes dédiés (filtres de bornes, cohérence d'arc).\n",
"\n",
"`alldifferent` est la plus utile : elle exprime en **une ligne** ce qui demanderait O(n²) contraintes binaires « différentes deux à deux ». Sur le N-Reines, trois `alldifferent` suffisent à coder tout le problème (lignes, diagonale montante, diagonale descendante). C'est ce gain de concision — et surtout de **vitesse de propagation** — qui rend la CP si efficace sur les problèmes structurés."
"`alldifferent` est la plus utile : elle exprime ce qui demanderait O(n²) contraintes binaires « différentes deux à deux ». Sur le N-Reines, trois `alldifferent` suffisent à coder tout le problème (lignes, diagonale montante, diagonale descendante). C'est ce gain de concision — et surtout de **vitesse de propagation** — qui rend la CP si efficace sur les problèmes structurés."
]
},
{
Expand Down Expand Up @@ -694,7 +694,7 @@
"\n",
"Le solveur trouve une solution valide en quelques millisecondes. Deux observations pédagogiques :\n",
"\n",
"- **Concision moindre qu'en MiniZinc** (~12 vs ~5 lignes) : CP-SAT exige la création **explicite** des variables de diagonale intermédiaires (`d1[i] = q[i]+i`, `d2[i] = q[i]-i`) avant de pouvoir appliquer `AddAllDifferent` dessus. MiniZinc abstrait ces calculs via la **compréhension de liste** `[q[i] + i | i in 1..n]`. C'est le coût documenté du contrôle fin : on échange de la concision contre de la transparence sur ce que le solveur fait réellement.\n",
"- **Concision moindre qu'en MiniZinc** : CP-SAT exige la création **explicite** des variables de diagonale intermédiaires (`d1[i] = q[i]+i`, `d2[i] = q[i]-i`) avant de pouvoir appliquer `AddAllDifferent` dessus. MiniZinc abstrait ces calculs via la **compréhension de liste** `[q[i] + i | i in 1..n]`. C'est le coût documenté du contrôle fin : on échange de la concision contre de la transparence sur ce que le solveur fait réellement.\n",
"- **Symétrie des solutions** : pour 8 reines, il existe 92 solutions distinctes (12 à symétrie près). Le solveur en renvoie **une** arbitrairement — la première trouvée. L'énumération complète demanderait une boucle de recherche (« solution suivante »), hors scope de cette démonstration."
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,7 @@
"\n",
"| Critere | CP-SAT (Python) | MiniZinc |\n",
"|---------|-----------------|----------|\n",
"| Lignes de code utiles | ~12 | ~5 |\n",
"| Concision du code | Plus de code | Plus compact |\n",
"| Boilerplate (imports, solver, extraction) | Oui | Non |\n",
"| Lisibilite mathematique | Moyenne | Haute |\n",
"| Flexibilite du solveur | CP-SAT uniquement | Gecode, Chuffed, OR-Tools... |\n",
Expand Down Expand Up @@ -1182,7 +1182,7 @@
"| `dist[i, next[i]]` | Distance de la ville $i$ a la suivante (indexation par variable) |\n",
"\n",
"**Points cles** :\n",
"1. Tout le modèle TSP tient en ~5 lignes declaratives\n",
"1. Tout le modèle TSP tient en quelques lignes declaratives\n",
"2. `circuit` est une contrainte globale très puissante : elle elimine les sous-tours automatiquement\n",
"3. En CP-SAT, il faudrait ajouter manuellement des contraintes d'elimination de sous-tours (MTZ ou lazy constraints)"
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,7 @@
"id": "vrp17b-22",
"metadata": {},
"source": [
"**Véracité démontrée (SOTA-OK, #3801).** OR-Tools est la référence industrielle ; notre recuit from-scratch est **légèrement en retrait** (écart de quelques pour-cents), ce qui est honnête et attendu — une métaheuristique pédagogique de ~50 lignes ne bat pas une bibliothèque optimisée par des années de R&D. L'important : nous avons **reconstruit** chaque algorithme pour le comprendre, puis **mesuré** l'écart contre le vrai outil. C'est la complémentarité App-17 (OR-Tools) ↔ App-17b (from-scratch)."
"**Véracité démontrée (SOTA-OK, #3801).** OR-Tools est la référence industrielle ; notre recuit from-scratch est **légèrement en retrait** (écart de quelques pour-cents), ce qui est honnête et attendu — une métaheuristique pédagogique ne bat pas une bibliothèque optimisée par des années de R&D. L'important : nous avons **reconstruit** chaque algorithme pour le comprendre, puis **mesuré** l'écart contre le vrai outil. C'est la complémentarité App-17 (OR-Tools) ↔ App-17b (from-scratch)."
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@
"source": [
"## 6. Exécution fraîche — matérialiser le coût de chaque claim\n",
"\n",
"La cellule suivante régénère les CSV et le rapport JSON sous `data/app28-learning-to-branch-audit/`. Elle résout d'abord les 36 instances avec quatre heuristiques classiques, collecte 11 461 lignes candidates aux nœuds visités par `dom/wdeg`, puis entraîne et évalue 20 combinaisons split × graine.\n",
"La cellule suivante régénère les CSV et le rapport JSON sous `data/app28-learning-to-branch-audit/`. Elle résout d'abord les 36 instances avec quatre heuristiques classiques, collecte les lignes candidates aux nœuds visités par `dom/wdeg`, puis entraîne et évalue 20 combinaisons split × graine.\n",
"\n",
"Le coût de cette exécution est partie intégrante de l'expérience : une politique de branchement n'est pas évaluée hors du solveur. Les temps absolus restent dépendants de la machine et de la charge ; les ratios comparent deux méthodes dans le même run, sur la même instance. Même ces ratios ne sont pas universels, car les CSP sont petits et l'overhead Python occupe une place plus grande que dans un solveur compilé.\n",
"\n",
Expand Down
Loading
Loading