deribit-api 0.1.3 → 2.0.2

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.
data/TODOs.org CHANGED
@@ -1,4 +1,9 @@
1
+ #+TODO: TODO | DONE FAIL N/A
1
2
  * Tasks :DERIBIT:
3
+ :PROPERTIES:
4
+ :CATEGORY: deribit
5
+ :CREATED: 20200309
6
+ :END:
2
7
  ** DONE Initial deribit gem release
3
8
  CLOSED: [2019-01-04 Fri] SCHEDULED: <2019-01-04 Fri>
4
9
  ** DONE public HTTP API
@@ -24,18 +29,25 @@
24
29
  CLOCK: [2019-04-17 Wed 17:55]--[2019-04-17 Wed 18:26] => 0:31
25
30
  CLOCK: [2019-04-16 Tue 12:23]--[2019-04-16 Tue 18:16] => 5:53
26
31
  :END:
27
- ** response middleware
32
+ ** N/A response middleware
28
33
  ** check key/secret present for private endpoints
29
34
  ** DONE fix trade history
30
35
  CLOSED: [2019-04-23 Tue 15:17]
31
- ** research async websocket implementation
36
+ ** DONE research async websocket implementation
32
37
  ** cleanup 'params' for both http and websocket
33
- ** update buy/sell endpoints with new params
34
- ** TODO Deribit implementation
35
- SCHEDULED: <2019-08-02 Tue +1m>
38
+ ** DONE update buy/sell endpoints with new params
39
+ ** DONE initial 2.0 API implementaion
40
+ ** DONE refactor Naming module
41
+ ** TODO deribit-api-ruby maintenance
42
+ SCHEDULED: <2020-12-09 Wed +6m>
36
43
  :PROPERTIES:
37
- :LAST_REPEAT: [2019-07-02 Tue 13:01]
44
+ :LAST_REPEAT: [2020-06-10 Wed 07:36]
38
45
  :END:
46
+ - State "DONE" from "TODO" [2020-06-10 Wed 07:36]
47
+ - State "DONE" from "TODO" [2020-05-13 Wed 14:14]
48
+ - State "DONE" from "TODO" [2020-04-23 Thu 13:25]
49
+ - State "DONE" from "TODO" [2020-01-09 Thu 18:00]
50
+ - State "DONE" from "TODO" [2019-10-21 Mon 14:43]
39
51
  - State "DONE" from "TODO" [2019-07-02 Tue 13:01]
40
52
  - State "DONE" from "TODO" [2019-04-23 Tue 15:24]
41
53
  - State "DONE" from "TODO" [2019-04-17 Wed 18:26]
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env sh
2
+
3
+ source .env
4
+
5
+ ClientId=$API_KEY
6
+ ClientSecret=$API_SECRET
7
+ Timestamp=$( date +%s000 )
8
+ Nonce=$( cat /dev/urandom | tr -dc 'a-z0-9' | head -c8 )
9
+ URI="/api/v2/private/get_account_summary?currency=BTC"
10
+ HttpMethod=GET
11
+ Body=""
12
+
13
+ Data="${Timestamp}\n${Nonce}\n${HttpMethod}\n${URI}\n${Body}\n"
14
+ echo $Data
15
+ Signature=$( echo -ne $Data | openssl sha256 -r -hmac "$ClientSecret" | cut -f1 -d' ' )
16
+ echo $Signature
17
+
18
+ curl -s -X ${HttpMethod} -H "Authorization: deri-hmac-sha256 id=${ClientId},ts=${Timestamp},nonce=${Nonce},sig=${Signature}" "https://test.deribit.com${URI}"
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env python
2
+
3
+ import asyncio
4
+ import websockets
5
+ import json
6
+
7
+ # To subscribe to this channel:
8
+ msg = \
9
+ {"jsonrpc": "2.0",
10
+ "method": "public/subscribe",
11
+ "id": 42,
12
+ "params": {
13
+ "channels": ["trades.future.BTC.100ms"]}
14
+ }
15
+
16
+ async def call_api(msg):
17
+ async with websockets.connect('wss://test.deribit.com/ws/api/v2') as websocket:
18
+ await websocket.send(msg)
19
+ while websocket.open:
20
+ response = await websocket.recv()
21
+ # do something with the notifications...
22
+ print(response)
23
+
24
+ asyncio.get_event_loop().run_until_complete(call_api(json.dumps(msg)))
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'rubygems'
5
+ require 'websocket-client-simple'
6
+ require 'json'
7
+
8
+ ws = WebSocket::Client::Simple.connect 'wss://www.deribit.com/ws/api/v2'
9
+
10
+ ws.on :message do |msg|
11
+ p "msg: #{msg.data}"
12
+ end
13
+
14
+ ws.on :open do |e|
15
+ p "open: #{e}"
16
+ end
17
+
18
+ ws.on :close do |e|
19
+ p "close: #{e}"
20
+ exit 1
21
+ end
22
+
23
+ ws.on :error do |e|
24
+ p "error: #{e}"
25
+ end
26
+
27
+ sleep 3
28
+
29
+ puts 'Subscribing...'
30
+ payload = {
31
+ 'jsonrpc' => '2.0',
32
+ 'method' => 'public/subscribe',
33
+ 'id' => 66,
34
+ 'params' => {
35
+ 'channels' => ['trades.BTC-PERPETUAL.raw']
36
+ }
37
+ }
38
+ ws.send payload.to_json.to_s
39
+
40
+ while ws.open? do
41
+ sleep 1
42
+ puts 'Running...'
43
+ end
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'deribit-api'
5
+
6
+ puts "==> Watching BTC/ETH whales...\n"
7
+
8
+ client = Deribit::Client.new
9
+
10
+ # for BTC
11
+ client.trades instrument_name: 'BTC-PERPETUAL' do |trade|
12
+ baseNotional = trade.amount / trade.price
13
+ puts "BTC: #{trade.direction} #{baseNotional} @ #{trade.price}" if baseNotional > 1
14
+ end
15
+
16
+ # for ETH
17
+ client.trades instrument_name: 'ETH-PERPETUAL' do |trade|
18
+ baseNotional = trade.amount / trade.price
19
+ puts "ETH: #{trade.direction} #{baseNotional} @ #{trade.price}" if baseNotional > 10
20
+ end
21
+
22
+ # endless
23
+ loop do
24
+ sleep 1
25
+ end
@@ -7,10 +7,10 @@ Gem::Specification.new do |spec|
7
7
  spec.name = 'deribit-api'
