// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © HeWhoMustNotBeNamed
// __ __ __ __ __ __ __ __ __ __ __ _______ __ __ __
// / | / | / | _ / |/ | / \ / | / | / \ / | / | / \ / \ / | / |
// $$ | $$ | ______ $$ | / \ $$ |$$ |____ ______ $$ \ /$$ | __ __ _______ _$$ |_ $$ \ $$ | ______ _$$ |_ $$$$$$$ | ______ $$ \ $$ | ______ _____ ____ ______ ____$$ |
// $$ |__$$ | / \ $$ |/$ \$$ |$$ \ / \ $$$ \ /$$$ |/ | / | / |/ $$ | $$$ \$$ | / \ / $$ | $$ |__$$ | / \ $$$ \$$ | / \ / \/ \ / \ / $$ |
// $$ $$ |/$$$$$$ |$$ /$$$ $$ |$$$$$$$ |/$$$$$$ |$$$$ /$$$$ |$$ | $$ |/$$$$$$$/ $$$$$$/ $$$$ $$ |/$$$$$$ |$$$$$$/ $$ $$< /$$$$$$ |$$$$ $$ | $$$$$$ |$$$$$$ $$$$ |/$$$$$$ |/$$$$$$$ |
// $$$$$$$$ |$$ $$ |$$ $$/$$ $$ |$$ | $$ |$$ | $$ |$$ $$ $$/$$ |$$ | $$ |$$ \ $$ | __ $$ $$ $$ |$$ | $$ | $$ | __ $$$$$$$ |$$ $$ |$$ $$ $$ | / $$ |$$ | $$ | $$ |$$ $$ |$$ | $$ |
// $$ | $$ |$$$$$$$$/ $$$$/ $$$$ |$$ | $$ |$$ \__$$ |$$ |$$$/ $$ |$$ \__$$ | $$$$$$ | $$ |/ |$$ |$$$$ |$$ \__$$ | $$ |/ |$$ |__$$ |$$$$$$$$/ $$ |$$$$ |/$$$$$$$ |$$ | $$ | $$ |$$$$$$$$/ $$ \__$$ |
// $$ | $$ |$$ |$$$/ $$$ |$$ | $$ |$$ $$/ $$ | $/ $$ |$$ $$/ / $$/ $$ $$/ $$ | $$$ |$$ $$/ $$ $$/ $$ $$/ $$ |$$ | $$$ |$$ $$ |$$ | $$ | $$ |$$ |$$ $$ |
// $$/ $$/ $$$$$$$/ $$/ $$/ $$/ $$/ $$$$$$/ $$/ $$/ $$$$$$/ $$$$$$$/ $$$$/ $$/ $$/ $$$$$$/ $$$$/ $$$$$$$/ $$$$$$$/ $$/ $$/ $$$$$$$/ $$/ $$/ $$/ $$$$$$$/ $$$$$$$/
//
//
//
//@version=5
indicator("Discounted Price Probability", overlay=true)
import HeWhoMustNotBeNamed/_matrix/1 as ma
import HeWhoMustNotBeNamed/drawingutils/3 as dr
reference = input.string('Inception', title='Reference', options=['Inception', 'Window'], group='Reference')
startTime = input.time(defval=timestamp('01 Jan 2010 00:00 +0000'), title='Start Time', group='Reference')
endTime = input.time(defval=timestamp('01 Jan 2099 00:00 +0000'), title='End Time', group='Reference')
inDateRange = time >= startTime and time <= endTime
considerEarningPrice = input.bool(true, 'Earning Price', group='Main Factors', inline='1')
considerFundamentalsPerShare = input.bool(true, 'Fundamentals/Share', group='Main Factors', inline='1')
considerMargins = input.bool(true, 'Margins', group='Main Factors', inline='1')
considerReturns = input.bool(true, 'Returns', group='Main Factors', inline='2')
considerInvertedDebtRatios = input.bool(true, 'Inverted Debt Ratios', group='Main Factors', inline='2')
considerBvps = input.bool(true, 'Book Value', group='Fundamentals/Share', inline='1')
considerEps = input.bool(true, 'Earning', group='Fundamentals/Share', inline='1')
considerRps = input.bool(true, 'Revenue', group='Fundamentals/Share', inline='1')
considerFcf = input.bool(true, 'FCF', group='Fundamentals/Share', inline='2')
considerEbit = input.bool(true, 'EBIT', group='Fundamentals/Share', inline='2')
considerEbitda = input.bool(true, 'EBITDA', group='Fundamentals/Share', inline='2')
considerNetMargin = input.bool(true, 'Net', group='Margin', inline='1')
considerGrossMargin = input.bool(true, 'Gross', group='Margin', inline='1')
considerOperatingMargin = input.bool(true, 'Operating', group='Margin', inline='1')
considerEBITDAMargin = input.bool(true, 'EBITDA', group='Margin', inline='1')
considerFCFMargin = input.bool(true, 'FCF', group='Margin', inline='1')
considerROA = input.bool(true, 'ROA', group='Returns', inline='1')
considerROE = input.bool(true, 'ROE', group='Returns', inline='1')
considerROIC = input.bool(true, 'ROIC', group='Returns', inline='1')
considerDTA = input.bool(true, 'DTA', group='Inversed Debt Ratios', inline='1')
considerLDTA = input.bool(true, 'LDTA', group='Inversed Debt Ratios', inline='1')
considerDTE = input.bool(true, 'DTE', group='Inversed Debt Ratios', inline='1')
considerDTR = input.bool(true, 'DTR', group='Inversed Debt Ratios', inline='1')
considerDTEB = input.bool(true, 'DTEBITDA', group='Inversed Debt Ratios', inline='1')
displayTimeframe = input.bool(true, 'Display Timeframe', group='Display')
financialParameters = array.from('Current')
ignoredParameters = array.new_string()
fundamentalParameters = array.new_string()
marginParameters = array.new_string()
returnParameters = array.new_string()
debtParameters = array.new_string()
financialFactorColumns = array.from(1)
financialFactors = array.from('Price')
array.push(considerEarningPrice?financialParameters:ignoredParameters, 'Last Earnings')
array.push(financialFactorColumns, array.get(financialFactorColumns, array.size(financialFactorColumns)-1)+array.size(financialParameters))
array.push(considerFundamentalsPerShare and considerBvps?fundamentalParameters:ignoredParameters, 'Book Value')
array.push(considerFundamentalsPerShare and considerEps?fundamentalParameters:ignoredParameters, 'Earnings')
array.push(considerFundamentalsPerShare and considerRps?fundamentalParameters:ignoredParameters, 'Revenue')
array.push(considerFundamentalsPerShare and considerFcf?fundamentalParameters:ignoredParameters, 'FCF')
array.push(considerFundamentalsPerShare and considerEbit?fundamentalParameters:ignoredParameters, 'EBIT')
array.push(considerFundamentalsPerShare and considerEbitda?fundamentalParameters:ignoredParameters, 'EBITDA')
if(array.size(fundamentalParameters) != 0)
array.concat(financialParameters, fundamentalParameters)
array.push(financialFactorColumns, array.get(financialFactorColumns, array.size(financialFactorColumns)-1)+array.size(fundamentalParameters))
array.push(financialFactors, 'Fundamentals/Share')
array.push(considerMargins and considerNetMargin?marginParameters:ignoredParameters, 'Net')
array.push(considerMargins and considerGrossMargin?marginParameters:ignoredParameters, 'Gross')
array.push(considerMargins and considerOperatingMargin?marginParameters:ignoredParameters, 'Operating')
array.push(considerMargins and considerEBITDAMargin?marginParameters:ignoredParameters, 'EBITDA')
array.push(considerMargins and considerFCFMargin?marginParameters:ignoredParameters, 'FCF')
if(array.size(marginParameters) != 0)
array.concat(financialParameters, marginParameters)
array.push(financialFactorColumns, array.get(financialFactorColumns, array.size(financialFactorColumns)-1)+array.size(marginParameters))
array.push(financialFactors, 'Margin')
array.push(considerReturns and considerROA?returnParameters:ignoredParameters, 'ROA')
array.push(considerReturns and considerROE?returnParameters:ignoredParameters, 'ROE')
array.push(considerReturns and considerROIC?returnParameters:ignoredParameters, 'ROIC')
if(array.size(returnParameters) != 0)
array.concat(financialParameters, returnParameters)
array.push(financialFactorColumns, array.get(financialFactorColumns, array.size(financialFactorColumns)-1)+array.size(returnParameters))
array.push(financialFactors, 'Returns')
array.push(considerInvertedDebtRatios and considerDTA?debtParameters:ignoredParameters, 'Assets')
array.push(considerInvertedDebtRatios and considerLDTA?debtParameters:ignoredParameters, 'Assets(Long Term)')
array.push(considerInvertedDebtRatios and considerDTE?debtParameters:ignoredParameters, 'Equity')
array.push(considerInvertedDebtRatios and considerDTR?debtParameters:ignoredParameters, 'Revenue')
array.push(considerInvertedDebtRatios and considerDTEB?debtParameters:ignoredParameters, 'EBITDA')
if(array.size(debtParameters) != 0)
array.concat(financialParameters, debtParameters)
array.push(financialFactorColumns, array.get(financialFactorColumns, array.size(financialFactorColumns)-1)+array.size(debtParameters))
array.push(financialFactors, 'Inverted Debt Ratios')
f_getFinancials(financial_id, period) =>
request.financial(syminfo.tickerid, financial_id, period)
f_getOptimalFinancialBasic(financial_id) =>
f_getFinancials(financial_id, syminfo.currency == 'USD' ? 'FQ' : 'FY')
tso = request.financial(syminfo.tickerid, 'TOTAL_SHARES_OUTSTANDING', 'FQ')
bvps = request.financial(syminfo.tickerid, 'BOOK_VALUE_PER_SHARE', 'FQ')
eps = request.financial(syminfo.tickerid, 'EARNINGS_PER_SHARE_BASIC', 'TTM')
rps = request.financial(syminfo.tickerid, 'TOTAL_REVENUE', 'TTM') / tso
ebitda = request.financial(syminfo.tickerid, 'EBITDA', 'TTM') / tso
ebit = f_getOptimalFinancialBasic('EBIT') / tso
fcf = f_getOptimalFinancialBasic('FREE_CASH_FLOW') / tso
//currentassets = f_getOptimalFinancialBasic("NCAVPS_RATIO")
nmargin = f_getOptimalFinancialBasic('NET_MARGIN')
gmargin = f_getOptimalFinancialBasic('GROSS_MARGIN')
omargin = f_getOptimalFinancialBasic('OPERATING_MARGIN')
emargin = f_getOptimalFinancialBasic('EBITDA_MARGIN')
fmargin = f_getOptimalFinancialBasic('FREE_CASH_FLOW_MARGIN')
roa = f_getOptimalFinancialBasic('RETURN_ON_ASSETS')
roe = f_getOptimalFinancialBasic('RETURN_ON_EQUITY')
roic = f_getOptimalFinancialBasic('RETURN_ON_INVESTED_CAPITAL')
ldta = 1 / f_getOptimalFinancialBasic('LONG_TERM_DEBT_TO_ASSETS')
dta = 1 / f_getOptimalFinancialBasic('DEBT_TO_ASSET')
dte = 1 / f_getOptimalFinancialBasic('DEBT_TO_EQUITY')
dtr = 1 / f_getOptimalFinancialBasic('DEBT_TO_REVENUE')
dteb = 1 / f_getOptimalFinancialBasic('DEBT_TO_EBITDA')
NUMBER_OF_ITEMS = 20
earnings = request.earnings(syminfo.tickerid, earnings.actual, barmerge.gaps_on, barmerge.lookahead_off, true)
getPercentile(value, defaultToZero = true)=>
var arr = array.new_float()
array.unshift(arr, value)
array.size(arr)==1? 100.0 : array.percentrank(arr, 0)
getPercentileDrawdown(value, defaultToZero = true)=>
var arr = array.new_float()
sIndex = array.binary_search_rightmost(arr, value)
array.insert(arr, sIndex, value)
index = defaultToZero? array.indexof(arr, value) : array.lastindexof(arr, value)
percentile = (index+1)*100/array.size(arr)
percentile
f_calculate_drawdown_stats(value) =>
var float ath = na
var float drawdownPercentile = 0
var drawdown = 0.0
var percentile = 0.0
if(not na(value))
percentile := getPercentile(value)
ath := math.max(value, nz(ath, value))
drawdown := math.round(math.abs(ath - value)*100 / math.max(math.abs(ath), math.abs(value)))
drawdownPercentile := getPercentileDrawdown(drawdown)
percentileColor = color.from_gradient(percentile, 0, 100, color.red, color.green)
drawdownColor = color.from_gradient(drawdownPercentile, 0, 100, color.green, color.red)
[array.from(value, ath, percentile, drawdown, drawdownPercentile),
array.from(percentileColor, percentileColor, percentileColor, drawdownColor, drawdownColor)]
comparitive_drawdown(value, priceDrawdown, pricePercentile, statsMatrix, colorMatrix, condition=true) =>
if(condition)
[statsArray, colorArray] = f_calculate_drawdown_stats(value)
drawdownDiff = priceDrawdown - array.get(statsArray, 3)
percentileDiff = array.get(statsArray, 2)-pricePercentile
diffDrawdownPercentile = getPercentile(drawdownDiff)
diffPricePercentile = getPercentile(percentileDiff)
array.push(statsArray, diffPricePercentile)
array.push(statsArray, diffDrawdownPercentile)
array.push(colorArray, color.from_gradient(diffPricePercentile, 0, 100, color.red, color.green))
array.push(colorArray, color.from_gradient(diffDrawdownPercentile, 0, 100, color.red, color.green))
ma.push(statsMatrix, statsArray, NUMBER_OF_ITEMS)
ma.push(colorMatrix, colorArray, NUMBER_OF_ITEMS)
if reference == 'Inception' or inDateRange
if displayTimeframe
dr.runTimer()
[priceDrawdownStats, priceDrawdownColors] = f_calculate_drawdown_stats(high)
drawdown = array.get(priceDrawdownStats, 3)
percentile = array.get(priceDrawdownStats, 2)
var percentileArray = array.new_float(20, 0)
var diffArray = array.new_float(20, 0)
var drawdownArray = array.new_float(20, 0)
var matrix<float> statMatrix = matrix.new<float>()
var matrix<color> colorMatrix = matrix.new<color>()
statParameters = array.from("Value", "ATH", "Percentile", "Drawdown", "Drawdown\nPercentile", "Differential Percentile\n(Absolute)", "Differential Percentile\n(Drawdown)")
if(not na(earnings))
ma.clear(statMatrix)
ma.clear(colorMatrix)
comparitive_drawdown(close, drawdown, percentile, statMatrix, colorMatrix, considerEarningPrice)
comparitive_drawdown(bvps, drawdown, percentile, statMatrix, colorMatrix, considerFundamentalsPerShare and considerBvps)
comparitive_drawdown(eps, drawdown, percentile, statMatrix, colorMatrix, considerFundamentalsPerShare and considerEps)
comparitive_drawdown(rps, drawdown, percentile, statMatrix, colorMatrix, considerFundamentalsPerShare and considerRps)
comparitive_drawdown(fcf, drawdown, percentile, statMatrix, colorMatrix, considerFundamentalsPerShare and considerFcf)
comparitive_drawdown(ebit, drawdown, percentile, statMatrix, colorMatrix, considerFundamentalsPerShare and considerEbit)
comparitive_drawdown(ebitda, drawdown, percentile, statMatrix, colorMatrix, considerFundamentalsPerShare and considerEbitda)
comparitive_drawdown(nmargin, drawdown, percentile, statMatrix, colorMatrix, considerMargins and considerNetMargin)
comparitive_drawdown(gmargin, drawdown, percentile, statMatrix, colorMatrix, considerMargins and considerGrossMargin)
comparitive_drawdown(omargin, drawdown, percentile, statMatrix, colorMatrix, considerMargins and considerOperatingMargin)
comparitive_drawdown(emargin, drawdown, percentile, statMatrix, colorMatrix, considerMargins and considerEBITDAMargin)
comparitive_drawdown(fmargin, drawdown, percentile, statMatrix, colorMatrix, considerMargins and considerFCFMargin)
comparitive_drawdown(roa, drawdown, percentile, statMatrix, colorMatrix, considerReturns and considerROA)
comparitive_drawdown(roe, drawdown, percentile, statMatrix, colorMatrix, considerReturns and considerROE)
comparitive_drawdown(roic, drawdown, percentile, statMatrix, colorMatrix, considerReturns and considerROIC)
comparitive_drawdown(dta, drawdown, percentile, statMatrix, colorMatrix, considerInvertedDebtRatios and considerDTA)
comparitive_drawdown(ldta, drawdown, percentile, statMatrix, colorMatrix, considerInvertedDebtRatios and considerLDTA)
comparitive_drawdown(dte, drawdown, percentile, statMatrix, colorMatrix, considerInvertedDebtRatios and considerDTE)
comparitive_drawdown(dtr, drawdown, percentile, statMatrix, colorMatrix, considerInvertedDebtRatios and considerDTR)
comparitive_drawdown(dteb, drawdown, percentile, statMatrix, colorMatrix, considerInvertedDebtRatios and considerDTEB)
percentileDAvg = matrix.columns(statMatrix) > 6 ? array.avg(matrix.col(statMatrix, 6)) : na
percentilePAvg = matrix.columns(statMatrix) > 5 ? array.avg(matrix.col(statMatrix, 5)) : na
if(barstate.islastconfirmedhistory)
stats = table.new(position.middle_center, matrix.columns(statMatrix)+2, matrix.rows(statMatrix)+3, border_width=2)
table.clear(stats, 0, 0, matrix.columns(statMatrix)+1, matrix.rows(statMatrix)+2)
table.cell(stats, 0, 0, "P " +str.tostring(percentilePAvg, format.percent), bgcolor=color.from_gradient(percentilePAvg, 0, 100, color.red, color.green),
text_color=color.white, text_size=size.huge, tooltip='Probability based on absolute percentile')
table.cell(stats, 0, 1, "D " +str.tostring(percentileDAvg, format.percent), bgcolor=color.from_gradient(percentileDAvg, 0, 100, color.red, color.green),
text_color=color.white, text_size=size.huge, tooltip='Probability based on drawdown percentile')
for i=0 to array.size(financialFactors)-1
table.cell(stats, 0, array.get(financialFactorColumns, i)+1, array.get(financialFactors, i), bgcolor=color.maroon, text_color=color.white, text_size=size.small)
table.merge_cells(stats, 0, array.get(financialFactorColumns, i)+1, 0, array.get(financialFactorColumns, i+1))
table.merge_cells(stats, 0, 0, 1, 0)
table.merge_cells(stats, 0, 1, 1, 1)
for i=0 to array.size(financialParameters)-1
table.cell(stats, 1, i+2, array.get(financialParameters, i), bgcolor=color.teal, text_color=color.white, text_size=size.small)
for j=0 to array.size(priceDrawdownStats)-1
table.cell(stats, j+2, 2, str.tostring(array.get(priceDrawdownStats,j), j<2? '#.00' : format.percent), bgcolor=color.blue, text_color=color.white, text_size=size.small)
table.cell(stats, array.size(priceDrawdownStats)+2, 2, '', bgcolor=color.blue, text_color=color.white, text_size=size.small)
table.cell(stats, array.size(priceDrawdownStats)+3, 2, '', bgcolor=color.blue, text_color=color.white, text_size=size.small)
for j=0 to array.size(statParameters)-1
table.cell(stats, j+2, 1, array.get(statParameters, j), bgcolor=color.maroon, text_color=color.white, text_size=size.small)
for i=0 to matrix.rows(statMatrix)==0? na : matrix.rows(statMatrix)-1
for j=0 to matrix.columns(statMatrix)-1
table.cell(stats, j+2,i+2+1, str.tostring(matrix.get(statMatrix,i,j), j<2? '#.00' : format.percent), bgcolor=matrix.get(colorMatrix,i,j), text_color=color.white, text_size=size.small)
Show all 262 lines