Financial Fundamentals Labels for ThinkorSwim

MerryDay

Administrative
Staff member
Staff
VIP
Lifetime
UPDATED 12/2/24 can choose which fundamentals to display

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.
AiGdPyb.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);
 
Last edited by a moderator:

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

@mjlinhle I am SO excited that there is interest in Fundamental Analysis! Both longer-term investors and shorter-term traders may be able to improve their chances of success by using fundamental factors to select stocks, and technical indicators to dictate the ideal entry or exit price.

How P/E Ratio is Calculated:

The P/E ratio shown in this script is: Basic Trailing 12mth Earnings / Price. The internet confirms that Apple's trailing P/E ratio is 42.4 as of the close of Friday January 22nd (this is the diluted EPS which includes convertible securities). The TOS label in this study displays: 42.5 because it is the basic ttm w/o convertible securities.

wHQ5agc.png


What P/E ratio is TOS displaying in its Company Growth pane is a good question. Just after market close TOS shows: $40.32. The snapshot I just posted now shows $38.82. The difference between these two tells me that the TOS version is using after-hours data. We do not have access to the TOS P/E Ratio so that is just my best guess. HTH
 
Last edited:
I am a LONG time lurker - Never had much to contribute to the forum but am so thankful for everyone who does and gives me something to read. I check out everything posted on the forums indicator wise but really just use the same indicators I have been for the last 10 years. This fundamental indicator is amazing. I really can't thank you enough. What great work! created an account just to say thanks!
 
@mjlinhle I am SO excited that there is interest in Fundamental Analysis! Both longer-term investors and shorter-term traders may be able to improve their chances of success by using fundamental factors to select stocks, and technical indicators to dictate the ideal entry or exit price.

How P/E Ratio is Calculated:

The P/E ratio shown in this script is: Basic Trailing 12mth Earnings / Price. The internet confirms that Apple's trailing P/E ratio is 42.4 as of the close of Friday January 22nd (this is the diluted EPS which includes convertible securities). The TOS label in this study displays: 42.5 because it is the basic ttm w/o convertible securities.

wHQ5agc.png


What P/E ratio is TOS displaying in its Company Growth pane is a good question. In @STB's chart in post#2 which is a snapshot of just after market close TOS shows: $40.32. The snapshot I just posted now shows $38.82. The difference between these two tells me that the TOS version is using after-hours data. We do not have access to the TOS P/E Ratio so that is just my best guess. HTH

@arihantbaid Here is the Shared Chart Link: http://tos.mx/7UCFTD3
This is a great script, really helps with picks, Thank you so much for sharing. Just curious if it is possible to install a 3 year or 5 years earnings growth percentage?
 
Found this on a blog by Kevin McGrath its his thinkorswim thinkscript code, im just posting it, i have no clue how the algo portion works, someone may find it interesting. Im posting it more for the labels if someone wasnt to extract the code to take out the algo feel free to post back.


Sharpe & Sortino - CAGR (Compound annual growth rate )-- RoR ( Rate of Return) --- LABELS
image.png



Code:
# StochasticCrossoverSystem_Equity_Stats

# idea by Kevin McGrath
# source: http://www.stockfetcher.com...
#hint: Designed to be used in combination with a 3% trailing stop, NO EXCEPTIONS !.

# ported and adapted by TrendXplorer in cooperation with Aurelia
# blog : www.trendxplorer.info
# email: [email protected]
# build: June 24, 2013
# last update: October 14, 2013

#
# --- start of code ---
#

script Sharpe {
    input price = close;
    def length = 63;
    def AvgPrice63 = Average(price, length);
    def expectedReturn = (price / price[length]) - 1;
# riskfreeReturn: 13-week treasuries as a proxy for a risk free return
    def riskfreeReturn = if !IsNaN( close("IRX"))
then Average(close("IRX"), length) / 100
else riskfreeReturn[1];
    def effectiveReturn = expectedReturn - riskfreeReturn;
    def AvgVariance63 = ( fold i = 0 to length with AV do AV + Sqr(GetValue(price, i) - AvgPrice63) ) / length;
    def sd63 = Sqrt(AvgVariance63);
    def volatility63 = sd63 / AvgPrice63;
    plot Sharpe = Sqrt(length / 252) * (effectiveReturn / volatility63); # annual
}

