intrinio-realtime 2.0.0 → 2.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/lib/intrinio-realtime.rb +77 -21
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a230dd8a59f925f023ddde64d91f7d6c33e40ecb
|
4
|
+
data.tar.gz: d6fe3f0b65ececa7e939d036d9bdf7322b396737
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 194bf4c83eda268fcd8df8e522588e326027aeb23e9f769bf608bedcf4538414bd8e9849b669d9e94f84f18731c484fb146c2d678f802f2caccb2df92bdc9147
|
7
|
+
data.tar.gz: e5170c7f944938e482f8a205c3694cd137faa277a07834b199df81a41ab760ab60e40b5859cde468adbc46458f760e6937f9a073f9933a585e9940a0d5791b39
|
data/lib/intrinio-realtime.rb
CHANGED
@@ -7,10 +7,11 @@ require 'websocket-client-simple'
|
|
7
7
|
module Intrinio
|
8
8
|
module Realtime
|
9
9
|
HEARTBEAT_TIME = 3
|
10
|
-
SELF_HEAL_BACKOFFS = [0,100,500,1000,2000,5000]
|
11
|
-
IEX = "iex"
|
12
|
-
QUODD = "quodd"
|
13
|
-
|
10
|
+
SELF_HEAL_BACKOFFS = [0, 100, 500, 1000, 2000, 5000].freeze
|
11
|
+
IEX = "iex".freeze
|
12
|
+
QUODD = "quodd".freeze
|
13
|
+
CRYPTOQUOTE = "cryptoquote".freeze
|
14
|
+
PROVIDERS = [IEX, QUODD, CRYPTOQUOTE].freeze
|
14
15
|
|
15
16
|
def self.connect(options, &b)
|
16
17
|
EM.run do
|
@@ -21,16 +22,22 @@ module Intrinio
|
|
21
22
|
end
|
22
23
|
|
23
24
|
class Client
|
25
|
+
|
24
26
|
def initialize(options)
|
25
27
|
raise "Options parameter is required" if options.nil? || !options.is_a?(Hash)
|
26
|
-
|
27
|
-
@
|
28
|
-
@
|
29
|
-
|
30
|
-
|
28
|
+
|
29
|
+
@api_key = options[:api_key]
|
30
|
+
raise "API Key was formatted invalidly." if @api_key && !valid_api_key?(@api_key)
|
31
|
+
|
32
|
+
unless @api_key
|
33
|
+
@username = options[:username]
|
34
|
+
@password = options[:password]
|
35
|
+
raise "API Key or Username and password are required" if @username.nil? || @username.empty? || @password.nil? || @password.empty?
|
36
|
+
end
|
37
|
+
|
31
38
|
@provider = options[:provider]
|
32
39
|
raise "Provider must be 'quodd' or 'iex'" unless PROVIDERS.include?(@provider)
|
33
|
-
|
40
|
+
|
34
41
|
@channels = []
|
35
42
|
@channels = parse_channels(options[:channels]) if options[:channels]
|
36
43
|
bad_channels = @channels.select{|x| !x.is_a?(String)}
|
@@ -44,7 +51,7 @@ module Intrinio
|
|
44
51
|
@logger = Logger.new($stdout)
|
45
52
|
@logger.level = Logger::INFO
|
46
53
|
end
|
47
|
-
|
54
|
+
|
48
55
|
@quotes = EventMachine::Channel.new
|
49
56
|
@ready = false
|
50
57
|
@joined_channels = []
|
@@ -53,7 +60,7 @@ module Intrinio
|
|
53
60
|
@selfheal_backoffs = Array.new(SELF_HEAL_BACKOFFS)
|
54
61
|
@ws = nil
|
55
62
|
end
|
56
|
-
|
63
|
+
|
57
64
|
def provider
|
58
65
|
@provider
|
59
66
|
end
|
@@ -124,32 +131,55 @@ module Intrinio
|
|
124
131
|
|
125
132
|
def refresh_token
|
126
133
|
@token = nil
|
127
|
-
|
128
|
-
|
134
|
+
|
135
|
+
if @api_key
|
136
|
+
response = HTTP.get(auth_url)
|
137
|
+
else
|
138
|
+
response = HTTP.basic_auth(:user => @username, :pass => @password).get(auth_url)
|
139
|
+
end
|
140
|
+
|
129
141
|
return fatal("Unable to authorize") if response.status == 401
|
130
142
|
return fatal("Could not get auth token") if response.status != 200
|
131
|
-
|
143
|
+
|
132
144
|
@token = response.body
|
133
145
|
debug "Token refreshed"
|
134
146
|
end
|
135
147
|
|
136
148
|
def auth_url
|
149
|
+
url = ""
|
150
|
+
|
137
151
|
case @provider
|
138
|
-
when IEX then "https://realtime.intrinio.com/auth"
|
139
|
-
when QUODD then "https://api.intrinio.com/token?type=QUODD"
|
152
|
+
when IEX then url = "https://realtime.intrinio.com/auth"
|
153
|
+
when QUODD then url = "https://api.intrinio.com/token?type=QUODD"
|
154
|
+
when CRYPTOQUOTE then url = "https://crypto.intrinio.com/auth"
|
140
155
|
end
|
156
|
+
|
157
|
+
url = api_auth_url(url) if @api_key
|
158
|
+
|
159
|
+
url
|
141
160
|
end
|
142
|
-
|
161
|
+
|
162
|
+
def api_auth_url(url)
|
163
|
+
if @api_key.include? "?"
|
164
|
+
url = "#{url}&"
|
165
|
+
else
|
166
|
+
url = "#{url}?"
|
167
|
+
end
|
168
|
+
|
169
|
+
"#{url}api_key=#{@api_key}"
|
170
|
+
end
|
171
|
+
|
143
172
|
def socket_url
|
144
173
|
case @provider
|
145
174
|
when IEX then URI.escape("wss://realtime.intrinio.com/socket/websocket?vsn=1.0.0&token=#{@token}")
|
146
175
|
when QUODD then URI.escape("wss://www5.quodd.com/websocket/webStreamer/intrinio/#{@token}")
|
176
|
+
when CRYPTOQUOTE then URI.escape("wss://crypto.intrinio.com/socket/websocket?vsn=1.0.0&token=#{@token}")
|
147
177
|
end
|
148
178
|
end
|
149
|
-
|
179
|
+
|
150
180
|
def refresh_websocket
|
151
181
|
me = self
|
152
|
-
|
182
|
+
|
153
183
|
@ws.close() unless @ws.nil?
|
154
184
|
@ready = false
|
155
185
|
@joined_channels = []
|
@@ -160,7 +190,7 @@ module Intrinio
|
|
160
190
|
ws.on :open do
|
161
191
|
me.send :info, "Connection established"
|
162
192
|
me.send :ready, true
|
163
|
-
if me.send(:provider) == IEX
|
193
|
+
if me.send(:provider) == IEX || me.send(:provider) == CRYPTOQUOTE
|
164
194
|
me.send :refresh_channels
|
165
195
|
end
|
166
196
|
me.send :start_heartbeat
|
@@ -185,6 +215,10 @@ module Intrinio
|
|
185
215
|
elsif json["event"] == "quote" || json["event"] == "trade"
|
186
216
|
json["data"]
|
187
217
|
end
|
218
|
+
when CRYPTOQUOTE
|
219
|
+
if json["event"] == "book_update" || json["event"] == "ticker" || json["event"] == "trade"
|
220
|
+
json["payload"]
|
221
|
+
end
|
188
222
|
end
|
189
223
|
|
190
224
|
if quote && quote.is_a?(Hash)
|
@@ -245,6 +279,7 @@ module Intrinio
|
|
245
279
|
case @provider
|
246
280
|
when IEX then {topic: 'phoenix', event: 'heartbeat', payload: {}, ref: nil}.to_json
|
247
281
|
when QUODD then {event: 'heartbeat', data: {action: 'heartbeat', ticker: (Time.now.to_f * 1000).to_i}}.to_json
|
282
|
+
when CRYPTOQUOTE then {topic: 'phoenix', event: 'heartbeat', payload: {}, ref: nil}.to_json
|
248
283
|
end
|
249
284
|
end
|
250
285
|
|
@@ -341,6 +376,13 @@ module Intrinio
|
|
341
376
|
action: "subscribe"
|
342
377
|
}
|
343
378
|
}
|
379
|
+
when CRYPTOQUOTE
|
380
|
+
{
|
381
|
+
topic: channel,
|
382
|
+
event: "phx_join",
|
383
|
+
payload: {},
|
384
|
+
ref: nil
|
385
|
+
}
|
344
386
|
end
|
345
387
|
end
|
346
388
|
|
@@ -361,8 +403,22 @@ module Intrinio
|
|
361
403
|
action: "unsubscribe"
|
362
404
|
}
|
363
405
|
}
|
406
|
+
when CRYPTOQUOTE
|
407
|
+
{
|
408
|
+
topic: channel,
|
409
|
+
event: "phx_leave",
|
410
|
+
payload: {},
|
411
|
+
ref: nil
|
412
|
+
}
|
364
413
|
end
|
365
414
|
end
|
415
|
+
|
416
|
+
def valid_api_key?(api_key)
|
417
|
+
return false unless api_key.is_a?(String)
|
418
|
+
return false if api_key.empty?
|
419
|
+
true
|
420
|
+
end
|
421
|
+
|
366
422
|
end
|
367
423
|
end
|
368
424
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: intrinio-realtime
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Intrinio
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-11-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http
|
@@ -80,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
80
|
version: '0'
|
81
81
|
requirements: []
|
82
82
|
rubyforge_project:
|
83
|
-
rubygems_version: 2.5.
|
83
|
+
rubygems_version: 2.5.2.2
|
84
84
|
signing_key:
|
85
85
|
specification_version: 4
|
86
86
|
summary: Intrinio provides real-time stock prices from the IEX stock exchange, via
|