Create Bybit DCA Bot with Python

by John | May 04, 2023

 

Are you looking to take your cryptocurrency trading to the next level? Look no further than Bybit, the leading crypto derivatives exchange. With advanced trading tools, low fees, and a user-friendly platform, Bybit makes it easy to trade Bitcoin, Ethereum, and other popular cryptocurrencies. And if you sign up using our affiliate link  and use the referral code CODEARMO, you'll receive exclusive benefits and bonuses up to $30,000 to help you get started. Don't miss out on this opportunity to join one of the fastest-growing communities in crypto trading. Sign up for Bybit today and start trading like a pro!

 

 

What is Dollar Cost Averaging (DCA)?

 

In the context of cryptocurrencies, dollar cost averaging (DCA) is a strategy that involves investing a fixed amount of fiat currency into a cryptocurrency on a regular basis, regardless of the current market price of the cryptocurrency. The idea behind DCA is to spread out the investment over time and avoid the risk of investing a large lump sum at a single point in time when the price of the cryptocurrency may be particularly high. By investing a fixed amount on a regular basis, the investor can take advantage of market fluctuations and potentially reduce the average cost per unit of the cryptocurrency. DCA can be an effective strategy for long-term investors who believe in the potential of a particular cryptocurrency but wish to mitigate the risk of investing a large sum of money at once.

 

The plot below shows the price of Bitcoin since 2020-03-25 , the blue line represents the average price an investor would have had they bought equal amount of Bitcoin between 2020-03-25 and 2023-05-04 

 

Bitcoin DCA performance

 

 

Lets assume that an investor bought $10 per day each day for the period shown in the charts above and below. That would be a total of 1136 days, and a total investment of $11,360 , the plot below shows the total Bitcoin aquired through a DCA strategy (dashed black line) and an all-in point in time strategy, note that the all-in strategy values represent 11360 / BTC price at given point. 

 

DCA Buying Results

 

 

As illustrated above, the investor would now have approximately 0.54 Bitcoin, although there are points in the plot above that would have meant more Bitcoin had an investor went all-in on that date, the DCA investor currently has more Bitcoin than approximately 62% of investors that opted for the all-in approach. And almost double the Bitcoin quantity in comparison to anyone that went all-in at any point in 2021. 

 

 

Pros:

  • Reduced risk: By investing a fixed amount of money at regular intervals, investors can avoid the risk of investing a large lump sum of money at a single point in time, potentially at a high point in the market.
  • Mitigating market volatility: The regular and consistent investments in crypto can help to mitigate the impact of market volatility on the overall cost basis of the investment.
  • Potential for long-term gains: crypto has historically been known for its long-term potential for growth, and DCA can help investors participate in that potential without trying to time the market.

Cons:

  • Potential opportunity cost: If the price of crypto experiences a sustained decline over the period of regular investments, an investor using DCA may miss out on the opportunity to invest at lower prices.
  • Difficulty in timing the market: While DCA can help to mitigate the risk of trying to time the market, it may not be the best strategy for investors who are able to effectively analyze market trends and make informed trades at the right times.

 

Overall, DCA can be a viable strategy for long-term Crypto investors who wish to avoid the risk of investing a large lump sum at a single point in time, and who believe in the potential for Bitcoin to increase in value over the long term. However, investors should be aware of the potential drawbacks of the strategy, including transaction fees and the possibility of missing out on lower prices in a declining market.

 

 

 

Making a Python DCA Bot

 

To create a DCA bot, you will need to have created an API key for Bybit as shown in this article. We will be using the schedule python package so ensure you have installed it with:

pip install schedule

 

To use this DCA bot (at your own risk) , it is recommended to try it using $1 worth of stables. The logic of the bot is as follows:

  • Choose which pair you want to trade on , also add which stablecoin you intend to use. For the purposes of this article we have used BTCUSDT and we wish to buy $1 worth of Bitcoin on each trade. 
  • The get_available_stable_coin function below, takes the stablecoin of interest and retrieves our available balance, we want to ensure that we have enough cash in our spot account, prior to making any trades. 
  • The SpotOrderFormatter class ensures that the quantity we have chosen is of suitable precision to send to the API. 
  • Market order is sent to Bybit to buy the specified quantity. 
  • Extract order-id and send a request to Bybit for order history, to ensure the order has been filled correctly. Then log the quantity acquired and the average price. 
  • The tasks above are then scheduled once per day at the given time. 

 

Perhaps it would be useful if users put this program in the cloud. Users that sign up through the CODEARMO referral link can join the discord group chat to receive instructions on how to set this program to run in the cloud for as little as $5 cost to rent a server. 

 

from pybit.unified_trading import HTTP
import datetime as dt
import json
import time  
import schedule
import logging 

with open('authcreds.json') as j:
        creds = json.load(j)
        
PAIR = 'BTCUSDT'
STABLE = 'USDT'
     
logging.basicConfig(filename=f"{PAIR}_DCA_logs.log",
                    format='%(asctime)s %(message)s',
                    level=logging.INFO)
        


key = creds['KEY_NAME']['key']
secret = creds['KEY_NAME']['secret']
  
session = HTTP(api_key=key, api_secret=secret, testnet=False)


dca_increment = 1 # stable amount




class SpotOrderFormatter:
    
    def __init__(self, symbol, dollar_amount):
        self.symbol = symbol 
        self.info = self.get_coin_info()
        self.dollar_amount = self.get_order_qty_precision(dollar_amount)

    def get_coin_info(self):
        ticker = session.get_instruments_info(category='SPOT', symbol=self.symbol).get('result').get('list') 
        sym_info = [x for x in ticker if x['symbol'] == self.symbol][0]
        return sym_info 
    
    def get_order_qty_precision(self, dollar_amount):
        decimals =  len(self.info.get('lotSizeFilter').get('basePrecision').split('.')[-1])
        return str(round(dollar_amount, decimals))
    

       
def get_available_stable_coin(stable):
    balance = session.get_wallet_balance(accountType='SPOT', coin=stable)
    result = balance.get('result').get('list')[0].get('coin')[0]
    return float(result.get('free'))


def parse_order_id(json_resp):
    result = json_resp.get('result')
    oid = result.get('orderId')
    return oid


def confirm_order_filled(oid):
    response = session.get_order_history(category='SPOT',
                                         orderId=oid)

    order = response.get('result').get('list')[0]
    filled_qty = order.get('cumExecQty')
    avg_price = order.get('avgPrice')
    return filled_qty, avg_price
    


def main():
    
    available = get_available_stable_coin(stable=STABLE)
    
    if dca_increment > available:
        logging.info(f'Available balance {available} is less than specified increment, no trade placed')
        return 
    
    qty = SpotOrderFormatter(PAIR, dca_increment).dollar_amount 
    
    logging.info(f'Sending order for ${qty} on {PAIR}')

    response = session.place_order(
        category = 'SPOT',
        symbol = PAIR,
        side = 'Buy',
        orderType='Market',
        qty= qty
        )
    
    oid = parse_order_id(response) 
    
    try:
        fil_q, av_p = confirm_order_filled(oid)
        logging.info(f'Order for {fil_q} at average price of {av_p} confirmed')
    except Exception as ex:
        logging.error(f'{ex}')
    
    
   
if __name__ == '__main__':
    schedule.every().day.at("01:28").do(main)
    
    while True:
        schedule.run_pending()
        time.sleep(1)

 


Join the discussion

Share this post with your friends!