Financial Fundamentals Labels for ThinkorSwim


Thanks for the quick reply. I tried the code in post #1 and the chart link in post #3. All I get is a single turquoise line on my chart but none of the labels (including no overall score). I've downloaded many things without problems (both links and codes) but can't seem to get the indicator nor the code to work.
 

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Thanks for the quick reply. I tried the code in post #1 and the chart link in post #3. All I get is a single turquoise line on my chart but none of the labels (including no overall score). I've downloaded many things without problems (both links and codes) but can't seem to get the indicator nor the code to work.
Only works on a Daily chart. There are only labels in Post#1 There are no plotted lines.
If you are getting plotted lines. You didn't copy and paste the code from here:
https://usethinkscript.com/threads/financial-fundamentals-labels-for-thinkorswim.5308/#post-49796
 
In this updated script, each individual fundamental labels can be turned on and off.
When doing financial research, one would want to look at all 23 labels.

But once, you have created your corral of stocks, you might want to only display the 8-9 most important labels to remind yourself, why this stock is in your corral.

In this version, the 8-9 most important fundamentals have been selected based on what members seem most concerned about.
You should turn on and off those fundamentals most important to you.

ngIS6av.png

Ruby:
#Fundamental Data Labels _Mobius 4/26/20 (found on OneNote)
#
# @MerryDay revised 4/21:
# my interpretation of positive/negative values; should be modified to meet your strategy
# then calculated an overall weighted score based on:
# https://tradestation.tradingappstore.com/products/FundamentalScore/document/Fundamental_Score.pdf
# and other information found on the web
declare lower;
DefineGlobalColor("Pre_Cyan", CreateColor(50, 200, 255)) ;
DefineGlobalColor("LabelGreen",  CreateColor(0, 165, 0)) ;
DefineGlobalColor("LabelRed",  CreateColor(225, 0, 0)) ;
DefineGlobalColor("Violet", CreateColor (200, 125, 255)) ;
DefineGlobalColor("GrayGreen",  CreateColor(155, 167, 76)) ;
DefineGlobalColor("LitePink", CreateColor (220, 180, 180)) ;
DefineGlobalColor("neutral",  color.light_gray) ;
input lPE = yes ;
input lEPS = yes ;
input lCASH = yes ;
input lGP = yes ;
input lOP = no ;
input lNP = no ;
input lCRatio = no ;
input lQRatio = yes ;
input lROA = no ;
input lROE = yes ;
input lSPS = yes ;
input lFCC = no ;
input lAssTURNS = no ;
input lFinLev = no ;
input lBV = no ;
input lDEBT = yes ;
input lInvTurn = no ;
input lDivOUT = no ;
input lDPS = no ;
input lDIV = no ;
input lIR = no ;
input lTR = no ;
input lSCORE = yes ;

def fp = FiscalPeriod.YEAR;
def EPS = EarningsPerShareTTM(fiscalPeriod = fp);
def PE = round(close / EPS,1);
AddLabel(lPE and PE, "P/E ratio = " + Round(PE, 2),
                      if PE < 0 then GlobalColor("LitePink") else
                      if PE < 20 then GlobalColor("LabelGreen") else
                      if PE < 40 then GlobalColor("GrayGreen") else GlobalColor("Pre_Cyan"));

def EarnPerShare = if IsNaN(EarningsPerShareTTM())
                   then EarnPerShare[1]
                   else EarningsPerShareTTM();
AddLabel(lEPS and EarnPerShare, "EPS-TTM = " + AsDollars(EarnPerShare),
                      if EarnPerShare > 0 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));

def FreeCashFlowPerSh = if isNaN(FreeCashFlowPerShare())
                        then FreeCashFlowPerSh[1]
                        else FreeCashFlowPerShare();
AddLabel(lCASH and FreeCashFlowPerSh, "Free Cash Flow Per Share = " + AsDollars(FreeCashFlowPerSh),
                  if FreeCashFlowPerSh > 0 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));
def score_EarnCash = if PE <0 and FreeCashFlowPerSh < 0 and EarnPerShare < 0 then 0 else 5;

def Gross_Profit_Margin = if IsNaN(GrossProfitMargin())
                          then Gross_Profit_Margin[1]
                          else GrossProfitMargin();
AddLabel(lGP and Gross_Profit_Margin, "Gross Profit Margin = " + Round(Gross_Profit_Margin, 2),
               if Gross_Profit_Margin > 0 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));

def Operating_Profit_Margin = if IsNaN(OperatingProfitMargin())
                              then Operating_Profit_Margin[1]
                              else OperatingProfitMargin();
AddLabel(lOP and Operating_Profit_Margin, "Operating Profit Margin = " + Round(Operating_Profit_Margin, 2),           
              if Operating_Profit_Margin > 0 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));


def Net_Profit_Margin = if IsNaN(NetProfitMargin())
                        then Net_Profit_Margin[1]
                        else NetProfitMargin();
AddLabel(lNP and Net_Profit_Margin, "Net Profit Margin = " + Round(Net_Profit_Margin, 2),
               if Net_Profit_Margin > 0 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));
def score_Profits = if Gross_Profit_Margin>0 or Net_Profit_Margin>0 or Operating_Profit_Margin > 0 then 3 else 0 ;

def CurRatio = if IsNaN(CurrentRatio())
               then CurRatio[1]
               else CurrentRatio();
AddLabel(lCRatio and CurRatio, "Current Ratio = " + Round(CurRatio, 2),
               if CurRatio > 2  then GlobalColor("GrayGreen") else
               if CurRatio >= 1 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));

def Quick_Ratio = if IsNaN(QuickRatio())
                  then Quick_Ratio[1]
                  else QuickRatio();
AddLabel(lQRatio and Quick_Ratio, "Quick Ratio = " + Round(Quick_Ratio, 2),
               if Quick_Ratio > 2  then GlobalColor("GrayGreen") else
               if Quick_Ratio >= 1 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));
def score_Ratios = if Quick_Ratio >= 1 or CurRatio >= 1 then 3 else 0;

def Return_On_Assets = if IsNaN(ReturnOnAssets())
                       then Return_On_Assets[1]
                       else ReturnOnAssets();
AddLabel(lROA and Return_On_Assets, "Return On Assets = " + Round(Return_On_Assets),
              if Return_On_Assets >= 15 then GlobalColor("Pre_Cyan") else
              if Return_On_Assets >= 10 then GlobalColor("LabelGreen") else
              if Return_On_Assets > 0 then GlobalColor("GrayGreen") else GlobalColor("LitePink"));


def Return_On_Equity = if IsNaN(ReturnOnEquity())
                       then Return_On_Equity[1]
                       else ReturnOnEquity();
AddLabel(lROE and Return_On_Equity, "Return On Equity = " + Round(Return_On_Equity),
              if Return_On_Equity >= 15 then GlobalColor("Pre_Cyan") else
              if Return_On_Equity >= 10 then GlobalColor("LabelGreen") else
              if Return_On_Equity > 0 then GlobalColor("GrayGreen") else GlobalColor("LitePink"));
def score_Returns = if Return_On_Equity >= 10 or Return_On_Assets >=10 then 1 else 0 ;


def Sales_Per_Share = if IsNaN(SalesPerShare())
                      then Sales_Per_Share[1]
                      else SalesPerShare();
AddLabel(lSPS and Sales_Per_Share, "Sales Per Share = " + Round(Sales_Per_Share, 2),
                      if Sales_Per_Share > 0 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));
def score_Sales_Per_Share = if Sales_Per_Share > 0 then 1 else 0;

def FixChgCovRatio = if IsNaN(FixedChargeCoverageRatio())
                     then FixChgCovRatio[1]
                     else FixedChargeCoverageRatio();
AddLabel(lFCC and FixChgCovRatio, "Fixed Charge Coverage Ratio = " + Round(FixChgCovRatio, 2),
                     if FixChgCovRatio >= 1 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));

def Total_Asset_Turnover = if IsNaN(TotalAssetTurnover())
                           then Total_Asset_Turnover[1]
                           else TotalAssetTurnover();
AddLabel(lAssTURNS and Total_Asset_Turnover, "Total Asset Turnover = " + Round(Total_Asset_Turnover, 2),
               if Total_Asset_Turnover > 1 then GlobalColor("LabelGreen") else  GlobalColor("neutral"));

def FinLev = if IsNaN(FinancialLeverage())
             then FinLev[1]
             else FinancialLeverage();