8
8
  spec.version = Deribit::VERSION
9
9
  spec.authors = ['Iulian Costan']
10
- spec.email = ['iulian.costan@gmail.com']
10
+ spec.email = ['deribit-api@iuliancostan.com']
11
11
 
12
- spec.summary = %q{Ruby library for Deribit API}
13
- spec.description = %q{Ruby library for Deribit API}
12
+ spec.summary = %q{Idiomatic Ruby library for Deribit API 2.0}
13
+ spec.description = %q{Idiomatic Ruby library for Deribit API 2.0}
14
14
  spec.homepage = 'https://github.com/icostan/deribit-api-ruby'
15
15
 
16
16
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
@@ -37,8 +37,9 @@ Gem::Specification.new do |spec|
37
37
 
38
38
  spec.add_dependency 'faraday'
39
39
  spec.add_dependency 'faraday_middleware'
40
+ spec.add_dependency 'faraday-detailed_logger'
41
+ spec.add_dependency 'websocket-client-simple'
40
42
  spec.add_dependency 'hashie'
41
- spec.add_dependency 'faye-websocket'
42
43
 
43
44
  spec.add_development_dependency 'bundler'
44
45
  spec.add_development_dependency 'dotenv'
@@ -49,4 +50,7 @@ Gem::Specification.new do |spec|
49
50
  spec.add_development_dependency 'pry-doc'
50
51
  spec.add_development_dependency 'reek'
51
52
  spec.add_development_dependency 'simplecov'
53
+ spec.add_development_dependency 'rubocop'
54
+ spec.add_development_dependency 'solargraph'
55
+ spec.add_development_dependency 'irb'
52
56
  end
@@ -1,27 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openssl'
1
4
  require 'faraday'
2
5
  require 'faraday_middleware'
6
+ require 'faraday/detailed_logger'
3
7
  require 'hashie'
4
- require 'faye/websocket'
8
+ # require 'faye/websocket'
9
+ require 'websocket-client-simple'
5
10
 
6
11
  require 'deribit/version'
7
12
  require 'deribit/client'
8
13
  require 'deribit/authentication'
9
14
  require 'deribit/websocket'
10
15
  require 'deribit/http'
16
+ require 'deribit/naming'
11
17
 
12
18
  # Root module
13
19
  module Deribit
14
20
  # Base error class
15
21
  class Error < StandardError; end
22
+ class NotImplementedError < Error; end
16
23
 
17
- # @see https://docs.deribit.com/rpc-authentication.html
18
- def self.signature(key, nonce, params, query)
19
- signature_string = params.map { |k, v| "#{k}=#{v}" }.sort.join '&'
20
- signature_string += "&#{query}" if query
24
+ # @see https://docs.deribit.com/#authentication
25
+ def self.http_signature(env, timestamp, nonce, secret)
26
+ # RequestData = UPPERCASE(HTTP_METHOD()) + "\n" + URI() + "\n" + RequestBody + "\n";
27
+ uri = env['url'].path.dup
28
+ uri << '?' << env['url'].query if env['url'].query
29
+ request_data = [env['method'].upcase, uri, env['body'], ''].join "\n"
21
30
 
22
- signature_digest = Digest::SHA256.digest signature_string
23
- signature_hash = Base64.encode64 signature_digest
31
+ signature timestamp, nonce, request_data, secret
32
+ end
24
33
 
25
- "#{key}.#{nonce}.#{signature_hash.chomp}"
34
+ # @see https://docs.deribit.com/#authentication
35
+ def self.signature(timestamp, nonce, data, secret)
36
+ # StringToSign = Timestamp + "\n" + Nonce + "\n" + Data;
37
+ # Signature = HEX_STRING( HMAC-SHA256( ClientSecret, StringToSign ) );
38
+ string_to_sign = [timestamp, nonce, data].join "\n"
39
+ ::OpenSSL::HMAC.hexdigest('SHA256', secret, string_to_sign)
26
40
  end
27
41
  end
@@ -3,7 +3,8 @@ require 'digest'
3
3
 
4
4
  module Deribit
5
5
  # Deribit authentication implemented as Faraday middleware
6
- # @see https://docs.deribit.com/rpc-authentication.html
6
+ # @author Iulian Costan (deribit-api@iuliancostan.com)
7
+ # @see https://docs.deribit.com/#authentication
7
8
  class Authentication < Faraday::Middleware
8
9
  def initialize(app, key, secret)
9
10
  super(app)
@@ -12,25 +13,20 @@ module Deribit
12
13
  end
13
14
 
14
15
  def call(env)
16
+ return @app.call(env) if env['url'].path.include? 'public'
15
17
  return @app.call(env) if @key.nil? || @secret.nil?
16
18
 
17
- nonce = Time.now.to_i
18
- env['request_headers']['X-Deribit-Sig'] = signature env, nonce
19
+ timestamp = Time.now.utc.to_i * 1000
20
+ nonce = rand(999999)
21
+ env.request_headers['Authorization'] = header env, timestamp, nonce
19
22
 
20
23
  @app.call env
21
24
  end
22
25
 
23
- def signature(env, nonce)
24
- params = {
25
- _: nonce,
26
- _ackey: @key,
27
- _acsec: @secret,
28
- _action: env['url'].path
29
- }
30
- params.merge! JSON.parse(env['body']) if env['body']
31
- query = env['url'].query
32
-
33
- Deribit.signature @key, nonce, params, query
26
+ # @return the HTTP header: "Authorization: deri-hmac-sha256 id=ClientId,ts=Timestamp,sig=Signature,nonce=Nonce"
27
+ def header(env, timestamp, nonce)
28
+ signature = Deribit.http_signature env, timestamp, nonce, @secret
29
+ "deri-hmac-sha256 id=#{@key},ts=#{timestamp},sig=#{signature},nonce=#{nonce}"
34
30
  end
