Equity Curve : Une librairie Python pour l'analyse professionnelle de stratégies

Documentation Outils

equity-curve est une librairie Python pour les analystes quantitatifs et gérants de portefeuille. Elle couvre l'intégralité du pipeline d'analyse de stratégie — de la NAV brute aux dashboards interactifs — avec plus de 30 métriques de risque, des tests économétriques et des visualisations Plotly.

Bannière equity curve
Antoine Perrin Profile Picture

Antoine

CEO - CodeMarketLabs

2026-03-10

equity-curve : Une librairie Python pour l'analyse professionnelle de stratégies

equity-curve est une librairie Python conçue pour les analystes quantitatifs et gérants de portefeuille qui ont besoin d'un framework rigoureux et modulaire pour évaluer leurs stratégies de trading. Construite sur pandas et plotly, elle couvre l'intégralité du pipeline d'analyse — de la NAV brute aux dashboards prêts à publier — avec une API cohérente et des visualisations de qualité professionnelle. Chaque module est utilisable indépendamment : appelez un seul ratio, exécutez une batterie de tests économétriques, ou générez un dashboard interactif complet en une seule ligne.

Ce que la librairie apporte

  • Structures de données avec validation intégrée pour les séries de prix et données de portefeuille.
  • Plus de 30 mesures statistiques : skewness, kurtosis, entropie, déviation downside/upside, IQR, MAD.
  • Métriques de performance : WTD, MTD, YTD, CAGR, depuis l'inception, track record mensuel.
  • Ratios de risque : Sharpe, Sortino, Calmar, Omega, Martin, Burke, VaR, CVaR, Jensen Alpha, Treynor, Up/Down Capture.
  • Tests économétriques : stationnarité (ADF+KPSS), normalité (JB+Shapiro), autocorrélation, Hurst, Variance Ratio, BDS, cointégration, Granger.
  • Dashboards Plotly interactifs exportables en HTML ou PNG, thèmes sombre et clair.

1. Structures de Données

La librairie s'articule autour de trois classes. PriceSeries est la base abstraite — elle valide l'index, trie les données et avertit en cas de doublons. TimeSeries l'étend avec le calcul des rendements (normal ou logarithmique). PortfolioTs impose le contrat à trois colonnes nécessaire à toutes les fonctions en aval : strategy, benchmark et risk_free.

python
import pandas as pd
from equity_curve.utils.financial_ts import TimeSeries, PortfolioTs

# --- Série simple ---
nav = pd.Series([100, 101, 99, 103, 106], index=pd.date_range('2024-01-01', periods=5))
ts = TimeSeries(nav)

print(ts.get_returns('normal'))   # pct_change, dropna
print(ts.get_returns('log'))      # log(p_t / p_t-1), dropna
print(ts)
# PriceSeries(name=None, start=2024-01-01, end=2024-01-05, n=5)

# --- Portefeuille (obligatoire pour tous les ratios et performances) ---
df = pd.DataFrame({
    'strategy':  [100, 102, 101, 105, 108],
    'benchmark': [100, 101, 100, 103, 105],
    'risk_free': [100, 100.01, 100.02, 100.03, 100.04]
}, index=pd.date_range('2024-01-01', periods=5))

portfolio = PortfolioTs(df)
print(portfolio)
# PriceSeries(columns=['strategy', 'benchmark', 'risk_free'], start=2024-01-01, end=2024-01-05, n=5)

# Une colonne manquante lève une erreur immédiatement
try:
    PortfolioTs(df.drop(columns=['risk_free']))
except ValueError as e:
    print(e)  # Missing required columns: ['risk_free']

2. Configuration & Thèmes

config.py centralise toutes les constantes visuelles. Les couleurs de la stratégie et du benchmark sont définies une seule fois et utilisées partout — dans les graphiques, les tableaux et les annotations. Le dict THEMES contrôle l'apparence Plotly complète. Chaque fonction de graphique accepte un paramètre mode ('dark' ou 'light') pour basculer sans toucher à aucun autre code.

python
# config.py — personnalisez selon votre charte graphique
COLOR_STRAT = '#007668'   # vert teal
COLOR_BENCH = '#b20462'   # magenta
COLOR_RF    = '#ffde59'   # jaune pointillé
COLOR_RED   = '#ef0032'
COLOR_GREEN = '#00ef4a'

