Automatischer Push: 8 Datei(en) geändert
- .vault-tools/trading-plattform-pruefung/LIESMICH.md - .vault-tools/trading-plattform-pruefung/abbau_alpaca_lesen.py - .vault-tools/trading-plattform-pruefung/abbau_glattstellen.sh - .vault-tools/trading-plattform-pruefung/abbau_ibkr_lesen.sh - .vault-tools/trading-plattform-pruefung/abbau_restbestand.py - .vault-tools/trading-plattform-pruefung/abbau_restbestand_angriffe.py - .vault-tools/trading-plattform-pruefung/abbau_restbestand_einrichten.ps1 - AI/Regelwerk/windows-shell.md Erzeugt vom PostToolUse-Hook .vault-tools/auto-push/auto_push.py. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
1 parent
30ed04a643
commit
3784322a76
8 files changed
+1687
-3
No files matched your search
@@ -0,0 +1,101 @@
|
||||
"""Abbau Restbestand: liest Marktuhr, Positionen und offene Orders des Alpaca-Paper-Kontos, nur lesend.
|
||||
|
||||
Ersteller: Pascal Michel
|
||||
Erstellt: 2026-10-07
|
||||
Doku: LIESMICH.md in diesem Ordner, Abschnitt "Paket AB"
|
||||
|
||||
Laeuft in WSL mit dem Venv des Alpaca-Ordners (~/venvs/trading); gestartet von abbau_restbestand.py
|
||||
ueber wsl.exe --exec. Ruft nur marktuhr(), positionen() und offene_orders() von AlpacaBroker
|
||||
(trading/broker/alpaca.py: GET /v2/clock, /v2/positions, /v2/orders?status=open). Nichts davon
|
||||
schreibt beim Broker oder auf der Platte.
|
||||
Ausgabe: genau eine JSON-Zeile auf stdout mit
|
||||
uhr {"offen": bool, "sekunden_bis_schluss": int} oder null
|
||||
uhr_fehler Text oder null
|
||||
positionen [{"symbol": str, "menge": int}] oder null; menge ist negativ bei short
|
||||
orders Zahl der offenen Orders oder null
|
||||
bestand_fehler Text oder null
|
||||
Nie ein Betrag: Von einer Position gehen nur Symbol und Stueckzahl weiter, von den Orders nur die
|
||||
Zahl. Fehlertexte laufen durch ohne_kontonummer() aus abendkontrolle_wsl.py (Kontonummern, dann
|
||||
maskiere()) und danach durch DEZIMAL: jede Dezimalzahl wird [x], ganze Zahlen bleiben.
|
||||
Den Projektordner nennt der Aufrufer (--projekt); hier steht kein echter Pfad.
|
||||
Aufruf: python abbau_alpaca_lesen.py --projekt <alpaca-ordner>
|
||||
Exit: 0 mit der JSON-Zeile (auch wenn darin Fehler stehen), 2 Bedienfehler.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from datetime import timezone
|
||||
from pathlib import Path
|
||||
|
||||
HIER = Path(__file__).resolve().parent
|
||||
sys.path.insert(0, str(HIER))
|
||||
from abendkontrolle_wsl import ohne_kontonummer # noqa: E402
|
||||
|
||||
GEHEIMNISSE = "/home/claude/.config/trading-plattform/secrets.toml"
|
||||
RISIKO = "config/risk.toml"
|
||||
FEHLERTEXT_MAX = 200
|
||||
# Jede Dezimalzahl, auch ohne Geldwort davor; maskiere() faengt nur Zahlen hinter Geldwoertern,
|
||||
# vor Waehrungen oder mit vielen Stellen.
|
||||
DEZIMAL = re.compile(r"-?\d+[.,]\d+")
|
||||
|
||||
|
||||
def fehlertext(ausnahme: BaseException) -> str:
|
||||
"""Typ und Text einer Ausnahme: Kontonummern als [konto], Betraege als [x], gekuerzt."""
|
||||
text = ohne_kontonummer(f"{type(ausnahme).__name__}: {ausnahme}")
|
||||
return DEZIMAL.sub("[x]", text)[:FEHLERTEXT_MAX]
|
||||
|
||||
|
||||
def lies(broker, jetzt: datetime) -> dict:
|
||||
"""Marktuhr und Bestand; jede Frage fuer sich, ein Fehler in der einen haelt die andere nicht auf."""
|
||||
ergebnis = {"uhr": None, "uhr_fehler": None, "positionen": None, "orders": None, "bestand_fehler": None}
|
||||
try:
|
||||
uhr = broker.marktuhr()
|
||||
ergebnis["uhr"] = {
|
||||
"offen": bool(uhr.is_open),
|
||||
"sekunden_bis_schluss": int((uhr.next_close - jetzt).total_seconds()),
|
||||
}
|
||||
except Exception as ausnahme:
|
||||
ergebnis["uhr_fehler"] = fehlertext(ausnahme)
|
||||
try:
|
||||
positionen = broker.positionen()
|
||||
orders = broker.offene_orders()
|
||||
ergebnis["positionen"] = [
|
||||
{"symbol": position.symbol, "menge": int(position.menge)} for position in positionen
|
||||
]
|
||||
ergebnis["orders"] = len(orders)
|
||||
except Exception as ausnahme:
|
||||
ergebnis["positionen"] = None
|
||||
ergebnis["orders"] = None
|
||||
ergebnis["bestand_fehler"] = fehlertext(ausnahme)
|
||||
return ergebnis
|
||||
|
||||
|
||||
def main(argv=None) -> int:
|
||||
zerleger = argparse.ArgumentParser(description=__doc__.splitlines()[0], allow_abbrev=False)
|
||||
zerleger.add_argument("--projekt", required=True, help="Ordner der Alpaca-Instanz in WSL")
|
||||
argumente = zerleger.parse_args(argv)
|
||||
os.environ.setdefault("TRADING_GEHEIMNISSE", GEHEIMNISSE)
|
||||
try:
|
||||
os.chdir(argumente.projekt)
|
||||
sys.path.insert(0, str(Path(argumente.projekt).resolve()))
|
||||
from trading.broker.alpaca import AlpacaBroker
|
||||
from trading.risk.limits import lade_limits
|
||||
|
||||
broker = AlpacaBroker.from_secrets(None, universum=lade_limits(RISIKO).universum)
|
||||
except Exception as ausnahme:
|
||||
grund = fehlertext(ausnahme)
|
||||
print(json.dumps(
|
||||
{"uhr": None, "uhr_fehler": grund, "positionen": None, "orders": None, "bestand_fehler": grund},
|
||||
ensure_ascii=False,
|
||||
))
|
||||
return 0
|
||||
print(json.dumps(lies(broker, datetime.now(timezone.utc)), ensure_ascii=False))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in new issue
Block a user