35
31
  end
36
32
  end
@@ -1,11 +1,14 @@
1
+ # frozen_string_literal: true
2
+ require 'deribit/naming'
3
+
1
4
  module Deribit
2
- # @author Iulian Costan
3
- class Client
4
- # URL for testnet
5
- TESTNET_URL = 'test.deribit.com'
6
- # URL for mainnet
7
- MAINNET_URL = 'www.deribit.com'
5
+ TESTNET_HOST = 'test.deribit.com'
6
+ MAINNET_HOST = 'www.deribit.com'
8
7
 
8
+ # Deribit API 2.0 client implementation
9
+ # @author Iulian Costan (deribit-api@iuliancostan.com)
10
+ class Client
11
+ include Naming
9
12
  attr_reader :http, :websocket
10
13
 
11
14
  # Create new instance
@@ -15,469 +18,313 @@ module Deribit
15
18
  # @param debug [Boolean] set to true for debug output
16
19
  # @return [Deribit::Client] the instance of client
17
20
  def initialize(key: nil, secret: nil, testnet: false, debug: false)
18
- host = testnet ? TESTNET_URL : MAINNET_URL
19
- @http = Deribit::Http.new host, key: key, secret: secret
21
+ host = testnet ? TESTNET_HOST : MAINNET_HOST
22
+ @http = Deribit::Http.new host, key: key, secret: secret, debug: debug
20
23
  @websocket = Deribit::Websocket.new host, key: key, secret: secret
21
24
  end
22
25
 
23
- # Retrieves the current time (in ms).
24
- # @return [Integer] current time in milliseconds
25
- # @yield [Integer] current time in milliseconds
26
- # @see https://docs.deribit.com/rpc-endpoints.html#time
27
- def time(&blk)
28
- if block_given?
29
- websocket.subscribe :time, &blk
30
- else
31
- http.get :time
32
- end
33
- end
34
-
35
- # Signals the Websocket connection to send and request heartbeats.
36
- # @param interval [Integer] The heartbeat interval
37
- # @yield [String] 'ok' on success, error message otherwise
38
- # @see https://docs.deribit.com/rpc-endpoints.html#setheartbeat
39
- def enable_heartbeat(interval = 60, &blk)
40
- raise 'This API endpoint cannot be used over HTTP.' unless block_given?
41
-
42
- websocket.subscribe :setheartbeat, params: { interval: interval }, &blk
43
- end
44
-
45
- # Signals the Websocket connection to not send or request heartbeats.
46
- # @yield [String] 'ok' on success, error message otherwise
47
- # @see https://docs.deribit.com/rpc-endpoints.html#cancelheartbeat
48
- def cancel_heartbeat(&blk)
49
- raise 'This API endpoint cannot be used over HTTP.' unless block_given?
50
-
51
- websocket.subscribe :cancelheartbeat, &blk
52
- end
53
-
54
- # Tests the connection to the API server, and returns its version.
55
- # @param exception [any] Provide this parameter force an error message.
56
- # @return [Hashie::Mash] test data
57
- # @yield [Hashie::Mash] test data
58
- # @see https://docs.deribit.com/rpc-endpoints.html#test
59
- def test(exception: false, &blk)
60
- params = { exception: exception }
61
- if block_given?
62
- websocket.subscribe :test, params: params, &blk
63
- else
64
- http.get :test, params: params, raw_body: true
65
- end
66
- end
67
-
68
- # This API endpoint always responds with "pong".
69
- # @return [String] pong
70
- # @yield [String] pong
71
- # @see https://docs.deribit.com/rpc-endpoints.html#ping
72
- def ping(&blk)
73
- if block_given?
74
- websocket.subscribe :ping, &blk
75
- else
76
- http.get :ping
77
- end
78
- end
79
-
80
26
  # Retrieves available trading instruments.
81
- # @param expired [Boolean] Set to true to show expired instruments instead of active ones.
27
+ # @param options [Hash]
28
+ # @option options [String] :currency the currency to get instruments for
29
+ # @option options [String] :kind instrument kind, if not provided instruments of all kinds are considered
30
+ # @option options [Integer] :expired set to true to show expired instruments instead of active ones.
82
31
  # @return [Array] the list of instruments
83
- # @yield [Hashie::Mash] the instrument
84
- # @see https://docs.deribit.com/rpc-endpoints.html#getinstruments
85
- def instruments(expired: false, &blk)
86
- params = { expired: expired }
87
- if block_given?
88
- websocket.subscribe :getinstruments, params: params, &blk
89
- else
90
- http.get :getinstruments, params: params
91
- end
32
+ # @see https://docs.deribit.com/#public-get_instruments
33
+ def instruments(options = { currency: 'BTC' })
34
+ raise ArgumentError, 'currency is required' unless options[:currency]
35
+
36
+ http.get '/public/get_instruments', options
92
37
  end
93
38
 
94
39
  # Retrieves all cryptocurrencies supported by the API.
95
40
  # @return [Array] the list of cryptocurrencies
96
- # @yield [Hashie:Hash] the currency
97
- # @see https://docs.deribit.com/rpc-endpoints.html#getcurrencies
98
- def currencies(&blk)
99
- if block_given?
100
- websocket.subscribe :getcurrencies, &blk
101
- else
102
- http.get :getcurrencies
103
- end
41
+ # @see https://docs.deribit.com/#public-get_currencies
42
+ def currencies
43
+ http.get '/public/get_currencies'
104
44
  end
105
45
 
106
46
  # Retrieves the current index price for the BTC-USD instruments.
107
- # @param currency [String] the currency to get index for
47
+ # @param options [Hash]
48
+ # @option options [String] :currency the currency to get instruments for
108
49
  # @return [Hashie::Mash] index price for BTC-USD instrument
