(
trades: Union[List['Trade'], pd.DataFrame],
equity: np.ndarray,
ohlc_data: pd.DataFrame,
strategy_instance: Strategy | None,
risk_free_rate: float = 0,
)
| 35 | |
| 36 | |
| 37 | def compute_stats( |
| 38 | trades: Union[List['Trade'], pd.DataFrame], |
| 39 | equity: np.ndarray, |
| 40 | ohlc_data: pd.DataFrame, |
| 41 | strategy_instance: Strategy | None, |
| 42 | risk_free_rate: float = 0, |
| 43 | ) -> pd.Series: |
| 44 | assert -1 < risk_free_rate < 1 |
| 45 | |
| 46 | index = ohlc_data.index |
| 47 | dd = 1 - equity / np.maximum.accumulate(equity) |
| 48 | dd_dur, dd_peaks = compute_drawdown_duration_peaks(pd.Series(dd, index=index)) |
| 49 | |
| 50 | equity_df = pd.DataFrame({ |
| 51 | 'Equity': equity, |
| 52 | 'DrawdownPct': dd, |
| 53 | 'DrawdownDuration': dd_dur}, |
| 54 | index=index) |
| 55 | |
| 56 | if isinstance(trades, pd.DataFrame): |
| 57 | trades_df: pd.DataFrame = trades |
| 58 | commissions = None # Not shown |
| 59 | else: |
| 60 | # Came straight from Backtest.run() |
| 61 | trades_df = pd.DataFrame({ |
| 62 | 'Size': [t.size for t in trades], |
| 63 | 'EntryBar': [t.entry_bar for t in trades], |
| 64 | 'ExitBar': [t.exit_bar for t in trades], |
| 65 | 'EntryPrice': [t.entry_price for t in trades], |
| 66 | 'ExitPrice': [t.exit_price for t in trades], |
| 67 | 'SL': [t.sl for t in trades], |
| 68 | 'TP': [t.tp for t in trades], |
| 69 | 'PnL': [t.pl for t in trades], |
| 70 | 'Commission': [t._commissions for t in trades], |
| 71 | 'ReturnPct': [t.pl_pct for t in trades], |
| 72 | 'EntryTime': [t.entry_time for t in trades], |
| 73 | 'ExitTime': [t.exit_time for t in trades], |
| 74 | }) |
| 75 | trades_df['Duration'] = trades_df['ExitTime'] - trades_df['EntryTime'] |
| 76 | trades_df['Tag'] = [t.tag for t in trades] |
| 77 | |
| 78 | # Add indicator values |
| 79 | if len(trades_df) and strategy_instance: |
| 80 | for ind in strategy_instance._indicators: |
| 81 | ind = np.atleast_2d(ind) |
| 82 | for i, values in enumerate(ind): # multi-d indicators |
| 83 | suffix = f'_{i}' if len(ind) > 1 else '' |
| 84 | trades_df[f'Entry_{ind.name}{suffix}'] = values[trades_df['EntryBar'].values] |
| 85 | trades_df[f'Exit_{ind.name}{suffix}'] = values[trades_df['ExitBar'].values] |
| 86 | |
| 87 | commissions = sum(t._commissions for t in trades) |
| 88 | del trades |
| 89 | |
| 90 | pl = trades_df['PnL'] |
| 91 | returns = trades_df['ReturnPct'] |
| 92 | durations = trades_df['Duration'] |
| 93 | |
| 94 | def _round_timedelta(value, _period=_data_period(index)): |
no test coverage detected