finmodeling 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. data/.gitignore +3 -0
  2. data/Gemfile +10 -0
  3. data/README.md +292 -0
  4. data/Rakefile +6 -0
  5. data/TODO.txt +36 -0
  6. data/examples/dump_report.rb +33 -0
  7. data/examples/lists/nasdaq-mid-to-mega-tech-symbols.txt +226 -0
  8. data/examples/show_report.rb +218 -0
  9. data/examples/show_reports.rb +77 -0
  10. data/finmodeling.gemspec +31 -0
  11. data/lib/finmodeling/annual_report_filing.rb +104 -0
  12. data/lib/finmodeling/array_with_stats.rb +22 -0
  13. data/lib/finmodeling/assets_calculation.rb +36 -0
  14. data/lib/finmodeling/assets_item.rb +14 -0
  15. data/lib/finmodeling/assets_item_vectors.rb +638 -0
  16. data/lib/finmodeling/balance_sheet_analyses.rb +33 -0
  17. data/lib/finmodeling/balance_sheet_calculation.rb +68 -0
  18. data/lib/finmodeling/calculation_summary.rb +148 -0
  19. data/lib/finmodeling/can_cache_classifications.rb +36 -0
  20. data/lib/finmodeling/can_cache_summaries.rb +16 -0
  21. data/lib/finmodeling/can_classify_rows.rb +54 -0
  22. data/lib/finmodeling/cash_change_calculation.rb +67 -0
  23. data/lib/finmodeling/cash_change_item.rb +14 -0
  24. data/lib/finmodeling/cash_change_item_vectors.rb +241 -0
  25. data/lib/finmodeling/cash_flow_statement_calculation.rb +85 -0
  26. data/lib/finmodeling/classifiers.rb +11 -0
  27. data/lib/finmodeling/company.rb +102 -0
  28. data/lib/finmodeling/company_filing.rb +64 -0
  29. data/lib/finmodeling/company_filing_calculation.rb +75 -0
  30. data/lib/finmodeling/company_filings.rb +100 -0
  31. data/lib/finmodeling/config.rb +37 -0
  32. data/lib/finmodeling/constant_forecasting_policy.rb +23 -0
  33. data/lib/finmodeling/factory.rb +27 -0
  34. data/lib/finmodeling/float_helpers.rb +17 -0
  35. data/lib/finmodeling/forecasts.rb +48 -0
  36. data/lib/finmodeling/generic_forecasting_policy.rb +19 -0
  37. data/lib/finmodeling/has_string_classifer.rb +96 -0
  38. data/lib/finmodeling/income_statement_analyses.rb +74 -0
  39. data/lib/finmodeling/income_statement_calculation.rb +71 -0
  40. data/lib/finmodeling/income_statement_item.rb +14 -0
  41. data/lib/finmodeling/income_statement_item_vectors.rb +654 -0
  42. data/lib/finmodeling/liabs_and_equity_calculation.rb +36 -0
  43. data/lib/finmodeling/liabs_and_equity_item.rb +14 -0
  44. data/lib/finmodeling/liabs_and_equity_item_vectors.rb +1936 -0
  45. data/lib/finmodeling/net_income_calculation.rb +41 -0
  46. data/lib/finmodeling/paths.rb +5 -0
  47. data/lib/finmodeling/period_array.rb +24 -0
  48. data/lib/finmodeling/quarterly_report_filing.rb +23 -0
  49. data/lib/finmodeling/rate.rb +20 -0
  50. data/lib/finmodeling/ratio.rb +20 -0
  51. data/lib/finmodeling/reformulated_balance_sheet.rb +176 -0
  52. data/lib/finmodeling/reformulated_cash_flow_statement.rb +140 -0
  53. data/lib/finmodeling/reformulated_income_statement.rb +436 -0
  54. data/lib/finmodeling/string_helpers.rb +26 -0
  55. data/lib/finmodeling/version.rb +3 -0
  56. data/lib/finmodeling.rb +70 -0
  57. data/spec/annual_report_filing_spec.rb +68 -0
  58. data/spec/assets_calculation_spec.rb +21 -0
  59. data/spec/assets_item_spec.rb +66 -0
  60. data/spec/balance_sheet_analyses_spec.rb +43 -0
  61. data/spec/balance_sheet_calculation_spec.rb +91 -0
  62. data/spec/calculation_summary_spec.rb +63 -0
  63. data/spec/can_classify_rows_spec.rb +86 -0
  64. data/spec/cash_change_calculation_spec.rb +56 -0
  65. data/spec/cash_change_item_spec.rb +66 -0
  66. data/spec/cash_flow_statement_calculation_spec.rb +108 -0
  67. data/spec/company_filing_calculation_spec.rb +74 -0
  68. data/spec/company_filing_spec.rb +30 -0
  69. data/spec/company_filings_spec.rb +55 -0
  70. data/spec/company_spec.rb +73 -0
  71. data/spec/constant_forecasting_policy_spec.rb +37 -0
  72. data/spec/factory_spec.rb +18 -0
  73. data/spec/forecasts_spec.rb +21 -0
  74. data/spec/generic_forecasting_policy_spec.rb +33 -0
  75. data/spec/income_statement_analyses_spec.rb +63 -0
  76. data/spec/income_statement_calculation_spec.rb +88 -0
  77. data/spec/income_statement_item_spec.rb +86 -0
  78. data/spec/liabs_and_equity_calculation_spec.rb +20 -0
  79. data/spec/liabs_and_equity_item_spec.rb +66 -0
  80. data/spec/mocks/calculation.rb +10 -0
  81. data/spec/mocks/income_statement_analyses.rb +93 -0
  82. data/spec/mocks/sec_query.rb +31 -0
  83. data/spec/net_income_calculation_spec.rb +23 -0
  84. data/spec/period_array.rb +52 -0
  85. data/spec/quarterly_report_filing_spec.rb +69 -0
  86. data/spec/rate_spec.rb +33 -0
  87. data/spec/ratio_spec.rb +33 -0
  88. data/spec/reformulated_balance_sheet_spec.rb +146 -0
  89. data/spec/reformulated_cash_flow_statement_spec.rb +174 -0
  90. data/spec/reformulated_income_statement_spec.rb +293 -0
  91. data/spec/spec_helper.rb +5 -0
  92. data/spec/string_helpers_spec.rb +23 -0
  93. data/tools/create_balance_sheet_training_vectors.rb +65 -0
  94. data/tools/create_cash_change_training_vectors.rb +48 -0
  95. data/tools/create_credit_debit_training_vectors.rb +51 -0
  96. data/tools/create_income_statement_training_vectors.rb +48 -0
  97. metadata +289 -0