109
- # @yield [Hashie::Mash] index price for BTC-USD instrument
110
- # @see https://docs.deribit.com/rpc-endpoints.html#index
111
- def index(currency = 'BTC', &blk)
112
- params = { currency: currency }
113
- if block_given?
114
- websocket.subscribe :index, params: params, &blk
115
- else
116
- http.get :index, params: params
50
+ # @see https://docs.deribit.com/#public-get_index
51
+ def index(options = { currency: 'BTC' })
52
+ unless options[:currency]
53
+ raise ArgumentError, 'currency argument is required'
117
54
  end
55
+
56
+ http.get '/public/get_index', options
118
57
  end
119
58
 
120
- # Retrieves the order book, along with other market values for a given instrument.
121
- # @param instrument [String] The instrument name for which to retrieve the order book, (see #instruments) to obtain instrument names.
122
- # @param depth [Integer] the depth of the order book
59
+ # Notifies about changes to the order book for a certain instrument.
60
+ # @param instrument_name [String] The instrument name
61
+ # @param options [Hash]
62
+ # @option options [String] :instrument_name (BTC-PERPETUAL) Instrument to return open orders for
63
+ # @option options [Integer] :group (5) Group prices (by rounding): none, 5, 10
64
+ # @option options [Integer] :depth (10) the depth of the order book
65
+ # @option options [String] :interval (raw) Frequency of notifications: raw, 100ms
123
66
  # @return [Hashie::Mash] the order book
124
67
  # @yield [Hashie::Mash] the order book
125
- # @see https://docs.deribit.com/rpc-endpoints.html#getorderbook
126
- def orderbook(instrument, depth: 10, &blk)
127
- raise ArgumentError, 'instrument param is required' unless instrument
68
+ # @see https://docs.deribit.com/#book-instrument_name-group-depth-interval
69
+ # @see https://docs.deribit.com/#book-instrument_name-interval
70
+ def book(options = { instrument_name: 'BTC-PERPETUAL' }, &blk)
71
+ unless options[:instrument_name]
72
+ raise ArgumentError, 'instrument_name argument is required'
73
+ end
128
74
 
129
- params = { instrument: instrument, depth: depth }
130
75
  if block_given?
131
- websocket.subscribe :getorderbook, params: params, &blk
76
+ channel = book_channel options
77
+ websocket.subscribe channel, params: {}, &blk
132
78
  else
133
- http.get :getorderbook, params: params
79
+ http.get '/public/get_order_book', options
134
80
  end
135
81
  end
136
82
 
137
- # Retrieve the latest trades that have occurred for a specific instrument.
138
- # @param instrument [String] Either the name of the instrument, or "all" for all active instruments, "futures" for all active futures, or "options" for all active options.
83
+ # Retrieve the latest trades that have occurred for instruments in a specific currency symbol/for a specific instrument and optionally within given time range.
139
84
  # @!macro deribit.filters
140
- # @param filters [Hash] extra filters to apply
141
- # @option filters [Integer] :count (10) The number of trades returned (clamped to max 1000)
142
- # @option filters [Integer] :startId The ID of the first trade to be returned
143
- # @option filters [Integer] :endId The ID of the last trade to be returned
144
- # @option filters [Integer] :startSeq The trade sequence of the first trade to be returned
145
- # @option filters [Integer] :endSeq The trade sequence of the last trade to be returned
146
- # @option filters [Integer] :startTimestamp The timestamp (in ms) of the first trade to be returned
147
- # @option filters [Integer] :endTimestamp The timestamp (in ms) of the last trade to be returned
148
- # @option filters [Boolean] :includeOld (false) to get archived trades for expired instruments when true (added from performance considerations)
85
+ # @param filters [Hash] filters to apply
86
+ # @option filters [String] :instrument_name (BTC-PERPETUAL) Instrument name
87
+ # @option filters [String] :currency (BTC, ETH) The currency symbol
88
+ # @option filters [String] :kind (future, option) Instrument kind, if not provided instruments of all kinds are considered
89
+ # @option filters [Integer] :count (10) Number of requested items
90
+ # @option filters [Integer] :start_id The ID of the first trade to be returned
91
+ # @option filters [Integer] :end_id The ID of the last trade to be returned
92
+ # @option filters [Integer] :start_seq The trade sequence of the first trade to be returned
93
+ # @option filters [Integer] :end_seq The trade sequence of the last trade to be returned
94
+ # @option filters [Integer] :start_timestamp The timestamp (in ms) of the first trade to be returned
95
+ # @option filters [Integer] :end_timestamp The timestamp (in ms) of the last trade to be returned
96
+ # @option filters [Boolean] :include_old (false) Include trades older than a few recent days
97
+ # @option filters [Boolean] :sorting (none) Direction of results sorting
98
+ # @option filters [String] :interval (raw) Frequency of notifications.
149
99
  # @return [Array] the list of trades
150
100
  # @yield [Hashie::Mash] new trade
