[Python] Error 499 when running cloud function written in Python, Pybit library

Discussão em 'Python' iniciado por Stack, Janeiro 27, 2025.

  1. Stack

    Stack Membro Participativo

    This code is written in Python 3.12 and runs in a cloud service. The code works, but execution is unstable. Half of the time it executes successfully, but the other half of the time it returns an error:

    ERROR Code: 499 Message: Request cancelled.


    The error is returned in different places, but in most cases after the message "Waited 1 second" or "We start to place a closing order". Sometimes it is after the log "There are no long positions on the coin. We place an order."

    I added recv_window=60000 and timeout=30 to the client parameters, but it didn't help. Please help me identify the problem ibehind the unstable execution of the code.

    from pybit.unified_trading import HTTP
    from pybit import exceptions
    from pybit.exceptions import InvalidRequestError
    import inspect
    import os
    import hmac
    import time
    from typing import Optional
    import hashlib
    import requests
    import math
    import decimal
    import json
    import base64

    SYMBOL = "" # Global variable

    def assets(client: HTTP): # Function for receiving USDT balances on a UNIFIED account.

    r, _, _ = client.get_wallet_balance(accountType="UNIFIED") # Request balance on UNIFIED account.
    r = r.get('result', {}).get('list', [])[0] # Извлекаем первый элемент из списка результатов.

    usdt_balance = next((float(c.get('walletBalance', '0.0')) for c in r.get('coin', []) if c.get('coin') == 'USDT'), 0.0)

    usdt_balance_floor = math.floor(usdt_balance) # Round down to the nearest whole number.
    #print(f"USDT Balance: {usdt_balance_floor}") # Logging balance output
    return usdt_balance_floor

    def get_price(client, symbol): # Function to get the current price of SYMBOL.

    r, _, _ = client.get_tickers(category="linear", symbol=SYMBOL)
    r = r.get('result', {}).get('list', [])[0] # Extract the first element from the result list.

    # Extract lastPrice from the response, convert it to float and round it to 4 digits
    last_price = round(float(r['lastPrice']), 4)

    return last_price

    def open_limit_short_order(client, symbol, market_price, opening_price_factor, lot_size, persent):

    # Calculating the opening price
    opening_price = round(market_price * opening_price_factor, 4)

    try:
    # Checking for open short orders
    r, _, _ = client.get_positions(category="linear", symbol=symbol)
    positions = r.get('result', {}).get('list', [])

    if positions and positions[0]['side'] == 'Sell':
    print("There are open short positions on the coin. The order will not be opened.")
    return
    else:
    print("There are no short positions on the coin. We place an order.")

    client.place_order(
    category="linear",
    symbol=symbol,
    side="Sell",
    orderType="Limit",
    qty=lot_size,
    price=opening_price,
    positionIdx=2,
    )
    print("Message after placing an order, before checking the order status.")

    # Checking order status
    for _ in range(10): # We will limit the number of checks to 10
    print("Entered the order status check cycle")
    #time.sleep(1) # Wait 1 second before checking
    print("Waited 1 second.")

    r, _, _ = client.get_positions(category="linear", symbol=symbol)
    print("Response from API when receiving positions:", r) # Logging the response API

    positions = r.get('result', {}).get('list', [])
    print("Current positions:", positions) # Logging current positions

    if positions and positions[0]['side'] == 'Sell':
    print("Short order filled.")

    opening_price = round(float(positions[0]['avgPrice']), 4)
    print("opening_price = ", opening_price) # Logging opening_price

    closing_price = round(opening_price * (1 - persent / 100), 4)
    print("closing_price = ", closing_price) # Logging closing_price

    print("We start to place a closing order")
    closing_order_response = client.place_order(
    category="linear",
    symbol=symbol,
    side="Buy",
    order_type="Limit",
    qty=lot_size,
    price=closing_price,
    positionIdx=2,
    )
    print(f"The closing order is set at the price: {closing_price}")
    #print(closing_order_response)
    break

    print("Short order was not executed, we continue checking...")

    else:
    print("Short order was not executed within the maximum number of attempts.")

    except Exception as e:
    print(f"Error: {e}")

    def open_limit_long_order(client, symbol, market_price, opening_price_factor, lot_size, persent):

    # Calculation of the opening price rounded to 4 characters
    opening_price = round(market_price * opening_price_factor, 4)

    try:
    # Checking for open long orders
    r, _, _ = client.get_positions(category="linear", symbol=symbol)
    positions = r.get('result', {}).get('list', [])

    if positions and positions[0]['side'] == 'Buy':
    print("There are open long positions on the coin. The order will not be opened.")
    return
    else:
    print("There are no long positions on the coin. We place an order.")

    client.place_order(
    category="linear",
    symbol=symbol,
    side="Buy",
    orderType="Limit",
    qty=lot_size,
    price=opening_price,
    positionIdx=1,
    )
    print("Message after placing an order, before checking the order status")

    # Checking order status
    for _ in range(10): # We will limit the number of checks to 10
    print("Entered the order status check cycle")
    #time.sleep(1) # Wait 1 second before checking
    print("Waited 1 second")

    r, _, _ = client.get_positions(category="linear", symbol=symbol)
    print("Response from API when receiving positions:", r) # Logging the response API

    positions = r.get('result', {}).get('list', [])
    print("Current positions:", positions) # Logging current positions

    if positions and positions[0]['side'] == 'Buy':
    print("Long order filled.")

    opening_price = round(float(positions[0]['avgPrice']), 4)
    print("opening_price = ", opening_price) # Logging opening_price

    closing_price = round(opening_price * (1 + persent / 100), 4)
    print("closing_price = ", closing_price) # Logging closing_price

    print("We start to place a closing order")
    closing_order_response = client.place_order(
    category="linear",
    symbol=symbol,
    side="Sell",
    order_type="Limit",
    qty=lot_size,
    price=closing_price,
    positionIdx=1,
    )
    print(f"The closing order is set at the price: {closing_price}")
    #print(closing_order_response)
    break

    print("Long order not executed, continuing checking...")

    else:
    print("Long order was not filled within the maximum number of attempts.")

    except Exception as e:
    print(f"Error: {e}")

    def main(event, context):
    try:
    API_KEY = os.environ['API_KEY']
    SECRET_KEY = os.environ['SECRET_KEY']

    message = base64.b64decode(event['body']).decode('utf-8')
    #message = '{"strategy":"Short","symbol":"SUIUSDT.P","side":"sell","persent":"0.6"}'
    #message = '{"strategy":"Long","symbol":"SUIUSDT.P","side":"buy","persent":"0.6"}'
    data = json.loads(message) # Parsing JSON strings
    print(data) # Logging

    symbol_tv = data['symbol'] # Getting Ticker Values
    global SYMBOL
    SYMBOL = symbol_tv[:-2] # We discard the last two characters (.P)
    side = data['side'] # Getting trade direction values
    strategy = data['strategy'] # Getting the strategy type
    persent = float(data['persent']) # Getting % value for take profit


    client = HTTP( # Create an HTTP client object with the given API keys.
    testnet=False,
    api_key=API_KEY,
    api_secret=SECRET_KEY,
    recv_window=60000, # Set the time interval for receiving a response from the API.
    timeout=30,
    return_response_headers=True, # We indicate that we want to receive response headers.
    )

    balance=assets(client) # We call the function to get the USDT balance.
    print(balance) # Logging balance

    market_price = get_price(client, SYMBOL) # We call the function to get the ticker price
    print(market_price) # Logging market price

    lot_size = math.ceil(balance / 50 / 4 * 33 / market_price) # Calculation qty
    print(lot_size)

    # Output of information for control
    print("Balance: ", balance, "| Qty: ", lot_size, "| Market price: ", market_price)

    opening_price_factor_short=0.9
    opening_price_factor_long=1.1

    if strategy == 'Short' and side == 'sell':
    open_limit_short_order(client, SYMBOL, market_price, opening_price_factor_short, lot_size, persent) # Short limit orders opening function


    if strategy == 'Long' and side == 'buy':
    open_limit_long_order(client, SYMBOL, market_price, opening_price_factor_long, lot_size, persent) # Function of opening long limit orders


    r = {'statusCode': 200, 'body': 'Message sent'}
    except Exception as e:
    r = {'statusCode': 400, 'body': 'Some error!'}

    return r

    Continue reading...

Compartilhe esta Página