figa 0.0.1 → 0.1.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -1
- data/README.md +107 -0
- data/lib/figa.rb +57 -38
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6711826553277276616030f1bd03f3661fdb4f2d
|
4
|
+
data.tar.gz: 839c8010b513be67b475ddc66faab9e046d27b60
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f5710c727d6a221f0d846574ae75d81fe0d51ad8b690480e9c163025b0cf17c61d6bc4c6519158bc1080dae98170555ee33a263bc3696ff4bb0ecc292936750
|
7
|
+
data.tar.gz: 1210ffc9cff8af805336b6ec2be04b2c5e2ab2067a1e9369816ed41b25e5720c9d9f1ac17f3c0d576b12a79188a89f2d4f5590aa531d11bf0b8f26f83eb84585
|
data/CHANGELOG.md
CHANGED
@@ -2,7 +2,14 @@
|
|
2
2
|
# CHANGELOG.md
|
3
3
|
|
4
4
|
|
5
|
-
##
|
5
|
+
## figa 0.1.0 released 2019-06-14
|
6
|
+
|
7
|
+
* Refine Figa::Client #map and #search
|
8
|
+
* Provide #next for #search results
|
9
|
+
* Use API key if provided to Figa::Client.new
|
10
|
+
|
11
|
+
|
12
|
+
## figa 0.0.1 released 2019-06-13
|
6
13
|
|
7
14
|
* Initial release
|
8
15
|
|
data/README.md
CHANGED
@@ -1,11 +1,118 @@
|
|
1
1
|
|
2
2
|
# figa
|
3
3
|
|
4
|
+
[](http://badge.fury.io/rb/figa)
|
5
|
+
|
4
6
|
A Ruby library to query [OpenFIGI](https://www.openfigi.com/) API v2.
|
5
7
|
|
6
8
|
|
7
9
|
## usage
|
8
10
|
|
11
|
+
Instantiate a Figa client:
|
12
|
+
```ruby
|
13
|
+
client = Figa::Client.new
|
14
|
+
#
|
15
|
+
# instantiate a client without API key
|
16
|
+
|
17
|
+
client = Figa::Client.new('321456cd-af64-9932-bcbe-1a2345677999')
|
18
|
+
#
|
19
|
+
# instantiate a client with an API key
|
20
|
+
```
|
21
|
+
|
22
|
+
Query for mappings ([/v2/mapping](https://www.openfigi.com/api#post-v2-mapping)):
|
23
|
+
```ruby
|
24
|
+
client = Figa::Client.new
|
25
|
+
|
26
|
+
r = client.map(isin: 'US4592001014')
|
27
|
+
|
28
|
+
pp r
|
29
|
+
# ==>
|
30
|
+
# [{"data"=>
|
31
|
+
# [{"figi"=>"BBG000BLNNH6",
|
32
|
+
# "name"=>"INTL BUSINESS MACHINES CORP",
|
33
|
+
# "ticker"=>"IBM",
|
34
|
+
# "exchCode"=>"US",
|
35
|
+
# "compositeFIGI"=>"BBG000BLNNH6",
|
36
|
+
# "uniqueID"=>"EQ0010080100001000",
|
37
|
+
# "securityType"=>"Common Stock",
|
38
|
+
# "marketSector"=>"Equity",
|
39
|
+
# "shareClassFIGI"=>"BBG001S5S399",
|
40
|
+
# "uniqueIDFutOpt"=>nil,
|
41
|
+
# "securityType2"=>"Common Stock",
|
42
|
+
# "securityDescription"=>"IBM"},
|
43
|
+
# {"figi"=>"BBG000BLNNV0",
|
44
|
+
# "name"=>"INTL BUSINESS MACHINES CORP",
|
45
|
+
# "ticker"=>"IBM",
|
46
|
+
# "exchCode"=>"UA",
|
47
|
+
# "compositeFIGI"=>"BBG000BLNNH6",
|
48
|
+
# "uniqueID"=>"EQ0010080100001000",
|
49
|
+
# "securityType"=>"Common Stock",
|
50
|
+
# "marketSector"=>"Equity",
|
51
|
+
# "shareClassFIGI"=>"BBG001S5S399",
|
52
|
+
# "uniqueIDFutOpt"=>nil,
|
53
|
+
# "securityType2"=>"Common Stock",
|
54
|
+
# "securityDescription"=>"IBM"},
|
55
|
+
# ...
|
56
|
+
|
57
|
+
r = client.map(isin: 'US4592001014', exchCode: 'US')
|
58
|
+
r = client.map(idType: 'ID_ISIN', idValue: 'US4592001014', exchCode: 'US')
|
59
|
+
|
60
|
+
# one can query for multiple items
|
61
|
+
r = client.map([
|
62
|
+
{ isin: 'US4592001014' },
|
63
|
+
{ idType: 'ID_WERTPAPIER', idValue: '851399', exchCode: 'US' } ])
|
64
|
+
```
|
65
|
+
|
66
|
+
Query for search ([/v2/search](https://www.openfigi.com/api#post-v2-search)):
|
67
|
+
```ruby
|
68
|
+
r = client.search('ibm')
|
69
|
+
r = client.search(query: 'ibm')
|
70
|
+
r = client.search('ibm', exchCode: 'US')
|
71
|
+
r = client.search(query: 'ibm', exchCode: 'US')
|
72
|
+
|
73
|
+
pp r
|
74
|
+
# ==>
|
75
|
+
# {"data"=>
|
76
|
+
# [{"figi"=>"BBG00196W5Z9",
|
77
|
+
# "name"=>"Ibm",
|
78
|
+
# "ticker"=>"IBMD=4",
|
79
|
+
# "exchCode"=>"OC",
|
80
|
+
# "compositeFIGI"=>nil,
|
81
|
+
# "uniqueID"=>"EF12901854300074186897",
|
82
|
+
# "securityType"=>"DIVIDEND NEUTRAL STOCK FUTURE",
|
83
|
+
# "marketSector"=>"Equity",
|
84
|
+
# "shareClassFIGI"=>nil,
|
85
|
+
# "uniqueIDFutOpt"=>"IBMD=4 OC Equity",
|
86
|
+
# "securityType2"=>"Future",
|
87
|
+
# "securityDescription"=>"IBMD=4"},
|
88
|
+
# {"figi"=>"BBG00196W5Y0",
|
89
|
+
# "name"=>"Ibm",
|
90
|
+
# "ticker"=>"IBMD=3",
|
91
|
+
# "exchCode"=>"OC",
|
92
|
+
# "compositeFIGI"=>nil,
|
93
|
+
# "uniqueID"=>"EF12901854290074186860",
|
94
|
+
# "securityType"=>"DIVIDEND NEUTRAL STOCK FUTURE",
|
95
|
+
# "marketSector"=>"Equity",
|
96
|
+
# "shareClassFIGI"=>nil,
|
97
|
+
# "uniqueIDFutOpt"=>"IBMD=3 OC Equity",
|
98
|
+
# "securityType2"=>"Future",
|
99
|
+
# "securityDescription"=>"IBMD=3"},
|
100
|
+
# ...
|
101
|
+
```
|
102
|
+
|
103
|
+
Search and `#next`:
|
104
|
+
```ruby
|
105
|
+
r = client.search('ibm')
|
106
|
+
#
|
107
|
+
# grab the first "page" of results
|
108
|
+
|
109
|
+
r = r.next
|
110
|
+
#
|
111
|
+
# grab the next page of results
|
112
|
+
|
113
|
+
# ...
|
114
|
+
```
|
115
|
+
|
9
116
|
|
10
117
|
## license
|
11
118
|
|
data/lib/figa.rb
CHANGED
@@ -5,7 +5,7 @@ require 'net/http'
|
|
5
5
|
|
6
6
|
module Figa
|
7
7
|
|
8
|
-
VERSION = '0.0
|
8
|
+
VERSION = '0.1.0'
|
9
9
|
|
10
10
|
USER_AGENT = "Figa - https://github.com/jmettraux/figa - #{VERSION}"
|
11
11
|
API_ROOT_URI = 'https://api.openfigi.com/v2'
|
@@ -18,28 +18,16 @@ module Figa
|
|
18
18
|
@enum_values = {}
|
19
19
|
end
|
20
20
|
|
21
|
-
def map(
|
21
|
+
def map(array_or_hash)
|
22
22
|
|
23
|
-
|
23
|
+
a = to_mapping_parameter_array(array_or_hash)
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
h = { idType: h.keys.first, idValue: h.values.first }
|
28
|
-
end
|
29
|
-
|
30
|
-
validate(h)
|
31
|
-
|
32
|
-
fail ArgumentError.new("parameter 'idType' is missing"
|
33
|
-
) unless h[:idType] || h['idType']
|
34
|
-
fail ArgumentError.new("parameter 'idValue' is missing"
|
35
|
-
) unless h[:idValue] || h['idValue']
|
36
|
-
|
37
|
-
post('/mapping', h)
|
25
|
+
post('/mapping', a)
|
38
26
|
end
|
39
27
|
|
40
|
-
def search(h)
|
28
|
+
def search(q, h={})
|
41
29
|
|
42
|
-
h =
|
30
|
+
h = q.is_a?(String) ? h.merge(query: q) : q
|
43
31
|
|
44
32
|
validate(h)
|
45
33
|
|
@@ -51,35 +39,56 @@ module Figa
|
|
51
39
|
|
52
40
|
protected
|
53
41
|
|
54
|
-
|
55
|
-
|
42
|
+
def to_mapping_parameter_array(aoh)
|
43
|
+
|
44
|
+
a = aoh.is_a?(Array) ? aoh : [ aoh ]
|
45
|
+
|
46
|
+
id_types = enum_values('idType')
|
56
47
|
|
57
|
-
|
48
|
+
a.collect do |h|
|
58
49
|
|
59
|
-
|
60
|
-
|
61
|
-
|
50
|
+
oldk, itk =
|
51
|
+
h.keys.inject(nil) { |r, k|
|
52
|
+
next r if r
|
53
|
+
kk = k.upcase; next [ k, kk ] if id_types.include?(kk)
|
54
|
+
kk = "ID_#{kk}"; next [ k, kk ] if id_types.include?(kk)
|
55
|
+
nil }
|
56
|
+
if oldk
|
57
|
+
h[:idType] = itk
|
58
|
+
h[:idValue] = h.delete(oldk)
|
59
|
+
end
|
62
60
|
|
63
|
-
|
61
|
+
validate(h)
|
62
|
+
|
63
|
+
fail ArgumentError.new("parameter 'idType' is missing"
|
64
|
+
) unless h[:idType] || h['idType']
|
65
|
+
fail ArgumentError.new("parameter 'idValue' is missing"
|
66
|
+
) unless h[:idValue] || h['idValue']
|
67
|
+
|
68
|
+
h
|
69
|
+
end
|
64
70
|
end
|
65
71
|
|
72
|
+
ENUM_KEYS = %w[
|
73
|
+
idType exchCode micCode currency marketSecDes securityType securityType2 ]
|
74
|
+
|
66
75
|
def enum_values(key)
|
67
76
|
|
68
|
-
@enum_values[key] ||=
|
77
|
+
@enum_values[key] ||= get('/mapping/values/' + key)['values']
|
69
78
|
end
|
70
79
|
|
71
80
|
def validate(h)
|
72
81
|
|
82
|
+
fail ArgumentError.new("#{h.inspect} is not a Hash") unless h.is_a?(Hash)
|
83
|
+
|
73
84
|
h.each do |k, v|
|
74
85
|
|
75
86
|
sk = k.to_s
|
76
87
|
next unless ENUM_KEYS.include?(sk)
|
77
88
|
|
78
|
-
vs = (@enum_values[sk] ||= list_enum_values(key))
|
79
|
-
|
80
89
|
fail ArgumentError.new(
|
81
90
|
"value #{v.inspect} is not a valid value for key #{k.inspect}"
|
82
|
-
) unless enum_values(
|
91
|
+
) unless enum_values(sk).include?(v)
|
83
92
|
end
|
84
93
|
end
|
85
94
|
|
@@ -88,7 +97,7 @@ module Figa
|
|
88
97
|
|
89
98
|
def request(method, uri, data=nil)
|
90
99
|
|
91
|
-
uri = API_ROOT_URI + uri
|
100
|
+
uri = API_ROOT_URI + uri unless uri.match(/\Ahttps:\/\//)
|
92
101
|
|
93
102
|
req = (method == :post ? Net::HTTP::Post : Net::HTTP::Get).new(uri)
|
94
103
|
req.instance_eval { @header.clear }
|
@@ -101,7 +110,7 @@ module Figa
|
|
101
110
|
|
102
111
|
req.set_header('User-Agent', USER_AGENT)
|
103
112
|
req.set_header('Accept', 'application/json')
|
104
|
-
|
113
|
+
req.set_header('X-OPENFIGI-APIKEY', @api_key) if @api_key
|
105
114
|
|
106
115
|
u = URI(uri)
|
107
116
|
|
@@ -110,17 +119,27 @@ module Figa
|
|
110
119
|
t = Net::HTTP.new(u.host, u.port)
|
111
120
|
t.use_ssl = (u.scheme == 'https')
|
112
121
|
#t.set_debug_output($stdout)
|
113
|
-
#t.set_debug_output($stdout) if
|
122
|
+
#t.set_debug_output($stdout) if uri.match(/search/)
|
114
123
|
|
115
124
|
res = t.request(req)
|
116
125
|
|
117
|
-
#class << res; attr_accessor :_elapsed; end
|
118
|
-
#res._elapsed = monow - t0
|
119
|
-
|
120
126
|
j = JSON.parse(res.body)
|
121
|
-
|
122
|
-
|
123
|
-
|
127
|
+
#
|
128
|
+
class << j
|
129
|
+
attr_accessor :_response, :_client, :_elapsed, :_method, :_uri, :_form
|
130
|
+
end
|
131
|
+
#
|
132
|
+
j._response = res
|
133
|
+
j._client = self
|
134
|
+
j._elapsed = monow - t0
|
135
|
+
j._method = method
|
136
|
+
j._uri = uri
|
137
|
+
j._form = data
|
138
|
+
#
|
139
|
+
def j.next
|
140
|
+
n = self['next']; return nil unless n && n.is_a?(String)
|
141
|
+
_client.send(:request, _method, _uri, _form.merge(start: n))
|
142
|
+
end if j.is_a?(Hash)
|
124
143
|
|
125
144
|
j
|
126
145
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: figa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Mettraux
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-06-
|
11
|
+
date: 2019-06-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|