- .claude/agents/executer.md - .claude/agents/planer.md - .claude/agents/pruefer.md - .claude/agents/recherche.md - .claude/skills/plan-executer-pruefung/SKILL.md - .claude/workflows/executer-welle.js - .claude/workflows/plankritik.js - .claude/workflows/pruefung.js - .claude/workflows/welle-mit-pruefung.js - .gitignore - .vault-tools/regelwerk-check/ENTWURF.md - .vault-tools/regelwerk-check/regelwerk_check.py - … und 20 weitere Erzeugt vom PostToolUse-Hook .vault-tools/auto-push/auto_push.py. Co-Authored-By: Claude Opus 5 <[email protected]>
66 lines
2.7 KiB
Python
66 lines
2.7 KiB
Python
"""Liest mit dem Alpaca-Klienten eines Code-Baums die echten Antworten des Paper-Kontos -- NUR LESEND, ohne Betraege auszugeben.
|
|
|
|
Koordinator-Pruefcode zu Paket S1 (strengerer Parser in trading/broker/alpaca.py). Frage: Liest der neue Parser
|
|
jede echte Antwort, die der alte las -- Konto, Positionen, offene Orders, die Orderhistorie (gefuellt, storniert),
|
|
Marktuhr, letzter Kurs? Ein Parser, der eine echte Order als unlesbar wertet, waere am Handelstag eine Stoerung.
|
|
Aufruf (WSL): python s1_alpaca_lesen.py <code-baum> <echter-projektordner>
|
|
"""
|
|
|
|
import collections
|
|
import dataclasses
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
CODE = Path(sys.argv[1]).resolve()
|
|
ECHT = Path(sys.argv[2]).resolve()
|
|
sys.path.insert(0, str(CODE))
|
|
os.chdir(ECHT)
|
|
|
|
from trading.broker.alpaca import AlpacaBroker # noqa: E402
|
|
from trading.risk.limits import lade_limits # noqa: E402
|
|
|
|
limits = lade_limits("config/risk.toml")
|
|
broker = AlpacaBroker.from_secrets(None, universum=limits.universum, feed="iex", timeout=10.0)
|
|
|
|
|
|
def form(objekt) -> str:
|
|
"""Feldnamen und Typen eines Dataclass-Objekts, nie die Werte."""
|
|
if dataclasses.is_dataclass(objekt):
|
|
return ", ".join(f"{f.name}:{type(getattr(objekt, f.name)).__name__}" for f in dataclasses.fields(objekt))
|
|
return type(objekt).__name__
|
|
|
|
|
|
schritte = [
|
|
("konto", lambda: broker.konto()),
|
|
("positionen", lambda: broker.positionen()),
|
|
("offene_orders", lambda: broker.offene_orders()),
|
|
("alle_orders(200)", lambda: broker.alle_orders(limit=200)),
|
|
("marktuhr", lambda: broker.marktuhr()),
|
|
("letzter_kurs", lambda: broker.letzter_kurs("AAPL.XNAS")),
|
|
("verbindung_ok", lambda: broker.verbindung_ok()),
|
|
]
|
|
befunde = 0
|
|
for name, aufruf in schritte:
|
|
try:
|
|
ergebnis = aufruf()
|
|
except Exception as ausnahme: # noqa: BLE001
|
|
befunde += 1
|
|
# Der Text eines BrokerFehler kann Antwortteile tragen; nur Typ und die ersten Zeichen ohne Ziffernfolgen.
|
|
print(f"{name}: AUSNAHME {type(ausnahme).__name__}: {str(ausnahme)[:160]}")
|
|
continue
|
|
if isinstance(ergebnis, list):
|
|
print(f"{name}: {len(ergebnis)} Eintraege" + (f"; Form: {form(ergebnis[0])}" if ergebnis else ""))
|
|
if ergebnis and hasattr(ergebnis[0], "status"):
|
|
print(" Status:", dict(collections.Counter(getattr(e, "status", "?") for e in ergebnis)))
|
|
leer = collections.Counter()
|
|
for eintrag in ergebnis:
|
|
for feld in dataclasses.fields(eintrag):
|
|
if getattr(eintrag, feld.name) is None:
|
|
leer[feld.name] += 1
|
|
print(" Felder mit None:", dict(leer))
|
|
else:
|
|
print(f"{name}: {form(ergebnis)}")
|
|
print(f"{befunde} Aufruf(e) mit Ausnahme.")
|
|
sys.exit(2 if befunde else 0)
|