finmodeling 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
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