Silen's Financials Fair Value
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © The_Silen

//@version=4
study("Silen's Financials Fair Value", overlay=true)
string str= (syminfo.prefix+":"+syminfo.ticker)

bool cut_off = input(defval = 1, title = "Cut-off Historical Behavior (for formatting reasons)") 

float pe_rate_pos = 0
float pe_rate_neg = 0
float pe_rate_norm = 0
float targeta = 0
float targetb = 0
float targetc = 0
col_targeta = color.new(color.purple,0)
col_targetb = color.new(color.lime,0)
col_targetc = color.new(color.blue,70)
float rev_b = 0
float earn = 0
float earn_b = 0
float pe_rate_b = 0
float ps_rate_b = 0
float debt_to_equity = 0
float debt_score = 0
float fair_value_distance = 0
float fair_value_distance_kum = 0
float fair_value_count = 0
int pe_rate_max = 100
float equitydebt_factor = 0.33
float close_max = 0
float targeta_max = 0.0
float targetb_max = 0.0

close_max := close

if (close[1] > close_max[1])
    close_max := close[1]
else
    if (close_max[1] > 0)
        close_max := close_max[1]
    
if (targeta[1] > targeta_max[1])
    targeta_max := targeta[1]
else
    if (targeta_max[1] > 0)
        targeta_max := targeta_max[1]
    
if (targetb[1] > targetb_max[1])
    targetb_max := targetb[1]
else
    if (targetb_max[1] > 0)
        targetb_max := targetb_max[1]



if (fair_value_count[1] > 0)
    fair_value_count := fair_value_count[1]
    
if (fair_value_distance_kum[1] > 0 or fair_value_distance_kum[1] < 0)
    fair_value_distance_kum := fair_value_distance_kum[1]

if (targetb[1] > 0 and targeta[1] > 0 and targeta[1] > (close[1]/100))
    fair_value_count := fair_value_count + 1
    fair_value_distance := (close[1] / targetb[1])
    if (fair_value_distance_kum[1] > 0 or fair_value_distance_kum < 0)
        fair_value_distance_kum := fair_value_distance_kum - (fair_value_distance_kum - fair_value_distance) / fair_value_count 
    else
        fair_value_distance_kum := fair_value_distance

tso = financial (str, "TOTAL_SHARES_OUTSTANDING", "FQ")
rev_total = financial (str, "TOTAL_REVENUE", "TTM")
market_cap = tso * close
ps_rate = market_cap / rev_total

equity = financial (str, "TOTAL_EQUITY", "FQ")
equity_price = equity / tso
debt = financial (str, "TOTAL_DEBT", "FQ")
debt_price = debt / tso
equitydebt_price = (equity_price - debt_price) * equitydebt_factor 

eps_rate = financial (str, "EARNINGS_PER_SHARE", "TTM")
pe_rate = close/eps_rate
earn := market_cap / pe_rate 

debt_to_equity := debt / equity
if (debt_to_equity <= 1.5 and debt_to_equity >= 0)
    debt_score := 1.5 - debt_to_equity + 1.0/3.0
    debt_score := debt_score / 1.2
    
if (debt_score < (1.0/3.0))
    debt_score := 1.0/3.0
    



if (pe_rate > 0)
    targeta := close * (3/ps_rate +  17.5/pe_rate) / 2
else
    targeta := close * ((3/ps_rate)/2) * ((rev_total+earn)/rev_total)
targeta := targeta * debt_score
targeta := targeta + equitydebt_price
if (targeta < 0)
    targeta := 0

if (pe_rate > 0)
    pe_rate_pos := pe_rate
    pe_rate_norm := pe_rate
    
if (pe_rate < 0)
    pe_rate_neg := pe_rate *(-1)
    pe_rate_norm := 1/pe_rate


if (pe_rate_pos > pe_rate_max)
    pe_rate_pos := pe_rate_max
    
if (pe_rate_neg > pe_rate_max)
    pe_rate_neg := pe_rate_max



if (rev_total[724] < rev_total[472] and rev_total[472] < rev_total[220] and rev_total[220] < rev_total) // 252 trading days a year, -32 for half a quarter.
    rev_b := rev_total * 2 - rev_total[850]
else
    rev_b := rev_total
ps_rate_b := market_cap / rev_b    

if (earn[724] < earn[472] and earn[472] < earn[220] and earn[220] < earn)
    earn_b := (earn * 2) - earn[850]
else
    earn_b := earn
pe_rate_b := market_cap / earn_b


//if (earn_b > 0)   
targetb := close * (3/ps_rate_b +  17.5/pe_rate_b) / 2
targetb := targetb * debt_score
targetb := targetb + equitydebt_price
    
if (targetb <= 0 or targetb < targeta or na(targetb))
    targetb := targeta
    
if (targetb == targeta and targetb[95] > targeta[95]) // 1,5 Quarters
    targetb := targetb + (targetb[95] - targeta[95]) / 3
    
if (fair_value_count > 252)
    targetc := targetb * fair_value_distance_kum
    
if (targetc <= 0 or na(targetc))
    targetc := targetb
    
if (targetb[1] == targeta[1] and targetb == targeta)
    col_targetb := color.new(color.lime,100)
    
if (targetc[1] == targetb[1] and targetc == targetb)
    col_targetc := color.new(color.blue,100)    
    
if (cut_off == 1)    
    if (targetc >= (close_max*1.2) and targetc >= (targeta_max*1.2) and targetc >= (targetb_max*1.2))
        col_targetc := color.new(color.blue,90)
        targetc := max(close_max,targeta_max,targetb_max)*1.2
    
if (not timeframe.isdaily)
    col_targeta := color.new(color.black,100)
    col_targetb := color.new(color.black,100)
    col_targetc := color.new(color.black,100)
    targeta := na
    targetb := na
    targetc := na

//plot(earn_b, color = color.blue)
//plot(earn, color = color.orange)
//plot(debt_score * 100, color = color.red)
//plot(pe_rate_b, color = color.silver)
//plot(pe_rate_neg, color = color.red)
//plot(ps_rate * 10, color = color.yellow)
//plot(fair_value_count)
//plot(fair_value_distance)
//plot(fair_value_distance_kum)
//plot(targeta_max)
//plot(close_max)
plot(targeta, title = "Fair Value w/o growth",  color = col_targeta, linewidth = 4)
plot(targetb, title = "Fair Value with growth", color = col_targetb, linewidth = 4)
plot(targetc, title = "Historical Behavior compared to Fair Value", color = col_targetc, linewidth = 4)