import pandas as pd from pyecharts.charts import Kline, Line, Bar, Grid from pyecharts import options as opts from pyecharts.commons.utils import JsCode class StockKlineChart: def __init__(self, df: pd.DataFrame, stock_code: str): """ 初始化 K 线图表对象 :param df: 股票数据 DataFrame(包含“日期”,“开盘”,“收盘”,“最低”,“最高”,“成交量”) :param stock_code: 股票代码 """ self.df = df.sort_values("日期") # 按日期排序,确保数据按时间顺序排列 self.stock_code = stock_code # 股票代码 self.color_up = "#ef232a" # 阳线(上涨)颜色 self.color_down = "#14b143" # 阴线(下跌)颜色 self.ma_periods = [5, 10, 20] # 移动平均线周期 self.ma_colors = {5: "#FF0000", 10: "#0000FF", 20: "#00FF00"} # 均线颜色 def _prepare_data(self): """ 处理数据:提取 K 线数据、计算移动均线、设置成交量颜色 """ self.dates = self.df['日期'].tolist() # 提取日期列表 self.kline_data = self.df[["开盘", "收盘", "最低", "最高"]].values.tolist() # 提取 K 线数据 # 计算移动平均线 for period in self.ma_periods: self.df[f'MA{period}'] = ( self.df['收盘'] .rolling(window=period) .mean() .bfill() # 处理 NaN 值(前向填充) .round(2) # 保留两位小数 ) # 计算成交量颜色标记(1: 上涨, -1: 下跌) self.df['color'] = self.df.apply( lambda x: 1 if x['收盘'] >= x['开盘'] else -1, axis=1 ) self.df['index_vol'] = range(len(self.df)) # 给成交量数据添加索引 def create_chart(self): """ 生成 K 线图表 """ self._prepare_data() # 处理数据 # ================== K 线图配置 ================== kline = ( Kline() .add_xaxis(self.dates) # 设置 X 轴日期 .add_yaxis( series_name="K线", # K 线名称 y_axis=self.kline_data, # K 线数据(开盘、收盘、最低、最高) itemstyle_opts=opts.ItemStyleOpts( color=self.color_up, # 阳线颜色 color0=self.color_down # 阴线颜色 ) ) .set_global_opts( title_opts=opts.TitleOpts( title="股票K线走势图", # 图表标题 subtitle=f"股票代码:{self.stock_code}", # 副标题 pos_left="left" # 标题位置 ), legend_opts=opts.LegendOpts( is_show=True, # 是否显示图例 pos_top=10, # 图例位置(顶部) pos_left="center" # 居中对齐 ), xaxis_opts=opts.AxisOpts( type_="category", # X 轴类型(类别) axislabel_opts=opts.LabelOpts(rotate=0), # X 轴标签角度 splitline_opts=opts.SplitLineOpts(is_show=True) # 是否显示网格线 ), yaxis_opts=opts.AxisOpts( is_scale=True, # Y 轴是否自适应缩放 splitarea_opts=opts.SplitAreaOpts( is_show=True, # 是否显示网格背景 areastyle_opts=opts.AreaStyleOpts(opacity=1) # 设置透明度 ) ), tooltip_opts=opts.TooltipOpts( trigger="axis", # 触发方式:鼠标悬浮时显示 axis_pointer_type="cross", # 坐标轴指示器类型(十字指示) ), datazoom_opts=[ opts.DataZoomOpts( is_show=False, # 是否显示数据缩放控件 type_="inside", # 缩放类型:内部滑动 xaxis_index=[0, 1], # 作用于 X 轴 range_start=80, # 初始显示范围 range_end=100 ), &nbs |