Class: Deribit::WS

Inherits:
Object
  • Object
show all
Defined in:
lib/deribit/ws.rb,
lib/deribit/ws/handler.rb

Defined Under Namespace

Classes: Handler

Constant Summary collapse

AVAILABLE_EVENTS =
[:order_book, :trade, :my_trade, :user_order, :index, :portfolio, :announcement]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key, secret, handler: Handler, test_server: nil) ⇒ WS

Returns a new instance of WS.



8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/deribit/ws.rb', line 8

def initialize(key, secret, handler: Handler, test_server: nil)
  @test_server = test_server || ENV["DERIBIT_TEST_SERVER"]
  @request     = Request.new(key, secret, test_server: test_server)
  @socket      = connect
  @handler     = handler.instance_of?(Class) ? handler.new : handler
  @ids_stack  = []

  # the structure of subscribed_instruments: {'event_name' => ['instrument1', 'instrument2']]}
  @subscribed_instruments = {}

  start_handle
end

Instance Attribute Details

#handlerObject (readonly)

Returns the value of attribute handler.



6
7
8
# File 'lib/deribit/ws.rb', line 6

def handler
  @handler
end

#ids_stackObject (readonly)

Returns the value of attribute ids_stack.



6
7
8
# File 'lib/deribit/ws.rb', line 6

def ids_stack
  @ids_stack
end

#responseObject (readonly)

Returns the value of attribute response.



6
7
8
# File 'lib/deribit/ws.rb', line 6

def response
  @response
end

#socketObject (readonly)

Returns the value of attribute socket.



6
7
8
# File 'lib/deribit/ws.rb', line 6

def socket
  @socket
end

#subscribed_instrumentsObject (readonly)

Returns the value of attribute subscribed_instruments.



6
7
8
# File 'lib/deribit/ws.rb', line 6

def subscribed_instruments
  @subscribed_instruments
end

#test_serverObject (readonly)

Returns the value of attribute test_server.



6
7
8
# File 'lib/deribit/ws.rb', line 6

def test_server
  @test_server
end

Instance Method Details

#accountObject



157
158
159
# File 'lib/deribit/ws.rb', line 157

def 
  send(path: '/api/v1/private/account')
end

#add_subscribed_instruments(instruments:, events:) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/deribit/ws.rb', line 21

def add_subscribed_instruments(instruments: , events: )
  instruments = [instruments] unless instruments.is_a?(Array)

  events.each do |event|
    _event = event.to_sym
    @subscribed_instruments[_event] = if sub_instr = @subscribed_instruments[_event]
                                        (sub_instr + instruments).uniq
                                      else
                                        instruments.uniq
                                      end
  end
end

#buy(instrument, quantity, price, type: "limit", stopPx: nil, execInst: "mark_price", post_only: nil, label: nil, max_show: nil, adv: nil) ⇒ Object

| Name | Type | Decription |

|--------------|------------|-----------------------------------------------------------------------------------|
| `instrument` | `string`   | Required, instrument name                                                         |
| `quantity`   | `integer`  | Required, quantity, in contracts ($10 per contract for futures, ฿1 — for options) |
| `price`      | `float`    | Required, USD for futures, BTC for options                                        |
| `type`       | `string`   | Required, "limit", "market" or for futures only: "stop_limit"                     |
| `stopPx`     | `string`   | Required, needed for stop_limit order, defines stop price                         |
| `post_only`  | `boolean`  | Optional, if true then the order will be POST ONLY                                |
| `label`      | `string`   | Optional, user defined maximum 32-char label for the order                        |
| `max_show`   | `string`   | Optional, optional parameter, if "0" then the order will be hidden                |
| `adv`        | `string`   | Optional, can be "implv", "usd", or absent (advanced order type)                  |


116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/deribit/ws.rb', line 116

def buy(instrument, quantity, price, type: "limit", stopPx: nil, execInst: "mark_price", post_only: nil, label: nil, max_show: nil, adv: nil)
  params = {
      instrument: instrument,
      quantity:   quantity
  }
  params[:price] = price if price

  %i(type stopPx post_only label max_show adv execInst).each do |var|
    variable = eval(var.to_s)
    params[var] = variable if variable
  end

  send(path: '/api/v1/private/buy', arguments: params)
end

#cancel(order_id) ⇒ Object



182
183
184
185
186
187
188
# File 'lib/deribit/ws.rb', line 182

def cancel(order_id)
  params = {
    "orderId": order_id
  }

  send(path: '/api/v1/private/cancel', arguments: params)
end

#cancel_all(type = "all") ⇒ Object



190
191
192
193
194
195
196
# File 'lib/deribit/ws.rb', line 190

def cancel_all(type = "all")
  params = {
    "type": type
  }

  send(path: '/api/v1/private/cancelall', arguments: params)
end

#closeObject



56
57
58
# File 'lib/deribit/ws.rb', line 56

def close
  @socket.close
end

#connectObject



34
35
36
37
38
# File 'lib/deribit/ws.rb', line 34

def connect
  url = test_server ? WS_TEST_URL : WS_SERVER_URL
  puts "Connecting to #{url}"
  WebSocket::Client::Simple.connect(url)
end

#currenciesObject



165
166
167
# File 'lib/deribit/ws.rb', line 165

def currencies
  send(path: '/api/v1/public/getcurrencies')
end

#handle_notifications(notifications) ⇒ Object



206
207
208
209
210
211
212
# File 'lib/deribit/ws.rb', line 206

