orderbook 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/README.md +8 -0
- data/lib/orderbook/real_time_book.rb +89 -11
- data/lib/orderbook/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84269d46b54589bbc0b4ef3cc68427ea1f41160d
|
4
|
+
data.tar.gz: 355f66f391af0c02d0eea84d9edbcff19c9761ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 978af2908c7c1c0be124d3fff39fb1f43cb0bb3d980b4252842e50d1059617c82ffeeab34997e3d30513eb14c1ddb89992d4730f98761d6660cd9608172634b5
|
7
|
+
data.tar.gz: 5540ecd2f5cd99f9d68648d934d8d4b226aa4f66f7646294b72d6673c9f41a71a3f3c536b3af364af4d22fa1020eb0840674f0fd2641eac03198ee189d1a28c9
|
data/README.md
CHANGED
@@ -31,6 +31,14 @@ rtb = Orderbook::RealTimeBook.new
|
|
31
31
|
rtb.bids # Returns an array of bids.
|
32
32
|
|
33
33
|
rtb.asks # Returns an array of asks.
|
34
|
+
|
35
|
+
# Setup a callback that runs after the message is applied to the book. Each
|
36
|
+
message received on the WebSocket is passed to this block. Running this method
|
37
|
+
again will redefine the callback.
|
38
|
+
|
39
|
+
rtb.set_callback do |msg|
|
40
|
+
puts msg.fetch('type')
|
41
|
+
end
|
34
42
|
```
|
35
43
|
|
36
44
|
## Contributing
|
@@ -3,36 +3,114 @@ require 'orderbook/book_analysis'
|
|
3
3
|
|
4
4
|
module Orderbook
|
5
5
|
class RealTimeBook
|
6
|
+
include BookMethods
|
7
|
+
include BookAnalysis
|
8
|
+
|
9
|
+
# Time to wait until considering skipped messages lost.
|
10
|
+
#
|
11
|
+
LOST_TIMEOUT = 5
|
12
|
+
|
13
|
+
# Array of bids
|
14
|
+
#
|
6
15
|
attr_reader :bids
|
16
|
+
|
17
|
+
# Array of asks
|
18
|
+
#
|
7
19
|
attr_reader :asks
|
20
|
+
|
21
|
+
# Sequence number of snapshot
|
22
|
+
#
|
8
23
|
attr_reader :sequence
|
9
24
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
25
|
+
# Most recently processed sequence
|
26
|
+
#
|
27
|
+
attr_reader :last_sequence
|
28
|
+
|
29
|
+
# Hash of missing sequence numbers and their timeout threads.
|
30
|
+
#
|
31
|
+
attr_reader :missing
|
32
|
+
|
33
|
+
# CoinbaseExchange::Feed object
|
34
|
+
#
|
35
|
+
attr_reader :feed
|
36
|
+
|
37
|
+
# Queue of messages to be processed
|
38
|
+
#
|
39
|
+
attr_reader :queue
|
40
|
+
|
41
|
+
def initialize(&block)
|
42
|
+
if block_given?
|
43
|
+
@callback = block
|
44
|
+
end
|
45
|
+
subscribe
|
46
|
+
snapshot
|
47
|
+
process_queue
|
48
|
+
end
|
49
|
+
|
50
|
+
def set_callback(&block)
|
51
|
+
@callback = block
|
52
|
+
end
|
53
|
+
|
54
|
+
def refresh_snapshot
|
55
|
+
@thread.kill
|
56
|
+
snapshot
|
57
|
+
process_queue
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def subscribe
|
14
63
|
@queue = Queue.new
|
64
|
+
@missing = {}
|
15
65
|
on_msg = lambda {|msg| @queue << msg}
|
16
66
|
on_close = lambda {|close| puts close}
|
17
67
|
on_err = lambda {|err| puts err}
|
18
68
|
@feed = ::CoinbaseExchange::Feed.new(on_msg, on_close, on_err)
|
69
|
+
end
|
70
|
+
|
71
|
+
def snapshot
|
72
|
+
@cb || @cb = ::CoinbaseExchange.new
|
19
73
|
@snapshot = @cb.orderbook(3, 'BTC-USD')
|
20
|
-
@sequence = @snapshot.fetch('sequence').
|
74
|
+
@sequence = @snapshot.fetch('sequence').to_i
|
21
75
|
@bids = @snapshot.fetch('bids')
|
22
76
|
@asks = @snapshot.fetch('asks')
|
23
|
-
|
77
|
+
end
|
78
|
+
|
79
|
+
def timeout(sequence)
|
80
|
+
warn "Missing sequence #{sequence} timed out. Refreshingn snapshot."
|
81
|
+
refresh_snapshot
|
82
|
+
end
|
83
|
+
|
84
|
+
def process_queue
|
85
|
+
@thread && @thread.kill
|
86
|
+
@thread = Thread.new do
|
87
|
+
@last_sequence = 'start'
|
24
88
|
loop do
|
25
89
|
msg = @queue.shift
|
26
|
-
|
90
|
+
sequence = msg.fetch('sequence').to_i
|
91
|
+
if sequence > @sequence
|
92
|
+
unless @last_sequence == 'start'
|
93
|
+
expected_sequence = @last_sequence + 1
|
94
|
+
if sequence != expected_sequence
|
95
|
+
if @missing.keys.include? (expected_sequence)
|
96
|
+
@missing.fetch(expected_sequence).kill
|
97
|
+
@missing.delete(expected_sequence)
|
98
|
+
else
|
99
|
+
@missing[expected_sequence] = Thread.new do
|
100
|
+
sleep LOST_TIMEOUT
|
101
|
+
timeout expected_sequence
|
102
|
+
end
|
103
|
+
end
|
104
|
+
@missing < expected_sequence
|
105
|
+
end
|
106
|
+
end
|
27
107
|
apply(msg)
|
28
108
|
@callback && @callback.call(msg)
|
29
109
|
end
|
110
|
+
@last_sequence = sequence
|
30
111
|
end
|
31
112
|
end
|
32
113
|
end
|
33
|
-
|
34
|
-
def set_callback(&block)
|
35
|
-
@callback = block
|
36
|
-
end
|
37
114
|
end
|
38
115
|
end
|
116
|
+
|
data/lib/orderbook/version.rb
CHANGED