上一篇文章《PySide6 打造 TradingView级专业K线图,超简单教程来袭!(附完整源码)》有详细介绍了在PySide6中使用lightweight-charts,并可以集成到咱们的CryptoTrader中,使得K线的显示更加的专业。那么今天,我就来介绍一下如何将lightweight-charts集成到咱们的CryptoTrader中。
1. 环境准备
1.1 安装lightweight-charts-python
pip install lightweight-charts
2. 新建一个组件
在gui下components包下面新建一个python文件,命名为kline_charts.py。
2.1 导入必要的库
import pandas as pd
from gui.ui.qt import QVBoxLayout, QWidget
from core.trader.object import BarData
from lightweight_charts.widgets import QtChart
- • pandas 是一个强大的数据处理库,用于处理和分析数据;
- • QVBoxLayout 和 QWidget 来自 gui.ui.qt模块,用于创建和管理图形用户界面的布局和窗口;
- • BarData是 core.trader.object模块中的类,存储K线数据;
- • QtChart是 lightweight_charts.widgets模块中的类,用于创建 K 线图表,专门用于PyQT或者Pyside中。
2.2 KlineCharts类定义
class KlineCharts(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.inited: bool = False
self.layout = QVBoxLayout(self)
self.KLineChart = QtChart(self)
self.KLineChart.legend(visible=True)
self.KLineChart.topbar.button('my_button', 'Off', func=on_button_press)
self.layout.setContentsMargins(0, 0, 0, 0)
self.layout.addWidget(self.KLineChart.get_webview())
- • KlineCharts类继承自QWidget,是一个图形用户界面的窗口组件;
- • self.inited:一个布尔类型的变量,用于标记图表是否已经初始化;
- • self.layout:创建一个垂直布局 QVBoxLayout,用于管理图表组件的布局;
- • self.KLineChart:创建一个 QtChart 实例,用于显示 K 线图表;
- • self.KLineChart.legend(visible=True):设置图表的图例可见;
- • self.KLineChart.topbar.button('my_button', 'Off', func=on_button_press):在图表的顶部栏添加一个按钮,初始状态为 “Off”,点击按钮时会调用 on_button_press 函数;
- • self.layout.setContentsMargins(0, 0, 0, 0):设置布局的边距为 0;
- • self.layout.addWidget(self.KLineChart.get_webview()):将图表的网页视图添加到布局中。
2.3 设置历史数据方法
def set_history(self, history: list[BarData]):
data: list = []
for bar in history:
data.append([bar.datetime.strftime("%Y-%m-%d %H:%M:%S"), bar.open_price, bar.high_price, bar.low_price,
bar.close_price, bar.volume])
df = pd.DataFrame(data=data, columns=["time", "open", "high", "low", "close", "volume"])
self.KLineChart.set(df)
self.inited = True
- • set_history方法接受一个BarData对象列表作为参数,用于设置图表的历史数据。
- • 首先,将BarData对象列表转换为一个二维列表 data,每个元素包含时间、开盘价、最高价、最低价、收盘价和成交量。
- • 然后,使用pandas 的 DataFrame 类将 data 转换为DataFrame,并设置列名。
- • 最后,调用self.KLineChart.set(df)方法将数据框设置到图表中,并将self.inited标记为True,表示图表已经初始化。
2.4 更新数据方法
def update_data(self, bar):
if self.inited and bar is not None:
bar_data = pd.Series(
data=[bar.datetime.strftime("%Y-%m-%d %H:%M:%S"), bar.open_price, bar.high_price, bar.low_price,
bar.close_price,
bar.volume],
index=["time", "open", "high", "low", "close", "volume"])
self.KLineChart.update(bar_data)
- • update_data方法接受一个BarData对象作为参数,用于更新图表的数据。
- • 首先,检查图表是否已经初始化并且传入的BarData对象不为None。
- • 然后,将BarData对象转换为pandas的Series对象。
- • 最后,调用self.KLineChart.update(bar_data)方法更新图表的数据。]]
2.5 按钮点击处理函数
def on_button_press(chart):
new_button_value = 'On' if chart.topbar['my_button'].value == 'Off' else 'Off'
chart.topbar['my_button'].set(new_button_value)
print(f'Turned something {new_button_value.lower()}.')
- • on_button_press函数用于处理图表顶部栏按钮的点击事件。当按钮状态为 “Off” 时,点击后将其状态改为 “On”,反之亦然,并打印相应的信息。
3. 创建K线显示页面
根据架构的规则,我们先在gui下我view目录下新建一个trade_interface.py文件,我们会在这个文件里面显示K线,并进行交易操作。
3.1 导入 KlineCharts 类
from gui.components.kline_charts import KlineCharts
3.2 创建 KlineCharts
实例
在 init_ui 方法中创建 KlineCharts 类的实例,并将其添加到布局中:
self.verticalLayout_klines = QHBoxLayout()
self.verticalLayout_klines.setObjectName(u"verticalLayout_klines")
self.kline_widge = KlineCharts() # 创建 KlineCharts 实例
self.verticalLayout_klines.addWidget(self.kline_widge) # 将实例添加到布局中
self.horizontalLayout.addLayout(self.verticalLayout_klines)
3.3 设置历史数据
KlineCharts类提供了set_history方法,用于设置 K 线图表的历史数据。在 process_history_event方法中都调用了该方法:
# 在 process_history_event 方法中设置历史数据
def process_history_event(self, event: Event) -> None:
history: List[BarData] = event.data
if not history:
return
bar_first: BarData = history[0]
self.kline_widge.set_history(history) # 调用 set_history 方法设置历史数据
3.4 更新数据
KlineCharts类可能提供了update_data方法,用于实时更新 K 线图表的数据。在update_bar、process_tick_event、process_spread_event 和on_bar方法中都调用了该方法:
# 在 update_bar 方法中更新数据
def update_bar(self):
bar = self.new_data.pop(0)
self.kline_widge.update_data(bar) # 调用 update_data 方法更新数据
# 在 process_tick_event 方法中更新数据
def process_tick_event(self, event: Event) -> None:
if bar is not None:
bar.datetime = bar.datetime.replace(second=0, microsecond=0)
if bar.symbol == self.current_symbol:
self.kline_widge.update_data(bar) # 调用 update_data 方法更新数据
# 在 process_spread_event 方法中更新数据
def process_spread_event(self, event: Event) -> None:
if bar is not None:
bar.datetime = bar.datetime.replace(second=0, microsecond=0)
if bar.symbol == self.current_symbol:
self.kline_widge.update_data(bar) # 调用 update_data 方法更新数据
# 在 on_bar 方法中更新数据
def on_bar(self, bar: BarData) -> None:
if bar.symbol == self.current_symbol:
self.kline_widge.update_data(bar) # 调用 update_data 方法更新数据
4. 显示页面
CryptoTrader的页面显示都是在mainwindow.py文件设置,下面详细介绍TradeInterface的使用方法。
4.1 导入 TradeInterface
类
from gui.view.trade_interface import TradeInterface
4.2 创建 TradeInterface
实例
在MainWindow类的init_widgets方法里,创建TradeInterface类的实例。创建时需要传入MainEngine和EventEngine两个参数:
def init_widgets(self) -> None:
self.trade_widget = TradeInterface(self.main_engine, self.event_engine)
self.trade_widget.setObjectName("trade")
- • self.main_engine:MainEngine类的实例,它是交易平台的核心引擎,负责管理各种交易功能和数据。
- • self.event_engine:EventEngine类的实例,用于事件的发布和处理,实现不同模块之间的通信。
4.3 将 radeInterface实例添加到导航界面
在MainWindow类的init_navigation方法中,把TradeInterface实例添加到导航界面,这样用户就能在主窗口中访问该界面:
def init_navigation(self) -> None:
self.addSubInterface(interface=self.trade_widget, icon=Icon.KLINE, text="交易")
- • interface:传入TradeInterface实例。
- • icon:指定该界面在导航栏显示的图标。
- • text:指定该界面在导航栏显示的文本。
4.4 与其他组件交互
TradeInterface类内部可能定义了信号和槽,用于与其他组件进行交互。从用户之前编辑的trade_interface.py文件可知,TradeInterface 类定义了多个信号,用于处理不同的事件:
class TradeInterface(QtWidgets.QWidget):
signal_tick: QtCore.pyqtSignal = QtCore.pyqtSignal(Event)
signal_spread: QtCore.pyqtSignal = QtCore.pyqtSignal(Event)
signal_history: QtCore.pyqtSignal = QtCore.pyqtSignal(Event)
signal_symbol_change: QtCore.pyqtSignal = QtCore.pyqtSignal(Event)
def __init__(self, main_engine: MainEngine, event_engine: EventEngine) -> None:
self.register_event()
def register_event(self) -> None:
self.signal_tick.connect(self.process_tick_event)
self.signal_spread.connect(self.process_spread_event)
self.signal_history.connect(self.process_history_event)
self.signal_symbol_change.connect(self.process_symbol_change_event)
这些信号会连接到相应的事件处理方法,当事件触发时,会执行对应的处理逻辑。
4.5 总结
使用TradeInterface的基本步骤如下:
- • 导入TradeInterface类。
- • 创建TradeInterface实例,并传入MainEngine和EventEngine参数。
- • 将TradeInterface实例添加到导航界面,方便用户访问。
- • 利用TradeInterface类定义的信号和槽,实现与其他组件的交互。
5. 效果
6. 联系方式
- • Github: github.com/KandyYe
感谢你看到这里,如果觉得文章对你有所收获,请在文末为我点个【赞】+【推荐】,或者【分享】给身边更多有需要的人看,你的点赞就是对我莫大的支持与动力!