def handle_notifications(notifications)
  return if notifications.empty?
  notification, *tail = notifications
  handler.send(notification[:message], notification[:result])

  handle_notifications(tail)
end

#instruments(expired: false) ⇒ Object



161
162
163
# File 'lib/deribit/ws.rb', line 161

def instruments(expired: false)
  send(path: '/api/v1/public/getinstruments', arguments: {expired: expired})
end

#openorders(instrument: "BTC-PERPETUAL", order_id: nil, type: nil) ⇒ Object



173
174
175
176
177
178
179
180
# File 'lib/deribit/ws.rb', line 173

def openorders(instrument: "BTC-PERPETUAL", order_id: nil, type: nil)
  params = {}
  params[:instrument] = instrument if instrument
  params[:orderId]    = order_id if order_id
  params[:type]       = type if type

  send(path: '/api/v1/private/getopenorders', arguments: params)
end

#pingObject



60
61
62
63
# File 'lib/deribit/ws.rb', line 60

def ping
  message = {action: "/api/v1/public/ping"}
  @socket.send(message.to_json)
end

#reconnect!Object



40
41
42
43
44
45
# File 'lib/deribit/ws.rb', line 40

def reconnect!
  @socket = connect
  start_handle
  sleep 3
  resubscribe!
end

#resubscribe!Object



47
48
49
50
51
52
53
54
# File 'lib/deribit/ws.rb', line 47

def resubscribe!
  if subscribed_instruments.any?
    subscribed_instruments.each do |event, instruments|
      p "Reconnecting to event: #{event} at instrument: #{instruments}"
      subscribe(instruments, events: event.to_s)
    end
  end
end

#sell(instrument, quantity, price, type: "limit", stopPx: nil, execInst: "mark_price", post_only: nil, label: nil, max_show: nil, adv: nil) ⇒ Object

| Name | Type | Decription |

|--------------|------------|-----------------------------------------------------------------------------------|
| `instrument` | `string`   | Required, instrument name                                                         |
| `quantity`   | `integer`  | Required, quantity, in contracts ($10 per contract for futures, ฿1 — for options) |
| `price`      | `float`    | Required, USD for futures, BTC for options                                        |
| `post_only`  | `boolean`  | Optional, if true then the order will be POST ONLY                                |
| `label`      | `string`   | Optional, user defined maximum 32-char label for the order                        |
| `max_show`   | `string`   | Optional, optional parameter, if "0" then the order will be hidden                |
| `adv`        | `string`   | Optional, can be "implv", "usd", or absent (advanced order type)                  |


142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/deribit/ws.rb', line 142

def sell(instrument, quantity, price, type: "limit", stopPx: nil, execInst: "mark_price", post_only: nil, label: nil, max_show: nil, adv: nil)
  params = {
      instrument: instrument,
      quantity:   quantity
  }
  params[:price] = price if price

  %i(type stopPx post_only label max_show adv execInst).each do |var|
    variable = eval(var.to_s)
    params[var] = variable if variable
  end

  send(path: '/api/v1/private/sell', arguments: params)
end

#set_heartbeat(interval = "60") ⇒ Object



198
199
200
201
202
203
204
# File 'lib/deribit/ws.rb', line 198

def set_heartbeat(interval = "60")
  params = {
    "interval": interval.to_s
  }

  send(path: '/api/v1/public/setheartbeat', arguments: params)
end

#subscribe(instruments = ['BTC-PERPETUAL'], events: ["user_order"], arguments: {}) ⇒ Object

events to be reported, possible events: “order_book” – order book change “trade” – trade notification “announcements” – announcements (list of new announcements titles is send) “user_order” – change of user orders (openning, cancelling, filling) “my_trade” – filtered trade notification, only trades of the subscribed user are reported with trade direction “buy”/“sell” from the subscribed user point of view (“I sell …”, “I buy …”), see below. Note, for “index” - events are ignored and can be []



79
80
81
82
83
84
85
86
87
88
# File 'lib/deribit/ws.rb', line 79

def subscribe(instruments = ['BTC-PERPETUAL'] , events: ["user_order"], arguments: {})
  instruments = [instruments]  unless instruments.is_a?(Array)
  events = [events]  unless events.is_a?(Array)

  raise "Events must include only #{AVAILABLE_EVENTS.join(", ")} actions" if events.map{|e| AVAILABLE_EVENTS.include?(e.to_sym)}.index(false) or events.empty?
  raise "instruments are required" if instruments.empty?

  arguments = arguments.merge(instrument: instruments, event: events)
  send(path: '/api/v1/private/subscribe', arguments: arguments)
end

#summary(instrument = 'BTC-PERPETUAL') ⇒ Object



169
170
171
# File 'lib/deribit/ws.rb', line 169

def summary(instrument = 'BTC-PERPETUAL')
  send(path: '/api/v1/public/getsummary', arguments: { instrument: instrument })
end

#testObject



65
66
67
68
# File 'lib/deribit/ws.rb', line 65

def test
  message = {action: "/api/v1/public/test"}
  @socket.send(message.to_json)
end

#unsubscribe(instruments = []) ⇒ Object

unsubscribe for all notifications if instruments is empty



91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/deribit/ws.rb', line 91

def unsubscribe(instruments=[])
  instruments = [instruments] unless instruments.is_a?(Array)
  send(path: '/api/v1/private/unsubscribe')
  sleep(0.2)
  if instruments.any?
    @subscribed_instruments.each do |event, _instruments|
      @subscribed_instruments[event] = _instruments - instruments
      subscribe(@subscribed_instruments[event], events: [event])
      sleep(0.2)
    end
  end
end