Deribit – An Introductory API Guide

13 min read

Get 10-day Free Algo Trading Course

Last Updated on September 4, 2022

Deribit API Guide

Table of contents:

  1. What is Deribit?
  2. What is Deribit API?
  3. Is Deribit free?
  4. Does Deribit require KYC?
  5. Why should I use Deribit?
  6. Why shouldn’t I use the Deribit?
  7. Is Deribit available in my country?
  8. What are the alternatives to using Deribit?
  9. What clients are available for the Deribit API?
  10. How to get started with Deribit?
  11. How to get currency info with Deribit?
  12. How to get Price Data on Deribit?
  13. How to get historical data with Deribit?
  14. How to get Order Book data with Deribit?
  15. How to get Transactions with Deribit?
  16. How to fire an order with Deribit?
  17. How to fire an order on a Perpetual contract with Deribit?
  18. How to fire an order on a Futures contract with Deribit?
  19. How to fire an order on an Option contract with Deribit?
  20. How to execute a trade on ETH when BTC hits a certain price with the Deribit API?
  21. How to execute an ETH trade when BTC moves 5% in the last 5 minutes with the Deribit API?
  22. How to cancel orders with Deribit?
  23. Full code

What is Deribit?

Deribit is an online cryptocurrency derivatives exchange that focuses on cryptocurrency futures and options trading.

What is Deribit API?

Derbit API is a method that allows us to automatically trade cryptocurrency futures and options on Deribit via code.

Is Deribit free?

Opening an account on Deribit is completely free while the exchange does impose trading fees on its customers. The exchanges’ fee model is based on a maker-taker premise.

A maker order is an order that removes liquidity from the order book while the taker order does the opposite. Deribit fees vary per product and are calculated as a percentage of the underlying asset of the contract.

When it comes to contracts here is how the fee structure looks like:

Have in mind that the Options fees can’t go over the 12.5% of the options price. Moreover, Futures and Options contracts have a delivery fee as shown in the picture below:

When it comes to liquidation fees they are the following:

Deribit doesn’t impose any deposit fees while the withdrawal fees for BTC may depend on the current state of the Bitcoin network.

When it comes to funding your account you have only one option and that is Bitcoin 🙂 . This means that Deribit doesn’t support any fiat currency deposit methods.

Does Deribit require KYC?

As of 9th November 2020, Deribit requires all new clients to obtain a verified status in order to get allowed to trade. This implies providing a proof of residence and an ID document.

Why should I use Deribit?

  • Deribit is easy to use
  • Has low fees
  • Offers leveraged trading (up to 100x leverage)
  • Has a good API
  • Has a test environment
  • Has an insurance fund protection

Why shouldn’t I use the Deribit?

  • Deribit may be a bit confusing for beginners
  • Deribit is not a regulated exchange
  • It doesn’t provide fiat deposits

Is Deribit available in my country?

As of 2021, access to Deribit is not available

if you are located, incorporated, or otherwise established in, or a citizen or resident of any of the countries in the list below:

  • Cuba
  • Guam
  • Iran
  • Iraq
  • Japan
  • Democratic People’s Republic of Korea
  • Panama
  • Puerto Rico
  • Samoa
  • Sudan
  • Syrian Arab Republic
  • United States
  • Virgin Islands (U.S.)

What are the alternatives to using Deribit?

Deribit can be replaced with other applications that can be more suitable for you needs. Here is the list:

What clients are available for the Deribit API?

Deribit features the following clients:

  • C
  • C#
  • Python
  • Go
  • Java
  • JavaScript
  • Swift
  • Ruby
  • R and more.

Be sure to visit the following GitHub to access these clients:

https://github.com/deribit/deribit-api-clients

How to get started with Deribit?

In order to fully see what the Deribit API is capable of, we will first need to open up an account to obtain the API Key. As I will show you a few trading scenarios, the account we need is the test account that is found on this link:

https://test.deribit.com/

The sign-up process for both the test and production Deribit account is pretty much the same. Here is a link to the production website:

https://www.deribit.com/

When there, you will see an account creation box right in front of you. Be sure to click the green “Create Account” button and fill in your email address, nickname, create a password, and select your country.

After that, you will receive a verification email from Deribit. Be sure to go over and confirm it. When done, you will be taken to the following screen:

Now, all we need is the API key. For this go to your profile icon that is found in the upper right corner and click on settings. After that, navigate to the API section and click the “Add a new key” button.

A pop-up screen will appear that will prompt you to assign the main functions of your new API key. The options range from account to custody permissions. For this article, I’ll give all of them a read + write permission.

After you approve, the API key will be created and you will clearly see your Client ID and Client Secret. You will also have several action possibilities like the QR Code, Reset Secret, Remove Key, and more.

As all that we need is set, the following headers will explore the API starting with the main public endpoints and finishing with private API order within two trading scenarios.

How to get currency info with Deribit?

In order to obtain all the currencies that Deribit has to offer you can use the get_currencies endpoint. We will import the required libraries and call their API in the following way:

import asyncio
import websockets
import json
import pandas as pd
import pprint
import nest_asyncio
nest_asyncio.apply()

msg = \
{
  "jsonrpc" : "2.0",
  "id" : 7538,
  "method" : "public/get_currencies",
  "params" : {

  }
}

async def call_api(msg):
    async with websockets.connect('wss://test.deribit.com/ws/api/v2') as websocket:
        await websocket.send(msg)
        while websocket.open:
            response = await websocket.recv()
            json_par = json.loads(response)
            print(json_par)
            return(json_par)
            
response = asyncio.get_event_loop().run_until_complete(call_api(json.dumps(msg)))

As the response doesn’t look too nice we will pretty print it by using the pprint library.

pprint.pprint(response)

Much better, let’s add the pprint as our main printing way in the function and call the next endpoint that will obtain the price data.

How to get Price Data on Deribit?

There are several Deribit endpoints that include the price data but the most “precise” one would be the public ticker endpoint. Let’s update the function for a prettier print.

msg = {
  "jsonrpc" : "2.0",
  "id" : 8106,
  "method" : "public/ticker",
  "params" : {
    "instrument_name" : "BTC-PERPETUAL"
  }
}

async def call_api(msg):
    async with websockets.connect('wss://test.deribit.com/ws/api/v2') as websocket:
        await websocket.send(msg)
        while websocket.open:
            response = await websocket.recv()
            json_par = json.loads(response)
            pprint.pprint(json_par)
            return(json_par)
            
response = asyncio.get_event_loop().run_until_complete(call_api(json.dumps(msg)))

If you want to obtain the index price, you an use the “get_index_price” endpoint.

msg = {"jsonrpc": "2.0",
     "method": "public/get_index_price",
     "id": 42,
     "params": {
     "index_name": "btc_usd"}
    }

response = asyncio.get_event_loop().run_until_complete(call_api(json.dumps(msg)))
{'id': 42,
 'jsonrpc': '2.0',
 'result': {'estimated_delivery_price': 57848.15, 'index price': 57848.15},
 'testnet': True,
 'usDiff': 177,
 'usIn': 1616071078267979,
 'usOut': 16160710782681561}

How to get historical data with Deribit?

Deribit offers a few Historical data endpoints like the funding rate history and historical volatility. Let us go ahead and obtain the two starting with the latter one:

msg = {
  "jsonrpc" : "2.0",
  "id" : 8387,
  "method" : "public/get_historical_volatility",
  "params" : {
    "currency" : "BTC"
  }
}

response = asyncio.get_event_loop().run_until_complete(call_api(json.dumps(msg)))

The next thin we want to do is to put the response into a pandas data frame so it can be used for later on.

volatility = pd.DataFrame(response['result'])
volatility.head()

In order to get some basic stats about the dataframe you can use the pd.describe function:

pd.set_option('precision', 3)
volatility.describe()

And now for the funding rate history:

msg = {
  "jsonrpc" : "2.0",
  "id" : 7617,
  "method" : "public/get_funding_rate_history",
  "params" : {
    "instrument_name" : "BTC-PERPETUAL",
    "start_timestamp" : 1569888000000,
    "end_timestamp" : 1569902400000
  }
}

response = asyncio.get_event_loop().run_until_complete(call_api(json.dumps(msg)))

How to get Order Book data with Deribit?

Order book data can be obtained by utilizing the public get_order_book endpoint. The max level depth of the order book is not specified by the exchange. We’ll use level 25 for our request:

msg = {
  "jsonrpc" : "2.0",
  "id" : 8772,
  "method" : "public/get_order_book",
  "params" : {
    "instrument_name" : "BTC-PERPETUAL",
    "depth" : 25
  }
}

response = asyncio.get_event_loop().run_until_complete(call_api(json.dumps(msg)))

We should clean up the response now by extracting the important bits out of it. For this, I will create separate data frames for both bids and asks and then merge the two together.

bids = pd.DataFrame(response['result']['bids'])
asks = pd.DataFrame(response['result']['asks'])