THEMES = {
    'dark': {
        'TEMPLATE':   'plotly_dark',
        'BG_COLOR':   '#0f1117',
        'COLOR_GRID': 'rgba(255,255,255,0.06)',
        'COLOR_TEXT': '#ffffff'
    },
    'light': {
        'TEMPLATE':   'plotly_white',
        'BG_COLOR':   '#ffffff',
        'COLOR_GRID': 'rgba(0,0,0,0.06)',
        'COLOR_TEXT': '#000000'
    }
}

# Utilisation — passer mode à n'importe quel graphique
from equity_curve.graphs import plot_performance
plot_performance(perf, mode='dark').show()
plot_performance(perf, mode='light').show()

3. Métriques de Performance

La classe Performances encapsule un PortfolioTs avec une computation_date et une base (nombre de périodes par an). Elle sert d'objet central passé à toutes les fonctions de calcul. Les rendements par période gèrent les cas limites calendaires : si la date cible exacte est manquante, la fonction remonte jusqu'à 5 jours pour trouver une observation valide.

python
from datetime import datetime
from equity_curve.performances import (
    Performances, cagr, wtd_perf, mtd_perf, ytd_perf,
    one_month_perf, three_month_perf, since_inception_perf,
    track_record, seasonality_analysis, hit_ratio, avg_win_loss
)

perf = Performances(
    strat=portfolio,
    computation_date=datetime(2024, 12, 31),
    period_per_year=252   # jours de trading
)

# Rendements par période — tous retournent {'strategy': x, 'benchmark': y, 'risk_free': z}
print(wtd_perf(perf))              # week-to-date
print(mtd_perf(perf))              # month-to-date
print(ytd_perf(perf))              # year-to-date
print(three_month_perf(perf))      # 3 mois glissants
print(since_inception_perf(perf))  # depuis l'inception
print(cagr(perf))                  # taux de croissance annuel composé

# Track record — pivot années x mois
print(track_record(perf))

# Saisonnalité
monthly = seasonality_analysis(perf, frequency='M')   # rendements moyens Jan–Déc
daily   = seasonality_analysis(perf, frequency='D')   # rendements moyens Lun–Ven

# Statistiques Win/Loss
print(hit_ratio(perf))      # 0.54 — 54% des jours positifs
print(avg_win_loss(perf))   # {'avg_win': 0.008, 'avg_loss': -0.006}
Graphs des performances relatives
Graphs des performances relatives

4. Statistiques

Le module statistics opère sur tout objet TimeSeries et couvre l'analyse distributionnelle complète. Toutes les fonctions acceptent un paramètre r_type ('normal' ou 'log') et un flag d'annualisation optionnel. Elles fonctionnent aussi bien sur des Series que sur des DataFrame.

python
from equity_curve.statistics import (
    mean_returns, standard_deviation, skewness, kurtosis,
    downside_deviation, upside_deviation, iqr, mad,
    entropy, percentile, zscore, coefficient_of_variation
)

ts = TimeSeries(df['strategy'])

# Moments
print(mean_returns(ts, annualized=True))          # rendement moyen annualisé
print(standard_deviation(ts, annualized=True))    # volatilité annualisée
print(skewness(ts))       # -0.42 — légère asymétrie négative
print(kurtosis(ts))       # 3.81  — kurtosis excédentaire, queues épaisses

# Queues & dispersion
print(downside_deviation(ts))   # sqrt(moyenne des rendements négatifs au carré)
print(upside_deviation(ts))     # sqrt(moyenne des rendements positifs au carré)
print(iqr(ts))                  # Q75 - Q25
print(mad(ts))                  # écart absolu médian
print(percentile(ts, 0.05))     # 5e percentile — proxy VaR

# Qualité de distribution
print(entropy(ts, bins=50))               # entropie de Shannon
print(coefficient_of_variation(ts))       # std / |mean|
print(zscore(ts, prices=False).tail(3))   # z-score sur les rendements

5. Ratios de Risque

pm_ratios.py couvre toutes les métriques de performance ajustées au risque, standard et alternatives. Les fonctions retournent un dict indexé par nom de colonne, de sorte que strategy et benchmark sont toujours calculés ensemble. La fonction all_ratios() calcule tout d'un coup et inclut une description en langage clair de chaque métrique.