AddLabel(lFinLev and FinLev, "Financial Leverage = " + Round(FinLev, 2),
                      if FinLev > 0 and FinLev < 2 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));
def score_FinLev = if FinLev < 2 then 1 else 0;

def BookValue = if IsNaN(BookValuePerShare())
                then BookValue[1]
                else BookValuePerShare();
AddLabel(lBV and BookValue, "Book Value Per Share = " + Round(BookValue),
                if BookValue < 2 then GlobalColor("Pre_Cyan") else
                if BookValue < 3 then GlobalColor("LabelGreen") else GlobalColor("neutral"));

def Long_Term_Debt_To_Capital = if IsNaN(LongTermDebtToCapital())
                                then Long_Term_Debt_To_Capital[1]
                                else LongTermDebtToCapital();
AddLabel(lDEBT and Long_Term_Debt_To_Capital, "Long Term Debt To Capital = " + Round(Long_Term_Debt_To_Capital, 2),
 if Long_Term_Debt_To_Capital < 5 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));
def score_Long_Term_Debt_To_Capital = if Long_Term_Debt_To_Capital < 5 then 1 else 0;

def Inventory_Turnover = if IsNaN(InventoryTurnover())
                         then Inventory_Turnover[1]
                         else InventoryTurnover();
AddLabel(lInvTurn and Inventory_Turnover, "Inventory Turnover = " + Round(Inventory_Turnover, 2),
               if Inventory_Turnover < 5  then GlobalColor("LitePink") else
               if Inventory_Turnover < 10 then GlobalColor("Pre_Cyan") else
               if Inventory_Turnover < 15 then GlobalColor("GrayGreen") else GlobalColor("LitePink"));

def DivPayout = if IsNaN(DividendPayout())
                then DivPayout[1]
                else DividendPayout();
AddLabel(lDivOUT and DivPayout, "Dividend Payout = " + round(DivPayout,2) + "%", GlobalColor("neutral"));

def DivPerShare = if IsNaN(DividendsPerShareTTM())
                  then DivPerShare[1]
                  else DividendsPerShareTTM();
AddLabel(lDPS and DivPerShare, "Dividend Per Share = " + AsDollars(DivPerShare), GlobalColor("neutral"));

def DivYield = if IsNaN(DividendsPerShareTTM())
                  then DivPerShare[1]
                  else DividendsPerShareTTM()/Close;
AddLabel(lDIV and DivPerShare, "Dividend Yield = " + AsPercent(DivYield), GlobalColor("neutral"));

def Interest_Rate = if IsNaN(InterestRate())
                    then Interest_Rate[1]
                    else InterestRate();
AddLabel(lIR and Interest_Rate, "Interest Rate = " + Round(Interest_Rate, 2), GlobalColor("neutral"));

def Tax_Rate = if IsNaN(TaxRate())
               then Tax_Rate[1]
               else TaxRate();
AddLabel(lTR and Tax_Rate, "Tax Rate = " + Round(Tax_Rate, 2), GlobalColor("neutral"));

def score = score_Returns + score_EarnCash + score_ratios + score_Profits
           + score_FinLev + score_Sales_Per_Share + score_Long_Term_Debt_To_Capital;

AddLabel(lSCORE, "SCORE: " + score,
if score >= 12 then GlobalColor("Pre_Cyan") else
if score >= 10 then GlobalColor("LabelGreen") else
if score >= 8 then GlobalColor("GrayGreen") else GlobalColor("LitePink"),
Location.BOTTOM_LEFT);
 
@MerryDay I've found that the fundamental score is blacked out on certain tickers, CAT, HD, MSFT, AAPL, CRM to name a few but then on COST, works fine.
1737643550352.png
 
Last edited:
@MerryDay I've found that the fundamental score is blacked out on certain tickers, CAT, HD, MSFT, AAPL, CRM to name a few but then on COST, works fine.

Here is a shared grid link w/ labels displaying that the fundamental labels do work
http://tos.mx/!MJhHZANS MUST follow these instructions for loading shared links.
NFZbgNX.png



If your question is why is there not a total score for CAT, HD, MSFT, AAPL, CRM but yet there is a total score for Costco.

Answer:
Score is only calculated on current year reported earnings. Out of the stocks that you listed, only COSTCO has earnings reported so far.

@JSCS_22
 
Last edited by a moderator:
Thank you for these studies. Would you happen to know if it's possible to display this data in a chart form, as in the historical data and most recent, to be able to visually see any changes with the balance sheet numbers, cash flows, revenues, etc?
Thank you
 
Thank you for these studies. Would you happen to know if it's possible to display this data in a chart form, as in the historical data and most recent, to be able to visually see any changes with the balance sheet numbers, cash flows, revenues, etc?
Thank you

To Graph Fundamentals On A Chart.

1. Choose which fundamental you want to graph
2. Copy that definition statement from the beginning post into a new study.
3. Add the following code to create the plot:
declare lower;
plot x = name of whatever fundamental that you are plotting;

Here is an example to get you started
Ruby:
def EarnPerShare = if IsNaN(EarningsPerShareTTM())
                   then EarnPerShare[1]
                   else EarningsPerShareTTM();

declare lower;
plot x = EarnPerShare;


Here is an example graphing two of the fundamentals:
shared chart link: http://tos.mx/!OH8kpQrE MUST follow these instructions for loading shared links.
qvHuuE7.png
 
Last edited:
To Graph Fundamentals On A Chart.

1. Choose which fundamental you want to graph
2. Copy that definition statement into a new study.
3. Add the following code to create the plot:


Here is an example to get you started
Ruby:
def EarnPerShare = if IsNaN(EarningsPerShareTTM())
                   then EarnPerShare[1]
                   else EarningsPerShareTTM();

declare lower;
plot x = EarnPerShare;


Here is an example graphing two of the fundamentals:
shared chart link: http://tos.mx/!OH8kpQrE MUST follow these instructions for loading shared links.
qvHuuE7.png
Thank you so very much. I called Schwab several days ago and spoke with their Tier 3 support and even programmers; no one could help with the line chart. It was possible to display the current value only what I was told.

And are these fundamental labels that could work? https://toslc.thinkorswim.com/center/howToTos/thinkManual/Scan/Fundamental-Filters

To Graph Fundamentals On A Chart.

1. Choose which fundamental you want to graph
2. Copy that definition statement into a new study.
3. Add the following code to create the plot:


Here is an example to get you started
Ruby:
def EarnPerShare = if IsNaN(EarningsPerShareTTM())
                   then EarnPerShare[1]
                   else EarningsPerShareTTM();

declare lower;
plot x = EarnPerShare;


Here is an example graphing two of the fundamentals:
shared chart link: http://tos.mx/!OH8kpQrE MUST follow these instructions for loading shared links.
qvHuuE7.png
I tried to make a new fundamentals indicator using a Book value per share, but I get an error,

def BookValuePerShare = if IsNaN(BookValuePerShareTTM())
then BookValuePerShare[1]
else BookValuePerShareTTM();

declare lower;
plot x = BookValuePerShare;

No such function BookValuePerShareTTM

Am I missing something?

Thank you.
 
Thank you so very much. I called Schwab several days ago and spoke with their Tier 3 support and even programmers; no one could help with the line chart. It was possible to display the current value only what I was told.

And are these fundamental labels that could work? https://toslc.thinkorswim.com/center/howToTos/thinkManual/Scan/Fundamental-Filters


I tried to make a new fundamentals indicator using a Book value per share, but I get an error,

def BookValuePerShare = if IsNaN(BookValuePerShareTTM())
then BookValuePerShare[1]
else BookValuePerShareTTM();

declare lower;
plot x = BookValuePerShare;

No such function BookValuePerShareTTM

Am I missing something?

Thank you.


The Fundamentals are already defined in the code at the beginning of this post:
https://usethinkscript.com/threads/financial-fundamentals-labels-for-thinkorswim.5308/
You can copy the one that you want.

or

If you have autocomplete turned on in settings;
ToS will automatically provide the correct syntax for any Fundamental, Constant, Declaration, or Indicator.
0faGYJG.png



Ruby:
def BookValue = if IsNaN(BookValuePerShare())
                then BookValue[1]
                else BookValuePerShare();
            
declare lower;
plot x = BookValue;

ToS Support, deservedly, has an unparallel excellent reputation.
They can walk you through all facets of the ThinkOrSwim app.

However, they can not / will not write custom code.
Nor can they provide support for troubleshooting custom code.

Thus the reason, the forum was born.
Through stumbling, experimenting, and figuring things out together.
Members are inspired to
take ThinkScript where no man has gone before...
;)
 
Last edited by a moderator:
The Fundamentals are already defined in the code at the beginning of this post:
https://usethinkscript.com/threads/financial-fundamentals-labels-for-thinkorswim.5308/
You can copy the one that you want.

or

If you have autocomplete turned on in settings;
ToS will automatically provide the correct syntax for any Fundamental, Constant, Declaration, or Indicator.
0faGYJG.png



Ruby:
def BookValue = if IsNaN(BookValuePerShare())
                then BookValue[1]
                else BookValuePerShare();
            
declare lower;
plot x = BookValue;

ToS Support, deservedly, has an unparallel excellent reputation.
They can walk you through all facets of the ThinkOrSwim app.

However, they can not / will not write custom code.
Nor can they provide support for troubleshooting custom code.

The reason, the forum was born.
Through stumbling, experimenting, and figuring things out together.
Members are inspired to
take ThinkScript where no man has gone before...
;)
"take ThinkScript where no man has gone before..." Indeed. !!! Thank you for this awesome community to pave the way toward uncharted "World(s)". :)
 
This indicator displays fundamental data of a stock, including financial info such as Free Cash Flow, Profit Margin, etc., on your chart.
An overall weighted Score is calculated to gauge the overall financial health.

Use on a Daily Chart. Useful for anyone interested in fundamental stock research.
View attachment 9186
Ruby:
#Fundamental Data Labels _Mobius 4/26/20 (found on OneNote)
#
# @MerryDay revised 4/21:
# my interpretation of positive/negative values; should be modified to meet your strategy
# then calculated an overall weighted score based on:
# https://tradestation.tradingappstore.com/products/FundamentalScore/document/Fundamental_Score.pdf
# and other information found on the web
declare lower;
DefineGlobalColor("Pre_Cyan", CreateColor(50, 200, 255)) ;
DefineGlobalColor("LabelGreen",  CreateColor(0, 165, 0)) ;
DefineGlobalColor("LabelRed",  CreateColor(225, 0, 0)) ;
DefineGlobalColor("Violet", CreateColor (200, 125, 255)) ;
DefineGlobalColor("GrayGreen",  CreateColor(155, 167, 76)) ;
DefineGlobalColor("LitePink", CreateColor (220, 180, 180)) ;
DefineGlobalColor("neutral",  color.light_gray) ;
input lPE = yes ;
input lEPS = yes ;
input lCASH = yes ;
input lGP = yes ;
input lOP = no ;
input lNP = no ;
input lCRatio = no ;
input lQRatio = yes ;
input lROA = no ;
input lROE = yes ;
input lSPS = yes ;
input lFCC = no ;
input lAssTURNS = no ;
input lFinLev = no ;
input lBV = no ;
input lDEBT = yes ;
input lInvTurn = no ;
input lDivOUT = no ;
input lDPS = no ;
input lDIV = no ;
input lIR = no ;
input lTR = no ;
input lSCORE = yes ;

def fp = FiscalPeriod.YEAR;
def EPS = EarningsPerShareTTM(fiscalPeriod = fp);
def PE = round(close / EPS,1);
AddLabel(lPE and PE, "P/E ratio = " + Round(PE, 2),
                      if PE < 0 then GlobalColor("LitePink") else
                      if PE < 20 then GlobalColor("LabelGreen") else
                      if PE < 40 then GlobalColor("GrayGreen") else GlobalColor("Pre_Cyan"));

def EarnPerShare = if IsNaN(EarningsPerShareTTM())
                   then EarnPerShare[1]
                   else EarningsPerShareTTM();
AddLabel(lEPS and EarnPerShare, "EPS-TTM = " + AsDollars(EarnPerShare),
                      if EarnPerShare > 0 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));

def FreeCashFlowPerSh = if isNaN(FreeCashFlowPerShare())
                        then FreeCashFlowPerSh[1]
                        else FreeCashFlowPerShare();
AddLabel(lCASH and FreeCashFlowPerSh, "Free Cash Flow Per Share = " + AsDollars(FreeCashFlowPerSh),
                  if FreeCashFlowPerSh > 0 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));
def score_EarnCash = if PE <0 and FreeCashFlowPerSh < 0 and EarnPerShare < 0 then 0 else 5;

def Gross_Profit_Margin = if IsNaN(GrossProfitMargin())
                          then Gross_Profit_Margin[1]
                          else GrossProfitMargin();
AddLabel(lGP and Gross_Profit_Margin, "Gross Profit Margin = " + Round(Gross_Profit_Margin, 2),
               if Gross_Profit_Margin > 0 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));

def Operating_Profit_Margin = if IsNaN(OperatingProfitMargin())
                              then Operating_Profit_Margin[1]
                              else OperatingProfitMargin();
AddLabel(lOP and Operating_Profit_Margin, "Operating Profit Margin = " + Round(Operating_Profit_Margin, 2),          
              if Operating_Profit_Margin > 0 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));


def Net_Profit_Margin = if IsNaN(NetProfitMargin())
                        then Net_Profit_Margin[1]
                        else NetProfitMargin();
AddLabel(lNP and Net_Profit_Margin, "Net Profit Margin = " + Round(Net_Profit_Margin, 2),
               if Net_Profit_Margin > 0 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));
def score_Profits = if Gross_Profit_Margin>0 or Net_Profit_Margin>0 or Operating_Profit_Margin > 0 then 3 else 0 ;

def CurRatio = if IsNaN(CurrentRatio())
               then CurRatio[1]
               else CurrentRatio();
AddLabel(lCRatio and CurRatio, "Current Ratio = " + Round(CurRatio, 2),
               if CurRatio > 2  then GlobalColor("GrayGreen") else
               if CurRatio >= 1 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));

def Quick_Ratio = if IsNaN(QuickRatio())
                  then Quick_Ratio[1]
                  else QuickRatio();
AddLabel(lQRatio and Quick_Ratio, "Quick Ratio = " + Round(Quick_Ratio, 2),
               if Quick_Ratio > 2  then GlobalColor("GrayGreen") else
               if Quick_Ratio >= 1 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));
def score_Ratios = if Quick_Ratio >= 1 or CurRatio >= 1 then 3 else 0;

def Return_On_Assets = if IsNaN(ReturnOnAssets())
                       then Return_On_Assets[1]
                       else ReturnOnAssets();
AddLabel(lROA and Return_On_Assets, "Return On Assets = " + Round(Return_On_Assets),
              if Return_On_Assets >= 15 then GlobalColor("Pre_Cyan") else
              if Return_On_Assets >= 10 then GlobalColor("LabelGreen") else
              if Return_On_Assets > 0 then GlobalColor("GrayGreen") else GlobalColor("LitePink"));


def Return_On_Equity = if IsNaN(ReturnOnEquity())
                       then Return_On_Equity[1]
                       else ReturnOnEquity();
AddLabel(lROE and Return_On_Equity, "Return On Equity = " + Round(Return_On_Equity),
              if Return_On_Equity >= 15 then GlobalColor("Pre_Cyan") else
              if Return_On_Equity >= 10 then GlobalColor("LabelGreen") else
              if Return_On_Equity > 0 then GlobalColor("GrayGreen") else GlobalColor("LitePink"));
def score_Returns = if Return_On_Equity >= 10 or Return_On_Assets >=10 then 1 else 0 ;


def Sales_Per_Share = if IsNaN(SalesPerShare())
                      then Sales_Per_Share[1]
                      else SalesPerShare();
AddLabel(lSPS and Sales_Per_Share, "Sales Per Share = " + Round(Sales_Per_Share, 2),
                      if Sales_Per_Share > 0 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));
def score_Sales_Per_Share = if Sales_Per_Share > 0 then 1 else 0;

def FixChgCovRatio = if IsNaN(FixedChargeCoverageRatio())
                     then FixChgCovRatio[1]
                     else FixedChargeCoverageRatio();
AddLabel(lFCC and FixChgCovRatio, "Fixed Charge Coverage Ratio = " + Round(FixChgCovRatio, 2),
                     if FixChgCovRatio >= 1 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));

def Total_Asset_Turnover = if IsNaN(TotalAssetTurnover())
                           then Total_Asset_Turnover[1]
                           else TotalAssetTurnover();
