figa 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -1
  3. data/README.md +107 -0
  4. data/lib/figa.rb +57 -38
  5. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0730264f5ad57b4adcf105062fa9aa2396710067
4
- data.tar.gz: 882c6230a5d0b42cf50874f78904259f5ba5e820
3
+ metadata.gz: 6711826553277276616030f1bd03f3661fdb4f2d
4
+ data.tar.gz: 839c8010b513be67b475ddc66faab9e046d27b60
5
5
  SHA512:
6
- metadata.gz: ab01ea02cff6dc17a967b4b59e1ee1869b94b419df57ca0fb4090d9df7f3dc787bc66119a62c56726a536e4feec8b956a95388d26591f53345e06685b0ddad19
7
- data.tar.gz: 625d7b5399b4cdf8ee8cabac46990ad147532a634ef8773c4f470c82bd1352b1ff79ee3efde46c01a25ba429f0257e750f98b01fc02d0ce5ba679410bbcea655
6
+ metadata.gz: 7f5710c727d6a221f0d846574ae75d81fe0d51ad8b690480e9c163025b0cf17c61d6bc4c6519158bc1080dae98170555ee33a263bc3696ff4bb0ecc292936750
7
+ data.tar.gz: 1210ffc9cff8af805336b6ec2be04b2c5e2ab2067a1e9369816ed41b25e5720c9d9f1ac17f3c0d576b12a79188a89f2d4f5590aa531d11bf0b8f26f83eb84585
@@ -2,7 +2,14 @@
2
2
  # CHANGELOG.md
3
3
 
4
4
 
5
- ## sentofu 0.0.1 released 2019-06-13
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
 
@@ -5,7 +5,7 @@ require 'net/http'
5
5
 
6
6
  module Figa
7
7
 
8
- VERSION = '0.0.1'
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(h)
21
+ def map(array_or_hash)
22
22
 
23
- k0 = h.is_a?(Hash) ? h.keys.first.to_s : nil
23
+ a = to_mapping_parameter_array(array_or_hash)
24
24
 
25
- if k0 && h.size == 1 && enum_values('idType').include?(k0)
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 = { query: h } unless h.is_a?(Hash)
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
- ENUM_KEYS = %w[
55
- idType exchCode micCode currency marketSecDes securityType securityType2 ]
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
- def list_enum_values(key)
48
+ a.collect do |h|
58
49
 
59
- #fail ArgumentError.new(
60
- # "key #{key.inspect} not included in #{KEYS.inspect}"
61
- #) unless KEYS.include?(key)
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
- get('/mapping/values/' + key)
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] ||= list_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(keys).include?(v)
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
- # TODO api key
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 u.to_s.match(/search/)
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
- def j._response; res; end
122
- j['_elapsed'] = monow - t0
123
- # TODO j['next']
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.1
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-13 00:00:00.000000000 Z
11
+ date: 2019-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec