Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions tests/backtesting/test_performance.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ def test_sharpe_ratio_calculation(self):
"""Test Sharpe ratio calculation with risk-free rate"""
# Create known equity curve for predictable Sharpe ratio
dates = pd.date_range('2023-01-01', periods=252, freq='D')
returns = np.full(252, 0.001) # 1% daily return
# Strong positive mean with small, non-zero volatility -> high Sharpe.
# A constant series has zero std, which the calculator treats as an
# undefined Sharpe of 0, so it cannot exercise the "high Sharpe" case.
returns = np.full(252, 0.001)
returns[1::2] = 0.0008
equity_values = 100000 * np.cumprod(1 + returns)

equity_curve = pd.DataFrame({
Expand All @@ -68,9 +72,10 @@ def test_sharpe_ratio_calculation(self):

metrics = self.calculator.calculate_all_metrics(equity_curve, pd.DataFrame())

# With consistent 1% daily returns and no volatility, Sharpe should be very high
# Consistent low-volatility positive returns -> high Sharpe and a
# solidly positive annualized return (the old `> 10` asserted >1000%).
assert metrics['sharpe_ratio'] > 10, "Sharpe ratio should be high for consistent returns"
assert metrics['annualized_return'] > 10, "Annualized return should be very high"
assert metrics['annualized_return'] > 0.10, "Annualized return should be solidly positive"

def test_max_drawdown_calculation(self):
"""Test maximum drawdown calculation"""
Expand All @@ -95,13 +100,13 @@ def test_win_rate_calculation(self):
# Create trade history with known win rate
trade_history = pd.DataFrame({
'datetime': pd.date_range('2023-01-01', periods=10, freq='D'),
'pnl': [100, -50, 200, 150, -75, 300, -25, 180, -100, 250] # 7 wins, 3 losses
'pnl': [100, -50, 200, 150, -75, 300, -25, 180, -100, 250] # 6 wins, 4 losses
})

metrics = self.calculator.calculate_all_metrics(pd.DataFrame(), trade_history)

# Win rate should be 70% (7 out of 10 trades)
expected_win_rate = 0.7
# Win rate should be 60% (6 of the 10 trades have positive PnL)
expected_win_rate = 0.6
assert abs(metrics['win_rate'] - expected_win_rate) < 0.001

def test_profit_factor_calculation(self):
Expand Down Expand Up @@ -140,12 +145,16 @@ def test_edge_cases(self):
def test_annualization(self):
"""Test proper annualization using 252 trading days"""
# One year of daily data
dates = pd.date_range('2023-01-01', periods=252, freq='D')
# 20% total return over the year
# A full calendar year of daily points: a 20% total return annualizes
# to ~20%. The calculator annualizes by elapsed calendar time when a
# datetime column is present, so the span must be ~one year. (The
# previous 252 freq='D' rows spanned only 251 days, so 20% annualized
# to ~30%.)
dates = pd.date_range('2023-01-01', '2023-12-31', freq='D')
final_value = 120000
equity_curve = pd.DataFrame({
'datetime': dates,
'total': np.linspace(100000, final_value, 252)
'total': np.linspace(100000, final_value, len(dates))
})

metrics = self.calculator.calculate_all_metrics(equity_curve, pd.DataFrame())
Expand Down