Annual EPS

This commit is contained in:
Bobby Abellana 2025-02-03 22:10:09 -08:00
parent cb098278c9
commit b6c6518ad4
No known key found for this signature in database
GPG Key ID: 647714CC45F3647B
3 changed files with 56 additions and 29 deletions

View File

@ -1,6 +1,7 @@
import datetime
from screener.data_fetcher import validate_date_range, fetch_financial_data, get_stocks_in_time_range
from screener.c_canslim import check_quarterly_earnings, check_sales_growth, check_return_on_equity
from screener.c_canslim import check_quarterly_earnings
from screener.a_canslim import check_annual_eps_growth # New module
from screener.csv_appender import append_scores_to_csv
def main():
@ -27,21 +28,18 @@ def main():
if not data:
print(f"Warning: No data returned for {symbol}. Assigning default score.")
scores = {
"EPS_Score": 0.25, # EPS Growth
"Sales_Score": 0.25, # Sales Growth
"ROE_Score": 0.25 # Return on Equity
"EPS_Score": 0.25, # Quarterly EPS Growth
"Annual_EPS_Score": 0.25 # Annual EPS Growth
}
else:
# Extract relevant fields
quarterly_eps = data.get("eps", [])
sales_growth = data.get("sales_growth", [])
roe = 18 # Placeholder, modify if needed
quarterly_eps = data.get("quarterly_eps", [])
annual_eps = data.get("annual_eps", [])
# 5⃣ Compute CANSLIM Scores
scores = {
"EPS_Score": check_quarterly_earnings(quarterly_eps),
"Sales_Score": check_sales_growth(sales_growth),
"ROE_Score": check_return_on_equity(roe)
"Annual_EPS_Score": check_annual_eps_growth(annual_eps)
}
# 6⃣ Append results to a **generic** CSV file in `data/metrics/`

29
src/screener/a_canslim.py Normal file
View File

@ -0,0 +1,29 @@
def check_annual_eps_growth(annual_eps):
"""
Checks for 25%-50%+ annual EPS growth over the last three years.
Args:
annual_eps (list): List of annual EPS values (must contain at least 3 years of data).
Returns:
float: Score (1 pass, 0 fail, 0.25 insufficient data).
"""
if not annual_eps or len(annual_eps) < 3:
return 0.25 # Not enough data for 3-year growth calculation
# Calculate year-over-year EPS growth rates
growth_rates = []
for i in range(1, len(annual_eps)): # Compare consecutive years
prev_eps = annual_eps[i - 1]
current_eps = annual_eps[i]
if prev_eps <= 0: # Avoid division by zero or negative EPS
return 0.25
growth = ((current_eps - prev_eps) / abs(prev_eps)) * 100
growth_rates.append(growth)
# Check if all growth rates are 25%+
if all(rate >= 25 for rate in growth_rates):
return 1 # Pass
return 0 # Fail

View File

@ -31,8 +31,9 @@ def validate_date_range(start_date, end_date, required_quarters=4):
def fetch_financial_data(symbol, start_date, end_date):
"""
Fetch financial data (EPS, Sales Growth) from stock_financials table
for a given stock symbol within a specific date range.
Fetch financial data for a given stock symbol, including:
- Quarterly EPS for EPS Score
- Annual EPS for Annual EPS Score
Args:
symbol (str): Stock ticker symbol.
@ -40,21 +41,20 @@ def fetch_financial_data(symbol, start_date, end_date):
end_date (str or datetime): End date for data retrieval.
Returns:
dict: A dictionary containing calculated EPS and sales growth.
dict: Contains EPS, sales growth, and annual EPS.
"""
client = create_client()
# Query stock_financials for revenue, net income, and EPS
query = f"""
SELECT
filing_date,
diluted_eps,
revenue,
net_income,
diluted_eps -- Using diluted EPS for accuracy
timeframe
FROM stock_db.stock_financials
WHERE ticker = '{symbol}'
AND filing_date BETWEEN toDate('{start_date}') AND toDate('{end_date}')
AND timeframe = 'quarterly' -- Ensure only quarterly reports are used
AND (timeframe = 'quarterly' OR timeframe = 'annual') -- Fetch both annual and quarterly data
ORDER BY filing_date ASC
"""
@ -63,36 +63,36 @@ def fetch_financial_data(symbol, start_date, end_date):
if not result.result_rows:
return {}
# Extracting data
dates = []
quarterly_eps = []
annual_eps = []
revenues = []
net_incomes = []
eps_values = []
sales_growth = []
for row in result.result_rows:
dates.append(row[0])
revenues.append(row[1])
net_incomes.append(row[2])
eps_values.append(row[3]) # Directly using diluted EPS
filing_date, eps, revenue, timeframe = row
if timeframe == "quarterly":
quarterly_eps.append(eps)
revenues.append(revenue)
elif timeframe == "annual":
annual_eps.append(eps)
# Calculate Sales Growth (Quarter-over-Quarter)
for i in range(1, len(revenues)): # Start from index 1 since we compare with previous
prev_revenue = revenues[i - 1]
current_revenue = revenues[i]
if prev_revenue > 0: # Avoid division by zero
if prev_revenue > 0:
growth = ((current_revenue - prev_revenue) / prev_revenue) * 100
else:
growth = None # Not enough data
sales_growth.append(growth)
# Pad sales_growth list to match length of EPS (since first quarter lacks a previous value)
sales_growth.insert(0, None) # First quarter doesn't have a previous comparison
sales_growth.insert(0, None) # First quarter lacks comparison
return {
"symbol": symbol,
"dates": dates,
"eps": eps_values,
"quarterly_eps": quarterly_eps, # Used for EPS_Score
"annual_eps": annual_eps, # Used for Annual_EPS_Score
"sales_growth": sales_growth
}