book = pd.merge(bids, asks, left_index=True, right_index=True)
book.head()

If you want to rename the columns you can pass this:

book = df.rename({"0_x":"Bid Price","1_x":"Bid Amount",
                "0_y":"Ask Price","1_y":"Ask Amount"}, axis='columns')

How to get Transactions with Deribit?

Transactions aka trades can be obtained from Deribit by using the get trades by currency or by instrument endpoints. For settlements, all you need to do is to change the “trades” to “settlements” in the request message.

Let’s obtain the trades and settlements by currency starting with the former:

msg = {
  "jsonrpc" : "2.0",
  "id" : 9290,
  "method" : "public/get_last_trades_by_currency",
  "params" : {
    "currency" : "BTC",
    "count" : 2
  }
}

response = asyncio.get_event_loop().run_until_complete(call_api(json.dumps(msg)))

And now for the settlements:

msg = {
  "jsonrpc" : "2.0",
  "id" : 4497,
  "method" : "public/get_last_settlements_by_currency",
  "params" : {
    "currency" : "BTC",
    "type" : "delivery",
    "count" : 2
  }
}

response = asyncio.get_event_loop().run_until_complete(call_api(json.dumps(msg)))

How to order with Deribit?

Deribit offers several order types that can be launched through their endpoints. But before we go over each of them and code up two trading scenarios, we should see what parameters make the order.

The basic order parameters are the following:

  • instrument_name – the name of your asset (required)
  • amount – requested order size (required)
  • type – default is “limit” but it can be stop_limit, market, stop_market
  • label – user-defined label for the order
  • price – the order price in the base currency that works only for limit and stop_limit orders.
  • time_in_force – specifies how long the order lasts. It can be “good_til_cancelled”, “fill_or_kill”, “immediate_or_cancel”.
  • max_show – maximum amount within an order that is shown to other customers (e.g. 0 makes the order invisible)
  • post_only – “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 spread. Only valid in combination with time_in_force = good_til_cancelled
  • reject_post_only – “If an order is considered post-only and this field is set to true then the order is put to order book unmodified or request is rejected and order is canceled.”
  • reduce_only – if true, it reduces the current position
  • stop_price – Stop price for stop limit orders
  • trigger – it defines the trigger type for stop_limit and stop_market orders.
  • advanced – advanced option order type (only for options)
  • mmp – order MMP Flag

Now that we have the main order building blocks in mind, let’s explore some peculiar ones and how to launch them.

How to fire an order on a Perpetual contract with Deribit?

All orders in Deribit share a similar structure as shown in the last header. This means that in order to fire an order on a perpetual contract we just need to specify the right instrument name (e.g. BTC-PERPETUAL).

Here is an example of how the order message should look like:

msg = {
  "jsonrpc" : "2.0",
  "id" : 4122,
  "method" : "private/cancel_all_by_instrument",
  "params" : {
    "instrument_name" : "BTC-PERPETUAL",
    "type" : "all"
  }
}

If you skipped to this part this is the function that we use to send a request:

async def call_api(msg):
    async with websockets.connect('wss://test.deribit.com/ws/api/v2') as websocket:
        ###############
       # Before sending a message, make sure that your connection
       # is authenticated (use public/auth call before) 
       ###############
        await websocket.send(msg)
        while websocket.open:
            response = await websocket.recv()
            json_par = json.loads(response)
            print(json_par)
            return(json_par)

The Deribit perpetual contract features a continuous measurement of the difference between the mark price of the contract and the Deribit BTC Index.

The percentage difference between these two price levels is the basis for the 8-hourly funding rate that is applied to all outstanding perpetual contracts. For more information visit the following link:

https://www.deribit.com/pages/docs/perpetual

How to fire an order on a Futures contract with Deribit?

All orders in Deribit share a similar structure. This means that in order to fire an order on a futures contract we just need to specify the right instrument name (e.g. BTC-24SEP21).

Here is an example of how the order message should look like:

msg = {
  "jsonrpc" : "2.0",
  "id" : 4122,
  "method" : "private/cancel_all_by_instrument",
  "params" : {
    "instrument_name" : "BTC-24SEP21",
    "type" : "all"
  }
}

Bitcoin Futures on Deribit are cash settled rather than settled by “physical” delivery of BTC. This means that at the settlement, the buyer of BTC Futures will not buy the actual BTC, neither will the seller sell BTC.

There will only be a transfer of losses/gains at the settlement of the contract, based on the expiration price (calculated as the last 30 minute average of the BTC price index). For more information visit the following link:

https://www.deribit.com/pages/docs/futures

How to fire an order on an Option contract with Deribit?

All orders in Deribit share a similar structure. This means that in order to fire an order on a futures contract we just need to specify the right instrument name (e.g. ETH-19MAR21).

Here is an example of how the order message should look like:

msg = {
  "jsonrpc" : "2.0",
  "id" : 4122,
  "method" : "private/cancel_all_by_instrument",
  "params" : {
    "instrument_name" : "ETH-19MAR21",
    "type" : "all"
  }
}

Deribit follows the European style cash-settled options which means that the options are exercised only at expiry and cannot be exercised before. On Deribit, this will happen automatically.

For more information visit the following link:

https://www.deribit.com/pages/docs/options

How to execute a trade on ETH when BTC hits a certain price with the Deribit API?

In this example, I will show you how to properly and securely launch an order with specified requirements. The thing that we want to do is to launch a trade on ETH when BTC hits a certain price.

In order to make this work, we will need to set our order foundation and then create a loop that will check if the price level is hit. If the price is hit, we will execute a market order. On the contrary, we will continue looping.

When the price is executed we will wait for a few seconds and then check if the order was filled. This additional step is very important to have in your trading strategies as the exchange server may encounter some troubles.

Let us go ahead and import the relevant libraries and set up the main trading loop.

#Order Foundation
import asyncio
import websockets
import json
import pandas as pd
from time import sleep
import pprint
import hmac
import hashlib
from datetime import datetime
import nest_asyncio
nest_asyncio.apply()

async def call_api(msg):
    async with websockets.connect('wss://test.deribit.com/ws/api/v2') as websocket:
        await websocket.send(msg)
        while websocket.open:
            response = await websocket.recv()
            json_par = json.loads(response)
            #print(json_par)
            return(json_par)
        
clientId = "TzxHdA_N"
clientSecret = "3LsbOcO7Fqzv_oT9-RDy1JwvYG7uR3NnF5HXDnvn6AA"
timestamp = round(datetime.now().timestamp() * 1000)
nonce = "123"
data = ""

signature = hmac.new(
    bytes(clientSecret, "latin-1"),
    msg=bytes('{}\n{}\n{}'.format(timestamp, nonce, data), "latin-1"),
    digestmod=hashlib.sha256).hexdigest().lower()        
        
auth_msg = {
  "jsonrpc" : "2.0",
  "id" : 42,
  "method" : "public/auth",
  "params" : {
    "grant_type" : "client_signature",
    "client_id" : clientId,
    "timestamp" : timestamp,
    "signature" : signature,
    "nonce" : nonce,
    "data" : data
  }
}

price_msg = {
  "jsonrpc" : "2.0",
  "id" : 42,
  "method" : "public/ticker",
  "params" : {
    "instrument_name" : "BTC-PERPETUAL"
  }
}


order_msg = {
  "jsonrpc" : "2.0",
  "id" : 42,
  "method" : "private/buy",
  "params" : {
    "instrument_name" : "ETH-PERPETUAL",
    "amount" : 5,
    "type" : "market",
    "label" : "algoorder"
  }
}

check_order = {
  "jsonrpc" : "2.0",
  "id" : 42,
  "method" : "private/get_order_state",
  "params" : {
    "order_id" : "ETH-331562"
  }
}

#Main order loop
while True:
    try:
        btc = asyncio.get_event_loop().run_until_complete(call_api(json.dumps(price_msg)))
    except exception as e:
        print("Unable to obtain BTC price")
    
    if btc['result']['best_ask_price'] < 58800.0:
        print("The price mark was not reached.")
        sleep(60)
        continue
    
    elif btc['result']['best_ask_price'] >= 58800.0:
        try:
            auth = asyncio.get_event_loop().run_until_complete(call_api(json.dumps(auth_msg)))
            pprint.pprint(auth)
        except exception as e:
            print('There was an authentication error')
        
        try:
            order = asyncio.get_event_loop().run_until_complete(call_api(json.dumps(order_msg)))
            #print(order)
        except exception as e:
            print("Error occurred while placing order")
        
        sleep(2)
        
        try:
            order_check = asyncio.get_event_loop().run_until_complete(call_api(json.dumps(check_order)))
            pprint.pprint(order_check)
        except excpetion as e:
            print("Error checking order")
        
        if order_check['result']['order_state'] == 'filled' or order_check['result']['order_state'] == "open":
            print ('Order placed at {}'.format(pd.Timestamp.now()))
            break
            
        else:
            print('Order was canceled {}'.format(pd.Timestamp.now()))
            break

