finmodeling 0.1 → 0.2

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 (135) hide show
  1. data/.gitignore +0 -0
  2. data/Gemfile +2 -0
  3. data/README.md +289 -269
  4. data/Rakefile +12 -0
  5. data/TODO.txt +113 -20
  6. data/examples/{dump_report.rb → dump_latest_10k.rb} +1 -1
  7. data/examples/list_disclosures.rb +50 -0
  8. data/examples/lists/nasdaq-mid-to-mega-tech-symbols.txt +0 -0
  9. data/examples/show_report.rb +112 -32
  10. data/examples/show_reports.rb +162 -33
  11. data/finmodeling.gemspec +4 -1
  12. data/lib/finmodeling/annual_report_filing.rb +97 -18
  13. data/lib/finmodeling/array_with_stats.rb +0 -0
  14. data/lib/finmodeling/assets_calculation.rb +12 -3
  15. data/lib/finmodeling/assets_item.rb +0 -0
  16. data/lib/finmodeling/assets_item_vectors.rb +0 -0
  17. data/lib/finmodeling/balance_sheet_analyses.rb +19 -4
  18. data/lib/finmodeling/balance_sheet_calculation.rb +52 -37
  19. data/lib/finmodeling/calculation_summary.rb +119 -14
  20. data/lib/finmodeling/can_cache_classifications.rb +0 -0
  21. data/lib/finmodeling/can_cache_summaries.rb +0 -0
  22. data/lib/finmodeling/can_choose_successive_periods.rb +15 -0
  23. data/lib/finmodeling/can_classify_rows.rb +0 -0
  24. data/lib/finmodeling/capm.rb +80 -0
  25. data/lib/finmodeling/cash_change_calculation.rb +3 -3
  26. data/lib/finmodeling/cash_change_item.rb +0 -0
  27. data/lib/finmodeling/cash_change_item_vectors.rb +0 -0
  28. data/lib/finmodeling/cash_change_summary_from_differences.rb +36 -0
  29. data/lib/finmodeling/cash_flow_statement_analyses.rb +36 -0
  30. data/lib/finmodeling/cash_flow_statement_calculation.rb +28 -52
  31. data/lib/finmodeling/classifiers.rb +2 -0
  32. data/lib/finmodeling/company.rb +0 -0
  33. data/lib/finmodeling/company_filing.rb +30 -7
  34. data/lib/finmodeling/company_filing_calculation.rb +16 -6
  35. data/lib/finmodeling/company_filings.rb +112 -46
  36. data/lib/finmodeling/comprehensive_income_calculation.rb +60 -0
  37. data/lib/finmodeling/comprehensive_income_statement_calculation.rb +74 -0
  38. data/lib/finmodeling/comprehensive_income_statement_item.rb +20 -0
  39. data/lib/finmodeling/comprehensive_income_statement_item_vectors.rb +235 -0
  40. data/lib/finmodeling/config.rb +0 -0
  41. data/lib/finmodeling/debt_cost_of_capital.rb +14 -0
  42. data/lib/finmodeling/equity_change_calculation.rb +43 -0
  43. data/lib/finmodeling/equity_change_item.rb +25 -0
  44. data/lib/finmodeling/equity_change_item_vectors.rb +156 -0
  45. data/lib/finmodeling/factory.rb +0 -0
  46. data/lib/finmodeling/fama_french_cost_of_equity.rb +119 -0
  47. data/lib/finmodeling/float_helpers.rb +14 -8
  48. data/lib/finmodeling/forecasted_reformulated_balance_sheet.rb +55 -0
  49. data/lib/finmodeling/forecasted_reformulated_income_statement.rb +110 -0
  50. data/lib/finmodeling/forecasts.rb +4 -4
  51. data/lib/finmodeling/has_string_classifer.rb +0 -0
  52. data/lib/finmodeling/income_statement_analyses.rb +23 -17
  53. data/lib/finmodeling/income_statement_calculation.rb +46 -43
  54. data/lib/finmodeling/income_statement_item.rb +1 -1
  55. data/lib/finmodeling/income_statement_item_vectors.rb +24 -13
  56. data/lib/finmodeling/invalid_filing_error.rb +4 -0
  57. data/lib/finmodeling/liabs_and_equity_calculation.rb +18 -8
  58. data/lib/finmodeling/liabs_and_equity_item.rb +1 -1
  59. data/lib/finmodeling/liabs_and_equity_item_vectors.rb +24 -24
  60. data/lib/finmodeling/linear_trend_forecasting_policy.rb +23 -0
  61. data/lib/finmodeling/net_income_calculation.rb +23 -10
  62. data/lib/finmodeling/net_income_summary_from_differences.rb +51 -0
  63. data/lib/finmodeling/paths.rb +0 -0
  64. data/lib/finmodeling/period_array.rb +8 -4
  65. data/lib/finmodeling/quarterly_report_filing.rb +9 -4
  66. data/lib/finmodeling/rate.rb +8 -0
  67. data/lib/finmodeling/ratio.rb +0 -0
  68. data/lib/finmodeling/reformulated_balance_sheet.rb +47 -88
  69. data/lib/finmodeling/reformulated_cash_flow_statement.rb +18 -41
  70. data/lib/finmodeling/reformulated_income_statement.rb +44 -206
  71. data/lib/finmodeling/reformulated_shareholder_equity_statement.rb +50 -0
  72. data/lib/finmodeling/reoi_valuation.rb +104 -0
  73. data/lib/finmodeling/shareholder_equity_statement_calculation.rb +34 -0
  74. data/lib/finmodeling/string_helpers.rb +18 -1
  75. data/lib/finmodeling/time_series_estimator.rb +25 -0
  76. data/lib/finmodeling/trailing_avg_forecasting_policy.rb +23 -0
  77. data/lib/finmodeling/version.rb +1 -1
  78. data/lib/finmodeling/weighted_avg_cost_of_capital.rb +35 -0
  79. data/lib/finmodeling/yahoo_finance_helpers.rb +20 -0
  80. data/lib/finmodeling.rb +33 -2
  81. data/spec/annual_report_filing_spec.rb +81 -45
  82. data/spec/assets_calculation_spec.rb +7 -4
  83. data/spec/assets_item_spec.rb +9 -14
  84. data/spec/balance_sheet_analyses_spec.rb +13 -13
  85. data/spec/balance_sheet_calculation_spec.rb +45 -51
  86. data/spec/calculation_summary_spec.rb +113 -21
  87. data/spec/can_classify_rows_spec.rb +0 -0
  88. data/spec/cash_change_calculation_spec.rb +1 -10
  89. data/spec/cash_change_item_spec.rb +10 -18
  90. data/spec/cash_flow_statement_calculation_spec.rb +10 -24
  91. data/spec/company_beta_spec.rb +53 -0
  92. data/spec/company_filing_calculation_spec.rb +39 -49
  93. data/spec/company_filing_spec.rb +0 -0
  94. data/spec/company_filings_spec.rb +75 -25
  95. data/spec/company_spec.rb +37 -47
  96. data/spec/comprehensive_income_statement_calculation_spec.rb +54 -0
  97. data/spec/comprehensive_income_statement_item_spec.rb +56 -0
  98. data/spec/debt_cost_of_capital_spec.rb +19 -0
  99. data/spec/equity_change_calculation_spec.rb +33 -0
  100. data/spec/equity_change_item_spec.rb +58 -0
  101. data/spec/factory_spec.rb +2 -2
  102. data/spec/forecasts_spec.rb +2 -2
  103. data/spec/income_statement_analyses_spec.rb +23 -21
  104. data/spec/income_statement_calculation_spec.rb +17 -49
  105. data/spec/income_statement_item_spec.rb +17 -29
  106. data/spec/liabs_and_equity_calculation_spec.rb +6 -3
  107. data/spec/liabs_and_equity_item_spec.rb +14 -22
  108. data/spec/linear_trend_forecasting_policy_spec.rb +37 -0
  109. data/spec/matchers/custom_matchers.rb +79 -0
  110. data/spec/mocks/calculation.rb +0 -0
  111. data/spec/mocks/income_statement_analyses.rb +0 -0
  112. data/spec/mocks/sec_query.rb +0 -0
  113. data/spec/net_income_calculation_spec.rb +16 -10
  114. data/spec/period_array.rb +0 -0
  115. data/spec/quarterly_report_filing_spec.rb +21 -38
  116. data/spec/rate_spec.rb +0 -0
  117. data/spec/ratio_spec.rb +0 -0
  118. data/spec/reformulated_balance_sheet_spec.rb +56 -33
  119. data/spec/reformulated_cash_flow_statement_spec.rb +18 -10
  120. data/spec/reformulated_income_statement_spec.rb +16 -15
  121. data/spec/reformulated_shareholder_equity_statement_spec.rb +43 -0
  122. data/spec/reoi_valuation_spec.rb +146 -0
  123. data/spec/shareholder_equity_statement_calculation_spec.rb +59 -0
  124. data/spec/spec_helper.rb +4 -1
  125. data/spec/string_helpers_spec.rb +15 -13
  126. data/spec/time_series_estimator_spec.rb +61 -0
  127. data/spec/trailing_avg_forecasting_policy_spec.rb +37 -0
  128. data/spec/weighted_avg_cost_of_capital_spec.rb +32 -0
  129. data/tools/create_equity_change_training_vectors.rb +49 -0
  130. data/tools/time_specs.sh +7 -0
  131. metadata +182 -36
  132. data/lib/finmodeling/constant_forecasting_policy.rb +0 -23
  133. data/lib/finmodeling/generic_forecasting_policy.rb +0 -19
  134. data/spec/constant_forecasting_policy_spec.rb +0 -37
  135. data/spec/generic_forecasting_policy_spec.rb +0 -33
@@ -0,0 +1,23 @@
1
+ module FinModeling
2
+ class TrailingAvgForecastingPolicy
3
+ def initialize(args)
4
+ @vals = args
5
+ end
6
+
7
+ def revenue_on(date)
8
+ @vals[:revenue_estimator].estimate_on(date)
9
+ end
10
+
11
+ def sales_pm_on(date)
12
+ @vals[:sales_pm_estimator].estimate_on(date)
13
+ end
14
+
15
+ def fi_over_nfa_on(date)
16
+ @vals[:fi_over_nfa_estimator].estimate_on(date)
17
+ end
18
+
19
+ def sales_over_noa_on(date)
20
+ @vals[:sales_over_noa_estimator].estimate_on(date)
21
+ end
22
+ end
23
+ end
@@ -1,3 +1,3 @@
1
1
  module FinModeling
2
- VERSION = "0.1"
2
+ VERSION = "0.2"
3
3
  end
@@ -0,0 +1,35 @@
1
+ module FinModeling
2
+ class WeightedAvgCostOfCapital
3
+ attr_reader :rate
4
+
5
+ def initialize(equity_market_val, debt_market_val, cost_of_equity, after_tax_cost_of_debt)
6
+ @equity_market_val = equity_market_val
7
+ @debt_market_val = debt_market_val
8
+ @cost_of_equity = cost_of_equity
9
+ @after_tax_cost_of_debt = after_tax_cost_of_debt
10
+
11
+ e_weight = @equity_market_val / (@equity_market_val + @debt_market_val)
12
+ d_weight = @debt_market_val / (@equity_market_val + @debt_market_val)
13
+
14
+ @rate = Rate.new((e_weight * @cost_of_equity.value) + (d_weight * @after_tax_cost_of_debt.value))
15
+ end
16
+
17
+ def summary
18
+ s = CalculationSummary.new
19
+ s.title = "Cost of Capital"
20
+ s.totals_row_enabled = false
21
+
22
+ s.header_row = CalculationHeader.new(:key => "", :vals => [Date.today.to_s])
23
+
24
+ s.rows = [ ]
25
+
26
+ s.rows << CalculationRow.new(:key => "Market Value of Equity ($MM)", :vals => [@equity_market_val.to_nearest_million])
27
+ s.rows << CalculationRow.new(:key => "Market Value of Debt ($MM)", :vals => [@debt_market_val.to_nearest_million])
28
+ s.rows << CalculationRow.new(:key => "Cost of Equity (%)", :vals => [sprintf("%.2f", 100.0*@cost_of_equity.value)])
29
+ s.rows << CalculationRow.new(:key => "Cost of Debt (%)", :vals => [sprintf("%.2f", 100.0*@after_tax_cost_of_debt.value)])
30
+ s.rows << CalculationRow.new(:key => "Weighted Avg Cost of Capital (%)", :vals => [sprintf("%.2f", 100.0*@rate.value)])
31
+
32
+ return s
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,20 @@
1
+ module YahooFinance
2
+ def YahooFinance.get_market_cap(stock_symbol)
3
+ quote = YahooFinance::get_quotes(YahooFinance::ExtendedQuote, stock_symbol).values.first
4
+ m = /([0-9\.]*)([MB])/.match(quote.marketCap)
5
+ mkt_cap = m[1].to_f
6
+ case
7
+ when m[2]=="M"
8
+ mkt_cap *= 1000*1000
9
+ when m[2]=="B"
10
+ mkt_cap *= 1000*1000*1000
11
+ end
12
+ mkt_cap
13
+ end
14
+
15
+ def YahooFinance.get_num_shares(stock_symbol)
16
+ mkt_cap = YahooFinance.get_market_cap(stock_symbol)
17
+ share_price = YahooFinance::get_quotes(YahooFinance::StandardQuote, stock_symbol).values.last.lastTrade.to_f
18
+ mkt_cap / share_price
19
+ end
20
+ end
data/lib/finmodeling.rb CHANGED
@@ -1,14 +1,21 @@
1
1
  require 'fileutils'
2
2
  require 'digest'
3
+
3
4
  require 'sec_query'
4
5
  require 'edgar'
6
+ require 'yahoofinance'
7
+ require 'finmodeling/yahoo_finance_helpers.rb'
8
+ require 'nasdaq_query'
5
9
 
6
10
  require 'xbrlware-ruby19'
7
11
  require 'xbrlware-extras'
8
12
 
13
+ require 'gsl'
9
14
  require 'naive_bayes'
10
15
  require 'statsample'
11
16
 
17
+ require 'finmodeling/invalid_filing_error'
18
+
12
19
  require 'finmodeling/float_helpers'
13
20
  require 'finmodeling/string_helpers'
14
21
  require 'finmodeling/factory'
@@ -39,22 +46,41 @@ require 'finmodeling/assets_item'
39
46
  require 'finmodeling/liabs_and_equity_item_vectors'
40
47
  require 'finmodeling/liabs_and_equity_item'
41
48
  require 'finmodeling/income_statement_item_vectors'
49
+ require 'finmodeling/comprehensive_income_statement_item_vectors'
42
50
  require 'finmodeling/income_statement_item'
51
+ require 'finmodeling/comprehensive_income_statement_item'
43
52
  require 'finmodeling/cash_change_item_vectors'
44
53
  require 'finmodeling/cash_change_item'
