How to place a trading order on Bybit programmatically

Alvin Mutebi
6 min readFeb 11, 2023

--

Bybit Test net

We shall go through a detailed chronology where we shall learn how to make a Limit order using node js, express typescript, and the Bybit API.

First, what is an order in regard to crypto trading, we shall talk about Limit and Market Orders;

Limit orders

A limit order is an agreement to buy or sell an asset at a specific price.

Market Orders

A market order is an instant buy or sell of an asset for the best available price at that time.

In this case, we shall be trading BTCUSDT, on Bybit without wasting time, let's dive into the development of our simple app

Requirements

We assume before you proceed you have node js installed globally in your system or development environment

Nodejs, Express, Typescript, Cors, dotenv, bybit-api,

Project folder setup

Here we create a folder and navigate to it

mkdir place_order_bybit && cd palce_order_bybit

We now initiate our node js project with either npm or yarn

npm init -y    or yarn init 

Next, we install the dependencies for our project

yarn add typescript express cors dotenv bybit-api node

We shall now install the types versions of our dependencies since we are using typescript

yarn add @type/node @types/typescript @types/express @types/cors @types/dotenv

We shall now create our folders in our application folder as shown below

Folder structure

We now create our .env configuration and it should look like this:

API_KEY=''   // your bybit api key
API_SECRET='' // your bybit api secret
MAIN_URL='https://api-testnet.bybit.com'

Head to the bybit testnet and create an account and thereafter create an API KEY and SECRET for your project.

In the config folder, create a new file called config.ts and add this code, where we call our variables from the .env.

import 'dotenv/config'

export const ConfigParams = {
API_KEY: process.env.API_KEY || "",
API_SECRET: process.env.API_SECRET || "",
TEST_NET: true,
MAIN_URL: process.env.MAIN_URL || ""
}

Next, we create our server.ts file and it should look like this for the first time

import express from 'express'
import { configureMiddlewares } from './middlewares/config';
import { ConfigureRoutes } from './routes';

const app = express()
configureMiddlewares(app)
ConfigureRoutes(app)
app.listen(3000, () => {
console.log('Server listening on port 3000! We are Good to go');
});

In the exchange folder, we create a bybitHelper.ts filer which should look like this

import { LinearClient, LinearOrder, LinearPositionIdx } from "bybit-api";

export class BybitExchange {
//call our client
private linear: LinearClient

//create a constructor with the required keys

constructor(options: { key: string, secret: string, testnet: boolean, baseUrl: string }) {
this.linear = new LinearClient(options)

}

//we crate an async function to create and order or make an order
//every async function should return a promsie

async makeOrder(params: {
symbol: string, side: any, qty: number, order_type: any,
time_in_force: any, reduce_only: boolean, close_on_trigger: boolean, price: number, position_idx: LinearPositionIdx
}): Promise<LinearOrder | null> {
console.log(params)
let { result, ret_code, ret_msg } = await this.linear.placeActiveOrder(params)
if (ret_code === 0) {
console.log(result)
return result
} else {
console.log(ret_code, ret_msg)
throw new Error(ret_msg);

}
return null

}

//get Current price Helper

async getCurrentPrice(symbol: string): Promise<number | null> {
try {
const { result, ret_code, ret_msg } = await this.linear.getTickers({ symbol })
let _result = result.find((item: { symbol: string }) => item.symbol === symbol)
if (ret_code === 0) {
return _result.last_price
}
console.log(result)
if (ret_code === 0 && _result[0]) {
return _result[0]?.symbol.last_price
} else {
throw new Error(ret_msg)
}

} catch (error) {

}
return null

}

}

In the above code, we import Linear Client from the bybit API and create a class which can be exported to other files. Here we create helper functions that get a reference from the bybit API like makeOrder and getCurrentPrice

Next, we create a file called placeOrder.ts which should reside in the controller's folder and it should look like this


import { Request, Response } from "express";
import { ConfigParams } from "../config/config";
import { BybitExchange } from "../exchange/bybitHelper";

const bybitExchange = new BybitExchange({
key: ConfigParams.API_KEY,
secret: ConfigParams.API_SECRET,
baseUrl: ConfigParams.MAIN_URL,
testnet: true

})

async function makeOrder(req: Request, res: Response) {
try {
console.log("Hello Place Order Controller")
if (req.body) {
let { symbol, side, order_type, qty, time_in_force, price, reduce_only, close_on_trigger } = req.body
//we find the current price with the help of our bybitexchange helper
const currentPrice: any = await bybitExchange.getCurrentPrice(symbol)
//we check if our price is greater than 0.07 or greater than 0.07 depending on our needs
reduce_only = side === 'Buy' ? false : true
price = side === 'Buy' ? currentPrice - 0.07 : currentPrice + 0.07
//our result to the body
const result = await bybitExchange.makeOrder({ symbol, side, order_type: "Limit", qty: parseFloat((qty / currentPrice).toFixed(3)), time_in_force, reduce_only, close_on_trigger, price, position_idx: 0 })
//we log the price we bought at or sold at
price = side === 'Buy' ? console.log("Bought at this Price", price) : console.log("Sold at this Price", price)
//we log the json resposne
res.status(200).json({ result: result })


} else {
console.log("Request wasnt Sent check for an error")
res.status(502).json({ error: true })
}

} catch (error) {
console.log("Failed to request", error)

}


}

export { makeOrder }

In the above code of the makeOrder controller we see we import our config.ts file and our bybitExchange class, we then create an instance of the bybitExchange as seen above.

This is helping us buy BTCUSDT considering the price which is lower than -0.07 from the live price or last traded price(live price) and selling when the price is greater than 0.07 the lasted traded price (live price)

Next, we create a folder named api in routes and create a new file named routes.ts, it should look like this

import { Router } from "express";
import { makeOrder } from "../../controllers/placeOrder";
makeOrder


const router = Router()

router.post('/make-order', makeOrder)

export { router as makeOrderRoute }

Here we import the Router function to help us with routes

We then create an index.ts in the api folder still

import { Application } from "express"
import { makeOrderRoute } from "./api/routes"


export const ConfigureRoutes = (app: Application) => {
app.get('/ping', (req, res) => {
res.send("Welcome to Crazy Bot")
})
app.use([makeOrderRoute])
}

Here we created a configureRoutes function to handle all our routes as shown above which passes the makeOrderRoute.

if all is setup, we should be able to type the following command in your terminal and have our app running

yarn start or npm start

Your terminal should look like this

Server running in the terminal

Next, we open a client like Postman and pass our URL http://localhost:3000/make-order like below to make a post request with the set parameters in the body more about the parameters visit bybit place order documentation

Request

Send the request and the output will look like this

Response

Hooray we just made a limit buy order programmatically, when you check your bybit account, u will see an order placed with the same amount specified in the request in Postman

An order made shown in bybit

Resources

ByBitAPI docs:https://bybit-exchange.github.io/docs/v5/intro

We are able to do a lot with the Bybit API and this is just one of the possibilities, watch out for more interesting articles on this topic and all about blockchain and crypto trading using code and please follow me for more updates.

--

--

Alvin Mutebi

Software Engineer, Python, JavaScript, Typescript, Solidity, Certified Amazon Cloud Practitioner.