From 7faf56a712381de4611ef696f8c92ee50b3dcb3d Mon Sep 17 00:00:00 2001 From: "Bobby Abellana (aider)" Date: Fri, 7 Feb 2025 00:24:08 -0800 Subject: [PATCH] refactor: Optimize sunny scanner with direct database query and simplified processing --- src/screener/t_sunnyband.py | 152 +++++++++++++++++++----------------- 1 file changed, 81 insertions(+), 71 deletions(-) diff --git a/src/screener/t_sunnyband.py b/src/screener/t_sunnyband.py index df41769..f1ccb91 100644 --- a/src/screener/t_sunnyband.py +++ b/src/screener/t_sunnyband.py @@ -277,81 +277,91 @@ def run_sunny_scanner(min_price: float, max_price: float, min_volume: int, portf interval = get_interval_choice() end_date = datetime.now() start_date = end_date - timedelta(days=1) - lookback_start = end_date - timedelta(days=60) - tickers = get_valid_tickers(min_price, max_price, min_volume, interval) - if not tickers: - print("No stocks found matching criteria.") - return + # First get the data from database + client = create_client() - print(f"\nScanning {len(tickers)} qualified stocks...") + # Query to get stocks meeting criteria + query = f""" + SELECT DISTINCT ticker, close + FROM stock_db.stock_prices_daily + WHERE date = (SELECT max(date) FROM stock_db.stock_prices_daily) + AND close BETWEEN {min_price} AND {max_price} + AND volume >= {min_volume} + ORDER BY ticker + """ - sunny = SunnyBands() - calculator = None - if portfolio_size and portfolio_size > 0: - calculator = PositionCalculator(account_size=portfolio_size) - - bullish_signals = [] - bearish_signals = [] - - for ticker in tickers: - try: - df = get_stock_data(ticker, start_date, end_date, interval) - if df.empty or len(df) < 50: - continue - - results = sunny.calculate(df) - last_day = df.iloc[-1] + try: + result = client.query(query) + qualified_stocks = [(row[0], row[1]) for row in result.result_rows] + + if not qualified_stocks: + print("No stocks found matching criteria.") + return - if results['bullish_signal'].iloc[-1]: - entry_price = last_day['close'] - dma = results['dma'].iloc[-1] - upper_band = results['upper_band'].iloc[-1] - band_range = upper_band - dma - target_price = upper_band + band_range + print(f"\nFound {len(qualified_stocks)} stocks matching criteria") + + # Initialize indicators + sunny = SunnyBands() + calculator = None + if portfolio_size and portfolio_size > 0: + calculator = PositionCalculator(account_size=portfolio_size) + + bullish_signals = [] + bearish_signals = [] + + # Process each qualified stock + for ticker, current_price in qualified_stocks: + try: + df = get_stock_data(ticker, start_date, end_date, interval) + if df.empty or len(df) < 50: + continue + + results = sunny.calculate(df) - signal_data = { - 'ticker': ticker, - 'entry': entry_price, - 'target': target_price - } + if results['bullish_signal'].iloc[-1]: + target_price = results['upper_band'].iloc[-1] + + if calculator: + position = calculator.calculate_position_size(current_price, target_price) + if position['shares'] > 0: + signal_data = { + 'ticker': ticker, + 'entry': current_price, + 'target': target_price, + 'shares': position['shares'], + 'position_size': position['position_value'], + 'stop_loss': position['stop_loss'], + 'risk': position['potential_loss'], + 'reward': position['potential_profit'], + 'r_r': position['risk_reward_ratio'] + } + bullish_signals.append(signal_data) + print(f"\n🟢 {ticker} Entry: ${current_price:.2f} Target: ${target_price:.2f}") + print(f" Shares: {signal_data['shares']} | Risk: ${abs(signal_data['risk']):.2f} | " + f"Reward: ${signal_data['reward']:.2f} | R/R: {signal_data['r_r']:.2f}") - if calculator: - position = calculator.calculate_position_size(entry_price, target_price) - signal_data.update({ - 'shares': position['shares'], - 'position_size': position['position_value'], - 'stop_loss': position['stop_loss'], - 'risk': position['potential_loss'], - 'reward': position['potential_profit'], - 'r_r': position['risk_reward_ratio'] + elif results['bearish_signal'].iloc[-1]: + bearish_signals.append({ + 'ticker': ticker, + 'price': current_price }) - - bullish_signals.append(signal_data) - print(f"\n🟢 {ticker} Entry: ${entry_price:.2f} Target: ${target_price:.2f}") - if calculator: - print(f" Shares: {signal_data['shares']} | Risk: ${abs(signal_data['risk']):.2f} | " - f"Reward: ${signal_data['reward']:.2f} | R/R: {signal_data['r_r']:.2f}") - - elif results['bearish_signal'].iloc[-1]: - bearish_signals.append({ - 'ticker': ticker, - 'price': last_day['close'] - }) - print(f"\n🔴 {ticker} at ${last_day['close']:.2f}") - - except Exception as e: - continue - - # Save results more concisely - output_date = datetime.now().strftime("%Y%m%d") - if bullish_signals: - df_bullish = pd.DataFrame(bullish_signals) - df_bullish.to_csv(f'reports/sunny_bullish_{output_date}.csv', index=False) - - if bearish_signals: - df_bearish = pd.DataFrame(bearish_signals) - df_bearish.to_csv(f'reports/sunny_bearish_{output_date}.csv', index=False) - - print(f"\nFound {len(bullish_signals)} bullish and {len(bearish_signals)} bearish signals") - print("Results saved to reports directory") + print(f"\n🔴 {ticker} at ${current_price:.2f}") + + except Exception as e: + continue + + # Save results + output_date = datetime.now().strftime("%Y%m%d") + if bullish_signals: + df_bullish = pd.DataFrame(bullish_signals) + df_bullish.to_csv(f'reports/sunny_bullish_{output_date}.csv', index=False) + + if bearish_signals: + df_bearish = pd.DataFrame(bearish_signals) + df_bearish.to_csv(f'reports/sunny_bearish_{output_date}.csv', index=False) + + print(f"\nFound {len(bullish_signals)} bullish and {len(bearish_signals)} bearish signals") + + except Exception as e: + print(f"Error during scan: {str(e)}")