121 lines
5.1 KiB
Python
121 lines
5.1 KiB
Python
import sys
|
|
import asyncio
|
|
from PySide6.QtWidgets import QApplication, QMainWindow, QLabel, QWidget, QVBoxLayout, QTabWidget
|
|
from PySide6.QtCore import Qt, QTimer, QThread, Signal
|
|
|
|
from .dashboard import DashboardPanel
|
|
from .strategy_panel import StrategyPanel
|
|
from .positions_panel import PositionsPanel
|
|
from .orders_panel import OrdersPanel
|
|
from .logs_panel import LogsPanel
|
|
|
|
|
|
class AsyncWorker(QThread):
|
|
def __init__(self, loop: asyncio.AbstractEventLoop, target_coro, kwargs):
|
|
super().__init__()
|
|
self.loop = loop
|
|
self.target_coro = target_coro
|
|
self.kwargs = kwargs
|
|
|
|
def run(self):
|
|
asyncio.set_event_loop(self.loop)
|
|
self.loop.run_until_complete(self.target_coro(**self.kwargs))
|
|
self.loop.close()
|
|
|
|
|
|
class MainWindow(QMainWindow):
|
|
def __init__(
|
|
self, broker, data_feed, db_session, order_manager, risk_manager, strategy_engine, settings, backend_runner, app_logger, portfolio
|
|
):
|
|
super().__init__()
|
|
self.broker = broker
|
|
self.data_feed = data_feed
|
|
self.db_session = db_session
|
|
self.order_manager = order_manager
|
|
self.risk_manager = risk_manager
|
|
self.strategy_engine = strategy_engine
|
|
self.settings = settings
|
|
self.backend_runner = backend_runner
|
|
self.app_logger = app_logger # Store the app_logger instance
|
|
self.portfolio = portfolio
|
|
|
|
self.setWindowTitle("Algo Trader")
|
|
self.setGeometry(100, 100, 1600, 900)
|
|
|
|
# Create main tab widget
|
|
self.tabs = QTabWidget()
|
|
self.tabs.setTabPosition(QTabWidget.North)
|
|
|
|
# Create panels
|
|
self.dashboard_panel = DashboardPanel()
|
|
self.strategy_panel = StrategyPanel()
|
|
self.positions_panel = PositionsPanel()
|
|
self.orders_panel = OrdersPanel()
|
|
self.logs_panel = LogsPanel()
|
|
|
|
# Add panels to tabs
|
|
self.tabs.addTab(self.dashboard_panel, "Dashboard")
|
|
self.tabs.addTab(self.strategy_panel, "Strategies")
|
|
self.tabs.addTab(self.positions_panel, "Positions")
|
|
self.tabs.addTab(self.orders_panel, "Orders")
|
|
self.tabs.addTab(self.logs_panel, "Logs")
|
|
|
|
self.setCentralWidget(self.tabs)
|
|
|
|
# Connect logger signal to logs panel
|
|
self.app_logger.log_signal.connect(self.logs_panel.append_log)
|
|
|
|
# Connect data_feed signals to dashboard and logger
|
|
self.data_feed.signals.connected.connect(lambda: self.app_logger.info("DataFeed: Connected"))
|
|
self.data_feed.signals.disconnected.connect(lambda: self.app_logger.warning("DataFeed: Disconnected"))
|
|
self.data_feed.signals.error.connect(lambda msg: self.app_logger.error(f"DataFeed Error: {msg}"))
|
|
self.data_feed.signals.tick.connect(self.dashboard_panel.update_market_data)
|
|
|
|
# Connect order_manager signals to orders panel
|
|
self.order_manager.signals.order_updated.connect(self.orders_panel.add_or_update_order)
|
|
|
|
# Connect portfolio signals to positions panel
|
|
self.portfolio.signals.position_updated.connect(self.positions_panel.add_or_update_position)
|
|
self.portfolio.signals.portfolio_value_updated.connect(lambda value: self.app_logger.info(f"Portfolio Value Updated: {value}"))
|
|
|
|
# Connect strategy_engine signals to strategy_panel and logger
|
|
self.strategy_engine.signals.strategy_loaded.connect(self.strategy_panel.update_status)
|
|
self.strategy_engine.signals.strategy_started.connect(lambda name: self.strategy_panel.update_status(f"Running: {name}"))
|
|
self.strategy_engine.signals.strategy_stopped.connect(lambda name: self.strategy_panel.update_status(f"Stopped: {name}"))
|
|
self.strategy_engine.signals.trade_signal.connect(lambda signal: self.app_logger.info(f"Trade Signal: {signal}"))
|
|
|
|
# Connect strategy_panel UI signals to strategy_engine methods
|
|
self.strategy_panel.strategy_selected.connect(self.strategy_engine.load_strategy)
|
|
self.strategy_panel.start_strategy_requested.connect(self.strategy_engine.start_strategy)
|
|
self.strategy_panel.stop_strategy_requested.connect(self.strategy_engine.stop_strategy)
|
|
|
|
# --- Asyncio Integration ---
|
|
self.loop = asyncio.get_event_loop()
|
|
if self.loop.is_running():
|
|
self.loop = asyncio.new_event_loop()
|
|
|
|
self.backend_worker = AsyncWorker(
|
|
loop=self.loop,
|
|
target_coro=self.backend_runner,
|
|
kwargs={
|
|
"broker": self.broker,
|
|
"data_feed": self.data_feed,
|
|
"db_session": self.db_session,
|
|
"order_manager": self.order_manager,
|
|
"risk_manager": self.risk_manager,
|
|
"strategy_engine": self.strategy_engine,
|
|
"settings": self.settings,
|
|
"portfolio": self.portfolio,
|
|
},
|
|
)
|
|
self.backend_worker.start()
|
|
|
|
def closeEvent(self, event):
|
|
if self.data_feed:
|
|
asyncio.run_coroutine_threadsafe(self.data_feed.close(), self.loop)
|
|
if self.db_session:
|
|
self.db_session.close()
|
|
self.loop.call_soon_threadsafe(self.loop.stop)
|
|
self.backend_worker.wait() # Wait for the backend thread to finish
|
|
super().closeEvent(event)
|