54
+ require 'finmodeling/equity_change_item_vectors'
55
+ require 'finmodeling/equity_change_item'
45
56
 
46
57
  require 'finmodeling/company_filing_calculation'
58
+ require 'finmodeling/can_choose_successive_periods'
47
59
  require 'finmodeling/balance_sheet_calculation'
48
60
  require 'finmodeling/assets_calculation'
49
61
  require 'finmodeling/liabs_and_equity_calculation'
50
62
  require 'finmodeling/income_statement_calculation'
63
+ require 'finmodeling/comprehensive_income_statement_calculation'
51
64
  require 'finmodeling/net_income_calculation'
65
+ require 'finmodeling/comprehensive_income_calculation'
52
66
  require 'finmodeling/cash_flow_statement_calculation'
53
67
  require 'finmodeling/cash_change_calculation'
68
+ require 'finmodeling/shareholder_equity_statement_calculation'
69
+ require 'finmodeling/equity_change_calculation'
70
+
71
+ require 'finmodeling/net_income_summary_from_differences'
72
+ require 'finmodeling/cash_change_summary_from_differences'
54
73
 
55
74
  require 'finmodeling/reformulated_income_statement'
56
75
  require 'finmodeling/reformulated_balance_sheet'
57
76
  require 'finmodeling/reformulated_cash_flow_statement'
77
+ require 'finmodeling/reformulated_shareholder_equity_statement'
78
+
79
+ require 'finmodeling/capm'
80
+ require 'finmodeling/debt_cost_of_capital'
81
+ require 'finmodeling/weighted_avg_cost_of_capital'
82
+ require 'finmodeling/fama_french_cost_of_equity'
83
+ require 'finmodeling/reoi_valuation'
58
84
 
59
85
  require 'finmodeling/config'
60
86
 
@@ -63,8 +89,13 @@ FinModeling::Classifiers.train
63
89
 
64
90
  require 'finmodeling/balance_sheet_analyses'
65
91
  require 'finmodeling/income_statement_analyses'
92
+ require 'finmodeling/cash_flow_statement_analyses'
93
+
94
+ require 'finmodeling/forecasted_reformulated_income_statement'
95
+ require 'finmodeling/forecasted_reformulated_balance_sheet'
66
96
 
67
- require 'finmodeling/generic_forecasting_policy'
68
- require 'finmodeling/constant_forecasting_policy'
97
+ require 'finmodeling/time_series_estimator'
98
+ require 'finmodeling/trailing_avg_forecasting_policy'
99
+ require 'finmodeling/linear_trend_forecasting_policy'
69
100
  require 'finmodeling/forecasts'
70
101
 
@@ -6,63 +6,99 @@ describe FinModeling::AnnualReportFiling do
6
6
  before(:all) do
7
7
  company = FinModeling::Company.new(FinModeling::Mocks::Entity.new)
8
8
  filing_url = company.annual_reports.last.link
9
- FinModeling::Config::disable_caching
10
9
  @filing = FinModeling::AnnualReportFiling.download(filing_url)
11
10
  end
12
11
 
13
- after(:all) do
14
- FinModeling::Config::enable_caching
15
- end
16
-
17
12
  subject { @filing }
18
- its(:balance_sheet) { should be_a FinModeling::BalanceSheetCalculation }
19
- its(:income_statement) { should be_a FinModeling::IncomeStatementCalculation }
20
- its(:cash_flow_statement) { should be_a FinModeling::CashFlowStatementCalculation }
13
+ its(:balance_sheet) { should be_a FinModeling::BalanceSheetCalculation }
14
+ its(:income_statement) { should be_a FinModeling::IncomeStatementCalculation }
15
+ its(:cash_flow_statement) { should be_a FinModeling::CashFlowStatementCalculation }
21
16
 
