How to place a trading order on Bybit programmatically
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
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
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
Send the request and the output will look like this
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
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.