151
- # @see https://docs.deribit.com/rpc-endpoints.html#getlasttrades
152
- def trades(instrument = :all, filters = {}, &blk)
153
- raise ArgumentError, 'instrument param is required' unless instrument
154
-
155
- params = filters.merge(instrument: instrument)
156
- if block_given?
157
- websocket.subscribe :getlasttrades, params: params, &blk
158
- else
159
- http.get :getlasttrades, params: params
160
- end
161
- end
162
-
163
- # Retrieves the summary information such as open interest, 24h volume, etc. for a specific instrument.
164
- # @param instrument [String] Either the name of the instrument, or 'all' for all active instruments, 'futures' for all active futures, or 'options' for all active options.
165
- # @return [Array, Hashie::Mash] the summary as array or hash based on instrument param
166
- # @yield [Hashie::Mash] the summary
167
- # @see https://docs.deribit.com/rpc-endpoints.html#getsummary
168
- def summary(instrument = :all, &blk)
169
- raise ArgumentError, 'instrument argument is required' unless instrument
170
-
171
- params = { instrument: instrument }
172
- if block_given?
173
- websocket.subscribe :getsummary, params: params, &blk
174
- else
175
- http.get :getsummary, params: params
101
+ # @see https://docs.deribit.com/#public-get_last_trades_by_currency
102
+ # @see https://docs.deribit.com/#public-get_last_trades_by_currency_and_time
103
+ # @see https://docs.deribit.com/#public-get_last_trades_by_instrument
104
+ # @see https://docs.deribit.com/#public-get_last_trades_by_instrument_and_time
105
+ # @see https://docs.deribit.com/#private-get_user_trades_by_currency
106
+ # @see https://docs.deribit.com/#private-get_user_trades_by_currency_and_time
107
+ # @see https://docs.deribit.com/#private-get_user_trades_by_instrument
108
+ # @see https://docs.deribit.com/#private-get_user_trades_by_instrument_and_time
109
+ # @see https://docs.deribit.com/#trades-instrument_name-interval
110
+ # @see https://docs.deribit.com/#trades-kind-currency-interval
111
+ # @see https://docs.deribit.com/#user-trades-instrument_name-interval
112
+ # @see https://docs.deribit.com/#user-trades-kind-currency-interval
113
+ def trades(filters, &blk)
114
+ instrument_name = filters[:instrument_name]
115
+ currency = filters[:currency]
116
+ unless instrument_name || currency
117
+ raise ArgumentError, 'either :instrument_name or :currency args is required'
176
118
  end
177
- end
178
119
 
179
- # Retrieves aggregated 24h trade volumes for different instrument types.
180
- # @return [Hashie::Mash] the statistics
181
- # @yield [Hashie::Mash] the statistics
182
- # @see https://docs.deribit.com/rpc-endpoints.html#stats
183
- def stats(&blk)
184
120
  if block_given?
185
- websocket.subscribe :stats, &blk
121
+ channel = trades_channel filters
122
+ websocket.subscribe channel, params: {}, &blk
186
123
  else
187
- http.get :stats
124
+ uri = trades_uri filters
125
+ response = http.get uri, filters
126
+ response.trades
188
127
  end
189
128
  end
190
129
 
191
130
  # Retrieves announcements from last 30 days.
192
131
  # @return [Array] the list of announcements
193
132
  # @yield [Hashie::Mash] the announcement
194
- # @see https://docs.deribit.com/rpc-endpoints.html#getannouncements
133
+ # @see https://docs.deribit.com/#public-get_announcements
134
+ # @see https://docs.deribit.com/#announcements
195
135
  def announcements(&blk)
196
136
  if block_given?
197
- websocket.subscribe :getannouncements, &blk
137
+ websocket.subscribe 'announcements', &blk
198
138
  else
199
- http.get :getannouncements
139
+ http.get '/public/get_announcements'
200
140
  end
201
141
  end
202
142
 
203
143
  # Retrieves settlement, delivery and bankruptcy events that have occurred.
204
144
  # @param filters [Hash] the filters
205
- # @option filters [String] :instrument The instrument name, or "all" to retrieve settlements for all instruments
206
- # @option filters [Integer] :count (10) The number of entries to be returned. This is clamped to max 1000
207
- # @option filters [String] :type The type of settlements to return. Possible values "settlement", "delivery", "bankruptcy"
208
- # @option filters [Integer] :startTstamp The latest timestamp to return result for
209
- # @option filters [String] :continuation Continuation token for pagination. Each response contains a token to be used for continuation
145
+ # @option filters [String] :instrument_name The instrument name,
146
+ # @option filters [String] :currency The currency of settlements
147
+ # @option filters [String] :type settlement type: settlement delivery bankruptcy
148
+ # @option filters [Integer] :count (20) Number of requested items, default
149
+ # @option filters [String] :continuation Continuation token for pagination
210
150
  # @return [Hashie::Mash] the settlements
211
151
  # @yield [Hashie::Mash] the settlements
212
- # @see https://docs.deribit.com/rpc-endpoints.html#getlastsettlements
213
- def settlements(filters = {}, &blk)
152
+ # @see https://docs.deribit.com/#public-get_last_settlements_by_instrument
153
+ # @see https://docs.deribit.com/#public-get_last_settlements_by_currency
154
+ def settlements(filters = { instrument_name: 'BTC-PERPETUAL' })
155
+ instrument_name = filters[:instrument_name]
156
+ currency = filters[:currency]
157
+ unless instrument_name || currency
158
+ raise ArgumentError, 'either :instrument_name or :currency arg is required'
159
+ end
160
+
214
161
  if block_given?
215
- websocket.subscribe :getlastsettlements, params: filters, &blk
162
+ raise Deribit::NotImplementedError, 'not implemented'
216
163
  else
217
- http.get :getlastsettlements, params: filters
164
+ http.get '/public/get_last_settlements_by_instrument', filters
218
165
  end
219
166
  end
220
167
 
221
168
  # Retrieves user account summary.
169
+ # @param currency [String] Currency summary
222
170
  # @param ext [Boolean] Requests additional fields
223
171
  # @return [Hashie::Mash] the account details
224
172
  # @yield [Hashie::Mash] the account details
225
- # @see https://docs.deribit.com/rpc-endpoints.html#account
226
- def account(ext: false, &blk)
173
+ # @see https://docs.deribit.com/#private-get_account_summary
174
+ def account(currency: 'BTC', ext: false)
227
175
  if block_given?
228
- websocket.subscribe :account, params: { auth: true }, &blk
176
+ raise Deribit::NotImplementedError, 'not implemented'
229
177
  else
230
- http.get :account, auth: true
178
+ http.get '/private/get_account_summary', currency: currency
231
179
  end
232
180
  end
233
181
 
234
182
  # Places a buy order for an instrument.
235
- # @param instrument [String] Name of the instrument to buy
236
- # @param quantity [Integer] The number of contracts to buy
237
- # @!macro deribit.options
183
+ # @param instrument_name [String] Name of the instrument to buy
184
+ # @param amount [Integer] The number of contracts to buy
185
+ # @!macro deribit.buy_sell_options
238
186
  # @param options [Hash] more options for the order
239
187
  # @option options [String] :type (limit) The order type, possible types: "limit", "stop_limit", "market", "stop_market"
240
- # @option options [Float] :price The order price (Only valid for limit and stop_limit orders)
241
188
  # @option options [String] :label user defined label for the order (maximum 32 characters)
189
+ # @option options [Float] :price The order price (Only valid for limit and stop_limit orders)
242
190
  # @option options [String] :time_in_force (good_til_cancelled) Specifies how long the order remains in effect, possible values "good_til_cancelled", "fill_or_kill", "immediate_or_cancel"
243
191
  # @option options [Integer] :max_show Maximum quantity within an order to be shown to other customers, 0 for invisible order.
244
192
  # @option options [String] :post_only (true) If true, the order is considered post-only. If the new price would cause the order to be filled immediately (as taker), the price will be changed to be just below the bid.
245
- # @option options [Float] :stopPx Stop price required for stop limit orders (Only valid for stop orders)
246
- # @option options [String] :execInst (index_price) Defines trigger type, required for "stop_limit" order type, possible values "index_price", "mark_price" (Only valid for stop orders)
247
- # @option options [String] :adv Advanced option order type, can be "implv", "usd". (Only valid for options)
193
+ # @option options [String] :reject_post_only (false) If order is considered post-only and this field is set to true than order is put to order book unmodified or request is rejected.
194
+ # @option options [String] :reduce_only If true, the order is considered reduce-only which is intended to only reduce a current position
195
+
196
+ # @option options [Float] :stop_price price required for stop limit orders (Only valid for stop orders)
197
+ # @option options [String] :trigger Defines trigger type: index_price mark_price last_price, required for "stop_limit" order type
198
+ # @option options [String] :advanced Advanced option order type, can be "implv", "usd". (Only valid for options)
248
199
  # @return [Hashie::Mash] the details of new order
249
- # @yield [Hashie::Mash] the details of new order
250
- # @see https://docs.deribit.com/rpc-endpoints.html#buy
251
- def buy(instrument, quantity, options = {}, &blk)
252
- params = { instrument: instrument, quantity: quantity, price: options[:price] }
253
- if block_given?
254
- websocket.subscribe :buy, params: params.merge(auth: true), &blk
255
- else
256
- http.post :buy, params
257
- end
200
+ # @see https://docs.deribit.com/#private-buy
201
+ def buy(instrument_name, amount, options = {})
202
+ params = options.merge instrument_name: instrument_name, amount: amount
203
+ http.get 'private/buy', params
258
204
  end
259
205
 
260
206
  # Places a sell order for an instrument.
261
- # @param instrument [String] Name of the instrument to sell
262
- # @param quantity [Integer] The number of contracts to sell
263
- # @!macro deribit.options
207
+ # @param instrument_name [String] Name of the instrument to sell
208
+ # @param amount [Integer] The number of contracts to buy
209
+ # @!macro deribit.buy_sell_options
264
210
  # @return [Hashie::Mash] the details of new order
265
- # @yield [Hashie::Mash] the details of new order
266
- # @see https://docs.deribit.com/rpc-endpoints.html#sell
267
- def sell(instrument, quantity, options = {}, &blk)
268
- params = options.merge instrument: instrument, quantity: quantity, auth: true
269
- if block_given?
270
- websocket.subscribe :sell, params: params, &blk
271
- else
272
- http.post :sell, params
273
- end
211
+ # @see https://docs.deribit.com/#private-sell
212
+ def sell(instrument_name, amount, options = {})
213
+ params = options.merge instrument_name: instrument_name, amount: amount
214
+ http.get '/private/sell', params
215
+ end
216
+
217
+ # Close a position
218
+ # @param instrument_name [String] Name of the instrument to sell
219
+ # @param type [String]
220
+ # @param options [Hash] the options
221
+ # @option options [String] :type The order type: limit or market
222
+ # @option options [String] :price Price for limit close
223
+ # @return [Hashie::Mash] the details of closed position
224
+ # @see https://docs.deribit.com/#private-sell
225
+ def close(instrument_name, options = { type: :market })
226
+ params = options.merge instrument_name: instrument_name, type: options[:type]
227
+ http.get '/private/close_position', params
274
228
  end
275
229
 
276
230
  # Changes price and/or quantity of the own order.
277
231
  # @param order_id [String] ID of the order to edit
278
- # @param quantity [Integer] The new order quantity
232
+ # @param amount [Integer] The new order quantity
279
233
  # @param price [Float] The new order price
280
234
  # @param options [Hash] extra options
281
235
  # @option options [Boolean] :post_only If true, the edited order is considered post-only. If the new price would cause the order to be filled immediately (as taker), the price will be changed to be just below the bid (for buy orders) or just above the ask (for sell orders).
282
- # @option options [String] :adv The new advanced order type (only valid for option orders)
283
- # @option options [Float] :stopPx The new stop price (only valid for stop limit orders)
236
+ # @option options [Boolean] :reduce_only If true, the order is considered reduce-only which is intended to only reduce a current position
237
+ # @option options [Boolean] :reject_post_only If order is considered post-only and this field is set to true than order is put to order book unmodified or request is rejected.
238
+ # @option options [String] :advanced Advanced option order type. If you have posted an advanced option order, it is necessary to re-supply this parameter when editing it (Only for options)
239
+ # @option options [Float] :stop_price Stop price, required for stop limit orders (Only for stop orders)
284
240
  # @return [Hashie::Mash] the edited order
285
- # @yield [Hashie::Mash] the edited order
286
- # @see https://docs.deribit.com/rpc-endpoints.html#edit
287
- def edit(order_id, quantity, price, options = {}, &blk)
288
- params = options.merge orderId: order_id, quantity: quantity, price: price, auth: true
289
- if block_given?
290
- websocket.subscribe :edit, params: params, &blk
291
- else
292
- http.post :edit, params
293
- end
241
+ # @see https://docs.deribit.com/#private-edit
242
+ def edit(order_id, amount, price, options = {})
243
+ params = options.merge order_id: order_id, amount: amount, price: price
244
+ http.get '/private/edit', params
294
245
  end
