89 lines
2.9 KiB
Python
89 lines
2.9 KiB
Python
from db.db_connection import create_client
|
|
|
|
def check_institutional_sponsorship(symbol):
|
|
"""
|
|
Determines if a stock has strong institutional sponsorship.
|
|
|
|
Criteria:
|
|
- Should have at least several institutional sponsors
|
|
- Look for increasing institutional ownership
|
|
- Focus on higher-quality institutions
|
|
- Avoid stocks with too much institutional ownership (>80-90%)
|
|
|
|
Args:
|
|
symbol (str): Stock ticker symbol.
|
|
|
|
Returns:
|
|
float: 1 (Pass), 0 (Fail), 0.25 (Insufficient Data)
|
|
"""
|
|
client = create_client()
|
|
|
|
# Get current institutional ownership data
|
|
query = """
|
|
SELECT
|
|
COUNT(DISTINCT holder_name) as num_institutions,
|
|
SUM(percentage_held) as total_ownership,
|
|
MAX(date_reported) as latest_date
|
|
FROM stock_db.yf_institutional_holders
|
|
WHERE ticker = '{}'
|
|
GROUP BY ticker
|
|
""".format(symbol)
|
|
|
|
result = client.query(query)
|
|
|
|
if not result.result_rows:
|
|
return 0.25 # Insufficient data
|
|
|
|
num_institutions, total_ownership, _ = result.result_rows[0]
|
|
|
|
# Get ownership trend (comparing with 3 months ago)
|
|
trend_query = """
|
|
WITH current AS (
|
|
SELECT SUM(percentage_held) as current_ownership,
|
|
MAX(date_reported) as latest_date
|
|
FROM stock_db.yf_institutional_holders
|
|
WHERE ticker = '{}'
|
|
),
|
|
previous AS (
|
|
SELECT SUM(percentage_held) as previous_ownership
|
|
FROM stock_db.yf_institutional_holders
|
|
WHERE ticker = '{}'
|
|
AND date_reported <= (SELECT latest_date - INTERVAL 3 MONTH FROM current)
|
|
)
|
|
SELECT current_ownership, previous_ownership
|
|
FROM current, previous
|
|
""".format(symbol, symbol)
|
|
|
|
trend_result = client.query(trend_query)
|
|
|
|
# Evaluate criteria
|
|
if num_institutions is None or total_ownership is None:
|
|
return 0.25
|
|
|
|
# Convert total_ownership to percentage (0-100 scale)
|
|
total_ownership = float(total_ownership)
|
|
|
|
# Criteria thresholds
|
|
MIN_INSTITUTIONS = 10
|
|
MIN_OWNERSHIP = 20 # percentage
|
|
MAX_OWNERSHIP = 85 # percentage
|
|
|
|
# Basic institutional presence check
|
|
has_sufficient_institutions = num_institutions >= MIN_INSTITUTIONS
|
|
has_healthy_ownership = MIN_OWNERSHIP <= total_ownership <= MAX_OWNERSHIP
|
|
|
|
# Check ownership trend
|
|
ownership_increasing = False
|
|
if trend_result.result_rows:
|
|
current_ownership, previous_ownership = trend_result.result_rows[0]
|
|
if current_ownership and previous_ownership:
|
|
ownership_increasing = current_ownership > previous_ownership
|
|
|
|
# Final evaluation
|
|
if has_sufficient_institutions and has_healthy_ownership and ownership_increasing:
|
|
return 1
|
|
elif not has_sufficient_institutions or total_ownership < MIN_OWNERSHIP:
|
|
return 0
|
|
else:
|
|
return 0.25 # Borderline cases
|