Skip to content

trading.analyzer.data.data_prep

trading.analyzer.data.data_prep

get_param_columns

get_param_columns(df: DataFrame, exclude_constant: bool = True) -> list[str]

Returns the columns in df that represent swept strategy parameters, inferred by exclusion of known metric column names.

Parameters:

Name Type Description Default
df DataFrame

DataFrame produced by results_to_dataframe.

required
exclude_constant bool

If True (default), drop parameters that only take a single unique value across all rows (e.g. a fixed allocation), since they carry zero information for comparison/graphing.

True

Returns:

Type Description
list[str]

List of parameter column names.

Source code in src\contango\trading\analyzer\data\data_prep.py
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
def get_param_columns(df: pd.DataFrame, exclude_constant: bool = True) -> list[str]:
    """
    Returns the columns in `df` that represent swept strategy parameters, inferred
    by exclusion of known metric column names.

    Args:
        df: DataFrame produced by `results_to_dataframe`.
        exclude_constant: If True (default), drop parameters that only take a
            single unique value across all rows (e.g. a fixed `allocation`),
            since they carry zero information for comparison/graphing.

    Returns:
        List of parameter column names.
    """
    param_columns = [c for c in df.columns if c not in _METRIC_COLUMNS]

    if exclude_constant:
        param_columns = [c for c in param_columns if df[c].nunique(dropna=False) > 1]

    return param_columns

results_to_dataframe

results_to_dataframe(results: list[BacktestExperimentResult]) -> pd.DataFrame

Flattens a list of BacktestExperimentResult into a tidy DataFrame.

Each row = one experiment. Columns: - one column per parameter key in experiment.parameters - flattened metric columns (total_return, sharpe_ratio, max_drawdown, ...) - "equity_curve" / "monthly_returns": kept as raw tuples (object dtype), consumed directly by the equity-curve / underwater-plot charts - "experiment_id": a human-readable label built from the parameter values, used for hover text, legends, and shortlist filtering

Parameters:

Name Type Description Default
results list[BacktestExperimentResult]

The list of BacktestExperimentResult from ResearchRunner.run(...).

required

Returns:

Type Description
DataFrame

A pandas DataFrame with one row per experiment.

Source code in src\contango\trading\analyzer\data\data_prep.py
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
def results_to_dataframe(results: list[BacktestExperimentResult]) -> pd.DataFrame:
    """
    Flattens a list of BacktestExperimentResult into a tidy DataFrame.

    Each row = one experiment. Columns:
        - one column per parameter key in experiment.parameters
        - flattened metric columns (total_return, sharpe_ratio, max_drawdown, ...)
        - "equity_curve" / "monthly_returns": kept as raw tuples (object dtype),
          consumed directly by the equity-curve / underwater-plot charts
        - "experiment_id": a human-readable label built from the parameter values,
          used for hover text, legends, and shortlist filtering

    Args:
        results: The list of BacktestExperimentResult from ResearchRunner.run(...).

    Returns:
        A pandas DataFrame with one row per experiment.
    """
    rows: list[dict[str, Any]] = []

    for result in results:
        params = dict(result.experiment.parameters)
        metrics = result.backtest_metrics

        row: dict[str, Any] = dict(params)

        # Returns
        row["total_return"] = metrics.returns.total_return
        row["monthly_returns"] = metrics.returns.monthly_returns
        row["equity_curve"] = metrics.returns.equity_curve

        # Risk
        row["annual_return"] = metrics.risk.annual_return
        row["monthly_volatility"] = metrics.risk.monthly_volatility
        row["sharpe_ratio"] = metrics.risk.sharpe_ratio
        row["calmar_ratio"] = metrics.risk.calmar_ratio

        # Drawdowns
        row["max_drawdown"] = metrics.drawdowns.max_drawdown
        row["average_drawdown"] = metrics.drawdowns.average_drawdown

        # Trades
        row["trade_count"] = metrics.trades.trade_count
        row["win_rate"] = metrics.trades.win_rate
        row["profit_factor"] = metrics.trades.profit_factor
        row["expectancy"] = metrics.trades.expectancy
        row["average_win"] = metrics.trades.average_win
        row["average_loss"] = metrics.trades.average_loss
        row["average_holding_period"] = metrics.trades.average_holding_period

        row["experiment_id"] = ", ".join(f"{k}={v}" for k, v in params.items())

        rows.append(row)

    return pd.DataFrame(rows)