> For the complete documentation index, see [llms.txt](https://docs.nexus.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nexus.xyz/math-engine/position-tracker.md).

# Position Tracker

Every trade on the Exchange either opens, grows, shrinks, closes, or reverses a position, and the position tracker is the single bookkeeping authority for what that position is worth. Its central design choice is the split between money already banked and money still at risk: when a fill closes part of a position, the profit on the closed quantity is settled immediately at that fill's own price (realized PnL), while the remainder keeps floating with the mark price (unrealized PnL). The entry price is a volume-weighted average that only ever moves when the position grows — reducing a position never rewrites its history.

From the same state the tracker derives the two prices that govern an account's survival. The liquidation price is where the account's collateral plus floating PnL falls to exactly the maintenance-margin requirement — the point where the Exchange must step in. The bankruptcy price is more adverse still: it is where the collateral is fully consumed and equity reaches zero. The gap between the two is the buffer the liquidation engine has to unwind the position before losses spill beyond the account.

![Every fill branches on side into either an entry-price update or a realized-PnL close, and both risk prices are a fan-in of the same two state variables — entry price and collateral.](/files/82UtGCrGDedVQyeIXP0l)

*Every fill branches on side into either an entry-price update or a realized-PnL close, and both risk prices are a fan-in of the same two state variables — entry price and collateral.*

## Setting

A market is described by its parameters: the maintenance margin rate $$r\_m$$, the taker fee $$\beta\_t$$ and maker rebate $$\beta\_r$$ (both in basis points). A position carries a side $$\sigma \in {+1, -1}$$ (long, short), a positive size $$q$$, and a volume-weighted entry price $$P\_e > 0$$. Fills arrive with a price $$P\_f > 0$$ and quantity $$q\_f > 0$$, the market publishes a mark price $$P\_{mark} > 0$$, and the position is backed by account collateral $$C \geq 0$$. All quantities are exact decimals in the implementation; the formulas below are exact real arithmetic.

| Symbol        | Name                      | Description                                                                                                                 | Units                  | Domain   |
| ------------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ---------------------- | -------- |
| $$q$$         | size                      | Absolute position size in units of the underlying asset; direction is carried separately by the side.                       | units of asset         | (0, ∞)   |
| $$P\_e$$      | entry\_price              | Volume-weighted entry price of the position.                                                                                | USDX per base unit     | (0, ∞)   |
| $$P\_{mark}$$ | mark\_price               | The Exchange's mark price for the market at valuation time.                                                                 | USDX per unit of asset | (0, ∞)   |
| $$\sigma$$    | side\_sign                | Direction indicator for the position: $$+1$$ for a long position, $$-1$$ for a short position.                              | dimensionless          | \[-1, 1] |
| $$P\_f$$      | fill\_price               | Execution price of an individual fill applied to the position.                                                              | USDX per base unit     | (0, ∞)   |
| $$q\_f$$      | fill\_quantity            | Quantity of an individual fill applied to the position (always positive; direction comes from the fill side).               | base units             | (0, ∞)   |
| $$q\_c$$      | closed\_qty               | The portion of an opposing fill that closes existing position size: the smaller of the position size and the fill quantity. | base units             | (0, ∞)   |
| $$C$$         | account\_collateral       | Collateral backing the position being evaluated.                                                                            | USDX                   | \[0, ∞)  |
| $$r\_m$$      | maintenance\_margin\_rate | Market maintenance margin rate; strictly less than the initial margin rate.                                                 | dimensionless ratio    | (0, 1]   |
| $$\beta\_t$$  | taker\_fee\_bps           | Taker fee for the market, in basis points of fill notional.                                                                 | basis points           | \[0, ∞)  |
| $$\beta\_r$$  | maker\_rebate\_bps        | Maker rebate for the market, in basis points of fill notional; stored as a signed value whose magnitude is credited.        | basis points           | \[-∞, 0] |

## The mechanism

### Building the position

When a fill lands on the same side as an existing position, the position grows and its entry price becomes the volume-weighted average of the old position and the new fill: the new entry is the total cost of both legs divided by the total quantity. This is the only path on which the entry price changes — reductions, closes, and funding leave it untouched, so $$P\_e$$ always answers the question "what did the currently open size cost, on average?" A fill that opens a fresh position is the degenerate case with $$q = 0$$: the entry is simply the fill price.

$$
P\_e' = \frac{q , P\_e + q\_f , P\_f}{q + q\_f} \tag{T.1}
$$

### Valuing the position

The floating profit of the open position is the signed distance from entry to mark, scaled by size: a long gains when the mark rises above entry ($$\sigma = +1$$), a short when it falls below ($$\sigma = -1$$). This value is recomputed after every fill that leaves a position open, and again on every mark-price update; it is a pure revaluation and never moves collateral by itself.

$$
\text{uPnL} = \sigma ,(P\_{mark} - P\_e), q \tag{T.2}
$$

### Settling reductions

A fill on the opposing side first consumes existing position size. The quantity that closes is capped at the position size: a partial reduce closes the whole fill, a full close consumes exactly the position, and a flip closes the position and carries the excess into a new one. Only this closed portion settles PnL — the excess, if any, opens fresh exposure with no PnL of its own.

$$
q\_c = \min(q, , q\_f) \tag{T.3}
$$

Closing $$q\_c$$ units at the fill's own price banks the entry-to-fill difference, signed by the position side — the closing analogue of (T.2) with the fill price standing in for the mark. On a partial close this accumulates on the surviving position; on a full close or flip it is returned per fill so the risk layer can settle it into collateral, since the carried position (gone, or newly opened at (T.5)) cannot recover it. Fills that open or increase a position realize exactly zero.

$$
\text{rPnL} = \sigma ,(P\_f - P\_e), q\_c \tag{T.4}
$$

When an opposing fill exceeds the position size, the position reverses through zero: the old side closes fully (realizing (T.4) on $$q\_c = q$$), and the remainder opens a new position on the fill's side with the fill price as its fresh entry. The new position inherits none of the old accumulators.

$$
q\_{new} = q\_f - q \tag{T.5}
$$

### Fees and funding

Each taker fill charges a fee proportional to its notional value, at the market's taker rate in basis points. The tracker debits this amount from the position's fee PnL accumulator so the full P\&L breakdown (entry, funding, fee) is visible in one place; the cash movement itself is settled at the collateral layer. When a fill fully closes the position there is no surviving position to accumulate on, and the fee is settled entirely via collateral transfers.

$$
F\_t = \frac{q\_f , P\_f , \beta\_t}{10,000} \tag{T.6}
$$

Maker fills earn a rebate: the magnitude of the (negatively stored) maker rate, applied to the same fill notional as (T.6), is credited to the position's fee PnL. The absolute value guards against the sign convention — the stored rate is negative, but the credit is always positive.

$$
F\_m = \frac{q\_f , P\_f , |\beta\_r|}{10,000} \tag{T.7}
$$

### Risk prices

The liquidation price is the mark at which the account's equity — collateral plus the unrealized PnL of (T.2) evaluated at that mark — falls to exactly the maintenance-margin requirement $$P \cdot q \cdot r\_m$$. Solving $$C + \sigma(P - P\_e)q = P q r\_m$$ for $$P$$ gives a single closed form covering both sides: for a long ($$\sigma=+1$$) the price sits below entry, for a short ($$\sigma=-1$$) above it. The formula is meaningful for leveraged positions, where collateral is less than notional; a fully collateralized long yields a non-positive (unreachable) result.

$$
P\_{liq} = \frac{P\_e , q - \sigma, C}{q,(1 - \sigma, r\_m)} \tag{T.8}
$$

The bankruptcy price is where equity reaches zero: the entire collateral pool is consumed by the position's loss. Setting $$C + \sigma(P - P\_e)q = 0$$ and solving gives the entry price shifted adversely by the per-unit collateral $$C/q$$. Because the maintenance requirement in (T.8) is strictly positive, the bankruptcy price is always at least as adverse as the liquidation price — the gap is the liquidation engine's buffer to unwind the position before losses exceed the account.

$$
P\_{bkr} = P\_e - \sigma,\frac{C}{q} \tag{T.9}
$$

## Invariants

* Every open position has $$q > 0$$ and $$P\_e > 0$$. *Why it holds:* Opens and flips set size to a positive fill quantity (or positive excess $$q\_f - q$$) and entry to a positive fill price; increases add positive quantities; a reduction that would take size to zero returns no position at all rather than a zero-size one. So no path produces a live position with non-positive size or entry.
* Partial closes never change the entry price: after a reducing fill, $$P\_e' = P\_e$$ (see (T.1) for the only mutating path). *Why it holds:* The reduce branch subtracts from size and accumulates realized PnL but does not touch the entry field. Only the same-side (increase) branch recomputes the entry, and full closes and flips discard the old entry entirely.
* For leveraged positions ($$C < P\_e q$$), the bankruptcy price is at least as adverse as the liquidation price: $$\sigma P\_{bkr} \le \sigma P\_{liq}$$, i.e. $$P\_{bkr} \le P\_{liq}$$ for longs and $$P\_{bkr} \ge P\_{liq}$$ for shorts. *Why it holds:* At the liquidation price equity equals the maintenance requirement $$P\_{liq}, q, r\_m > 0$$; at the bankruptcy price equity is zero. Since equity is monotone in the mark (decreasing for longs, increasing for shorts), the zero-equity price lies strictly further in the adverse direction whenever the maintenance requirement is positive. Verified by the property test prop\_p005\_bankruptcy\_worse\_than\_liq over randomized sizes, entries, and collateral.
* A fill realizes PnL only on the quantity that closes existing opposite-side exposure: opens and increases return exactly zero realized PnL, and a flip realizes on $$q\_c = q$$, never on the newly opened $$q\_{new}$$ of (T.5). *Why it holds:* The open and increase branches return a zero realized amount unconditionally. The opposing-side branch computes (T.4) on $$\min(q, q\_f)$$ before any new position is constructed, so the reopened side starts with fresh, empty accumulators.
* Funding accrual is additive and orthogonal: applying a funding payment adds its amount to the funding accumulator and changes no other field — in particular fee PnL, entry, and size are preserved. *Why it holds:* apply\_funding performs a single addition to funding\_accrued and returns; the cash flow is handled at the collateral layer. Test f005\_funding\_tick\_preserves\_fee\_pnl confirms fee PnL survives funding ticks unchanged.

## Worked example

A trader opens a long with a buy of $$1$$ unit at $$P\_f = 45{,}000$$: the position is $$q = 1$$, $$P\_e = 45{,}000$$. A second buy of $$1$$ unit at $$47{,}000$$ increases the position, and (T.1) blends the two legs: $$P\_e' = (1 \cdot 45{,}000 + 1 \cdot 47{,}000)/2 = 46{,}000$$ on a size of $$q = 2$$. With the mark at $$P\_{mark} = 50{,}000$$, (T.2) values the position at $$\text{uPnL} = (50{,}000 - 46{,}000) \cdot 2 = 8{,}000$$ USDX of floating profit.

The trader now sells $$1$$ unit at $$50{,}000$$. The fill opposes the long, so (T.3) gives $$q\_c = \min(2, 1) = 1$$, and (T.4) banks $$(50{,}000 - 46{,}000) \cdot 1 = 4{,}000$$ USDX. The surviving position has $$q = 1$$ at the unchanged entry $$P\_e = 46{,}000$$. If instead the trader had sold $$3$$ units, the position would flip: $$q\_c = 2$$ closes the long (realizing $$8{,}000$$), and (T.5) opens a short of $$q\_{new} = 1$$ at entry $$50{,}000$$.

Suppose the surviving $$1$$-unit long is backed by $$C = 10{,}000$$ USDX in a market with $$r\_m = 0.005$$. (T.8) gives $$P\_{liq} = (46{,}000 - 10{,}000)/(1 \cdot 0.995) \approx 36{,}180.90$$, and (T.9) gives $$P\_{bkr} = 46{,}000 - 10{,}000 = 36{,}000$$. The mark reaches the liquidation threshold about $$181$$ USDX before equity would hit zero — that gap is the buffer within which the position must be unwound. Each taker fill along the way also cost (T.6): the opening $$45{,}000$$-notional buy, at $$\beta\_t = 5$$ bps, debited $$22.50$$ USDX of fee PnL.

## Analysis

### Sensitivity

Elasticities ε = (∂y/∂x)·(x/y), computed numerically from the verified expressions at each worked-example point. |ε| > 1 means the output moves more than proportionally with that input.

| Expression          | Input                     | Elasticity ε |
| ------------------- | ------------------------- | ------------ |
| `vwap_entry`        | fill\_price               | 0.5109       |
| `vwap_entry`        | entry\_price              | 0.4891       |
| `vwap_entry`        | size                      | -0.01087     |
| `vwap_entry`        | fill\_quantity            | 0.01087      |
| `unrealized_pnl`    | mark\_price               | 12.5         |
| `unrealized_pnl`    | entry\_price              | -11.5        |
| `unrealized_pnl`    | side\_sign                | 1            |
| `unrealized_pnl`    | size                      | 1            |
| `closed_quantity`   | fill\_quantity            | 1            |
| `closed_quantity`   | size                      | 0            |
| `realized_pnl`      | fill\_price               | 11           |
| `realized_pnl`      | entry\_price              | -10          |
| `realized_pnl`      | side\_sign                | 1            |
| `realized_pnl`      | closed\_qty               | 1            |
| `flip_size`         | fill\_quantity            | 2            |
| `flip_size`         | size                      | -1           |
| `taker_fee`         | fill\_quantity            | 1            |
| `taker_fee`         | fill\_price               | 1            |
| `taker_fee`         | taker\_fee\_bps           | 1            |
| `maker_rebate`      | fill\_quantity            | 1            |
| `maker_rebate`      | fill\_price               | 1            |
| `maker_rebate`      | maker\_rebate\_bps        | 1            |
| `liquidation_price` | entry\_price              | 1.111        |
| `liquidation_price` | size                      | 0.1111       |
| `liquidation_price` | account\_collateral       | -0.1111      |
| `liquidation_price` | side\_sign                | -0.1061      |
| `liquidation_price` | maintenance\_margin\_rate | 0.005025     |
| `bankruptcy_price`  | entry\_price              | 1.111        |
| `bankruptcy_price`  | side\_sign                | -0.1111      |
| `bankruptcy_price`  | account\_collateral       | -0.1111      |
| `bankruptcy_price`  | size                      | 0.1111       |

![Sensitivity tornado — Volume-weighted entry price](/files/pKmXIHjUrOiRFVoVWRLu)

![Sensitivity tornado — Unrealized PnL](/files/WhQ07h2LV9mf4WFpAORx)

![Sensitivity tornado — Liquidation price](/files/E13CF6IJgS0ez5eTAbcp)

### Response curves

![More collateral pushes a long's liquidation price further below the 100,000 entry, and larger positions dilute each collateral dollar across more units; maintenance rate held at 0.5%.](/files/sg3FfX8xpEjJgom9jlJW)

*More collateral pushes a long's liquidation price further below the 100,000 entry, and larger positions dilute each collateral dollar across more units; maintenance rate held at 0.5%.*

![Floating PnL is linear in the mark and mirror-imaged between long and short around the 46,000 entry, with size held at 2 units.](/files/hIiy6TnpAex2Mqy974jT)

*Floating PnL is linear in the mark and mirror-imaged between long and short around the 46,000 entry, with size held at 2 units.*

![The volume-weighted entry moves toward the fill price in proportion to the fill's share of the combined size; existing position held at 2 units entered at 46,000.](/files/1IiRwL3FlzoDNTZqy3Lc)

*The volume-weighted entry moves toward the fill price in proportion to the fill's share of the combined size; existing position held at 2 units entered at 46,000.*

## References

* Derived from and adversarially verified against the Exchange's Rust implementation and its test suite.
* Sibling model: [funding-rate](/math-engine/funding-rate.md)
* Sibling model: [insurance-fund](/math-engine/insurance-fund.md)
* Sibling model: [liquidation-engine](/math-engine/liquidation-engine.md)
* Sibling model: [margin-math](/math-engine/margin-math.md)
* Sibling model: [oracle](/math-engine/oracle.md)
* Sibling model: [order-book](/math-engine/order-book.md)
* Sibling model: [settlement](/math-engine/settlement.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.nexus.xyz/math-engine/position-tracker.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