python
from equity_curve.pm_ratios import (
    sharpe_ratio, sortino_ratio, calmar_ratio, omega_ratio,
    martin_ratio, burke_ratio, gain_pain_ratio,
    max_drawdown, ulcer_index, pain_index,
    var_histo, cvar_histo,
    jensen_alpha, treynor_ratio, information_ratio,
    tracking_error, up_down_capture, linear_regression,
    all_ratios
)

# Ratios basés sur les rendements
print(sharpe_ratio(perf))     # {'strategy': 0.72, 'benchmark': 0.61}
print(sortino_ratio(perf))    # pénalise uniquement la volatilité négative
print(calmar_ratio(perf))     # CAGR / abs(drawdown maximum)
print(omega_ratio(perf))      # gains / pertes au-dessus du seuil=0
print(martin_ratio(perf))     # CAGR / Ulcer Index
print(burke_ratio(perf))      # CAGR / sqrt(somme des drawdowns au carré)
print(gain_pain_ratio(perf))  # somme(rendements) / somme(abs rendements négatifs)

# Métriques de drawdown
print(max_drawdown(perf))   # {'strategy': -0.184, 'benchmark': -0.241}
print(ulcer_index(perf))    # RMS de tous les drawdowns
print(pain_index(perf))     # drawdown absolu moyen

# Risque de queue
print(var_histo(perf, 0.95))    # VaR historique à 95%
print(cvar_histo(perf, 0.95))   # Expected Shortfall

# Relatif au benchmark
print(jensen_alpha(perf))       # alpha CAPM annualisé
print(information_ratio(perf))  # rendement actif / tracking error
print(up_down_capture(perf))    # {'capture_ratio': 1.24}

# Régression CAPM
reg = linear_regression(perf)
print(reg)  # {'alpha': 0.0003, 'beta': 0.82, 'r2': 0.76}

# Tout d'un coup avec descriptions
ratios = all_ratios(perf)
print(ratios['sharpe_ratio']['value'])        # {'strategy': 0.72, ...}
print(ratios['sharpe_ratio']['description'])  # explication en clair
Table complète des métriques de rendement et de risque
Table complète des métriques de rendement et de risque

6. Tests Économétriques

Le module econometric_tests fournit une interface homogène pour les tests d'hypothèses statistiques. Toutes les fonctions retournent le même dict structuré : stat, p-value, test_results (verdict lisible), et un bloc details avec description, H0 et H1. Les tests univariés fonctionnent sur Series et DataFrame. Les tests multivariés nécessitent exactement 2 colonnes.

python
from equity_curve.econometric_tests.univariate import (
    stationarity_test, normality_test, autocorrelation_test,
    heteroscedasticity_test, hurst_exponent_test,
    variance_ratio_test, bds_test
)
from equity_curve.econometric_tests.multivariate import (
    engle_granger_test, granger_test, johansen_test,
    correlation_test, chow_test
)

# --- Univarié ---
res = stationarity_test(ts)
print(res)  # ADF + KPSS combinés → 'Stationary' / 'Unit Root' / 'Trend Stationary'

res = normality_test(ts)
print(res['strategy']['test_results'])  # 'Not Normal'
print(res['strategy']['p-value'])       # {'JB-p-value': 0.001, 'SW-p-value': 0.003}

res = autocorrelation_test(ts, lags=10)
print(res)  # 'Positive Autocorr (Momentum)' / 'No Autocorr (White Noise)'

res = hurst_exponent_test(ts)
print(res['strategy']['stat'])          # 0.53 — légèrement tendanciel
print(res['strategy']['test_results'])  # 'Trending (Persistent Memory)'

res = variance_ratio_test(ts, lags=[2, 5, 10, 20])
print(res)  # par lag : 'Momentum' / 'Mean Reversion' / 'Random Walk'

# --- Multivarié ---
pair = TimeSeries(df[['strategy', 'benchmark']])

print(engle_granger_test(pair))                  # → 'Cointegrated' si p < 0.05
print(granger_test(pair, max_lag=5))             # strategy cause-t-elle benchmark ?
print(correlation_test(pair, method='pearson'))  # corrélation linéaire
print(correlation_test(pair, method='spearman')) # corrélation monotone

# Rupture structurelle à une date connue
from datetime import datetime
print(chow_test(pair, split_date=datetime(2022, 1, 1)))  # 'Structural Break' ou 'Stable'

