在网上找的资料,但没有数据,于是根据代码自己造了一些,发现跑起来太卡了,放弃
# coding=utf-8 # inter_candle.py import pandas as pd import numpy as np import matplotlib.pyplot as plt import mplfinance as mpf data = pd.read_csv('test_data2.csv', index_col=0) data.index = pd.to_datetime(data.index) my_color = mpf.make_marketcolors(up='r', down='g', edge='inherit', wick='inherit', volume='inherit') my_style = mpf.make_mpf_style(marketcolors=my_color, figcolor='(0.82, 0.83, 0.85)', gridcolor='(0.82, 0.83, 0.85)') title_font = {'fontname': 'SimHei', 'size': '16', 'color': 'black', 'weight': 'bold', 'va': 'bottom', 'ha': 'center'} large_red_font = {'fontname': 'SimHei', 'size': '24', 'color': 'red', 'weight': 'bold', 'va': 'bottom'} large_green_font = {'fontname': 'SimHei', 'size': '24', 'color': 'green', 'weight': 'bold', 'va': 'bottom'} small_red_font = {'fontname': 'SimHei', 'size': '12', 'color': 'red', 'weight': 'bold', 'va': 'bottom'} small_green_font = {'fontname': 'SimHei', 'size': '12', 'color': 'green', 'weight': 'bold', 'va': 'bottom'} normal_label_font = {'fontname': 'SimHei', 'size': '12', 'color': 'black', 'weight': 'normal', 'va': 'bottom', 'ha': 'right'} normal_font = {'fontname': 'SimHei', 'size': '12', 'color': 'black', 'weight': 'normal', 'va': 'bottom', 'ha': 'left'} class InterCandle: def __init__(self, data, my_style): self.pressed = False self.xpress = None # 初始化交互式K线图对象,历史数据作为唯一的参数用于初始化对象 self.data = data self.style = my_style # 设置初始化的K线图显示区间起点为0,即显示第0到第99个交易日的数据(前100个数据) self.idx_start = 0 self.idx_range = 100 # 设置ax1图表中显示的均线类型 self.avg_type = 'ma' self.indicator = 'macd' # 初始化figure对象,在figure上建立三个Axes对象并分别设置好它们的位置和基本属性 self.fig = mpf.figure(style=my_style, figsize=(12, 8), facecolor=(0.82, 0.83, 0.85)) fig = self.fig self.ax1 = fig.add_axes([0.08, 0.25, 0.88, 0.60]) self.ax2 = fig.add_axes([0.08, 0.15, 0.88, 0.10], sharex=self.ax1) self.ax2.set_ylabel('volume') self.ax3 = fig.add_axes([0.08, 0.05, 0.88, 0.10], sharex=self.ax1) self.ax3.set_ylabel('macd') # 初始化figure对象,在figure上预先放置文本并设置格式,文本内容根据需要显示的数据实时更新 self.t1 = fig.text(0.50, 0.94, '513100.SH - 纳斯达克指数ETF基金', **title_font) self.t2 = fig.text(0.12, 0.90, '开/收: ', **normal_label_font) self.t3 = fig.text(0.14, 0.89, f'', **large_red_font) self.t4 = fig.text(0.14, 0.86, f'', **small_red_font) self.t5 = fig.text(0.22, 0.86, f'', **small_red_font) self.t6 = fig.text(0.12, 0.86, f'', **normal_label_font) self.t7 = fig.text(0.40, 0.90, '高: ', **normal_label_font) self.t8 = fig.text(0.40, 0.90, f'', **small_red_font) self.t9 = fig.text(0.40, 0.86, '低: ', **normal_label_font) self.t10 = fig.text(0.40, 0.86, f'', **small_green_font) self.t11 = fig.text(0.55, 0.90, '量(万手): ', **normal_label_font) self.t12 = fig.text(0.55, 0.90, f'', **normal_font) self.t13 = fig.text(0.55, 0.86, '额(亿元): ', **normal_label_font) self.t14 = fig.text(0.55, 0.86, f'', **normal_font) self.t15 = fig.text(0.70, 0.90, '涨停: ', **normal_label_font) self.t16 = fig.text(0.70, 0.90, f'', **small_red_font) self.t17 = fig.text(0.70, 0.86, '跌停: ', **normal_label_font) self.t18 = fig.text(0.70, 0.86, f'', **small_green_font) self.t19 = fig.text(0.85, 0.90, '均价: ', **normal_label_font) self.t20 = fig.text(0.85, 0.90, f'', **normal_font) self.t21 = fig.text(0.85, 0.86, '昨收: ', **normal_label_font) self.t22 = fig.text(0.85, 0.86, f'', **normal_font) #fig.canvas.mpl_connect('button_press_event', self.on_press) #fig.canvas.mpl_connect('button_release_event', self.on_release) #fig.canvas.mpl_connect('motion_notify_event', self.on_motion) #fig.canvas.mpl_connect('scroll_event', self.on_scroll) #fig.canvas.mpl_connect('key_press_event', self.on_key_press) def refresh_plot(self, idx_start, idx_range): """ 根据最新的参数,重新绘制整个图表 """ all_data = self.data plot_data = all_data.iloc[idx_start: idx_start + idx_range] ap = [] # 添加K线图重叠均线,根据均线类型添加移动均线或布林带线 if self.avg_type == 'ma': ap.append(mpf.make_addplot(plot_data[['MA5', 'MA10', 'MA20', 'MA60']], ax=self.ax1)) elif self.avg_type == 'bb': ap.append(mpf.make_addplot(plot_data[['bb-u', 'bb-m', 'bb-l']], ax=self.ax1)) # 添加指标,根据指标类型添加MACD或RSI或DEMA if self.indicator == 'macd': ap.append(mpf.make_addplot(plot_data[['macd-m', 'macd-s']], ylabel='macd', ax=self.ax3)) bar_r = np.where(plot_data['macd-h'] > 0, plot_data['macd-h'], 0) bar_g = np.where(plot_data['macd-h'] <= 0, plot_data['macd-h'], 0) ap.append(mpf.make_addplot(bar_r, type='bar', color='red', ax=self.ax3)) ap.append(mpf.make_addplot(bar_g, type='bar', color='green', ax=self.ax3)) elif self.indicator == 'rsi': ap.append(mpf.make_addplot([75] * len(plot_data), color=(0.75, 0.6, 0.6), ax=self.ax3)) ap.append(mpf.make_addplot([30] * len(plot_data), color=(0.6, 0.75, 0.6), ax=self.ax3)) ap.append(mpf.make_addplot(plot_data['rsi'], ylabel='rsi', ax=self.ax3)) else: # indicator == 'dema' ap.append(mpf.make_addplot(plot_data['dema'], ylabel='dema', ax=self.ax3)) # 绘制图表 mpf.plot(plot_data, ax=self.ax1, volume=self.ax2, addplot=ap, type='candle', style=self.style, datetime_format='%Y-%m', xrotation=0) self.fig.show() def refresh_texts(self, display_data): return """ 更新K线图上的价格文本 """ # display_data是一个交易日内的所有数据,将这些数据分别填入figure对象上的文本中 self.t3.set_text(f'{np.round(display_data["open"], 3)} / {np.round(display_data["close"], 3)}') self.t4.set_text(f'{np.round(display_data["change"], 3)}') self.t5.set_text(f'[{np.round(display_data["pct_change"], 3)}%]') self.t6.set_text(f'{display_data.name.date()}') self.t8.set_text(f'{np.round(display_data["high"], 3)}') self.t10.set_text(f'{np.round(display_data["low"], 3)}') self.t12.set_text(f'{np.round(display_data["volume"] / 10000, 3)}') self.t14.set_text(f'{display_data["value"]}') self.t16.set_text(f'{np.round(display_data["upper_lim"], 3)}') self.t18.set_text(f'{np.round(display_data["lower_lim"], 3)}') self.t20.set_text(f'{np.round(display_data["average"], 3)}') self.t22.set_text(f'{np.round(display_data["last_close"], 3)}') # 根据本交易日的价格变动值确定开盘价、收盘价的显示颜色 if display_data['change'] > 0: # 如果今日变动额大于0,即今天价格高于昨天,今天价格显示为红色 close_number_color = 'red' elif display_data['change'] < 0: # 如果今日变动额小于0,即今天价格低于昨天,今天价格显示为绿色 close_number_color = 'green' else: close_number_color = 'black' self.t3.set_color(close_number_color) self.t4.set_color(close_number_color) self.t5.set_color(close_number_color) def on_press(self, event): if not event.inaxes == self.ax1: return if event.button != 1: return self.pressed = True self.xpress = event.xdata # 切换当前ma类型, 在ma、bb、none之间循环 if event.inaxes == self.ax1 and event.dblclick == 1: if self.avg_type == 'ma': self.avg_type = 'bb' elif self.avg_type == 'bb': self.avg_type = 'none' else: self.avg_type = 'ma' # 切换当前indicator类型,在macd/dma/rsi/kdj之间循环 if event.inaxes == self.ax3 and event.dblclick == 1: if self.indicator == 'macd': self.indicator = 'dma' elif self.indicator == 'dma': self.indicator = 'rsi' elif self.indicator == 'rsi': self.indicator = 'kdj' else: self.indicator = 'macd' self.ax1.clear() self.ax2.clear() self.ax3.clear() self.refresh_plot(self.idx_start, self.idx_range) def on_release(self, event): self.pressed = False dx = int(event.xdata - self.xpress) self.idx_start -= dx if self.idx_start <= 0: self.idx_start = 0 if self.idx_start >= len(self.data) - 100: self.idx_start = len(self.data) - 100 def on_motion(self, event): if not self.pressed: return if not event.inaxes == self.ax1: return dx = int(event.xdata - self.xpress) new_start = self.idx_start - dx # 设定平移的左右界限,如果平移后超出界限,则不再平移 if new_start <= 0: new_start = 0 if new_start >= len(self.data) - 100: new_start = len(self.data) - 100 self.ax1.clear() self.ax2.clear() self.ax3.clear() self.refresh_texts(self.data.iloc[new_start]) self.refresh_plot(new_start, self.idx_range) def on_scroll(self, event): # 仅当鼠标滚轮在axes1范围内滚动时起作用 if event.inaxes != self.ax1: return if event.button == 'down': # 缩小20%显示范围 scale_factor = 0.8 if event.button == 'up': # 放大20%显示范围 scale_factor = 1.2 # 设置K线的显示范围大小 self.idx_range = int(self.idx_range * scale_factor) # 限定可以显示的K线图的范围,最少不能少于30个交易日,最大不能超过当前位置与 # K线数据总长度的差 data_length = len(self.data) if self.idx_range >= data_length - self.idx_start: self.idx_range = data_length - self.idx_start if self.idx_range <= 30: self.idx_range = 30 # 更新图表(注意因为多了一个参数idx_range,refresh_plot函数也有所改动) self.ax1.clear() self.ax2.clear() self.ax3.clear() self.refresh_texts(self.data.iloc[self.idx_start]) self.refresh_plot(self.idx_start, self.idx_range) # 键盘按下处理 def on_key_press(self, event): data_length = len(self.data) if event.key == 'a': # avg_type, 在ma,bb,none之间循环 if self.avg_type == 'ma': self.avg_type = 'bb' elif self.avg_type == 'bb': self.avg_type = 'none' elif self.avg_type == 'none': self.avg_type = 'ma' elif event.key == 'up': # 向上,看仔细1倍 if self.idx_range > 60: self.idx_range = int(self.idx_range / 2) elif event.key == 'down': # 向下,看多1倍标的 if self.idx_range <= 480: self.idx_range = self.idx_range * 2 elif event.key == 'left': if self.idx_start > self.idx_range: self.idx_start = self.idx_start - self.idx_range elif event.key == 'right': if self.idx_start < data_length - self.idx_range: self.idx_start = self.idx_start + self.idx_range self.ax1.clear() self.ax2.clear() self.ax3.clear() self.refresh_texts(self.data.iloc[self.idx_start]) self.refresh_plot(self.idx_start, self.idx_range) if __name__ == '__main__': candle = InterCandle(data, my_style) candle.idx_start = 1 candle.idx_range = 200 candle.refresh_texts(data.iloc[249]) candle.refresh_plot(1, 200) input()
数据,请存为test_data2.csv:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ,ts_code,trade_date,open,high,low,close,pre_close,change,pct_chg,volume,amount,MA5,MA10,MA20,MA60,macd-m,macd-s,macd-h 0 , 000001 .SZ, 20201231 , 19.21 , 19.58 , 19.02 , 19.34 , 19.2 , 0.14 , 0.7292 , 924503.43 , 1781736.285 , 19.275 , 19.275 , 19.275 , 19.275 , 0.1 , 0.12 , 0.1 1 , 000001 .SZ, 20201230 , 19 , 19.2 , 18.72 , 19.2 , 19.17 , 0.03 , 0.1565 , 978497.78 , 1854082.812 , 19.1 , 19.1 , 19.1 , 19.1 , 0.1 , 0.12 , 0.1 2 , 000001 .SZ, 20201229 , 18.87 , 19.3 , 18.7 , 19.17 , 18.85 , 0.32 , 1.6976 , 963092.23 , 1837947.238 , 19.02 , 19.02 , 19.02 , 19.02 , 0.1 , 0.12 , 0.1 3 , 000001 .SZ, 20201228 , 18.02 , 18.86 , 17.96 , 18.85 , 18.04 , 0.81 , 4.49 , 1270337.06 , 2352947.321 , 18.435 , 18.435 , 18.435 , 18.435 , 0.1 , 0.12 , 0.1 4 , 000001 .SZ, 20201225 , 18.26 , 18.26 , 17.8 , 18.04 , 18.26 ,- 0.22 ,- 1.2048 , 577077.33 , 1038128.197 , 18.15 , 18.15 , 18.15 , 18.15 , 0.1 , 0.12 , 0.1 5 , 000001 .SZ, 20201224 , 18.15 , 18.49 , 18.05 , 18.26 , 18 , 0.26 , 1.4444 , 632950.12 , 1155767.283 , 18.205 , 18.205 , 18.205 , 18.205 , 0.1 , 0.12 , 0.1 6 , 000001 .SZ, 20201223 , 17.96 , 18.07 , 17.79 , 18 , 17.9 , 0.1 , 0.5587 , 750082.73 , 1345650.736 , 17.98 , 17.98 , 17.98 , 17.98 , 0.1 , 0.12 , 0.1 7 , 000001 .SZ, 20201222 , 18.36 , 18.65 , 17.88 , 17.9 , 18.28 ,- 0.38 ,- 2.0788 , 1028737.51 , 1873638.734 , 18.13 , 18.13 , 18.13 , 18.13 , 0.1 , 0.12 , 0.1 8 , 000001 .SZ, 20201221 , 18.3 , 18.64 , 18.03 , 18.28 , 18.36 ,- 0.08 ,- 0.4357 , 906878.11 , 1662649.81 , 18.29 , 18.29 , 18.29 , 18.29 , 0.1 , 0.12 , 0.1 9 , 000001 .SZ, 20201218 , 19 , 19.1 , 18.23 , 18.36 , 18.95 ,- 0.59 ,- 3.1135 , 1058756.36 , 1959764.074 , 18.68 , 18.68 , 18.68 , 18.68 , 0.1 , 0.12 , 0.1 10 , 000001 .SZ, 20201217 , 18.91 , 19.07 , 18.6 , 18.95 , 19.01 ,- 0.06 ,- 0.3156 , 686140.69 , 1294658.299 , 18.93 , 18.93 , 18.93 , 18.93 , 0.1 , 0.12 , 0.1 11 , 000001 .SZ, 20201216 , 18.8 , 19.1 , 18.58 , 19.01 , 18.74 , 0.27 , 1.4408 , 689070.42 , 1302133.815 , 18.905 , 18.905 , 18.905 , 18.905 , 0.1 , 0.12 , 0.1 12 , 000001 .SZ, 20201215 , 18.8 , 18.85 , 18.15 , 18.74 , 18.88 ,- 0.14 ,- 0.7415 , 788857.94 , 1458268.62 , 18.77 , 18.77 , 18.77 , 18.77 , 0.1 , 0.12 , 0.1 13 , 000001 .SZ, 20201214 , 18.6 , 19.06 , 18.5 , 18.88 , 18.52 , 0.36 , 1.9438 , 835991.74 , 1575396.008 , 18.74 , 18.74 , 18.74 , 18.74 , 0.1 , 0.12 , 0.1 |
吐槽一下博客园,到现在传个文件,还不能在这个界面完成,唉。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
2010-09-19 用EXTJS做一个右下角的泡泡窗口(一)