refactor: Update sunny scanner to use intraday stock_prices table

This commit is contained in:
Bobby Abellana (aider) 2025-02-07 00:28:58 -08:00 committed by Bobby Abellana
parent 7faf56a712
commit d0583ddcc3
No known key found for this signature in database
GPG Key ID: 647714CC45F3647B

View File

@ -1,4 +1,5 @@
import os import os
import os
import numpy as np import numpy as np
from datetime import datetime, timedelta from datetime import datetime, timedelta
import pandas as pd import pandas as pd
@ -276,24 +277,41 @@ def run_sunny_scanner(min_price: float, max_price: float, min_volume: int, portf
interval = get_interval_choice() interval = get_interval_choice()
end_date = datetime.now() end_date = datetime.now()
start_date = end_date - timedelta(days=1) start_date = end_date - timedelta(days=1) # Get last trading day
# First get the data from database # First get qualified stocks from database
client = create_client() client = create_client()
# Query to get stocks meeting criteria # Convert dates to Unix timestamp in nanoseconds
end_ts = int(end_date.timestamp() * 1000000000)
start_ts = int(start_date.timestamp() * 1000000000)
# Query to get stocks meeting criteria with their latest data
query = f""" query = f"""
SELECT DISTINCT ticker, close WITH latest_data AS (
FROM stock_db.stock_prices_daily SELECT
WHERE date = (SELECT max(date) FROM stock_db.stock_prices_daily) ticker,
AND close BETWEEN {min_price} AND {max_price} argMax(close, window_start) as last_close,
AND volume >= {min_volume} sum(volume) as total_volume,
max(window_start) as last_update
FROM stock_db.stock_prices
WHERE window_start BETWEEN {start_ts} AND {end_ts}
GROUP BY ticker
HAVING last_close BETWEEN {min_price} AND {max_price}
AND total_volume >= {min_volume}
)
SELECT
ticker,
last_close,
total_volume,
last_update
FROM latest_data
ORDER BY ticker ORDER BY ticker
""" """
try: try:
result = client.query(query) result = client.query(query)
qualified_stocks = [(row[0], row[1]) for row in result.result_rows] qualified_stocks = [(row[0], row[1], row[2], row[3]) for row in result.result_rows]
if not qualified_stocks: if not qualified_stocks:
print("No stocks found matching criteria.") print("No stocks found matching criteria.")
@ -311,14 +329,18 @@ def run_sunny_scanner(min_price: float, max_price: float, min_volume: int, portf
bearish_signals = [] bearish_signals = []
# Process each qualified stock # Process each qualified stock
for ticker, current_price in qualified_stocks: for ticker, current_price, current_volume, last_update in qualified_stocks:
try: try:
# Get historical data based on interval
df = get_stock_data(ticker, start_date, end_date, interval) df = get_stock_data(ticker, start_date, end_date, interval)
if df.empty or len(df) < 50:
if df.empty or len(df) < 50: # Need at least 50 bars for the indicator
continue continue
# Calculate SunnyBands
results = sunny.calculate(df) results = sunny.calculate(df)
# Check for signals
if results['bullish_signal'].iloc[-1]: if results['bullish_signal'].iloc[-1]:
target_price = results['upper_band'].iloc[-1] target_price = results['upper_band'].iloc[-1]
@ -329,6 +351,8 @@ def run_sunny_scanner(min_price: float, max_price: float, min_volume: int, portf
'ticker': ticker, 'ticker': ticker,
'entry': current_price, 'entry': current_price,
'target': target_price, 'target': target_price,
'volume': current_volume,
'last_update': datetime.fromtimestamp(last_update/1000000000),
'shares': position['shares'], 'shares': position['shares'],
'position_size': position['position_value'], 'position_size': position['position_value'],
'stop_loss': position['stop_loss'], 'stop_loss': position['stop_loss'],
@ -344,22 +368,32 @@ def run_sunny_scanner(min_price: float, max_price: float, min_volume: int, portf
elif results['bearish_signal'].iloc[-1]: elif results['bearish_signal'].iloc[-1]:
bearish_signals.append({ bearish_signals.append({
'ticker': ticker, 'ticker': ticker,
'price': current_price 'price': current_price,
'volume': current_volume,
'last_update': datetime.fromtimestamp(last_update/1000000000)
}) })
print(f"\n🔴 {ticker} at ${current_price:.2f}") print(f"\n🔴 {ticker} at ${current_price:.2f}")
except Exception as e: except Exception as e:
print(f"Error processing {ticker}: {str(e)}")
continue continue
# Save results # Save results
output_date = datetime.now().strftime("%Y%m%d") output_dir = 'reports'
os.makedirs(output_dir, exist_ok=True)
output_date = datetime.now().strftime("%Y%m%d_%H%M")
if bullish_signals: if bullish_signals:
df_bullish = pd.DataFrame(bullish_signals) df_bullish = pd.DataFrame(bullish_signals)
df_bullish.to_csv(f'reports/sunny_bullish_{output_date}.csv', index=False) output_file = f'{output_dir}/sunny_bullish_{output_date}.csv'
df_bullish.to_csv(output_file, index=False)
print(f"\nSaved bullish signals to {output_file}")
if bearish_signals: if bearish_signals:
df_bearish = pd.DataFrame(bearish_signals) df_bearish = pd.DataFrame(bearish_signals)
df_bearish.to_csv(f'reports/sunny_bearish_{output_date}.csv', index=False) output_file = f'{output_dir}/sunny_bearish_{output_date}.csv'
df_bearish.to_csv(output_file, index=False)
print(f"\nSaved bearish signals to {output_file}")
print(f"\nFound {len(bullish_signals)} bullish and {len(bearish_signals)} bearish signals") print(f"\nFound {len(bullish_signals)} bullish and {len(bearish_signals)} bearish signals")