55 lines
1.9 KiB
Python
55 lines
1.9 KiB
Python
"""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
|