FastMM documentation
FastMM C++ API 0.6.0
Public headers, tier 1 and tier 2
Loading...
Searching...
No Matches
fastmm::bt::PnlDecomposition Struct Reference

How the net PnL of the run splits into the parts a market maker can act on: net == spread_capture + mid_drift - fees_paid + rebates_received + residual mid_drift is the move of the mid from each fill to the end of the run, valued at the signed quantity of the fill: adverse selection plus the mark-to-market of whatever is still open. More...

#include <fastmm/backtest/metrics.hpp>

Public Attributes

double spread_capture = 0.0
 sum of signed_qty * (mid at fill - fill price)
 
double spread_capture_bps = 0.0
 
double mid_drift = 0.0
 sum of signed_qty * (final mid - mid at fill)
 
double fees_paid = 0.0
 sum of the positive fees, >= 0
 
double rebates_received = 0.0
 sum of the negative fees with the sign flipped, >= 0
 
double net = 0.0
 spread_capture + mid_drift - fees_paid + rebates_received
 
double residual = 0.0
 reported net PnL - net
 
double notional = 0.0
 traded notional of every fill
 
double capture_notional = 0.0
 traded notional of the fills that had a mid at the fill
 
std::uint64_t capture_fills = 0
 
std::uint64_t fills = 0
 

Detailed Description

How the net PnL of the run splits into the parts a market maker can act on: net == spread_capture + mid_drift - fees_paid + rebates_received + residual mid_drift is the move of the mid from each fill to the end of the run, valued at the signed quantity of the fill: adverse selection plus the mark-to-market of whatever is still open.

residual is whatever the average-cost ledger books differently (fixed-point rounding, a contract multiplier, an instrument whose book never had two sides). A large residual means the decomposition does not describe this run; it is printed, not hidden.

A fill whose venue mid is unknown at the moment of the fill (the sweep that filled it emptied that side of the book) has no spread capture to attribute, so its whole signed_qty * (final mid - price) goes to mid_drift instead. capture_fills and capture_notional cover the rest, and are what spread_capture_bps divides by.

Member Data Documentation

◆ spread_capture

double fastmm::bt::PnlDecomposition::spread_capture = 0.0

sum of signed_qty * (mid at fill - fill price)

◆ spread_capture_bps

double fastmm::bt::PnlDecomposition::spread_capture_bps = 0.0

◆ mid_drift

double fastmm::bt::PnlDecomposition::mid_drift = 0.0

sum of signed_qty * (final mid - mid at fill)

◆ fees_paid

double fastmm::bt::PnlDecomposition::fees_paid = 0.0

sum of the positive fees, >= 0

◆ rebates_received

double fastmm::bt::PnlDecomposition::rebates_received = 0.0

sum of the negative fees with the sign flipped, >= 0

◆ net

double fastmm::bt::PnlDecomposition::net = 0.0

spread_capture + mid_drift - fees_paid + rebates_received

◆ residual

double fastmm::bt::PnlDecomposition::residual = 0.0

reported net PnL - net

◆ notional

double fastmm::bt::PnlDecomposition::notional = 0.0

traded notional of every fill

◆ capture_notional

double fastmm::bt::PnlDecomposition::capture_notional = 0.0

traded notional of the fills that had a mid at the fill

◆ capture_fills

std::uint64_t fastmm::bt::PnlDecomposition::capture_fills = 0

◆ fills

std::uint64_t fastmm::bt::PnlDecomposition::fills = 0