Guides

Include funding costs in a crypto perpetual futures backtest

At 0.01% per 8 hours, a constant 1x long pays about 11% a year in funding. It belongs in the backtest.

Why it happens

0.0001 × 3 payments a day × 365 days ≈ 11% a year at 1x. That's the arithmetic at Binance's baseline rate; real rates move around it. Funding is paid on the position you hold at the funding timestamp, not on the average over the bar. Two common mistakes are spreading it evenly across bars, and applying it to the position you're about to enter rather than the one you hold.

Fix it with plain pandas

import numpy as np

# positions: exposure as a fraction of equity, indexed like prices
held_at_event = positions.reindex(funding.index, method="ffill").fillna(0)
funding_cost = (held_at_event * funding).sum()      # + = paid
gross = (positions.shift(1) * prices.pct_change()).sum()
print(f"funding took {funding_cost / abs(gross):.0%} of gross PnL")

Or with Deptho

Deptho's cost attribution is lookahead-safe by default: a position decided at a bar's close earns from the next bar, and each funding event is charged to the position held at that moment. You get the breakdown into gross, fees, assumed slippage and funding, and a dashboard that shows the drag over time:

import deptho as dp

pnl = dp.pnl_from_positions(prices, positions, funding=funding, fee_bps=5)
dp.tearsheet(pnl=pnl, benchmark=prices.pct_change()).show()

Related