7. Visualisation & Dashboard

graphs.py expose une figure Plotly autonome pour chaque module d'analyse, et une fonction dashboard() qui les assemble en une seule figure scrollable. L'helper _add() route intelligemment les traces xy et table vers le bon type de subplot, rendant la mise en page entièrement automatique. L'export HTML préserve l'interactivité complète ; l'export PNG utilise kaleido.

python
from equity_curve.graphs import (
    plot_performance, plot_underwater, plot_drawdowns,
    plot_rolling_sharpe, plot_rolling_volatility, plot_rolling_beta, plot_rolling_correlation,
    plot_annual_returns, plot_returns_histogram, plot_seasonality,
    table_perf, table_ratios, table_track_record, table_returns_stats,
    dashboard, export_dashboard, export_dashboard_png
)

# Graphiques individuels
plot_performance(perf, mode='dark').show()
plot_drawdowns(perf, top_n=5, mode='dark').show()
plot_rolling_sharpe(perf, window=90, mode='dark').show()
plot_seasonality(perf, frequency='M', mode='dark').show()   # rendements moyens mensuels
plot_seasonality(perf, frequency='D', mode='dark').show()   # rendements moyens par jour

# Tableaux individuels
table_perf(perf, mode='dark').show()
table_ratios(perf, mode='dark').show()
table_track_record(perf, mode='dark').show()

# Dashboard complet — assemble tous les graphiques et tableaux
fig = dashboard(
    perf,
    window_roll=90,    # fenêtre rolling en jours
    top_dd=5,          # nombre de drawdowns à mettre en évidence
    mode='dark',
    title='Global Portfolio Strategy'
)
fig.show()  # s'ouvre dans le navigateur, scrollable

# Export
export_dashboard(perf, 'rapport.html', title='Global Portfolio Strategy')
export_dashboard_png(perf, 'rapport.png', title='Global Portfolio Strategy')
Dashboard Complet
Dashboard Complet

Obtenir equity-curve

equity-curve est disponible en tant que package Python standalone. Que vous gériez une stratégie systématique, analysiez un fonds discrétionnaire, ou construisiez des rapports de performance pour vos clients, la librairie vous donne un stack analytique prêt pour la production en quelques lignes de code.

Ce que vous obtenez

  • Code source complet avec fonctions typées et documentées.
  • Dashboards thème sombre et clair exportables en HTML et PNG.
  • Plus de 30 métriques de risque et performance avec comparaison strategy vs benchmark.
  • Suite complète de tests économétriques : univariés et multivariés.
  • Mises à jour à vie — nouveaux ratios et graphiques ajoutés régulièrement.
Quel format de données equity-curve attend-il ?

Un DataFrame pandas avec un DatetimeIndex et trois colonnes : strategy, benchmark et risk_free — toutes en séries de prix/NAV démarrant à n'importe quelle base (ex : 100). L'index doit être parseable comme des dates ; la librairie convertit automatiquement les chaînes de caractères.

Fonctionne-t-il avec des données journalières, hebdomadaires ou mensuelles ?

Oui. Définissez period_per_year en conséquence lors de l'instanciation de Performances : 252 pour les jours de trading, 365 pour les jours calendaires, 52 pour hebdomadaire, 12 pour mensuel. Toute l'annualisation dans les ratios et graphiques rolling utilise cette base automatiquement.

Est-ce compatible avec Jupyter ?

Oui. Tous les graphiques sont des figures Plotly et s'affichent inline dans JupyterLab ou les notebooks classiques. Pour le dashboard complet, fig.show() l'ouvre dans votre navigateur où la grande figure est nativement scrollable.

Puis-je utiliser seulement une partie de la librairie ?

Oui. Chaque module est importable indépendamment. Vous pouvez utiliser uniquement pm_ratios pour les calculs de ratios, uniquement econometric_tests pour les tests statistiques, ou uniquement graphs pour un graphique spécifique — sans instancier l'objet Performances complet.

Comment personnaliser les couleurs et les thèmes des graphiques ?

Modifiez config.py pour définir COLOR_STRAT, COLOR_BENCH et le dict THEMES. Chaque graphique récupère ces valeurs automatiquement via le paramètre mode. Aucune autre modification n'est nécessaire.