pyfinmodel 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyfinmodel/__init__.py +219 -0
- pyfinmodel/core/__init__.py +1 -0
- pyfinmodel/core/affichage.py +66 -0
- pyfinmodel/cours1/__init__.py +5 -0
- pyfinmodel/cours1/concepts_finance.py +148 -0
- pyfinmodel/cours1/python_bases.py +179 -0
- pyfinmodel/cours2/__init__.py +5 -0
- pyfinmodel/cours2/numpy_pandas.py +347 -0
- pyfinmodel/cours2/python_fonctionnel.py +220 -0
- pyfinmodel/cours3/__init__.py +5 -0
- pyfinmodel/cours3/chargement.py +199 -0
- pyfinmodel/cours3/rendements.py +192 -0
- pyfinmodel/cours3/visualisation.py +197 -0
- pyfinmodel/cours4/__init__.py +5 -0
- pyfinmodel/cours4/indicateurs.py +245 -0
- pyfinmodel/cours4/signaux.py +173 -0
- pyfinmodel/cours5/__init__.py +5 -0
- pyfinmodel/cours5/medaf.py +303 -0
- pyfinmodel/cours5/regression_ols.py +329 -0
- pyfinmodel-0.1.0.dist-info/METADATA +117 -0
- pyfinmodel-0.1.0.dist-info/RECORD +23 -0
- pyfinmodel-0.1.0.dist-info/WHEEL +5 -0
- pyfinmodel-0.1.0.dist-info/top_level.txt +1 -0
pyfinmodel/__init__.py
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"""
|
|
2
|
+
pyfinmodel — Modélisation Financière avec Python
|
|
3
|
+
Documentation interactive des cours FIN8524.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from pyfinmodel.core.affichage import (
|
|
7
|
+
_afficher_md,
|
|
8
|
+
_afficher_section,
|
|
9
|
+
_afficher_texte,
|
|
10
|
+
_afficher_titre,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
__version__ = "0.1.0"
|
|
14
|
+
__all__ = ["aide", "liste_cours", "resume_cours", "chercher"]
|
|
15
|
+
|
|
16
|
+
_COURS_META = {
|
|
17
|
+
1: {
|
|
18
|
+
"titre": "Introduction Python & Finance d'Entreprise",
|
|
19
|
+
"niveau": "Débutant",
|
|
20
|
+
"themes": [
|
|
21
|
+
"Décisions financières",
|
|
22
|
+
"Gouvernance",
|
|
23
|
+
"Variables Python",
|
|
24
|
+
"Listes",
|
|
25
|
+
"f-strings",
|
|
26
|
+
],
|
|
27
|
+
"librairies": ["Python natif"],
|
|
28
|
+
},
|
|
29
|
+
2: {
|
|
30
|
+
"titre": "Calcul Appliqué — NumPy & Pandas",
|
|
31
|
+
"niveau": "Intermédiaire",
|
|
32
|
+
"themes": [
|
|
33
|
+
"List comprehension",
|
|
34
|
+
"Lambda / map / filter",
|
|
35
|
+
"NumPy arrays",
|
|
36
|
+
"Pandas DataFrames",
|
|
37
|
+
],
|
|
38
|
+
"librairies": ["numpy", "pandas"],
|
|
39
|
+
},
|
|
40
|
+
3: {
|
|
41
|
+
"titre": "Analyse de Données Financières & Visualisation",
|
|
42
|
+
"niveau": "Intermédiaire–Avancé",
|
|
43
|
+
"themes": [
|
|
44
|
+
"Chargement CSV",
|
|
45
|
+
"Rendements",
|
|
46
|
+
"Nettoyage",
|
|
47
|
+
"Matplotlib",
|
|
48
|
+
"Seaborn",
|
|
49
|
+
"Yahoo Finance",
|
|
50
|
+
],
|
|
51
|
+
"librairies": ["pandas", "numpy", "matplotlib", "seaborn", "yfinance"],
|
|
52
|
+
},
|
|
53
|
+
4: {
|
|
54
|
+
"titre": "Analyse Technique & Indicateurs Boursiers",
|
|
55
|
+
"niveau": "Avancé",
|
|
56
|
+
"themes": ["SMA / EMA", "Bandes de Bollinger", "Signaux achat/vente"],
|
|
57
|
+
"librairies": ["yfinance", "matplotlib", "pandas"],
|
|
58
|
+
},
|
|
59
|
+
5: {
|
|
60
|
+
"titre": "Économétrie & MEDAF/CAPM",
|
|
61
|
+
"niveau": "Avancé",
|
|
62
|
+
"themes": [
|
|
63
|
+
"Régression OLS",
|
|
64
|
+
"Coefficient Bêta",
|
|
65
|
+
"R²",
|
|
66
|
+
"F-stat",
|
|
67
|
+
"t-stat",
|
|
68
|
+
"p-value",
|
|
69
|
+
"MEDAF",
|
|
70
|
+
],
|
|
71
|
+
"librairies": ["statsmodels", "pandas", "yfinance"],
|
|
72
|
+
},
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
_INDEX_GLOBAL = {
|
|
76
|
+
"décision": (1, "cours1.concepts_finance.decisions_financieres"),
|
|
77
|
+
"investissement": (1, "cours1.concepts_finance.decision_investissement"),
|
|
78
|
+
"financement": (1, "cours1.concepts_finance.decision_financement"),
|
|
79
|
+
"dividende": (1, "cours1.concepts_finance.decision_dividendes"),
|
|
80
|
+
"gouvernance": (1, "cours1.concepts_finance.gouvernance_entreprise"),
|
|
81
|
+
"agence": (1, "cours1.concepts_finance.probleme_agence"),
|
|
82
|
+
"f-string": (1, "cours1.python_bases.f_strings_demo"),
|
|
83
|
+
"liste": (1, "cours1.python_bases.listes_intro"),
|
|
84
|
+
"list comprehension": (2, "cours2.python_fonctionnel.list_comprehension_intro"),
|
|
85
|
+
"lambda": (2, "cours2.python_fonctionnel.lambda_intro"),
|
|
86
|
+
"map": (2, "cours2.python_fonctionnel.map_demo"),
|
|
87
|
+
"filter": (2, "cours2.python_fonctionnel.filter_demo"),
|
|
88
|
+
"numpy": (2, "cours2.numpy_pandas.numpy_array_intro"),
|
|
89
|
+
"array": (2, "cours2.numpy_pandas.numpy_array_intro"),
|
|
90
|
+
"reshape": (2, "cours2.numpy_pandas.numpy_reshape_demo"),
|
|
91
|
+
"dataframe": (2, "cours2.numpy_pandas.pandas_dataframe_intro"),
|
|
92
|
+
"pandas": (2, "cours2.numpy_pandas.pandas_dataframe_intro"),
|
|
93
|
+
"csv": (3, "cours3.chargement.charger_csv_demo"),
|
|
94
|
+
"datetime": (3, "cours3.chargement.convertir_dates_demo"),
|
|
95
|
+
"yfinance": (3, "cours3.chargement.telecharger_yfinance_demo"),
|
|
96
|
+
"rendement": (3, "cours3.rendements.rendement_simple_demo"),
|
|
97
|
+
"pct_change": (3, "cours3.rendements.rendement_simple_demo"),
|
|
98
|
+
"boxplot": (3, "cours3.visualisation.boxplot_demo"),
|
|
99
|
+
"seaborn": (3, "cours3.visualisation.boxplot_demo"),
|
|
100
|
+
"matplotlib": (3, "cours3.visualisation.graphique_prix_demo"),
|
|
101
|
+
"sma": (4, "cours4.indicateurs.sma_definition"),
|
|
102
|
+
"moyenne mobile": (4, "cours4.indicateurs.sma_definition"),
|
|
103
|
+
"ema": (4, "cours4.indicateurs.ema_definition"),
|
|
104
|
+
"bollinger": (4, "cours4.indicateurs.bollinger_definition"),
|
|
105
|
+
"signal": (4, "cours4.signaux.signal_bollinger_definition"),
|
|
106
|
+
"achat": (4, "cours4.signaux.signal_bollinger_definition"),
|
|
107
|
+
"économétrie": (5, "cours5.regression_ols.ols_definition"),
|
|
108
|
+
"ols": (5, "cours5.regression_ols.ols_definition"),
|
|
109
|
+
"régression": (5, "cours5.regression_ols.ols_demo"),
|
|
110
|
+
"r²": (5, "cours5.regression_ols.r_carre_definition"),
|
|
111
|
+
"r2": (5, "cours5.regression_ols.r_carre_definition"),
|
|
112
|
+
"f-stat": (5, "cours5.regression_ols.f_statistique_definition"),
|
|
113
|
+
"t-stat": (5, "cours5.regression_ols.t_statistique_definition"),
|
|
114
|
+
"p-value": (5, "cours5.regression_ols.p_value_interpretation"),
|
|
115
|
+
"bêta": (5, "cours5.medaf.beta_definition"),
|
|
116
|
+
"beta": (5, "cours5.medaf.beta_definition"),
|
|
117
|
+
"medaf": (5, "cours5.medaf.medaf_definition"),
|
|
118
|
+
"capm": (5, "cours5.medaf.medaf_definition"),
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def aide() -> None:
|
|
123
|
+
"""Affiche la vue d'ensemble complète du package pyfinmodel."""
|
|
124
|
+
_afficher_titre("pyfinmodel — Documentation des Cours de Modélisation Financière")
|
|
125
|
+
_afficher_texte(
|
|
126
|
+
f"**Version :** {__version__}\n\n"
|
|
127
|
+
"**Fonctions globales :**\n\n"
|
|
128
|
+
"- `pyfinmodel.aide()` → Cette aide\n"
|
|
129
|
+
"- `pyfinmodel.liste_cours()` → Liste de tous les cours\n"
|
|
130
|
+
"- `pyfinmodel.resume_cours(n)` → Résumé du cours n (1 à 5)\n"
|
|
131
|
+
"- `pyfinmodel.chercher('terme')` → Chercher un concept"
|
|
132
|
+
)
|
|
133
|
+
_afficher_section("Modules disponibles")
|
|
134
|
+
lignes = []
|
|
135
|
+
for numero, meta in _COURS_META.items():
|
|
136
|
+
themes_courts = ", ".join(meta["themes"][:3]) + (
|
|
137
|
+
"..." if len(meta["themes"]) > 3 else ""
|
|
138
|
+
)
|
|
139
|
+
lignes.append(
|
|
140
|
+
f"**Cours {numero} : {meta['titre']}** \n"
|
|
141
|
+
f"Niveau : {meta['niveau']} | Thèmes : {themes_courts} \n"
|
|
142
|
+
f"`from pyfinmodel.cours{numero} import ...`"
|
|
143
|
+
)
|
|
144
|
+
_afficher_md("\n\n---\n\n".join(lignes))
|
|
145
|
+
_afficher_section("Exemple rapide")
|
|
146
|
+
_afficher_texte(
|
|
147
|
+
"```python\n"
|
|
148
|
+
"from pyfinmodel.cours5 import medaf\n"
|
|
149
|
+
"medaf.medaf_definition()\n"
|
|
150
|
+
"medaf.beta_definition()\n"
|
|
151
|
+
"```"
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def liste_cours() -> None:
|
|
156
|
+
"""Affiche la liste des cours avec titre, niveau et thèmes."""
|
|
157
|
+
_afficher_titre("Cours disponibles dans pyfinmodel")
|
|
158
|
+
lignes = []
|
|
159
|
+
for numero, meta in _COURS_META.items():
|
|
160
|
+
lignes.append(
|
|
161
|
+
f"**Cours {numero} — {meta['titre']}** \n"
|
|
162
|
+
f"🎓 Niveau : {meta['niveau']} \n"
|
|
163
|
+
f"📌 Thèmes : {', '.join(meta['themes'])} \n"
|
|
164
|
+
f"📦 Librairies : `{'`, `'.join(meta['librairies'])}`"
|
|
165
|
+
)
|
|
166
|
+
_afficher_md("\n\n---\n\n".join(lignes))
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def resume_cours(numero_cours: int) -> None:
|
|
170
|
+
"""Affiche le résumé complet d'un cours.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
numero_cours: Numéro du cours (1 à 5).
|
|
174
|
+
"""
|
|
175
|
+
if numero_cours not in _COURS_META:
|
|
176
|
+
print(
|
|
177
|
+
f" Erreur: le cours {numero_cours} n'existe pas. Choisissez entre 1 et 5."
|
|
178
|
+
)
|
|
179
|
+
return
|
|
180
|
+
|
|
181
|
+
meta = _COURS_META[numero_cours]
|
|
182
|
+
_afficher_titre(f"Cours {numero_cours} — {meta['titre']}")
|
|
183
|
+
themes_md = "\n".join(f"- {t}" for t in meta["themes"])
|
|
184
|
+
_afficher_texte(
|
|
185
|
+
f"**Niveau** : {meta['niveau']} \n"
|
|
186
|
+
f"**Librairies** : `{'`, `'.join(meta['librairies'])}`\n\n"
|
|
187
|
+
f"{themes_md}"
|
|
188
|
+
)
|
|
189
|
+
_afficher_section("Pour explorer le cours")
|
|
190
|
+
_afficher_texte(f"```python\nfrom pyfinmodel.cours{numero_cours} import *\n```")
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def chercher(terme: str) -> None:
|
|
194
|
+
"""Recherche un concept/terme dans l'ensemble du package.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
terme: Mot-clé à rechercher (ex: 'bêta', 'bollinger', 'lambda').
|
|
198
|
+
"""
|
|
199
|
+
terme_lower = terme.lower().strip()
|
|
200
|
+
_afficher_titre(f"Résultats pour : « {terme} »")
|
|
201
|
+
|
|
202
|
+
resultats = [
|
|
203
|
+
(cle, cours, chemin)
|
|
204
|
+
for cle, (cours, chemin) in _INDEX_GLOBAL.items()
|
|
205
|
+
if terme_lower in cle.lower()
|
|
206
|
+
]
|
|
207
|
+
|
|
208
|
+
if not resultats:
|
|
209
|
+
_afficher_texte(
|
|
210
|
+
f"Aucun résultat pour **« {terme} »**. \n"
|
|
211
|
+
"Conseil : essayez `bêta`, `ema`, `ols`, `rendement`, `lambda`..."
|
|
212
|
+
)
|
|
213
|
+
return
|
|
214
|
+
|
|
215
|
+
lignes = [
|
|
216
|
+
f"**Cours {cours}** — `{cle}` \n⇒ `{chemin}()`"
|
|
217
|
+
for cle, cours, chemin in resultats
|
|
218
|
+
]
|
|
219
|
+
_afficher_md("\n\n".join(lignes))
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Module core — utilitaires internes."""
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Utilitaires d'affichage communs pour pyfinmodel.
|
|
2
|
+
|
|
3
|
+
Utilise IPython.display (Markdown + HTML) quand disponible (Jupyter),
|
|
4
|
+
sinon bascule sur du texte brut (terminal).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import textwrap
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# ── Détection de l'environnement Jupyter ────────────────────────────
|
|
11
|
+
def _est_jupyter() -> bool:
|
|
12
|
+
try:
|
|
13
|
+
from IPython import get_ipython
|
|
14
|
+
|
|
15
|
+
shell = get_ipython()
|
|
16
|
+
return shell is not None and hasattr(shell, "kernel")
|
|
17
|
+
except ImportError:
|
|
18
|
+
return False
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _afficher_md(contenu: str) -> None:
|
|
22
|
+
"""Affiche du Markdown rendu dans Jupyter, texte brut sinon."""
|
|
23
|
+
if _est_jupyter():
|
|
24
|
+
from IPython.display import Markdown, display
|
|
25
|
+
|
|
26
|
+
display(Markdown(contenu))
|
|
27
|
+
else:
|
|
28
|
+
print(contenu)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# ── API publique ─────────────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _afficher_titre(texte: str) -> None:
|
|
35
|
+
"""Affiche un titre de niveau 2."""
|
|
36
|
+
_afficher_md(f"\n## 📘 {texte}\n---")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _afficher_section(texte: str) -> None:
|
|
40
|
+
"""Affiche un titre de section (niveau 3)."""
|
|
41
|
+
_afficher_md(f"\n### {texte}")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _afficher_formule(nom: str, formule: str, description: str = "") -> None:
|
|
45
|
+
"""Affiche une formule dans un bloc de code inline."""
|
|
46
|
+
lignes = [f"\n**📐 {nom}**", f"`{formule}`"]
|
|
47
|
+
if description:
|
|
48
|
+
lignes.append(f"*{description}*")
|
|
49
|
+
_afficher_md("\n\n".join(lignes) + "\n")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _afficher_code(titre: str, code: str) -> None:
|
|
53
|
+
"""Affiche un snippet Python avec coloration syntaxique."""
|
|
54
|
+
code_propre = textwrap.dedent(code).strip()
|
|
55
|
+
_afficher_md(f"\n**💻 {titre}**\n\n```python\n{code_propre}\n```\n")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _afficher_texte(texte: str) -> None:
|
|
59
|
+
"""Affiche un bloc de texte brut déjà formaté en Markdown."""
|
|
60
|
+
_afficher_md(textwrap.dedent(texte).strip())
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _afficher_definition(terme: str, definition: str) -> None:
|
|
64
|
+
"""Affiche une définition formatée."""
|
|
65
|
+
definition_propre = definition.replace("\n ", "\n").replace("\n ", "\n")
|
|
66
|
+
_afficher_md(f"\n> **📖 {terme}** \n> {definition_propre}\n")
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Cours 1 — Concepts de Finance d'Entreprise
|
|
3
|
+
===========================================
|
|
4
|
+
Les trois grandes décisions, gouvernance et problème d'agence.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from pyfinmodel.core.affichage import (
|
|
8
|
+
_afficher_code,
|
|
9
|
+
_afficher_definition,
|
|
10
|
+
_afficher_section,
|
|
11
|
+
_afficher_texte,
|
|
12
|
+
_afficher_titre,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def decisions_financieres() -> None:
|
|
17
|
+
"""Affiche les trois grandes décisions en finance d'entreprise."""
|
|
18
|
+
_afficher_titre("Les Trois Grandes Décisions en Finance d'Entreprise")
|
|
19
|
+
_afficher_texte(
|
|
20
|
+
"L'objectif ultime de toute décision financière est de "
|
|
21
|
+
"**MAXIMISER LA VALEUR DE LA FIRME** (mesurée par le cours de l'action)."
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
_afficher_section("1. Décision d'Investissement")
|
|
25
|
+
_afficher_texte(
|
|
26
|
+
"Quels projets ou actifs l'entreprise doit-elle financer ?\n\n"
|
|
27
|
+
"- Règle : accepter les projets dont la VAN (Valeur Actuelle Nette) > 0\n"
|
|
28
|
+
"- Exemples : achat d'équipements, R&D, acquisitions"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
_afficher_section("2. Décision de Financement")
|
|
32
|
+
_afficher_texte(
|
|
33
|
+
"Comment l'entreprise doit-elle se financer ?\n\n"
|
|
34
|
+
"- Dettes vs Capitaux propres (structure du capital)\n"
|
|
35
|
+
"- Compromis entre avantage fiscal de la dette et coûts de détresse"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
_afficher_section("3. Décision de Distribution (Dividendes)")
|
|
39
|
+
_afficher_texte(
|
|
40
|
+
"Quoi faire avec les bénéfices générés ?\n\n"
|
|
41
|
+
"- Distribuer des dividendes aux actionnaires\n"
|
|
42
|
+
"- OU réinvestir dans de nouveaux projets"
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def decision_investissement() -> None:
|
|
47
|
+
"""Détail de la décision d'investissement."""
|
|
48
|
+
_afficher_titre("Décision d'Investissement")
|
|
49
|
+
_afficher_definition(
|
|
50
|
+
"Règle de la VAN",
|
|
51
|
+
"Accepter tous les projets avec une Valeur Actuelle Nette > 0.\n"
|
|
52
|
+
" VAN = Σ [ CF_t / (1+r)^t ] - Investissement initial",
|
|
53
|
+
)
|
|
54
|
+
_afficher_texte(
|
|
55
|
+
"**Critères complémentaires :**\n\n"
|
|
56
|
+
"- TRI (Taux de Rendement Interne) > Coût du Capital\n"
|
|
57
|
+
"- Délai de récupération acceptable"
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def decision_financement() -> None:
|
|
62
|
+
"""Détail de la décision de financement."""
|
|
63
|
+
_afficher_titre("Décision de Financement — Structure du Capital")
|
|
64
|
+
_afficher_definition(
|
|
65
|
+
"Structure optimale du capital",
|
|
66
|
+
"Combinaison dettes / capitaux propres qui maximise la valeur\n"
|
|
67
|
+
" en minimisant le Coût Moyen Pondéré du Capital (CMPC/WACC).",
|
|
68
|
+
)
|
|
69
|
+
_afficher_texte(
|
|
70
|
+
"**Avantages de la dette :**\n\n"
|
|
71
|
+
"- Déductibilité fiscale des intérêts (bouclier fiscal)\n"
|
|
72
|
+
"- Discipline des dirigeants\n\n"
|
|
73
|
+
"**Inconvénients de la dette :**\n\n"
|
|
74
|
+
"- Coûts de détresse financière\n"
|
|
75
|
+
"- Problèmes d'agence dette-actionnaires"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def decision_dividendes() -> None:
|
|
80
|
+
"""Détail de la politique de dividendes."""
|
|
81
|
+
_afficher_titre("Décision de Distribution — Politique de Dividendes")
|
|
82
|
+
_afficher_definition(
|
|
83
|
+
"Théorème de Modigliani-Miller (dividendes)",
|
|
84
|
+
"En marchés parfaits, la politique de dividendes n'affecte pas\n"
|
|
85
|
+
" la valeur de la firme.",
|
|
86
|
+
)
|
|
87
|
+
_afficher_texte(
|
|
88
|
+
"**En pratique :**\n\n"
|
|
89
|
+
"- Les dividendes envoient un signal sur la santé financière\n"
|
|
90
|
+
"- Rachat d'actions = forme alternative de distribution\n"
|
|
91
|
+
"- Ratio de distribution = Dividendes / Bénéfice net"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def gouvernance_entreprise() -> None:
|
|
96
|
+
"""Explique la gouvernance d'entreprise et ses mécanismes."""
|
|
97
|
+
_afficher_titre("Gouvernance d'Entreprise")
|
|
98
|
+
_afficher_texte(
|
|
99
|
+
"La gouvernance vise à **ALIGNER LES INTÉRÊTS** des différentes parties "
|
|
100
|
+
"prenantes : actionnaires, dirigeants et créanciers."
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
_afficher_section("Mécanismes de gouvernance")
|
|
104
|
+
_afficher_texte(
|
|
105
|
+
"1. **Conseil d'Administration (CA)** — Surveille les dirigeants, approuve les grandes décisions\n\n"
|
|
106
|
+
"2. **Rémunération des dirigeants** — Stock-options, bonus liés à la performance\n\n"
|
|
107
|
+
"3. **Activisme actionnarial** — Actionnaires qui exercent leur influence pour changer la stratégie\n\n"
|
|
108
|
+
"4. **Réglementation** — Lois boursières (SEC, AMF), normes comptables (IFRS, GAAP)"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
_afficher_section("Efficacité de la gouvernance")
|
|
112
|
+
_afficher_texte(
|
|
113
|
+
"Dépend du contexte légal et institutionnel du pays. "
|
|
114
|
+
"Les pays avec de meilleures protections légales ont une gouvernance généralement plus efficace."
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def probleme_agence() -> None:
|
|
119
|
+
"""Explique le problème d'agence en finance."""
|
|
120
|
+
_afficher_titre("Le Problème d'Agence")
|
|
121
|
+
_afficher_definition(
|
|
122
|
+
"Relation d'agence",
|
|
123
|
+
"Contrat par lequel une personne (le principal) délègue une tâche\n"
|
|
124
|
+
" à une autre (l'agent). Conflit d'intérêts potentiel.",
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
_afficher_section("Les trois conflits principaux")
|
|
128
|
+
_afficher_texte(
|
|
129
|
+
"1. **Actionnaires ↔ Dirigeants** — Les dirigeants peuvent poursuivre leurs propres intérêts. "
|
|
130
|
+
"Solutions : stock-options, surveillance du CA\n\n"
|
|
131
|
+
"2. **Actionnaires ↔ Créanciers** — Les actionnaires peuvent prendre des risques excessifs. "
|
|
132
|
+
"Transfert de richesse des créanciers vers actionnaires\n\n"
|
|
133
|
+
"3. **Actionnaires majoritaires ↔ Minoritaires** — Expropriation des minoritaires par les majoritaires"
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
_afficher_code(
|
|
137
|
+
"Illustration Python — Modélisation d'intérêts divergents",
|
|
138
|
+
"""
|
|
139
|
+
acteur = {
|
|
140
|
+
"actionnaire": {"objectif": "maximiser_valeur_action", "horizon": "long_terme"},
|
|
141
|
+
"dirigeant": {"objectif": "maximiser_bonus", "horizon": "court_terme"},
|
|
142
|
+
"créancier": {"objectif": "rembourser_dette", "horizon": "fixé_par_contrat"},
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
for role, profil in acteur.items():
|
|
146
|
+
print(f"{role:12s} → objectif: {profil['objectif']}, horizon: {profil['horizon']}")
|
|
147
|
+
""",
|
|
148
|
+
)
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Cours 1 — Bases de Python avec exemples financiers
|
|
3
|
+
===================================================
|
|
4
|
+
Variables, chaînes de caractères, f-strings, listes.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from pyfinmodel.core.affichage import (
|
|
8
|
+
_afficher_code,
|
|
9
|
+
_afficher_definition,
|
|
10
|
+
_afficher_section,
|
|
11
|
+
_afficher_texte,
|
|
12
|
+
_afficher_titre,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def variables_types_demo() -> None:
|
|
17
|
+
"""Présente les types de base Python avec exemples financiers."""
|
|
18
|
+
_afficher_titre("Variables et Types de Base en Python")
|
|
19
|
+
_afficher_section("Types primitifs courants")
|
|
20
|
+
_afficher_texte(
|
|
21
|
+
"| Type | Exemple financier | Code Python |\n"
|
|
22
|
+
"|------|-------------------|-------------|\n"
|
|
23
|
+
"| `int` | Nombre d'actions | `nb_actions = 500` |\n"
|
|
24
|
+
"| `float` | Prix d'une action | `prix = 94.54` |\n"
|
|
25
|
+
"| `str` | Ticker de l'entreprise | `ticker = 'MRU.TO'` |\n"
|
|
26
|
+
"| `bool` | Action en hausse ? | `en_hausse = True` |"
|
|
27
|
+
)
|
|
28
|
+
_afficher_code(
|
|
29
|
+
"Exemple complet",
|
|
30
|
+
"""
|
|
31
|
+
nom = "Metro"
|
|
32
|
+
ticker = "MRU.TO"
|
|
33
|
+
prix = 94.54
|
|
34
|
+
nb_actions = 1000
|
|
35
|
+
en_hausse = True
|
|
36
|
+
|
|
37
|
+
valeur_portefeuille = prix * nb_actions
|
|
38
|
+
print(f"Portefeuille {nom} ({ticker}) : {valeur_portefeuille:,.2f} $")
|
|
39
|
+
""",
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def f_strings_demo() -> None:
|
|
44
|
+
"""Démontre les f-strings pour le formatage financier."""
|
|
45
|
+
_afficher_titre("f-strings — Formatage de Texte en Python")
|
|
46
|
+
_afficher_definition(
|
|
47
|
+
"f-string (formatted string literal)",
|
|
48
|
+
"Syntaxe Python moderne pour insérer des expressions directement\n"
|
|
49
|
+
' dans une chaîne de caractères. Préfixe f"...".',
|
|
50
|
+
)
|
|
51
|
+
_afficher_texte(
|
|
52
|
+
"**Méthode 1 — `.format()`**\n\n"
|
|
53
|
+
'```python\nmsg = "Prix de {} : {} $".format(ticker, prix)\n```\n\n'
|
|
54
|
+
"**Méthode 2 — f-string (recommandée ✓)**\n\n"
|
|
55
|
+
'```python\nmsg = f"Prix de {ticker} : {prix} $"\n```'
|
|
56
|
+
)
|
|
57
|
+
_afficher_section("Modificateurs de format utiles en finance")
|
|
58
|
+
_afficher_texte(
|
|
59
|
+
"| Modificateur | Effet | Exemple |\n"
|
|
60
|
+
"|-------------|-------|---------|\n"
|
|
61
|
+
"| `{prix:.2f}` | 2 décimales | `94.54` |\n"
|
|
62
|
+
"| `{valeur:,.0f}` | séparateur de milliers | `1,000,000` |\n"
|
|
63
|
+
"| `{taux:.1%}` | pourcentage | `5.3%` |\n"
|
|
64
|
+
"| `{nom.upper()}` | majuscules | `METRO` |"
|
|
65
|
+
)
|
|
66
|
+
_afficher_code(
|
|
67
|
+
"Snippet copiable — f-strings financiers",
|
|
68
|
+
_f_strings_code(),
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def listes_intro() -> None:
|
|
73
|
+
"""Introduction aux listes Python avec exemples de portefeuille."""
|
|
74
|
+
_afficher_titre("Listes Python — Portefeuilles et Séries de Prix")
|
|
75
|
+
_afficher_definition(
|
|
76
|
+
"Liste",
|
|
77
|
+
"Structure de données HÉTÉROGÈNE ordonnée et modifiable.\n"
|
|
78
|
+
" Peut contenir des éléments de types différents.",
|
|
79
|
+
)
|
|
80
|
+
_afficher_definition(
|
|
81
|
+
"Vecteur (Array NumPy)",
|
|
82
|
+
"Structure HOMOGÈNE où tous les éléments ont le même type.\n"
|
|
83
|
+
" Optimisée pour les calculs numériques.",
|
|
84
|
+
)
|
|
85
|
+
_afficher_section("Opérations courantes sur les listes")
|
|
86
|
+
_afficher_texte(
|
|
87
|
+
"| Opération | Syntaxe | Exemple |\n"
|
|
88
|
+
"|-----------|---------|---------|\n"
|
|
89
|
+
"| Créer | `liste = [...]` | `tickers = ['AAPL', 'GOOG']` |\n"
|
|
90
|
+
"| Accéder | `liste[index]` | `tickers[0]` → `'AAPL'` |\n"
|
|
91
|
+
"| Slicing | `liste[début:fin]` | `tickers[1:3]` |\n"
|
|
92
|
+
"| Ajouter 1 élément | `liste.append(x)` | `tickers.append('MSFT')` |\n"
|
|
93
|
+
"| Ajouter plusieurs | `liste.extend([x, y])` | `tickers.extend(['META','TSLA'])` |\n"
|
|
94
|
+
"| Longueur | `len(liste)` | `len(tickers)` → `4` |"
|
|
95
|
+
)
|
|
96
|
+
_afficher_code(
|
|
97
|
+
"Snippet copiable — Listes de portefeuille",
|
|
98
|
+
_liste_code(),
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def liste_extend_demo() -> None:
|
|
103
|
+
"""Démontre la méthode extend() pour fusionner des portefeuilles."""
|
|
104
|
+
_afficher_titre("liste.extend() — Fusionner des Portefeuilles")
|
|
105
|
+
_afficher_texte(
|
|
106
|
+
"`extend()` ajoute **PLUSIEURS** éléments à la fin d'une liste existante. "
|
|
107
|
+
"Différent de `append()` qui n'ajoute qu'**UN** seul élément."
|
|
108
|
+
)
|
|
109
|
+
_afficher_code(
|
|
110
|
+
"Comparaison append vs extend",
|
|
111
|
+
"""
|
|
112
|
+
portefeuille_a = ["AAPL", "GOOG", "MSFT"]
|
|
113
|
+
portefeuille_b = ["META", "TSLA", "NVDA"]
|
|
114
|
+
|
|
115
|
+
# append() ajoute la liste comme UN SEUL élément (nested)
|
|
116
|
+
portefeuille_a.append(portefeuille_b)
|
|
117
|
+
# Résultat: ["AAPL", "GOOG", "MSFT", ["META", "TSLA", "NVDA"]] ← non désiré
|
|
118
|
+
|
|
119
|
+
# extend() fusionne les deux listes correctement
|
|
120
|
+
portefeuille_a = ["AAPL", "GOOG", "MSFT"]
|
|
121
|
+
portefeuille_a.extend(portefeuille_b)
|
|
122
|
+
# Résultat: ["AAPL", "GOOG", "MSFT", "META", "TSLA", "NVDA"] ← correct
|
|
123
|
+
print(portefeuille_a)
|
|
124
|
+
""",
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _liste_code() -> str:
|
|
129
|
+
"""Retourne le snippet listes en tant que chaîne copiable.
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
Code Python sous forme de chaîne de caractères.
|
|
133
|
+
"""
|
|
134
|
+
return """
|
|
135
|
+
# Portefeuille — liste hétérogène
|
|
136
|
+
portefeuille = ["AAPL", "GOOG", "MSFT"]
|
|
137
|
+
prix_actuels = [189.5, 175.2, 415.8]
|
|
138
|
+
|
|
139
|
+
# Accès par index (0-basé)
|
|
140
|
+
print("Premier ticker :", portefeuille[0]) # AAPL
|
|
141
|
+
print("Dernier prix :", prix_actuels[-1]) # 415.8
|
|
142
|
+
|
|
143
|
+
# Ajout d'actions
|
|
144
|
+
portefeuille.append("META")
|
|
145
|
+
portefeuille.extend(["TSLA", "NVDA"])
|
|
146
|
+
|
|
147
|
+
# Itération couplée
|
|
148
|
+
for ticker, prix in zip(portefeuille[:3], prix_actuels):
|
|
149
|
+
print(f"{ticker:6s}: {prix:>8.2f} $")
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _f_strings_code() -> str:
|
|
154
|
+
"""Retourne le snippet f-strings en tant que chaîne copiable.
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
Code Python sous forme de chaîne de caractères.
|
|
158
|
+
"""
|
|
159
|
+
return """
|
|
160
|
+
nom = "Metro"
|
|
161
|
+
ticker = "MRU.TO"
|
|
162
|
+
prix = 94.54
|
|
163
|
+
taux = 0.053
|
|
164
|
+
|
|
165
|
+
# Méthode .format() — ancienne
|
|
166
|
+
phrase1 = "Le nom est {}, ticker {} et prix {} $.".format(nom.upper(), ticker, prix)
|
|
167
|
+
|
|
168
|
+
# f-string — moderne et recommandée
|
|
169
|
+
phrase2 = f"Le nom est {nom.upper()}, ticker {ticker} et prix {prix:.2f} $."
|
|
170
|
+
|
|
171
|
+
# Formatage avancé
|
|
172
|
+
resume = (
|
|
173
|
+
f"{'Entreprise':15s}: {nom}\\n"
|
|
174
|
+
f"{'Ticker':15s}: {ticker}\\n"
|
|
175
|
+
f"{'Prix':15s}: {prix:>8.2f} $\\n"
|
|
176
|
+
f"{'Taux annuel':15s}: {taux:>8.1%}"
|
|
177
|
+
)
|
|
178
|
+
print(resume)
|
|
179
|
+
"""
|