Class: FinModeling::ReformulatedIncomeStatement
- Inherits:
-
Object
- Object
- FinModeling::ReformulatedIncomeStatement
- Defined in:
- lib/finmodeling/reformulated_income_statement.rb
Direct Known Subclasses
Instance Attribute Summary collapse
-
#cost_of_revenues ⇒ Object
Returns the value of attribute cost_of_revenues.
-
#operating_expenses ⇒ Object
Returns the value of attribute operating_expenses.
-
#operating_revenues ⇒ Object
Returns the value of attribute operating_revenues.
-
#period ⇒ Object
Returns the value of attribute period.
Class Method Summary collapse
Instance Method Summary collapse
- #-(ris2) ⇒ Object
- #analysis(re_bs, prev_re_is, prev_re_bs, expected_rate_of_return) ⇒ Object
- #comprehensive_income ⇒ Object
- #core_oi_growth(prev) ⇒ Object
- #fi_over_nfa(reformed_bal_sheet) ⇒ Object
- #fi_over_sales ⇒ Object
- #gross_margin ⇒ Object
- #gross_revenue ⇒ Object
- #income_from_sales_after_tax ⇒ Object
- #income_from_sales_before_tax ⇒ Object
-
#initialize(period, net_income_summary, comprehensive_income_summary, tax_rate = 0.35) ⇒ ReformulatedIncomeStatement
constructor
FIXME: clarify naming.
- #net_financing_income ⇒ Object
- #ni_over_sales ⇒ Object
- #oi_growth(prev) ⇒ Object
- #operating_income_after_tax ⇒ Object
- #operating_profit_margin ⇒ Object
- #re_oi(prev_bal_sheet, expected_rate_of_return) ⇒ Object
- #revenue_growth(prev) ⇒ Object
- #sales_over_noa(reformed_bal_sheet) ⇒ Object
- #sales_profit_margin ⇒ Object
Constructor Details
#initialize(period, net_income_summary, comprehensive_income_summary, tax_rate = 0.35) ⇒ ReformulatedIncomeStatement
FIXME: clarify naming. This is effective tax rate? marginal? statutory?
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 6 def initialize(period, net_income_summary, comprehensive_income_summary, tax_rate=0.35) # FIXME: clarify naming. This is effective tax rate? marginal? statutory? @period = period @tax_rate = tax_rate @operating_revenues = net_income_summary.filter_by_type(:or ) @cost_of_revenues = net_income_summary.filter_by_type(:cogs) @operating_expenses = net_income_summary.filter_by_type(:oe ) @oibt = net_income_summary.filter_by_type(:oibt ) @fibt = net_income_summary.filter_by_type(:fibt ) @tax = net_income_summary.filter_by_type(:tax ) @ooiat = net_income_summary.filter_by_type(:ooiat ) @ooiat_nci = net_income_summary.filter_by_type(:ooiat_nci) @fiat = net_income_summary.filter_by_type(:fiat ) # If there is a CI statement: # Strip O-NCI-OCI out of the NI calculation (***) # Double-check that the NI portion of the CI calculation matches (NI minus O-NCI-OCI) # Add OOCI + 1/2 of the UNKOCI in as an OOIAT # Add FOCI + 1/2 of the UNKOCI in as a FIAT if comprehensive_income_summary @ooiat.rows += comprehensive_income_summary.filter_by_type(:ooci).rows @ooiat.rows += comprehensive_income_summary.filter_by_type(:ooci_nci).rows @fiat.rows += comprehensive_income_summary.filter_by_type(:foci).rows comprehensive_income_summary.filter_by_type(:unkoci).rows.each do |row| row.vals = row.vals.map{ |val| val / 2.0 } @ooiat.rows << row @fiat.rows << row end end @fibt_tax_effect = (@fibt.total * @tax_rate).round.to_f @nfi = @fibt.total + -@fibt_tax_effect + @fiat.total @oibt_tax_effect = (@oibt.total * @tax_rate).round.to_f @gm = @operating_revenues.total + @cost_of_revenues.total @oisbt = @gm + @operating_expenses.total @oisat = @oisbt + @tax.total + @fibt_tax_effect + @oibt_tax_effect @oi = @oisat + @oibt.total - @oibt_tax_effect + @ooiat.total @ci = @nfi + @oi end |
Instance Attribute Details
#cost_of_revenues ⇒ Object
Returns the value of attribute cost_of_revenues.
4 5 6 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 4 def cost_of_revenues @cost_of_revenues end |
#operating_expenses ⇒ Object
Returns the value of attribute operating_expenses.
4 5 6 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 4 def @operating_expenses end |
#operating_revenues ⇒ Object
Returns the value of attribute operating_revenues.
4 5 6 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 4 def @operating_revenues end |
#period ⇒ Object
Returns the value of attribute period.
3 4 5 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 3 def period @period end |
Class Method Details
.empty_analysis ⇒ Object
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 159 def self.empty_analysis analysis = CalculationSummary.new analysis.title = "" analysis.rows = [] analysis.header_row = CalculationHeader.new(:key => "", :vals => ["Unknown..."]) analysis.rows << CalculationRow.new(:key => "Revenue ($MM)", :vals => [nil]) if Config.income_detail_enabled? analysis.rows << CalculationRow.new(:key => "COGS ($MM)", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "GM ($MM)", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "OE ($MM)", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "OISBT ($MM)", :vals => [nil]) end analysis.rows << CalculationRow.new(:key => "Core OI ($MM)", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "OI ($MM)", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "FI ($MM)", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "NI ($MM)", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "Gross Margin", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "Sales PM", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "Operating PM", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "FI / Sales", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "NI / Sales", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "Sales / NOA", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "FI / NFA", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "Revenue Growth", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "Core OI Growth", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "OI Growth", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "ReOI ($MM)", :vals => [nil]) return analysis end |
.forecast_next(period, policy, last_re_bs, last_re_is) ⇒ Object
239 240 241 242 243 244 245 246 247 248 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 239 def self.forecast_next(period, policy, last_re_bs, last_re_is) = policy.revenue_on(period.value["end_date"]) income_from_sales_after_tax = * policy.sales_pm_on(period.value["end_date"]) net_financing_income = last_re_bs.net_financial_assets.total * Ratio.new(policy.fi_over_nfa_on(period.value["end_date"])).yearly_to_quarterly comprehensive_income = income_from_sales_after_tax + net_financing_income ForecastedReformulatedIncomeStatement.new(period, , income_from_sales_after_tax, net_financing_income, comprehensive_income) end |
Instance Method Details
#-(ris2) ⇒ Object
51 52 53 54 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 51 def -(ris2) net_income_summary = NetIncomeSummaryFromDifferences.new(self, ris2) return ReformulatedIncomeStatement.new(@period, net_income_summary, nil, @tax_rate) end |
#analysis(re_bs, prev_re_is, prev_re_bs, expected_rate_of_return) ⇒ Object
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 192 def analysis(re_bs, prev_re_is, prev_re_bs, expected_rate_of_return) analysis = CalculationSummary.new analysis.title = "" analysis.rows = [] if re_bs.nil? analysis.header_row = CalculationHeader.new(:key => "", :vals => ["Unknown..."]) else analysis.header_row = CalculationHeader.new(:key => "", :vals => [re_bs.period.to_pretty_s]) end analysis.rows << CalculationRow.new(:key => "Revenue ($MM)", :vals => [@operating_revenues.total.to_nearest_million]) if Config.income_detail_enabled? analysis.rows << CalculationRow.new(:key => "COGS ($MM)", :vals => [@cost_of_revenues.total.to_nearest_million]) analysis.rows << CalculationRow.new(:key => "GM ($MM)", :vals => [@gm.to_nearest_million]) analysis.rows << CalculationRow.new(:key => "OE ($MM)", :vals => [@operating_expenses.total.to_nearest_million]) analysis.rows << CalculationRow.new(:key => "OISBT ($MM)", :vals => [income_from_sales_before_tax.total.to_nearest_million]) end analysis.rows << CalculationRow.new(:key => "Core OI ($MM)", :vals => [income_from_sales_after_tax.total.to_nearest_million]) analysis.rows << CalculationRow.new(:key => "OI ($MM)", :vals => [.total.to_nearest_million]) analysis.rows << CalculationRow.new(:key => "FI ($MM)", :vals => [net_financing_income.total.to_nearest_million]) analysis.rows << CalculationRow.new(:key => "NI ($MM)", :vals => [comprehensive_income.total.to_nearest_million]) analysis.rows << CalculationRow.new(:key => "Gross Margin", :vals => [gross_margin]) analysis.rows << CalculationRow.new(:key => "Sales PM", :vals => [sales_profit_margin]) analysis.rows << CalculationRow.new(:key => "Operating PM", :vals => []) analysis.rows << CalculationRow.new(:key => "FI / Sales", :vals => [fi_over_sales]) analysis.rows << CalculationRow.new(:key => "NI / Sales", :vals => [ni_over_sales]) if !prev_re_bs.nil? && !prev_re_is.nil? analysis.rows << CalculationRow.new(:key => "Sales / NOA", :vals => [sales_over_noa(prev_re_bs)]) analysis.rows << CalculationRow.new(:key => "FI / NFA", :vals => [fi_over_nfa( prev_re_bs)]) analysis.rows << CalculationRow.new(:key => "Revenue Growth",:vals => [revenue_growth(prev_re_is)]) analysis.rows << CalculationRow.new(:key => "Core OI Growth",:vals => [core_oi_growth(prev_re_is)]) analysis.rows << CalculationRow.new(:key => "OI Growth", :vals => [oi_growth( prev_re_is)]) analysis.rows << CalculationRow.new(:key => "ReOI ($MM)", :vals => [re_oi(prev_re_bs, expected_rate_of_return).to_nearest_million]) else analysis.rows << CalculationRow.new(:key => "Sales / NOA", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "FI / NFA", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "Revenue Growth",:vals => [nil]) analysis.rows << CalculationRow.new(:key => "Core OI Growth",:vals => [nil]) analysis.rows << CalculationRow.new(:key => "OI Growth", :vals => [nil]) analysis.rows << CalculationRow.new(:key => "ReOI ($MM)", :vals => [nil]) end return analysis end |
#comprehensive_income ⇒ Object
101 102 103 104 105 106 107 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 101 def comprehensive_income cs = FinModeling::CalculationSummary.new cs.title = "Comprehensive income (CI)" cs.rows = [ CalculationRow.new(:key => "Operating income, after tax (OI)", :vals => [@oi] ), CalculationRow.new(:key => "Net financing income, after tax (NFI)", :vals => [@nfi] ) ] return cs end |
#core_oi_growth(prev) ⇒ Object
144 145 146 147 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 144 def core_oi_growth(prev) rate = (income_from_sales_after_tax.total - prev.income_from_sales_after_tax.total) / prev.income_from_sales_after_tax.total return annualize_rate(prev, rate) end |
#fi_over_nfa(reformed_bal_sheet) ⇒ Object
134 135 136 137 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 134 def fi_over_nfa(reformed_bal_sheet) ratio = net_financing_income.total / reformed_bal_sheet.net_financial_assets.total Ratio.new(ratio).annualize(from_days=@period.days, to_days=365.0) end |
#fi_over_sales ⇒ Object
121 122 123 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 121 def fi_over_sales net_financing_income.total / .total end |
#gross_margin ⇒ Object
109 110 111 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 109 def gross_margin gross_revenue.total / .total end |
#gross_revenue ⇒ Object
56 57 58 59 60 61 62 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 56 def gross_revenue cs = FinModeling::CalculationSummary.new cs.title = "Gross Revenue" cs.rows = [ CalculationRow.new(:key => "Operating Revenues (OR)", :vals => [@operating_revenues.total] ), CalculationRow.new(:key => "Cost of Goods Sold (COGS)", :vals => [@cost_of_revenues.total] ) ] return cs end |
#income_from_sales_after_tax ⇒ Object
72 73 74 75 76 77 78 79 80 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 72 def income_from_sales_after_tax cs = FinModeling::CalculationSummary.new cs.title = "Operating Income from sales, after tax (OISAT)" cs.rows = [ CalculationRow.new(:key => "Operating income from sales (before tax)", :vals => [@oisbt] ), CalculationRow.new(:key => "Reported taxes", :vals => [@tax.total] ), CalculationRow.new(:key => "Taxes on net financing income", :vals => [@fibt_tax_effect] ), CalculationRow.new(:key => "Taxes on other operating income", :vals => [@oibt_tax_effect] ) ] return cs end |
#income_from_sales_before_tax ⇒ Object
64 65 66 67 68 69 70 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 64 def income_from_sales_before_tax cs = FinModeling::CalculationSummary.new cs.title = "Operating Income from sales, before tax (OISBT)" cs.rows = [ CalculationRow.new(:key => "Gross Margin (GM)", :vals => [@gm] ), CalculationRow.new(:key => "Operating Expense (OE)", :vals => [@operating_expenses.total] ) ] return cs end |
#net_financing_income ⇒ Object
92 93 94 95 96 97 98 99 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 92 def net_financing_income cs = FinModeling::CalculationSummary.new cs.title = "Net financing income, after tax (NFI)" cs.rows = [ CalculationRow.new(:key => "Financing income, before tax (FIBT)", :vals => [@fibt.total] ), CalculationRow.new(:key => "Tax effect (FIBT_TAX_EFFECT)", :vals => [-@fibt_tax_effect] ), CalculationRow.new(:key => "Financing income, after tax (FIAT)", :vals => [@fiat.total] ) ] return cs end |
#ni_over_sales ⇒ Object
125 126 127 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 125 def ni_over_sales comprehensive_income.total / .total end |
#oi_growth(prev) ⇒ Object
149 150 151 152 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 149 def oi_growth(prev) rate = (.total - prev..total) / prev..total return annualize_rate(prev, rate) end |
#operating_income_after_tax ⇒ Object
82 83 84 85 86 87 88 89 90 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 82 def cs = FinModeling::CalculationSummary.new cs.title = "Operating income, after tax (OI)" cs.rows = [ CalculationRow.new(:key => "Operating income after sales, after tax (OISAT)", :vals => [@oisat] ), CalculationRow.new(:key => "Other operating income, before tax (OIBT)", :vals => [@oibt.total] ), CalculationRow.new(:key => "Tax on other operating income", :vals => [-@oibt_tax_effect] ), CalculationRow.new(:key => "Other operating income, after tax (OOIAT)", :vals => [@ooiat.total] ) ] return cs end |
#operating_profit_margin ⇒ Object
117 118 119 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 117 def .total / .total end |
#re_oi(prev_bal_sheet, expected_rate_of_return) ⇒ Object
154 155 156 157 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 154 def re_oi(prev_bal_sheet, expected_rate_of_return) e_ror = deannualize_rate(prev_bal_sheet, expected_rate_of_return) return (.total - (e_ror * prev_bal_sheet..total)) end |
#revenue_growth(prev) ⇒ Object
139 140 141 142 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 139 def revenue_growth(prev) rate = (.total - prev..total) / prev..total return annualize_rate(prev, rate) end |
#sales_over_noa(reformed_bal_sheet) ⇒ Object
129 130 131 132 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 129 def sales_over_noa(reformed_bal_sheet) ratio = .total / reformed_bal_sheet..total Ratio.new(ratio).annualize(from_days=@period.days, to_days=365.0) end |
#sales_profit_margin ⇒ Object
113 114 115 |
# File 'lib/finmodeling/reformulated_income_statement.rb', line 113 def sales_profit_margin income_from_sales_after_tax.total / .total end |