script Sortino {
    input price = close;
    def length = 63;
    def AvgPrice63 = Average(price, length);
    def expectedReturn = (price / price[length]) - 1;
# riskfreeReturn: 13-week treasuries as a proxy for a risk free return
    def riskfreeReturn = if !IsNaN( close("IRX"))
then Average(close("IRX"), length) / 100
else riskfreeReturn[1];
    def effectiveReturn = expectedReturn - riskfreeReturn;
    def AvgUnderperf63 = ( fold n = 0 to length with AUP do AUP + if GetValue(price, n) - AvgPrice63 > 0
then 0 else Sqr(GetValue(price, n) - AvgPrice63) ) / length;
    def sdUnderperf63 = Sqrt(AvgUnderperf63);
    def volatilityUP63 = sdUnderperf63 / AvgPrice63;
    plot Sortino = Sqrt(length / 252) * (effectiveReturn / volatilityUP63); # annual
}

declare lower;

input longETF = "SSO";
input shortETF = "SDS";

input tradingType = {"LONG ONLY", default "LONG & SHORT"};

input kPeriod = 5;
input dPeriod5 = 5;
input dPeriod10 = 10;

input valueStart = 100000;
input DDcloud = yes;

# stochastic crossover logic for generating long/short triggers & initialization
def notValid = IsNaN(close(longETF)) or IsNaN(close(shortETF));
def D5 = CompoundValue(1, if BarNumber() <= 1 then 0 else if notValid then 0 else -1 * StochasticFull(80,  20,  kPeriod,  dPeriod5,  high,  low,  close,  1, averageType = AverageType.SIMPLE).FullD, 0);
def D10 = CompoundValue(1, if BarNumber() <= 1 then 0 else if notValid then 0 else -1 * StochasticFull(80,  20,  kPeriod,  dPeriod10,  high,  low,  close,  1, averageType = AverageType.SIMPLE).FullD, 0);

# logic for entry, exit and open market position
def length = dPeriod10;
def long = D5[1] crosses above D10[1];
def longOn = CompoundValue(length, if long then 1 else if D5[1] > D10[1] then longOn[1] else 0, 0);
def short = longOn[1] and D5[1] crosses below D10[1];
def shortOn = CompoundValue(length, if short then 1 else if D5[1] < D10[1] then shortOn[1] else 0, 0);

# prices
def buyLong = CompoundValue(length, if long then open(longETF) else buyLong[1], 50);
def buyShort = CompoundValue(length, if short then open(shortETF) else buyShort[1], 50);
def sellLong = if short then open(longETF) else buyLong;
def sellShort = if long then open(shortETF) else buyShort;

# "value" keeps track of dollar value at long/short switching
rec value = CompoundValue(1, if long and shortOn[1] then if tradingType == tradingType."LONG ONLY" then value[1] else value[1] + Floor(value[1] / buyShort) * (sellShort - buyShort) else if short then value[1] + Floor(value[1] / buyLong) * (sellLong - buyLong) else value[1], valueStart);

# floating profit/loss:
def longFPL = (Floor(value[1] / buyLong)) * (open(longETF) - buyLong);
def shortFPL = if tradingType == tradingType."LONG ONLY" then 0 else (Floor(value[1] / buyShort)) * (open(shortETF) - buyShort);
def openFPL = if longOn then longFPL else if shortOn then shortFPL else 0;
def lockFPL = CompoundValue(1, if longOn and shortOn[1] then lockFPL[1] + shortFPL else if shortOn and longOn[1] then lockFPL[1] + longFPL else lockFPL[1], 0);

# realized profits
plot pocketPL = if !IsNaN(close) then lockFPL else Double.NaN;
pocketPL.SetDefaultColor(Color.WHITE);
pocketPL.SetLineWeight(1);
pocketPL.HideBubble();

plot startLevel = if !IsNaN(close) then valueStart else Double.NaN;
startLevel.SetDefaultColor(Color.DARK_GREEN);
startLevel.SetLineWeight(3);
startLevel.HideBubble();
startLevel.HideTitle();

# Net Liquidation Value of portfolio
plot NLV = if !IsNaN(close) then value + openFPL else Double.NaN;
NLV.SetDefaultColor(Color.WHITE);
NLV.AssignValueColor(if longOn then CreateColor(0, 153, 0) else if shortOn then Color.DARK_GREEN else Color.WHITE);
NLV.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
NLV.SetLineWeight(3);

# calculation of DrawDown percentage and MaxDD percentage:
def peak = Max(NLV, peak[1]);
def peakPL = peak;
def _DD = if NLV <> 0 then 100 * (peak - NLV) / peak else 0;
def mDD = Max(_DD, mDD[1]);
def maxDD = mDD;
def lastBar = if !IsNaN(close) and IsNaN(close[-1]) then 1 else 0;
plot DD = if lastBar then Round(_DD) else Double.NaN;
DD.SetDefaultColor(Color.RED);
DD.HideBubble();

# Rate of Return (RoR) calculation
def RoR = 100 * (NLV - valueStart) / valueStart;

# CAGR calculation
def init = CompoundValue(1, if long then 1 else init[1], 0);
def initBar = CompoundValue(1, if init and !init[1] then BarNumber() else initBar[1], 0);
def endBar = BarNumber();
def chartAgg = GetAggregationPeriod();
def nBarYear = if chartAgg == AggregationPeriod.WEEK then 52 else if chartAgg == AggregationPeriod.DAY then 252 else 0;
def years = (endBar - initBar) / nBarYear;
def CAGR = 100 * (Power( (NLV / valueStart), (1 / years) )) - 100;

# Sharpe & Sortino
def Sharpe = Sharpe(RoR);
def Sortino = Sortino(RoR);

# profit for each ETF
rec profitLong = if shortOn and longOn[1] then profitLong[1] + longFPL else profitLong[1];
rec profitShort = if longOn and shortOn[1] then profitShort[1] + shortFPL else profitShort[1];

# contribution of long and short to total PL
plot totLongPL = profitLong;
plot totShortPL = profitShort;

# default: painting is off
totLongPL.SetDefaultColor(Color.CYAN);
totLongPL.SetLineWeight(2);
totLongPL.Hide();
totLongPL.HideBubble();
totLongPL.HideTitle();
totShortPL.SetDefaultColor(Color.MAGENTA);
totShortPL.SetLineWeight(2);
totShortPL.Hide();
totShortPL.HideBubble();
totShortPL.HideTitle();

# number of trades
def trades = CompoundValue(1, if long or short then trades[1] + 2 else trades[1], 1);
def winTrades = CompoundValue(1, if long or short then if openFPL[1] >= 0 then winTrades[1] + 1 else winTrades[1] else winTrades[1], 0);
def lossTrades = CompoundValue(1, if long or short then if openFPL[1] < 0 then lossTrades[1] + 1 else lossTrades[1] else lossTrades[1], 0);

# Cloud, Bubbles and Labels
AddCloud(if DDcloud then peakPL else Double.NaN, if DDcloud then NLV else Double.NaN, Color.RED);

AddChartBubble(yes and peak == HighestAll(peak) and !(peak[1] == HighestAll(peak)), NLV, Concat("Peak NLV: $ ", Floor(peakPL)), Color.WHITE, yes);
AddChartBubble(yes and maxDD == HighestAll(_DD) and !(maxDD[1] == HighestAll(_DD)), NLV, Concat("Max DD: ", Concat(Concat(Concat(Concat(Round(maxDD), " %"), "\n (= $ "), Floor(peak - NLV)), " )")), Color.RED, no);

AddLabel(yes, Concat("NLV: $ ", Floor(NLV)), if NLV >= valueStart then CreateColor(0, 153, 0) else Color.RED);
AddLabel(yes, Concat("PocketPL: $ ", Floor(pocketPL)), if lockFPL >= 0 then Color.WHITE else Color.RED);
AddLabel(yes, Concat("Open Profit: $ ", Floor(openFPL)), if openFPL >= 0 then Color.GREEN else Color.RED);
AddLabel(yes, " " + longETF + ": $" + Floor(profitLong) + " (" + Floor(100 * profitLong / lockFPL) + "%)", Color.CYAN);
AddLabel(tradingType == tradingType."LONG & SHORT", " " + shortETF + ": $" + Floor(profitShort) + " (" + Floor(100 * profitShort / lockFPL) + "%)", Color.MAGENTA);
AddLabel(yes, Concat(" RoR: ", Concat(Round(RoR), " %")), if RoR >= 0 then Color.LIGHT_GREEN else Color.RED);
AddLabel(yes, Concat(" CAGR: ", Concat(Round(CAGR), " %")), Color.GREEN);
AddLabel(yes, Concat(" Sharpe: ", Round(Sharpe)), Color.VIOLET);
AddLabel(yes, Concat(" Sortino: ", Round(Sortino)), Color.YELLOW);
AddLabel(yes, Concat(" Current DD: ", Concat( Round((_DD) ), " %")), Color.DARK_ORANGE);
AddLabel(yes, Concat(" max DD: ", Concat( Round(maxDD), " %")), Color.RED);
AddLabel(yes, " Round trips: " + (trades - 1) / 2 + " [ Win: " + winTrades + " (" + Round(100 * winTrades / ((trades - 1) / 2)) + "%), Loss: " + lossTrades + " (" + Round(100 * lossTrades / ((trades - 1) / 2)) + "%) ]", Color.PINK);

#
# --- end of code ---
#
 
Updated The Analysis and Score For Fundamental Labels
the code in post#1 has been updated.

The biggest revision of this script is to the scoring of the Fundamentals. Originally the P/E was weighted so heavily that no stock w/ a negative P/E could get a score over the minimum threshold. Now, if a stock has positive profits / book ratios and/or positive debt/asset ratios, positive sales/share, good inventory turnover but a negative P/E that stock could possibly receive a good score. CommScope's fundamentals in the 1st post is a good example. CommScope has a negative P/E but otherwise some really interesting numbers.

Additional labels have been added for inventory turnover, book value, and a few more. I originally left these off because how to interpret them varies drastically by sector. But given that fundamentals analysis assumes a certain amount of in-depth understanding of the equity to start with, these can give breathe to that analysis.
HTH
 
Important fix and yield addition.
Added dividend yield and changed how payout is displayed. The dividend payout is the percentage of the earnings that are paid out as dividend. Previously this showed it as a dollar amount. Just delete and replace all of the dividend info/labels with this.

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

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

def DivYield = if IsNaN(DividendsPerShareTTM())
                  then DivPerShare[1]
                  else DividendsPerShareTTM()/Close;
AddLabel(show_labels and DivPerShare, "Dividend Yield = " + AsPercent(DivYield), GlobalColor("neutral"));
 
Last edited:
Code:
Declare Lower;
input symbol1 = "TYX";
Input Length = 63;
Input Length2 = 126;
def Return_On_Equity = if IsNaN(ReturnOnEquity())
                       then Return_On_Equity[1]
                       else ReturnOnEquity();
def BookValue = if IsNaN(BookValuePerShare())
                then BookValue[1]
                else BookValuePerShare();
Def Factor = Close(symbol1);
Def ROE_BV = (Return_On_Equity/Factor)*BookValue;
Def ROE_BV_A = ExpAverage(ROE_BV,Length);
Def ROE_BV_A2 = ExpAverage(ROE_BV,Length2);
Plot A = ROE_BV;
Plot B = ROE_BV_A;
Plot B2 = ROE_BV_A2;
A.setDefaultColor(Color.Cyan);
B.setDefaultColor(Color.Magenta);
B2.setdefaultColor(Color.Red);
AddCloud(A,B,Color.Cyan,Color.Magenta);
AddCloud(B,B2,Color.Magenta,Color.Red);
A.SetLineWeight(2);
B.setLineWeight(2);
B2.setLineWeight(2);

The code works when plotted on a chart, but I fail to see how this brings any value to my trading? I tried to use EMA's to smooth and show crossings? I'm still dumbfounded as to how to interpret this ?
 
henrys study shows what code is needed for using the data on a chart. these functions only produce a value once in a few months or once a year. so you need a data source that goes back a year and once a valid number is read, it has to be passed on to the next bar.

ReturnOnEquity() , can be set to have a value as often as quarterly, 1 bar every 3 months.
BookValuePerShare() , can be set to have a value on 1 bar over a year.

i'm not sure if a scan study can find the most recent bar with a valid value, and then read the value itself?
 
This indicator displays fundamental data of a stock, including financial info such as Free Cash Flow, Profit Margin, etc., on your chart. Use on a Daily Chart. Useful for anyone interested in fundamental stock research.
AiGdPyb.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;
declare hide_on_intraday;
input show_labels = yes ;
input show_summaries = no ;
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) ;
def fp = FiscalPeriod.YEAR;
def EPS = EarningsPerShareTTM(fiscalPeriod = fp);
def PE = round(close / EPS,1);
AddLabel(show_labels 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(show_labels 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(show_labels 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(show_labels 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(show_labels 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(show_labels 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(show_labels 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(show_labels 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(show_labels 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(show_labels 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(show_labels 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(show_labels 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(show_labels 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(show_labels 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(show_labels 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(show_labels 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(show_labels 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(show_labels and DivPayout, "Dividend Payout = " + AsDollars(DivPayout), GlobalColor("neutral"));

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

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

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

plot score = score_Returns + score_EarnCash + score_ratios + score_Profits
           + score_FinLev + score_Sales_Per_Share + score_Long_Term_Debt_To_Capital;
AddLabel(show_summaries, "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"));
score.hide();

Link to shared study: http://tos.mx/zF4if7t
Thank you for this indicator of fundamental metrics. I can see it being very useful. Yet I am wondering if there is a way to plot each of these as a lower study, then you would easily be able to back test the metrics on a chart?
 

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
421 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