refactor: Centralize signal output and CSV saving in data_utils.py

This commit is contained in:
Bobby (aider) 2025-02-08 19:01:18 -08:00
parent b64e3b5a27
commit fd3ded3f72
4 changed files with 46 additions and 53 deletions

View File

@ -4,7 +4,7 @@ from datetime import datetime, timedelta
import pandas as pd import pandas as pd
from db.db_connection import create_client from db.db_connection import create_client
from trading.position_calculator import PositionCalculator from trading.position_calculator import PositionCalculator
from utils.data_utils import get_stock_data, validate_signal_date from utils.data_utils import get_stock_data, validate_signal_date, print_signal, save_signals_to_csv
from indicators.three_atr_ema import ThreeATREMAIndicator from indicators.three_atr_ema import ThreeATREMAIndicator
def check_atr_ema_bullish_signal(df: pd.DataFrame) -> bool: def check_atr_ema_bullish_signal(df: pd.DataFrame) -> bool:
@ -144,18 +144,7 @@ def run_atr_ema_scanner(min_price: float, max_price: float, min_volume: int, por
print(f"Error processing {ticker}: {str(e)}") print(f"Error processing {ticker}: {str(e)}")
continue continue
# Save results save_signals_to_csv(bullish_signals, 'atr_ema')
output_dir = 'reports'
os.makedirs(output_dir, exist_ok=True)
output_date = datetime.now().strftime("%Y%m%d_%H%M")
if bullish_signals:
df_bullish = pd.DataFrame(bullish_signals)
output_file = f'{output_dir}/atr_ema_bullish_{output_date}.csv'
df_bullish.to_csv(output_file, index=False)
print(f"\nSaved bullish signals to {output_file}")
else:
print("No bullish signals found")
except Exception as e: except Exception as e:
print(f"Error during scan: {str(e)}") print(f"Error during scan: {str(e)}")

View File

@ -3,7 +3,7 @@ import pandas as pd
import os import os
from db.db_connection import create_client from db.db_connection import create_client
from trading.position_calculator import PositionCalculator from trading.position_calculator import PositionCalculator
from utils.data_utils import get_stock_data, validate_signal_date from utils.data_utils import get_stock_data, validate_signal_date, print_signal, save_signals_to_csv
from screener.user_input import get_interval_choice, get_date_range from screener.user_input import get_interval_choice, get_date_range
from indicators.three_atr_ema import ThreeATREMAIndicator from indicators.three_atr_ema import ThreeATREMAIndicator
@ -148,32 +148,13 @@ def run_atr_ema_scanner_v2(min_price: float, max_price: float, min_volume: int,
entry_signals.append(entry_data) entry_signals.append(entry_data)
# Print signal information with date # Print signal information with date
print(f"\n🔍 {ticker} @ ${entry_data['price']:.2f} on {signal_date.strftime('%Y-%m-%d %H:%M')}") print_signal(entry_data)
if calculator:
print(f" Size: {entry_data['shares']} shares (${entry_data['position_size']:.2f})")
print(f" Stop: ${entry_data['stop_loss']:.2f} (7%)")
print(f" Risk: ${abs(entry_data['risk']):.2f}")
# Add potential profit calculation and display
target_price = entry_data['ema'] # Use stored EMA as target
potential_profit = (target_price - entry_data['price']) * entry_data['shares']
print(f" Target: ${target_price:.2f} | Profit: ${potential_profit:.2f}")
except Exception as e: except Exception as e:
print(f"Error processing {ticker}: {str(e)}") print(f"Error processing {ticker}: {str(e)}")
continue continue
# Save results save_signals_to_csv(entry_signals, 'atr_ema_v2')
if entry_signals:
output_dir = 'reports'
os.makedirs(output_dir, exist_ok=True)
output_date = datetime.now().strftime("%Y%m%d_%H%M")
output_file = f'{output_dir}/atr_ema_v2_{output_date}.csv'
df_signals = pd.DataFrame(entry_signals)
df_signals.to_csv(output_file, index=False)
print(f"\nSaved {len(entry_signals)} signals to {output_file}")
else:
print("\nNo entry signals found")
except Exception as e: except Exception as e:
print(f"Error during scan: {str(e)}") print(f"Error during scan: {str(e)}")

View File

@ -6,7 +6,7 @@ from db.db_connection import create_client
from indicators.sunny_bands import SunnyBands from indicators.sunny_bands import SunnyBands
from trading.position_calculator import PositionCalculator from trading.position_calculator import PositionCalculator
from screener.user_input import get_interval_choice, get_date_range from screener.user_input import get_interval_choice, get_date_range
from utils.data_utils import get_stock_data, validate_signal_date from utils.data_utils import get_stock_data, validate_signal_date, print_signal, save_signals_to_csv
@ -271,11 +271,7 @@ def run_sunny_scanner(min_price: float, max_price: float, min_volume: int, portf
dollar_risk = position['potential_loss'] * -1 dollar_risk = position['potential_loss'] * -1
signal_date = validate_signal_date(df.iloc[-1]['date']) # Get and validate the date signal_date = validate_signal_date(df.iloc[-1]['date']) # Get and validate the date
signal_data['signal_date'] = signal_date # Add to signal data signal_data['signal_date'] = signal_date # Add to signal data
print(f"\n🟢 {ticker} @ ${current_price:.2f} on {signal_date.strftime('%Y-%m-%d %H:%M')}") print_signal(signal_data, "🟢")
print(f" Size: {position['shares']} shares (${position['position_value']:.2f})")
print(f" Stop: ${signal_data['stop_loss']:.2f} (-7%) | Target: ${target_price:.2f}")
print(f" Risk/Reward: 1:{position['risk_reward_ratio']:.1f} | Risk: ${dollar_risk:.2f}")
print(f" Potential Profit: ${position['potential_profit']:.2f}")
except ValueError as e: except ValueError as e:
print(f"Skipping {ticker} position: {str(e)}") print(f"Skipping {ticker} position: {str(e)}")
continue continue
@ -295,18 +291,7 @@ def run_sunny_scanner(min_price: float, max_price: float, min_volume: int, portf
print(f"Error processing {ticker}: {str(e)}") print(f"Error processing {ticker}: {str(e)}")
continue continue
# Save results save_signals_to_csv(bullish_signals, 'sunny')
output_dir = 'reports'
os.makedirs(output_dir, exist_ok=True)
output_date = datetime.now().strftime("%Y%m%d_%H%M")
if bullish_signals:
df_bullish = pd.DataFrame(bullish_signals)
output_file = f'{output_dir}/sunny_signals_{output_date}.csv'
df_bullish.to_csv(output_file, index=False)
print(f"\nSaved {len(bullish_signals)} signals to {output_file}")
else:
print("\nNo signals found")
except Exception as e: except Exception as e:
print(f"Error during scan: {str(e)}") print(f"Error during scan: {str(e)}")

View File

@ -17,6 +17,44 @@ def validate_signal_date(signal_date: datetime) -> datetime:
return current_date return current_date
return signal_date return signal_date
def print_signal(signal_data: dict, signal_type: str = "🔍") -> None:
"""
Print standardized signal output
Args:
signal_data (dict): Dictionary containing signal information
signal_type (str): Emoji indicator for signal type (default: 🔍)
"""
try:
print(f"\n{signal_type} {signal_data['ticker']} @ ${signal_data['entry_price']:.2f} on {signal_data['signal_date'].strftime('%Y-%m-%d %H:%M')}")
print(f" Size: {signal_data['shares']} shares (${signal_data['position_size']:.2f})")
print(f" Stop: ${signal_data['stop_loss']:.2f} (7%) | Target: ${signal_data['target_price']:.2f}")
print(f" Risk/Reward: 1:{signal_data['risk_reward_ratio']:.1f} | Risk: ${abs(signal_data['risk_amount']):.2f}")
print(f" Potential Profit: ${signal_data['profit_amount']:.2f}")
except KeyError as e:
print(f"Error printing signal: Missing key {e}")
def save_signals_to_csv(signals: list, scanner_name: str) -> None:
"""
Save signals to CSV file with standardized format and naming
Args:
signals (list): List of signal dictionaries
scanner_name (str): Name of the scanner for file naming
"""
if not signals:
print("\nNo signals found")
return
output_dir = 'reports'
os.makedirs(output_dir, exist_ok=True)
output_date = datetime.now().strftime("%Y%m%d_%H%M")
output_file = f'{output_dir}/{scanner_name}_{output_date}.csv'
df_signals = pd.DataFrame(signals)
df_signals.to_csv(output_file, index=False)
print(f"\nSaved {len(signals)} signals to {output_file}")
def get_stock_data(ticker: str, start_date: datetime, end_date: datetime, interval: str) -> pd.DataFrame: def get_stock_data(ticker: str, start_date: datetime, end_date: datetime, interval: str) -> pd.DataFrame:
""" """
Fetch stock data from the database with enhanced fallback logic Fetch stock data from the database with enhanced fallback logic