financial-growth.pine
Copy
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © morzor61
// ###### Revision Note ################################################################ //
// 1. Released
// 2. Add more items
//--------------------------------------------------------------------------------------//
// 3. 2022-Dec-17 :
// - add 2 financial item.
// - add, eps diluted.
// - re-arrange code.
//--------------------------------------------------------------------------------------//
// 4. 2023-Jan-22
// - Add more items.
// - re-arranged code.
//@version=5
indicator("Financial Growth",overlay=false, format = format.volume)
// TEXT SIZE +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
text_size_AUTO = size.auto , text_size_TINY = size.tiny
text_size_SMALL = size.small , text_size_NORMAL = size.normal
text_size_LARGE = size.large , text_size_HUGE = size.huge
// TABLE POSITION ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
tb_pos_POS01 = position.top_left , tb_pos_POS02 = position.top_center
tb_pos_POS03 = position.top_right , tb_pos_POS04 = position.middle_left
tb_pos_POS05 = position.middle_center , tb_pos_POS06 = position.middle_right
tb_pos_POS07 = position.bottom_left , tb_pos_POS08 = position.bottom_center
tb_pos_POS09 = position.bottom_right
// Financial Items +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Income Statement
_revenue = "Revenue" ,_revenue_id = 'TOTAL_REVENUE'
_net_income = "Net Income" ,_net_income_id = 'NET_INCOME'
_ebitda = "EBITDA" ,_ebitda_id = "EBITDA"
_eps = "EPS" ,_eps_id = "EARNINGS_PER_SHARE_BASIC"
_eps_diluted = "EPS, Diluted" ,_eps_diluted_id = 'EARNINGS_PER_SHARE_DILUTED'
_dvps = "Dividend per share" ,_dvps_id = 'DPS_COMMON_STOCK_PRIM_ISSUE'
// Balance Sheet
_total_asset = "Total Assets", _total_asset_id = "TOTAL_ASSETS"
_total_liability = "Total Liabilities", _total_liability_id = "TOTAL_LIABILITIES"
_total_debt = "Total Debt" ,_total_debt_id = 'TOTAL_DEBT' // Interest Bearing Debt
_short_term_debt = "ST Debt", _short_term_debt_id = "SHORT_TERM_DEBT"
_long_term_debt = "LT Debt", _long_term_debt_id = "LONG_TERM_DEBT"
_net_debt = "Net Debt", _net_debt_id = "NET_DEBT"
_interest_expense_on_debt = "Interest Expense", _interest_expense_on_debt_id = "INTEREST_EXPENSE_ON_DEBT"
_total_euity = "Total Equity", _total_equity_id = "TOTAL_EQUITY"
// Cash Flow
_free_cash_flow = "Free Cash Flow" ,_free_cash_flow_id = 'FREE_CASH_FLOW'
// Statistics and Ratios
_de = "D/E", _de_id = "DEBT_TO_EQUITY"
_interest_coverage = "Coverage Ratio", _interest_coverage_id = "INTERST_COVER"
_gross_margin = "Gross Margin" ,_gross_margin_id = 'GROSS_MARGIN'
_operating_margin = "Operating Margin" ,_operating_margin_id = "OPERATING_MARGIN"
_ebitda_margin = "EBITDA Margin" ,_ebitda_margin_id = 'EBITDA_MARGIN'
_net_margin = "Net Margin" ,_net_margin_id = 'NET_MARGIN'
_roe = "ROE" ,_roe_id = 'RETURN_ON_EQUITY'
_roa = "ROA" ,_roa_id = 'RETURN_ON_ASSETS'
// Calculated Items
_pbv = "P/BV" //,_pbv_id = 'BOOK_VALUE_PER_SHARE'
_pe = "P/E" //,_pe_id = "P/E" // Calculated
_ps = "P/S" //,_ps_id = "P/S" // Price to Sales Total outstanding share (FQ), * close / Total Revenue (TTM)
_pfcf = "P/FCF" //,_pfcf_id = "P/FCF" // Price to Free Cash Flow, Total outstanding share (FQ) * close / Free Cash Flow (FQ)
price_to_earning = close / request.financial(syminfo.tickerid, "EARNINGS_PER_SHARE_DILUTED",'TTM', ignore_invalid_symbol = true)
price_to_book_value = close / request.financial(syminfo.tickerid, "BOOK_VALUE_PER_SHARE", 'FQ', ignore_invalid_symbol = true)
price_to_sales = (
(request.financial(syminfo.tickerid, "TOTAL_SHARES_OUTSTANDING", "FQ", ignore_invalid_symbol = true ) * close) /
request.financial(syminfo.tickerid, "TOTAL_REVENUE", "TTM", ignore_invalid_symbol = true )
)
price_to_free_cash_flow = (
(request.financial(syminfo.tickerid, "TOTAL_SHARES_OUTSTANDING", "FQ", ignore_invalid_symbol = true ) * close) /
request.financial(syminfo.tickerid, "FREE_CASH_FLOW", "FQ", ignore_invalid_symbol = true )
)
published_date() =>
// Get published date of financial report
_ticker = 'ESD_FACTSET:'+syminfo.prefix+';'+syminfo.ticker+';EARNINGS'
published_date = request.security(_ticker, 'D',time,gaps=barmerge.gaps_on, ignore_invalid_symbol=true, lookahead=barmerge.lookahead_on)
// 3. INPUT =============================================================================
group4 ='Input'
group_item_01 = "Items"
group_item_01_line_01 = "line 01"
group_item_01_line_02 = "line 02"
group_item_01_line_03 = "line 03"
group_item_02 = "Group 02"
financial_item_selection_01 = input.string( _revenue, "Item 1 / 2", options=[
"===== Income ======",
_revenue,_net_income, _ebitda, _eps, _eps_diluted, _dvps,
"== Balance Sheet ==",
_total_asset,
_total_liability,
_total_debt,
_net_debt,
_long_term_debt,
_short_term_debt,
_interest_expense_on_debt ,
_total_euity,
"==== Cash Flow ====",
_free_cash_flow,
"===== Margin =====",
_gross_margin, _ebitda_margin, _operating_margin, _net_margin,
"===== Ratio =====",
_roe, _roa, _pbv, _pe, _ps, _pfcf, _de, _interest_coverage],
inline = group_item_01_line_01, group = group_item_01)
financial_item_selection_02 = input.string( _net_income, "", options=[
"===== Income ======",
_revenue,
_net_income, _ebitda, _eps, _eps_diluted, _dvps,
"== Balance Sheet ==",
_total_asset,
_total_liability,
_total_debt,
_net_debt,
_long_term_debt,
_short_term_debt,
_interest_expense_on_debt ,
_total_euity,
"==== Cash Flow ====",
_free_cash_flow,
"===== Margin =====",
_gross_margin, _ebitda_margin, _operating_margin, _net_margin,
"===== Ratio =====",
_roe, _roa, _pbv, _pe, _ps, _pfcf, _de, _interest_coverage ],
inline = group_item_01_line_01, group = group_item_01 )
period_selection = input.string('FQ', 'Period / Number of Period', options=['FQ', 'FY', 'TTM'], inline = group_item_01_line_02, group=group_item_01)
data_size_selection = input.int(4, '', minval = 4, inline = group_item_01_line_02, group=group_item_01) +5
// Future Plan
// report_date = input.string(defval = "Period Ended", title = "Report Date", options = ["Period Ended", "Published Date"], inline = group_item_01_line_03, group = group_item_01)
group_table_01 = 'Table'
show_table = input.bool(true, 'Show Table', inline='01', group=group_table_01)
is_qoq = input.bool(true, "Show QoQ", inline='02', group=group_table_01)
is_yoy = input.bool(true, "Show YoY", inline='02', group=group_table_01)
is_cagr = input.bool(false, "Show CAGR", inline='02', group=group_table_01)
table_text_color = input.color(color.black, 'Text/BG/Head/Body', inline = group_table_01, group = group_table_01)
table_bg_color = input.color(color.new(#979797, 0), '', inline = group_table_01, group = group_table_01)
table_body_color = input.color(color.new(#fffffa, 0), '', inline = group_table_01, group = group_table_01)
table_header_color= input.color(color.new(#f0af8a, 0), '', inline = group_table_01, group = group_table_01)
table_text_size = input.string(text_size_NORMAL, 'Text Size/Postion', options=[text_size_AUTO, text_size_TINY, text_size_SMALL, text_size_NORMAL, text_size_LARGE, text_size_HUGE], inline='02', group=group_table_01)
table_position_selection = input.string(tb_pos_POS09, '', options=[tb_pos_POS01,tb_pos_POS02, tb_pos_POS03, tb_pos_POS04, tb_pos_POS05, tb_pos_POS06, tb_pos_POS07, tb_pos_POS08, tb_pos_POS09], inline='02', group=group_table_01)
group_plot_01 = "Plotting"
group_plot_line_01 = "plotting line"
show_plot = input.bool(false, "Show plot", inline = group_plot_01, group = group_plot_01)
show_plot_label = input.bool(false, "Show plot labels", inline = group_plot_01, group = group_plot_01)
label_text_color = input.color(color.new(color.black, 0), 'Text', inline=group_plot_line_01, group=group_plot_01)
label_bg_color = input.color(color.new(color.aqua, 25), 'Bg Color', inline=group_plot_line_01, group=group_plot_01)
// 2. FUNCTION ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Function for Financial
is_calculated_data(_financial_item)=>
bool logic = (_financial_item == _pbv or _financial_item == _pe or _financial_item == _pfcf or _financial_item == _ps)
get_financial_ratio(_financial_ratio)=>
switch _financial_ratio
_pe => price_to_earning
_pbv => price_to_book_value
_ps => price_to_sales
_pfcf => price_to_free_cash_flow
=> na
get_financial_id(_financial_item)=>
// Get financial id from financial item
switch _financial_item
// income statement
_revenue => _revenue_id
_net_income => _net_income_id
_ebitda => _ebitda_id
_eps => _eps_id
_eps_diluted => _eps_diluted_id
_dvps => _dvps_id
// balance sheet
_total_asset =>_total_asset_id
_total_liability =>_total_liability_id
// Debt
_total_debt =>_total_debt_id
_long_term_debt => _long_term_debt_id
_short_term_debt => _short_term_debt_id
_net_debt => _net_debt_id
_interest_expense_on_debt => _interest_expense_on_debt_id
_total_euity =>_total_equity_id
// cash flow
_free_cash_flow =>_free_cash_flow_id
// statistic and ratio
_gross_margin =>_gross_margin_id
_ebitda_margin =>_ebitda_margin_id
_operating_margin => _operating_margin_id
_net_margin =>_net_margin_id
_roe =>_roe_id
_roa =>_roa_id
_de => _de_id
_interest_coverage => _interest_coverage_id
// _pbv =>_pbv_id
// _pe =>_pe_id
// _ps =>_ps_id
// _pfcf =>_pfcf_id
retreive_financial_data(_financial_item, _period)=>
// Retreive financial data from finanancial id.
// _id Financial id
// _period period, FQ, FY, TTM
_id = get_financial_id(_financial_item = _financial_item)
financial_data = request.financial(syminfo.tickerid, _id, _period, barmerge.gaps_on, ignore_invalid_symbol = true)
create_array(arrayId, val) =>
// Function to get financial data from TradingView.
array.unshift(arrayId, val) // append value to an array
array.pop(arrayId)
// array.push(arrayId, val)
// array.shift(arrayId)
get_value_formating(_financial_item)=>
// return format, divider and suffix of value.
value_divider = 0 , value_decimal = "", value_suffix = ""
is_true = (
_financial_item == _revenue or _financial_item ==_net_income or
_financial_item == _ebitda or
_financial_item == _free_cash_flow or
_financial_item == _total_asset or
_financial_item == _total_liability or
// Debt
_financial_item == _total_debt or
_financial_item == _long_term_debt or
_financial_item == _short_term_debt or
_financial_item == _interest_expense_on_debt or
_financial_item == _net_debt or
_financial_item == _total_euity )
value_divider := is_true ? 1000000 : 1
value_suffix := is_true ? " M" : ""
value_decimal := is_true ? "#,##0" : "#,##0.000"
[value_divider, value_suffix, value_decimal]
get_cagr(_data_array, _id, _idmax)=>
// Get compound annual growth rate
_current_value = array.get(_data_array, _id)
_start_value = array.get(_data_array, _idmax)
cagr = (math.pow((_current_value/math.abs(_start_value)), 1/_idmax)-1)*100
// Table ----------------------------------------------------------------------------
header_column( _table, _col, _row, _value) =>
table.cell(table_id = _table , column= _col , row= _row ,text = _value, text_color = table_text_color, text_size = table_text_size ,bgcolor = table_header_color)
date_column( _table, _col, _row, _data_array, _id) =>
_date_value = str.format('{0, date, yyyy-MMM-dd}', array.get(_data_array, _id))
table.cell( table_id = _table, column = _col,row = _row, text = _date_value, text_color = table_text_color, text_size = table_text_size, bgcolor = table_body_color )
value_column( _table, _col, _row, _data_array, _id, _financial_item)=>
[value_divider, value_suffix, value_decimal] = get_value_formating(_financial_item)
val = array.get(_data_array, _id)/ value_divider
table.cell(table_id= _table, column = _col, row = _row,text = str.tostring(val, value_decimal) + value_suffix, text_color = table_text_color, text_size = table_text_size, bgcolor = table_body_color)
qoq_column( _table, _col, _row, _data_array, _id, _period)=>
_compare = (_period == "FQ" or _period == "TTM") ? 1 : na
_current_value = array.get(_data_array, _id), _previous_value = array.get(_data_array, _id+_compare)
_different_value = ((_current_value-_previous_value)/ math.abs(_previous_value))*100
_symbol = _different_value >= 0 ? ' 😍' : ' 😡'
_text = str.tostring(_different_value, '#,##0.0') + _symbol
table.cell(table_id = _table, column = _col, row = _row,text = _text,text_halign = text.align_right,text_color = table_text_color,text_size = table_text_size, bgcolor = color.new(_different_value >= 0 ? color.green : color.red, 75))
yoy_column( _table, _col, _row, _data_array, _id, _period)=>
_compare = (_period == "FQ" or _period == "TTM") ? 4 : 1
_current_value = array.get(_data_array, _id), _previous_value = array.get(_data_array, _id+_compare)
_different_value = ((_current_value-_previous_value)/ math.abs(_previous_value))*100
_symbol = _different_value >= 0 ? ' 😍' : ' 😡'
_text = str.tostring(_different_value, '#,##0.0') + _symbol
table.cell( table_id = _table, column = _col, row = _row, text = _text, text_halign = text.align_right,text_color = table_text_color , text_size = table_text_size, bgcolor = color.new(_different_value >= 0 ? color.green : color.red, 75))
cagr_column( _table, _col, _row, _data_array, _id, _idmax)=>
_value = get_cagr(_data_array, _id, _idmax)
_symbol = _value >= 0 ? ' 😍' : ' 😡'
_text = str.tostring(_value , '#,##0.0')+_symbol
_bgcolor = color.new(_value >= 0 ? color.green : color.red, 75)
table.cell( table_id = _table, column = _col, row = _row, text = _text, text_halign = text.align_right, text_color = table_text_color, text_size = table_text_size, bgcolor = _bgcolor)
//
// 4. Calculation =======================================================================
reference_revenue = request.financial(symbol = syminfo.tickerid, financial_id = 'TOTAL_REVENUE', period= period_selection, gaps= barmerge.gaps_on, ignore_invalid_symbol =true )
temp_financial_data_01 = retreive_financial_data(_financial_item = financial_item_selection_01, _period = period_selection)
temp_financial_data_02 = retreive_financial_data(_financial_item = financial_item_selection_02, _period = period_selection)
financial_data_01 = is_calculated_data(financial_item_selection_01) ? get_financial_ratio(financial_item_selection_01) : temp_financial_data_01
financial_data_02 = is_calculated_data(financial_item_selection_02) ? get_financial_ratio(financial_item_selection_02) : temp_financial_data_02
var date_array = array.new_int( data_size_selection) // Date
var financial_data_array = array.new_float( data_size_selection) // EPS
var financial_data_array_02 = array.new_float( data_size_selection) // EPS
if reference_revenue
create_array(date_array, time)
create_array(financial_data_array, financial_data_01)
create_array(financial_data_array_02, financial_data_02)
// 5. TABLE ================================================================================
var table t = table.new(
position = table_position_selection, columns = 10, rows = data_size_selection,
bgcolor = table_bg_color, frame_color = color.rgb(156, 156, 156),
frame_width = 2, border_color = color.rgb(229, 226, 229), border_width = 1 )
// Show & Hide Column
bool qoq_column = (period_selection == "FQ" or period_selection == "TTM" ) and is_qoq
bool yoy_column = (period_selection == "FQ" or period_selection == "TTM" or period_selection == "FY") and is_yoy
bool cagr_column = (period_selection == "FY" or period_selection == "TTM") and is_cagr
if barstate.islast and show_table
period_header = period_selection == "FY" ? "Year" : "Quarter"
header_column(_table = t, _col = 0, _row = 0, _value = period_header )
header_column(_table = t, _col = 1, _row = 0, _value = financial_item_selection_01 )
header_column(_table = t, _col = 5, _row = 0, _value = financial_item_selection_02 )
if qoq_column
header_column(_table = t, _col = 2,_row = 0, _value = "QoQ")
header_column(_table = t, _col = 6,_row = 0, _value = "QoQ")
if yoy_column
header_column(_table = t, _col = 3,_row = 0,_value = 'YoY')
header_column(_table = t, _col = 7,_row = 0,_value = 'YoY')
if cagr_column
header_column(_table = t, _col = 4,_row = 0,_value = 'CAGR')
header_column(_table = t, _col = 8,_row = 0,_value = 'CAGR')
for _irow = 0 to data_size_selection - 5
if barstate.islast and show_table
date_column( _table = t,_col = 0 ,_row = _irow + 1, _data_array = date_array, _id = _irow)
value_column(_table = t,_col = 1 ,_row = _irow + 1, _data_array = financial_data_array, _id = _irow, _financial_item = financial_item_selection_01)
value_column(_table = t,_col = 5 ,_row = _irow + 1, _data_array = financial_data_array_02,_id = _irow, _financial_item = financial_item_selection_02)
if qoq_column
qoq_column(_table = t,_col = 2,_row = _irow+1,_data_array = financial_data_array, _id = _irow, _period = period_selection)
qoq_column(_table = t,_col = 6,_row = _irow+1,_data_array = financial_data_array_02,_id = _irow, _period = period_selection)
if yoy_column
yoy_column(_table = t, _col = 3, _row = _irow+1,_data_array = financial_data_array,_id = _irow, _period = period_selection)
yoy_column(_table = t,_col = 7,_row = _irow+1,_data_array = financial_data_array_02,_id = _irow,_period = period_selection)
if cagr_column
cagr_column(_table = t,_col = 4,_row = _irow+1,_data_array = financial_data_array,_id = _irow,_idmax = data_size_selection-5 )
cagr_column(_table = t,_col = 8,_row = _irow+1,_data_array = financial_data_array_02,_id = _irow,_idmax = data_size_selection-5 )
// Ploting ========================================================================================================//
plot_data_01 = show_plot ? financial_data_01 : na
plot_data_02 = show_plot ? financial_data_02 : na
plot(plot_data_01, "Plot 01", style = plot.style_circles, linewidth = 2, join = true, color = color.rgb(255, 2, 158))
plot(plot_data_02, "Plot 02", style = plot.style_circles, linewidth = 2, join = true, color = color.rgb(25, 0, 255))
// Labels
if show_plot and show_plot_label and reference_revenue
[val_divide, val_suffix, val_decimal] = get_value_formating(financial_item_selection_01)
label_01 = label.new(
x = bar_index, y = plot_data_01,
text = str.tostring(plot_data_01/val_divide, val_decimal + val_suffix)
, color = label_bg_color
, textcolor = label_text_color)
[val_divide2, val_suffix2, val_decimal2] = get_value_formating(financial_item_selection_02)
label_02 = label.new(
x = bar_index,y = plot_data_02,
text = str.tostring(plot_data_02/val_divide2, val_decimal2+val_suffix2)
, color = label_bg_color
, textcolor = label_text_color)
Show all 392 lines