refactor: Enhance multi-ticker backtest error handling and debugging

This commit is contained in:
Bobby (aider) 2025-02-14 00:04:40 -08:00
parent 0b9742eb61
commit 8c2b8233cf

View File

@ -466,40 +466,67 @@ def run_multi_ticker_backtest(tickers: list, start_date: datetime, end_date: dat
print(f"\nTesting strategy on {ticker}") print(f"\nTesting strategy on {ticker}")
df = get_stock_data(ticker, start_date, end_date, 'daily') df = get_stock_data(ticker, start_date, end_date, 'daily')
if df.empty: if df is None or df.empty:
print(f"No data available for {ticker}") print(f"No data available for {ticker}")
continue continue
df = prepare_data_for_backtest(df) print(f"Data shape for {ticker}: {df.shape}")
print(f"Date range: {df.index.min()} to {df.index.max()}")
print(f"Columns: {df.columns.tolist()}")
try:
df = prepare_data_for_backtest(df)
except Exception as e:
print(f"Error preparing data for {ticker}: {str(e)}")
continue
print(f"Prepared data shape: {df.shape}")
print(f"Final columns: {df.columns.tolist()}")
# Run backtest # Run backtest
DynamicStrategy.indicator_configs = indicator_settings try:
bt = Backtest(df, DynamicStrategy, cash=100000, commission=.002) DynamicStrategy.indicator_configs = indicator_settings
stats = bt.run() bt = Backtest(df, DynamicStrategy, cash=100000, commission=.002)
stats = bt.run()
# Print raw stats for debugging print(f"Backtest completed for {ticker}")
print("Debug - Available stats keys:", stats.keys()) print("Available stats keys:", stats.keys())
# Store results with error handling for each metric # Store results with error handling for each metric
result = { result = {
'Ticker': ticker, 'Ticker': ticker,
'Return [%]': stats.get('Return [%]', stats.get('Return', 0)), 'Return [%]': float(stats.get('Return [%]', stats.get('Return', 0))),
'Sharpe Ratio': stats.get('Sharpe Ratio', 0), 'Sharpe Ratio': float(stats.get('Sharpe Ratio', 0)),
'Max Drawdown [%]': stats.get('Max. Drawdown [%]', stats.get('Max Drawdown', 0)), 'Max Drawdown [%]': float(stats.get('Max. Drawdown [%]', stats.get('Max Drawdown', 0))),
'Win Rate [%]': stats.get('Win Rate [%]', stats.get('Win Rate', 0)), 'Win Rate [%]': float(stats.get('Win Rate [%]', stats.get('Win Rate', 0))),
'Number of Trades': stats.get('# Trades', stats.get('Number of Trades', 0)) 'Number of Trades': int(stats.get('# Trades', stats.get('Number of Trades', 0)))
} }
all_results.append(result)
print(f"{ticker} - Return: {result['Return [%]']:.2f}%, " # Verify results are valid
f"Sharpe: {result['Sharpe Ratio']:.2f}, " if any(pd.isna(val) for val in result.values()):
f"Drawdown: {result['Max Drawdown [%]']:.2f}%") print(f"Warning: NaN values in results for {ticker}")
continue
all_results.append(result)
print(f"Success - {ticker} results:")
for key, value in result.items():
print(f"{key}: {value}")
except Exception as e:
print(f"Error during backtest for {ticker}: {str(e)}")
continue
except Exception as e: except Exception as e:
print(f"Error processing {ticker}: {str(e)}") print(f"Error processing {ticker}: {str(e)}")
continue continue
if not all_results: if not all_results:
print("No valid results were generated. Check the following:")
print("1. Are the tickers valid?")
print("2. Is there data available for the selected date range?")
print("3. Are the indicator settings valid?")
print("4. Are there any errors in the strategy logic?")
raise ValueError("No valid results were generated from any ticker") raise ValueError("No valid results were generated from any ticker")
return pd.DataFrame(all_results) return pd.DataFrame(all_results)