22
- its(:is_valid?) { should == (@filing.income_statement.is_valid? && @filing.balance_sheet.is_valid? && @filing.cash_flow_statement.is_valid?) }
23
-
24
- describe "write_constructor" do
17
+ context "when the report doesn't have a comprehensive income statement" do
18
+ its(:has_a_comprehensive_income_statement?) { should be_false }
19
+ its(:comprehensive_income_statement) { should be_nil }
20
+ end
21
+ context "when the report doesn't have a statement of shareholders' equity" do
22
+ its(:has_a_shareholder_equity_statement?) { should be_false }
23
+ its(:shareholder_equity_statement) { should be_nil }
24
+ its(:is_valid?) { should == [@filing.income_statement,
25
+ @filing.balance_sheet,
26
+ @filing.cash_flow_statement].all?{|x| x.is_valid?} }
27
+ end
28
+ context "when the report has a statement of shareholders' equity" do
25
29
  before(:all) do
26
- file_name = "/tmp/finmodeling-annual-rpt.rb"
27
- schema_version_item_name = "@schema_version"
28
- item_name = "@annual_rpt"
29
- file = File.open(file_name, "w")
30
- @filing.write_constructor(file, item_name)
31
- file.close
30
+ filing_url = "http://www.sec.gov/Archives/edgar/data/315189/000110465910063219/0001104659-10-063219-index.htm"
31
+ FinModeling::Config::disable_caching
32
+ @filing = FinModeling::AnnualReportFiling.download filing_url
33
+ FinModeling::Config::enable_caching
34
+ end
35
+ subject { @filing }
32
36
 
33
- eval(File.read(file_name))
37
+ its(:has_a_shareholder_equity_statement?) { should be_true }
38
+ its(:shareholder_equity_statement) { should be_a FinModeling::ShareholderEquityStatementCalculation }
39
+ its(:is_valid?) { should == [@filing.income_statement,
40
+ @filing.balance_sheet,
41
+ @filing.cash_flow_statement,
42
+ @filing.shareholder_equity_statement].all?{|x| x.is_valid?} }
34
43
 
35
- @schema_version = eval(schema_version_item_name)
36
- @loaded_filing = eval(item_name)
44
+ context "after write_constructor()ing it to a file and then eval()ing the results" do
45
+ before(:all) do
46
+ file_name = "/tmp/finmodeling-annual-rpt.rb"
47
+ schema_version_item_name = "@schema_version"
48
+ item_name = "@annual_rpt"
49
+ file = File.open(file_name, "w")
50
+ @filing.write_constructor(file, item_name)
51
+ file.close
52
+
53
+ eval(File.read(file_name))
54
+
55
+ @schema_version = eval(schema_version_item_name)
56
+ @loaded_filing = eval(item_name)
57
+ end
58
+
59
+ specify { @schema_version.should be == 1.3 }
60
+
61
+ subject { @loaded_filing }
62
+ its(:balance_sheet) { should have_the_same_periods_as(@filing.balance_sheet) }
63
+ its(:balance_sheet) { should have_the_same_reformulated_last_total(:net_operating_assets).as(@filing.balance_sheet) }
64
+ its(:income_statement) { should have_the_same_reformulated_last_total(:net_financing_income).as(@filing.income_statement) }
65
+ its(:cash_flow_statement) { should have_the_same_last_total(:cash_change_calculation).as(@filing.cash_flow_statement) }
66
+ its(:shareholder_equity_statement) { should be_a FinModeling::ShareholderEquityStatementCalculation }
67
+ its(:shareholder_equity_statement) { should have_the_same_last_total(:equity_change_calculation).as(@filing.shareholder_equity_statement) }
68
+ its(:disclosures) { should have_the_same_last_total(:first).as(@filing.disclosures) }
37
69
  end
70
+ end
38
71
 
39
- it "writes itself to a file, and saves a schema version of 1.1" do
40
- @schema_version.should be == 1.1
72
+ context "when the report has a comprehensive income statement" do
73
+ before(:all) do
74
+ filing_url = "http://www.sec.gov/Archives/edgar/data/818479/000081847912000023/0000818479-12-000023-index.htm"
75
+ FinModeling::Config::disable_caching
76
+ @filing = FinModeling::AnnualReportFiling.download filing_url
77
+ FinModeling::Config::enable_caching
41
78
  end
79
+ subject { @filing }
42
80
 
