From 0cd3e430ac4415e5acda8162658cd66edb8a42e7 Mon Sep 17 00:00:00 2001 From: wyn Date: Sat, 21 Sep 2024 11:56:30 +0800 Subject: [PATCH 1/4] =?UTF-8?q?Echarts=E5=A2=9E=E5=8A=A0=E6=9B=B4=E6=96=B0?= =?UTF-8?q?options=E7=9A=84=E6=96=B9=E6=B3=95update=5Foptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chartspy/echarts.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/chartspy/echarts.py b/chartspy/echarts.py index 552c4c9..7249735 100644 --- a/chartspy/echarts.py +++ b/chartspy/echarts.py @@ -165,6 +165,18 @@ def overlap_series(self, other_chart_options: list = [], add_yaxis=False, add_ya this_options["visualMap"].extend(chart_option["visualMap"]) return Echarts(options=this_options, extra_js=self.extra_js, width=self.width, height=self.height) + def update_options(self, options: dict) -> "Echarts": + def _update_dict(a: dict, b: dict) -> dict: + for k, v in b.items(): + if k in a.keys() and isinstance(a[k], dict) and isinstance(v, dict): + a[k] = _update_dict(a[k], v) + else: + a[k] = v + return a + + self.options = _update_dict(self.options, options) + return self + def print_options(self, drop_data=False): """ 格式化打印options 方便二次修改 From d5ebfb3d5810018bd9ecba28384bce2d1ac1fd50 Mon Sep 17 00:00:00 2001 From: wyn Date: Sat, 21 Sep 2024 12:25:23 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E4=BC=98=E5=8C=96docstring=E5=B1=95?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chartspy/charts.py | 54 ++++++++++++++++++++++++++++++------- chartspy/echarts.py | 20 +++++++++++--- chartspy/express/echarts.py | 33 ++++++++++++++--------- chartspy/klinecharts.py | 10 +++++-- 4 files changed, 90 insertions(+), 27 deletions(-) diff --git a/chartspy/charts.py b/chartspy/charts.py index a05cc40..dedb992 100644 --- a/chartspy/charts.py +++ b/chartspy/charts.py @@ -248,7 +248,7 @@ def json_type_convert(o: object): return json_encoder.default(o) -ECHARTS_JS_URL = "https://cdn.staticfile.org/echarts/5.3.2/echarts.min.js" +ECHARTS_JS_URL = "https://cdn.staticfile.org/echarts/5.4.3/echarts.min.js" ECHARTS_GL_JS_URL = "https://cdn.staticfile.org/echarts-gl/2.0.8/echarts-gl.min.js" @@ -370,16 +370,19 @@ def timeline(echarts_dict: dict = {}, visual_map_options=None): return Echarts(options=options) - def overlap_series(self, other_chart_options: list = [], add_yaxis=False, add_yaxis_grid_index=0): + def overlap_series(self, other_chart_options: list = [], add_yaxis=False, add_yaxis_grid_index=0) -> "Echarts": """ 叠加其他配置中的Series数据到现有配置,现有配置有多个坐标轴的,建议Series声明对应的axisIndex - :param other_chart_options:要叠加的Echarts对象列表,或者options列表 + + :param other_chart_options: 要叠加的Echarts对象列表,或者options列表 :param add_yaxis: 是否增加一个Y轴 :param add_yaxis_grid_index: 0 :return: """ this_options = copy.deepcopy(self.options) if add_yaxis: + if type(this_options['yAxis']).__name__=='dict': + this_options['yAxis'] = [this_options['yAxis']] this_options['yAxis'].append({'scale': True, 'type': 'value', 'gridIndex': add_yaxis_grid_index}) if this_options["legend"]["data"] is None: this_options["legend"]["data"] = [] @@ -406,9 +409,28 @@ def overlap_series(self, other_chart_options: list = [], add_yaxis=False, add_ya this_options["visualMap"].extend(chart_option["visualMap"]) return Echarts(options=this_options, extra_js=self.extra_js, width=self.width, height=self.height) + def update_options(self, options: dict) -> "Echarts": + """ + 更新options + + :param options: 要更新的options,相同key进行递归覆盖 + :return: 更新options后的Echarts + """ + def _update_dict(a: dict, b: dict) -> dict: + for k, v in b.items(): + if k in a.keys() and isinstance(a[k], dict) and isinstance(v, dict): + a[k] = _update_dict(a[k], v) + else: + a[k] = v + return a + + self.options = _update_dict(self.options, options) + return self + def print_options(self, drop_data=False): """ 格式化打印options 方便二次修改 + :param drop_data: 是否过滤掉data,减小打印长度,方便粘贴 :return: """ @@ -421,7 +443,8 @@ def print_options(self, drop_data=False): def dump_options(self): """ - 导出 js option字符串表示 + 导出 js option字符串表示 + :return: """ self.js_options = Tools.convert_dict_to_js(self.options) @@ -430,6 +453,7 @@ def dump_options(self): def render_notebook(self) -> Html: """ 在jupyter notebook 环境输出 + :return: """ self.js_options = Tools.convert_dict_to_js(self.options) @@ -438,8 +462,8 @@ def render_notebook(self) -> Html: html = f"""
@@ -487,6 +511,7 @@ def render_notebook(self) -> Html: def render_jupyterlab(self) -> Html: """ 在jupyterlab 环境输出 + :return: """ self.js_options = Tools.convert_dict_to_js(self.options) @@ -549,6 +574,7 @@ def render_jupyterlab(self) -> Html: def render_html(self) -> str: """ 渲染html字符串,可以用于 streamlit + :return: """ self.js_options = Tools.convert_dict_to_js(self.options) @@ -588,8 +614,8 @@ def render_html(self) -> str: @@ -609,6 +635,7 @@ def render_html(self) -> str: def render_html_fragment(self): """ 渲染html 片段,方便一个网页输出多个图表 + :return: """ self.js_options = Tools.convert_dict_to_js(self.options) @@ -656,6 +683,7 @@ def render_html_fragment(self): def _repr_html_(self): """ jupyter 环境,直接输出 + :return: """ self.js_options = Tools.convert_dict_to_js(self.options) @@ -1279,11 +1307,12 @@ def __init__(self, df: pd.DataFrame, mas=[5, 10, 30, 60, 120, 250], main_indicat height: str = "500px"): """ k线图 + :param df: [open,high,low,close,volume,turnover,timestamp] :param mas: [5, 10, 30, 60, 120, 250] :param main_indicators: 主图显示的指标列表 MA,EMA,SMA,BOLL,SAR,BBI - :param bottom_indicators:副图显示指标列表 VOL,MACD,KDJ,RSI,BIAS,BBAR,CCI,DMI,CR,PSY,DMA,TRIX,OBV,VR,WR,MTM,EMV,SAR,SMA,ROC,PVT,BBI,AO - :param df_segments:[start_time,start_price,end_time,end_price] + :param bottom_indicators: 副图显示指标列表 VOL,MACD,KDJ,RSI,BIAS,BBAR,CCI,DMI,CR,PSY,DMA,TRIX,OBV,VR,WR,MTM,EMV,SAR,SMA,ROC,PVT,BBI,AO + :param df_segments: [start_time,start_price,end_time,end_price] :param extra_js: :param width: :param height: @@ -1314,6 +1343,7 @@ def __init__(self, df: pd.DataFrame, mas=[5, 10, 30, 60, 120, 250], main_indicat def render_notebook(self) -> Html: """ 在jupyter notebook 环境输出 + :return: """ plot = self @@ -1347,6 +1377,7 @@ def render_notebook(self) -> Html: def render_jupyterlab(self) -> Html: """ 在jupyterlab 环境输出 + :return: """ plot = self @@ -1378,6 +1409,7 @@ def render_jupyterlab(self) -> Html: def render_html(self) -> str: """ 渲染html字符串,可以用于 streamlit + :return: """ plot = self @@ -1410,6 +1442,7 @@ def render_html(self) -> str: def render_html_fragment(self): """ 渲染html 片段,方便一个网页输出多个图表 + :return: """ plot = self @@ -1434,6 +1467,7 @@ def render_html_fragment(self): def _repr_html_(self): """ jupyter 环境,直接输出 + :return: """ plot = self diff --git a/chartspy/echarts.py b/chartspy/echarts.py index 7249735..45149e7 100644 --- a/chartspy/echarts.py +++ b/chartspy/echarts.py @@ -127,10 +127,11 @@ def timeline(echarts_dict: dict = {}, visual_map_options=None): return Echarts(options=options) - def overlap_series(self, other_chart_options: list = [], add_yaxis=False, add_yaxis_grid_index=0): + def overlap_series(self, other_chart_options: list = [], add_yaxis=False, add_yaxis_grid_index=0) -> "Echarts": """ 叠加其他配置中的Series数据到现有配置,现有配置有多个坐标轴的,建议Series声明对应的axisIndex - :param other_chart_options:要叠加的Echarts对象列表,或者options列表 + + :param other_chart_options: 要叠加的Echarts对象列表,或者options列表 :param add_yaxis: 是否增加一个Y轴 :param add_yaxis_grid_index: 0 :return: @@ -166,6 +167,12 @@ def overlap_series(self, other_chart_options: list = [], add_yaxis=False, add_ya return Echarts(options=this_options, extra_js=self.extra_js, width=self.width, height=self.height) def update_options(self, options: dict) -> "Echarts": + """ + 更新options + + :param options: 要更新的options,相同key进行递归覆盖 + :return: 更新options后的Echarts + """ def _update_dict(a: dict, b: dict) -> dict: for k, v in b.items(): if k in a.keys() and isinstance(a[k], dict) and isinstance(v, dict): @@ -180,6 +187,7 @@ def _update_dict(a: dict, b: dict) -> dict: def print_options(self, drop_data=False): """ 格式化打印options 方便二次修改 + :param drop_data: 是否过滤掉data,减小打印长度,方便粘贴 :return: """ @@ -192,7 +200,8 @@ def print_options(self, drop_data=False): def dump_options(self): """ - 导出 js option字符串表示 + 导出 js option字符串表示 + :return: """ self.js_options = Tools.convert_dict_to_js(self.options) @@ -201,6 +210,7 @@ def dump_options(self): def render_notebook(self) -> Html: """ 在jupyter notebook 环境输出 + :return: """ self.js_options = Tools.convert_dict_to_js(self.options) @@ -258,6 +268,7 @@ def render_notebook(self) -> Html: def render_jupyterlab(self) -> Html: """ 在jupyterlab 环境输出 + :return: """ self.js_options = Tools.convert_dict_to_js(self.options) @@ -320,6 +331,7 @@ def render_jupyterlab(self) -> Html: def render_html(self) -> str: """ 渲染html字符串,可以用于 streamlit + :return: """ self.js_options = Tools.convert_dict_to_js(self.options) @@ -380,6 +392,7 @@ def render_html(self) -> str: def render_html_fragment(self): """ 渲染html 片段,方便一个网页输出多个图表 + :return: """ self.js_options = Tools.convert_dict_to_js(self.options) @@ -427,6 +440,7 @@ def render_html_fragment(self): def _repr_html_(self): """ jupyter 环境,直接输出 + :return: """ self.js_options = Tools.convert_dict_to_js(self.options) diff --git a/chartspy/express/echarts.py b/chartspy/express/echarts.py index 71a4124..bca80c9 100644 --- a/chartspy/express/echarts.py +++ b/chartspy/express/echarts.py @@ -146,7 +146,6 @@ def scatter_echarts(data_frame: pd.DataFrame, x_field: str = None, y_field: str """ scatter chart - :param data_frame: 必填 DataFrame :param x_field: 必填 x轴映射的列 :param y_field: 必填 y轴映射的列 @@ -326,6 +325,7 @@ def line_echarts(data_frame: pd.DataFrame, x_field: str = None, y_field: str = N width: str = "100%", height: str = "500px",**kwargs) -> Echarts: """ 绘制线图 + :param data_frame: 必填 DataFrame :param x_field: 必填 x轴映射的列 :param y_field: 必填 y轴映射的列 @@ -383,12 +383,12 @@ def bar_echarts(data_frame: pd.DataFrame, x_field: str = None, y_field: str = No :param x_field: 必填 x轴映射的列 :param y_field: 必填 y轴映射的列 :param series_field: 选填 series 对应列 - :param stack:堆叠分组 + :param stack: 堆叠分组 :param tooltip_trigger: axis item :param title: 可选标题 :param width: 输出div的宽度 支持像素和百分比 比如800px/100% :param height: 输出div的高度 支持像素和百分比 比如800px/100% - :return:Echarts + :return: Echarts """ options = copy.deepcopy(ECHARTS_BASE_GRID_OPTIONS) df = data_frame.copy() @@ -482,6 +482,7 @@ def pie_echarts(data_frame: pd.DataFrame, name_field: str = None, value_field: s width: str = "100%", height: str = "500px",**kwargs) -> Echarts: """ 饼图 + :param data_frame: 必填 DataFrame :param name_field: name列名 :param value_field: value列名 @@ -555,6 +556,7 @@ def candlestick_echarts(data_frame: pd.DataFrame, time_field: str = 'time', open right_padding: str = '3%',**kwargs) -> Echarts: """ 绘制K线 + :param data_frame: :param time_field: 时间列名, 如果指定的列不存在,使用index作为time :param open_field: open列名 @@ -994,6 +996,7 @@ def calendar_heatmap_echarts(data_frame: pd.DataFrame, date_field: str = None, v width: str = "100%", height: str = "300px",**kwargs) -> Echarts: """ 日历热度图,显示日期热度 + :param data_frame: :param date_field: 日期列 :param value_field: 值列 @@ -1079,6 +1082,7 @@ def parallel_echarts(data_frame: pd.DataFrame, name_field: str = None, indicator width: str = "100%", height: str = "500px",**kwargs) -> Echarts: """ 平行坐标图,要求name列每行唯一 比如:显示每个报告期各财务指标 + :param data_frame: :param name_field: name列 :param indicator_field_list: 数据维度列list @@ -1173,7 +1177,6 @@ def sankey_echarts(data_frame: pd.DataFrame, source_field: str = None, target_fi width: str = "100%", height: str = "500px",**kwargs) -> Echarts: """ - :param data_frame: :param source_field: source列 :param target_field: target列 @@ -1370,6 +1373,7 @@ def mark_area_echarts(data_frame: pd.DataFrame, x1: str, y1: str, x2: str, y2: s ): """ 在现有图表上叠加矩形,不能单独显示 + :param data_frame: :param x1: 左上方顶点x坐标对应列 :param y1: 左上方顶点y坐标对应列 @@ -1377,7 +1381,7 @@ def mark_area_echarts(data_frame: pd.DataFrame, x1: str, y1: str, x2: str, y2: s :param y2: 右下方顶点y坐标对应列 :param label: 矩形标签文字对应列 :param title: 用于在legend显示,控制叠加矩形显示隐藏 - :param label_position:top / left / right / bottom / inside / insideLeft / insideRight / insideTop / insideBottom / insideTopLeft / insideBottomLeft / insideTopRight / insideBottomRight + :param label_position: top / left / right / bottom / inside / insideLeft / insideRight / insideTop / insideBottom / insideTopLeft / insideBottomLeft / insideTopRight / insideBottomRight :param label_distance: :param label_font_size: :param label_font_color: @@ -1420,12 +1424,13 @@ def mark_background_echarts(data_frame: pd.DataFrame, x1: str, x2: str, label: s ): """ 在现有图表上叠加背景,不能单独显示 + :param data_frame: :param x1: 左上方顶点x坐标对应列 :param x2: 右下方顶点x坐标对应列 :param label: 矩形标签文字对应列 :param title: 用于在legend显示,控制叠加矩形显示隐藏 - :param label_position:top / left / right / bottom / inside / insideLeft / insideRight / insideTop / insideBottom / insideTopLeft / insideBottomLeft / insideTopRight / insideBottomRight + :param label_position: top / left / right / bottom / inside / insideLeft / insideRight / insideTop / insideBottom / insideTopLeft / insideBottomLeft / insideTopRight / insideBottomRight :param label_distance: :param label_font_size: :param label_font_color: @@ -1479,7 +1484,7 @@ def mark_segment_echarts(data_frame: pd.DataFrame, x1: str, y1: str, x2: str, y2 :param label: 矩形标签文字对应列 :param title: 用于在legend显示,控制叠加矩形显示隐藏 :param show_label: 是否显示label - :param label_position:top / left / right / bottom / inside / insideLeft / insideRight / insideTop / insideBottom / insideTopLeft / insideBottomLeft / insideTopRight / insideBottomRight + :param label_position: top / left / right / bottom / inside / insideLeft / insideRight / insideTop / insideBottom / insideTopLeft / insideBottomLeft / insideTopRight / insideBottomRight :param label_distance: 10 :param label_font_color:inherit :param label_font_size:12 @@ -1527,16 +1532,17 @@ def mark_label_echarts(data_frame: pd.DataFrame, x: str, y: str, label: str, tit label_font_color: str = 'inherit', label_background_color: str = "transparent",**kwargs): """ 在现有图表上叠加标签,不能单独显示 + :param data_frame: :param x: 左上方顶点x坐标对应列 :param y: 左上方顶点y坐标对应列 :param label: 矩形标签文字对应列 :param title: 用于在legend显示,控制叠加矩形显示隐藏 - :param label_position:top / left / right / bottom / inside / insideLeft / insideRight / insideTop / insideBottom / insideTopLeft / insideBottomLeft / insideTopRight / insideBottomRight + :param label_position: top / left / right / bottom / inside / insideLeft / insideRight / insideTop / insideBottom / insideTopLeft / insideBottomLeft / insideTopRight / insideBottomRight :param label_distance: 10 - :param label_font_color:inherit - :param label_font_size:12 - :param label_background_color:transparent + :param label_font_color: inherit + :param label_font_size: 12 + :param label_background_color: transparent :return: """ options = copy.deepcopy(ECHARTS_BASE_OVERLAY_OPTIONS) @@ -1569,6 +1575,7 @@ def mark_vertical_line_echarts(data_frame: pd.DataFrame, x: str, label: str, tit label_font_color: str = 'inherit',**kwargs): """ 在现有图表上叠加竖线,不能单独显示 + :param data_frame: :param x: :param label: @@ -1614,6 +1621,7 @@ def mark_horizontal_line_echarts(data_frame: pd.DataFrame, y: str, label: str, t label_font_color: str = 'inherit',**kwargs): """ 在现有图表上叠加横线,不能单独显示 + :param data_frame: :param y: :param label: @@ -1668,7 +1676,6 @@ def scatter3d_echarts(data_frame: pd.DataFrame, x_field: str = None, y_field: st """ 3d 气泡图 - :param data_frame: :param x_field: :param y_field: @@ -1812,6 +1819,7 @@ def bar3d_echarts(data_frame: pd.DataFrame, x_field: str = None, y_field: str = height: str = "500px",**kwargs): """ 3d bar + :param data_frame: :param x_field: :param y_field: @@ -1916,6 +1924,7 @@ def drawdown_echarts(data_frame: pd.DataFrame, time_field: str, value_field: str height='500px',**kwargs) -> Echarts: """ 回撤图 + :param data_frame: pd.DataFrame :param time_field: 时间列名 :param value_field: 价格列名 diff --git a/chartspy/klinecharts.py b/chartspy/klinecharts.py index 320610d..3195db8 100644 --- a/chartspy/klinecharts.py +++ b/chartspy/klinecharts.py @@ -53,11 +53,12 @@ def __init__(self, df: pd.DataFrame, mas=[5, 10, 30, 60, 120, 250], main_indicat height: str = "500px"): """ k线图 + :param df: [open,high,low,close,volume,turnover,timestamp] :param mas: [5, 10, 30, 60, 120, 250] :param main_indicators: 主图显示的指标列表 MA,EMA,SMA,BOLL,SAR,BBI - :param bottom_indicators:副图显示指标列表 VOL,MACD,KDJ,RSI,BIAS,BBAR,CCI,DMI,CR,PSY,DMA,TRIX,OBV,VR,WR,MTM,EMV,SAR,SMA,ROC,PVT,BBI,AO - :param df_segments:[start_time,start_price,end_time,end_price] + :param bottom_indicators: 副图显示指标列表 VOL,MACD,KDJ,RSI,BIAS,BBAR,CCI,DMI,CR,PSY,DMA,TRIX,OBV,VR,WR,MTM,EMV,SAR,SMA,ROC,PVT,BBI,AO + :param df_segments: [start_time,start_price,end_time,end_price] :param extra_js: :param width: :param height: @@ -88,6 +89,7 @@ def __init__(self, df: pd.DataFrame, mas=[5, 10, 30, 60, 120, 250], main_indicat def render_notebook(self) -> Html: """ 在jupyter notebook 环境输出 + :return: """ plot = self @@ -121,6 +123,7 @@ def render_notebook(self) -> Html: def render_jupyterlab(self) -> Html: """ 在jupyterlab 环境输出 + :return: """ plot = self @@ -152,6 +155,7 @@ def render_jupyterlab(self) -> Html: def render_html(self) -> str: """ 渲染html字符串,可以用于 streamlit + :return: """ plot = self @@ -184,6 +188,7 @@ def render_html(self) -> str: def render_html_fragment(self): """ 渲染html 片段,方便一个网页输出多个图表 + :return: """ plot = self @@ -208,6 +213,7 @@ def render_html_fragment(self): def _repr_html_(self): """ jupyter 环境,直接输出 + :return: """ plot = self From b49f7a6b8a65429e94a97d79c6472b5cb4b7a339 Mon Sep 17 00:00:00 2001 From: wyn Date: Wed, 30 Oct 2024 20:10:21 +0800 Subject: [PATCH 3/4] =?UTF-8?q?KlineCharts=E6=94=AF=E6=8C=81=E5=90=91kline?= =?UTF-8?q?charts=E6=B3=A8=E5=85=A5=E5=AE=9A=E5=88=B6=E5=8C=96js=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chartspy/klinecharts.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/chartspy/klinecharts.py b/chartspy/klinecharts.py index 3195db8..5a1cc4d 100644 --- a/chartspy/klinecharts.py +++ b/chartspy/klinecharts.py @@ -11,7 +11,7 @@ # language=jinja2 -def kline_chart_segment(plot): +def kline_chart_segment(plot, inject_js: str=None): parts = [] parts.append( f"""var chart_{plot.plot_id} = klinecharts.init("{plot.plot_id}", @@ -39,6 +39,8 @@ def kline_chart_segment(plot): chart_{plot.plot_id}.createShape({{name: 'segment',points:[{{timestamp:{seg['start_time']},value:{seg['start_price']}}},{{timestamp:{seg['end_time']},value:{seg['end_price']}}}]}},"candle_pane") """) parts.append(f"""chart_{plot.plot_id}.applyNewData(data_{plot.plot_id})""") + if inject_js: + parts.append(inject_js) return "\n".join(parts) @@ -50,7 +52,8 @@ class KlineCharts(object): def __init__(self, df: pd.DataFrame, mas=[5, 10, 30, 60, 120, 250], main_indicators=["MA"], bottom_indicators=["VOL", "MACD"], df_segments: pd.DataFrame = None, extra_js: str = "", width: str = "100%", - height: str = "500px"): + height: str = "500px", + inject_klinecharts_js: str = None): """ k线图 @@ -62,9 +65,12 @@ def __init__(self, df: pd.DataFrame, mas=[5, 10, 30, 60, 120, 250], main_indicat :param extra_js: :param width: :param height: + :param inject_klinecharts_js: 注入 klinecharts 的定制化js代码\n + 以'{chart}'方式引用chart,如 {chart}.createIndicator(...) """ data = df.copy() - data['timestamp'] = (pd.to_datetime(data['timestamp']) - pd.Timedelta(hours=8)).view("i8") // 10 ** 6 + u = None if data['timestamp'].dtype != int else 'ms' if data['timestamp'].iloc[-1] > 1e10 else 's' + data['timestamp'] = (pd.to_datetime(data['timestamp'], unit=u) - pd.Timedelta(hours=8)).view("i8") // 10 ** 6 data = data.sort_values(by=['timestamp']) if len(mas) > 0 and "MA" not in main_indicators: main_indicators.append("MA") @@ -85,6 +91,7 @@ def __init__(self, df: pd.DataFrame, mas=[5, 10, 30, 60, 120, 250], main_indicat self.plot_id = "u" + uuid.uuid4().hex self.js_url = KlineCharts_JS_URL self.extra_js = extra_js + self.inject_js = inject_klinecharts_js.replace('{chart}', f'chart_{self.plot_id}') def render_notebook(self) -> Html: """ @@ -113,7 +120,7 @@ def render_notebook(self) -> Html: {plot.extra_js} var data_{plot.plot_id} = {plot.data} require(['klinecharts'], function (klinecharts) {{ - """ + kline_chart_segment(plot) + f""" + """ + kline_chart_segment(plot, self.inject_js) + f""" }}); @@ -146,7 +153,7 @@ def render_jupyterlab(self) -> Html: script.src = "{plot.js_url}"; document.head.appendChild(script); }}).then(() => {{ - """ + kline_chart_segment(plot) + f""" + """ + kline_chart_segment(plot, self.inject_js) + f""" }}); """ @@ -177,7 +184,7 @@ def render_html(self) -> str:
@@ -204,7 +211,7 @@ def render_html_fragment(self):
""" @@ -235,7 +242,7 @@ def _repr_html_(self): }} }}); require(['klinecharts'], function (klinecharts) {{ - """ + kline_chart_segment(plot) + f""" + """ + kline_chart_segment(plot, self.inject_js) + f""" }}); }}else{{ new Promise(function(resolve, reject) {{ @@ -245,7 +252,7 @@ def _repr_html_(self): script.src = "{plot.js_url}"; document.head.appendChild(script); }}).then(() => {{ - """ + kline_chart_segment(plot) + f""" + """ + kline_chart_segment(plot, self.inject_js) + f""" }}); }} From 98f85199781c7ffe27957b13ffa74b4946a4f1b4 Mon Sep 17 00:00:00 2001 From: wyn Date: Wed, 30 Oct 2024 21:12:48 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix=20bug:=20KlineCharts=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=90=91klinecharts=E6=B3=A8=E5=85=A5=E5=AE=9A=E5=88=B6?= =?UTF-8?q?=E5=8C=96js=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chartspy/klinecharts.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/chartspy/klinecharts.py b/chartspy/klinecharts.py index 5a1cc4d..d74d8e4 100644 --- a/chartspy/klinecharts.py +++ b/chartspy/klinecharts.py @@ -91,7 +91,9 @@ def __init__(self, df: pd.DataFrame, mas=[5, 10, 30, 60, 120, 250], main_indicat self.plot_id = "u" + uuid.uuid4().hex self.js_url = KlineCharts_JS_URL self.extra_js = extra_js - self.inject_js = inject_klinecharts_js.replace('{chart}', f'chart_{self.plot_id}') + self.inject_js = inject_klinecharts_js + if self.inject_js is not None: + self.inject_js = self.inject_js.replace('{chart}', f'chart_{self.plot_id}') def render_notebook(self) -> Html: """ @@ -184,6 +186,7 @@ def render_html(self) -> str: