Sicherheits-Gates

Bevor ein Vorschlag (Proposal) den Lynx-Adapter erreicht, durchlaeuft er mehrere Schutzschichten. Sie verhindern teure Fehlklicks und sorgen dafuer, dass nur konsistente Orders rausgehen.

1. Plan-Gate

Schreib-Endpoints (Proposals erstellen / submitten / senden / verwerfen, Presets speichern, Watchlist editieren) sind nur fuer Plaene medium, premium oder ultra freigegeben. Free- und Basic-Konten erhalten:

HTTP 403  { "error_code": "PLAN_REQUIRED", "data": { "required_plans": [...] } }

Im Frontend wird der Button vom <StrategyGate>-Wrapper halbtransparent und non-interaktiv dargestellt.

2. Statemachine-Gate

proposal_service.ALLOWED_TRANSITIONS bildet die zulaessigen Status-Uebergaenge ab:

draft       ─► pending, discarded
pending     ─► sent_to_lynx, discarded, expired
sent_to_lynx ─► executed, partially_executed, rejected, expired
partially_executed ─► executed, rejected

Verbotene Uebergaenge werfen IllegalProposalTransition → HTTP 409 mit error_code: "ILLEGAL_TRANSITION".

3. Auto-Cancel-Scheduler (3 Handelstage ohne Fill)

APScheduler ruft alle 5 Minuten proposal_service.discard_unfilled_after_3d auf (Alias: expire_overdue). Vorschlaege in sent_to_lynx oder partially_executed, deren expires_at ueberschritten ist, werden am Broker storniert und auf discarded gesetzt (status_reason='auto_3day_no_fill+...').

expires_at-Berechnung (1:1 wie Desktop-App):

  • Submit an einem Trading-Tag vor 14:00 ET -> Submit-Tag zaehlt als

Tag 1.

  • Submit nach 14:00 ET oder am Wochenende/Feiertag -> der naechste

Trading-Tag ist Tag 1.

  • Loeschung am 3. Trading-Tag nach 16:00 ET (NYSE-Schluss).
  • expires_at ist via zoneinfo("America/New_York") sommer-/

winterzeit-korrekt.

Drei Gates, damit nicht faelschlich storniert wird:

  1. Markt-Geschlossen-Gate: Cleanup laeuft nur ausserhalb der

NYSE-Handelszeit (sonst Skip).

  1. Gateway-Auth-Gate pro User: bei gateway_not_authenticated /

gateway_not_running werden die Kandidaten des Users uebersprungen; der naechste Tick versucht es erneut. Verhindert false-positive Discards bei Gateway-Ausfall.

  1. Broker-Confirm: Discard nur wenn Lynx den Cancel positiv bestaetigt

ODER die Order in den Live-Orders gar nicht mehr auftaucht. Sonst bleibt der Proposal offen mit status_reason='cleanup_failed:<grund>'.

4. CC-Lock-Gate

Beim Anlegen eines Covered-Calls prueft shares_locked_in_cc(symbol), wieviele Aktien bereits durch andere offene CCs (pending, sent_to_lynx, partially_executed) blockiert sind. Sie können nicht mehr Calls schreiben als Sie Aktien hast.

5. Mid-Drift-Gate

Bevor send_to_lynx ausgefuehrt wird, holt das Backend den frischen Mid und vergleicht mit dem urspruenglichen mid_initial_usd (Schwelle 2 % oder 0.01 USD absolut). Drift > Schwelle → HTTP 409 mit error_code: "MID_DRIFT_GATE". Im Frontend oeffnet sich das Drift-Modal.

Siehe Help-Topic "Smart-Limit & Mid-Drift".

6. Risk-Flag-Bewusstsein

Beim Anlegen aus einem Medal werden vorhandene Risk-Flags (Earnings, Ex-Div, IV-extreme, Low-Liquidity) in preflight_checks gespeichert. Das Frontend zeigt sie an, der User bestaetigt sie mit user_confirmed_warnings: true beim Submit.

7. User-Isolation

Alle Reads/Writes filtern strikt nach user_id. Es ist nicht moeglich, auf fremde Proposals, Watchlists oder Presets zuzugreifen. Jede HTTP-Route zieht den User aus Depends(get_current_active_user).

Zusammenspiel

        ┌───────────────────────────────────────────────────┐
Klick → │ Plan-Gate → Statemachine → CC-Lock → Mid-Drift    │ → Lynx-Adapter
        └───────────────────────────────────────────────────┘
                          ↑               ↑
                      Auto-Expire   User-Confirmation (Modal)

Erst wenn alle Gates passieren, geht die Order raus.