File size: 4,212 Bytes
c99df4c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
from PyQt6.QtWidgets import (
    QMainWindow, QDockWidget, QStatusBar, QMessageBox, QWidget
)
from PyQt6.QtCore import Qt

from src.ui.control_panel import ControlPanel
from src.ui.chart_widget import ChartWidget
from src.core.data_worker import DataWorker

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Python Trading Terminal (MT5 + Gap-Filled Profile)")
        self.resize(1200, 800)
        
        self.init_ui()
        self.worker = None

    def init_ui(self):
        # Status Bar
        self.status_bar = QStatusBar()
        self.setStatusBar(self.status_bar)
        
        # Dock: Control Panel
        self.dock_controls = QDockWidget("Controls", self)
        self.control_panel = ControlPanel()
        self.dock_controls.setWidget(self.control_panel)
        self.dock_controls.setAllowedAreas(Qt.DockWidgetArea.LeftDockWidgetArea | Qt.DockWidgetArea.RightDockWidgetArea)
        self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, self.dock_controls)
        
        # Central: Chart
        self.chart_widget = ChartWidget()
        self.setCentralWidget(self.chart_widget)
        
        # Connections
        self.control_panel.start_signal.connect(self.start_worker)
        self.control_panel.stop_signal.connect(self.stop_worker)

    def start_worker(self, symbol, date, multiplier):
        if self.worker is not None and self.worker.isRunning():
            return
            
        self.chart_widget.clear()
        self.chart_widget.price_plot.setTitle(f"{symbol} - {date} (Multiplier: {multiplier}x)")
        
        self.worker = DataWorker(symbol, date, multiplier=multiplier)
        self.worker.status_signal.connect(self.status_bar.showMessage)
        self.worker.data_signal.connect(self.handle_data)
        self.worker.levels_signal.connect(self.handle_levels)
        self.worker.finished.connect(self.on_worker_finished)
        
        self.worker.start()

    def stop_worker(self):
        if self.worker:
            self.worker.stop()
            self.worker = None
            self.status_bar.showMessage("Stream stopped.")

    def handle_data(self, ticks_df, profile_counts):
        # Update Chart with new ticks
        # Note: ChartWidget.update_ticks expects a dataframe. 
        # If we just append, we might need to handle state inside chart widget better.
        # But simpler: pass the full set or update logic.
        # For performance, we should probably append.
        # In current ChartWidget, update_ticks SETS data. 
        # DataWorker emits chunks (new_ticks) during loop, but FULL history at start.
        # We need to distinguish or accumulate in ChartWidget?
        # Actually, DataWorker emits distinct chunks in the loop.
        # But ChartWidget `setData` replaces content.
        # We need to accumulate data in ChartWidget or pass accumulated data from Worker.
        # Passing Full DF every 500ms with millions of rows is bad.
        # Better: ChartWidget accumulates.
        
        # Actually, let's just make ChartWidget append.
        # Or better: Worker sends everything? No.
        # Let's Modify ChartWidget to accumulate.
        
        # WAIT: My ChartWidget implementation `update_ticks` does: `self.bid_curve.setData(t_float, bids)`
        # This REPLACES.
        # I need to fix ChartWidget to handle incremental updates or large data better.
        # For now, let's just pass the full accumulated history from Worker?
        # Worker doesn't store accumulated history openly, it just emits `ticks_df` (chunk).
        # We need a way to append.
        
        # Let's fix ChartWidget in next step. For now assume it appends.
        self.chart_widget.update_ticks(ticks_df)
        self.chart_widget.update_profile(profile_counts) # Full profile is cheap (dict)

    def handle_levels(self, times, vah, val, poc):
        self.chart_widget.update_levels(times, vah, val, poc)

    def on_worker_finished(self):
        self.control_panel.on_stop()
        self.worker = None
        self.status_bar.showMessage("Ready.")