"""Orchestrierung von Paper-/Simulations- und Live-Trading über den Broker. - Paper-Modus: Simulationslauf über die Engine (Käufe/Verkäufe werden lokal gegen den Kurs-Feed gebucht, kein echtes Geld). - Live-Modus: platziert echte Markerorders über die Exchange-API. """ from __future__ import annotations import logging from .config import Config from .engine import Engine, Result from .exchange import Broker from .strategy import Strategy log = logging.getLogger("trademind.trader") class Trader: def __init__(self, cfg: Config, broker: Broker, strategy: Strategy): self.cfg = cfg self.t = cfg.trading self.broker = broker self.strategy = strategy self.engine = Engine(self.t, strategy) def symbol(self) -> str: base = self.t.base_currency.upper() quote = self.t.quote_currency.upper() if self.broker.name == "coinbase": return f"{base}-{quote}" return f"{base}/{quote}" def fetch_candles(self): return self.broker.fetch_ohlcv(self.symbol(), self.t.timeframe, self.t.candles) def simulate(self) -> Result: """Simulationslauf (Paper-Trading) über die verfügbaren Candles.""" candles = self.fetch_candles() return self.engine.run(candles) def live_cycle(self): """Ein Live-Zyklus: Signal bewerten und ggf. echte Order platzieren.""" candles = self.fetch_candles() prep = self.strategy.prepare(candles) sig = self.strategy.last_signal(prep) if sig.action == 1: size = (self.t.initial_balance * self.t.position_size_pct) / max(sig.price, 1e-9) return self.broker.create_market_order(self.symbol(), "buy", size) if sig.action in (-1, 2): size = (self.t.initial_balance * self.t.position_size_pct) / max(sig.price, 1e-9) return self.broker.create_market_order(self.symbol(), "sell", size) return None