diff --git a/src/screener/t_sunnyband.py b/src/screener/t_sunnyband.py index db1cd84..fe2ecf9 100644 --- a/src/screener/t_sunnyband.py +++ b/src/screener/t_sunnyband.py @@ -10,6 +10,44 @@ from utils.data_utils import get_stock_data, validate_signal_date, print_signal, +def check_entry_signal(df: pd.DataFrame) -> list: + """ + Check for entry signals based on Sunny Bands strategy throughout the date range + + Args: + df (pd.DataFrame): DataFrame with price data + + Returns: + list: List of tuples (signal, date, signal_data) for each signal found + """ + if len(df) < 2: # Need at least 2 bars for comparison + return [] + + sunny = SunnyBands() + results = sunny.calculate(df) + + if len(results) < 2: + return [] + + signals = [] + + # Start from index 1 to compare with previous + for i in range(1, len(df)): + current = df.iloc[i] + current_bands = results.iloc[i] + + # Check for bullish signal + if current_bands['bullish_signal']: + signal_data = { + 'price': current['close'], + 'upper_band': current_bands['upper_band'], + 'lower_band': current_bands['lower_band'], + 'dma': current_bands['dma'] + } + signals.append((True, current['date'], signal_data)) + + return signals + def get_valid_tickers(min_price: float, max_price: float, min_volume: int, interval: str) -> list: """Get tickers that meet the price and volume criteria""" client = create_client() @@ -235,57 +273,36 @@ def run_sunny_scanner(min_price: float, max_price: float, min_volume: int, portf if df.empty or len(df) < 50: # Need at least 50 bars for the indicator continue - # Calculate SunnyBands - results = sunny.calculate(df) - - # Check for signals - if results['bullish_signal'].iloc[-1]: - target_price = results['upper_band'].iloc[-1] - + # Check for signals throughout the date range + signals = check_entry_signal(df) + for signal, signal_date, signal_data in signals: if calculator: try: position = calculator.calculate_position_size( - entry_price=current_price, - target_price=target_price + entry_price=signal_data['price'], + target_price=signal_data['upper_band'] ) if position['shares'] > 0: - # Update signal data with proper stop loss calculation - # Get signal date from latest data point - signal_date = df.iloc[-1]['date'] - signal_data = { + entry_data = { 'ticker': ticker, - 'entry_price': current_price, - 'target_price': target_price, + 'entry_price': signal_data['price'], + 'target_price': signal_data['upper_band'], 'signal_date': signal_date, 'volume': current_volume, 'last_update': datetime.fromtimestamp(last_update/1000000000), 'shares': position['shares'], 'position_size': position['position_value'], - 'stop_loss': current_price * 0.93, # 7% stop loss + 'stop_loss': signal_data['price'] * 0.93, # 7% stop loss 'risk_amount': position['potential_loss'], 'profit_amount': position['potential_profit'], 'risk_reward_ratio': position['risk_reward_ratio'] } - bullish_signals.append(signal_data) - # Update print output format - dollar_risk = position['potential_loss'] * -1 - signal_date = validate_signal_date(df.iloc[-1]['date']) # Get and validate the date - signal_data['signal_date'] = signal_date # Add to signal data - print_signal(signal_data, "🟢") + bullish_signals.append(entry_data) + print_signal(entry_data, "🟢") + except ValueError as e: print(f"Skipping {ticker} position: {str(e)}") continue - - elif results['bearish_signal'].iloc[-1]: - signal_date = df.iloc[-1]['date'] - bearish_signals.append({ - 'ticker': ticker, - 'price': current_price, - 'volume': current_volume, - 'signal_date': signal_date, - 'last_update': datetime.fromtimestamp(last_update/1000000000) - }) - print(f"\nšŸ”“ {ticker} @ ${current_price:.2f} on {signal_date.strftime('%Y-%m-%d %H:%M')}") except Exception as e: print(f"Error processing {ticker}: {str(e)}")