Как правильно добавлять/изменять динамические данные в gui типа pyqt5
Хочу сделать что-то типа торгового терминала криптобиржи для себя. Делаю стакан(orderbook), почти все работает, но нагрузка на процессор начинает быстро расти, с ростом новых строк в таблице gui. Может нужно иначе менять данные или этот pyqt5 не подходит для обмена большим кол-вом данных? Данные подгружаются через стрим, обрабатываются и распределяются по строкам в таблице. Может кто подскажет в какую сторону копать? Просто любой крипто терминал обрабатывает очень много стаканов и ведет себя нормально относительно нагрузки, а у меня от одного стакана нагрузка перегружает процессор до торможения и зависания программы. Если увеличить интервал на подгрузку данных в таблицу будет тоже самое, только через более длительное время. Сильно не ругайте, я новичок.
class Window(QMainWindow):
def __init__(self):
super().__init__()
desktop_width = QApplication.desktop().width()
desktop_height = QApplication.desktop().height()
self.sorted_ob_a = {}
self.sorted_ob_b = {}
self.is_first = True
window_width = 500
window_height = 800
ax = desktop_width // 2 - window_width // 2
ay = desktop_height // 2 - window_height // 2
self.setWindowTitle("Терминал для торговли")
self.setGeometry(ax, ay, window_width, window_height)
self.table = OrderBookTable(parent=self)
self.thread = MyThread(self.table)
self.thread.start()
self.thread.mysignal.connect(self.get_data)
def get_data(self, l_ob):
if self.is_first == True:
self.sorted_ob_a = l_ob[0]
self.sorted_ob_b = l_ob[1]
step_asset = int(0.010*1000)
start_price = 0
end_price = 0
for key, value in self.sorted_ob_a.items():
end_price = int(float(key)*1000)
for key, value in self.sorted_ob_b.items():
if start_price == 0:
start_price = int(float(key)*1000)
l_prices = [format(price/1000, '.3f') for price in range(start_price, end_price, step_asset)]
#
for row in l_prices:
item1 = QtGui.QStandardItem('0')
item2 = QtGui.QStandardItem('0')
item3 = QtGui.QStandardItem(str(row))
item3.setData(row, QtCore.Qt.ItemDataRole.DisplayRole)
self.table.sti.appendRow([item1, item2, item3])
self.table.sti.sort(2, order=QtCore.Qt.SortOrder.DescendingOrder)
self.table.setModel(self.table.sti)
self.table.setColumnWidth(1, 70)
self.table.setColumnWidth(2, 70)
self.table.resize(500, 800)
self.is_first = False
else:
# print('Im here')
self.sorted_ob_a = l_ob[0]
self.sorted_ob_b = l_ob[1]
for key, value in self.sorted_ob_a.items():
l_items = self.table.sti.findItems(str(key), column=2)
if len(l_items) > 0:
item_row = l_items[0].row()
self.table.sti.takeRow(item_row)
item1 = QtGui.QStandardItem('ask')
item2 = QtGui.QStandardItem(str(value))
item3 = QtGui.QStandardItem(str(key))
item3.setData(key, QtCore.Qt.ItemDataRole.DisplayRole)
item3.setBackground(QtGui.QColor.fromRgb(209, 151, 144))
self.table.sti.insertRow(item_row, [item1, item2, item3])
else:
item1 = QtGui.QStandardItem('ask')
item2 = QtGui.QStandardItem(str(value))
item3 = QtGui.QStandardItem(str(key))
item3.setData(key, QtCore.Qt.ItemDataRole.DisplayRole)
item3.setBackground(QtGui.QColor.fromRgb(209, 151, 144))
self.table.sti.appendRow([item1, item2, item3])
for key, value in self.sorted_ob_b.items():
l_items = self.table.sti.findItems(str(key), column=2)
if len(l_items) > 0:
item_row = l_items[0].row()
self.table.sti.takeRow(item_row)
item1 = QtGui.QStandardItem('bid')
item2 = QtGui.QStandardItem(str(value))
item3 = QtGui.QStandardItem(str(key))
item3.setData(key, QtCore.Qt.ItemDataRole.DisplayRole)
item3.setBackground(QtGui.QColor.fromRgb(144, 209, 162))
self.table.sti.insertRow(item_row, [item1, item2, item3])
else:
item1 = QtGui.QStandardItem('bid')
item2 = QtGui.QStandardItem(str(value))
item3 = QtGui.QStandardItem(str(key))
item3.setData(key, QtCore.Qt.ItemDataRole.DisplayRole)
item3.setBackground(QtGui.QColor.fromRgb(144, 209, 162))
self.table.sti.appendRow([item1, item2, item3])
self.table.sti.sort(2, order=QtCore.Qt.SortOrder.DescendingOrder)
self.table.setModel(self.table.sti)
self.table.resize(500, 800)
class OrderBookTable(QTableView):
def __init__(self, parent=None):
super().__init__(parent)
self.sti = QtGui.QStandardItemModel()
self.sti.setHorizontalHeaderLabels(['Направление', 'Кол-во', 'Цена'])
class MyThread(QtCore.QThread):
mysignal = QtCore.pyqtSignal(list)
def __init__(self, table: OrderBookTable):
super().__init__()
self.table = table
self.running = False
def run(self):
self.running = True
self.isFirst = True
url = 'wss://fstream.binance.com/ws/bnbusdt@depth'
json_result = []
order_book_a = {}
order_book_b = {}
prev_u = 0
count = 0
threading.Thread(target=Binance_FStream, args=(url, json_result), daemon=True).start()
client = None
print('Started')
while self.running:
if client == None:
client = Binance_API_F(api_key=keys.api_key, secret_key=keys.secret_key)
snapshot_result = client.get_depth('bnbusdt', 50)
lastUpdateId = snapshot_result['lastUpdateId']
for i in snapshot_result['asks']:
order_book_a[i[0]] = i[1]
for i in snapshot_result['bids']:
order_book_b[i[0]] = i[1]
for i in json_result:
# print("u = ", i['u'], "U = ", i['U'], "lastUpdateId = ", lastUpdateId)
if i['u'] <= lastUpdateId:
json_result.remove(i)
prev_u = lastUpdateId
print('First Start Client!')
sorted_ob_a = dict(sorted(order_book_a.items()))
sorted_ob_b = dict(sorted(order_book_b.items()))
l_ob = [sorted_ob_a, sorted_ob_b]
self.mysignal.emit(l_ob)
else:
if self.isFirst == True:
for i in json_result:
# print("u = ", i['u'], "pu = ", i['pu'], "lastUpdateId = ", lastUpdateId)
if i['U'] <= lastUpdateId +1 <= i['u']:
print('WE ARE IN LASTUPDATE +1')
for j in i['a']:
order_book_a[j[0]] = j[1]
for j in i['b']:
order_book_b[j[0]] = j[1]
prev_u = i['u']
json_result.remove(i)
self.isFirst = False
else:
for i in json_result:
count = 0
if i['pu'] == prev_u:
count += 1
print('Im here')
print(len(json_result))
for j in i['a']:
order_book_a[j[0]] = j[1]
for j in i['b']:
order_book_b[j[0]] = j[1]
prev_u = i['u']
json_result.remove(i)
if count == 0:
client = None
self.isFirst = True
sorted_ob_a = dict(sorted(order_book_a.items()))
sorted_ob_b = dict(sorted(order_book_b.items()))
l_ob = [sorted_ob_a, sorted_ob_b]
self.mysignal.emit(l_ob)
time.sleep(0.5)