orderbook 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0d5cc78ce1824c5c00fce053a371b7f43e6ab9e9
4
- data.tar.gz: 780c397a8788c3bdbce8bc2e6c1ce4f2383562b0
3
+ metadata.gz: 82bf3042bbd14421f52d056b6bd7c07ded3a4745
4
+ data.tar.gz: 04b949de80478883f3400d7d90ba99ca61160e15
5
5
  SHA512:
6
- metadata.gz: 3c1cf4ae709490839a03b509980b3478b86ef1c0a4019da68e9bff37eee53d2dcc540ea26bb4c360bf1e21f15bfc1ba7e3a36871d0f92c38c7d52223d0ea0336
7
- data.tar.gz: ac832ab9024886040366b1343961d777c4b428e085118935d4ed0a9ac956a6e0139025c651c333aa008382957631d276fb2fa1c661208945197b8d0078acdf8d
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', :git => 'https://github.com/mikerodrigues/coinbase-exchange-ruby.git', :branch => 'orderbook'
5
+ gem 'coinbase-exchange', git: 'https://github.com/mikerodrigues/coinbase-exchange-ruby.git', branch: 'orderbook'
6
6
  gem 'json'
data/Rakefile CHANGED
@@ -27,7 +27,7 @@ task :console do
27
27
  PRY.start
28
28
  end
29
29
 
30
- task :default => ['build', 'install']
30
+ task default: %w(build install)
31
31
 
32
32
  Rake::TestTask.new do |t|
33
33
  t.libs << 'test'
@@ -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 do |price, size, order_id|
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 come in as individual messages.
4
+ # as they are received by the websocket.
5
5
  #
6
6
  module BookMethods
7
- BIGDECIMAL_KEYS = ['size', 'old_size', 'new_size', 'remaining_size', 'price', 'funds', 'old_funds', 'new_funds']
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
- unless msg.fetch('sequence') <= @first_sequence
14
- @last_sequence = msg.fetch('sequence')
15
- BIGDECIMAL_KEYS.each do |key|
16
- if msg.fetch(key, false)
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 = { price: msg.fetch('price'), size: msg.fetch('remaining_size'), order_id: msg.fetch('order_id') }
28
- case msg.fetch('side')
29
- when 'buy'
30
- @bids << order
31
- when 'sell'
32
- @asks << order
33
- end
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
- case msg.fetch('side')
38
- when 'sell'
39
- @asks.map do |ask|
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
- case msg.fetch('side')
65
- when 'sell'
66
- @asks.reject! {|a| a.fetch(:order_id) == msg['order_id']}
67
- when 'buy'
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
- case msg.fetch('side')
74
- when 'sell'
75
- @asks.map do |a|
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(msg)
64
+ def received(_)
90
65
  # The book doesn't change for this message type.
91
66
  end
92
-
93
67
  end
94
68
  end
@@ -1,7 +1,4 @@
1
1
  class Orderbook
2
- class RealTimeBook < Orderbook
3
- # For backwards compatability
4
-
5
- end
2
+ # For backwards compatability
3
+ class RealTimeBook < Orderbook; end
6
4
  end
7
-
@@ -1,3 +1,5 @@
1
+ # Orderbook version number. I try to keep it semantic.
2
+ #
1
3
  class Orderbook
2
- VERSION = "2.0.1"
4
+ VERSION = '2.0.2'
3
5
  end
@@ -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 = "orderbook"
7
+ spec.name = 'orderbook'
8
8
  spec.version = Orderbook::VERSION
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
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 = "https://github.com/mikerodrigues/orderbook"
16
- spec.license = "MIT"
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 = ["lib"]
21
+ spec.require_paths = ['lib']
22
22
 
23
- spec.add_development_dependency "bundler", "~> 1.7"
24
- spec.add_development_dependency "rake", "~> 10.0"
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.1
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-03 00:00:00.000000000 Z
11
+ date: 2015-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler