Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

order_update['rp'] Returns Partial PnL Instead of Total PnL for Multi-Trade Filled Orders #1523

Open
zhen1007 opened this issue Dec 23, 2024 · 0 comments

Comments

@zhen1007
Copy link
Contributor

Describe the bug
I placed a LONG position and, at the same time, placed two opposite orders for TP and SL.
While monitoring these two orders to see which one gets filled, I noticed an issue.

The 'rp' (realized profit) value does not reflect the total PnL of the order. Instead, it shows a partial amount (e.g., -23.35659708 USDT in the screenshot).

Is this the expected behavior? If not, can anyone help me retrieve the total PnL?

To Reproduce

client = await AsyncClient.create(API_KEY, API_SECRET, testnet=TESTNET)

position = await client.futures_create_order(
    symbol=symbol,
    side=SIDE_BUY,
    type=FUTURE_ORDER_TYPE_MARKET,
    quantity=quantity,
    newOrderRespType=ORDER_RESP_TYPE_RESULT
)

tp_order = await client.futures_create_order(
    symbol=symbol,
    side=SIDE_SELL,
    type=FUTURE_ORDER_TYPE_TAKE_PROFIT_MARKET,
    quantity=quantity,
    stopPrice=tp_price,
    reduceOnly=True,
    newOrderRespType=ORDER_RESP_TYPE_RESULT
)
sl_order = await client.futures_create_order(
    symbol=symbol,
    side=SIDE_SELL,
    type=FUTURE_ORDER_TYPE_STOP_MARKET,
    quantity=quantity,
    stopPrice=sl_price,
    reduceOnly=True,
    newOrderRespType=ORDER_RESP_TYPE_RESULT
)

# monitor if one of the TP/SL order is filled

bsm = BinanceSocketManager(client)

kline_socket = bsm.kline_futures_socket(symbol, ma_interval)
user_socket = bsm.futures_user_socket()

async with kline_socket as kline_stream, user_socket as user_stream:
    while self.running:
        kline_task = asyncio.create_task(kline_stream.recv())
        user_task = asyncio.create_task(user_stream.recv())
        done, pending = await asyncio.wait([kline_task, user_task], return_when=asyncio.FIRST_COMPLETED)

        if kline_task in done:
            # ...

        if user_task in done and self.position is not None:
            user_res = user_task.result()
            if user_res['e'] == 'ORDER_TRADE_UPDATE':
                order_update = user_res['o']
                if order_update['i'] == self.position['tp_order_id'] and order_update['X'] == ORDER_STATUS_FILLED:
                    await client.futures_cancel_order(symbol=symbol, orderId=self.position['sl_order_id'])
                    await self.exit_position('TP', order_update['rp'])
                elif order_update['i'] == self.position['sl_order_id'] and order_update['X'] == ORDER_STATUS_FILLED:
                    await client.futures_cancel_order(symbol=symbol, orderId=self.position['tp_order_id'])
                    await self.exit_position('SL', order_update['rp'])
  
        for task in pending:
            task.cancel()

Expected behavior
order_update['rp'] should return the total PnL, not a partial value, when the order is filled by multiple trades.

Environment (please complete the following information):

  • Python version: 3.13.0
  • Virtual Env: virtualenv
  • OS: Windows 11
  • python-binance version: v1.0.25

Additional context
image
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant