Skip to content

feat(orders): TradingView margin-call liquidation#47

Merged
luisleo526 merged 1 commit into
mainfrom
feat/margin-call-liquidation
Jun 30, 2026
Merged

feat(orders): TradingView margin-call liquidation#47
luisleo526 merged 1 commit into
mainfrom
feat/margin-call-liquidation

Conversation

@luisleo526

Copy link
Copy Markdown
Collaborator

Summary

Models TradingView's broker-emulator forced liquidation (margin call), which the engine previously didn't — margin_liquidation_price() was stubbed to na and positions were never liquidated. Proven parity gap: 24 scraped strategies have TV Margin call rows the engine never produced (it held the position).

Implementation

  • margin_liquidation_price() — validated TV formula: liq = ((init_cap + net_profit)/(pointvalue·|size|) − dir·entry) / (margin/100 − dir), mintick-rounded (ceil short / floor long); na when flat or for a long at 100% margin (denominator 0 → can never be liquidated → corpus no-op).
  • per-bar process_margin_call() — when equity at the bar's adverse extreme (high for shorts, low for longs) drops below required margin, force-close 4× the minimum needed to restore margin (TV's documented over-liquidation), filled at the adverse extreme, tagged "Margin call". Default-on to match TV, with set_margin_call_enabled() opt-out.

The formula + trigger + fill price were reverse-engineered and validated against a TradingView ground-truth probe (TV margin-call docs).

Gates

  • ctest 76/76 — new test_margin_call (teeth-verified: neutralizing the liquidation → 9 failures).
  • Corpus verify_corpus --all = 251 excellent / 1 anomaly — a true no-op (equity-mirror is long-only → na); zero tier regressions.
  • Functional proof: P2 probe (100%-equity short, no exit) 0 → 48 margin-call exits, first fills 1798.26 / 1819.00 / 1845.78 / 1885.00 byte-for-byte vs TV.
  • Scraped strict-match wins: abhivish 16→64%, pridarasx 44→80%.
  • No PF_API/C-ABI export added (CI ABI gate unaffected).

Known residual (separable follow-up): TV floors each liquidation to the instrument's qty-step, so its position survives longer (68 calls vs our 48). Doesn't affect corpus parity.

🤖 Generated with Claude Code

Model TradingView's broker-emulator forced liquidation, which the engine
previously did not (margin_liquidation_price() was stubbed to na). Closes a
proven parity gap on strategies that ride leveraged/short positions into a
margin call: 24 scraped strategies have TV "Margin call" rows the engine never
produced (it held the position instead).

- margin_liquidation_price(): the validated TV formula
  liq = ((init_cap + net_profit)/(pointvalue*|size|) - dir*entry) / (margin/100 - dir),
  mintick-rounded (ceil short / floor long); na when flat or for a long at 100%
  margin (denominator 0 -> can never be liquidated).
- per-bar process_margin_call(): when equity at the bar's adverse extreme (high for
  shorts, low for longs) drops below required margin, force-close 4x the minimum
  needed to restore margin (TV's documented over-liquidation), filled at the
  adverse extreme, tagged "Margin call". Default-on to match TV, with
  set_margin_call_enabled() opt-out.

Validated: P2 probe (100%-equity short) 0 -> 48 margin-call exits, first fills
1798.26 / 1819.00 / 1845.78 / 1885.00 byte-for-byte vs TradingView. Scraped strict
match: abhivish 16->64%, pridarasx 44->80%. ctest 76/76 (new test_margin_call,
teeth-verified). Corpus verify_corpus --all = 251 excellent / 1 anomaly: a true
no-op (equity-mirror is long-only -> na). Residual vs TV's 68 calls is
per-instrument liquidation-lot quantization, a separable follow-up.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@luisleo526 luisleo526 merged commit 848cce3 into main Jun 30, 2026
5 checks passed
@luisleo526 luisleo526 deleted the feat/margin-call-liquidation branch June 30, 2026 10:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant