PaperEx.Fill (PaperEx v0.8.0)

Copy Markdown View Source

An atomic fill against a single price level.

A Fill represents one of potentially many price-level fills that compose a PaperEx.Execution. Adapters return a list of Fills when an order walks through several levels of an order book; an execution whose status is :filled carries that list on the :fills field of PaperEx.Execution.

This is a plain data struct. P&L math, aggregation across fills, and cash/position accounting live in PaperEx.Engine (engine phase).

Fields

  • :size (required) — number of units filled at this level. Positive number.
  • :price (required) — price per unit at this level. Non-negative number.
  • :side (required):buy or :sell, matching the order side that produced the fill.
  • :fee — fee charged for this fill, in quote currency. Defaults to 0. Fees are kept on the fill rather than aggregated on the execution so adapters can model per-level or maker/taker fees.
  • :liquidity:maker, :taker, or nil. Optional; useful for adapters that distinguish maker vs taker rebates.
  • :timestampDateTime.t() when the fill occurred. Defaults to DateTime.utc_now/0.
  • :metadata — free-form map. Adapter-specific data (book level index, original price/size in adapter's unit system, raw payload, etc.) lives here.

Notional and notional+fee

Convenience helpers notional/1 and cost/1 compute size * price and size * price + fee respectively. Callers building higher-level aggregations (volume-weighted average price, total fees paid) compose these against a list of Fills.

Summary

Functions

size * price + fee for a fill — the gross notional plus the fee, side-agnostic (there is no sign convention).

Builds a Fill from a map or keyword list.

size * price for a fill. Quote-currency notional, before fees.

Types

liquidity()

@type liquidity() :: :maker | :taker | nil

side()

@type side() :: :buy | :sell

t()

@type t() :: %PaperEx.Fill{
  fee: number(),
  liquidity: liquidity(),
  metadata: map(),
  price: number(),
  side: side(),
  size: number(),
  timestamp: DateTime.t()
}

Functions

cost(fill)

@spec cost(t()) :: number()

size * price + fee for a fill — the gross notional plus the fee, side-agnostic (there is no sign convention).

For a :buy this is the total outlay the buyer paid. For a :sell it is the notional plus the fee, which is not the seller's net proceeds — net sell revenue is notional - fee (what the engine credits to cash). Use notional/1 for the fee-free amount.

new(attrs)

@spec new(keyword() | map()) :: t()

Builds a Fill from a map or keyword list.

Required: :size, :price, :side. Raises ArgumentError on shape violations.

notional(fill)

@spec notional(t()) :: number()

size * price for a fill. Quote-currency notional, before fees.