finmodeling 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. data/.gitignore +3 -0
  2. data/Gemfile +10 -0
  3. data/README.md +292 -0
  4. data/Rakefile +6 -0
  5. data/TODO.txt +36 -0
  6. data/examples/dump_report.rb +33 -0
  7. data/examples/lists/nasdaq-mid-to-mega-tech-symbols.txt +226 -0
  8. data/examples/show_report.rb +218 -0
  9. data/examples/show_reports.rb +77 -0
  10. data/finmodeling.gemspec +31 -0
  11. data/lib/finmodeling/annual_report_filing.rb +104 -0
  12. data/lib/finmodeling/array_with_stats.rb +22 -0
  13. data/lib/finmodeling/assets_calculation.rb +36 -0
  14. data/lib/finmodeling/assets_item.rb +14 -0
  15. data/lib/finmodeling/assets_item_vectors.rb +638 -0
  16. data/lib/finmodeling/balance_sheet_analyses.rb +33 -0
  17. data/lib/finmodeling/balance_sheet_calculation.rb +68 -0
  18. data/lib/finmodeling/calculation_summary.rb +148 -0
  19. data/lib/finmodeling/can_cache_classifications.rb +36 -0
  20. data/lib/finmodeling/can_cache_summaries.rb +16 -0
  21. data/lib/finmodeling/can_classify_rows.rb +54 -0
  22. data/lib/finmodeling/cash_change_calculation.rb +67 -0
  23. data/lib/finmodeling/cash_change_item.rb +14 -0
  24. data/lib/finmodeling/cash_change_item_vectors.rb +241 -0
  25. data/lib/finmodeling/cash_flow_statement_calculation.rb +85 -0
  26. data/lib/finmodeling/classifiers.rb +11 -0
  27. data/lib/finmodeling/company.rb +102 -0
  28. data/lib/finmodeling/company_filing.rb +64 -0
  29. data/lib/finmodeling/company_filing_calculation.rb +75 -0
  30. data/lib/finmodeling/company_filings.rb +100 -0
  31. data/lib/finmodeling/config.rb +37 -0
  32. data/lib/finmodeling/constant_forecasting_policy.rb +23 -0
  33. data/lib/finmodeling/factory.rb +27 -0
  34. data/lib/finmodeling/float_helpers.rb +17 -0
  35. data/lib/finmodeling/forecasts.rb +48 -0
  36. data/lib/finmodeling/generic_forecasting_policy.rb +19 -0
  37. data/lib/finmodeling/has_string_classifer.rb +96 -0
  38. data/lib/finmodeling/income_statement_analyses.rb +74 -0
  39. data/lib/finmodeling/income_statement_calculation.rb +71 -0
  40. data/lib/finmodeling/income_statement_item.rb +14 -0
  41. data/lib/finmodeling/income_statement_item_vectors.rb +654 -0
  42. data/lib/finmodeling/liabs_and_equity_calculation.rb +36 -0
  43. data/lib/finmodeling/liabs_and_equity_item.rb +14 -0
  44. data/lib/finmodeling/liabs_and_equity_item_vectors.rb +1936 -0
  45. data/lib/finmodeling/net_income_calculation.rb +41 -0
  46. data/lib/finmodeling/paths.rb +5 -0
  47. data/lib/finmodeling/period_array.rb +24 -0
  48. data/lib/finmodeling/quarterly_report_filing.rb +23 -0
  49. data/lib/finmodeling/rate.rb +20 -0
  50. data/lib/finmodeling/ratio.rb +20 -0
  51. data/lib/finmodeling/reformulated_balance_sheet.rb +176 -0
  52. data/lib/finmodeling/reformulated_cash_flow_statement.rb +140 -0
  53. data/lib/finmodeling/reformulated_income_statement.rb +436 -0
  54. data/lib/finmodeling/string_helpers.rb +26 -0
  55. data/lib/finmodeling/version.rb +3 -0
  56. data/lib/finmodeling.rb +70 -0
  57. data/spec/annual_report_filing_spec.rb +68 -0
  58. data/spec/assets_calculation_spec.rb +21 -0
  59. data/spec/assets_item_spec.rb +66 -0
  60. data/spec/balance_sheet_analyses_spec.rb +43 -0
  61. data/spec/balance_sheet_calculation_spec.rb +91 -0
  62. data/spec/calculation_summary_spec.rb +63 -0
  63. data/spec/can_classify_rows_spec.rb +86 -0
  64. data/spec/cash_change_calculation_spec.rb +56 -0
  65. data/spec/cash_change_item_spec.rb +66 -0
  66. data/spec/cash_flow_statement_calculation_spec.rb +108 -0
  67. data/spec/company_filing_calculation_spec.rb +74 -0
  68. data/spec/company_filing_spec.rb +30 -0
  69. data/spec/company_filings_spec.rb +55 -0
  70. data/spec/company_spec.rb +73 -0
  71. data/spec/constant_forecasting_policy_spec.rb +37 -0
  72. data/spec/factory_spec.rb +18 -0
  73. data/spec/forecasts_spec.rb +21 -0
  74. data/spec/generic_forecasting_policy_spec.rb +33 -0
  75. data/spec/income_statement_analyses_spec.rb +63 -0
  76. data/spec/income_statement_calculation_spec.rb +88 -0
  77. data/spec/income_statement_item_spec.rb +86 -0
  78. data/spec/liabs_and_equity_calculation_spec.rb +20 -0
  79. data/spec/liabs_and_equity_item_spec.rb +66 -0
  80. data/spec/mocks/calculation.rb +10 -0
  81. data/spec/mocks/income_statement_analyses.rb +93 -0
  82. data/spec/mocks/sec_query.rb +31 -0
  83. data/spec/net_income_calculation_spec.rb +23 -0
  84. data/spec/period_array.rb +52 -0
  85. data/spec/quarterly_report_filing_spec.rb +69 -0
  86. data/spec/rate_spec.rb +33 -0
  87. data/spec/ratio_spec.rb +33 -0
  88. data/spec/reformulated_balance_sheet_spec.rb +146 -0
  89. data/spec/reformulated_cash_flow_statement_spec.rb +174 -0
  90. data/spec/reformulated_income_statement_spec.rb +293 -0
  91. data/spec/spec_helper.rb +5 -0
  92. data/spec/string_helpers_spec.rb +23 -0
  93. data/tools/create_balance_sheet_training_vectors.rb +65 -0
  94. data/tools/create_cash_change_training_vectors.rb +48 -0
  95. data/tools/create_credit_debit_training_vectors.rb +51 -0
  96. data/tools/create_income_statement_training_vectors.rb +48 -0
  97. metadata +289 -0
