orderbook 2.0.2 → 3.0.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/Gemfile +1 -0
- data/Gemfile.lock +4 -3
- data/README.md +10 -11
- data/lib/orderbook.rb +89 -41
- data/lib/orderbook/book_methods.rb +5 -1
- data/lib/orderbook/version.rb +1 -1
- metadata +2 -3
- data/lib/orderbook/real_time_book.rb +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20a70a3b134b39779181f6f4137a5200f003593e
|
4
|
+
data.tar.gz: 269d90ef37d27f7925e10f241326cf65c41ad3e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 255c3b44bb6cb4bee6bd90975bac52f51401d79d0e4374250545e438f2348223ca01e78a348f23bffa1e444d1d0aa479b024872fcdd40b3ec3ff17e415d5e426
|
7
|
+
data.tar.gz: a1581ff672f3e345c5745171754a399f6b552203fa73828976468445d36883a79f72a05d2eaddbe67176c1fc57dd33ff21dea919ec16ab71f649c9944c2f1444
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
GIT
|
2
2
|
remote: https://github.com/mikerodrigues/coinbase-exchange-ruby.git
|
3
|
-
revision:
|
3
|
+
revision: 527d6b4e9d5e6bd2d2deab7ac5f16f58674194bc
|
4
4
|
branch: orderbook
|
5
5
|
specs:
|
6
6
|
coinbase-exchange (0.1.2)
|
@@ -11,7 +11,7 @@ GIT
|
|
11
11
|
PATH
|
12
12
|
remote: .
|
13
13
|
specs:
|
14
|
-
orderbook (
|
14
|
+
orderbook (3.0.0)
|
15
15
|
|
16
16
|
GEM
|
17
17
|
remote: https://rubygems.org/
|
@@ -27,7 +27,7 @@ GEM
|
|
27
27
|
http_parser.rb (>= 0.6.0)
|
28
28
|
em-socksify (0.3.0)
|
29
29
|
eventmachine (>= 1.0.0.beta.4)
|
30
|
-
eventmachine (1.0.
|
30
|
+
eventmachine (1.0.8)
|
31
31
|
faye-websocket (0.10.0)
|
32
32
|
eventmachine (>= 0.12.0)
|
33
33
|
websocket-driver (>= 0.5.1)
|
@@ -44,6 +44,7 @@ PLATFORMS
|
|
44
44
|
DEPENDENCIES
|
45
45
|
bundler (~> 1.7)
|
46
46
|
coinbase-exchange!
|
47
|
+
eventmachine
|
47
48
|
json
|
48
49
|
orderbook!
|
49
50
|
rake (~> 10.0)
|
data/README.md
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
# Orderbook
|
1
|
+
# Orderbook 3.0.0
|
2
|
+
<a href="https://codeclimate.com/github/mikerodrigues/orderbook"><img src="https://codeclimate.com/github/mikerodrigues/orderbook/badges/gpa.svg" /></a>
|
3
|
+
|
4
|
+
Version 3.0.0 has a slightly different interface and properly queues messages
|
5
|
+
for an accurate Orderbook.
|
2
6
|
|
3
7
|
A gem for creating a realtime order book for the Coinbase Exchange.
|
4
8
|
|
@@ -43,7 +47,7 @@ ob = Orderbook.new(false)
|
|
43
47
|
|
44
48
|
# When you want it to go live:
|
45
49
|
|
46
|
-
ob.
|
50
|
+
ob.start!
|
47
51
|
```
|
48
52
|
|
49
53
|
* Create a live Orderbook with a callback to fire on each message:
|
@@ -53,18 +57,13 @@ ob = Orderbook.new do |message|
|
|
53
57
|
end
|
54
58
|
```
|
55
59
|
|
56
|
-
* Create or reset the callback:
|
60
|
+
* Create or reset the message callback:
|
57
61
|
```ruby
|
58
|
-
ob.
|
59
|
-
puts message.fetch '
|
62
|
+
ob.on_message do |message|
|
63
|
+
puts message.fetch 'sequence'
|
60
64
|
end
|
61
65
|
```
|
62
66
|
|
63
|
-
* The old class name is still supported and is equivalent to an Orderbook:
|
64
|
-
```ruby
|
65
|
-
rtb = Orderbook::RealTimeBook.new
|
66
|
-
```
|
67
|
-
|
68
67
|
* List current bids:
|
69
68
|
```ruby
|
70
69
|
ob.bids
|
@@ -77,7 +76,7 @@ ob.asks
|
|
77
76
|
|
78
77
|
* Show sequence number for initial level 3 snapshot:
|
79
78
|
```ruby
|
80
|
-
ob.
|
79
|
+
ob.snapshot_sequence
|
81
80
|
```
|
82
81
|
|
83
82
|
* Show sequence number for the last message received
|
data/lib/orderbook.rb
CHANGED
@@ -11,7 +11,9 @@ class Orderbook
|
|
11
11
|
include BookMethods
|
12
12
|
include BookAnalysis
|
13
13
|
|
14
|
-
|
14
|
+
# seconds in between pinging the connection.
|
15
|
+
#
|
16
|
+
PING_INTERVAL = 15
|
15
17
|
|
16
18
|
# Array of bids
|
17
19
|
#
|
@@ -23,7 +25,7 @@ class Orderbook
|
|
23
25
|
|
24
26
|
# Sequence number from the initial level 3 snapshot
|
25
27
|
#
|
26
|
-
attr_reader :
|
28
|
+
attr_reader :snapshot_sequence
|
27
29
|
|
28
30
|
# Sequence number of most recently received message
|
29
31
|
#
|
@@ -33,71 +35,107 @@ class Orderbook
|
|
33
35
|
#
|
34
36
|
attr_reader :websocket
|
35
37
|
|
36
|
-
# Coinbase::Exchange::
|
38
|
+
# Coinbase::Exchange::Client object
|
37
39
|
#
|
38
40
|
attr_reader :client
|
39
41
|
|
40
|
-
# Thread running the EM loop
|
42
|
+
# Thread running the EM loop for the websocket
|
43
|
+
#
|
44
|
+
attr_reader :em_thread
|
45
|
+
|
46
|
+
# Thread running the processing loop
|
41
47
|
#
|
42
|
-
attr_reader :
|
48
|
+
attr_reader :processing_thread
|
43
49
|
|
44
|
-
#
|
50
|
+
# DateTime of last successful pong
|
45
51
|
#
|
46
52
|
attr_reader :last_pong
|
47
53
|
|
48
|
-
#
|
54
|
+
# Message queue for incoming messages.
|
49
55
|
#
|
50
|
-
|
56
|
+
attr_reader :queue
|
51
57
|
|
52
58
|
# Creates a new live copy of the orderbook.
|
53
59
|
#
|
54
|
-
# If +
|
60
|
+
# If +start+ is set to false, the orderbook will not start automatically.
|
55
61
|
#
|
56
62
|
# If a +block+ is given it is passed each message as it is received.
|
57
63
|
#
|
58
|
-
def initialize(
|
59
|
-
@bids = [
|
60
|
-
@asks = [
|
61
|
-
@
|
64
|
+
def initialize(start = true, &block)
|
65
|
+
@bids = []
|
66
|
+
@asks = []
|
67
|
+
@snapshot_sequence = 0
|
62
68
|
@last_sequence = 0
|
69
|
+
@queue = Queue.new
|
63
70
|
@websocket = Coinbase::Exchange::Websocket.new(keepalive: true)
|
64
|
-
@client = Coinbase::Exchange::
|
65
|
-
@
|
66
|
-
|
71
|
+
@client = Coinbase::Exchange::Client.new
|
72
|
+
@on_message = block if block_given?
|
73
|
+
start && start!
|
67
74
|
end
|
68
75
|
|
69
76
|
# Used to start the thread that listens to updates on the websocket and
|
70
77
|
# applies them to the current orderbook to create a live book.
|
71
78
|
#
|
72
|
-
def
|
73
|
-
|
74
|
-
|
79
|
+
def start!
|
80
|
+
start_em_thread
|
81
|
+
|
82
|
+
# Wait to make sure the snapshot sequence ID is higher than the sequence of
|
83
|
+
# the first message in the queue.
|
84
|
+
#
|
85
|
+
sleep 0.3
|
86
|
+
apply_orderbook_snapshot
|
87
|
+
start_processing_thread
|
88
|
+
end
|
89
|
+
|
90
|
+
# Stops the processing thread, EM thread, and the websocket.
|
91
|
+
#
|
92
|
+
def stop!
|
93
|
+
@processing_thread.kill
|
94
|
+
@em_thread.kill
|
95
|
+
@websocket.stop!
|
96
|
+
end
|
97
|
+
|
98
|
+
# Start and stop the Orderbook. Used to reset Orderbook state with a fresh
|
99
|
+
# snapshot.
|
100
|
+
#
|
101
|
+
def reset!
|
102
|
+
stop!
|
103
|
+
start!
|
104
|
+
end
|
105
|
+
|
106
|
+
def on_message(&block)
|
107
|
+
@on_message = block
|
75
108
|
end
|
76
109
|
|
77
110
|
private
|
78
111
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
112
|
+
# Converts an order array from the API into a hash.
|
113
|
+
#
|
114
|
+
def order_to_hash(price, size, order_id)
|
115
|
+
{ price: BigDecimal.new(price),
|
116
|
+
size: BigDecimal.new(size),
|
117
|
+
order_id: order_id
|
118
|
+
}
|
84
119
|
end
|
85
120
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
size: BigDecimal.new(size),
|
90
|
-
order_id: order_id
|
91
|
-
}
|
92
|
-
end
|
121
|
+
# Fetch orderbook snapshot from API and convert order arrays to hashes.
|
122
|
+
#
|
123
|
+
def apply_orderbook_snapshot
|
93
124
|
@client.orderbook(level: 3) do |resp|
|
94
|
-
@bids = resp['bids'].map(
|
95
|
-
@asks = resp['asks'].map(
|
96
|
-
@
|
125
|
+
@bids = resp['bids'].map { |b| order_to_hash(*b) }
|
126
|
+
@asks = resp['asks'].map { |a| order_to_hash(*a) }
|
127
|
+
@snapshot_sequence = resp['sequence']
|
128
|
+
@last_sequence = resp['sequence']
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def setup_websocket_callback
|
133
|
+
@websocket.message do |message|
|
134
|
+
@queue.push(message)
|
97
135
|
end
|
98
136
|
end
|
99
137
|
|
100
|
-
def
|
138
|
+
def setup_ping_timer
|
101
139
|
EM.add_periodic_timer(PING_INTERVAL) do
|
102
140
|
@websocket.ping do
|
103
141
|
@last_pong = Time.now
|
@@ -105,19 +143,29 @@ class Orderbook
|
|
105
143
|
end
|
106
144
|
end
|
107
145
|
|
108
|
-
def
|
146
|
+
def setup_error_handler
|
109
147
|
EM.error_handler do |e|
|
110
148
|
print "Websocket Error: #{e.message} - #{e.backtrace.join("\n")}"
|
111
149
|
end
|
112
150
|
end
|
113
151
|
|
114
|
-
def
|
115
|
-
@
|
152
|
+
def start_em_thread
|
153
|
+
@em_thread = Thread.new do
|
154
|
+
setup_websocket_callback
|
116
155
|
EM.run do
|
117
|
-
fetch_current_orderbook
|
118
156
|
@websocket.start!
|
119
|
-
|
120
|
-
|
157
|
+
setup_ping_timer
|
158
|
+
setup_error_handler
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def start_processing_thread
|
164
|
+
@processing_thread = Thread.new do
|
165
|
+
loop do
|
166
|
+
message = @queue.shift
|
167
|
+
apply(message)
|
168
|
+
@on_message.call(message) unless @on_message.nil?
|
121
169
|
end
|
122
170
|
end
|
123
171
|
end
|
@@ -10,7 +10,11 @@ class Orderbook
|
|
10
10
|
# @bids, @asks, and @last_sequence.
|
11
11
|
#
|
12
12
|
def apply(msg)
|
13
|
-
return if msg.fetch('sequence')
|
13
|
+
return if msg.fetch('sequence') != @last_sequence + 1
|
14
|
+
#if msg.fetch('sequence') != @last_sequence + 1
|
15
|
+
# puts "Expected #{@last_sequence + 1}, got #{msg.fetch('sequence')}"
|
16
|
+
# @websocket.stop!
|
17
|
+
#end
|
14
18
|
@last_sequence = msg.fetch('sequence')
|
15
19
|
BIGDECIMAL_KEYS.each do |key|
|
16
20
|
msg[key] = BigDecimal.new(msg.fetch(key)) if msg.fetch(key, false)
|
data/lib/orderbook/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: orderbook
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Rodrigues
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-08-
|
11
|
+
date: 2015-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -57,7 +57,6 @@ files:
|
|
57
57
|
- lib/orderbook.rb
|
58
58
|
- lib/orderbook/book_analysis.rb
|
59
59
|
- lib/orderbook/book_methods.rb
|
60
|
-
- lib/orderbook/real_time_book.rb
|
61
60
|
- lib/orderbook/version.rb
|
62
61
|
- orderbook.gemspec
|
63
62
|
homepage: https://github.com/mikerodrigues/orderbook
|