class Deribit::WS
Constants
- AVAILABLE_EVENTS
Attributes
Public Class Methods
# 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
Public Instance Methods
# File lib/deribit/ws.rb, line 157 def account send(path: '/api/v1/private/account') end
# 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
| 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) |
# 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
# File lib/deribit/ws.rb, line 182 def cancel(order_id) params = { "orderId": order_id } send(path: '/api/v1/private/cancel', arguments: params) end
# File lib/deribit/ws.rb, line 190 def cancel_all(type = "all") params = { "type": type } send(path: '/api/v1/private/cancelall', arguments: params) end
# File lib/deribit/ws.rb, line 56 def close @socket.close end
# 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
# File lib/deribit/ws.rb, line 165 def currencies send(path: '/api/v1/public/getcurrencies') end
# 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
# File lib/deribit/ws.rb, line 161 def instruments(expired: false) send(path: '/api/v1/public/getinstruments', arguments: {expired: expired}) end
# 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
# File lib/deribit/ws.rb, line 60 def ping message = {action: "/api/v1/public/ping"} @socket.send(message.to_json) end
# File lib/deribit/ws.rb, line 40 def reconnect! @socket = connect start_handle sleep 3 resubscribe! end
# 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
| 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) |
# 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
# 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
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 []
# 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
# File lib/deribit/ws.rb, line 169 def summary(instrument = 'BTC-PERPETUAL') send(path: '/api/v1/public/getsummary', arguments: { instrument: instrument }) end
# File lib/deribit/ws.rb, line 65 def test message = {action: "/api/v1/public/test"} @socket.send(message.to_json) end
unsubscribe for all notifications if instruments is empty
# 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
Private Instance Methods
# File lib/deribit/ws.rb, line 282 def pop_id(id) @ids_stack.delete(id) end
# File lib/deribit/ws.rb, line 278 def put_id(id, action) @ids_stack << {id => action} end
# File lib/deribit/ws.rb, line 263 def send(path: , arguments: {}) return unless path params = {action: path, arguments: arguments} sig = @request.generate_signature(path, arguments) params[:sig] = sig params[:id] = Time.now.to_i action = path[/\/api.*\/([^\/]+)$/, 1] put_id(params[:id], [action, params]) p params @socket.send(params.to_json) end
# File lib/deribit/ws.rb, line 216 def start_handle instance = self @socket.on :message do |msg| # puts "msg = #{msg.inspect}" begin if msg.type == :text json = JSON.parse(msg.data, symbolize_names: true) puts "Subscribed!" if json[:message] == "subscribed" # puts "Got json: #{json}" if json[:message] == "test_request" # puts "Got test request: #{json.inspect}" # DEBUG instance.test elsif json[:id] and stack_id = instance.ids_stack.find{|i| i[json[:id]]} method = stack_id[json[:id]][0] #pass the method to handler params = instance.ids_stack.delete(stack_id) #save subscribed_instruments for resubscribe in unsubscribe action if method == 'subscribe' params = params[json[:id]][1][:arguments] instance.add_subscribed_instruments(instruments: params[:instrument], events: params[:event]) end instance.handler.send(method, json) elsif json[:notifications] instance.handle_notifications(json[:notifications]) else instance.handler.send(:notice, json) end # puts "Want to update timestamp for handler for event: #{json.inspect}" instance.handler.update_timestamp! elsif msg.type == :close puts "trying to reconnect = got close event, msg: #{msg.inspect}" instance.reconnect! end rescue StandardError => e instance.handler.handle_error(json, e) end end @socket.on :error do |e| puts e end end