@@ -0,0 +1,41 @@
1
+ module FinModeling
2
+ class NetIncomeCalculation < CompanyFilingCalculation
3
+ include CanCacheClassifications
4
+ include CanCacheSummaries
5
+ include CanClassifyRows
6
+
7
+ BASE_FILENAME = File.join(FinModeling::BASE_PATH, "summaries/net_income_")
8
+
9
+ ALL_STATES = [ :or, :cogs, :oe, :oibt, :fibt, :tax, :ooiat, :fiat ]
10
+ NEXT_STATES = { nil => [ :or, :cogs, :oe, :oibt, :fibt, :tax, :ooiat, :fiat ],
11
+ :or => [ :or, :cogs, :oe, :oibt, :fibt, :tax, :ooiat, :fiat ],
12
+ :cogs => [ :cogs, :oe, :oibt, :fibt, :tax, :ooiat, :fiat ],
13
+ :oe => [ :oe, :oibt, :fibt, :tax, :ooiat, :fiat ],
14
+ :oibt => [ :oibt, :fibt, :tax, :ooiat, :fiat ], # obit/fibt can cycle back/forth
15
+ :fibt => [ :obit, :fibt, :tax, :ooiat, :fiat ], # obit/fibt can cycle back/forth
16
+ :tax => [ :ooiat, :fiat ], # tax can't go to itself. only 1 such item.
17
+ :ooiat => [ :ooiat, :fiat ], # ooiat/fiat can cycle back/forth
18
+ :fiat => [ :ooiat, :fiat ] }# ooiat/fiat can cycle back/forth
19
+
20
+ def summary(args)
21
+ summary_cache_key = args[:period].to_pretty_s
22
+ thesummary = lookup_cached_summary(summary_cache_key)
23
+ return thesummary if !thesummary.nil?
24
+
25
+ mapping = Xbrlware::ValueMapping.new
26
+ mapping.policy[:debit] = :flip
27
+
28
+ thesummary = super(:period => args[:period], :mapping => mapping) # FIXME: flip_total should == true!
29
+ if !lookup_cached_classifications(BASE_FILENAME, thesummary.rows)
30
+ lookahead = [4, thesummary.rows.length-1].min
31
+ classify_rows(ALL_STATES, NEXT_STATES, thesummary.rows, FinModeling::IncomeStatementItem, lookahead)
32
+ save_cached_classifications(BASE_FILENAME, thesummary.rows)
33
+ end
34
+
35
+ save_cached_summary(summary_cache_key, thesummary)
36
+
37
+ return thesummary
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,5 @@
1
+ module FinModeling
2
+
3
+ BASE_PATH = File.expand_path("~/.finmodeling")
4
+
5
+ end
@@ -0,0 +1,24 @@
1
+ module FinModeling
2
+ class PeriodArray < Array
3
+ def quarterly
4
+ PeriodArray.new(self.select{ |x| (Xbrlware::DateUtil.days_between(x.value["end_date"], x.value["start_date"]) >= 2*28) &&
5
+ (Xbrlware::DateUtil.days_between(x.value["end_date"], x.value["start_date"]) <= 4*31) })
6
+ end
7
+
8
+ def halfyearly
9
+ PeriodArray.new(self.select{ |x| (Xbrlware::DateUtil.days_between(x.value["end_date"], x.value["start_date"]) >= 5*30) &&
10
+ (Xbrlware::DateUtil.days_between(x.value["end_date"], x.value["start_date"]) <= 7*31) })
11
+ end
12
+
13
+ def threequarterly
14
+ PeriodArray.new(self.select{ |x| (Xbrlware::DateUtil.days_between(x.value["end_date"], x.value["start_date"]) >= 8*30) &&
15
+ (Xbrlware::DateUtil.days_between(x.value["end_date"], x.value["start_date"]) <= 10*31) })
16
+ end
17
+
18
+ def yearly
19
+ PeriodArray.new(self.select{ |x| (Xbrlware::DateUtil.days_between(x.value["end_date"], x.value["start_date"]) >= 11*30) &&
20
+ (Xbrlware::DateUtil.days_between(x.value["end_date"], x.value["start_date"]) <= 13*31) })
21
+ end
22
+ end
23
+ end
24
+
@@ -0,0 +1,23 @@
1
+ module FinModeling
2
+ class QuarterlyReportFiling < AnnualReportFiling
3
+
4
+ def write_constructor(file, item_name)
5
+ balance_sheet.write_constructor( file, bs_name = item_name + "_bs")
6
+ income_statement.write_constructor( file, is_name = item_name + "_is")
7
+ cash_flow_statement.write_constructor(file, cfs_name = item_name + "_cfs")
8
+
9
+ names_of_discs = []
10
+ disclosures.each_with_index do |disclosure, idx|
11
+ name_of_disc = item_name + "_disc#{idx}"
12
+ disclosure.write_constructor(file, name_of_disc)
13
+ names_of_discs << name_of_disc
14
+ end
15
+ names_of_discs_str = "[" + names_of_discs.join(',') + "]"
16
+
17
+ file.puts "#{SCHEMA_VERSION_ITEM} = #{CURRENT_SCHEMA_VERSION}"
18
+
19
+ file.puts "#{item_name} = FinModeling::CachedQuarterlyFiling.new(#{bs_name}, #{is_name}, #{cfs_name}, #{names_of_discs_str})"
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ module FinModeling
2
+ class Rate
3
+ def initialize(value)
4
+ @value = value
5
+ end
6
+
7
+ def annualize(from_days=365, to_days=365)
8
+ ((1.0 + @value)**(to_days.to_f/from_days.to_f)) - 1.0
9
+ end
10
+
11
+ def yearly_to_quarterly
12
+ annualize(from_days=365.0, to_days=365.0/4.0)
13
+ end
14
+
15
+ def quarterly_to_yearly
16
+ annualize(from_days=365.0/4.0, to_days=365.0)
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,20 @@
1
+ module FinModeling
2
+ class Ratio
3
+ def initialize(value)
4
+ @value = value
5
+ end
6
+
7
+ def annualize(from_days=365, to_days=365)
8
+ @value*(to_days.to_f/from_days.to_f)
9
+ end
10
+
11
+ def yearly_to_quarterly
12
+ annualize(from_days=365.0, to_days=365.0/4.0)
13
+ end
14
+
15
+ def quarterly_to_yearly
16
+ annualize(from_days=365.0/4.0, to_days=365.0)
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,176 @@
1
+ module FinModeling
2
+ class ReformulatedBalanceSheet
3
+ attr_accessor :period
4
+
5
+ def initialize(period, assets_summary, liabs_and_equity_summary)
6
+ @period = period
7
+ @oa = assets_summary.filter_by_type(:oa)
8
+ @fa = assets_summary.filter_by_type(:fa)
9
+ @ol = liabs_and_equity_summary.filter_by_type(:ol)
10
+ @fl = liabs_and_equity_summary.filter_by_type(:fl)
11
+ @cse = liabs_and_equity_summary.filter_by_type(:cse)
12
+ end
13
+
14
+ def operating_assets
15
+ @oa
16
+ end
17
+
18
+ def financial_assets
19
+ @fa
20
+ end
21
+
22
+ def operating_liabilities
23
+ @ol
24
+ end
25
+
26
+ def financial_liabilities
27
+ @fl
28
+ end
29
+
30
+ def net_operating_assets
31
+ cs = FinModeling::CalculationSummary.new
32
+ cs.title = "Net Operational Assets"
33
+ cs.rows = [ CalculationRow.new( :key => "OA", :vals => [ @oa.total ] ),
34
+ CalculationRow.new( :key => "OL", :vals => [ -@ol.total ] ) ]
35
+ return cs
36
+ end
37
+
38
+ def net_financial_assets
39
+ cs = FinModeling::CalculationSummary.new
40
+ cs.title = "Net Financial Assets"
41
+ cs.rows = [ CalculationRow.new( :key => "FA", :vals => [ @fa.total ] ),
42
+ CalculationRow.new( :key => "FL", :vals => [ -@fl.total ] ) ]
43
+ return cs
44
+ end
45
+
46
+ def common_shareholders_equity
47
+ cs = FinModeling::CalculationSummary.new
48
+ cs.title = "Common Shareholders' Equity"
49
+ cs.rows = [ CalculationRow.new( :key => "NOA", :vals => [ net_operating_assets.total ] ),
50
+ CalculationRow.new( :key => "NFA", :vals => [ net_financial_assets.total ] ) ]
51
+ return cs
52
+ end
53
+
54
+ def composition_ratio
55
+ net_operating_assets.total / net_financial_assets.total
56
+ end
57
+
58
+ def noa_growth(prev)
59
+ rate = (net_operating_assets.total - prev.net_operating_assets.total) / prev.net_operating_assets.total
60
+ return annualize_rate(prev, rate)
61
+ end
62
+
63
+ def cse_growth(prev)
64
+ rate = (common_shareholders_equity.total - prev.common_shareholders_equity.total) / prev.common_shareholders_equity.total
65
+ return annualize_rate(prev, rate)
66
+ end
67
+
68
+ def analysis(prev)
69
+ analysis = CalculationSummary.new
70
+
71
+ analysis.title = ""
72
+ analysis.header_row = CalculationHeader.new(:key => "", :vals => [@period.to_pretty_s])
73
+
74
+ analysis.rows = []
75
+ if Config.balance_detail_enabled?
76
+ analysis.rows << CalculationRow.new(:key => "A ($MM)",:vals => [@oa.total.to_nearest_million +
77
+ @fa.total.to_nearest_million])
78
+ analysis.rows << CalculationRow.new(:key => "L ($MM)",:vals => [@ol.total.to_nearest_million +
79
+ @fl.total.to_nearest_million])
80
+ end
81
+ analysis.rows << CalculationRow.new(:key => "NOA ($MM)", :vals => [net_operating_assets.total.to_nearest_million])
82
+ if Config.balance_detail_enabled?
83
+ analysis.rows << CalculationRow.new(:key => "OA ($MM)",:vals => [operating_assets.total.to_nearest_million])
84
+ analysis.rows << CalculationRow.new(:key => "OL ($MM)",:vals => [operating_liabilities.total.to_nearest_million])
85
+ end
86
+ analysis.rows << CalculationRow.new(:key => "NFA ($MM)", :vals => [net_financial_assets.total.to_nearest_million])
87
+ if Config.balance_detail_enabled?
88
+ analysis.rows << CalculationRow.new(:key => "FA ($MM)",:vals => [financial_assets.total.to_nearest_million])
89
+ analysis.rows << CalculationRow.new(:key => "FL ($MM)",:vals => [financial_liabilities.total.to_nearest_million])
90
+ end
91
+ analysis.rows << CalculationRow.new(:key => "CSE ($MM)", :vals => [common_shareholders_equity.total.to_nearest_million])
92
+ analysis.rows << CalculationRow.new(:key => "Composition Ratio", :vals => [composition_ratio] )
93
+ if prev.nil?
94
+ analysis.rows << CalculationRow.new(:key => "NOA Growth", :vals => [nil] )
95
+ analysis.rows << CalculationRow.new(:key => "CSE Growth", :vals => [nil] )
96
+ else
97
+ analysis.rows << CalculationRow.new(:key => "NOA Growth", :vals => [noa_growth(prev)] )
98
+ analysis.rows << CalculationRow.new(:key => "CSE Growth", :vals => [cse_growth(prev)] )
99
+ end
100
+
101
+ return analysis
102
+ end
103
+
104
+ def self.forecast_next(period, policy, last_re_bs, next_re_is)
105
+ noa = next_re_is.operating_revenues.total / Ratio.new(policy.sales_over_noa).yearly_to_quarterly
106
+ cse = last_re_bs.common_shareholders_equity.total + next_re_is.comprehensive_income.total
107
+ nfa = cse - noa
108
+
109
+ ForecastedReformulatedBalanceSheet.new(period, noa, nfa, cse)
110
+ end
111
+
112
+ private
113
+
114
+ def annualize_rate(prev, rate)
115
+ from_days = Xbrlware::DateUtil.days_between(prev.period.value, @period.value)
116
+ return Rate.new(rate).annualize(from_days, to_days=365)
117
+ end
118
+
119
+ def deannualize_rate(prev, rate)
120
+ to_days = Xbrlware::DateUtil.days_between(prev.period.value, @period.value)
121
+ return Rate.new(rate).annualize(from_days=365, to_days)
122
+ end
123
+ end
124
+
125
+ class ForecastedReformulatedBalanceSheet < ReformulatedBalanceSheet
126
+ def initialize(period, noa, nfa, cse)
127
+ @period = period
128
+ @noa = noa
129
+ @nfa = nfa
130
+ @cse = cse
131
+ end
132
+
133
+ def operating_assets
134
+ nil
135
+ end
136
+
137
+ def financial_assets
138
+ nil
139
+ end
140
+
141
+ def operating_liabilities
142
+ nil
143
+ end
144
+
145
+ def financial_liabilities
146
+ nil
147
+ end
148
+
149
+ def net_operating_assets
150
+ cs = FinModeling::CalculationSummary.new
151
+ cs.title = "Net Operational Assets"
152
+ cs.rows = [ CalculationRow.new( :key => "NOA", :vals => [@noa] ) ]
153
+ return cs
154
+ end
155
+
156
+ def net_financial_assets
157
+ cs = FinModeling::CalculationSummary.new
158
+ cs.title = "Net Financial Assets"
159
+ cs.rows = [ CalculationRow.new( :key => "NFA", :vals => [@nfa] ) ]
160
+ return cs
161
+ end
162
+
163
+ def common_shareholders_equity
164
+ cs = FinModeling::CalculationSummary.new
165
+ cs.title = "Common Shareholders' Equity"
166
+ cs.rows = [ CalculationRow.new( :key => "CSE", :vals => [@cse] ) ]
167
+ return cs
168
+ end
169
+
170
+ def analysis(prev)
171
+ analysis = super(prev)
172
+ analysis.header_row.vals[0] += "E" # for estimated
173
+ return analysis
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,140 @@
1
+ module FinModeling
2
+ class ReformulatedCashFlowStatement
3
+ attr_accessor :period
4
+
5
+ class FakeCashChangeSummary
6
+ def initialize(re_cfs1, re_cfs2)
7
+ @re_cfs1 = re_cfs1
8
+ @re_cfs2 = re_cfs2
9
+ end
10
+ def filter_by_type(key)
11
+ case key
12
+ when :c
13
+ @cs = FinModeling::CalculationSummary.new
14
+ @cs.title = "Cash from Operations"
15
+ @cs.rows = [ CalculationRow.new(:key => "First Row", :vals => [ @re_cfs1.cash_from_operations.total] ),
16
+ CalculationRow.new(:key => "Second Row", :vals => [-@re_cfs2.cash_from_operations.total] ) ]
17
+ return @cs
18
+ when :i
19
+ @cs = FinModeling::CalculationSummary.new
20
+ @cs.title = "Cash Investments in Operations"
21
+ @cs.rows = [ CalculationRow.new(:key => "First Row", :vals => [ @re_cfs1.cash_investments_in_operations.total] ),
22
+ CalculationRow.new(:key => "Second Row", :vals => [-@re_cfs2.cash_investments_in_operations.total] ) ]
23
+ return @cs
24
+ when :d
25
+ @cs = FinModeling::CalculationSummary.new
26
+ @cs.title = "Payments to Debtholders"
27
+ @cs.rows = [ CalculationRow.new(:key => "First Row", :vals => [ @re_cfs1.payments_to_debtholders.total] ),
28
+ CalculationRow.new(:key => "Second Row", :vals => [-@re_cfs2.payments_to_debtholders.total] ) ]
29
+ return @cs
30
+ when :f
31
+ @cs = FinModeling::CalculationSummary.new
32
+ @cs.title = "Payments to Stockholders"
33
+ @cs.rows = [ CalculationRow.new(:key => "First Row", :vals => [ @re_cfs1.payments_to_stockholders.total] ),
34
+ CalculationRow.new(:key => "Second Row", :vals => [-@re_cfs2.payments_to_stockholders.total] ) ]
35
+ return @cs
36
+ end
37
+ end
38
+ end
39
+
40
+ def initialize(period, cash_change_summary)
41
+ @period = period
42
+
43
+ @c = cash_change_summary.filter_by_type(:c) # just make this a member....
44
+ @i = cash_change_summary.filter_by_type(:i)
45
+ @d = cash_change_summary.filter_by_type(:d)
46
+ @f = cash_change_summary.filter_by_type(:f)
47
+
48
+ @c.title = "Cash from operations"
49
+ @i.title = "Cash investments in operations"
50
+ @d.title = "Payments to debtholders"
51
+ @f.title = "Payments to stockholders"
52
+
53
+ if cash_change_summary.class != FakeCashChangeSummary
54
+ @d.rows << CalculationRow.new(:key => "Investment in Cash and Equivalents",
55
+ :type => :d,
56
+ :vals => [-cash_change_summary.total])
57
+ end
58
+ end
59
+
60
+ def -(re_cfs2)
61
+ summary = FakeCashChangeSummary.new(self, re_cfs2)
62
+ return ReformulatedCashFlowStatement.new(@period, summary)
63
+ end
64
+
65
+ def cash_from_operations
66
+ @c
67
+ end
68
+
69
+ def cash_investments_in_operations
70
+ @i
71
+ end
72
+
73
+ def payments_to_debtholders
74
+ @d
75
+ end
76
+
77
+ def payments_to_stockholders
78
+ @f
79
+ end
80
+
81
+ def free_cash_flow
82
+ cs = FinModeling::CalculationSummary.new
83
+ cs.title = "Free Cash Flow"
84
+ cs.rows = [ CalculationRow.new(:key => "Cash from Operations (C)", :vals => [@c.total] ),
85
+ CalculationRow.new(:key => "Cash Investment in Operations (I)", :vals => [@i.total] ) ]
86
+ return cs
87
+ end
88
+
89
+ def financing_flows
90
+ cs = FinModeling::CalculationSummary.new
91
+ cs.title = "Financing Flows"
92
+ cs.rows = [ CalculationRow.new(:key => "Payments to debtholders (d)", :vals => [@d.total] ),
93
+ CalculationRow.new(:key => "Payments to stockholders (F)", :vals => [@f.total] ) ]
94
+ return cs
95
+ end
96
+
97
+ def ni_over_c(inc_stmt)
98
+ inc_stmt.comprehensive_income.total.to_f / cash_from_operations.total
99
+ end
100
+
101
+ def self.empty_analysis
102
+ analysis = CalculationSummary.new
103
+
104
+ analysis.title = ""
105
+ analysis.header_row = CalculationHeader.new(:key => "", :vals => ["Unknown..."])
106
+
107
+ analysis.rows = []
108
+ analysis.rows << CalculationRow.new(:key => "C ($MM)", :vals => [nil])
109
+ analysis.rows << CalculationRow.new(:key => "I ($MM)", :vals => [nil])
110
+ analysis.rows << CalculationRow.new(:key => "d ($MM)", :vals => [nil])
111
+ analysis.rows << CalculationRow.new(:key => "F ($MM)", :vals => [nil])
112
+ analysis.rows << CalculationRow.new(:key => "FCF ($MM)", :vals => [nil])
113
+ analysis.rows << CalculationRow.new(:key => "NI / C", :vals => [nil])
114
+
115
+ return analysis
116
+ end
117
+
118
+ def analysis(inc_stmt)
119
+ analysis = CalculationSummary.new
120
+
121
+ analysis.title = ""
122
+ analysis.header_row = CalculationHeader.new(:key => "", :vals => [@period.value["end_date"].to_s])
123
+
124
+ analysis.rows = []
125
+ analysis.rows << CalculationRow.new(:key => "C ($MM)", :vals => [cash_from_operations.total.to_nearest_million])
126
+ analysis.rows << CalculationRow.new(:key => "I ($MM)", :vals => [cash_investments_in_operations.total.to_nearest_million])
127
+ analysis.rows << CalculationRow.new(:key => "d ($MM)", :vals => [payments_to_debtholders.total.to_nearest_million])
128
+ analysis.rows << CalculationRow.new(:key => "F ($MM)", :vals => [payments_to_stockholders.total.to_nearest_million])
129
+ analysis.rows << CalculationRow.new(:key => "FCF ($MM)", :vals => [free_cash_flow.total.to_nearest_million])
130
+ if inc_stmt
131
+ analysis.rows << CalculationRow.new(:key => "NI / C", :vals => [ni_over_c(inc_stmt)])
132
+ else
133
+ analysis.rows << CalculationRow.new(:key => "NI / C", :vals => [nil])
134
+ end
135
+
136
+ return analysis
137
+ end
138
+
139
+ end
140
+ end