By-bit spot stop loss and take profit orders.- My findings!

After trying so many different ways to place these types of orders on the exchange, and no real success, I ended up doing this:

First we need to place our order. We can do so like this:

def place_order(testmode,type, symbol, side, takeprofitprice, stoplossprice,  qty):

    takeprofitprice = round(takeprofitprice,2)
    stoplossprice = round(stoplossprice,2)

    # Get the market data
    market_data = get_market_ask_price(testmode, symbol="BTCUSDT")
    
    # Get the market price
    market_price = float(market_data)
    # Calculate the take profit and stop loss prices
    uid = str(uuid.uuid4())    
    
    # market_order = exchange.privatePostV5OrderCreate(request)
    market_order = get_session(TEST).place_order(category="spot",
        symbol="BTCUSDT",
        side=side,
        orderType="Market",
        qty=str(qty), #in btc 
        timeInForce="GTC",
        orderLinkId=uid,  )
    
    print("Market order",market_order)

    # now we need to save this order to a csv called orders and append the stoploss and take profit prices to the row
    with open('orders.csv', mode='a') as orders_file:
        fieldnames = ['uid', 'symbol', 'side', 'qty', 'takeprofitprice', 'stoplossprice']
        writer = csv.DictWriter(orders_file, fieldnames=fieldnames)

        writer.writerow({
            'uid': uid,
            'symbol': symbol,
            'side': side,
            'qty': qty,
            'takeprofitprice': takeprofitprice,
            'stoplossprice': stoplossprice
        })    
    return market_order

Notice we have saved our order into a csv called “orders.csv”? We can now use this to check if our price is hitting the price we want to close off our current order.

Please note this is not really closing the order. Its just placing a sell order (opposite to the buy order) to basically reverse the original order, thereby closing off the trade cycle. because of this, we can also get a profit value and record that to the orders.csv 😎

Also note we are using web-sockets to ‘listen’ to the prices:

from pybit.unified_trading import WebSocket
from time import sleep, time
import csv

from bybitapi import place_order

orders = []
last_refresh_time = 0


def refresh_orders():
    global orders
    global last_refresh_time

    # Load the orders from the CSV file
    with open('orders.csv', mode='r') as orders_file:
        reader = csv.DictReader(orders_file)
        orders = list(reader)

    last_refresh_time = time()


def check_orders(testmode, symbol, market_price):
    global orders
    global last_refresh_time

    # Refresh the orders if it has been more than 5 seconds since the last refresh
    if time() - last_refresh_time > 5:
        refresh_orders()

    # Check for open orders that have reached their take profit or stop loss prices
    for order in orders:
        if not order['profit']:
            takeprofitprice = float(order['takeprofitprice'])
            stoplossprice = float(order['stoplossprice'])
            side = order['side']
            qty = float(order['qty'])

            if (side == 'Buy' and market_price >= takeprofitprice) or (side == 'Sell' and market_price <= takeprofitprice):
                # Take profit
                new_side = 'Sell' if side == 'Buy' else 'Buy'
                place_order(testmode, symbol, new_side,
                            takeprofitprice, stoplossprice, qty)
                order['profit'] = (market_price - takeprofitprice) * \
                    qty if side == 'Buy' else (
                        takeprofitprice - market_price) * qty
            elif (side == 'Buy' and market_price <= stoplossprice) or (side == 'Sell' and market_price >= stoplossprice):
                # Stop loss
                new_side = 'Sell' if side == 'Buy' else 'Buy'
                place_order(testmode, symbol, new_side,
                            takeprofitprice, stoplossprice, qty)
                order['profit'] = (market_price - stoplossprice) * \
                    qty if side == 'Buy' else (
                        stoplossprice - market_price) * qty

    # Save the updated orders back to the CSV file
    with open('orders.csv', mode='w') as orders_file:
        fieldnames = ['uid', 'symbol', 'side', 'qty',
                      'takeprofitprice', 'stoplossprice', 'profit']
        writer = csv.DictWriter(orders_file, fieldnames=fieldnames)
        writer.writeheader()
        writer.writerows(orders)


def getws():

    return WebSocket(
        testnet=True,
        channel_type="spot",
    )


def handle_message(message):
    if 'topic' in message and message['topic'] == 'tickers.BTCUSDT':
        last_price = float(message['data']['lastPrice'])
        # print(last_price)
        check_orders(True, "BTCUSDT", last_price)


getws().ticker_stream(
    symbol="BTCUSDT",
    callback=handle_message
)

# while True:
#     sleep(1)

If you have an easier way (I love easy solutions) please let me know 🙏

UPDATE – I have since switched to Binance. Here is the post: Placing a TP profit and Stop loss order using CCXT and BINANCE


Posted

in

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *