Futures Trading 6.2.3
Latest3 September 2026
This release has upgrade notes. Read them before updating — they describe behaviour changes that need your attention.
Futures v6.2.3
Release Date: September 3, 2026 Tags: LIQUIDATION, INSURANCE-FUND, ADL, DATABASE
Requires Core v6.7.6. The schema relaxation this release needs is applied by Core's boot sequence.
Overview
Auto-deleveraging did not work, in both directions at once: it fired too late to prevent money being created, and once it fired it closed every profitable trader on the other side of the market. Both come from the same mistake, which is reading the insurance fund's balance as if it were the fund's spare capital.
The balance is a reserve plus the float the fund holds for open positions. A bankrupt trader's forfeited margin lands in it and is owed, in full and more, to the winner who has not closed yet. So:
- The trigger. A fund holding a bankrupt trader's margin shows a positive balance and reads as covered, while owing more than that to the counterparty. Deleveraging fired only once the balance had already gone negative, which is after the money had been created. In the simplest two-party case it never fired at all.
- The stop condition. Every deleveraged close pays the winner out of the fund, so the balance falls with each one. Recovery was measured as the improvement in that balance, which was therefore never positive, so the loop ran to the end of the queue and closed every profitable position on that side.
Both now use the same measure. Cover is the balance minus what the open book would take out of the fund at current marks, and recovery per close is the gain the deleveraged trader was not paid, which is what actually funds the deficit.
A separate defect in the fund's ledger is fixed too: a position closing in several fills recorded only its first slice, so the fund's own balance was wrong on any liquidation that swept more than one price level.
Update Instructions
pnpm updatorServer-side only for this extension, but it carries a schema change applied by Core. Update Core to 6.7.6 in the same maintenance window and let the backend boot once against a database it can alter.
Upgrade Notes
The insurance ledger gains a column and swaps a unique index
futures_insurance_ledger gains sliceKey and a unique index on
(positionId, type, sliceKey). The old unique index on (positionId, type) is
what dropped every clearing slice after the first; Core's boot sequence relaxes
it to a plain index and the schema sync creates the new one. Installs that boot
with DB_SYNC=none must boot once with DB_SYNC=always (or with the variable
unset, which syncs when the models changed). Fresh installs import a
regenerated initial.sql.
Your recorded fund balance may be wrong, in your favour or against you
Any liquidation that filled across more than one price level recorded one
clearing slice instead of all of them, so the fund's balance and its reported
deficit have drifted by the value of the missing slices. There is no automatic
repair: the missing rows were never written. Read the current figure as a
fresh starting point rather than a running total: it is the per-currency sum of
futures_insurance_ledger, which the admin futures dashboard endpoint
(GET /api/admin/futures/dashboard) returns under insurance along with the
markets still in deficit. No admin screen renders that block yet. If you carry
a deficit there, compare it against your own settlement records before acting
on it.
Deleveraging will now fire on markets where it never did
The trigger was wrong in the safe-looking direction: it under-fired. On an
install that has been carrying deficits quietly, correcting it means ADL starts
closing profitable positions at the bankruptcy price where previously the
platform absorbed the gap. That is the designed behaviour and it is what stops
money being created, but it is a visible change for traders. If you would
rather carry the deficit yourself, set futuresDeficitPolicy to absorb
before you update, and the fund goes negative instead where you can see it.
Fixed
Auto-deleveraging
- Fixed — the fund is judged on
balance − exposure, where exposure is what every open position in that settlement currency would take out of the fund at its current mark: a winner is owed their whole gain, a loser pays in at most their margin. The bankrupt position is excluded, because its margin is already in the balance and its loss beyond it is the shortfall being judged. A symbol with no usable mark counts as flat rather than as a maximum loss, the same reading the mark monitor applies, and a currency whose exposure cannot be measured falls back to judging on the balance alone with a warning. - Fixed — recovery is measured per close as the gain the deleveraged trader was not paid, the difference between their profit at the mark and at the bankruptcy price, which is exactly what closing them early frees. It was measured as the change in the fund's balance, which falls on every close, so it read as zero recovered forever and the loop closed the entire queue. The loop now stops as soon as the closes cover the uncovered part, and a close that would recover nothing is skipped rather than taken.
- Fixed — a deleveraged close writes an
ADLrow carrying the recovered amount as a negative shortfall, so the outstanding deficit nets down as deleveraging proceeds instead of standing at its original figure. The admin futures dashboard endpoint used to drop those rows with a per-rowshortfall > 0filter; it now sums per market and keeps the markets still in debt, so its figure agrees with the settlement code. The critical shortfall log is not raised for these closes, which are the remedy rather than the fault. - Changed —
autoDeleveragereports what it carried as well as what it recovered and closed, and refuses to run on an unusable mark price rather than deleveraging against a figure it cannot trust. Both call sites, liquidation and manual close, pass the mark they settled against.
The insurance ledger
- Fixed — a position that closes in several fills records every clearing slice. The unique index admitted one row per position and type, and the duplicate was swallowed as a concurrent settlement getting there first, so a liquidation sweeping four price levels contributed one slice of margin to the fund instead of four and the fund's balance was wrong from then on. Each slice now carries the same cumulative-fill key the wallet movement is keyed by, so genuine double settlement is still refused while distinct slices are kept.