- .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]>
78 lines
3.4 KiB
Python
78 lines
3.4 KiB
Python
"""Handabruf: Wie alt ist die juengste Minutenkerze, die Alpaca per REST fuer AAPL liefert?
|
|
|
|
Koordinator-Werkzeug zu Teil 10, nicht fuers Repo. Beantwortet vor dem ersten Paper-Lauf die
|
|
ungemessene Frage, ob der IEX-Feed eine gerade abgeschlossene Minute innerhalb von Sekunden
|
|
liefert (der Runner wartet `kerze_verzoegerung_s` und versucht es `kerze_versuche` mal) oder
|
|
ob die Kerzen verzoegert kommen. Sinnvoll, solange gehandelt wird -- Vorboerse ab 10:00 Uhr
|
|
Berliner Zeit (04:00 ET), regulaer ab 15:30 Uhr. Nachts zeigt es nur die letzte Kerze des
|
|
Vortags; dann belegt es nur, dass Schluessel und Abruf funktionieren.
|
|
|
|
Liest die Geheimnisdatei ueber den Aufloeser des Projekts (TRADING_GEHEIMNISSE, sonst config/secrets.toml), gibt die Schluessel nie aus.
|
|
|
|
Aufruf aus dem Projektordner (WSL, Venv):
|
|
~/venvs/trading/bin/python /mnt/d/Claude/.vault-tools/trading-plattform-pruefung/handabruf_kerzen.py [feed]
|
|
feed: iex (Standard) oder sip.
|
|
"""
|
|
|
|
import sys
|
|
import tomllib
|
|
from datetime import UTC, datetime, timedelta
|
|
from pathlib import Path
|
|
|
|
import requests
|
|
|
|
sys.path.insert(0, str(Path.cwd()))
|
|
from trading import geheimnisse # noqa: E402 -- aus dem Projektordner, wie oben verlangt
|
|
|
|
DATEN_URL = "https://data.alpaca.markets"
|
|
FRISCH_S = 120 # eine abgeschlossene Minute plus die Wartezeit des Runners
|
|
|
|
|
|
def main() -> int:
|
|
feed = sys.argv[1] if len(sys.argv) > 1 else "iex"
|
|
secrets = geheimnisse.pfad()
|
|
if not secrets.is_file():
|
|
print(f"VORAUSSETZUNG FEHLT: {geheimnisse.beschreibung()}")
|
|
return 3
|
|
werte = tomllib.loads(secrets.read_text(encoding="utf-8"))["alpaca"]
|
|
kopf = {"APCA-API-KEY-ID": werte["key_id"], "APCA-API-SECRET-KEY": werte["secret_key"]}
|
|
|
|
jetzt = datetime.now(UTC).replace(microsecond=0)
|
|
parameter = {
|
|
"symbols": "AAPL",
|
|
"timeframe": "1Min",
|
|
"start": (jetzt - timedelta(hours=36)).strftime("%Y-%m-%dT%H:%M:%SZ"),
|
|
"end": jetzt.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
|
"feed": feed,
|
|
"adjustment": "raw",
|
|
"limit": 10_000,
|
|
"sort": "desc",
|
|
}
|
|
gesendet = datetime.now(UTC)
|
|
antwort = requests.get(f"{DATEN_URL}/v2/stocks/bars", headers=kopf, params=parameter, timeout=30)
|
|
dauer_s = (datetime.now(UTC) - gesendet).total_seconds()
|
|
print(f"Feed {feed}, Anfrage bis {jetzt.isoformat()} (jetzt), Antwort {antwort.status_code} in {dauer_s:.2f} s")
|
|
if antwort.status_code >= 400:
|
|
print("Antworttext:", antwort.text[:300])
|
|
return 2
|
|
kerzen = (antwort.json().get("bars") or {}).get("AAPL") or []
|
|
if not kerzen:
|
|
print("keine Kerze in den letzten 36 Stunden -- das ist bei einem laufenden Handelstag ein Befund")
|
|
return 2
|
|
juengste = kerzen[0]
|
|
zeit = datetime.fromisoformat(juengste["t"].replace("Z", "+00:00"))
|
|
alter_s = (jetzt - zeit).total_seconds()
|
|
berlin = zeit.astimezone().strftime("%H:%M:%S %Z")
|
|
print(f"{len(kerzen)} Kerzen; juengste Kerze beginnt {zeit.isoformat()} ({berlin}), "
|
|
f"Alter {alter_s:.0f} s, Schluss {juengste['c']}, Volumen {juengste['v']}")
|
|
if alter_s <= FRISCH_S:
|
|
print(f"FRISCH: innerhalb von {FRISCH_S} s -- der Runner bekommt seine Kerze rechtzeitig")
|
|
else:
|
|
print(f"ALT: {alter_s / 60:.1f} min -- entweder wird gerade nicht gehandelt, oder der Feed kommt verzoegert; "
|
|
"waehrend der Handelszeit ist das ein Befund")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|