43
- it "writes itself to a file, and when reloaded, has the same periods" do
44
- expected_periods = @filing.balance_sheet.periods.map{|x| x.to_pretty_s}.join(',')
45
- @loaded_filing.balance_sheet.periods.map{|x| x.to_pretty_s}.join(',').should == expected_periods
46
- end
47
- it "writes itself to a file, and when reloaded, has the same net operating assets" do
48
- period = @filing.balance_sheet.periods.last
49
- expected_noa = @filing.balance_sheet.reformulated(period).net_operating_assets.total
50
- @loaded_filing.balance_sheet.reformulated(period).net_operating_assets.total.should be_within(1.0).of(expected_noa)
51
- end
52
- it "writes itself to a file, and when reloaded, has the same net financing income" do
53
- period = @filing.income_statement.periods.last
54
- expected_nfi = @filing.income_statement.reformulated(period).net_financing_income.total
55
- @loaded_filing.income_statement.reformulated(period).net_financing_income.total.should be_within(1.0).of(expected_nfi)
56
- end
57
- it "writes itself to a file, and when reloaded, has the same net change in cash" do
58
- period = @filing.cash_flow_statement.periods.last
59
- expected_cash_change = @filing.cash_flow_statement.cash_change_calculation.summary(:period=>period).total
60
- @loaded_filing.cash_flow_statement.cash_change_calculation.summary(:period=>period).total.should be_within(1.0).of(expected_cash_change)
61
- end
62
- it "writes itself to a file, and when reloaded, has the same disclosures" do
63
- period = @filing.disclosures.first.periods.last
64
- expected_total = @filing.disclosures.first.summary(:period=>period).total
65
- @loaded_filing.disclosures.first.summary(:period=>period).total.should == expected_total
81
+ its(:has_a_comprehensive_income_statement?) { should be_true }
82
+ its(:comprehensive_income_statement) { should be_a FinModeling::ComprehensiveIncomeStatementCalculation }
83
+
84
+ context "after write_constructor()ing it to a file and then eval()ing the results" do
85
+ before(:all) do
86
+ file_name = "/tmp/finmodeling-annual-rpt.rb"
87
+ schema_version_item_name = "@schema_version"
88
+ item_name = "@annual_rpt"
89
+ file = File.open(file_name, "w")
90
+ @filing.write_constructor(file, item_name)
91
+ file.close
92
+
93
+ eval(File.read(file_name))
94
+ @loaded_filing = eval(item_name)
95
+ end
96
+
97
+ subject { @loaded_filing }
98
+ its(:comprehensive_income_statement) { should be_a FinModeling::ComprehensiveIncomeStatementCalculation }
99
+ its(:comprehensive_income_statement) { should have_the_same_last_total(:comprehensive_income_calculation).as(@filing.comprehensive_income_statement) }
66
100
  end
101
+
67
102
  end
103
+
68
104
  end
@@ -12,10 +12,13 @@ describe FinModeling::AssetsCalculation do
12
12
  @a = @bal_sheet.assets_calculation
13
13
  end
14
14
 
15
- describe "summary" do
16
- it "only requires a period (knows how debts/credits work and whether to flip the total)" do
17
- @a.summary(:period=>@period).should be_an_instance_of FinModeling::CalculationSummary
18
- end
15
+ describe ".summary" do
16
+ subject { @a.summary(:period=>@period) }
17
+ it { should be_a FinModeling::CalculationSummary }
18
+ end
19
+
20
+ describe ".has_cash_item" do
21
+ pending "Find a test case..."
19
22
  end
20
23
  end
21
24
 
@@ -9,33 +9,28 @@ describe FinModeling::AssetsItem do
9
9
  end
10
10
 
11
11
  describe "new" do
12
- it "takes a string and returns a new AssetsItem" do
13
- ai = FinModeling::AssetsItem.new("Property Plant And Equipment Net")
14
- ai.should be_an_instance_of FinModeling::AssetsItem
15
- end
12
+ subject { FinModeling::AssetsItem.new("Property Plant And Equipment Net") }
13
+ it { should be_a FinModeling::AssetsItem }
16
14
  end
17
15
 
18
16
  describe "train" do
17
+ subject { FinModeling::AssetsItem.new("Property Plant And Equipment Net") }
19
18
  it "trains the classifier that this AssetsItem is of the given type" do
20
- FinModeling::AssetsItem.new("Property Plant and Equipment Net").train(:oa)
19
+ subject.train(:oa)
21
20
  end
22
21
  end
23
22
 
24
23
  describe "classification_estimates" do
25
- it "returns a hash with the confidence in each AssetsItem type" do
26
- ai = FinModeling::AssetsItem.new("Property Plant And Equipment Net")
27
-
28
- FinModeling::AssetsItem::TYPES.each do |klass|
29
- ai.classification_estimates.keys.include?(klass).should be_true
30
- end
31
- end
24
+ subject { FinModeling::AssetsItem.new("Property Plant And Equipment Net").classification_estimates }
25
+ its(:keys) { should == FinModeling::AssetsItem::TYPES }
32
26
  end
33
27
 
34
28
  describe "classify" do
29
+ let(:ai) { FinModeling::AssetsItem.new("Property Plant And Equipment Net") }
30
+ subject { ai.classify }
35
31
  it "returns the AssetsItem type with the highest probability estimate" do
36
- ai = FinModeling::AssetsItem.new("Property Plant And Equipment Net")
37
32
  estimates = ai.classification_estimates
38
- estimates[ai.classify].should be_within(0.1).of(estimates.values.max)
33
+ estimates[subject].should be_within(0.1).of(estimates.values.max)
39
34
  end
40
35
  end
41
36
 
@@ -8,30 +8,30 @@ describe FinModeling::BalanceSheetAnalyses do
8
8
  @summary.title = "Title 123"
