figa 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/figa.svg)](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
|