gekko 0.3.1 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 724b1a6b9a228d238ffdcb74a84e2460a09df83e
4
- data.tar.gz: 3c9ce015f90c21e9b43780dddae3b7581d865299
3
+ metadata.gz: 6e807cf299a74840caedd3ab554af8b30c797d51
4
+ data.tar.gz: bce631e42323b43fd1864033a8e8bd6f4c97ffea
5
5
  SHA512:
6
- metadata.gz: 1956c91a15816852444d39cb70aa3f62c43ded976493d7dd54c474e3c4e64716c65985479ba1b9d63e9a5beeece308d7d3904f7c8ecbe2dbc5596c5bc5b777d4
7
- data.tar.gz: 3d54b6d4daae77ac190ca2fc4a95f5fe2f9238e9275ca91a0d72d33f77b28578cc149e2cb95bec053cc679bf5c41bdae995adef22f957ad3349f02cbdf84cc00
6
+ metadata.gz: ce1211699c74fc7232ddfbbc83db30d71fa45445a78c2b54c6ba547cd62b6d18d8d93b11486642b4ed6e6dfc496e9ab8acb32f55c916c0ac139edc6a64e0b9df
7
+ data.tar.gz: 31f755d6134b1650909bfb8860a28ab1a89e4732ee529fb87fb88161909acca8c6a51569bd7dbeb580997f76c11d33c8091a792b81c54f31eb6ab7eca74ce161
data/lib/gekko/book.rb CHANGED
@@ -1,3 +1,6 @@
1
+ require 'oj'
2
+ Oj.default_options = { mode: :compat }
3
+
1
4
  require 'gekko/book_side'
2
5
  require 'gekko/tape'
3
6
  require 'gekko/errors'
@@ -12,12 +15,12 @@ module Gekko
12
15
  attr_accessor :pair, :bids, :asks, :tape, :received, :base_precision
13
16
 
14
17
  def initialize(pair, opts = {})
15
- self.pair = pair
16
- self.bids = BookSide.new(:bid)
17
- self.asks = BookSide.new(:ask)
18
- self.tape = Tape.new(opts[:logger])
18
+ self.pair = opts[:pair] || pair
19
+ self.bids = opts[:bids] || BookSide.new(:bid)
20
+ self.asks = opts[:asks] || BookSide.new(:ask)
21
+ self.tape = opts[:tape] || Tape.new({ logger: opts[:logger] })
19
22
  self.base_precision = opts[:base_precision] || 8
20
- self.received = {}
23
+ self.received = opts[:received] || {}
21
24
  end
22
25
 
23
26
  #
@@ -75,7 +78,6 @@ module Gekko
75
78
  quote_size: quote_size,
76
79
  maker_order_id: next_match.id.to_s,
77
80
  taker_order_id: order.id.to_s,
78
- time: Time.now.to_f,
79
81
  tick: order.bid? ? :up : :down
80
82
  }
81
83
 
@@ -187,6 +189,49 @@ module Gekko
187
189
  }
188
190
  end
189
191
 
192
+ #
193
+ # Dumps the book to a JSON string
194
+ #
195
+ # @return [String] The serialized order book
196
+ #
197
+ def dump
198
+ Oj.dump({
199
+ time: Time.now.to_f,
200
+ bids: bids.to_hash,
201
+ asks: asks.to_hash,
202
+ pair: pair,
203
+ tape: tape.to_hash,
204
+ received: received,
205
+ base_precision: base_precision
206
+ })
207
+ end
208
+
209
+ #
210
+ # Loads the book from a JSON string
211
+ #
212
+ # @param serialized [String] A serialized book
213
+ # @return [Gekko::Book] The deserialized book instance
214
+ #
215
+ def self.load(serialized)
216
+ hsh = symbolize_keys(Oj.load(serialized))
217
+
218
+ hsh[:tape] = Tape.new(symbolize_keys(hsh[:tape]))
219
+ hsh[:bids] = BookSide.new(:bid, orders: hsh[:bids].map { |o| symbolize_keys(o) })
220
+ hsh[:asks] = BookSide.new(:ask, orders: hsh[:asks].map { |o| symbolize_keys(o) })
221
+
222
+ Book.new(hsh[:pair], hsh)
223
+ end
224
+
225
+ #
226
+ # Symbolizes keys of a non-nested +Hash+
227
+ #
228
+ # @param hsh [Hash] The +Hash+ for which we want to symbolize the keys
229
+ # @return [Hash] A copy of the parameter with all first-level keys symbolized
230
+ #
231
+ def self.symbolize_keys(hsh)
232
+ hsh.inject({}) { |mem, obj| mem[obj[0].to_sym] = obj[1]; mem }
233
+ end
234
+
190
235
  end