@@ -0,0 +1,218 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'finmodeling'
4
+
5
+ class Arguments
6
+ def self.show_usage_and_exit
7
+ puts "usage:"
8
+ puts "\t#{__FILE__} [options] <stock symbol> <10-k|10-q> <0, for most recent|-1 for prevous|-2, etc>"
9
+ puts "\t#{__FILE__} [options] <report URL> <10-k|10-q>"
10
+ puts
11
+ puts "\tOptions:"
12
+ puts "\t\t--no-cache: disables caching"
13
+ puts "\t\t--show-disclosures: prints out all the disclosure calculations in the filing"
14
+ exit
15
+ end
16
+
17
+ def self.parse(raw_args)
18
+ parsed_args = { :stock_symbol => nil, :filing_url => nil,
19
+ :report_type => nil, :report_offset => nil,
20
+ :show_disclosures => false }
21
+
22
+ while raw_args.any? && raw_args.first =~ /^--/
23
+ case raw_args.first.downcase
24
+ when '--no-cache'
25
+ FinModeling::Config.disable_caching
26
+ puts "Caching is #{FinModeling::Config.caching_enabled? ? "enabled" : "disabled"}"
27
+ when '--show-disclosures'
28
+ parsed_args[:show_disclosures] = true
29
+ puts "Showing disclosures"
30
+ else
31
+ self.show_usage_and_exit
32
+ end
33
+ raw_args = raw_args[1..-1]
34
+ end
35
+
36
+ if raw_args[0] =~ /http/
37
+ return self.parse_just_a_url(raw_args, parsed_args)
38
+ else
39
+ return self.parse_symbol_etc(raw_args, parsed_args)
40
+ end
41
+ end
42
+
43
+ protected
44
+
45
+ def self.parse_just_a_url(raw_args, parsed)
46
+ self.show_usage_and_exit if raw_args.length != 2
47
+
48
+ parsed_args[:filing_url] = raw_args[0]
49
+ parsed_args[:report_type] = case raw_args[1].downcase
50
+ when "10-k"
51
+ :annual_report
52
+ when "10-q"
53
+ :quarterly_report
54
+ else
55
+ self.show_usage_and_exit
56
+ end
57
+
58
+ return parsed_args
59
+ end
60
+
61
+ def self.parse_symbol_etc(raw_args, parsed_args)
62
+ self.show_usage_and_exit if raw_args.length != 3
63
+
64
+ parsed_args[:stock_symbol] = raw_args[0]
65
+ parsed_args[:report_type] = case raw_args[1].downcase
66
+ when "10-k"
67
+ :annual_report
68
+ when "10-q"
69
+ :quarterly_report
70
+ else
71
+ self.show_usage_and_exit
72
+ end
73
+ parsed_args[:report_offset] = raw_args[2].to_i
74
+
75
+ return parsed_args
76
+ end
77
+ end
78
+
79
+ def get_company_filing_url(stock_symbol, report_type, report_offset)
80
+ company = FinModeling::Company.find(stock_symbol)
81
+ raise RuntimeError.new("couldn't find company") if company.nil?
82
+ puts "company name: #{company.name}"
83
+
84
+ filing_url = case report_type
85
+ when :annual_report
86
+ raise RuntimeError.new("company has no annual reports") if company.annual_reports.length == 0
87
+ company.annual_reports[-1+report_offset].link
88
+ when :quarterly_report
89
+ raise RuntimeError.new("company has no quarterly reports") if company.annual_reports.length == 0
90
+ company.quarterly_reports[-1+report_offset].link
91
+ end
92
+
93
+ return filing_url
94
+ end
95
+
96
+ def get_filing(filing_url, report_type)
97
+ puts "url: #{filing_url}\n"
98
+ return FinModeling::AnnualReportFiling.download( filing_url) if report_type == :annual_report
99
+ return FinModeling::QuarterlyReportFiling.download(filing_url) if report_type == :quarterly_report
100
+ end
101
+
102
+ def print_balance_sheet(filing, report_type)
103
+ period = filing.balance_sheet.periods.last
104
+ puts "Balance Sheet (#{period.to_pretty_s})"
105
+
106
+ summaries = []
107
+ summaries << filing.balance_sheet.assets_calculation.summary(:period => period)
108
+ summaries << filing.balance_sheet.liabs_and_equity_calculation.summary(:period => period)
109
+
110
+ print_summaries(summaries)
111
+ end
112
+
113
+ def print_reformulated_balance_sheet(filing, report_type)
114
+ period = filing.balance_sheet.periods.last
115
+
116
+ reformed_balance_sheet = filing.balance_sheet.reformulated(period)
117
+
118
+ summaries = []
119
+ summaries << reformed_balance_sheet.net_operating_assets
120
+ summaries << reformed_balance_sheet.net_financial_assets
121
+ summaries << reformed_balance_sheet.common_shareholders_equity
122
+
123
+ print_summaries(summaries)
124
+ end
125
+
126
+ def print_income_statement(filing, report_type)
127
+ period = filing.income_statement.net_income_calculation.periods.yearly.last if report_type == :annual_report
128
+ period = filing.income_statement.net_income_calculation.periods.quarterly.last if report_type == :quarterly_report
129
+ puts "Income Statement (#{period.to_pretty_s})"
130
+
131
+ summaries = []
132
+ summaries << filing.income_statement.net_income_calculation.summary(:period => period)
133
+
134
+ print_summaries(summaries)
135
+ end
136
+
137
+ def print_reformulated_income_statement(filing, report_type)
138
+ period = filing.income_statement.net_income_calculation.periods.yearly.last if report_type == :annual_report
139
+ period = filing.income_statement.net_income_calculation.periods.quarterly.last if report_type == :quarterly_report
140
+
141
+ reformed_inc_stmt = filing.income_statement.reformulated(period)
142
+
143
+ summaries = []
144
+ summaries << reformed_inc_stmt.gross_revenue
145
+ summaries << reformed_inc_stmt.income_from_sales_before_tax
146
+ summaries << reformed_inc_stmt.income_from_sales_after_tax
147
+ summaries << reformed_inc_stmt.operating_income_after_tax
148
+ summaries << reformed_inc_stmt.net_financing_income
149
+ summaries << reformed_inc_stmt.comprehensive_income
150
+
151
+ print_summaries(summaries)
152
+ end
153
+
154
+ def print_cash_flow_statement(filing, report_type)
155
+ period = filing.cash_flow_statement.periods.yearly.last if report_type == :annual_report
156
+ period = filing.cash_flow_statement.periods.quarterly.last if report_type == :quarterly_report
157
+ puts "Cash Flow Statement (#{period.to_pretty_s})"
158
+
159
+ summaries = []
160
+ summaries << filing.cash_flow_statement.cash_change_calculation.summary(:period => period)
161
+
162
+ print_summaries(summaries)
163
+ end
164
+
165
+ def print_reformulated_cash_flow_statement(filing, report_type)
166
+ period = filing.cash_flow_statement.periods.yearly.last if report_type == :annual_report
167
+ period = filing.cash_flow_statement.periods.quarterly.last if report_type == :quarterly_report
168
+
169
+ reformed_cash_flow_stmt = filing.cash_flow_statement.reformulated(period)
170
+
171
+ summaries = []
172
+ summaries << reformed_cash_flow_stmt.cash_from_operations
173
+ summaries << reformed_cash_flow_stmt.cash_investments_in_operations
174
+ summaries << reformed_cash_flow_stmt.payments_to_debtholders
175
+ summaries << reformed_cash_flow_stmt.payments_to_stockholders
176
+ summaries << reformed_cash_flow_stmt.free_cash_flow
177
+ summaries << reformed_cash_flow_stmt.financing_flows
178
+
179
+ print_summaries(summaries)
180
+ end
181
+
182
+ def print_disclosures(filing, report_type)
183
+ puts "Disclosures"
184
+
185
+ summaries = []
186
+ filing.disclosures.each do |disclosure|
187
+ summaries << disclosure.summary(:period => disclosure.periods.last)
188
+ end
189
+
190
+ print_summaries(summaries)
191
+ end
192
+
193
+ def print_summaries(summaries)
194
+ summaries.each do |summary|
195
+ summary.key_width = 60
196
+ summary.val_width = 18
197
+ summary.print
198
+ end
199
+ end
200
+
201
+
202
+
203
+ args = Arguments.parse(ARGV)
204
+ if args[:filing_url].nil?
205
+ args[:filing_url] = get_company_filing_url(args[:stock_symbol], args[:report_type], args[:report_offset])
206
+ end
207
+
208
+ filing = get_filing( args[:filing_url], args[:report_type])
209
+
210
+ print_balance_sheet( filing, args[:report_type])
211
+ print_reformulated_balance_sheet( filing, args[:report_type])
212
+ print_income_statement( filing, args[:report_type])
213
+ print_reformulated_income_statement( filing, args[:report_type])
214
+ print_cash_flow_statement( filing, args[:report_type])
215
+ print_reformulated_cash_flow_statement(filing, args[:report_type])
216
+ print_disclosures( filing, args[:report_type]) if args[:show_disclosures]
217
+
218
+ raise RuntimeError.new("filing is not valid") if !filing.is_valid?
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'finmodeling'
4
+
5
+ class Arguments
6
+ def self.show_usage_and_exit
7
+ puts "usage:"
8
+ puts "\t#{__FILE__} [options] <stock symbol> <start date, e.g. '2010-01-01'>"
9
+ puts
10
+ puts "\tOptions:"
11
+ puts "\t\t--num-forecasts <num>: how many periods to forecast"
12
+ puts "\t\t--no-cache: disable caching"
13
+ puts "\t\t--balance-detail: show details about the balance sheet calculation"
14
+ puts "\t\t--income-detail: show details about the net income calculation"
15
+ exit
16
+ end
17
+
18
+ def self.parse(args)
19
+ a = { :stock_symbol => nil, :start_date => nil, :num_forecasts => nil }
20
+
21
+ while args.any? && args.first =~ /^--/
22
+ case args.first.downcase
23
+ when '--no-cache'
24
+ FinModeling::Config.disable_caching
25
+ puts "Caching is #{FinModeling::Config.caching_enabled? ? "enabled" : "disabled"}"
26
+ when '--balance-detail'
27
+ FinModeling::Config.enable_balance_detail
28
+ puts "Balance sheet detail is #{FinModeling::Config.balance_detail_enabled? ? "enabled" : "disabled"}"
29
+ when '--income-detail'
30
+ FinModeling::Config.enable_income_detail
31
+ puts "Net income detail is #{FinModeling::Config.income_detail_enabled? ? "enabled" : "disabled"}"
32
+ when '--num-forecasts'
33
+ a[:num_forecasts] = args[1].to_i
34
+ self.show_usage_and_exit unless a[:num_forecasts] >= 1
35
+ puts "Forecasting #{a[:num_forecasts]} periods"
36
+ args = args[1..-1]
37
+ else
38
+ self.show_usage_and_exit
39
+ end
40
+ args = args[1..-1]
41
+ end
42
+
43
+ self.show_usage_and_exit if args.length != 2
44
+ a[:stock_symbol] = args[0]
45
+ a[:start_date] = Time.parse(args[1])
46
+
47
+ return a
48
+ end
49
+ end
50
+
51
+ args = Arguments.parse(ARGV)
52
+
53
+ company = FinModeling::Company.find(args[:stock_symbol])
54
+ raise RuntimeError.new("couldn't find company") if !company
55
+ puts "company name: #{company.name}"
56
+
57
+ filings = FinModeling::CompanyFilings.new(company.filings_since_date(args[:start_date]))
58
+ if filings.empty?
59
+ puts "No filings..."
60
+ exit
61
+ end
62
+
63
+ forecasts = filings.forecasts(filings.choose_forecasting_policy, num_quarters=args[:num_forecasts]) if args[:num_forecasts]
64
+
65
+ bs_analyses = filings.balance_sheet_analyses
66
+ bs_analyses += forecasts.balance_sheet_analyses(filings) if forecasts
67
+ bs_analyses.totals_row_enabled = false
68
+ bs_analyses.print
69
+ filings.balance_sheet_analyses.print_extras if filings.balance_sheet_analyses.respond_to?(:print_extras)
70
+
71
+ is_analyses = filings.income_statement_analyses
72
+ is_analyses += forecasts.income_statement_analyses(filings) if forecasts
73
+ is_analyses.totals_row_enabled = false
74
+ is_analyses.print
75
+ filings.income_statement_analyses.print_extras if filings.income_statement_analyses.respond_to?(:print_extras)
76
+
77
+ filings.cash_flow_statement_analyses.print
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/finmodeling/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Jim Lindstrom"]
6
+ gem.email = ["jim.lindstrom@gmail.com"]
7
+ gem.description = %q{A gem for manipulating XBRL financial filings}
8
+ gem.summary = %q{A gem for manipulating XBRL financial filings}
9
+ gem.homepage = "https://github.com/jimlindstrom/FinModeling"
10
+
11
+ gem.add_dependency("fileutils")
12
+ gem.add_dependency("sec_query")
13
+ gem.add_dependency("edgar")
14
+
15
+ gem.add_dependency("xbrlware-ruby19", "1.1.2.19.2")
16
+ gem.add_dependency("xbrlware-extras", "1.1.2.19.2")
17
+
18
+ gem.add_dependency("sec_query")
19
+ gem.add_dependency("naive_bayes")
20
+ gem.add_dependency("statsample")
21
+
22
+ gem.add_development_dependency("rspec", "2.5")
23
+ gem.add_development_dependency("rake")
24
+
25
+ gem.files = `git ls-files`.split($\)
26
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
27
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
28
+ gem.name = "finmodeling"
29
+ gem.require_paths = ["lib"]
30
+ gem.version = FinModeling::VERSION
31
+ end
@@ -0,0 +1,104 @@
1
+ module FinModeling
2
+
3
+ class AnnualReportFiling < CompanyFiling
4
+
5
+ CONSTRUCTOR_PATH = File.join(FinModeling::BASE_PATH, "constructors/")
6
+ SCHEMA_VERSION_ITEM = "@schema_version"
7
+ CURRENT_SCHEMA_VERSION = 1.1
8
+ # History:
9
+ # 1.0: initial version
10
+ # 1.1: added CFS to quarterly filings
11
+ # added disclosures
12
+ # renamed fake(.*)report to cached(.*)report
13
+
14
+ def self.download(url)
15
+ uid = url.split("/")[-2..-1].join('-').gsub(/\.[A-zA-z]*$/, '')
16
+ constructor_file = CONSTRUCTOR_PATH + uid + '.rb'
17
+ if File.exists?(constructor_file) && FinModeling::Config.caching_enabled?
18
+ begin
19
+ eval(File.read(constructor_file))
20
+ #puts "info: annual report, cache hit. schema version: #{@schema_version}"
21
+ return @filing if @schema_version == CURRENT_SCHEMA_VERSION
22
+ rescue
23
+ #puts "warn: annual report, cache hit. error eval'ing though."
24
+ end
25
+ end
26
+
27
+ filing = super(url)
28
+
29
+ FileUtils.mkdir_p(CONSTRUCTOR_PATH) if !File.exists?(CONSTRUCTOR_PATH)
30
+ file = File.open(constructor_file, "w")
31
+ filing.write_constructor(file, "@filing")
32
+ file.close
33
+
34
+ return filing
35
+ end
36
+
37
+ def balance_sheet
38
+ if @balance_sheet.nil?
39
+ calculations=@taxonomy.callb.calculation
40
+ bal_sheet = calculations.find{ |x| (x.clean_downcased_title =~ /statement.*financial.*position/) or
41
+ (x.clean_downcased_title =~ /statement.*financial.*condition/) or
42
+ (x.clean_downcased_title =~ /balance.*sheet/) }
43
+ if bal_sheet.nil?
44
+ raise RuntimeError.new("Couldn't find balance sheet in: " + calculations.map{ |x| "\"#{x.clean_downcased_title}\"" }.join("; "))
45
+ end
46
+
47
+ @balance_sheet = BalanceSheetCalculation.new(bal_sheet)
48
+ end
49
+ return @balance_sheet
50
+ end
51
+
52
+ def income_statement
53
+ if @income_stmt.nil?
54
+ calculations=@taxonomy.callb.calculation
55
+ inc_stmt = calculations.find{ |x| (x.clean_downcased_title =~ /statement.*operations/) or
56
+ (x.clean_downcased_title =~ /statement[s]*.*of.*earnings/) or
57
+ (x.clean_downcased_title =~ /statement[s]*.*of.*income/) or
58
+ (x.clean_downcased_title =~ /statement[s]*.*of.*net.*income/) }
59
+ if inc_stmt.nil?
60
+ raise RuntimeError.new("Couldn't find income statement in: " + calculations.map{ |x| "\"#{x.clean_downcased_title}\"" }.join("; "))
61
+ end
62
+
63
+ @income_stmt = IncomeStatementCalculation.new(inc_stmt)
64
+ end
65
+ return @income_stmt
66
+ end
67
+
68
+ def cash_flow_statement
69
+ if @cash_flow_stmt.nil?
70
+ calculations=@taxonomy.callb.calculation
71
+ cash_flow_stmt = calculations.find{ |x| (x.clean_downcased_title =~ /statement.*cash.*flows/) or
72
+ (x.clean_downcased_title =~ /^cash flows$/) }
73
+ if cash_flow_stmt.nil?
74
+ raise RuntimeError.new("Couldn't find cash flow statement in: " + calculations.map{ |x| "\"#{x.clean_downcased_title}\"" }.join("; "))
75
+ end
76
+
77
+ @cash_flow_stmt = CashFlowStatementCalculation.new(cash_flow_stmt)
78
+ end
79
+ return @cash_flow_stmt
80
+ end
81
+
82
+ def is_valid?
83
+ return (income_statement.is_valid? and balance_sheet.is_valid? and cash_flow_statement.is_valid?)
84
+ end
85
+
86
+ def write_constructor(file, item_name)
87
+ balance_sheet.write_constructor( file, bs_name = item_name + "_bs")
88
+ income_statement.write_constructor( file, is_name = item_name + "_is")
89
+ cash_flow_statement.write_constructor(file, cfs_name = item_name + "_cfs")
90
+
91
+ names_of_discs = []
92
+ disclosures.each_with_index do |disclosure, idx|
93
+ name_of_disc = item_name + "_disc#{idx}"
94
+ disclosure.write_constructor(file, name_of_disc)
95
+ names_of_discs << name_of_disc
96
+ end
97
+ names_of_discs_str = "[" + names_of_discs.join(',') + "]"
98
+
99
+ file.puts "#{SCHEMA_VERSION_ITEM} = #{CURRENT_SCHEMA_VERSION}"
100
+
101
+ file.puts "#{item_name} = FinModeling::CachedAnnualFiling.new(#{bs_name}, #{is_name}, #{cfs_name}, #{names_of_discs_str})"
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,22 @@
1
+ module FinModeling
2
+
3
+ class ArrayWithStats < Array
4
+ def mean
5
+ return nil if empty?
6
+ self.inject(:+) / self.length
7
+ end
8
+
9
+ def variance
10
+ x_sqrd = self.map{ |x| x*x }
11
+ x_sqrd_mean = (ArrayWithStats.new(x_sqrd).mean)
12
+ x_sqrd_mean - (mean**2)
13
+ end
14
+
15
+ def linear_regression
16
+ x = Array(0..(self.length-1)).to_scale
17
+ y = self.to_scale
18
+ Statsample::Regression.simple(x,y)
19
+ end
20
+ end
21
+
22
+ end
@@ -0,0 +1,36 @@
1
+ module FinModeling
2
+
3
+ class AssetsCalculation < CompanyFilingCalculation
4
+ include CanCacheClassifications
5
+ include CanCacheSummaries
6
+ include CanClassifyRows
7
+
8
+ BASE_FILENAME = File.join(FinModeling::BASE_PATH, "summaries/ai_")
9
+
10
+ ALL_STATES = [ :oa, :fa ]
11
+ NEXT_STATES = { nil => [ :oa, :fa ],
12
+ :oa => [ :oa, :fa ],
13
+ :fa => [ :oa, :fa ] }
14
+
15
+ def summary(args)
16
+ summary_cache_key = args[:period].to_pretty_s
17
+ thesummary = lookup_cached_summary(summary_cache_key)
18
+ return thesummary if !thesummary.nil?
19
+
20
+ mapping = Xbrlware::ValueMapping.new
21
+ mapping.policy[:credit] = :flip
22
+
23
+ thesummary = super(:period => args[:period], :mapping => mapping)
24
+ if !lookup_cached_classifications(BASE_FILENAME, thesummary.rows)
25
+ lookahead = [4, thesummary.rows.length-1].min
26
+ classify_rows(ALL_STATES, NEXT_STATES, thesummary.rows, FinModeling::AssetsItem, lookahead)
27
+ save_cached_classifications(BASE_FILENAME, thesummary.rows)
28
+ end
29
+
30
+ save_cached_summary(summary_cache_key, thesummary)
31
+
32
+ return thesummary
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,14 @@
1
+ module FinModeling
2
+ class AssetsItem < String
3
+ include HasStringClassifier
4
+
5
+ BASE_FILENAME = File.join(FinModeling::BASE_PATH, "classifiers/ai_")
6
+ TYPES = [ :oa, :fa ]
7
+
8
+ has_string_classifier(TYPES, AssetsItem)
9
+
10
+ def self.load_vectors_and_train
11
+ self._load_vectors_and_train(BASE_FILENAME, FinModeling::AssetsItem::TRAINING_VECTORS)
12
+ end
13
+ end
14
+ end