Skip to content

trading.analyzer.graphing.equity_curve_overlay

trading.analyzer.graphing.equity_curve_overlay

build_equity_curve_overlay

build_equity_curve_overlay(df: DataFrame, rank_by: str = 'calmar_ratio', default_top_n: int = 8, max_traces: int = 40) -> go.Figure

Builds an equity curve with the top amount of points, adjustable with a slider.

Parameters:

Name Type Description Default
df DataFrame

The experiment DataFrame.

required
rank_by str

Metric column to rank by (descending = best first).

'calmar_ratio'
default_top_n int

How many traces are visible when the chart first loads.

8
max_traces int

How many experiments get a trace at all (available in the slider).

40

Returns:

Type Description
Figure

A plotly Figure with an embedded slider.

Source code in src\contango\trading\analyzer\graphing\equity_curve_overlay.py
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
def build_equity_curve_overlay(
    df: pd.DataFrame,
    rank_by: str = "calmar_ratio",
    default_top_n: int = 8,
    max_traces: int = 40,
) -> go.Figure:
    """
    Builds an equity curve with the top amount of points, adjustable with a slider.

    Args:
        df: The experiment DataFrame.
        rank_by: Metric column to rank by (descending = best first).
        default_top_n: How many traces are visible when the chart first loads.
        max_traces: How many experiments get a trace at all (available in the slider).

    Returns:
        A plotly Figure with an embedded slider.
    """
    plot_df = (
        df.dropna(subset=["equity_curve"])
        .sort_values(rank_by, ascending=False)
        .head(max_traces)
        .reset_index(drop=True)
    )
    n_traces = len(plot_df)
    default_top_n = min(default_top_n, n_traces)

    fig = go.Figure()
    for i, (_, row) in enumerate(plot_df.iterrows()):
        curve = row["equity_curve"]
        timestamps: list[pd.Timestamp] = [pd.to_datetime(t, unit="ms") for t, _ in curve]
        values = [v for _, v in curve]
        fig.add_trace(  # type: ignore[unknownMemberType]
            go.Scatter(
                x=timestamps,
                y=values,
                mode="lines",
                name=f"{row['experiment_id']} ({rank_by}={row[rank_by]:.2f})",
                visible=(i < default_top_n),
            )
        )

    # One slider step per N, from 1 up to n_traces.
    steps: list[dict[str, str | list[dict[str, list[bool]]]]] = []
    for n in range(1, n_traces + 1):
        steps.append(
            dict(
                method="restyle",
                args=[{"visible": [i < n for i in range(n_traces)]}],
                label=str(n),
            )
        )

    sliders = [
        dict(
            active=default_top_n - 1,
            currentvalue={"prefix": "Showing top "},
            pad={"t": 60},
            steps=steps,
        )
    ]

    fig.update_layout(  # type: ignore[unknownMemberType]
        title=f"Equity Curve Overlay — ranked by {rank_by}",
        xaxis_title="Time",
        yaxis_title="Account Value (USD)",
        sliders=sliders,
    )
    return fig