aureon-os / cli /trading_runtime.py
GaryLeckey's picture
Deploy Aureon OS (deploy/selfhost stack: nginx edge + fusion API x2 + console + HNC organ + redis + postgres; paper mode) (part 9)
d361784 verified
Raw History Blame Contribute Delete
3.68 kB
from __future__ import annotations
from aureon_baton_link import link_system as _baton_link; _baton_link(__name__)
import random
import threading
import time
from dataclasses import dataclass, field
from typing import List
from .config_manager import TradingConfig
@dataclass
class Position:
symbol: str
size: float
entry_price: float
@dataclass
class RuntimeState:
running: bool = False
pnl: float = 0.0
positions: List[Position] = field(default_factory=list)
logs: List[str] = field(default_factory=list)
class TradingService:
def __init__(self, config: TradingConfig):
self.config = config
self.state = RuntimeState()
self._worker: threading.Thread | None = None
self._stop_event = threading.Event()
self._current_price = 100.0
def start(self) -> None:
if self.state.running:
self.state.logs.append("Trading already running.")
return
self.state.running = True
self.state.logs.append(
f"Trading service started in {self.config.mode} mode for {self.config.base_asset}/{self.config.quote_asset}."
)
self._stop_event.clear()
self._worker = threading.Thread(target=self._run_loop, daemon=True)
self._worker.start()
def stop(self) -> None:
if not self.state.running:
return
self.state.logs.append("Stopping trading service...")
self._stop_event.set()
if self._worker and self._worker.is_alive():
self._worker.join(timeout=2)
self.state.running = False
self.state.logs.append("Trading stopped.")
def _run_loop(self) -> None:
while not self._stop_event.is_set():
jitter = random.uniform(-0.8, 1.5)
self._current_price = max(1.0, self._current_price + jitter)
# Mark-to-market for open positions
if self.state.positions:
pos = self.state.positions[0]
unrealized = (self._current_price - pos.entry_price) * pos.size * 0.01
self.state.pnl = round(unrealized, 2)
# Occasionally open or adjust a position
if random.random() > 0.75:
# Defensive check: trade_size is validated as positive in setup_wizard.py (lines 52-53),
# but this check is necessary in case the config is modified externally.
if self.config.trade_size <= 0:
self.state.logs.append("Trade size must be positive; adjust config to resume trading.")
else:
position = Position(
symbol=f"{self.config.base_asset}/{self.config.quote_asset}",
size=self.config.trade_size,
entry_price=round(self._current_price, 2),
)
self.state.positions = [position]
self.state.logs.append(
f"Opened {position.size} {position.symbol} @ {position.entry_price}"
)
if random.random() > 0.9 and self.state.positions:
closed = self.state.positions.pop()
realized = (self._current_price - closed.entry_price) * closed.size * 0.01
self.state.pnl = round(realized, 2)
self.state.logs.append(
f"Closed {closed.size} {closed.symbol} at {self._current_price:.2f} | P&L: {self.state.pnl}"
)
time.sleep(1)
__all__ = ["TradingService", "RuntimeState", "Position"]