Skip to content

pmengine v0.6.0

Latest

Choose a tag to compare

@github-actions github-actions released this 24 Aug 02:28
· 75 commits to master since this release

Public flavor — private strategies not included. This build carries only the in-tree example strategy; it is not the binary the live engine runs.

Two engine-halting bugs, and the tape now reaches a remote operator.

Fixed

  • The circuit breaker halted on a paper loss it could not price. It judged on realized + unrealized, but taker fills never write realized, and mid_price returns nothing for a one-sided book — so a resolving market's mark froze, the next position reconcile re-derived a doubling loss against that stale price, and the breaker tripped at −412 while the session was up $29. It now reads realized P&L in full plus marks on only the positions carrying a fresh, tradeable price, and reconcile moves share counts without inventing a re-mark.
  • Cancel storm. A cancel the CLOB refused terminally — already cancelled, already matched, not found — was read as "still live" and re-sent every 50ms tick: 16,028 round trips against 195 dead order ids, with 97% of batch cancels retiring nothing. A terminal answer now retires the order once; only transient failures retry, backing off 0.5s to a 30s ceiling. The worst observed window drops from 416 refusals to at most 5 calls.
  • Cancel/replace churn on coarse-tick markets. The keep-vs-replace check compared the strategy's raw model price against the order's wire price — two different grids — so a sub-tick drift cancelled and re-posted the identical wire order, buying nothing and paying queue position.
  • Position reconcile fetches the account once per pass instead of once per subscribed token. Sixteen sequential whole-account downloads every ~1.5s were starving the control plane for up to 9s and running the tick loop 22% behind schedule.

Added

  • GET /tape?since=&limit= on the control plane — a bounded reverse-tail of the eval/fire tape, so pmt crypto watch renders against an engine on another host. It never enters the trading loop, and is capped twice: at most 512KB read off the tail and at most limit records parsed, so cost does not grow with the tape.
  • PM_SIGNATURE_TYPE=3 for deposit wallets (EIP-1271 / ERC-7739). Frozen golden vectors prove the Rust order path byte-identical to the Python reference offline. An unrecognised value now warns instead of silently becoming an EOA.
  • PMENGINE_SERIES_ALLOWLIST — the slug prefixes this engine may trade. Two engines under one operator account share a book, so one can match the other's resting quote; arms outside the list are now refused. Unset keeps prior behaviour byte-for-byte.
  • replay --trace writes a decision trace per tape record, and an unknown tunables key is a hard error rather than a silent fall back to the default.