feat: Add comprehensive debug logging to trading strategy and optimization
This commit is contained in:
parent
e48fcfafbd
commit
4feaf51b4c
@ -71,12 +71,20 @@ class DynamicStrategy(Strategy):
|
|||||||
def next(self):
|
def next(self):
|
||||||
price = self.data.Close[-1]
|
price = self.data.Close[-1]
|
||||||
|
|
||||||
|
# Debug current price and position
|
||||||
|
if len(self.data.Close) % 20 == 0: # Log every 20th candle to avoid spam
|
||||||
|
print(f"Current price: {price}, Has position: {bool(self.position)}")
|
||||||
|
|
||||||
# Example trading logic using indicators
|
# Example trading logic using indicators
|
||||||
for ind_name, ind_config in self.indicator_configs.items():
|
for ind_name, ind_config in self.indicator_configs.items():
|
||||||
if ind_config['type'] == 'SMA':
|
if ind_config['type'] == 'SMA':
|
||||||
if price > self.indicators[ind_name][-1] and not self.position:
|
current_sma = self.indicators[ind_name][-1]
|
||||||
|
print(f"SMA - Price: {price:.2f}, SMA: {current_sma:.2f}")
|
||||||
|
if price > current_sma and not self.position:
|
||||||
|
print(f"BUY signal - Price above SMA")
|
||||||
self.buy()
|
self.buy()
|
||||||
elif price < self.indicators[ind_name][-1] and self.position:
|
elif price < current_sma and self.position:
|
||||||
|
print(f"SELL signal - Price below SMA")
|
||||||
self.position.close()
|
self.position.close()
|
||||||
|
|
||||||
elif ind_config['type'] == 'MACD':
|
elif ind_config['type'] == 'MACD':
|
||||||
@ -85,36 +93,49 @@ class DynamicStrategy(Strategy):
|
|||||||
prev_macd = self.indicators[f"{ind_name}_macd"][-2]
|
prev_macd = self.indicators[f"{ind_name}_macd"][-2]
|
||||||
prev_signal = self.indicators[f"{ind_name}_signal"][-2]
|
prev_signal = self.indicators[f"{ind_name}_signal"][-2]
|
||||||
|
|
||||||
|
print(f"MACD - MACD: {macd:.2f}, Signal: {signal:.2f}")
|
||||||
if macd > signal and prev_macd <= prev_signal and not self.position:
|
if macd > signal and prev_macd <= prev_signal and not self.position:
|
||||||
|
print(f"BUY signal - MACD crossover")
|
||||||
self.buy()
|
self.buy()
|
||||||
elif macd < signal and prev_macd >= prev_signal and self.position:
|
elif macd < signal and prev_macd >= prev_signal and self.position:
|
||||||
|
print(f"SELL signal - MACD crossunder")
|
||||||
self.position.close()
|
self.position.close()
|
||||||
|
|
||||||
elif ind_config['type'] == 'BB':
|
elif ind_config['type'] == 'BB':
|
||||||
upper = self.indicators[f"{ind_name}_upper"][-1]
|
upper = self.indicators[f"{ind_name}_upper"][-1]
|
||||||
lower = self.indicators[f"{ind_name}_lower"][-1]
|
lower = self.indicators[f"{ind_name}_lower"][-1]
|
||||||
|
|
||||||
|
print(f"BB - Price: {price:.2f}, Upper: {upper:.2f}, Lower: {lower:.2f}")
|
||||||
# Buy when price touches lower band
|
# Buy when price touches lower band
|
||||||
if price <= lower and not self.position:
|
if price <= lower and not self.position:
|
||||||
|
print(f"BUY signal - Price at lower band")
|
||||||
self.buy()
|
self.buy()
|
||||||
# Sell when price touches upper band
|
# Sell when price touches upper band
|
||||||
elif price >= upper and self.position:
|
elif price >= upper and self.position:
|
||||||
|
print(f"SELL signal - Price at upper band")
|
||||||
self.position.close()
|
self.position.close()
|
||||||
|
|
||||||
elif ind_config['type'] == 'RSI':
|
elif ind_config['type'] == 'RSI':
|
||||||
rsi = self.indicators[ind_name][-1]
|
rsi = self.indicators[ind_name][-1]
|
||||||
|
print(f"RSI - Value: {rsi:.2f}")
|
||||||
|
|
||||||
# Buy when RSI is below 30 (oversold)
|
# Buy when RSI is below 30 (oversold)
|
||||||
if rsi < 30 and not self.position:
|
if rsi < 30 and not self.position:
|
||||||
|
print(f"BUY signal - RSI oversold")
|
||||||
self.buy()
|
self.buy()
|
||||||
# Sell when RSI is above 70 (overbought)
|
# Sell when RSI is above 70 (overbought)
|
||||||
elif rsi > 70 and self.position:
|
elif rsi > 70 and self.position:
|
||||||
|
print(f"SELL signal - RSI overbought")
|
||||||
self.position.close()
|
self.position.close()
|
||||||
|
|
||||||
elif ind_config['type'] == 'EMA':
|
elif ind_config['type'] == 'EMA':
|
||||||
if price > self.indicators[ind_name][-1] and not self.position:
|
current_ema = self.indicators[ind_name][-1]
|
||||||
|
print(f"EMA - Price: {price:.2f}, EMA: {current_ema:.2f}")
|
||||||
|
if price > current_ema and not self.position:
|
||||||
|
print(f"BUY signal - Price above EMA")
|
||||||
self.buy()
|
self.buy()
|
||||||
elif price < self.indicators[ind_name][-1] and self.position:
|
elif price < current_ema and self.position:
|
||||||
|
print(f"SELL signal - Price below EMA")
|
||||||
self.position.close()
|
self.position.close()
|
||||||
|
|
||||||
def get_available_indicators() -> Dict:
|
def get_available_indicators() -> Dict:
|
||||||
@ -149,22 +170,31 @@ def get_available_indicators() -> Dict:
|
|||||||
|
|
||||||
def prepare_data_for_backtest(df: pd.DataFrame) -> pd.DataFrame:
|
def prepare_data_for_backtest(df: pd.DataFrame) -> pd.DataFrame:
|
||||||
"""Prepare the dataframe for backtesting"""
|
"""Prepare the dataframe for backtesting"""
|
||||||
|
print("\nPreparing data for backtest...")
|
||||||
|
print(f"Initial dataframe shape: {df.shape}")
|
||||||
|
print(f"Initial columns: {df.columns.tolist()}")
|
||||||
|
|
||||||
# Ensure the dataframe has the required columns
|
# Ensure the dataframe has the required columns
|
||||||
required_columns = ['Open', 'High', 'Low', 'Close', 'Volume']
|
required_columns = ['Open', 'High', 'Low', 'Close', 'Volume']
|
||||||
|
|
||||||
# Rename columns if needed
|
# Rename columns if needed
|
||||||
df = df.copy()
|
df = df.copy()
|
||||||
df.columns = [c.capitalize() for c in df.columns]
|
df.columns = [c.capitalize() for c in df.columns]
|
||||||
|
print(f"Columns after capitalization: {df.columns.tolist()}")
|
||||||
|
|
||||||
# Set the date as index if it's not already
|
# Set the date as index if it's not already
|
||||||
if 'Date' in df.columns:
|
if 'Date' in df.columns:
|
||||||
df.set_index('Date', inplace=True)
|
df.set_index('Date', inplace=True)
|
||||||
|
print("Set Date as index")
|
||||||
|
|
||||||
# Verify all required columns exist
|
# Verify all required columns exist
|
||||||
missing_cols = [col for col in required_columns if col not in df.columns]
|
missing_cols = [col for col in required_columns if col not in df.columns]
|
||||||
if missing_cols:
|
if missing_cols:
|
||||||
|
print(f"WARNING: Missing columns: {missing_cols}")
|
||||||
raise ValueError(f"Missing required columns: {missing_cols}")
|
raise ValueError(f"Missing required columns: {missing_cols}")
|
||||||
|
|
||||||
|
print(f"Final dataframe shape: {df.shape}")
|
||||||
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
def backtesting_page():
|
def backtesting_page():
|
||||||
@ -259,9 +289,13 @@ def backtesting_page():
|
|||||||
def run_optimization(df: pd.DataFrame, indicator_settings: Dict) -> List:
|
def run_optimization(df: pd.DataFrame, indicator_settings: Dict) -> List:
|
||||||
"""Run optimization with different parameter combinations"""
|
"""Run optimization with different parameter combinations"""
|
||||||
param_combinations = generate_param_combinations(indicator_settings)
|
param_combinations = generate_param_combinations(indicator_settings)
|
||||||
|
print(f"Generated {len(param_combinations)} parameter combinations")
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
for params in param_combinations:
|
for i, params in enumerate(param_combinations):
|
||||||
|
print(f"\nTesting combination {i+1}/{len(param_combinations)}")
|
||||||
|
print(f"Parameters: {params}")
|
||||||
|
|
||||||
# Configure strategy with current parameters
|
# Configure strategy with current parameters
|
||||||
DynamicStrategy.indicator_configs = params
|
DynamicStrategy.indicator_configs = params
|
||||||
|
|
||||||
@ -269,6 +303,10 @@ def run_optimization(df: pd.DataFrame, indicator_settings: Dict) -> List:
|
|||||||
bt = Backtest(df, DynamicStrategy, cash=100000, commission=.002)
|
bt = Backtest(df, DynamicStrategy, cash=100000, commission=.002)
|
||||||
stats = bt.run()
|
stats = bt.run()
|
||||||
|
|
||||||
|
print(f"Results - Return: {stats['Return [%]']:.2f}%, "
|
||||||
|
f"Sharpe: {stats['Sharpe Ratio']:.2f}, "
|
||||||
|
f"Drawdown: {stats['Max. Drawdown [%]']:.2f}%")
|
||||||
|
|
||||||
results.append({
|
results.append({
|
||||||
'parameters': params,
|
'parameters': params,
|
||||||
'Return [%]': stats['Return [%]'],
|
'Return [%]': stats['Return [%]'],
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user