Skip to content

[RULE-REVIEW] POS-KILL: a leg of a defined-risk structure is never killed on its own (v1.0.1252) - #1583

Merged
github-actions[bot] merged 1 commit into
mainfrom
claude/poskill-structure-hold
Nov 2, 2026
Merged

github-actions[bot] merged 1 commit into
mainfrom
claude/poskill-structure-hold

Conversation

@mctils12-arch

Copy link
Copy Markdown
Owner

Why

Second half of "fix the condor close … make sure it works so we don't have this issue again" (2026-11-02). The first half, #1582 (v1.0.1251), makes options_manager close a multi-leg strategy as a unit and pursue the close until the legs are gone. This PR stops the Node side from undoing that.

The Tier-1 per-position kill in syncMonitoredPositions judged every option leg by its own premium P&L (−75 % long / −150 % short). On 10-28/29 it read the two long wings of the GOOGL Nov-27 iron condor as "down −99.8 %" and retried their liquidation every minute pre-market (122 audit lines), bought the short 310P back on a "−309 %" reading at $27.60 while its 300P wing was itself submitted for a sell on a zero mark — in the same minutes the options manager's own rules fired on the same legs (held_for_orders rejections). A defined-risk structure's worst case is bounded by its wings; a per-leg percent kill cannot see that and, by closing the legs at different times, pushed the loss past the structure's max loss.

What changes ([RULE-REVIEW]: scope, not threshold)

  • shared/positionLevels.ts: OPTIONS_DEFINED_RISK_STRATEGIES = iron_condor, qqq_iron_condor, bull_put_credit_spread, bull_call_spread, bear_put_spread, buy_straddle (a subset of the multi-leg set; short straddles are undefined-risk and stay out).
  • server/bot.ts: posKillOptionsStructures() reads voltrade_options_state.json once per sync (60 s cache) through the pure posKillDefinedRiskLegs(); inside the kill branch, a leg whose recorded strategy is defined-risk leaves the branch with one POS-KILL-STRUCTURE-HOLD audit line per ticker per UTC day and no order — the options manager closes the group. The branch opener, the mark guard, the two-tick confirmation, the duplicate guard, the POST and the informational POS-KILL-OPTION-HOLD line are untouched (the hold is one more continue before the mark guard; the sibling harness tests slice on the unchanged opener and still pass).
  • Prior value: every option leg judged alone (the 2026-10-13 scope fix). Rollback trigger (experiments.md): a defined-risk structure's realized loss exceeding its max loss (wing width × qty × 100 − net credit) by > 10 % while the manager could not act.

Downstream chain (REASONING STANDARD §1)

Fewer per-leg liquidations on structures → no duplicate orders against the manager's group close → the group closes as a unit at one moment, inside its wings' bound. During a Python-side halt a defined-risk structure is now unmanaged by Node, which is acceptable precisely because its loss is bounded by construction; undefined-risk legs keep the backstop. Single legs (the CSP sleeve) are unchanged.

Tests

  • server/posKillStructureHold.test.ts (new, 7): the set is a subset of the multi-leg set without short_straddle; posKillDefinedRiskLegs admits only defined-risk legs (unknown / single / short-straddle / garbage rejected); wiring pins (read once per sync, unchanged opener, hold before the mark guard with continue, option-skip line untouched); the real loop body run tick by tick against stubs — a condor wing at −99 % held with one line per day, the condor's short leg at −309 % held, a standalone sold put at −160 % and a straddle leg still killed on the second valid-mark tick, the informational OPTION-HOLD line unchanged.
  • All 117 kill-branch harness tests pass; full suites: server 2945/2945, client 1429/1429; tsc ratchet 6 ≤ 6; counter pins locked (tests 710, assertions 25863).

Closes research/open_questions.md KNOWN BROKEN #45 (b).


Generated by Claude Code

…lled on its own (v1.0.1252)

Human (2026-11-02): "fix the condor close … make sure it works so we don't
have this issue again and the logic works." Second half of that repair
(the first, v1.0.1251, makes options_manager pursue a group close until
the legs are gone).

The Tier-1 per-position kill in syncMonitoredPositions judged every
option leg by its own premium P&L. On 10-28/29 it read the two LONG WINGS
of the GOOGL Nov-27 iron condor as "down −99.8%" and retried their
liquidation every minute pre-market (122 audit lines), bought the short
310P back on a "−309%" reading at $27.60 while its 300P wing was itself
submitted for a sell on a zero mark — while options_manager's own group
rules fired on the same legs in the same minutes. A defined-risk
structure's worst case is bounded by its wings; a per-leg percent kill
cannot see that and closed the legs at different times, past max loss.

Scope change, no threshold change: a leg whose recorded strategy
(voltrade_options_state.json, read once per sync, 60 s cache) is in
OPTIONS_DEFINED_RISK_STRATEGIES (shared/positionLevels.ts) leaves the
kill branch with one POS-KILL-STRUCTURE-HOLD line per ticker per UTC day
and no order; options_manager closes the group as a unit. Single legs and
undefined-risk groups (short straddles) keep the backstop byte-for-byte:
the branch opener, mark guard, two-tick confirmation, duplicate guard and
POST are untouched (the hold is one more `continue` before the mark guard).

Prior value, evidence and the rollback trigger (a defined-risk structure's
realized loss beyond its max loss by > 10% while the manager could not
act) are logged in research/experiments.md; KNOWN BROKEN #45 (b) closes.

Tests: server/posKillStructureHold.test.ts (7) — the defined-risk set,
the pure filter, wiring pins, and the real loop body run tick by tick
against stubs (wing held, short leg held, standalone short put and a
straddle leg still killed). All 117 kill-branch harness tests pass.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BrrwY7BFkP8VNdwKPfaVn5
@github-actions
github-actions Bot merged commit 20adf65 into main Nov 2, 2026
6 checks passed
github-actions Bot pushed a commit that referenced this pull request Nov 2, 2026
… under candidate profit-taking rules (#1584)

Human (2026-11-02): "for the other options, figure out what's best for
taking profit". Data: /api/diag/lots (400 option lots since 05-07) and
/api/diag/option_bars (96 contracts' daily bars), the probes #1581 added.

Result: no bought-option profit rule has a population — of 91 bought lots,
7 lived past a day, all legs of structures, none ever closed a day above
+50% of its premium; the RULE-REVIEW candidate is withdrawn. Sold lots: the
live 50% target holds (a 25% target cuts the best lot $1,300 → $520 and
the total by ~$1,200; 75% ~ 50%). Where the money goes: 288 of 400 lots
never saw a second session (<1h −$4,812, <1d −$5,011, 1–7d −$3,784,
8–30d +$845) — the exit churn the condor repair (#1582) and the POS-KILL
structure hold (#1583) address in part; the same-day churn on single sold
legs needs intraday marks the archive does not keep yet.

Compiled: scripts/options_exit_study.py (re-runnable with DIAG_TOKEN);
research/options_exit_study_2026-11-02.md (method, limits, the GOOGL
condor case study, tables); research/experiments.md entry. No code path
of the bot touched; no threshold changed.


Claude-Session: https://claude.ai/code/session_01BrrwY7BFkP8VNdwKPfaVn5

Co-authored-by: Claude <noreply@anthropic.com>
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.

2 participants