finmodeling 0.1

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