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.
- data/.gitignore +0 -0
- data/Gemfile +2 -0
- data/README.md +289 -269
- data/Rakefile +12 -0
- data/TODO.txt +113 -20
- data/examples/{dump_report.rb → dump_latest_10k.rb} +1 -1
- data/examples/list_disclosures.rb +50 -0
- data/examples/lists/nasdaq-mid-to-mega-tech-symbols.txt +0 -0
- data/examples/show_report.rb +112 -32
- data/examples/show_reports.rb +162 -33
- data/finmodeling.gemspec +4 -1
- data/lib/finmodeling/annual_report_filing.rb +97 -18
- data/lib/finmodeling/array_with_stats.rb +0 -0
- data/lib/finmodeling/assets_calculation.rb +12 -3
- data/lib/finmodeling/assets_item.rb +0 -0
- data/lib/finmodeling/assets_item_vectors.rb +0 -0
- data/lib/finmodeling/balance_sheet_analyses.rb +19 -4
- data/lib/finmodeling/balance_sheet_calculation.rb +52 -37
- data/lib/finmodeling/calculation_summary.rb +119 -14
- data/lib/finmodeling/can_cache_classifications.rb +0 -0
- data/lib/finmodeling/can_cache_summaries.rb +0 -0
- data/lib/finmodeling/can_choose_successive_periods.rb +15 -0
- data/lib/finmodeling/can_classify_rows.rb +0 -0
- data/lib/finmodeling/capm.rb +80 -0
- data/lib/finmodeling/cash_change_calculation.rb +3 -3
- data/lib/finmodeling/cash_change_item.rb +0 -0
- data/lib/finmodeling/cash_change_item_vectors.rb +0 -0
- data/lib/finmodeling/cash_change_summary_from_differences.rb +36 -0
- data/lib/finmodeling/cash_flow_statement_analyses.rb +36 -0
- data/lib/finmodeling/cash_flow_statement_calculation.rb +28 -52
- data/lib/finmodeling/classifiers.rb +2 -0
- data/lib/finmodeling/company.rb +0 -0
- data/lib/finmodeling/company_filing.rb +30 -7
- data/lib/finmodeling/company_filing_calculation.rb +16 -6
- data/lib/finmodeling/company_filings.rb +112 -46
- data/lib/finmodeling/comprehensive_income_calculation.rb +60 -0
- data/lib/finmodeling/comprehensive_income_statement_calculation.rb +74 -0
- data/lib/finmodeling/comprehensive_income_statement_item.rb +20 -0
- data/lib/finmodeling/comprehensive_income_statement_item_vectors.rb +235 -0
- data/lib/finmodeling/config.rb +0 -0
- data/lib/finmodeling/debt_cost_of_capital.rb +14 -0
- data/lib/finmodeling/equity_change_calculation.rb +43 -0
- data/lib/finmodeling/equity_change_item.rb +25 -0
- data/lib/finmodeling/equity_change_item_vectors.rb +156 -0
- data/lib/finmodeling/factory.rb +0 -0
- data/lib/finmodeling/fama_french_cost_of_equity.rb +119 -0
- data/lib/finmodeling/float_helpers.rb +14 -8
- data/lib/finmodeling/forecasted_reformulated_balance_sheet.rb +55 -0
- data/lib/finmodeling/forecasted_reformulated_income_statement.rb +110 -0
- data/lib/finmodeling/forecasts.rb +4 -4
- data/lib/finmodeling/has_string_classifer.rb +0 -0
- data/lib/finmodeling/income_statement_analyses.rb +23 -17
- data/lib/finmodeling/income_statement_calculation.rb +46 -43
- data/lib/finmodeling/income_statement_item.rb +1 -1
- data/lib/finmodeling/income_statement_item_vectors.rb +24 -13
- data/lib/finmodeling/invalid_filing_error.rb +4 -0
- data/lib/finmodeling/liabs_and_equity_calculation.rb +18 -8
- data/lib/finmodeling/liabs_and_equity_item.rb +1 -1
- data/lib/finmodeling/liabs_and_equity_item_vectors.rb +24 -24
- data/lib/finmodeling/linear_trend_forecasting_policy.rb +23 -0
- data/lib/finmodeling/net_income_calculation.rb +23 -10
- data/lib/finmodeling/net_income_summary_from_differences.rb +51 -0
- data/lib/finmodeling/paths.rb +0 -0
- data/lib/finmodeling/period_array.rb +8 -4
- data/lib/finmodeling/quarterly_report_filing.rb +9 -4
- data/lib/finmodeling/rate.rb +8 -0
- data/lib/finmodeling/ratio.rb +0 -0
- data/lib/finmodeling/reformulated_balance_sheet.rb +47 -88
- data/lib/finmodeling/reformulated_cash_flow_statement.rb +18 -41
- data/lib/finmodeling/reformulated_income_statement.rb +44 -206
- data/lib/finmodeling/reformulated_shareholder_equity_statement.rb +50 -0
- data/lib/finmodeling/reoi_valuation.rb +104 -0
- data/lib/finmodeling/shareholder_equity_statement_calculation.rb +34 -0
- data/lib/finmodeling/string_helpers.rb +18 -1
- data/lib/finmodeling/time_series_estimator.rb +25 -0
- data/lib/finmodeling/trailing_avg_forecasting_policy.rb +23 -0
- data/lib/finmodeling/version.rb +1 -1
- data/lib/finmodeling/weighted_avg_cost_of_capital.rb +35 -0
- data/lib/finmodeling/yahoo_finance_helpers.rb +20 -0
- data/lib/finmodeling.rb +33 -2
- data/spec/annual_report_filing_spec.rb +81 -45
- data/spec/assets_calculation_spec.rb +7 -4
- data/spec/assets_item_spec.rb +9 -14
- data/spec/balance_sheet_analyses_spec.rb +13 -13
- data/spec/balance_sheet_calculation_spec.rb +45 -51
- data/spec/calculation_summary_spec.rb +113 -21
- data/spec/can_classify_rows_spec.rb +0 -0
- data/spec/cash_change_calculation_spec.rb +1 -10
- data/spec/cash_change_item_spec.rb +10 -18
- data/spec/cash_flow_statement_calculation_spec.rb +10 -24
- data/spec/company_beta_spec.rb +53 -0
- data/spec/company_filing_calculation_spec.rb +39 -49
- data/spec/company_filing_spec.rb +0 -0
- data/spec/company_filings_spec.rb +75 -25
- data/spec/company_spec.rb +37 -47
- data/spec/comprehensive_income_statement_calculation_spec.rb +54 -0
- data/spec/comprehensive_income_statement_item_spec.rb +56 -0
- data/spec/debt_cost_of_capital_spec.rb +19 -0
- data/spec/equity_change_calculation_spec.rb +33 -0
- data/spec/equity_change_item_spec.rb +58 -0
- data/spec/factory_spec.rb +2 -2
- data/spec/forecasts_spec.rb +2 -2
- data/spec/income_statement_analyses_spec.rb +23 -21
- data/spec/income_statement_calculation_spec.rb +17 -49
- data/spec/income_statement_item_spec.rb +17 -29
- data/spec/liabs_and_equity_calculation_spec.rb +6 -3
- data/spec/liabs_and_equity_item_spec.rb +14 -22
- data/spec/linear_trend_forecasting_policy_spec.rb +37 -0
- data/spec/matchers/custom_matchers.rb +79 -0
- data/spec/mocks/calculation.rb +0 -0
- data/spec/mocks/income_statement_analyses.rb +0 -0
- data/spec/mocks/sec_query.rb +0 -0
- data/spec/net_income_calculation_spec.rb +16 -10
- data/spec/period_array.rb +0 -0
- data/spec/quarterly_report_filing_spec.rb +21 -38
- data/spec/rate_spec.rb +0 -0
- data/spec/ratio_spec.rb +0 -0
- data/spec/reformulated_balance_sheet_spec.rb +56 -33
- data/spec/reformulated_cash_flow_statement_spec.rb +18 -10
- data/spec/reformulated_income_statement_spec.rb +16 -15
- data/spec/reformulated_shareholder_equity_statement_spec.rb +43 -0
- data/spec/reoi_valuation_spec.rb +146 -0
- data/spec/shareholder_equity_statement_calculation_spec.rb +59 -0
- data/spec/spec_helper.rb +4 -1
- data/spec/string_helpers_spec.rb +15 -13
- data/spec/time_series_estimator_spec.rb +61 -0
- data/spec/trailing_avg_forecasting_policy_spec.rb +37 -0
- data/spec/weighted_avg_cost_of_capital_spec.rb +32 -0
- data/tools/create_equity_change_training_vectors.rb +49 -0
- data/tools/time_specs.sh +7 -0
- metadata +182 -36
- data/lib/finmodeling/constant_forecasting_policy.rb +0 -23
- data/lib/finmodeling/generic_forecasting_policy.rb +0 -19
- data/spec/constant_forecasting_policy_spec.rb +0 -37
- 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
|
data/lib/finmodeling/version.rb
CHANGED
|
@@ -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/
|
|
68
|
-
require 'finmodeling/
|
|
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)
|
|
19
|
-
its(:income_statement)
|
|
20
|
-
its(:cash_flow_statement)
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
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
|
-
|
|
36
|
-
|
|
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
|
-
|
|
40
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
|
data/spec/assets_item_spec.rb
CHANGED
|
@@ -9,33 +9,28 @@ describe FinModeling::AssetsItem do
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
describe "new" do
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
19
|
+
subject.train(:oa)
|
|
21
20
|
end
|
|
22
21
|
end
|
|
23
22
|
|
|
24
23
|
describe "classification_estimates" do
|
|
25
|
-
|
|
26
|
-
|
|
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[
|
|
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",
|
|
12
|
-
@summary.rows << FinModeling::CalculationRow.new(:key => "Row",
|
|
13
|
-
@summary.rows << FinModeling::CalculationRow.new(:key => "Row",
|
|
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)
|
|
21
|
-
its(:rows)
|
|
22
|
-
its(:header_row)
|
|
23
|
-
its(:rows)
|
|
24
|
-
its(:num_value_columns)
|
|
25
|
-
its(:key_width)
|
|
26
|
-
its(:val_width)
|
|
27
|
-
its(: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 ".
|
|
31
|
+
describe ".print_regressions" do
|
|
32
32
|
subject { FinModeling::BalanceSheetAnalyses.new(@summary) }
|
|
33
33
|
|
|
34
|
-
it { should respond_to(:
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
56
|
-
|
|
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
|
-
|
|
62
|
-
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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
|
|