stock_index 0.8.3 → 0.8.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +33 -27
- data/bsym/.keep +0 -0
- data/bsym/JP.csv +3009 -2984
- data/bsym/LN.csv +362 -384
- data/bsym/US.csv +19969 -16631
- data/cache/.keep +0 -0
- data/cache/XJPX.pstore +0 -0
- data/cache/XLON.pstore +0 -0
- data/cache/XNAS.pstore +0 -0
- data/cache/XNYS.pstore +0 -0
- data/csv/.keep +0 -0
- data/csv/JP.csv +3676 -0
- data/csv/LN.csv +1838 -0
- data/csv/US.csv +19757 -0
- data/lib/stock_index/bsym_search.rb +0 -8
- data/lib/stock_index/component.rb +26 -21
- data/lib/stock_index/scrapers/base_scraper.rb +2 -2
- data/lib/stock_index/scrapers/ftse_scraper.rb +45 -3
- data/lib/stock_index/scrapers/nasdaq_scraper.rb +2 -1
- data/lib/stock_index/scrapers/nikkei_scraper.rb +4 -4
- data/lib/stock_index/symbol_parser.rb +8 -5
- data/lib/stock_index/version.rb +1 -1
- data/spec/stock_index/bsym_search_spec.rb +0 -8
- data/spec/stock_index/component_spec.rb +1 -1
- metadata +8 -3
- data/cache/test.pstore +0 -0
@@ -4,17 +4,9 @@ class StockIndex
|
|
4
4
|
|
5
5
|
require 'csv'
|
6
6
|
|
7
|
-
EXCEPTIONS = {
|
8
|
-
'BIDU' => {name: 'BAIDU INC', bbgid: 'BBG000QXWHD1'},
|
9
|
-
'LVNTA' => {name: 'LIBERTY VENTURES', bbgid: 'BBG0038K9G41'},
|
10
|
-
'VIP' => {name: 'VIMPELCOM LTD', bbgid: 'BBG000QCW561'},
|
11
|
-
'VOD' => {name: 'VODAFONE GROUP PLC', bbgid: 'BBG000C4R6H6'}
|
12
|
-
}
|
13
|
-
|
14
7
|
class << self
|
15
8
|
|
16
9
|
def find(symbol, pricing_source)
|
17
|
-
return {name: EXCEPTIONS[symbol][:name], bbgid: EXCEPTIONS[symbol][:bbgid]} if EXCEPTIONS.keys.include? symbol
|
18
10
|
CSV.foreach(files(pricing_source)) do |row|
|
19
11
|
return {name: row[1], bbgid: row[2]} if row[0] == symbol
|
20
12
|
end
|
@@ -12,11 +12,9 @@ class StockIndex
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def attributes
|
15
|
-
cache_lookup || attributes_lookup
|
16
|
-
|
17
|
-
|
18
|
-
def valid?
|
19
|
-
@market && @symbol
|
15
|
+
attrs = cache_lookup || attributes_lookup
|
16
|
+
puts "---- ERROR #{attrs}" unless valid?(attrs)
|
17
|
+
attrs
|
20
18
|
end
|
21
19
|
|
22
20
|
def cache_lookup
|
@@ -36,10 +34,20 @@ class StockIndex
|
|
36
34
|
end
|
37
35
|
|
38
36
|
def attributes_lookup
|
39
|
-
bsym =
|
37
|
+
bsym = StockIndex::BsymSearch.find(@symbol, @pricing_source)
|
40
38
|
cik = lookup_cik
|
39
|
+
puts " --- #{@symbol} bsym: #{bsym}"
|
40
|
+
puts " --- #{@symbol} cik: #{cik}"
|
41
41
|
return nil unless bsym
|
42
|
-
a = {
|
42
|
+
a = {
|
43
|
+
market: @market,
|
44
|
+
share: {
|
45
|
+
symbol: @symbol,
|
46
|
+
name: bsym[:name],
|
47
|
+
bbgid: bsym[:bbgid]
|
48
|
+
},
|
49
|
+
company: {wikipedia: @wikipedia}.merge( cik || {} )
|
50
|
+
}
|
43
51
|
cache_write(a)
|
44
52
|
a
|
45
53
|
end
|
@@ -48,16 +56,6 @@ class StockIndex
|
|
48
56
|
@pricing_source == :us
|
49
57
|
end
|
50
58
|
|
51
|
-
def lookup_bsym
|
52
|
-
bsym = StockIndex::BsymSearch.find(@symbol, @pricing_source)
|
53
|
-
if bsym
|
54
|
-
bsym
|
55
|
-
else
|
56
|
-
puts "bsym --> #{@symbol}" unless testing?
|
57
|
-
return nil
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
59
|
def lookup_cik
|
62
60
|
if us?
|
63
61
|
lookup_cik_us
|
@@ -69,15 +67,22 @@ class StockIndex
|
|
69
67
|
def lookup_cik_us
|
70
68
|
edgar = Cik.lookup(SymbolParser.new(@symbol).bsym_to_cik)
|
71
69
|
if edgar
|
72
|
-
|
70
|
+
{
|
71
|
+
cik: edgar[:cik],
|
72
|
+
name: edgar[:name],
|
73
|
+
sic: edgar[:sic]
|
74
|
+
}
|
73
75
|
else
|
74
|
-
puts "cik --> #{@symbol}" unless testing?
|
75
76
|
return nil
|
76
77
|
end
|
77
78
|
end
|
78
79
|
|
79
|
-
def
|
80
|
-
|
80
|
+
def valid?(attributes)
|
81
|
+
!attributes[:market].nil? &&
|
82
|
+
!attributes[:share][:symbol].nil? &&
|
83
|
+
!attributes[:share][:name].nil? &&
|
84
|
+
!attributes[:share][:bbgid].nil? &&
|
85
|
+
!attributes[:company][:wikipedia].nil?
|
81
86
|
end
|
82
87
|
|
83
88
|
end
|
@@ -10,7 +10,7 @@ class StockIndex
|
|
10
10
|
market = market(tr)
|
11
11
|
if symbol && market
|
12
12
|
component = StockIndex::Component.new(symbol, market, wikipedia_link(tr))
|
13
|
-
array << component.attributes
|
13
|
+
array << component.attributes
|
14
14
|
end
|
15
15
|
array
|
16
16
|
end
|
@@ -27,7 +27,7 @@ class StockIndex
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def build_wikipedia_link(wikipedia_path)
|
30
|
-
URI::
|
30
|
+
URI::Generic.new('https', nil, 'en.wikipedia.org', nil, nil, wikipedia_path, nil, nil, nil).to_s rescue nil
|
31
31
|
end
|
32
32
|
|
33
33
|
end
|
@@ -17,7 +17,7 @@ class FtseScraper < StockIndex::BaseScraper
|
|
17
17
|
market = 'XLON'
|
18
18
|
if symbol && market
|
19
19
|
component = StockIndex::Component.new(symbol, market, @wikipedia_hash[symbol], :ln)
|
20
|
-
array << component.attributes
|
20
|
+
array << component.attributes
|
21
21
|
end
|
22
22
|
array
|
23
23
|
end
|
@@ -26,7 +26,7 @@ class FtseScraper < StockIndex::BaseScraper
|
|
26
26
|
def symbol(tr)
|
27
27
|
symbol_td = td(tr, 0)
|
28
28
|
s = symbol_td ? symbol_td.text : nil
|
29
|
-
|
29
|
+
s.nil? ? nil : s.sub('.', '/')
|
30
30
|
end
|
31
31
|
|
32
32
|
def url(page)
|
@@ -41,7 +41,49 @@ class FtseScraper < StockIndex::BaseScraper
|
|
41
41
|
hash[symbol_td[1].text] = build_wikipedia_link(link_td.css('a').first.attributes['href'].value)
|
42
42
|
end
|
43
43
|
hash
|
44
|
-
end
|
44
|
+
end.merge(ftse_not_found_wikipedia_links)
|
45
|
+
end
|
46
|
+
|
47
|
+
def ftse_not_found_wikipedia_links
|
48
|
+
{
|
49
|
+
'III' => 'https://en.wikipedia.org/wiki/3i',
|
50
|
+
'AHT' => 'https://en.wikipedia.org/wiki/Ashtead_Group',
|
51
|
+
'AV/' => 'https://en.wikipedia.org/wiki/Aviva',
|
52
|
+
'BA/' => 'https://en.wikipedia.org/wiki/BAE_Systems',
|
53
|
+
'BDEV' => 'https://en.wikipedia.org/wiki/Barratt_Developments',
|
54
|
+
'BG/' => 'https://en.wikipedia.org/wiki/BG_Group',
|
55
|
+
'BP/' => 'https://en.wikipedia.org/wiki/BP',
|
56
|
+
'BATS' => 'https://en.wikipedia.org/wiki/British_American_Tobacco',
|
57
|
+
'BT/A' => 'https://en.wikipedia.org/wiki/BT_Group',
|
58
|
+
'CCL' => 'https://en.wikipedia.org/wiki/Carnival_Corporation_%26_plc',
|
59
|
+
'DLG' => 'https://en.wikipedia.org/wiki/Direct_Line_Group',
|
60
|
+
'DC/' => 'https://en.wikipedia.org/wiki/Dixons_Carphone',
|
61
|
+
'EZJ' => 'https://en.wikipedia.org/wiki/EasyJet',
|
62
|
+
'HL/' => 'https://en.wikipedia.org/wiki/Hargreaves_Lansdown',
|
63
|
+
'HIK' => 'https://en.wikipedia.org/wiki/Hikma_Pharmaceuticals',
|
64
|
+
'ISAT' => 'https://en.wikipedia.org/wiki/Inmarsat',
|
65
|
+
'INTU' => 'https://en.wikipedia.org/wiki/Intu_Properties',
|
66
|
+
'LSE' => 'https://en.wikipedia.org/wiki/London_Stock_Exchange_Group',
|
67
|
+
'MERL' => 'https://en.wikipedia.org/wiki/Merlin_Entertainments',
|
68
|
+
'MNDI' => 'https://en.wikipedia.org/wiki/Mondi',
|
69
|
+
'NG/' => 'https://en.wikipedia.org/wiki/National_Grid_plc',
|
70
|
+
'PSON' => 'https://en.wikipedia.org/wiki/Pearson_PLC',
|
71
|
+
'PSN' => 'https://en.wikipedia.org/wiki/Persimmon_plc',
|
72
|
+
'RDSB' => 'https://en.wikipedia.org/wiki/Royal_Dutch_Shell',
|
73
|
+
'RB/' => 'https://en.wikipedia.org/wiki/Reckitt_Benckiser',
|
74
|
+
'RR/' => 'https://en.wikipedia.org/wiki/Rolls-Royce_Holdings',
|
75
|
+
'RMG' => 'https://en.wikipedia.org/wiki/Royal_Mail',
|
76
|
+
'SHP' => 'https://en.wikipedia.org/wiki/Shire_(pharmaceutical_company)',
|
77
|
+
'SKY' => 'https://en.wikipedia.org/wiki/Sky_plc',
|
78
|
+
'SN/' => 'https://en.wikipedia.org/wiki/Smith_%26_Nephew',
|
79
|
+
'SPD' => 'https://en.wikipedia.org/wiki/Sports_Direct',
|
80
|
+
'STJ' => 'https://en.wikipedia.org/wiki/St._James%27s_Place_plc',
|
81
|
+
'SL/' => 'https://en.wikipedia.org/wiki/Standard_Life',
|
82
|
+
'TW/' => 'https://en.wikipedia.org/wiki/Taylor_Wimpey',
|
83
|
+
'TPK' => 'https://en.wikipedia.org/wiki/Travis_Perkins',
|
84
|
+
'TUI' => 'https://en.wikipedia.org/wiki/TUI_Group',
|
85
|
+
'UU/' => 'https://en.wikipedia.org/wiki/United_Utilities'
|
86
|
+
}
|
45
87
|
end
|
46
88
|
|
47
89
|
end
|
@@ -8,10 +8,11 @@ class NasdaqScraper < StockIndex::BaseScraper
|
|
8
8
|
def parse_rows(rows)
|
9
9
|
rows.inject([]) do |array, li|
|
10
10
|
symbol = /.+\((\w+)\)/.match(li)[1]
|
11
|
+
symbol = 'SWKS' if symbol == 'SKWS' # wikipedia erratum
|
11
12
|
market = 'XNAS'
|
12
13
|
if symbol && market
|
13
14
|
component = StockIndex::Component.new(symbol, market, wikipedia(li))
|
14
|
-
array << component.attributes
|
15
|
+
array << component.attributes
|
15
16
|
end
|
16
17
|
array
|
17
18
|
end
|
@@ -14,18 +14,18 @@ class NikkeiScraper < StockIndex::BaseScraper
|
|
14
14
|
market = 'XJPX'
|
15
15
|
if symbol && market
|
16
16
|
component = StockIndex::Component.new(symbol, market, @wikipedia_hash[symbol], :jp)
|
17
|
-
array << component.attributes
|
17
|
+
array << component.attributes
|
18
18
|
end
|
19
19
|
array
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
23
|
def parse_wikipedia_page(wikipedia_doc)
|
24
|
-
wikipedia_doc.css('
|
25
|
-
md =
|
24
|
+
wikipedia_doc.css('#constituents tr').inject({}) do |hash, tr|
|
25
|
+
md = tr.text.match(/\n(\d{4})\n/)
|
26
26
|
if md
|
27
27
|
symbol = md[1]
|
28
|
-
link = build_wikipedia_link(
|
28
|
+
link = build_wikipedia_link(tr.css('a').first.attributes['href'].value)
|
29
29
|
hash[symbol] = link
|
30
30
|
end
|
31
31
|
hash
|
@@ -6,7 +6,7 @@ class SymbolParser
|
|
6
6
|
|
7
7
|
def symbol_to_bsym
|
8
8
|
if @symbol
|
9
|
-
@symbol.sub('
|
9
|
+
@symbol.sub('-', '/')
|
10
10
|
else
|
11
11
|
nil
|
12
12
|
end
|
@@ -20,12 +20,15 @@ class SymbolParser
|
|
20
20
|
# BF/B (Brown-Forman Corp)
|
21
21
|
when 'BF/B'
|
22
22
|
'0000014693'
|
23
|
+
# QRVO (Qorvo, Inc.)
|
24
|
+
# when 'QRVO'
|
25
|
+
# '0001604778'
|
23
26
|
# QVCA (Liberty Interactive Corp)
|
24
|
-
when 'QVCA'
|
25
|
-
|
27
|
+
# when 'QVCA'
|
28
|
+
# '0001355096'
|
26
29
|
# LMCK (Liberty Media Corp)
|
27
|
-
when 'LMCK'
|
28
|
-
|
30
|
+
# when 'LMCK'
|
31
|
+
# '0001560385'
|
29
32
|
else
|
30
33
|
@symbol
|
31
34
|
end
|
data/lib/stock_index/version.rb
CHANGED
@@ -2,14 +2,6 @@ require 'helper'
|
|
2
2
|
|
3
3
|
describe StockIndex::BsymSearch do
|
4
4
|
|
5
|
-
context 'searching a symbol in EXCEPTIONS' do
|
6
|
-
|
7
|
-
it 'returns the component' do
|
8
|
-
expect(StockIndex::BsymSearch.find('BIDU', :us)).to eq({name: 'BAIDU INC', bbgid: 'BBG000QXWHD1'})
|
9
|
-
end
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
5
|
context 'searching a symbol in the CSV file' do
|
14
6
|
|
15
7
|
it 'returns the component' do
|
@@ -10,7 +10,7 @@ describe StockIndex::Component do
|
|
10
10
|
|
11
11
|
it 'returns the correct attributes with a valid symbol' do
|
12
12
|
component = StockIndex::Component.new('CSCO', 'XNAS', nil)
|
13
|
-
expect(component.attributes_lookup).to eq({:market=>"XNAS", :symbol=>"CSCO", :name=>"CISCO SYSTEMS INC", :wikipedia=>nil, :cik=>"0000858877", :
|
13
|
+
expect(component.attributes_lookup).to eq({:market=>"XNAS", :share=>{:symbol=>"CSCO", :name=>"CISCO SYSTEMS INC", :bbgid=>"BBG000C3J3C9"}, :company=>{:wikipedia=>nil, :cik=>"0000858877", :name=>"CISCO SYSTEMS, INC.", :sic=>"3576"}})
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'returns nil with an invalid symbol' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stock_index
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Javier Vidal
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -153,14 +153,19 @@ files:
|
|
153
153
|
- LICENSE.txt
|
154
154
|
- README.md
|
155
155
|
- Rakefile
|
156
|
+
- bsym/.keep
|
156
157
|
- bsym/JP.csv
|
157
158
|
- bsym/LN.csv
|
158
159
|
- bsym/US.csv
|
160
|
+
- cache/.keep
|
159
161
|
- cache/XJPX.pstore
|
160
162
|
- cache/XLON.pstore
|
161
163
|
- cache/XNAS.pstore
|
162
164
|
- cache/XNYS.pstore
|
163
|
-
-
|
165
|
+
- csv/.keep
|
166
|
+
- csv/JP.csv
|
167
|
+
- csv/LN.csv
|
168
|
+
- csv/US.csv
|
164
169
|
- lib/stock_index.rb
|
165
170
|
- lib/stock_index/bsym_search.rb
|
166
171
|
- lib/stock_index/component.rb
|
data/cache/test.pstore
DELETED
Binary file
|