irix 2.4.2 → 2.4.5

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
  SHA256:
3
- metadata.gz: c95445e49c906a31bbc9e16f2b4b78ca8d023fca73f5d29128d9531ab0112c18
4
- data.tar.gz: 79e6e7f4d815726d6624e4d79c0a0d8db2ebed9bda2534645c29b40bbffbf7d4
3
+ metadata.gz: f657a9eb4e3dfc49657b176fafc409ef49511836fffe48cfaa13d80b0d39368c
4
+ data.tar.gz: 00baaa01a84aafd3ff46ec00752fbd99705edf206a5e2c76483926555b1065e5
5
5
  SHA512:
6
- metadata.gz: '0509583f671a0de4396eaec6ae5cc524e0bf4924afb4186c7efa6487dfff53fcc657eccfdf53158a1e81deb3e24b7937a066a4c0e65669b209fda92c1c507133'
7
- data.tar.gz: d77b1f4410a5ff9d7ce1268aa30ea7e16556534f5684b3b14ddb241c6d9774e4c19518d92484d34cb8525818b53c3af72954f48eaf7782c1467bf6d3eef2b8d5
6
+ metadata.gz: d506765d1553093958e4597267bc0c3588648af480de6fb56ca9767c023ef17583a75da2c6806344e0732dd72a15fcd5ab650e0bb5a6d0bf6e469d699ef2709c
7
+ data.tar.gz: aafdb928c1c213c7685600a45812d0d1d630694c731b173ffdf2fe62155b4cf9de1fce67d039f5239590f670e004d3f86415375fbe786e3b7bcf0d206f1e81fa
data/.drone.yml CHANGED
@@ -9,6 +9,21 @@ steps:
9
9
  - gem install bundler:2.0.2
10
10
  - bundle install --jobs=$(nproc) --retry=3 --path vendor/bundle
11
11
  - bundle exec rspec
12
+
13
+ - name: Release gem
14
+ image: ruby:2.6
15
+ environment:
16
+ GEM_CREDENTIALS:
17
+ from_secret: gem_credentials
18
+ commands:
19
+ - mkdir -p ~/.gem
20
+ - echo $GEM_CREDENTIALS | base64 -d > ~/.gem/credentials
21
+ - chmod 0600 ~/.gem/credentials
22
+ - gem build irix.gemspec
23
+ - gem push irix-*.gem
24
+ when:
25
+ branch:
26
+ - master
12
27
 
13
28
  trigger:
14
29
  event:
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- irix (2.4.2)
4
+ irix (2.4.5)
5
5
  em-synchrony (~> 1.0)
6
6
  em-websocket
7
7
  eventmachine
@@ -22,13 +22,13 @@ GEM
22
22
  zeitwerk (~> 2.1, >= 2.1.8)
23
23
  addressable (2.7.0)
24
24
  public_suffix (>= 2.0.2, < 5.0)
25
- amq-protocol (2.3.0)
25
+ amq-protocol (2.3.1)
26
26
  amqp (1.8.0)
27
27
  amq-protocol (>= 2.2.0)
28
28
  eventmachine
29
29
  ast (2.4.0)
30
- bunny (2.14.4)
31
- amq-protocol (~> 2.3, >= 2.3.0)
30
+ bunny (2.15.0)
31
+ amq-protocol (~> 2.3, >= 2.3.1)
32
32
  byebug (11.1.1)
33
33
  clamp (1.3.1)
34
34
  coderay (1.1.2)
@@ -60,7 +60,7 @@ GEM
60
60
  multipart-post (>= 1.2, < 3)
61
61
  faraday_middleware (0.13.1)
62
62
  faraday (>= 0.7.4, < 1.0)
63
- faye (1.2.4)
63
+ faye (1.2.5)
64
64
  cookiejar (>= 0.3.0)
65
65
  em-http-request (>= 0.3.0)
66
66
  eventmachine (>= 0.12.0)
@@ -85,7 +85,7 @@ GEM
85
85
  parallel (1.19.0)
86
86
  parser (2.6.5.0)
87
87
  ast (~> 2.4.0)
88
- peatio (2.4.2)
88
+ peatio (2.4.4)
89
89
  activemodel (> 5.2, <= 6.0.0)
90
90
  amqp
91
91
  bunny
@@ -106,7 +106,7 @@ GEM
106
106
  pry-byebug (3.8.0)
107
107
  byebug (~> 11.0)
108
108
  pry (~> 0.10)
109
- public_suffix (4.0.3)
109
+ public_suffix (4.0.5)
110
110
  rack (2.2.2)
111
111
  rainbow (3.0.0)
112
112
  rake (13.0.1)
@@ -151,7 +151,7 @@ GEM
151
151
  eventmachine (~> 1.0, >= 1.0.4)
152
152
  rack (>= 1, < 3)
153
153
  thread_safe (0.3.6)
154
- tzinfo (1.2.6)
154
+ tzinfo (1.2.7)
155
155
  thread_safe (~> 0.1)
156
156
  unicode-display_width (1.6.0)
157
157
  websocket (1.2.8)
@@ -177,4 +177,4 @@ DEPENDENCIES
177
177
  simplecov-json
178
178
 
179
179
  BUNDLED WITH
180
- 2.0.2
180
+ 2.1.4
data/lib/irix/bitfinex.rb CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  module Irix
4
4
  class Bitfinex < Peatio::Upstream::Base
5
+ require 'time'
6
+
7
+ MIN_INCREMENT_COUNT_TO_SNAPSHOT = 100
8
+ MIN_PERIOD_TO_SNAPSHOT = 5
9
+ MAX_PERIOD_TO_SNAPSHOT = 60
10
+
11
+ attr_accessor :snap, :snapshot_time, :increment_count, :sequence_number,
12
+ :open_channels, :asks, :bids
13
+
5
14
  def initialize(config)
6
15
  super
7
16
  @connection = Faraday.new(url: (config['rest']).to_s) do |builder|
@@ -12,15 +21,22 @@ module Irix
12
21
  builder.ssl[:verify] = config['verify_ssl']
13
22
  end
14
23
  end
24
+ @open_channels = {}
15
25
  @ping_set = false
16
26
  @rest = (config['rest']).to_s
17
- @ws_url = "#{config['websocket']}"
27
+ @ws_url = (config['websocket']).to_s
18
28
  end
19
29
 
20
30
  def ws_connect
21
31
  super
22
32
  return if @ping_set
23
33
 
34
+ @ws.on(:open) do |_e|
35
+ subscribe_trades(@target, @ws)
36
+ subscribe_orderbook(@target, @ws)
37
+ logger.info { 'Websocket connected' }
38
+ end
39
+
24
40
  Fiber.new do
25
41
  EM::Synchrony.add_periodic_timer(80) do
26
42
  @ws.send('{"event":"ping"}')
@@ -30,6 +46,8 @@ module Irix
30
46
  end
31
47
 
32
48
  def subscribe_trades(market, ws)
49
+ return unless @config['trade_proxy']
50
+
33
51
  sub = {
34
52
  event: 'subscribe',
35
53
  channel: 'trades',
@@ -42,9 +60,40 @@ module Irix
42
60
  end
43
61
  end
44
62
 
63
+ def subscribe_orderbook(market, ws)
64
+ return unless @config['orderbook_proxy']
65
+
66
+ @sequence_number = 0
67
+ @increment_count = 0
68
+ @bids = []
69
+ @asks = []
70
+ @snap = { 'asks' => [], 'bids' => [] }
71
+ sub = {
72
+ event: 'subscribe',
73
+ channel: 'book',
74
+ symbol: market.upcase,
75
+ len: 25
76
+ }
77
+ Rails.logger.info 'Open event' + sub.to_s
78
+ EM.next_tick do
79
+ ws.send(JSON.generate(sub))
80
+ end
81
+ Fiber.new do
82
+ EM::Synchrony.add_periodic_timer(0.2) do
83
+ publish_increment
84
+ end
85
+ end.resume
86
+ end
87
+
45
88
  def ws_read_public_message(msg)
46
89
  if msg.is_a?(Array)
47
- detect_trade(msg)
90
+ if msg[1] == 'hb'
91
+ @ws.send('{"event":"ping"}')
92
+ elsif @open_channels[msg[0]] == 'trades'
93
+ detect_trade(msg)
94
+ elsif @open_channels[msg[0]] == 'book'
95
+ detect_order(msg)
96
+ end
48
97
  elsif msg.is_a?(Hash)
49
98
  message_event(msg)
50
99
  end
@@ -65,10 +114,85 @@ module Irix
65
114
  end
66
115
  end
67
116
 
117
+ # [
118
+ # CHANNEL_ID,
119
+ # [
120
+ # PRICE,
121
+ # COUNT,
122
+ # AMOUNT
123
+ # ]
124
+ # ]
125
+ def detect_order(msg)
126
+ if msg[1][0].is_a?(Array)
127
+ msg[1].each do |point|
128
+ if point[2] > 0
129
+ @snap['bids'] << [point[0].to_s, point[2].to_s]
130
+ else
131
+ @snap['asks'] << [point[0].to_s, point[2].abs.to_s]
132
+ end
133
+ end
134
+ publish_snapshot
135
+ else
136
+ if @increment_count < MIN_INCREMENT_COUNT_TO_SNAPSHOT && @snapshot_time <= Time.now - MAX_PERIOD_TO_SNAPSHOT
137
+ publish_snapshot
138
+ @increment_count = 0
139
+ elsif @increment_count >= MIN_INCREMENT_COUNT_TO_SNAPSHOT && @snapshot_time < Time.now - MIN_PERIOD_TO_SNAPSHOT
140
+ publish_snapshot
141
+ @increment_count = 0
142
+ end
143
+
144
+ fill_increment(msg[1])
145
+ end
146
+ end
147
+
148
+ def fill_increment(order)
149
+ side = order[2].positive? ? 'bid' : 'ask'
150
+ price = order[0].to_s
151
+ if order[1].zero?
152
+ amount = 0
153
+ @snap["#{side}s"].delete_if { |point| point[0] == price }
154
+ else
155
+ amount = order[2].abs.to_s
156
+ @snap["#{side}s"].delete_if { |point| point[0] == price }
157
+ @snap["#{side}s"] << [price.to_s, amount.to_s]
158
+ end
159
+ if side == 'bid'
160
+ @bids.delete_if { |point| point[0] == price }
161
+ @bids << [price.to_s, amount.to_s]
162
+ elsif side == 'ask'
163
+ @asks.delete_if { |point| point[0] == price }
164
+ @asks << [price.to_s, amount.to_s]
165
+ end
166
+ @increment_count += 1
167
+ end
168
+
169
+ def publish_increment
170
+ inc = {}
171
+ inc['bids'] = @bids.sort.reverse if @bids.present?
172
+ inc['asks'] = @asks.sort if @asks.present?
173
+ if inc.present?
174
+ @sequence_number += 1
175
+ @peatio_mq.enqueue_event('public', @market, 'ob-inc',
176
+ 'bids' => inc['bids'], 'asks' => inc['asks'],
177
+ 'sequence' => @sequence_number)
178
+ end
179
+ @bids = []
180
+ @asks = []
181
+ end
182
+
183
+ def publish_snapshot
184
+ @snapshot_time = Time.now
185
+ @peatio_mq.enqueue_event('public', @market, 'ob-snap',
186
+ 'bids' => @snap['bids'].sort.reverse,
187
+ 'asks' => @snap['asks'].sort,
188
+ 'sequence' => @sequence_number)
189
+ end
190
+
68
191
  def message_event(msg)
69
192
  case msg['event']
70
193
  when 'subscribed'
71
194
  Rails.logger.info "Event: #{msg}"
195
+ @open_channels[msg['chanId']] = msg['channel']
72
196
  when 'error'
73
197
  Rails.logger.info "Event: #{msg} ignored"
74
198
  end
data/lib/irix/huobi.rb CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  module Irix
4
4
  class Huobi < Peatio::Upstream::Base
5
+ require 'time'
6
+
7
+ MIN_INCREMENT_COUNT_TO_SNAPSHOT = 100
8
+ MIN_PERIOD_TO_SNAPSHOT = 5
9
+ MAX_PERIOD_TO_SNAPSHOT = 60
10
+
11
+ attr_accessor :snap, :snapshot_time, :increment_count, :sequence_number,
12
+ :asks, :bids
5
13
  # WS huobi global
6
14
  # websocket: "wss://api.huobi.pro/ws/"
7
15
  # WS for krw markets
@@ -37,11 +45,72 @@ module Irix
37
45
  end
38
46
 
39
47
  case msg['ch']
40
- when /market\.([^.]+)\.trade\.detail/
48
+ when /market\.#{@target}\.trade\.detail/
41
49
  detect_trade(msg.dig('tick', 'data'))
50
+ when /market\.#{@target}\.mbp\.150/
51
+ detect_order(msg.dig('tick'))
52
+ end
53
+ end
54
+
55
+ def detect_order(msg)
56
+ if @increment_count < MIN_INCREMENT_COUNT_TO_SNAPSHOT && @snapshot_time <= Time.now - MAX_PERIOD_TO_SNAPSHOT
57
+ publish_snapshot
58
+ @increment_count = 0
59
+ elsif @increment_count >= MIN_INCREMENT_COUNT_TO_SNAPSHOT && @snapshot_time < Time.now - MIN_PERIOD_TO_SNAPSHOT
60
+ publish_snapshot
61
+ @increment_count = 0
62
+ end
63
+ fill_increment(msg)
64
+ end
65
+
66
+ def fill_increment(inc)
67
+ fill_side(inc, "bids")
68
+ fill_side(inc, "asks")
69
+ @increment_count += 1
70
+ end
71
+
72
+ def fill_side(inc, side)
73
+ inc[side].each do |price_point|
74
+ price = price_point[0]
75
+ amount = price_point[1]
76
+ if amount.zero?
77
+ @snap[side].delete_if { |point| point[0] == price.to_s }
78
+ else
79
+ @snap[side].delete_if { |point| point[0] == price.to_s }
80
+ @snap[side] << [price.to_s, amount.to_s]
81
+ end
82
+ if side == "bids"
83
+ @bids.delete_if { |point| point[0] == price }
84
+ @bids << [price.to_s, amount.to_s]
85
+ elsif side == "asks"
86
+ @asks.delete_if { |point| point[0] == price }
87
+ @asks << [price.to_s, amount.to_s]
88
+ end
42
89
  end
43
90
  end
44
91
 
92
+ def publish_increment
93
+ inc = {}
94
+ inc['bids'] = @bids.sort.reverse if @bids.present?
95
+ inc['asks'] = @asks.sort if @asks.present?
96
+ if inc.present?
97
+ @sequence_number += 1
98
+ @peatio_mq.enqueue_event('public', @market, 'ob-inc',
99
+ 'bids' => inc['bids'], 'asks' => inc['asks'],
100
+ 'sequence' => @sequence_number)
101
+ end
102
+ @bids = []
103
+ @asks = []
104
+ end
105
+
106
+ def publish_snapshot
107
+ @snapshot_time = Time.now
108
+ @peatio_mq.enqueue_event('public', @market, 'ob-snap',
109
+ 'bids' => @snap['bids'].sort.reverse,
110
+ 'asks' => @snap['asks'].sort,
111
+ 'sequence' => @sequence_number)
112
+ end
113
+
45
114
  def detect_trade(msg)
46
115
  msg.map do |t|
47
116
  trade =
@@ -69,6 +138,8 @@ module Irix
69
138
  end
70
139
 
71
140
  def subscribe_trades(market, ws)
141
+ return unless @config['trade_proxy']
142
+
72
143
  sub = {
73
144
  'sub' => "market.#{market}.trade.detail"
74
145
  }
@@ -78,5 +149,29 @@ module Irix
78
149
  ws.send(JSON.generate(sub))
79
150
  end
80
151
  end
152
+
153
+ def subscribe_orderbook(market, ws)
154
+ return unless @config['orderbook_proxy']
155
+
156
+ @sequence_number = 0
157
+ @increment_count = 0
158
+ @snapshot_time = Time.now
159
+ @bids = []
160
+ @asks = []
161
+ @snap = { 'asks' => [], 'bids' => [] }
162
+ sub = {
163
+ 'sub' => "market.#{market}.mbp.150"
164
+ }
165
+
166
+ Rails.logger.info 'Open event' + sub.to_s
167
+ EM.next_tick do
168
+ ws.send(JSON.generate(sub))
169
+ end
170
+ Fiber.new do
171
+ EM::Synchrony.add_periodic_timer(0.2) do
172
+ publish_increment
173
+ end
174
+ end.resume
175
+ end
81
176
  end
82
177
  end
data/lib/irix/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Irix
2
- VERSION = "2.4.2"
2
+ VERSION = "2.4.5"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: irix
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.2
4
+ version: 2.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Naichuk M.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-24 00:00:00.000000000 Z
11
+ date: 2020-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: em-synchrony