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)