orderbook 2.0.1 → 2.0.2
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 -1
- data/Rakefile +1 -1
- data/lib/orderbook.rb +10 -16
- data/lib/orderbook/book_analysis.rb +9 -11
- data/lib/orderbook/book_methods.rb +34 -60
- data/lib/orderbook/real_time_book.rb +2 -5
- data/lib/orderbook/version.rb +3 -1
- data/orderbook.gemspec +11 -11
- 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: 82bf3042bbd14421f52d056b6bd7c07ded3a4745
|
4
|
+
data.tar.gz: 04b949de80478883f3400d7d90ba99ca61160e15
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 701b49e1646e44a5e08c7e3f09ea480f90bd7c47d629aa1be1c1c31f11de0137c893619c177e9491e2105b0e7c1668507090d2f836dc268b62825501a02fa784
|
7
|
+
data.tar.gz: df12ea165dffa99585bc74eb50d600c76065f4b58a7fcfb617fd873b6923aab0340000a85d7eed79e0757b53afc00991852e7002ec8dfe29a47ad0da1f492ad5
|
data/Gemfile
CHANGED
@@ -2,5 +2,5 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in orderbook.gemspec
|
4
4
|
gemspec
|
5
|
-
gem 'coinbase-exchange', :
|
5
|
+
gem 'coinbase-exchange', git: 'https://github.com/mikerodrigues/coinbase-exchange-ruby.git', branch: 'orderbook'
|
6
6
|
gem 'json'
|
data/Rakefile
CHANGED
data/lib/orderbook.rb
CHANGED
@@ -56,8 +56,8 @@ class Orderbook
|
|
56
56
|
# If a +block+ is given it is passed each message as it is received.
|
57
57
|
#
|
58
58
|
def initialize(live = true, &block)
|
59
|
-
@bids = [{price: nil, size: nil, order_id: nil}]
|
60
|
-
@asks = [{price: nil, size: nil, order_id: nil}]
|
59
|
+
@bids = [{ price: nil, size: nil, order_id: nil }]
|
60
|
+
@asks = [{ price: nil, size: nil, order_id: nil }]
|
61
61
|
@first_sequence = 0
|
62
62
|
@last_sequence = 0
|
63
63
|
@websocket = Coinbase::Exchange::Websocket.new(keepalive: true)
|
@@ -84,21 +84,15 @@ class Orderbook
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def fetch_current_orderbook
|
87
|
+
order_to_hash = lambda do |price, size, order_id|
|
88
|
+
{ price: BigDecimal.new(price),
|
89
|
+
size: BigDecimal.new(size),
|
90
|
+
order_id: order_id
|
91
|
+
}
|
92
|
+
end
|
87
93
|
@client.orderbook(level: 3) do |resp|
|
88
|
-
@bids = resp['bids'].map
|
89
|
-
|
90
|
-
price: BigDecimal.new(price),
|
91
|
-
size: BigDecimal.new(size),
|
92
|
-
order_id: order_id
|
93
|
-
}
|
94
|
-
end
|
95
|
-
@asks = resp['asks'].map do |price, size, order_id|
|
96
|
-
{
|
97
|
-
price: BigDecimal.new(price),
|
98
|
-
size: BigDecimal.new(size),
|
99
|
-
order_id: order_id
|
100
|
-
}
|
101
|
-
end
|
94
|
+
@bids = resp['bids'].map(&order_to_hash)
|
95
|
+
@asks = resp['asks'].map(&order_to_hash)
|
102
96
|
@first_sequence = resp['sequence']
|
103
97
|
end
|
104
98
|
end
|
@@ -1,4 +1,7 @@
|
|
1
1
|
class Orderbook
|
2
|
+
# Simple collection of commands to get info about the orderbook. Add our own
|
3
|
+
# methods for calculating whatever it is you feel like calculating.
|
4
|
+
#
|
2
5
|
module BookAnalysis
|
3
6
|
def bid_count
|
4
7
|
@bids.count
|
@@ -13,11 +16,11 @@ class Orderbook
|
|
13
16
|
end
|
14
17
|
|
15
18
|
def bid_volume
|
16
|
-
@bids.map {|x| x.fetch(:size)}.inject(:+)
|
19
|
+
@bids.map { |x| x.fetch(:size) }.inject(:+)
|
17
20
|
end
|
18
21
|
|
19
22
|
def ask_volume
|
20
|
-
@asks.map {|x| x.fetch(:size)}.inject(:+)
|
23
|
+
@asks.map { |x| x.fetch(:size) }.inject(:+)
|
21
24
|
end
|
22
25
|
|
23
26
|
def volume
|
@@ -25,12 +28,12 @@ class Orderbook
|
|
25
28
|
end
|
26
29
|
|
27
30
|
def average_bid
|
28
|
-
bids = @bids.map {|x| x.fetch(:price)}
|
31
|
+
bids = @bids.map { |x| x.fetch(:price) }
|
29
32
|
bids.inject(:+) / bids.count
|
30
33
|
end
|
31
34
|
|
32
35
|
def average_ask
|
33
|
-
asks = @asks.map {|x| x.fetch(:price)}
|
36
|
+
asks = @asks.map { |x| x.fetch(:price) }
|
34
37
|
asks.inject(:+) / asks.count
|
35
38
|
end
|
36
39
|
|
@@ -39,11 +42,11 @@ class Orderbook
|
|
39
42
|
end
|
40
43
|
|
41
44
|
def best_bid
|
42
|
-
@bids.sort_by {|x| x.fetch(:price)}.last
|
45
|
+
@bids.sort_by { |x| x.fetch(:price) }.last
|
43
46
|
end
|
44
47
|
|
45
48
|
def best_ask
|
46
|
-
@asks.sort_by {|x| x.fetch(:price)}.first
|
49
|
+
@asks.sort_by { |x| x.fetch(:price) }.first
|
47
50
|
end
|
48
51
|
|
49
52
|
def best
|
@@ -57,11 +60,6 @@ class Orderbook
|
|
57
60
|
def summarize
|
58
61
|
print "# of asks: #{ask_count}\n# of bids: #{bid_count}\nAsk volume: #{ask_volume.to_s('F')}\nBid volume: #{bid_volume.to_s('F')}\n"
|
59
62
|
$stdout.flush
|
60
|
-
# puts "Avg. ask: #{average_ask}"
|
61
|
-
# puts "Avg. bid: #{average_bid}"
|
62
|
-
# puts "Best ask: #{best_bid}"
|
63
|
-
# puts "Best bid: #{best_ask}"
|
64
|
-
# puts "Spread: #{spread}"
|
65
63
|
end
|
66
64
|
end
|
67
65
|
end
|
@@ -1,94 +1,68 @@
|
|
1
|
-
require 'bigdecimal'
|
1
|
+
require 'bigdecimal'
|
2
2
|
class Orderbook
|
3
3
|
# This class provides methods to apply updates to the state of the orderbook
|
4
|
-
# as they
|
4
|
+
# as they are received by the websocket.
|
5
5
|
#
|
6
6
|
module BookMethods
|
7
|
-
BIGDECIMAL_KEYS =
|
7
|
+
BIGDECIMAL_KEYS = %w(size old_size new_size remaining_size price)
|
8
8
|
|
9
9
|
# Applies a message to an Orderbook object by making relevant changes to
|
10
10
|
# @bids, @asks, and @last_sequence.
|
11
11
|
#
|
12
12
|
def apply(msg)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
msg[key] = BigDecimal.new(msg.fetch(key))
|
18
|
-
end
|
19
|
-
end
|
20
|
-
__send__(msg.fetch('type'), msg)
|
13
|
+
return if msg.fetch('sequence') <= @first_sequence
|
14
|
+
@last_sequence = msg.fetch('sequence')
|
15
|
+
BIGDECIMAL_KEYS.each do |key|
|
16
|
+
msg[key] = BigDecimal.new(msg.fetch(key)) if msg.fetch(key, false)
|
21
17
|
end
|
18
|
+
|
19
|
+
__send__(msg.fetch('type'), msg)
|
22
20
|
end
|
23
21
|
|
24
22
|
private
|
25
23
|
|
26
24
|
def open(msg)
|
27
|
-
order = {
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
25
|
+
order = {
|
26
|
+
price: msg.fetch('price'),
|
27
|
+
size: msg.fetch('remaining_size'),
|
28
|
+
order_id: msg.fetch('order_id')
|
29
|
+
}
|
30
|
+
|
31
|
+
@bids << order if msg.fetch('side') == 'buy'
|
32
|
+
@asks << order if msg.fetch('side') == 'sell'
|
34
33
|
end
|
35
34
|
|
36
35
|
def match(msg)
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
if ask.fetch(:order_id) == msg.fetch('maker_order_id')
|
41
|
-
ask[:size] = ask[:size] - msg.fetch('size')
|
42
|
-
end
|
43
|
-
end
|
44
|
-
@bids.map do |bid|
|
45
|
-
if bid.fetch(:order_id) == msg.fetch('taker_order_id')
|
46
|
-
bid[:size] = bid[:size] - msg.fetch('size')
|
47
|
-
end
|
48
|
-
end
|
49
|
-
when 'buy'
|
50
|
-
@bids.map do |bid|
|
51
|
-
if bid.fetch(:order_id) == msg.fetch('maker_order_id')
|
52
|
-
bid[:size] = bid[:size] - msg.fetch('size')
|
53
|
-
end
|
54
|
-
end
|
55
|
-
@asks.map do |ask|
|
56
|
-
if ask.fetch(:order_id) == msg.fetch('taker_order_id')
|
57
|
-
ask[:size] = ask[:size] - msg.fetch('size')
|
58
|
-
end
|
36
|
+
decrement_match = lambda do |o|
|
37
|
+
if o.fetch(:order_id) == msg.fetch('maker_order_id')
|
38
|
+
o[:size] = o.fetch(:size) - msg.fetch('size')
|
59
39
|
end
|
60
40
|
end
|
41
|
+
|
42
|
+
@asks.map(&decrement_match) if msg.fetch('side') == 'sell'
|
43
|
+
@bids.map(&decrement_match) if msg.fetch('side') == 'buy'
|
61
44
|
end
|
62
45
|
|
63
46
|
def done(msg)
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
@bids.reject! {|b| b.fetch(:order_id) == msg['order_id']}
|
69
|
-
end
|
47
|
+
matching_order = ->(o) { o.fetch(:order_id) == msg.fetch('order_id') }
|
48
|
+
|
49
|
+
@asks.reject!(&matching_order) if msg.fetch('side') == 'sell'
|
50
|
+
@bids.reject!(&matching_order) if msg.fetch('side') == 'buy'
|
70
51
|
end
|
71
52
|
|
72
53
|
def change(msg)
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
if a.fetch(:order_id) == msg.fetch('order_id')
|
77
|
-
a[:size] = msg.fetch('new_size')
|
78
|
-
end
|
79
|
-
end
|
80
|
-
when 'buy'
|
81
|
-
@bids.map do |b|
|
82
|
-
if b.fetch(:order_id) == msg.fetch('order_id')
|
83
|
-
b[:size] = msg.fetch('new_size')
|
84
|
-
end
|
54
|
+
change_order = lambda do |o|
|
55
|
+
if o.fetch(:order_id) == msg.fetch('order_id')
|
56
|
+
o[:size] = msg.fetch('new_size')
|
85
57
|
end
|
86
58
|
end
|
59
|
+
|
60
|
+
@asks.map(&change_order) if msg.fetch('side') == 'sell'
|
61
|
+
@bids.map(&change_order) if msg.fetch('side') == 'buy'
|
87
62
|
end
|
88
63
|
|
89
|
-
def received(
|
64
|
+
def received(_)
|
90
65
|
# The book doesn't change for this message type.
|
91
66
|
end
|
92
|
-
|
93
67
|
end
|
94
68
|
end
|
data/lib/orderbook/version.rb
CHANGED
data/orderbook.gemspec
CHANGED
@@ -4,22 +4,22 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'orderbook/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'orderbook'
|
8
8
|
spec.version = Orderbook::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.summary = %q
|
12
|
-
spec.description = %q
|
9
|
+
spec.authors = ['Michael Rodrigues']
|
10
|
+
spec.email = ['mikebrodrigues@gmail.com']
|
11
|
+
spec.summary = %q(Maintains an real-time copy of the Coinbase Exchange order book.)
|
12
|
+
spec.description = %q(Orderbook uses the Coinbase Exchange Websocket stream
|
13
13
|
to maintain a real-time copy of the order book. Use it
|
14
|
-
in your BTC trading bot.
|
15
|
-
spec.homepage =
|
16
|
-
spec.license =
|
14
|
+
in your BTC trading bot.)
|
15
|
+
spec.homepage = 'https://github.com/mikerodrigues/orderbook'
|
16
|
+
spec.license = 'MIT'
|
17
17
|
|
18
18
|
spec.files = `git ls-files -z`.split("\x0")
|
19
19
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
|
-
spec.require_paths = [
|
21
|
+
spec.require_paths = ['lib']
|
22
22
|
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
24
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
25
25
|
end
|
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: 2.0.
|
4
|
+
version: 2.0.2
|
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-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|