refactor: migrate to official Tralgo API, remove cookie/logfile parser

This commit is contained in:
2026-06-02 19:36:14 +02:00
parent c474b82bf0
commit 3e55f5f12d
6 changed files with 86 additions and 757 deletions
+55 -47
View File
@@ -7,9 +7,8 @@ from tkinter import messagebox, ttk
from config import (DEFAULT_INSTRUMENTS, load_config, load_sent, save_config,
save_sent)
from cookie_reader import find_cookies
from dtc_client import DTCClient, fills_to_trades, monitor_realtime
from tralgo_api import build_session, send_trade
from tralgo_api import send_trade, send_trades_bulk
try:
from PIL import Image, ImageTk
@@ -58,7 +57,6 @@ class ConfigWindow:
pad = {"padx": 10, "pady": 3}
self._api_key_var = self._labeled_entry("API Key *", cfg.get("api_key", ""), **pad)
self._email_var = self._labeled_entry("Tralgo E-Mail", cfg.get("email", ""), **pad)
self._dtc_host_var = self._labeled_entry(
"SC DTC Host", cfg.get("dtc_host", "localhost"), **pad)
@@ -210,7 +208,6 @@ class ConfigWindow:
}
self._on_save({
"api_key": api_key,
"email": self._email_var.get().strip(),
"dtc_host": self._dtc_host_var.get().strip() or "localhost",
"dtc_port": dtc_port,
"accounts": list(self._acc_listbox.get(0, tk.END)),
@@ -231,16 +228,16 @@ class ManualImportWindow:
"Entry", "Exit", "PnL $", "Ticks", "Status")
_WIDTHS = (30, 100, 140, 65, 70, 80, 80, 70, 55, 70)
def __init__(self, parent, config, sent, session, api_key, on_imported):
def __init__(self, parent, config, sent, api_key, on_imported, on_reset):
self.win = tk.Toplevel(parent)
self.win.title("Manueller Import GizerBridge")
self.win.geometry("870x520")
self.win.resizable(True, True)
self._config = config
self._sent = sent # set of trade IDs already sent
self._session = session # requests.Session or None
self._api_key = api_key
self._on_imported = on_imported # callback(trade_id) → updates App.sent
self._on_reset = on_reset # callback(trade_id) → removes from App.sent
self._rows = [] # [(iid, trade_dict, is_sent)]
self._build()
@@ -312,6 +309,9 @@ class ManualImportWindow:
tk.Button(bot, text="Alle auswählen", command=self._select_all).pack(side=tk.LEFT, padx=(0, 4))
tk.Button(bot, text="Keine", command=self._select_none).pack(side=tk.LEFT, padx=4)
self._reset_btn = tk.Button(bot, text="Import zurücksetzen",
command=self._reset_sent, state=tk.DISABLED)
self._reset_btn.pack(side=tk.LEFT, padx=4)
self._status_lbl = tk.Label(bot, text="", fg="gray")
self._status_lbl.pack(side=tk.LEFT, padx=12)
@@ -416,6 +416,7 @@ class ManualImportWindow:
if already:
parts.append(f"{already} bereits importiert")
self._count_lbl.config(text=" ".join(parts))
self._refresh_import_btn()
# ── Checkbox interaction ──────────────────────────────────────────────────
@@ -426,18 +427,22 @@ class ManualImportWindow:
for row_iid, trade, is_sent in self._rows:
if row_iid != iid:
continue
if is_sent:
return
vals = list(self._tree.item(iid, "values"))
if vals[0] == self._CHK_OFF:
vals[0] = self._CHK_ON
self._tree.item(iid, values=vals, tags=("sel",))
else:
vals[0] = self._CHK_OFF
self._tree.item(iid, values=vals, tags=("sent" if is_sent else "desel",))
self._tree.item(iid, values=vals, tags=("desel",))
break
self._refresh_import_btn()
def _select_all(self):
for iid, _, is_sent in self._rows:
if is_sent:
continue
vals = list(self._tree.item(iid, "values"))
vals[0] = self._CHK_ON
self._tree.item(iid, values=vals, tags=("sel",))
@@ -456,19 +461,36 @@ class ManualImportWindow:
for iid, _, _ in self._rows
)
self._import_btn.config(state=tk.NORMAL if any_checked else tk.DISABLED)
any_sent = any(is_sent for _, _, is_sent in self._rows)
self._reset_btn.config(state=tk.NORMAL if any_sent else tk.DISABLED)
# ── Reset sent ────────────────────────────────────────────────────────────
def _reset_sent(self):
if not messagebox.askyesno(
"Import zurücksetzen",
"Bereits importierte Trades zurücksetzen?\n"
"Sie können danach erneut importiert werden.",
parent=self.win,
):
return
updated = []
for iid, trade, is_sent in self._rows:
if is_sent:
self._on_reset(trade["trade_id"])
vals = list(self._tree.item(iid, "values"))
vals[0] = self._CHK_OFF
vals[9] = ""
self._tree.item(iid, values=vals, tags=("desel",))
updated.append((iid, trade, False))
else:
updated.append((iid, trade, is_sent))
self._rows = updated
self._refresh_import_btn()
# ── Import ────────────────────────────────────────────────────────────────
def _import_selected(self):
if self._session is None:
messagebox.showerror(
"Keine Verbindung",
"Keine aktive Tralgo-Sitzung.\n"
"Bitte Firefox-Cookie prüfen und App neu starten.",
parent=self.win,
)
return
to_send = [
(iid, trade)
for iid, trade, _ in self._rows
@@ -483,28 +505,21 @@ class ManualImportWindow:
self._status_lbl.config(text=f"Importiere {len(to_send)} Trade(s)…")
def _run():
ok = err = 0
for iid, trade in to_send:
try:
send_trade(self._session, trade, self._api_key)
trades_list = [trade for _, trade in to_send]
try:
send_trades_bulk(self._api_key, trades_list)
for iid, trade in to_send:
self._on_imported(trade["trade_id"])
ok += 1
self.win.after(0, lambda i=iid, t=trade: self._mark_ok(i, t))
except Exception as e:
err += 1
self.win.after(0, lambda i=iid, msg=str(e): self._mark_err(i, msg))
summary = f"Fertig: {ok} importiert"
if err:
summary += f", {err} Fehler"
summary = f"Fertig: {len(to_send)} importiert"
except Exception as e:
msg = str(e)
for iid, _ in to_send:
self.win.after(0, lambda i=iid, m=msg: self._mark_err(i, m))
summary = f"Fehler: {msg[:60]}"
self.win.after(0, lambda: self._import_btn.config(state=tk.NORMAL))
self.win.after(0, lambda: self._status_lbl.config(text=summary))
self.win.after(0, lambda: self._search_btn.config(state=tk.NORMAL))
# Re-enable import for any rows that still failed
remaining = any(
not is_sent and self._tree.item(r_iid, "values")[0] == self._CHK_ON
for r_iid, _, is_sent in self._rows
)
if remaining:
self.win.after(0, lambda: self._import_btn.config(state=tk.NORMAL))
threading.Thread(target=_run, daemon=True).start()
@@ -539,7 +554,6 @@ class App:
pass
self.config = load_config()
self.sent = load_sent()
self.session = None
self._status_color = "yellow"
self._status_msg = "Initialisierung..."
self._log_entries = []
@@ -631,16 +645,6 @@ class App:
self._queue.put(lambda: self._set_icon_color("red"))
return
cookies, err = find_cookies()
if err:
self._log(f"Cookie-Fehler: {err}")
self._queue.put(lambda: self._set_icon_color("red"))
self._queue.put(lambda: messagebox.showwarning(
"Tralgo Cookie fehlt", err, parent=self.root))
return
self.session = build_session(cookies)
host = cfg.get("dtc_host", "localhost")
port = cfg.get("dtc_port", 11099)
accounts = cfg.get("accounts", [])
@@ -650,7 +654,7 @@ class App:
if trade["trade_id"] in self.sent:
return
try:
send_trade(self.session, trade, cfg["api_key"])
send_trade(cfg["api_key"], trade)
self.sent.add(trade["trade_id"])
save_sent(self.sent)
msg = (f"Übertragen: {trade['instrument']} {trade['direction']} "
@@ -773,15 +777,19 @@ class App:
self.root,
self.config,
self.sent,
self.session,
self.config.get("api_key", ""),
self._on_trade_manually_imported,
self._on_trade_reset,
)
def _on_trade_manually_imported(self, trade_id):
self.sent.add(trade_id)
save_sent(self.sent)
def _on_trade_reset(self, trade_id):
self.sent.discard(trade_id)
save_sent(self.sent)
def _on_config_saved(self, new_cfg):
self.config = new_cfg
save_config(new_cfg)