How to execute an ETH trade when BTC moves 5% in the last 5 minutes with the Deribit API?

What if we want to calculate the percentage move between two currencies and then launch an order? Well, this example will take care of that!

The main task will be to execute an ETH trade when BTC moves 5% in the last 5 minutes. This means that we will want to create a loop that will obtain the prices of the two cryptos and calculate the percentage change between the two.

If the percentage change is less than 5%, the algorithm will be sleeping for 5 minutes and calculating the percentage change again. If the percentage change is equal to or more than 5% the trade will execute.

After the trade execution, we will sleep for a few seconds and then check on the trade if it was filled or not. Now that the logic is set, it is time to code it out:

clientId = "ID_HERE"
clientSecret = "SECRET_HERE"
timestamp = round(datetime.now().timestamp() * 1000)
nonce = "123"
data = ""

signature = hmac.new(
    bytes(clientSecret, "latin-1"),
    msg=bytes('{}\n{}\n{}'.format(timestamp, nonce, data), "latin-1"),
    digestmod=hashlib.sha256).hexdigest().lower()        
        
auth_msg = {
  "jsonrpc" : "2.0",
  "id" : 42,
  "method" : "public/auth",
  "params" : {
    "grant_type" : "client_signature",
    "client_id" : clientId,
    "timestamp" : timestamp,
    "signature" : signature,
    "nonce" : nonce,
    "data" : data
  }
}

btc_price_msg = {
  "jsonrpc" : "2.0",
  "id" : 42,
  "method" : "public/ticker",
  "params" : {
    "instrument_name" : "BTC-PERPETUAL"
  }
}

order_msg = {
  "jsonrpc" : "2.0",
  "id" : 42,
  "method" : "private/buy",
  "params" : {
    "instrument_name" : "ETH-PERPETUAL",
    "amount" : 5,
    "type" : "market",
    "label" : "algoorder"
  }
}

check_order = {
  "jsonrpc" : "2.0",
  "id" : 42,
  "method" : "private/get_order_state",
  "params" : {
    "order_id" : "ETH-331562"
  }
}

while True:
    try:
        btc_old = asyncio.get_event_loop().run_until_complete(call_api(json.dumps(btc_price_msg)))
    except exception as e:
        print("Unable to obtain BTC price")
    
    sleep(300)
    
    try:
        btc_new = asyncio.get_event_loop().run_until_complete(call_api(json.dumps(btc_price_msg)))
    except exception as e:
        print("Unable to obtain BTC price")
    
    percent = (btc_new['result']['best_ask_price'] - btc_old['result']['best_ask_price'] * 100) / btc_old['result']['best_ask_price']
    
    if percent < 5:
        print("The requirement was not fulfilled.")
        sleep(0.1)
        continue
    
    elif percent >= 5:
        try:
            auth = asyncio.get_event_loop().run_until_complete(call_api(json.dumps(auth_msg)))
            pprint.pprint(auth)
        except exception as e:
            print('There was an authentication error')
        
        try:
            order = asyncio.get_event_loop().run_until_complete(call_api(json.dumps(order_msg)))
            #print(order)
        except exception as e:
            print("Error occurred while placing order")
        
        sleep(2)
        
        try:
            order_check = asyncio.get_event_loop().run_until_complete(call_api(json.dumps(check_order)))
            pprint.pprint(order_check)
        except excpetion as e:
            print("Error checking order")
        
        if order_check['result']['order_state'] == 'filled' or order_check['result']['order_state'] == "open":
            print ('Order placed at {}'.format(pd.Timestamp.now()))
            break
            
        else:
            print('Order was canceled {}'.format(pd.Timestamp.now()))
            break

How to cancel orders with Deribit?

If you want to cancel and order with Deribit you can pass something like the following request:

msg = \
{
  "jsonrpc" : "2.0",
  "id" : 4214,
  "method" : "private/cancel",
  "params" : {
    "order_id" : "ETH-SLIS-12"
  }
}

async def call_api(msg):
   async with websockets.connect('wss://test.deribit.com/ws/api/v2') as websocket:
       ###############
       # Before sending the message, make sure that your connection
       # is authenticated (use public/auth call before) 
       ###############
       await websocket.send(msg)
       while websocket.open:
           response = await websocket.recv()
           # do something with the response...
           print(response)

asyncio.get_event_loop().run_until_complete(call_api(json.dumps(msg)))

Full code

GitHub Link

Igor Radovanovic