295
246
 
296
247
  # Cancels an order, specified by order id.
297
248
  # @param order_id [String] The order id of the order to be cancelled
298
249
  # @return [Hashie::Mash] details of the cancelled order
299
- # @yield [Hashie::Mash] details of the cancelled order
300
- # @see https://docs.deribit.com/rpc-endpoints.html#cancel
301
- def cancel(order_id, &blk)
302
- params = { orderId: order_id, auth: true }
303
- if block_given?
304
- websocket.subscribe :cancel, params: params, &blk
305
- else
306
- http.post :cancel, params
307
- end
250
+ # @see https://docs.deribit.com/#private-cancel
251
+ def cancel(order_id)
252
+ http.get '/private/cancel', order_id: order_id
308
253
  end
309
254
 
310
255
  # Cancels all orders, optionally filtered by instrument or instrument type.
311
- # @param type [all futures options] Which type of orders to cancel. Valid values are "all", "futures", "options"
312
256
  # @param options [Hash] extra options
313
- # @option options [String] :instrument The name of the instrument for which to cancel all orders
257
+ # @option options [String] :instrument_name The name of the instrument for which to cancel all orders
258
+ # @option options [String] :currency The currency symbol
259
+ # @option options [String] :type Which type of orders to cancel. Valid values are "all", "futures", "options"
260
+ # @option options [String] :kind Instrument kind, if not provided instruments of all kinds are considered
314
261
  # @return [Boolean] success or not
315
- # @yield [Boolean] success or not
316
- # @see https://docs.deribit.com/rpc-endpoints.html#cancelall
317
- def cancelall(type = :all, options = {}, &blk)
318
- params = options.merge type: type, auth: true
319
- if block_given?
320
- websocket.subscribe :cancelall, params: params, &blk
321
- else
322
- http.post :cancelall, params
323
- end
262
+ # @see https://docs.deribit.com/#private-cancel_all
263
+ # @see https://docs.deribit.com/#private-cancel_all_by_currency
264
+ # @see https://docs.deribit.com/#private-cancel_all_by_instrument
265
+ def cancel_all(options = {})
266
+ uri = cancel_uri options
267
+ http.get uri, options
324
268
  end
325
269
 
326
- # Retrieves open orders.
270
+ # Best bid/ask price and size.
327
271
  # @param options [Hash]
328
- # @option options [String] :instrument Instrument to return open orders for
329
- # @option options [string] ;orderId order ID
330
- # @option options [String] :type Order types to return. Valid values include "limit", "stop_limit", "any"
331
- # @return [Array] the list of open orders
332
- # @yield [Hashie::Mash] the order
333
- # @see https://docs.deribit.com/rpc-endpoints.html#getopenorders
334
- def orders(options = {}, &blk)
335
- if block_given?
336
- websocket.subscribe :getopenorders, params: options.merge(auth: true), &blk
337
- else
338
- http.get :getopenorders, auth: true, params: options
272
+ # @option options [String] :instrument_name (BTC-PERPETUAL) Instrument to return open orders for
273
+ # @see https://docs.deribit.com/#quote-instrument_name
274
+ def quote(options = { instrument_name: 'BTC-PERPETUAL' }, &blk)
275
+ unless block_given?
276
+ raise 'block is missing, HTTP-RPC not supported for this endpoint'
339
277
  end
340
- end
341
278
 
342
- # Retrieves current positions.
343
- # @return [Array] the list of positions
344
- # @yield [Hashie::Mash] the position
345
- # @see https://docs.deribit.com/rpc-endpoints.html#positions
346
- def positions(&blk)
347
- params = { auth: true }
348
- if block_given?
349
- websocket.subscribe :positions, params: params, &blk
350
- else
351
- http.get :positions, params
352
- end
279
+ channel = channel_for_instrument 'quote', options
280
+ websocket.subscribe channel, params: options, &blk
353
281
  end
354
282
 
355
- # Retrieves history of orders that have been partially or fully filled.
283
+ # Key information about the instrument
356
284
  # @param options [Hash]
357
- # @option options [String] :instrument Instrument to return open orders for
358
- # @option options [String] :count The number of items to be returned.
359
- # @option options [string] :offset The offset for pagination
360
- # @return [Array] the list of history orders
361
- # @yield [Hashie::Mash] the order
362
- # @see https://docs.deribit.com/rpc-endpoints.html#orderhistory
363
- def orders_history(options = {}, &blk)
364
- if block_given?
365
- websocket.subscribe :orderhistory, params: options.merge(auth: true), &blk
366
- else
367
- http.get :orderhistory, auth: true, params: options
368
- end
369
- end
370
-
371
- # Retrieve order details state by order id.
372
- # @param order_id [String] the ID of the order to be retrieved
373
- # @return [Hashie::Mash] the details of the order
374
- # @yield [Hashie::Mash] the details of the order
375
- # @see https://docs.deribit.com/rpc-endpoints.html#orderstate
376
- def order(order_id, &blk)
377
- params = { orderId: order_id, auth: true }
378
- if block_given?
379
- websocket.subscribe :orderstate, params: params, &blk
380
- else
381
- http.get :orderstate, auth: true, params: params
382
- end
383
- end
384
-
385
- # Retrieve the trade history of the account
386
- # @param instrument [String] Either the name of the instrument, or "all" for instruments, "futures" for all futures, or "options" for all options.
387
- # @!macro deribit.filters
388
- # @return [Array] the list of trades
389
- # @yield [Hashie::Mash] the trade
390
- # @see https://docs.deribit.com/rpc-endpoints.html?q=#tradehistory
391
- def trades_history(instrument = :all, filters = {}, &blk)
392
- params = filters.merge(instrument: instrument, auth: true)
393
- if block_given?
394
- websocket.subscribe :tradehistory, params: params, &blk
395
- else
396
- http.get :tradehistory, auth: true, params: params
397
- end
398
- end
399
-
400
- # Retrieves announcements that have not been marked read by the current user.
401
- # @return [Array] the list of new announcements
402
- # @yield [Hashie::Mash] the announcement
403
- def new_announcements(&blk)
404
- if block_given?
405
- websocket.subscribe :newannouncements, params: { auth: true }, &blk
406
- else
407
- http.get :newannouncements, auth: true
408
- end
409
- end
410
-
411
- # Logs out the websocket connection.
412
- # @yield [Boolean] success or not
413
- # @see https://docs.deribit.com/rpc-endpoints.html#logout
414
- def logout(&blk)
415
- raise 'This API endpoint cannot be used over HTTP.' unless block_given?
416
-
417
- websocket.subscribe :logout, params: {}, &blk
418
- end
419
-
420
- # Enables or disables "COD" (cancel on disconnect) for the current connection.
421
- # @param state [String] Whether COD is to be enabled for this connection. "enabled" or "disabled"
422
- # @yield [Boolean] success or not
423
- # @see https://docs.deribit.com/rpc-endpoints.html#cancelondisconnect
424
- def cancelondisconnect(state, &blk)
425
- raise 'This API endpoint cannot be used over HTTP.' unless block_given?
426
-
427
- websocket.subscribe :cancelondisconnect, params: { state: state, auth: true }, &blk
428
- end
429
-
430
- # Retrieves the language to be used for emails.
431
- # @return [String] the language name (e.g. "en", "ko", "zh")
432
- # @yield [String] the language name (e.g. "en", "ko", "zh")
433
- def getemaillang(&blk)
285
+ # @option options [String] :instrument_name (BTC-PERPETUAL) Instrument to return open orders for
286
+ # @option options [String] :interval (raw) Frequency of notifications: raw, 100ms
287
+ # @see https://docs.deribit.com/#ticker-instrument_name-interval
288
+ def ticker(options = { instrument_name: 'BTC-PERPETUAL' }, &blk)
434
289
  if block_given?
435
- websocket.subscribe :getemaillang, params: { auth: true }, &blk
290
+ channel = channel 'ticker', options
291
+ websocket.subscribe channel, params: options, &blk
436
292
  else
437
- http.get :getemaillang, auth: true
293
+ http.get '/public/ticker', options
438
294
  end
439
295
  end
440
296
 
441
- # Changes the language to be used for emails.
442
- # @param lang [String] the abbreviated language name. Valid values include "en", "ko", "zh"
443
- # @return [Boolean] success or not
444
- # @yield [Boolean] success or not
445
- def setemaillang(lang, &blk)
446
- if block_given?
447
- websocket.subscribe :setemaillang, params: { lang: lang, auth: true }, &blk
448
- else
449
- http.post :setemaillang, lang: lang
450
- end
451
- end
297
+ # Retrieves open orders.
298
+ # @param options [Hash]
299
+ # @option options [String] :instrument_name Instrument to return open orders for
300
+ # @option options [String] :currency The currency symbol, BTC, ETH, any
301
+ # @option options [string] :kind (any) Instrument kind, future, option or any
302
+ # @option options [string] :type (all) Order type: all, limit, stop_all, stop_limit, stop_market
303
+ # @option options [String] :interval (raw) Frequency of notifications: raw, 100ms
304
+ # @return [Array] the list of open orders
305
+ # @yield [Hashie::Mash] the order
306
+ # @see https://docs.deribit.com/#private-get_open_orders_by_currency
307
+ # @see https://docs.deribit.com/#private-get_open_orders_by_instrument
308
+ def orders(options, &blk)
309
+ raise ArgumentError, 'either :instrument_name or :currency is required' unless options[:instrument_name] || options[:currency]
452
310
 
453
- # Marks an announcement as read, so it will not be shown in newannouncements
454
- # @param announcement_id [String] the ID of the announcement
455
- # @return [String] ok
456
- # @yield [String] ok
457
- def setannouncementasread(announcement_id, &blk)
458
311
  if block_given?
459
- websocket.subscribe :setannouncementasread, params: { announcementid: announcement_id, auth: true }, &blk
312
+ channel = channel 'user.orders', options
313
+ websocket.subscribe channel, params: options, &blk
460
314
  else
461
- http.post :setannouncementasread, announcementid: announcement_id
315
+ uri = orders_uri options
316
+ http.get uri, options
462
317
  end
463
318
  end
464
319
 
465
- # Retrieves settlement, delivery and bankruptcy events that have affected your account.
466
- # @param filters [Hash] the filters
467
- # @option filters [String] :instrument The instrument name, or "all" to retrieve settlements for all instruments
468
- # @option filters [Integer] :count (10) The number of entries to be returned. This is clamped to max 1000
469
- # @option filters [String] :type The type of settlements to return. Possible values "settlement", "delivery", "bankruptcy"
470
- # @option filters [Integer] :startTstamp The latest timestamp to return result for
471
- # @option filters [String] :continuation Continuation token for pagination. Each response contains a token to be used for continuation
472
- # @return [Hashie::Mash] the settlements
473
- # @yield [Hashie::Mash] the settlement
474
- # @see https://docs.deribit.com/rpc-endpoints.html#settlementhistory
475
- def settlements_history(filters = {}, &blk)
476
- if block_given?
477
- websocket.subscribe :settlementhistory, params: filters.merge(auth: true), &blk
478
- else
479
- http.get :settlementhistory, auth: true, params: filters
480
- end
320
+ # Retrieves current positions.
321
+ # @param options [Hash]
322
+ # @option options [String] :currency (any) The currency symbol, BTC, ETH
323
+ # @option options [string] :kind (any) Instrument kind, future, option
324
+ # @return [Array] the list of positions
325
+ # @see https://docs.deribit.com/#private-get_positions
326
+ def positions(options = { currency: 'BTC' })
327
+ http.get '/private/get_positions', options
481
328
  end
482
329
  end
483
330
  end