🗃️Advanced Topics

Profit Loss Over Custom Time Periods

Currently, the dex_trader_stats_30d_by_hour_token table into consideration all trades an address have made in its life time

There is another table, dex_trader_stats_30d_by_hour_token, which only looks at balances opened in the last 30 days, on a rolling basis.

For custom time windows, please contact us for additional instructions.

How to Estimate Unrealized P&L

Each row has an end_valid_balance field which is the remaining balance of that token after that trade (counting only tokens purchased on DEXs from the start of the table time range).

1) For each token, take the end_valid_balance from the row with most recent block_hour (the latest trade)

2) multiply that by the current token price

Note as mentioned in a previous section, because that table only tracks DEX sales and purchases, if those tokens are transferred out/ used to buy an nft/staked/used as collateral/... that is not reflected in end_valid_balance. So you might have someone with high unrealized PnL when their wallet is actually empty.

An idea for a better estimate is to calculate their actual current token balance and pick the lowest between that and end_valid_balance before multiplying by current price.

How to Calculate the P&L Manually?

You can use the following SQL to validate the correctness of the P&L calculation.

WITH
profit_including_cost_of_unsold_tokens AS
(
    SELECT
        trader,
        token,
        SUM(valid_revenue_usd - cost_usd - block_hour_fees_usd) AS total_profit_without_refund
    FROM
        nansen-query.aggregates_ethereum.dex_trader_stats_by_hour_token
    GROUP BY
        trader,
        token
),

latest_refund_for_unsold_tokens AS (
    SELECT DISTINCT
        trader,
        token,
        FIRST_VALUE(total_refund) OVER(
            PARTITION BY trader, token
            ORDER BY block_hour DESC
        ) AS unsold_tokens_refund,
        FIRST_VALUE(total_profit) OVER(
            PARTITION BY trader, token
            ORDER BY block_hour DESC
        ) AS total_profit_from_table
    FROM
        nansen-query.aggregates_ethereum.dex_trader_stats_by_hour_token
)

SELECT
    trader,
    token,
    (total_profit_without_refund + unsold_tokens_refund) AS total_profit_we_calculated,
    total_profit_from_table
FROM
    profit_including_cost_of_unsold_tokens
INNER JOIN
    latest_refund_for_unsold_tokens
    USING(trader,token)

Last updated