191
236
  end
192
237
 
@@ -9,9 +9,20 @@ module Gekko
9
9
 
10
10
  attr_accessor :side
11
11
 
12
- def initialize(side)
12
+ def initialize(side, opts = {})
13
13
  raise "Incorrect side <#{side}>" unless [:bid, :ask].include?(side)
14
14
  @side = side
15
+
16
+ opts[:orders] && opts[:orders].each_with_index { |obj, idx| self[idx] = Order.load(obj) }
17
+ end
18
+
19
+ #
20
+ # Returns a +Hash+ representation of this +BookSide+ instance
21
+ #
22
+ # @return [Hash] The serializable representation
23
+ #
24
+ def to_hash
25
+ map(&:to_hash)
15
26
  end
16
27
 
17
28
  #
data/lib/gekko/order.rb CHANGED
@@ -24,6 +24,36 @@ module Gekko
24
24
  raise 'The order creation timestamp can''t be nil' if !@created_at
25
25
  end
26
26
 
27
+
28
+ #
29
+ # Loads an +Order+ from a +Hash+. Only limit orders are supported as market
30
+ # orders should never need to get serialized
31
+ #
32
+ # @return [LimitOrder] The unserialized order
33
+ #
34
+ def self.load(hsh)
35
+ order = LimitOrder.new(hsh[:side], UUID.parse(hsh[:id]), hsh[:size], hsh[:price], hsh[:expiration])
36
+ order.created_at = hsh[:created_at]
37
+ order
38
+ end
39
+
40
+ #
41
+ # Returns a +Hash+ representation of this +Order+ instance
42
+ #
43
+ # @return [Hash] The serializable representation
44
+ #
45
+ def to_hash
46
+ {
47
+ id: @id,
48
+ side: @side,
49
+ size: @size,
50
+ price: @price,
51
+ remaining: @remaining,
52
+ expiration: @expiration,
53
+ created_at: @created_at
54
+ }
55
+ end
56
+
27
57
  #
28
58
  # Returns +true+ if this order can execute against +limit_order+
29
59
  #
data/lib/gekko/tape.rb CHANGED
@@ -5,23 +5,57 @@ module Gekko
5
5
  #
6
6
  class Tape < Array
7
7
 
8
+ # The number of seconds in 24h
9
+ SECONDS_IN_24H = 60 * 60 * 24
10
+
8
11
  attr_accessor :logger, :last_trade_price
12
+ attr_reader :volume_24h, :high_24h, :low_24h
13
+
14
+ def initialize(opts = {})
15
+ @logger = opts[:logger]
16
+
17
+ @cursor = opts[:cursor] || 0
18
+ @cursor_24h = opts[:cursor_24h] || 0
19
+ @volume_24h = opts[:volume_24h] || 0
20
+ @quote_volume_24h = opts[:quote_volume_24h] || 0
21
+
22
+ @low_24h = opts[:low_24h]
23
+ @high_24h = opts[:high_24h]
24
+ @last_trade_price = opts[:last_trade_price]
9
25
 
10
- def initialize(logger = nil)
11
- @logger = logger
12
- @cursor = 0
13
- @cursor_24h = 0
14
- @volume_24h = 0
15
- @quote_volume_24h = 0
26
+ opts[:events] && opts[:events].each_with_index { |obj, idx| self[idx] = obj }
27
+ end
28
+
29
+ #
30
+ # Returns this +Tape+ object as a +Hash+ for the purpose of serialization
31
+ #
32
+ # @return [Hash] The JSON-friendly +Hash+ representation
33
+ #
34
+ def to_hash
35
+ {
36
+ cursor: @cursor,
37
+ cursor_24h: @cursor_24h,
38
+ volume_24h: @volume_24h,
39
+ high_24h: @high_24h,
40
+ low_24h: @low_24h,
41
+ quote_volume_24h: @quote_volume_24h,
42
+ last_trade_price: @last_trade_price,
43
+ events: self
44
+ }
16
45
  end
17
46
 
47
+
18
48
  #
19
49
  # Prints a message on the tape
20
50
  #
21
51
  # @param message [Hash] The message to record
22
52
  #
23
53
  def <<(message)
24
- message[:sequence] = length
54
+ message.merge!({
55
+ sequence: length,
56
+ time: Time.now.to_f
57
+ })
58
+
25
59
  logger && logger.info(message)
26
60
 
27
61
  super(message)
@@ -44,36 +78,6 @@ module Gekko
44
78
  end
45
79
  end
46
80
 
47
- #
48
- # Returns the traded volume for the last 24h
49
- #
50
- # @return [Fixnum] The last 24h volume
51
- #
52
- def volume_24h
53
- move_24h_cursor!
54
- @volume_24h
55
- end
56
-
57
- #
58
- # Returns the highest trade price that occurred during the last 24h
59
- #
60
- # @return [Fixnum] The last 24h high
61
- #
62
- def high_24h
63
- move_24h_cursor!
64
- @high_24h
65
- end
66
-
67
- #
68
- # Returns the lowest trade price that occurred during the last 24h
69
- #
70
- # @return [Fixnum] The last 24h low
71
- #
72
- def low_24h
73
- move_24h_cursor!
74
- @low_24h
75
- end
76
-
77
81
  #
78
82
  # Recalculates the previous 24h high and low
79
83
  #
@@ -87,8 +91,10 @@ module Gekko
87
91
  evt = self[tmp_cursor]
88
92
 
89
93
  while (evt && (evt[:time] >= time_24h_ago)) do
90
- @high_24h = ((@high_24h.nil? || (evt[:price] > @high_24h)) && evt[:price]) || @high_24h
91
- @low_24h = ((@low_24h.nil? || (evt[:price] < @low_24h)) && evt[:price]) || @low_24h
94
+ if evt[:type] == :execution
95
+ @high_24h = ((@high_24h.nil? || (evt[:price] > @high_24h)) && evt[:price]) || @high_24h
96
+ @low_24h = ((@low_24h.nil? || (evt[:price] < @low_24h)) && evt[:price]) || @low_24h
97
+ end
92
98
 
93
99
  tmp_cursor -= 1
94
100
  evt = (tmp_cursor >= 0) && self[tmp_cursor]
@@ -101,7 +107,7 @@ module Gekko
101
107
  # @return [Fixnum] The last 24h quote currency volume
102
108
  #
103
109
  def quote_volume_24h
104
- move_24h_cursor!
110
+ #move_24h_cursor!
105
111
  @quote_volume_24h
106
112
  end
107
113
 
@@ -136,7 +142,7 @@ module Gekko
136
142
  # @return [Float] Yesterday's cut-off timestamp
137
143
  #
138
144
  def time_24h_ago
139
- Time.now.to_f - 24*3600
145
+ Time.now.to_f - SECONDS_IN_24H
140
146
  end
141
147
 
142
148
  #
@@ -145,7 +151,7 @@ module Gekko
145
151
  # passed to Tape#fall_out_of_24h_window
146
152
  #
147
153
  def move_24h_cursor!
148
- while(self[@cursor_24h] && ((self[@cursor_24h][:type] != :execution) || (self[@cursor_24h][:time] < time_24h_ago)))
154
+ while(self[@cursor_24h] && (self[@cursor_24h][:time] < time_24h_ago))
149
155
  if self[@cursor_24h][:type] == :execution
150
156
  fall_out_of_24h_window(self[@cursor_24h])
151
157
  end
data/lib/gekko/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Gekko
2
2
 
3
3
  # The Gekko version string
4
- VERSION = '0.3.1'
4
+ VERSION = '0.5.0'
5
5
 
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gekko
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David FRANCOIS
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-12 00:00:00.000000000 Z
11
+ date: 2015-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: uuidtools
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: oj
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: pry
29
43
  requirement: !ruby/object:Gem::Requirement