AddLabel(lAssTURNS and Total_Asset_Turnover, "Total Asset Turnover = " + Round(Total_Asset_Turnover, 2),
               if Total_Asset_Turnover > 1 then GlobalColor("LabelGreen") else  GlobalColor("neutral"));

def FinLev = if IsNaN(FinancialLeverage())
             then FinLev[1]
             else FinancialLeverage();
AddLabel(lFinLev and FinLev, "Financial Leverage = " + Round(FinLev, 2),
                      if FinLev > 0 and FinLev < 2 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));
def score_FinLev = if FinLev < 2 then 1 else 0;

def BookValue = if IsNaN(BookValuePerShare())
                then BookValue[1]
                else BookValuePerShare();
AddLabel(lBV and BookValue, "Book Value Per Share = " + Round(BookValue),
                if BookValue < 2 then GlobalColor("Pre_Cyan") else
                if BookValue < 3 then GlobalColor("LabelGreen") else GlobalColor("neutral"));

def Long_Term_Debt_To_Capital = if IsNaN(LongTermDebtToCapital())
                                then Long_Term_Debt_To_Capital[1]
                                else LongTermDebtToCapital();
AddLabel(lDEBT and Long_Term_Debt_To_Capital, "Long Term Debt To Capital = " + Round(Long_Term_Debt_To_Capital, 2),
 if Long_Term_Debt_To_Capital < 5 then GlobalColor("LabelGreen") else GlobalColor("LitePink"));
def score_Long_Term_Debt_To_Capital = if Long_Term_Debt_To_Capital < 5 then 1 else 0;

def Inventory_Turnover = if IsNaN(InventoryTurnover())
                         then Inventory_Turnover[1]
                         else InventoryTurnover();
AddLabel(lInvTurn and Inventory_Turnover, "Inventory Turnover = " + Round(Inventory_Turnover, 2),
               if Inventory_Turnover < 5  then GlobalColor("LitePink") else
               if Inventory_Turnover < 10 then GlobalColor("Pre_Cyan") else
               if Inventory_Turnover < 15 then GlobalColor("GrayGreen") else GlobalColor("LitePink"));

def DivPayout = if IsNaN(DividendPayout())
                then DivPayout[1]
                else DividendPayout();
AddLabel(lDivOUT and DivPayout, "Dividend Payout = " + round(DivPayout,2) + "%", GlobalColor("neutral"));

def DivPerShare = if IsNaN(DividendsPerShareTTM())
                  then DivPerShare[1]
                  else DividendsPerShareTTM();
AddLabel(lDPS and DivPerShare, "Dividend Per Share = " + AsDollars(DivPerShare), GlobalColor("neutral"));

def DivYield = if IsNaN(DividendsPerShareTTM())
                  then DivPerShare[1]
                  else DividendsPerShareTTM()/Close;
AddLabel(lDIV and DivPerShare, "Dividend Yield = " + AsPercent(DivYield), GlobalColor("neutral"));

def Interest_Rate = if IsNaN(InterestRate())
                    then Interest_Rate[1]
                    else InterestRate();
AddLabel(lIR and Interest_Rate, "Interest Rate = " + Round(Interest_Rate, 2), GlobalColor("neutral"));

def Tax_Rate = if IsNaN(TaxRate())
               then Tax_Rate[1]
               else TaxRate();
AddLabel(lTR and Tax_Rate, "Tax Rate = " + Round(Tax_Rate, 2), GlobalColor("neutral"));

def score = score_Returns + score_EarnCash + score_ratios + score_Profits
           + score_FinLev + score_Sales_Per_Share + score_Long_Term_Debt_To_Capital;

AddLabel(lSCORE, "SCORE: " + score,
if score >= 12 then GlobalColor("Pre_Cyan") else
if score >= 10 then GlobalColor("LabelGreen") else
if score >= 8 then GlobalColor("GrayGreen") else GlobalColor("LitePink"),
Location.BOTTOM_LEFT);
Thank you very much for the code. To perform a stock scan with good fundamentals, you can send which parameters to choose and what the values are from a menu that exists in TOS.
 
Here is a shared grid link w/ labels displaying that the fundamental labels do work
http://tos.mx/!MJhHZANS MUST follow these instructions for loading shared links.
NFZbgNX.png



If your question is why is there not a total score for CAT, HD, MSFT, AAPL, CRM but yet there is a total score for Costco.

Answer:


@JSCS_22
Dear @merryDay,


I can’t thank you enough for sharing these fundamental label scripts


I noticed there have been a few updates, so I’m not sure which link is the most recent. Could you please resend the latest updated links that has all the lables ?


Also, do you happen to have label versions that include any of the following metrics?


  • Forward P/E
  • PEG Ratio
  • EV/EBITDA

Again, thanks a million for all your work and generosity in sharing these tools — they truly make a difference! JDL
 
Dear @merryDay,


I can’t thank you enough for sharing these fundamental label scripts


I noticed there have been a few updates, so I’m not sure which link is the most recent. Could you please resend the latest updated links that has all the lables ?


Also, do you happen to have label versions that include any of the following metrics?


  • Forward P/E
  • PEG Ratio
  • EV/EBITDA

Again, thanks a million for all your work and generosity in sharing these tools — they truly make a difference! JDL

Yes, the code in the beginning post is up-to-date.

Unfortunately, the data feeds to ToS and most other trading platforms do not include nor provide enough information to calculate:
Forward P/E
PEG Ratio
EV/EBITDA
 
Last edited by a moderator:
BP-01.png
@merryDay — first, thank you for posting the original Fundamentals Labels script a while back.
It has been one of the most useful reference points for anyone who wants quick data on a chart without digging through the Analyze tab.

I’ve spent some time cleaning up the code, reorganizing the inputs, improving the label consistency, expanding the color palette, and adding a few new options. I also reworked the P/E ratio rating system, which turned out to be one of the biggest weak points in the original version.

This post is not to “replace” the original —
but to build on it, refine it, and get help from the rest of the community to make the fundamentals scoring far more accurate and useful.

There are a LOT of fundamental metrics in this study, and many of them really need better tiering, color logic, thresholds, or scoring adjustments — and that is not a small job for one person.


🔍 Example of Why This Needs a Group Effort: P/E Ratio Fix
The original PE rating was very simplistic.
It treated high PE as good and low PE as meh.

Here’s the original PE logic (simplified):
if PE < 0 then Red
else if PE < 20 then Green
else if PE < 40 then Gray
else Blue

This made high PE look “elite” even when the stock was extremely overvalued or risky.
So I rewrote it into a 7-tier system that correctly reflects valuation risk:

if PE < 0 → WarningSoftRed (losing money)
else if PE < 10 → SuperiorBlue (deep value)
else if PE < 15 → ExcellentGreen (good value)
else if PE < 30 → AcceptableGray (normal range)
else if PE < 60 → CautionYellow (expensive)
else if PE < 90 → WarningSoftRed (very expensive)
else → DangerRed (extreme risk)

This is just ONE example of where the script needs improved logic — and there are over 20 other fundamentals that need the same kind of attention.


🛠 What Has Been Cleaned Up / Added So Far
  • Completely reorganized input toggles
  • Renamed all color definitions for clarity
  • Clean, consistent global color tier system
  • Added showLabels master toggle
  • Cleaned up label spacing
  • Simplified label loading behavior
  • Added _On suffix for all individual metric toggles
  • Updated the P/E system with a proper 7-tier rating
  • General code cleanup for readability
The script is now much easier to work on.

📢 What We Need Help With (Community Collaboration)
There are still MANY fundamentals that need:
  • better color-tier thresholds
  • more accurate scoring
  • multi-tier logic (like the new PE system)
  • sector-adjusted ranges
  • improvements to the Balance Sheet Score
  • improvements to the Fundamental Score
  • discussion on realistic thresholds for:
    • Gross Margin
    • Operating Margin
    • ROA
    • ROE
    • Debt to Capital
    • Quick Ratio
    • Financial Leverage
    • Inventory Turnover
    • Fixed Charge Coverage
    • Book Value
    • etc.
This would be much easier and MUCH more accurate if done with multiple people giving input rather than one person trying to solve every metric alone.

If anyone wants to help improve the thresholds, colors, or scoring logic for any of these fundamentals, please jump in.


🙏 Thanks Again to @merryDay
Without the original script posted by you, none of this expansion, cleanup, or analysis work would even exist.
This thread is meant to continue your work — not replace it — and hopefully turn it into an even more useful tool for the community.


Code:
#===================================================================
# Fundamental Data Labels (Enhanced)
#   - Original concept: Mobius / MerryDay
#   - Revision: Richard Campbell + GPT, 2025
#===================================================================

#-------------------------------------------------------
# COLOR PALETTE  —  FUNDAMENTAL TIER SYSTEM
#-------------------------------------------------------

# Used for: top-tier fundamentals such as excellent ROA/ROE, strong margins, or elite value (PE<10).
DefineGlobalColor("SuperiorBlue",    CreateColor(102, 179, 255));   # Elite / Outstanding performance

# Used for: strong metrics, positive earnings, healthy balance sheet, good profitability.
DefineGlobalColor("ExcellentGreen",  CreateColor(60, 208, 112));    # Strong / Healthy

# Used for: average fundamentals, normal valuation ranges, acceptable but not impressive metrics.
DefineGlobalColor("AcceptableGray",  Color.LIGHT_GRAY);             # Neutral / Average

# Used for: borderline metrics, elevated valuation, early warnings, “monitor this.”
DefineGlobalColor("CautionYellow",   CreateColor(253, 253, 150));   # Caution / Borderline

# Used for: weak metrics, slightly negative trends, expensive valuation (but growth still possible).
DefineGlobalColor("WarningSoftRed",  CreateColor(255, 185, 190));   # Mild Warning / Soft Negative

# Used for: worst-tier metrics, high risk, severe valuation extremes, or major financial issues.
DefineGlobalColor("DangerRed",       CreateColor(234, 60, 83));     # High Risk / Major Warning

#-------------------------------------------------------
# LABEL / DISPLAY SETTINGS
#-------------------------------------------------------
# Master label visibility – turn ALL labels on/off at once.
input LabelDisplay = { default "< LABEL & DISPLAY SETTINGS >" };

# Master toggle – if "no", no labels will plot at all
input showLabels = yes;

# Label location on chart
input LabelLocation =
{
    default "Top-Left",
    "Top-Right",
    "Bottom-Left",
    "Bottom-Right"
};

def lblLoc =
    if LabelLocation == LabelLocation."Top-Left" then Location.TOP_LEFT
    else if LabelLocation == LabelLocation."Top-Right" then Location.TOP_RIGHT
    else if LabelLocation == LabelLocation."Bottom-Left" then Location.BOTTOM_LEFT
    else Location.BOTTOM_RIGHT;

#-------------------------------------------------------
# INPUTS – EARNINGS, CASH FLOW, & VALUATION
#-------------------------------------------------------
input ECFV = { default "< EARNINGS, CASH FLOW, & VALUATION >" };

# PE – Price/Earnings ratio using close / EPS(TTM).
# Lower can mean cheaper valuation, but negative means losing money.
# Classic quick valuation snapshot.
input PE_On = yes;

# EPS – Earnings Per Share (TTM).
# Positive and rising EPS is generally bullish; negative EPS = losing money.
# Used as the base for many other valuation ratios.
input EPS_On = yes;

# FCF – Free Cash Flow Per Share.
# Positive free cash flow is very important for financial health.
# Negative for long periods can signal stress.
input CashFlow_On = yes;

#-------------------------------------------------------
# INPUTS – PROFIT MARGINS
#-------------------------------------------------------
input ProfitsSection = { default "< PROFITABILITY MARGINS >" };

# Gross Profit Margin – (Sales - COGS) / Sales.
# Higher = better; negative or falling often a warning sign.
input GrossMargin_On = yes;

# Operating Profit Margin – core profitability from operations.
# Higher = better; negative means operations are not profitable.
input OperatingMargin_On = no;

# Net Profit Margin – bottom-line profit after all expenses and taxes.
# Higher = better; negative values = net loss.
input NetMargin_On = no;

#-------------------------------------------------------
# INPUTS – LIQUIDITY, LEVERAGE, & EFFICIENCY
#-------------------------------------------------------
input BalanceSection = { default "< BALANCE SHEET & EFFICIENCY >" };

# Current Ratio – Current Assets / Current Liabilities.
# > 1.0 means more near-term assets than liabilities. > 2.0 very comfortable.
input CurrentRatio_On = no;

# Quick Ratio – (Current Assets - Inventory) / Current Liabilities.
# Stricter liquidity test; >= 1.0 is generally considered healthy.
input QuickRatio_On = yes;

# ROA – Return On Assets (%).
# Profit generated per dollar of total assets. Higher is better.
input ROA_On = no;

# ROE – Return On Equity (%).
# Profit generated per dollar of shareholder equity. Higher is better.
input ROE_On = yes;

# SPS – Sales Per Share.
# Revenue per share; a positive number is generally a sign of a real business.
input SalesPerShare_On = yes;

# FCCR – Fixed Charge Coverage Ratio.
# Ability to cover fixed charges (like interest + lease) from earnings.
input FixedChargeCoverage_On = no;

# Asset Turnover – Total Asset Turnover.
# Measures how efficiently assets are used to generate sales.
input AssetTurnover_On = no;

# Financial Leverage – balance sheet leverage factor.
# Higher leverage = more risk; < 2 is generally considered moderate.
input FinancialLeverage_On = no;

# Book Value Per Share.
# Approximate net asset value per share.
input BookValue_On = no;

# LTD-to-Capital – Long Term Debt To Capital (%).
# Higher % = more debt load; very high values can be a warning.
input DebtToCapital_On = yes;

# Inventory Turnover – how fast inventory is sold and replaced.
# Very low can indicate weak demand; very high may indicate efficient operations.
input InventoryTurnover_On = no;

#-------------------------------------------------------
# INPUTS – DIVIDENDS & RATES
#-------------------------------------------------------
input DivSection = { default "< DIVIDENDS & RATES >" };

# Dividend Payout Ratio (% of earnings paid out as dividends).
# Very high payout can be unsustainable; very low = more retained earnings.
input DividendPayout_On = no;

# Dividend Per Share (TTM).
# Total dividend paid per share over trailing 12 months.
input DividendPerShare_On = no;

# Dividend Yield (%).
# Dividend per share divided by current price.
input DividendYield_On = no;

# Interest Rate – company-level effective interest rate.
input InterestRate_On = no;

# Tax Rate – effective tax rate.
input TaxRate_On = no;

#-------------------------------------------------------
# INPUTS – SCORES
#-------------------------------------------------------
input ScoreSection = { default "< SCORES & SUMMARY LABELS >" };

# Fundamental Score – existing composite score from original script.
input FundamentalScore_On = yes;

# Balance Sheet Score – new 0–10 numeric score for balance sheet strength.
input BalanceSheetScore_On = yes;

#-------------------------------------------------------
# FUNDAMENTAL SERIES
#-------------------------------------------------------
def fp = FiscalPeriod.YEAR;

#-------------------------------------------------------
# EPS / PE / CASH FLOW
#-------------------------------------------------------
def EPS_raw = EarningsPerShareTTM(fiscalPeriod = fp);
def EPS_TTM = if IsNaN(EPS_raw) then EPS_TTM[1] else EPS_raw;

def PE_raw  = if EPS_TTM != 0 then close / EPS_TTM else Double.NaN;
def PE_val  = Round(PE_raw, 1);

def FreeCashFlowPerSh_raw = FreeCashFlowPerShare();
def FreeCashFlowPerSh =
    if IsNaN(FreeCashFlowPerSh_raw) then FreeCashFlowPerSh[1]
    else FreeCashFlowPerSh_raw;

# Label: P/E
AddLabel(
    showLabels and PE_On and !IsNaN(PE_val),
    "  P/E | " + Round(PE_val, 2) + "  ",
    if PE_val < 0        then GlobalColor("WarningSoftRed")       # Negative EPS (losses)
    else if PE_val < 10  then GlobalColor("SuperiorBlue")         # Extremely strong value
    else if PE_val < 15  then GlobalColor("ExcellentGreen")       # Good value
    else if PE_val < 30  then GlobalColor("AcceptableGray")       # Normal valuation
    else if PE_val < 60  then GlobalColor("CautionYellow")        # Expensive
    else if PE_val < 90  then GlobalColor("WarningSoftRed")       # Very expensive (growth possible)
    else                      GlobalColor("DangerRed"),           # Hyper-expensive / highest risk
    location = lblLoc
);

# Label: EPS-TTM
AddLabel(
    showLabels and EPS_On and !IsNaN(EPS_TTM),
    "  EPS-TTM | " + AsDollars(EPS_TTM) + "  ",
    if EPS_TTM > 0 then GlobalColor("ExcellentGreen")
    else               GlobalColor("WarningSoftRed"),
    location = lblLoc
);

# Label: Free Cash Flow Per Share
AddLabel(
    showLabels and CashFlow_On and !IsNaN(FreeCashFlowPerSh),
    "  FCF/Share | " + AsDollars(FreeCashFlowPerSh) + "  ",
    if FreeCashFlowPerSh > 0 then GlobalColor("ExcellentGreen")
    else                          GlobalColor("WarningSoftRed"),
    location = lblLoc
);

# Earnings + Cash Flow + Valuation score component
def score_EarnCash =
    if PE_val < 0 and FreeCashFlowPerSh < 0 and EPS_TTM < 0 then 0 else 5;

#-------------------------------------------------------
# PROFIT MARGINS
#-------------------------------------------------------
def Gross_Profit_Margin_raw = GrossProfitMargin();
def Gross_Profit_Margin =
    if IsNaN(Gross_Profit_Margin_raw) then Gross_Profit_Margin[1]
    else Gross_Profit_Margin_raw;

AddLabel(
    showLabels and GrossMargin_On and !IsNaN(Gross_Profit_Margin),
    "  Gross Margin | " + Round(Gross_Profit_Margin, 2) + "%  ",
    if Gross_Profit_Margin > 0 then GlobalColor("ExcellentGreen")
    else                            GlobalColor("WarningSoftRed"),
    location = lblLoc
);

def Operating_Profit_Margin_raw = OperatingProfitMargin();
def Operating_Profit_Margin =
    if IsNaN(Operating_Profit_Margin_raw) then Operating_Profit_Margin[1]
    else Operating_Profit_Margin_raw;

AddLabel(
    showLabels and OperatingMargin_On and !IsNaN(Operating_Profit_Margin),
    "  Operating Margin | " + Round(Operating_Profit_Margin, 2) + "%  ",
    if Operating_Profit_Margin > 0 then GlobalColor("ExcellentGreen")
    else                                GlobalColor("WarningSoftRed"),
    location = lblLoc
);

def Net_Profit_Margin_raw = NetProfitMargin();
def Net_Profit_Margin =
    if IsNaN(Net_Profit_Margin_raw) then Net_Profit_Margin[1]
    else Net_Profit_Margin_raw;

AddLabel(
    showLabels and NetMargin_On and !IsNaN(Net_Profit_Margin),
    "  Net Margin | " + Round(Net_Profit_Margin, 2) + "%  ",
    if Net_Profit_Margin > 0 then GlobalColor("ExcellentGreen")
    else                          GlobalColor("WarningSoftRed"),
    location = lblLoc
);

def score_Profits =
    if Gross_Profit_Margin > 0 or Net_Profit_Margin > 0 or Operating_Profit_Margin > 0 then 3 else 0;

#-------------------------------------------------------
# LIQUIDITY RATIOS
#-------------------------------------------------------
def CurRatio_raw = CurrentRatio();
def CurRatio =
    if IsNaN(CurRatio_raw) then CurRatio[1]
    else CurRatio_raw;

AddLabel(
    showLabels and CurrentRatio_On and !IsNaN(CurRatio),
    "  Current Ratio | " + Round(CurRatio, 2) + "  ",
    if CurRatio > 2       then GlobalColor("AcceptableGray")
    else if CurRatio >= 1 then GlobalColor("ExcellentGreen")
    else                      GlobalColor("WarningSoftRed"),
    location = lblLoc
);

def Quick_Ratio_raw = QuickRatio();
def Quick_Ratio =
    if IsNaN(Quick_Ratio_raw) then Quick_Ratio[1]
    else Quick_Ratio_raw;

AddLabel(
    showLabels and QuickRatio_On and !IsNaN(Quick_Ratio),
    "  Quick Ratio | " + Round(Quick_Ratio, 2) + "  ",
    if Quick_Ratio > 2       then GlobalColor("AcceptableGray")
    else if Quick_Ratio >= 1 then GlobalColor("ExcellentGreen")
    else                        GlobalColor("WarningSoftRed"),
    location = lblLoc
);

def score_Ratios =
    if Quick_Ratio >= 1 or CurRatio >= 1 then 3 else 0;

#-------------------------------------------------------
# RETURNS (ROA / ROE)
#-------------------------------------------------------
def Return_On_Assets_raw = ReturnOnAssets();
def Return_On_Assets =
    if IsNaN(Return_On_Assets_raw) then Return_On_Assets[1]
    else Return_On_Assets_raw;

AddLabel(
    showLabels and ROA_On and !IsNaN(Return_On_Assets),
    "  ROA | " + Round(Return_On_Assets, 2) + "%  ",
    if Return_On_Assets >= 15 then GlobalColor("SuperiorBlue")
    else if Return_On_Assets >= 10 then GlobalColor("ExcellentGreen")
    else if Return_On_Assets > 0  then GlobalColor("AcceptableGray")
    else                             GlobalColor("WarningSoftRed"),
    location = lblLoc
);

def Return_On_Equity_raw = ReturnOnEquity();
def Return_On_Equity =
    if IsNaN(Return_On_Equity_raw) then Return_On_Equity[1]
    else Return_On_Equity_raw;

AddLabel(
    showLabels and ROE_On and !IsNaN(Return_On_Equity),
    "  ROE | " + Round(Return_On_Equity, 2) + "%  ",
    if Return_On_Equity >= 15 then GlobalColor("SuperiorBlue")
    else if Return_On_Equity >= 10 then GlobalColor("ExcellentGreen")
    else if Return_On_Equity > 0  then GlobalColor("AcceptableGray")
    else                             GlobalColor("WarningSoftRed"),
    location = lblLoc
);

def score_Returns =
    if Return_On_Equity >= 10 or Return_On_Assets >= 10 then 1 else 0;

#-------------------------------------------------------
# SALES / EFFICIENCY
#-------------------------------------------------------
def Sales_Per_Share_raw = SalesPerShare();
def Sales_Per_Share =
    if IsNaN(Sales_Per_Share_raw) then Sales_Per_Share[1]
    else Sales_Per_Share_raw;

AddLabel(
    showLabels and SalesPerShare_On and !IsNaN(Sales_Per_Share),
    "  Sales Per Share | " + AsDollars(Sales_Per_Share) + "  ",
    if Sales_Per_Share > 0 then GlobalColor("ExcellentGreen")
    else                        GlobalColor("WarningSoftRed"),
    location = lblLoc
);

def score_Sales_Per_Share = if Sales_Per_Share > 0 then 1 else 0;

def FixChgCovRatio_raw = FixedChargeCoverageRatio();
def FixChgCovRatio =
    if IsNaN(FixChgCovRatio_raw) then FixChgCovRatio[1]
    else FixChgCovRatio_raw;

AddLabel(
    showLabels and FixedChargeCoverage_On and !IsNaN(FixChgCovRatio),
    "  Fixed Charge Coverage | " + Round(FixChgCovRatio, 2) + "  ",
    if FixChgCovRatio >= 1 then GlobalColor("ExcellentGreen")
    else                        GlobalColor("WarningSoftRed"),
    location = lblLoc
);

def Total_Asset_Turnover_raw = TotalAssetTurnover();
def Total_Asset_Turnover =
    if IsNaN(Total_Asset_Turnover_raw) then Total_Asset_Turnover[1]
    else Total_Asset_Turnover_raw;

AddLabel(
    showLabels and AssetTurnover_On and !IsNaN(Total_Asset_Turnover),
    "  Asset Turnover | " + Round(Total_Asset_Turnover, 2) + "  ",
    if Total_Asset_Turnover > 1 then GlobalColor("ExcellentGreen")
    else                            GlobalColor("AcceptableGray"),
    location = lblLoc
);

def FinLev_raw = FinancialLeverage();
def FinLev =
    if IsNaN(FinLev_raw) then FinLev[1]
    else FinLev_raw;

AddLabel(
    showLabels and FinancialLeverage_On and !IsNaN(FinLev),
    "  Financial Leverage | " + Round(FinLev, 2) + "  ",
    if FinLev > 0 and FinLev < 2 then GlobalColor("ExcellentGreen")
    else                              GlobalColor("WarningSoftRed"),
    location = lblLoc
);

def score_FinLev = if FinLev < 2 then 1 else 0;

def BookValue_raw = BookValuePerShare();
def BookValue =
    if IsNaN(BookValue_raw) then BookValue[1]
    else BookValue_raw;

AddLabel(
    showLabels and BookValue_On and !IsNaN(BookValue),
    "  Book Value/Share | " + Round(BookValue, 2) + "  ",
    if BookValue < 2 then GlobalColor("SuperiorBlue")
    else if BookValue < 3 then GlobalColor("ExcellentGreen")
    else                      GlobalColor("AcceptableGray"),
    location = lblLoc
);

def Long_Term_Debt_To_Capital_raw = LongTermDebtToCapital();
def Long_Term_Debt_To_Capital =
    if IsNaN(Long_Term_Debt_To_Capital_raw) then Long_Term_Debt_To_Capital[1]
    else Long_Term_Debt_To_Capital_raw;

AddLabel(
    showLabels and DebtToCapital_On and !IsNaN(Long_Term_Debt_To_Capital),
    "  LT Debt/Capital | " + Round(Long_Term_Debt_To_Capital, 2) + "%  ",
    if Long_Term_Debt_To_Capital < 5 then GlobalColor("ExcellentGreen")
    else                                 GlobalColor("WarningSoftRed"),
    location = lblLoc
);

def score_Long_Term_Debt_To_Capital =
    if Long_Term_Debt_To_Capital < 5 then 1 else 0;

def Inventory_Turnover_raw = InventoryTurnover();
def Inventory_Turnover =
    if IsNaN(Inventory_Turnover_raw) then Inventory_Turnover[1]
    else Inventory_Turnover_raw;

AddLabel(
    showLabels and InventoryTurnover_On and !IsNaN(Inventory_Turnover),
    "  Inventory Turnover | " + Round(Inventory_Turnover, 2) + "  ",
    if Inventory_Turnover < 5  then GlobalColor("WarningSoftRed")
    else if Inventory_Turnover < 10 then GlobalColor("SuperiorBlue")
    else if Inventory_Turnover < 15 then GlobalColor("AcceptableGray")
    else                                GlobalColor("WarningSoftRed"),
    location = lblLoc
);

#-------------------------------------------------------
# DIVIDENDS & RATES
#-------------------------------------------------------
def DivPayout_raw = DividendPayout();
def DivPayout =
    if IsNaN(DivPayout_raw) then DivPayout[1]
    else DivPayout_raw;

AddLabel(
    showLabels and DividendPayout_On and !IsNaN(DivPayout),
    "  Dividend Payout | " + Round(DivPayout, 2) + "%  ",
    GlobalColor("AcceptableGray"),
    location = lblLoc
);

def DivPerShare_raw = DividendsPerShareTTM();
def DivPerShare =
    if IsNaN(DivPerShare_raw) then DivPerShare[1]
    else DivPerShare_raw;

AddLabel(
    showLabels and DividendPerShare_On and !IsNaN(DivPerShare),
    "  Dividend/Share | " + AsDollars(DivPerShare) + "  ",
    GlobalColor("AcceptableGray"),
    location = lblLoc
);

def DivYield =
    if IsNaN(DivPerShare) or close == 0 then Double.NaN
    else DivPerShare / close;

AddLabel(
    showLabels and DividendYield_On and !IsNaN(DivYield),
    "  Dividend Yield | " + AsPercent(DivYield) + "  ",
    GlobalColor("AcceptableGray"),
    location = lblLoc
);

def Interest_Rate_raw = InterestRate();
def Interest_Rate =
    if IsNaN(Interest_Rate_raw) then Interest_Rate[1]
    else Interest_Rate_raw;

AddLabel(
    showLabels and InterestRate_On and !IsNaN(Interest_Rate),
    "  Interest Rate | " + Round(Interest_Rate, 2) + "%  ",
    GlobalColor("AcceptableGray"),
    location = lblLoc
);

def Tax_Rate_raw = TaxRate();
def Tax_Rate =
    if IsNaN(Tax_Rate_raw) then Tax_Rate[1]
    else Tax_Rate_raw;

AddLabel(
    showLabels and TaxRate_On and !IsNaN(Tax_Rate),
    "  Tax Rate | " + Round(Tax_Rate, 2) + "%  ",
    GlobalColor("AcceptableGray"),
    location = lblLoc
);

#-------------------------------------------------------
# BALANCE SHEET STRENGTH SCORE (0–10)
#   Uses:
#     - Current Ratio / Quick Ratio
#     - LT Debt to Capital
#     - Financial Leverage
#     - Free Cash Flow per Share
#     - Fixed Charge Coverage
#-------------------------------------------------------

# Liquidity score (0–3)
def LiquidityScore =
    (if CurRatio >= 1 then 1 else 0) +
    (if Quick_Ratio >= 1 then 1 else 0) +
    (if CurRatio > 2 or Quick_Ratio > 2 then 1 else 0);

# Debt load & leverage score (0–3)
def DebtScore =
    (if Long_Term_Debt_To_Capital < 5 then 1 else 0) +
    (if Long_Term_Debt_To_Capital < 3 then 1 else 0) +
    (if FinLev < 2 then 1 else 0);

# Cash generation score (0–2)
def CashScore =
    if FreeCashFlowPerSh > 0 then
        if FreeCashFlowPerSh > 0 and EPS_TTM > 0 then 2
        else 1
    else 0;

# Fixed charge coverage score (0–2)
def CoverageScore =
    if FixChgCovRatio >= 1 then
        if FixChgCovRatio >= 3 then 2
        else 1
    else 0;

#-------------------------------------------------------
# BALANCE SHEET SCORE (0–10)
#   LiquidityScore   (0–3)
#   DebtScore        (0–3)
#   CashScore        (0–2)
#   CoverageScore    (0–2)
#
# Color tiers:
#   9–10  → SuperiorBlue      (elite)
#   7–8   → ExcellentGreen    (strong)
#   5–6   → AcceptableGray    (average)
#   3–4   → CautionYellow     (borderline)
#   2     → WarningSoftRed    (weak)
#   0–1   → DangerRed         (high risk)
#-------------------------------------------------------

def BalanceSheetScoreRaw = LiquidityScore + DebtScore + CashScore + CoverageScore;
def BalanceSheetScore     = Min(10, BalanceSheetScoreRaw);

# Spacer before balance sheet score / fundamental score block
AddLabel(
    showLabels and FundamentalScore_On,
    "    ",
    CreateColor(36, 36, 36),
    location = lblLoc
);

AddLabel(
    showLabels and BalanceSheetScore_On and !IsNaN(BalanceSheetScore),
    "  Balance Sheet | " + BalanceSheetScore + " / 10  ",
    if      BalanceSheetScore >= 9 then GlobalColor("SuperiorBlue")       # Elite
    else if BalanceSheetScore >= 7 then GlobalColor("ExcellentGreen")     # Strong
    else if BalanceSheetScore >= 5 then GlobalColor("AcceptableGray")     # Average
    else if BalanceSheetScore >= 3 then GlobalColor("CautionYellow")      # Borderline
    else if BalanceSheetScore >= 2 then GlobalColor("WarningSoftRed")     # Weak
    else                               GlobalColor("DangerRed"),          # High risk
    location = lblLoc
);

#-------------------------------------------------------
# FUNDAMENTAL SCORE (EXISTING COMPOSITE) – LAST LABEL
#-------------------------------------------------------
def score =
    score_Returns
    + score_EarnCash
    + score_Ratios
    + score_Profits
    + score_FinLev
    + score_Sales_Per_Share
    + score_Long_Term_Debt_To_Capital;

# Spacer before final fundamental score
AddLabel(
    showLabels and FundamentalScore_On,
    "    ",
    CreateColor(36, 36, 36),
    location = lblLoc
);

AddLabel(
    showLabels and FundamentalScore_On,
    "  Fundamentals | " + score + " / 15  ",
    if score >= 13 then GlobalColor("SuperiorBlue")        # Elite
    else if score >= 11 then GlobalColor("ExcellentGreen") # Strong
    else if score >=  9 then GlobalColor("AcceptableGray") # Average
    else if score >=  7 then GlobalColor("CautionYellow")  # Borderline
    else if score >=  5 then GlobalColor("WarningSoftRed") # # Weak
    else                    GlobalColor("DangerRed"),      # High risk
    location = lblLoc
);
 
Last edited by a moderator:
View attachment 26361@merryDay — first, thank you for posting the original Fundamentals Labels script a while back.
It has been one of the most useful reference points for anyone who wants quick data on a chart without digging through the Analyze tab.

I’ve spent some time cleaning up the code, reorganizing the inputs, improving the label consistency, expanding the color palette, and adding a few new options. I also reworked the P/E ratio rating system, which turned out to be one of the biggest weak points in the original version.

There is so much to learn from Fundamentals. Unfortunately, most of the details cannot be derived from the ToS data feeds. Which is why, what you’re attempting just can’t be done the way you’re imagining.

The Issue:
A company’s fundamentals can’t be labeled “good” or “bad” in a universal sense, the way that you would like to.
Because every industry works differently. A P/E ratio, profit margin, debt level, or inventory turnover that looks terrible in one sector might be totally normal—or even excellent—in another.

Tech companies often carry high P/E ratios because investors pay for future growth.
Consumer staples tend to have low P/Es because their growth is slow, steady, and predictable.
Retailers live and die by inventory turnover, while software companies have no inventory at all—so that metric is meaningless for them.

But data feeds do not classify by sector or industry, so the correct categorization that you are looking for cannot be assigned.
Fundamentals only matter when compared against a company’s own industry peers, its own historical performance, and the current economic environment.
There is no single “good or bad”—only “appropriate for that business model or not.”

The Solution:
We built a scoring system, keeping things very general and avoid letting extreme differences between industries—like tech vs. consumer-staples P/E ratios—overweight the total.
By doing this, it is possible to create an overall score that simply signals when a trader should take pause.

A “general” overall fundamental score of around 4 should make traders step back and pay attention. Research what that company is doing different from its peers. A score of 10+ is usually a sign of genuinely healthy financials.


Changing The Classifications:
Anything in between, you’re free to classify however makes sense for your style.

Personally, I’m debt-averse. That wasn’t a huge issue when money was basically free, but once interest rates climbed, it changed the equation. If long-term debt-to-capital is over 50% and the quick ratio is under 1, that tells me the company may not have enough liquid assets to comfortably cover short-term obligations while servicing its debt.
For my own analysis, I deduct 4 points from the total score when that happens.

It’s worth noting that a surprising number of AI-themed companies are running with exactly that profile. Their saving grace is usually one of two things:
They have just enough revenue arriving at the right time to keep the lights on,​
or​
They’re “story stocks.”​

Story stocks aren’t traded on fundamentals. They trade on a narrative. They claim massive future demand, huge potential, unverified backorders—anything that paints a picture of explosive growth someday.
Every month-end they go back to lenders, pitch the story again, and get just enough funding to keep going.

That’s why people compare the AI rally to the dot-com bubble. The composition of them both, weighed heavily toward story stocks. Which fly high… until they don’t.

I daytrade AI stocks myself. I’ll daytrade anything if the risk is low, the reward is high, and the safeguards are tight—regardless of the company’s fundamental score.

But I still deduct 4 points from the score of story stocks as a visual reminder: these are not positions that I would enter unless the risk was very very low and the stop-loss very very tight.

However, for many traders; these stocks are their bread and butter. Therefore, my bias does not go into the posted script found in the beginning post.
 
Last edited by a moderator:
There is so much to learn from Fundamentals. Unfortunately, most of the details cannot be derived from the ToS data feeds. Which is why, what you’re attempting just can’t be done the way you’re imagining.

The Issue:
A company’s fundamentals can’t be labeled “good” or “bad” in a universal sense, the way that you would like to.
Because every industry works differently. A P/E ratio, profit margin, debt level, or inventory turnover that looks terrible in one sector might be totally normal—or even excellent—in another.

Tech companies often carry high P/E ratios because investors pay for future growth.
Consumer staples tend to have low P/Es because their growth is slow, steady, and predictable.
Retailers live and die by inventory turnover, while software companies have no inventory at all—so that metric is meaningless for them.

But data feeds do not classify by sector or industry, so the correct categorization that you are looking for cannot be assigned.
Fundamentals only matter when compared against a company’s own industry peers, its own historical performance, and the current economic environment.
There is no single “good or bad”—only “appropriate for that business model or not.”

The Solution:
We built a scoring system, keeping things very general and avoid letting extreme differences between industries—like tech vs. consumer-staples P/E ratios—overweight the total.
By doing this, it is possible to create an overall score that simply signals when a trader should take pause.

A “general” overall fundamental score of around 4 should make traders step back and pay attention. Research what that company is doing different from its peers. A score of 10+ is usually a sign of genuinely healthy financials.


Changing The Classifications:
Anything in between, you’re free to classify however makes sense for your style.

Personally, I’m debt-averse. That wasn’t a huge issue when money was basically free, but once interest rates climbed, it changed the equation. If long-term debt-to-capital is over 50% and the quick ratio is under 1, that tells me the company may not have enough liquid assets to comfortably cover short-term obligations while servicing its debt.
For my own analysis, I deduct 4 points from the total score when that happens.

It’s worth noting that a surprising number of AI-themed companies are running with exactly that profile. Their saving grace is usually one of two things:
They have just enough revenue arriving at the right time to keep the lights on,​
or​
They’re “story stocks.”​

Story stocks aren’t traded on fundamentals. They trade on a narrative. They claim massive future demand, huge potential, unverified backorders—anything that paints a picture of explosive growth someday.
Every month-end they go back to lenders, pitch the story again, and get just enough funding to keep going.

That’s why people compare the AI rally to the dot-com bubble. The composition of them both, weighed heavily toward story stocks. Which fly high… until they don’t.

I daytrade AI stocks myself. I’ll daytrade anything if the risk is low, the reward is high, and the safeguards are tight—regardless of the company’s fundamental score.

But I still deduct 4 points from the score of story stocks as a visual reminder: these are not positions that I would enter unless the risk was very very low and the stop-loss very very tight.

However, for many traders; these stocks are their bread and butter. Therefore, my bias does not go into the posted script found in the beginning post.

I get what you’re saying about fundamentals not having a universal “good or bad” across all sectors — totally fair point. Tech, staples, industrials, retailers… they all play by different rules.

But where I look at it a little differently is this:

I’m not trying to “fix” fundamentals or force everything into the same standard.
I’m just trying to get more resolution out of the score we already have.

When you only have three buckets, you end up throwing a ton of companies together that really don’t belong in the same group. Expanding it to five or seven colors doesn’t magically make fundamentals perfect — it just gives you a clearer look at differences inside the same rough category.

It’s basically like adjusting chart resolution:
same data, just easier to spot the outliers.

If you’re watching stocks from the same sector all day, you’ll see them naturally fall into similar color bands — and the one that’s off will stand out immediately. That’s useful information, even if the system isn’t comparing sectors directly.

So I’m not disagreeing with your framework.
Just saying more granularity tends to make the tool more useful in practice, without pretending fundamentals are equal across sectors.

Nothing fancy — just a clearer picture for the trader.
 
Last edited by a moderator:
What to Know About Fundamentals

TL;DR
iPQrJnp.png


Remember your statistics class?
If you’re seeing patterns in certain metrics for the instruments you trade,​
yes — you’re probably correct that they’re correlated.​

But because causation cannot be determined, no meaningful conclusion can be drawn from any single data point.


Accounting is part art, part science.
Different companies operate under different economic models, growth rates, cost structures, and accounting standards.

Differences in:
» revenue recognition​
» cost capitalization​
» depreciation methods​
» leasing vs. owning assets​
…can make two companies with similar real-world performance look very different on paper.


So what can we rely on?
If a metric is truly concerning to investors, it will almost always show up during quarterly earnings or in management’s guidance. Always check the news widget; before taking a trade.


This is why the overall picture matters far more than any one number.
It’s designed to make traders pause and consider risk.
  • A high score (10+) usually indicates financial strength.
  • A low score (around 4) suggests higher risk — which is common among many AI-related companies.
  • Anything in between depends on your strategy and risk tolerance.
A low score doesn’t mean a stock is untradable. High-risk setups can offer high reward, especially for day traders. It simply means the fundamentals are signaling that caution is warranted.


@merryDay — Yes, high debt can be bad. But in many industries, it can also be perfectly normal or even strategically useful. Especially where huge physical infrastructure requires high capital injections.

@Ricky_005 — Yes, adjust the coloring of the fundamental metrics however you prefer. The original coloring was simply meant to show which fundamentals contributed to a high score or a low score — not to infer the quality of the metric itself.

 

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
563 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top