My calculation for AAAA+
Get only the best stocks regarding others, even is there are all bad !
This is a part of the code that does the calculation, the notation takes the best and the worst for each group to get the standard deviation and calculate a rank regarding values of each stock (without taking care of variance)
#*************************************************************
def convertToGrade(num):
if num >=9.23: return 'A+'
elif num >= 8.46: return 'A'
elif num >= 7.69: return 'A-'
elif num >= 6.92: return 'B+'
elif num >= 6.15: return 'B'
elif num >= 5.38: return 'B-'
elif num >= 4.61: return 'C+'
elif num >= 3.85: return 'C'
elif num >= 3.08: return 'C-'
elif num >= 2.31: return 'D+'
elif num >= 1.54: return 'D'
elif num >= 0.77: return 'D-'
else : return 'F'
def ScaledStats_0_to_10(val, mine, maxe):
return (val - mine)/(maxe- mine)*10
#*************************************************************
#!/usr/bin/env python
# coding:utf-8
from datetime import datetime
from pandas import DataFrame as pdDataframe, read_sql as pdRead_sql
from numpy import isnan as npIsnan
from sqlalchemy import create_engine
# relative import
from sys import path;path.extend("..")
from common.Helpers.helpers import init_logger
from analyst.analyst_helpers import get_FA_Sectors
from analyst.data_loaders.finviz_aaa import run_finviz_data_loader
def getIndex():
return ["ExtraSmallCap", "MidCap", "SmallCap", "SnP500"]
def get_SQL_engine(config):
return create_engine(config.parser["ANALYST"]["ANALYST_DB_URI"])
###########################################################################################################
def convertToGrade(num):
if num >=9.23: return 'A+'
elif num >= 8.46: return 'A'
elif num >= 7.69: return 'A-'
elif num >= 6.92: return 'B+'
elif num >= 6.15: return 'B'
elif num >= 5.38: return 'B-'
elif num >= 4.61: return 'C+'
elif num >= 3.85: return 'C'
elif num >= 3.08: return 'C-'
elif num >= 2.31: return 'D+'
elif num >= 1.54: return 'D'
elif num >= 0.77: return 'D-'
else : return 'F'
def ScaledStats_0_to_10(val, mine, maxe):
return (val - mine)/(maxe- mine)*10
###########################################################################################################
def setValuationGrade(dfTickers:pdDataframe, FwdPE_ponderation=1, PEG_ponderation=1, PS_ponderation=1, PB_ponderation=1, PFCF_ponderation=1):
dfTickers["score - valuation"] = (dfTickers['score - fwd p/e'] * FwdPE_ponderation) + \
(dfTickers['score - peg'] * PEG_ponderation) + \
(dfTickers['score - p/s'] * PS_ponderation) + \
(dfTickers['score - p/b'] * PB_ponderation) + \
(dfTickers['score - p/fcf'] * PFCF_ponderation)
dfTickers["score - valuation"] = ScaledStats_0_to_10(dfTickers["score - valuation"], dfTickers["score - valuation"].min(skipna=True), dfTickers["score - valuation"].max(skipna=True))
dfTickers["AAA - valuation"] = dfTickers["score - valuation"].apply(convertToGrade)
def setProfitabilityGrade(dfTickers:pdDataframe, profitMargin_ponderation=1, OperatingMargin_ponderation=1, grossMargin_ponderation=1, ROE_ponderation=1, ROA_ponderation=1):
dfTickers["score - profitability"] = (dfTickers['score - profit m'] * profitMargin_ponderation) + \
(dfTickers['score - oper m'] * OperatingMargin_ponderation) + \
(dfTickers['score - gross m'] * grossMargin_ponderation) + \
(dfTickers['score - roe'] * ROE_ponderation) + \
(dfTickers['score - roa'] * ROA_ponderation)
dfTickers["score - profitability"] = ScaledStats_0_to_10(dfTickers["score - profitability"], dfTickers["score - profitability"].min(skipna=True), dfTickers["score - profitability"].max(skipna=True))
dfTickers["AAA - profitability"] = dfTickers["score - profitability"].apply(convertToGrade)
def setGrowthGrade(dfTickers:pdDataframe, epsThisY_ponderation=1, epsNextY_ponderation=1, epsNext5Y_ponderation=1, salesQQ_ponderation=1, epsQQ_ponderation=1):
dfTickers["score - growth"] = (dfTickers['score - eps this y'] * epsThisY_ponderation) + \
(dfTickers['score - eps next y'] * epsNextY_ponderation) + \
(dfTickers['score - eps next 5y'] * epsNext5Y_ponderation) + \
(dfTickers['score - sales q/q'] * salesQQ_ponderation) + \
(dfTickers['score - eps q/q'] * epsQQ_ponderation)
dfTickers["score - growth"] = ScaledStats_0_to_10(dfTickers["score - growth"], dfTickers["score - growth"].min(skipna=True), dfTickers["score - growth"].max(skipna=True))
dfTickers["AAA - growth"] = dfTickers["score - growth"].apply(convertToGrade)
def setPerformanceGrade(dfTickers:pdDataframe, perfMonth_ponderation=1, perfQuarter_ponderation=1, perfHalfYear_ponderation=1, perfYear_ponderation=1, perfYTD_ponderation=1, volatility_ponderation=1):
dfTickers["score - performance"] = (dfTickers['score - perf month'] * perfMonth_ponderation) + \
(dfTickers['score - perf quart'] * perfQuarter_ponderation) + \
(dfTickers['score - perf half'] * perfHalfYear_ponderation) + \
(dfTickers['score - perf year'] * perfYear_ponderation) + \
(dfTickers['score - perf ytd'] * perfYTD_ponderation) + \
(dfTickers['score - volatility m'] * volatility_ponderation)
dfTickers["score - performance"] = ScaledStats_0_to_10(dfTickers["score - performance"], dfTickers["score - performance"].min(skipna=True), dfTickers["score - performance"].max(skipna=True))
dfTickers["AAA - performance"] = dfTickers["score - performance"].apply(convertToGrade)
def setOverallRating(dfTickers:pdDataframe, valGrade_ponderation=1, profGrade_ponderation=1, growGrade_ponderation=1, perfGrade_ponderation=1):
dfTickers["score - overall"] = (dfTickers["score - valuation"] * valGrade_ponderation) + \
(dfTickers['score - profitability'] * profGrade_ponderation) + \
(dfTickers['score - growth'] * growGrade_ponderation) + \
(dfTickers['score - performance'] * perfGrade_ponderation)
dfTickers["score - overall"] = ScaledStats_0_to_10(dfTickers["score - overall"], dfTickers["score - overall"].min(skipna=True), dfTickers["score - overall"].max(skipna=True))
dfTickers["AAA - overall"] = dfTickers["score - overall"].apply(convertToGrade)
###########################################################################################################
def setGrade(dfTickersSector:pdDataframe):
for column in dfTickersSector.select_dtypes(include=['float']):
dfTickersSector["score - {0}".format(column.lower())] = ScaledStats_0_to_10(dfTickersSector[column], dfTickersSector[column].min(skipna=True), dfTickersSector[column].max(skipna=True))
for column in dfTickersSector.columns:
if column.startswith("score - "):
dfTickersSector["AAA - {0}".format(column.replace("score - ", '').lower())] = dfTickersSector[column].apply(convertToGrade)
return dfTickersSector
def make_AAA_calculation(dfTickers:pdDataframe, engine, sector=None):
setValuationGrade(dfTickers)
setProfitabilityGrade(dfTickers)
setGrowthGrade(dfTickers)
setPerformanceGrade(dfTickers)
setOverallRating(dfTickers)
if sector == None:
dfTickers.to_sql("AAA_all", con=engine, if_exists='replace', index=False)
else:
dfTickers.to_sql("AAA_{0}".format(sector), con=engine, if_exists='replace', index=False)
###########################################################################################################
def stockRatingBySector(name, logger, config, engine=None, sectors=None):
if engine == None : engine = get_SQL_engine(config=config)
if sectors == None : sectors = get_FA_Sectors()
if type(sectors) != list: sectors = [sectors,]
for sector in sectors:
try:
sqlQuery = "select * from AAA_{0}".format(sector)
dfTickersSector = pdRead_sql(sqlQuery, engine)
dfTickersSector.fillna(0, inplace=True)
dfTickersSector = setGrade(dfTickersSector)
dfTickersSector.to_sql("AAA_{0}".format(sector), con=engine, if_exists='replace', index=False)
except Exception as e:
logger.error("{0} : error while trying to set grade for sector '{1}' : {2}".format(name, sector, e))
exit(1)
logger.info("{0} : stock rating for sector : '{1}' done successfully at : {2}".format(name, sector, datetime.utcnow()))
try:
make_AAA_calculation(dfTickers=dfTickersSector, engine=engine, sector=sector)
except Exception as e:
logger.error("{0} : error while trying to make AAA calculation for sector '{1}' : {2}".format(name, sector, e))
exit(1)
logger.info("{0} : AAA calculation for sector : '{1}' done successfully at : {2}".format(name, sector, datetime.utcnow()))
logger.info("{0} : AAA calculation by sectors done successfully at : {1}".format(name, datetime.utcnow()))
###########################################################################################################
def stockRatingIndex(name, logger, config, engine=None):
if engine == None : engine = get_SQL_engine(config=config)
indexs = getIndex()
for index in indexs:
try:
sqlQuery = "select * from AAA_{0}".format(index)
dfTickersSector = pdRead_sql(sqlQuery, engine)
dfTickersSector.fillna(0, inplace=True)
dfTickersSector = setGrade(dfTickersSector)
dfTickersSector.to_sql("AAA_{0}".format(index), con=engine, if_exists='replace', index=False)
except Exception as e:
logger.error("{0} : error while trying to set grade for index '{1}' : {2}".format(name, index, e))
continue
logger.info("{0} : stock rating for indexes : '{1}' done successfully at : {2}".format(name, index, datetime.utcnow()))
try:
make_AAA_calculation(dfTickers=dfTickersSector, engine=engine, sector=index)
except Exception as e:
logger.error("{0} : error while trying to make AAA calculation for index '{1}' : {2}".format(name, index, e))
exit(1)
logger.info("{0} : AAA calculation for indexes : '{1}' done successfully at : {2}".format(name, index, datetime.utcnow()))
logger.info("{0} : AAA calculation by indexes ({1}) done successfully at : {2}".format(name, indexs, datetime.utcnow()))
###########################################################################################################
def stockRatingAll(name, logger, config, engine=None):
try:
if engine == None : engine = get_SQL_engine(config=config)
sqlQuery = "select * from AAA_all"
dfTickersAll = pdRead_sql(sqlQuery, engine)
dfTickersAll.fillna(0, inplace=True)
dfTickersAll = setGrade(dfTickersAll)
dfTickersAll.to_sql("AAA_all", con=engine, if_exists='replace', index=False)
except Exception as e:
logger.error("{0} : error while trying to set grade for all tickers : {1}".format(name, e))
try:
make_AAA_calculation(dfTickers=dfTickersAll, engine=engine)
except Exception as e:
logger.info("{0} : AAA calculation for all sectors done successfully at : {1}".format(name, datetime.utcnow()))
exit(1)
logger.info("{0} : AAA calculation for 'all' done successfully at : {1}".format(name, datetime.utcnow()))
#================================================================
if __name__ == "__main__":
from sys import argv
name = "FA_Analyst"
if len(argv) == 2: name = argv[1]
name = name.lower()
config, logger = init_logger(name=name, config="analyst")
run_finviz_data_loader(config=config, logger=logger)
logger.info("{0} : warning this AAA calculation takes every metrics with the same 'weight'...".format(name))
stockRatingBySector(name=name, logger=logger, config=config)
stockRatingIndex(name=name, logger=logger, config=config)
stockRatingAll(name=name, logger=logger, config=config)