diff --git a/src/screener/t_atr_ema.py b/src/screener/t_atr_ema.py index 65fd273..edfe078 100644 --- a/src/screener/t_atr_ema.py +++ b/src/screener/t_atr_ema.py @@ -71,50 +71,7 @@ def run_atr_ema_scanner(min_price: float, max_price: float, min_volume: int, por end_ts = int(end_date.timestamp() * 1000000000) try: - with create_client() as client: - query = f""" - WITH filtered_data AS ( - SELECT - ticker, - window_start, - close, - volume, - toDateTime(toDateTime(window_start/1000000000)) as trade_date - FROM stock_db.stock_prices - WHERE window_start BETWEEN {start_ts} AND {end_ts} - AND toDateTime(window_start/1000000000) <= now() - ), - daily_data AS ( - SELECT - ticker, - toDate(trade_date) as date, - argMax(close, window_start) as daily_close, - sum(volume) as daily_volume - FROM filtered_data - GROUP BY ticker, toDate(trade_date) - HAVING daily_close BETWEEN {min_price} AND {max_price} - AND daily_volume >= {min_volume} - ), - latest_data AS ( - SELECT - ticker, - argMax(daily_close, date) as last_close, - sum(daily_volume) as total_volume, - max(toUnixTimestamp(date)) as last_update - FROM daily_data - GROUP BY ticker - ) - SELECT - ticker, - last_close, - total_volume, - last_update - FROM latest_data - ORDER BY ticker - """ - - result = client.query(query) - qualified_stocks = [(row[0], row[1], row[2], row[3]) for row in result.result_rows] + qualified_stocks = get_qualified_stocks(start_date, end_date, min_price, max_price, min_volume) if not qualified_stocks: print("No stocks found matching criteria.") diff --git a/src/screener/t_atr_ema_v2.py b/src/screener/t_atr_ema_v2.py index a4d65be..1a05425 100644 --- a/src/screener/t_atr_ema_v2.py +++ b/src/screener/t_atr_ema_v2.py @@ -79,51 +79,7 @@ def run_atr_ema_scanner_v2(min_price: float, max_price: float, min_volume: int, end_ts = int(end_date.timestamp() * 1000000000) try: - with create_client() as client: - # Query to get qualified stocks - query = f""" - WITH filtered_data AS ( - SELECT - ticker, - window_start, - close, - volume, - toDateTime(toDateTime(window_start/1000000000)) as trade_date - FROM stock_db.stock_prices - WHERE window_start BETWEEN {start_ts} AND {end_ts} - AND toDateTime(window_start/1000000000) <= now() - ), - daily_data AS ( - SELECT - ticker, - toDate(trade_date) as date, - argMax(close, window_start) as daily_close, - sum(volume) as daily_volume - FROM filtered_data - GROUP BY ticker, toDate(trade_date) - HAVING daily_close BETWEEN {min_price} AND {max_price} - AND daily_volume >= {min_volume} - ), - latest_data AS ( - SELECT - ticker, - argMax(daily_close, date) as last_close, - sum(daily_volume) as total_volume, - max(toUnixTimestamp(date)) as last_update - FROM daily_data - GROUP BY ticker - ) - SELECT - ticker, - last_close, - total_volume, - last_update - FROM latest_data - ORDER BY ticker - """ - - result = client.query(query) - qualified_stocks = [(row[0], row[1], row[2], row[3]) for row in result.result_rows] + qualified_stocks = get_qualified_stocks(start_date, end_date, min_price, max_price, min_volume) if not qualified_stocks: print("No stocks found matching criteria.") diff --git a/src/screener/t_sunnyband.py b/src/screener/t_sunnyband.py index cc29558..b1fe9b0 100644 --- a/src/screener/t_sunnyband.py +++ b/src/screener/t_sunnyband.py @@ -213,58 +213,12 @@ def run_sunny_scanner(min_price: float, max_price: float, min_volume: int, portf start_ts = int(start_date.timestamp() * 1000000000) try: - with create_client() as client: - # Query to get stocks meeting criteria with their latest data - query = f""" - WITH filtered_data AS ( - SELECT - ticker, - window_start, - close, - volume, - toDateTime(toDateTime(window_start/1000000000)) as trade_date - FROM stock_db.stock_prices - WHERE window_start BETWEEN {start_ts} AND {end_ts} - AND toDateTime(window_start/1000000000) <= now() - ), - daily_data AS ( - SELECT - ticker, - toDate(trade_date) as trade_date, - argMax(close, window_start) as daily_close, - sum(volume) as daily_volume - FROM filtered_data - GROUP BY ticker, toDate(trade_date) - HAVING daily_close BETWEEN {min_price} AND {max_price} - AND daily_volume >= {min_volume} - ), - latest_data AS ( - SELECT - ticker, - argMax(daily_close, trade_date) as last_close, - sum(daily_volume) as total_volume, - max(toUnixTimestamp(trade_date)) as last_update - FROM daily_data - GROUP BY ticker - ) - SELECT - ticker, - last_close, - total_volume, - last_update - FROM latest_data - ORDER BY ticker - """ - - result = client.query(query) - qualified_stocks = [(row[0], row[1], row[2], row[3]) for row in result.result_rows] - - qualified_stocks = [(row[0], row[1], row[2], row[3]) for row in result.result_rows] + qualified_stocks = get_qualified_stocks(start_date, end_date, min_price, max_price, min_volume) if not qualified_stocks: print("No stocks found matching criteria.") return - + print(f"\nFound {len(qualified_stocks)} stocks matching criteria") # Initialize indicators diff --git a/src/utils/data_utils.py b/src/utils/data_utils.py index 6bab95a..3cc7c58 100644 --- a/src/utils/data_utils.py +++ b/src/utils/data_utils.py @@ -38,6 +38,75 @@ def print_signal(signal_data: dict, signal_type: str = "🔍") -> None: # Print available keys for debugging print(f"Available keys: {list(signal_data.keys())}") +def get_qualified_stocks(start_date: datetime, end_date: datetime, min_price: float, max_price: float, min_volume: int) -> list: + """ + Get qualified stocks based on price and volume criteria within date range + + Args: + start_date (datetime): Start date for data fetch + end_date (datetime): End date for data fetch + min_price (float): Minimum stock price + max_price (float): Maximum stock price + min_volume (int): Minimum trading volume + + Returns: + list: List of tuples (ticker, price, volume, last_update) + """ + try: + start_ts = int(start_date.timestamp() * 1000000000) + end_ts = int(end_date.timestamp() * 1000000000) + + with create_client() as client: + query = f""" + WITH filtered_data AS ( + SELECT + ticker, + window_start, + close, + volume, + toDateTime(toDateTime(window_start/1000000000)) as trade_date + FROM stock_db.stock_prices + WHERE window_start BETWEEN {start_ts} AND {end_ts} + AND toDateTime(window_start/1000000000) <= now() + ), + daily_data AS ( + SELECT + ticker, + toDate(trade_date) as date, + argMax(close, window_start) as daily_close, + sum(volume) as daily_volume + FROM filtered_data + GROUP BY ticker, toDate(trade_date) + HAVING daily_close BETWEEN {min_price} AND {max_price} + AND daily_volume >= {min_volume} + ), + latest_data AS ( + SELECT + ticker, + argMax(daily_close, date) as last_close, + sum(daily_volume) as total_volume, + max(toUnixTimestamp(date)) as last_update + FROM daily_data + GROUP BY ticker + ) + SELECT + ticker, + last_close, + total_volume, + last_update + FROM latest_data + ORDER BY ticker + """ + + result = client.query(query) + qualified_stocks = [(row[0], row[1], row[2], row[3]) for row in result.result_rows] + + return qualified_stocks + + except Exception as e: + print(f"Error getting qualified stocks: {str(e)}") + return [] + def save_signals_to_csv(signals: list, scanner_name: str) -> None: """ Save signals to CSV file with standardized format and naming