sammchardy / python-binance

Binance Exchange API python implementation for automated trading
https://python-binance.readthedocs.io/en/latest/
MIT License
5.88k stars 2.2k forks source link

Correct way of implementing daily PnL query? #1383

Closed Karlheinzniebuhr closed 3 months ago

Karlheinzniebuhr commented 6 months ago

I'm trying to obtain the PnL from my latest trade, or the PnL from the current day. I've implemented something but the calculations are not accurate. What is the ideal way to obtain the daily PnL ?

My current function:

def get_daily_pnl(self, days=1):

    # Calculate the end time and start time based on the number of days
    end_time = dt.datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
    start_time = end_time - dt.timedelta(days=days)

    # https://binance-docs.github.io/apidocs/futures/en/#account-trade-list-user_data
    # If startTime and endTime are both not sent, then the last 7 days' data will be returned.
    # The time between startTime and endTime cannot be longer than 7 days.
    assert days < 8, 'days must be less than 8'

    # Get the daily PnL data for the futures account
    pnl_data = self.client.futures_account_trades(symbol=self.symbol, recvWindow=60000)

    daily_pnl = pd.DataFrame()

    if(pnl_data):
        # Convert the data into a DataFrame
        df = pd.DataFrame(pnl_data)

        # Convert the time column into datetime format
        df['time'] = pd.to_datetime(df['time'], unit='ms')

        # Convert the realizedPnl column to a numeric data type
        df['realizedPnl'] = pd.to_numeric(df['realizedPnl'])

        # Filter the DataFrame by date
        df = df[start_time < df['time']]

        # Group the DataFrame by date and sum the realizedPnl column
        daily_pnl = df.groupby(df['time'].dt.date)['realizedPnl'].sum()

    # Return the DataFrame
    return pd.DataFrame(daily_pnl)
Karlheinzniebuhr commented 3 months ago

Solved here: https://github.com/sammchardy/python-binance/issues/1405#issuecomment-1986956436

diltoncesar commented 3 months ago

I have same problem. Could you give a hint please?

Karlheinzniebuhr commented 3 months ago

I have same problem. Could you give a hint please?

This is my current function which works correctly, feel free to adapt it for your needs

    def get_last_trade_pnl_and_percentage(self):
        # Fetch the most recent trades for the futures account
        pnl_data = self.client.futures_account_trades(symbol=self.symbol, limit=100, recvWindow=60000)

        # Fetch the current available balance
        futures_balances = self.client.futures_account_balance(recvWindow=60000)
        futures_balance_df = pd.DataFrame(futures_balances)
        current_balance = round(float(futures_balance_df[futures_balance_df['asset'] == self.config.BASE_ASSET]['availableBalance'].values[0]), 2)

        total_pnl = 0
        total_pnl_percentage = 0

        if pnl_data:
            # Convert the trade data into a DataFrame
            df = pd.DataFrame(pnl_data)

            # Ensure the 'realizedPnl' column is treated as numeric for calculations
            df['realizedPnl'] = pd.to_numeric(df['realizedPnl'])

            if not df.empty:
                # Group trades by orderId and side
                grouped = df.groupby(['orderId', 'side'])

                # Get the last orderId
                last_order_id = df['orderId'].iloc[-1]

                for group_name, group in grouped:
                    order_id, side = group_name

                    # If it's the last origOrderId, sum the realizedPnl to get the total PnL of the last trade
                    if order_id == last_order_id:
                        last_trade_pnl = round(group['realizedPnl'].sum(), 2)
                        break  # Exit the loop after finding the last trade

                # Calculate the balance before the last trade
                balance_before_last_trade = current_balance - total_pnl - last_trade_pnl

                # Calculate PnL percentage based on the balance before the last trade
                if balance_before_last_trade != 0:
                    last_trade_pnl_percentage = round((last_trade_pnl / balance_before_last_trade) * 100, 2)

        # Return the PnL of the last trade, its percentage, and the current balance
        return last_trade_pnl, last_trade_pnl_percentage, current_balance
diltoncesar commented 3 months ago

Thank you so much Karl. I got it!. In time, I'm trying in 6months to set a strategy to trade that are consistently. But I'm not successful. I used Bands, MA, RSI...etc. but due the volatile sometimes gain and lost. Another problem is set TP and SL. Could you give a north my friend? Regards.Dilton from Brazil

Karlheinzniebuhr commented 3 months ago

Thank you so much Karl. I got it!. In time, I'm trying in 6months to set a strategy to trade that are consistently. But I'm not successful. I used Bands, MA, RSI...etc. but due the volatile sometimes gain and lost. Another problem is set TP and SL. Could you give a north my friend? Regards.Dilton from Brazil

you are likely overfitting, try testing your strategy on data that you have not used for optimization. Hold at least 1-2 years of data that you have never used to create your strategy, and run your simulation with that data. Also try trading other coins besides BTC they tend to be easier to trade

diltoncesar commented 3 months ago

Excellent Karl. I'll try to implement it. Was does your best experience, scalp or intraday? I'm trying create a scalp strategy. My dificult is to set Tp and Sl. If I use 2x1, the ratio is below 50%. If I use 1x2, the ratio increase but got a loss, your profit go out...