stock_system/src/screener/l_canslim.py

115 lines
3.7 KiB
Python

import csv
import os
from db.db_connection import create_client
# Load SIC Industry Data
SIC_LOOKUP = {}
def load_sic_data():
"""Loads SIC Code data into a dictionary from the new CSV location above `src/`."""
global SIC_LOOKUP
script_dir = os.path.dirname(os.path.abspath(__file__)) # Get the directory of l_canslim.py
project_root = os.path.abspath(os.path.join(script_dir, "../../")) # Go up to project root
sic_file = os.path.join(project_root, "industry_sic_codes.csv") # Adjust path
if not os.path.exists(sic_file):
raise FileNotFoundError(f"Error: SIC Code CSV file not found at {sic_file}")
with open(sic_file, mode="r", encoding="utf-8") as file:
reader = csv.DictReader(file)
for row in reader:
sic_code = row["SIC Code"].strip() # Match CSV header exactly
industry = row["Industry Title"].strip() # Match CSV header exactly
SIC_LOOKUP[sic_code] = industry
# Ensure SIC data is loaded at module import
load_sic_data()
def check_industry_leadership(symbol):
"""
Determines if a stock is a leader in its industry group.
Criteria:
- RSI should be 60 or higher as a strength indicator
- Stock should be trading near its 52-week high
- Must have valid industry classification
Args:
symbol (str): Stock ticker symbol.
Returns:
float: 1 (Pass), 0 (Fail), 0.25 (Insufficient Data).
"""
client = create_client()
# First get the SIC code from stock_tickers table
sic_query = f"""
SELECT sic_code
FROM stock_db.stock_tickers
WHERE ticker = '{symbol}'
"""
# Get RSI from stock_indicators and price data from stock_prices_daily
metrics_query = f"""
WITH latest_date AS (
SELECT MAX(date) as max_date
FROM stock_db.stock_prices_daily
WHERE ticker = '{symbol}'
),
year_range AS (
SELECT
close as current_price,
(
SELECT MAX(close)
FROM stock_db.stock_prices_daily
WHERE ticker = '{symbol}'
AND date >= DATE_SUB(
(SELECT max_date FROM latest_date),
INTERVAL 52 WEEK
)
) as high_52_week
FROM stock_db.stock_prices_daily
WHERE ticker = '{symbol}'
AND date = (SELECT max_date FROM latest_date)
),
latest_rsi AS (
SELECT rsi
FROM stock_db.stock_indicators
WHERE ticker = '{symbol}'
ORDER BY date DESC
LIMIT 1
)
SELECT
yr.current_price,
yr.high_52_week,
lr.rsi
FROM year_range yr
CROSS JOIN latest_rsi lr
"""
# Execute queries
sic_result = client.query(sic_query)
metrics_result = client.query(metrics_query)
if not sic_result.result_rows or not metrics_result.result_rows:
return 0.25 # Not enough data
sic = sic_result.result_rows[0][0]
if not sic or str(sic) not in SIC_LOOKUP:
return 0.25 # No SIC industry data available
current_price, high_52_week, rsi = metrics_result.result_rows[0]
# Ensure we have valid data
if high_52_week is None or current_price is None or rsi is None:
return 0.25 # Missing necessary data
# Industry Leader Criteria
passes_rs = rsi >= 60 # Using RSI as a substitute for relative strength
near_high = current_price >= (high_52_week * 0.90) # Within 10% of 52-week high
if passes_rs and near_high:
return 1 # Stock is an industry leader
else:
return 0 # Stock is lagging