9
9
  @summary.rows = [ ]
10
10
  @summary.rows << FinModeling::CalculationRow.new(:key => "NOA Growth", :type => :oa, :vals => [ 4])
11
- @summary.rows << FinModeling::CalculationRow.new(:key => "Row", :type => :fa, :vals => [109])
12
- @summary.rows << FinModeling::CalculationRow.new(:key => "Row", :type => :oa, :vals => [ 93])
13
- @summary.rows << FinModeling::CalculationRow.new(:key => "Row", :type => :fa, :vals => [ 1])
11
+ @summary.rows << FinModeling::CalculationRow.new(:key => "Row", :type => :fa, :vals => [109])
12
+ @summary.rows << FinModeling::CalculationRow.new(:key => "Row", :type => :oa, :vals => [ 93])
13
+ @summary.rows << FinModeling::CalculationRow.new(:key => "Row", :type => :fa, :vals => [ 1])
14
14
  end
15
15
 
16
16
  describe ".new" do
17
17
  subject { FinModeling::BalanceSheetAnalyses.new(@summary) }
18
18
 
19
19
  it { should be_a_kind_of FinModeling::CalculationSummary }
20
- its(:title) { should == @summary.title }
21
- its(:rows) { should == @summary.rows }
22
- its(:header_row) { should == @summary.header_row }
23
- its(:rows) { should == @summary.rows }
24
- its(:num_value_columns) { should == @summary.num_value_columns }
25
- its(:key_width) { should == @summary.key_width }
26
- its(:val_width) { should == @summary.val_width }
27
- its(:max_decimals) { should == @summary.max_decimals }
20
+ its(:title) { should == @summary.title }
21
+ its(:rows) { should == @summary.rows }
22
+ its(:header_row) { should == @summary.header_row }
23
+ its(:rows) { should == @summary.rows }
24
+ its(:num_value_columns) { should == @summary.num_value_columns }
25
+ its(:key_width) { should == @summary.key_width }
26
+ its(:val_width) { should == @summary.val_width }
27
+ its(:max_decimals) { should == @summary.max_decimals }
28
28
  its(:totals_row_enabled) { should be_false }
29
29
  end
30
30
 
31
- describe ".print_extras" do
31
+ describe ".print_regressions" do
32
32
  subject { FinModeling::BalanceSheetAnalyses.new(@summary) }
33
33
 
34
- it { should respond_to(:print_extras) }
34
+ it { should respond_to(:print_regressions) }
35
35
  end
36
36
 
37
37
  describe ".noa_growth_row" do
@@ -10,60 +10,59 @@ describe FinModeling::BalanceSheetCalculation do
10
10
  @period = @balance_sheet.periods.last
11
11
  end
12
12
 
13
- describe "assets_calculation" do
14
- it "returns an AssetsCalculation" do
15
- @balance_sheet.assets_calculation.should be_an_instance_of FinModeling::AssetsCalculation
16
- end
17
- it "returns the root node of the assets calculation" do
18
- @balance_sheet.assets_calculation.label.downcase.should match /asset/
19
- end
20
- it "sums to the same value as do the liabilities and equity" do
21
- left_sum = @balance_sheet.assets_calculation.leaf_items_sum(:period=>@period)
22
- right_sum = @balance_sheet.liabs_and_equity_calculation.leaf_items_sum(:period=>@period)
23
- left_sum.should be_within(1.0).of(right_sum)
24
- end
13
+ describe ".assets_calculation" do
14
+ subject { @balance_sheet.assets_calculation }
15
+ it { should be_a FinModeling::AssetsCalculation }
16
+ its(:label) { should match /asset/i }
17
+
18
+ let(:right_side_sum) { @balance_sheet.liabs_and_equity_calculation.leaf_items_sum(:period=>@period) }
19
+ specify { subject.leaf_items_sum(:period=>@period).should be_within(1.0).of(right_side_sum) }
25
20
  end
26
21
 
27
- describe "liabs_and_equity_calculation" do
28
- it "returns a LiabsAndEquityCalculation" do
29
- @balance_sheet.liabs_and_equity_calculation.should be_an_instance_of FinModeling::LiabsAndEquityCalculation
30
- end
31
- it "returns the root node of the liability & shareholders' equity calculation" do
32
- @balance_sheet.liabs_and_equity_calculation.label.downcase.should match /liab.*equity/
33
- end
22
+ describe ".liabs_and_equity_calculation" do
23
+ subject { @balance_sheet.liabs_and_equity_calculation}
24
+ it { should be_a FinModeling::LiabsAndEquityCalculation }
25
+ its(:label) { should match /liab.*equity/i }
34
26
  end
35
27
 
36
- describe "is_valid?" do
37
- it "returns false if none of the asset leaf nodes contains the term 'cash'" do
38
- #ea_2011_annual_rpt = "http://www.sec.gov/Archives/edgar/data/712515/000119312511149262/0001193125-11-149262-index.htm"
39
- #filing = FinModeling::AnnualReportFiling.download ea_2011_annual_rpt
40
- #filing.balance_sheet.is_valid?.should be_false
41
- pending
28
+ describe ".is_valid?" do
29
+ context "if none of the asset leaf nodes contains the term 'cash'" do
30
+ it "returns false" do
31
+ #ea_2011_annual_rpt = "http://www.sec.gov/Archives/edgar/data/712515/000119312511149262/0001193125-11-149262-index.htm"
32
+ #filing = FinModeling::AnnualReportFiling.download ea_2011_annual_rpt
33
+ #filing.balance_sheet.is_valid?.should be_false
34
+ pending "Need to find another example of this...."
35
+ end
42
36
  end
43
- it "returns false if none of the liability/equity net income leaf nodes contains the term 'equity'" do
44
- #ea_2011_annual_rpt = "http://www.sec.gov/Archives/edgar/data/712515/000119312511149262/0001193125-11-149262-index.htm"
45
- #filing = FinModeling::AnnualReportFiling.download ea_2011_annual_rpt
46
- #filing.balance_sheet.is_valid?.should be_false
47
- pending
37
+ context "if none of the liability/equity net income leaf nodes contains the term 'equity'" do
38
+ it "returns false" do
39
+ #ea_2011_annual_rpt = "http://www.sec.gov/Archives/edgar/data/712515/000119312511149262/0001193125-11-149262-index.htm"
40
+ #filing = FinModeling::AnnualReportFiling.download ea_2011_annual_rpt
41
+ #filing.balance_sheet.is_valid?.should be_false
42
+ pending "Need to find another example of this...."
43
+ end
48
44
  end
49
- it "returns false if the assets total does not match the liabilities and equity total" do
50
- #ea_2011_annual_rpt = "http://www.sec.gov/Archives/edgar/data/712515/000119312511149262/0001193125-11-149262-index.htm"
51
- #filing = FinModeling::AnnualReportFiling.download ea_2011_annual_rpt
52
- #filing.balance_sheet.is_valid?.should be_false
53
- pending
45
+ context "if the assets total does not match the liabilities and equity total" do
46
+ it "returns false" do
47
+ #ea_2011_annual_rpt = "http://www.sec.gov/Archives/edgar/data/712515/000119312511149262/0001193125-11-149262-index.htm"
48
+ #filing = FinModeling::AnnualReportFiling.download ea_2011_annual_rpt
49
+ #filing.balance_sheet.is_valid?.should be_false
50
+ pending "Need to find another example of this...."
51
+ end
54
52
  end
55
- it "returns true otherwise" do
56
- @balance_sheet.is_valid?.should be_true
53
+ context "otherwise" do
54
+ it "returns true" do
55
+ @balance_sheet.is_valid?.should be_true
56
+ end
57
57
  end
58
58
  end
59
59
 
60
- describe "reformulated" do
61
- it "takes a period and returns a ReformulatedBalanceSheet" do
62
- @balance_sheet.reformulated(@period).should be_an_instance_of FinModeling::ReformulatedBalanceSheet
63
- end
60
+ describe ".reformulated" do
61
+ subject { @balance_sheet.reformulated(@period) }
62
+ it { should be_a FinModeling::ReformulatedBalanceSheet }
64
63
  end
65
64
 
66
- describe "write_constructor" do
65
+ describe ".write_constructor" do
67
66
  before(:all) do
68
67
  file_name = "/tmp/finmodeling-bal-sheet.rb"
69
68
  item_name = "@bal_sheet"
@@ -72,18 +71,13 @@ describe FinModeling::BalanceSheetCalculation do
72
71
  file.close
73
72
 
74
73
  eval(File.read(file_name))
75
-
76
74
  @loaded_bs = eval(item_name)
77
75
  end
78
76
 
79
- it "writes itself to a file, and when reloaded, has the same periods" do
80
- expected_periods = @balance_sheet.periods.map{|x| x.to_pretty_s}.join(',')
81
- @loaded_bs.periods.map{|x| x.to_pretty_s}.join(',').should == expected_periods
82
- end
83
- it "writes itself to a file, and when reloaded, has the same net operating assets" do
84
- period = @balance_sheet.periods.last
85
- expected_noa = @balance_sheet.reformulated(period).net_operating_assets.total
86
- @loaded_bs.reformulated(period).net_operating_assets.total.should be_within(1.0).of(expected_noa)
77
+ context "after write_constructor()ing it to a file and then eval()ing the results" do
78
+ subject { @loaded_bs }
79
+ it { should have_the_same_periods_as @balance_sheet }
80
+ it { should have_the_same_reformulated_last_total(:net_operating_assets).as(@balance_sheet) }
87
81
  end
88
82
  end
89
83