def test_js_on_change_executes(self, bokeh_model_page): group = CheckboxGroup(labels=LABELS, css_classes=["foo"]) group.js_on_click(CustomJS(code=RECORD("active", "cb_obj.active"))) page = bokeh_model_page(group) el = page.driver.find_element_by_css_selector('.foo input[value="2"]') el.click() results = page.results assert results['active'] == [2] el = page.driver.find_element_by_css_selector('.foo input[value="0"]') el.click() results = page.results assert results['active'] == [0, 2] el = page.driver.find_element_by_css_selector('.foo input[value="2"]') el.click() results = page.results assert results['active'] == [0] assert page.has_no_console_errors()
def test_js_on_change_executes(self, bokeh_model_page: BokehModelPage) -> None: group = CheckboxGroup(labels=LABELS) group.js_on_click(CustomJS(code=RECORD("active", "cb_obj.active"))) page = bokeh_model_page(group) el = find_element_for(page.driver, group, 'input[value="2"]') el.click() results = page.results assert results['active'] == [2] el = find_element_for(page.driver, group, 'input[value="0"]') el.click() results = page.results assert results['active'] == [0, 2] el = find_element_for(page.driver, group, 'input[value="2"]') el.click() results = page.results assert results['active'] == [0] assert page.has_no_console_errors()
def one_filter(plot, filter_col, filter_vals, filters_state, max_items): # Remove (FX) from column name; probaby temporary title = re.sub(r'\s*[(]F[0-9]+[)]\s*', '', filter_col) # Deduplicate and turn into name-value pairs, as required by MultiSelect. #options = [(opt,) * 2 for opt in sorted(filter_vals)] options = list(filter_vals) multi_select = CheckboxGroup(name=title, labels=options, active=[0, 1]) # The state of each multi-select is stored in an intermediate # table; when a given multi-select is changed, the table is updated. # The change to the table triggers a second update, defined below # in `point_plot`. That second update modifies the map based on # the state of all multi-selects simultaneously. This way, individual # multi-select widgets can operate independently without knowing # anything about one another. multi_select.js_on_click( CustomJS(args=dict(filter_col=filter_col, filters_state=filters_state), code=""" console.log(this.active); let select_vals = this.active; let state_col = filters_state.data[filter_col]; for (let i = 0; i < state_col.length; i++) { if (i < select_vals.length) { state_col[i] = select_vals[i]; } else { state_col[i] = ''; } } filters_state.properties.data.change.emit(); """)) return multi_select
def trend_chart(self, target_stock: str): """Trend chart of the result using Bokeh.""" result = self.__check_result(target_stock) tabs = [] for i in result.keys(): label_name = i tickers = result[i] cumprod = (self.daily_return[tickers] + 1).cumprod() source = ColumnDataSource(data=cumprod) p = figure(x_axis_type="datetime", title="Trend Line", plot_height=350, plot_width=800) p.xgrid.grid_line_color = None p.ygrid.grid_line_alpha = 0.5 p.xaxis.axis_label = 'Time' p.yaxis.axis_label = 'Total Return' lines = [] for i in range(len(cumprod.columns)): lines.append( p.line("Date", cumprod.columns[i], source=source, line_width=2, line_alpha=0.8, line_color=Spectral10[i % 10], legend_label=cumprod.columns[i], muted_color=Spectral10[i % 10], muted_alpha=0.1)) p.legend.location = "top_left" p.legend.click_policy = "mute" LABELS = list(cumprod.columns) checkbox_group = CheckboxGroup(labels=LABELS) checkbox_group.active = list(range(len(LABELS))) code = """ for (var i = 0; i < lines.length; i++) { lines[i].visible = false; if (cb_obj.active.includes(i)){lines[i].visible = true;} } """ callback = CustomJS(code=code, args={'lines': lines}) checkbox_group.js_on_click(callback) layout = row(p, checkbox_group) tabs.append(Panel(child=layout, title=label_name)) tabs = Tabs(tabs=tabs) show(tabs)
def one_filter(plot, filter_col, filter_vals, filters_state, max_items): # Remove (FX) from column name; probaby temporary title = re.sub(r'\s*[(]F[0-9]+[)]\s*', '', filter_col) title = title.replace(" ", "") options = list(filter_vals) multi_select = CheckboxGroup( name=title, labels=options, css_classes=[title], default_size=150, height_policy='min', visible=True ) # The state of each multi-select is stored in an intermediate # table; when a given multi-select is changed, the table is updated. # The change to the table triggers a second update, defined below # in `point_plot`. That second update modifies the map based on # the state of all multi-selects simultaneously. This way, individual # multi-select widgets can operate independently without knowing # anything about one another. multi_select.js_on_click(CustomJS( args=dict(filter_col=filter_col, filters_state=filters_state), code=""" // Turn the list of active indices into a list of labels. let select_vals = this.active.map((act) => this.labels[act]); let state_col = filters_state.data[filter_col]; for (let i = 0; i < state_col.length; i++) { if (i < select_vals.length) { state_col[i] = select_vals[i]; } else { state_col[i] = ''; } } filters_state.properties.data.change.emit(); """) ) return multi_select
def trend_chart(self, policy_names: list, compounding: bool = False, height: int = 350, width: int = 800): """Trend chart of the result using Bokeh. Parameters ---------- policy_names : list List of selected policy names compounding : bool, default False Whether returns are reinvested back into the account. height : int Height of the plot width : int Width of the plot Returns ------- None """ selected_rst_dict = {key: self.rst_dict[key] for key in policy_names} data = pd.DataFrame(selected_rst_dict) data["strategy_return"] = self.strategy_return if compounding: cum = (data + 1).cumprod() else: cum = data.cumsum() + 1 if compounding: mdd = (cum / cum.cummax() - 1) else: mdd = cum - cum.cummax() source = ColumnDataSource(data=cum) source_mdd = ColumnDataSource(data=mdd) p = figure(x_axis_type="datetime", title="Trend Line", plot_height=height, plot_width=width) p.xgrid.grid_line_color = None p.ygrid.grid_line_alpha = 0.5 p.xaxis.axis_label = 'Time' p.yaxis.axis_label = 'Total Return' p_mdd = figure(x_axis_type="datetime", title="Max Drawdown", plot_height=height, plot_width=width, x_range=p.x_range) p_mdd.xgrid.grid_line_color = None p_mdd.ygrid.grid_line_alpha = 0.5 p_mdd.xaxis.axis_label = 'Time' p_mdd.yaxis.axis_label = 'MDD' lines = [] for i in range(len(cum.columns)): lines.append( p.line("Date", cum.columns[i], source=source, line_width=2, line_alpha=0.8, line_color=Spectral10[i % 10], legend_label=cum.columns[i], muted_color=Spectral10[i % 10], muted_alpha=0.1)) lines_mdd = [] for i in range(len(mdd.columns)): lines_mdd.append( p_mdd.line("Date", mdd.columns[i], source=source_mdd, line_width=2, line_alpha=0.8, line_color=Spectral10[i % 10], legend_label=mdd.columns[i], muted_color=Spectral10[i % 10], muted_alpha=0.1)) p.legend.location = "top_left" p.legend.click_policy = "mute" p_mdd.legend.location = "bottom_left" p_mdd.legend.click_policy = "mute" LABELS = list(cum.columns) checkbox_group = CheckboxGroup(labels=LABELS) checkbox_group.active = list(range(len(LABELS))) code = """ for (var i = 0; i < lines.length; i++) { lines[i].visible = false; if (cb_obj.active.includes(i)){lines[i].visible = true;} } """ callback = CustomJS(code=code, args={'lines': lines}) checkbox_group.js_on_click(callback) callback = CustomJS(code=code, args={'lines': lines_mdd}) checkbox_group.js_on_click(callback) grid = gridplot([[p, checkbox_group], [p_mdd]]) show(grid)
def create_water_tanks_iplot(data_df, logger): columns = ['L_T' + str(i) for i in range(1, 8)] max_y = max([data_df[col].max() for col in columns]) source = ColumnDataSource({ 'x_t1': data_df.index, 'y_t1': data_df['L_T1'], 'x_t2': data_df.index, 'y_t2': data_df['L_T2'], 'x_t3': data_df.index, 'y_t3': data_df['L_T3'], 'x_t4': data_df.index, 'y_t4': data_df['L_T4'], 'x_t5': data_df.index, 'y_t5': data_df['L_T5'], 'x_t6': data_df.index, 'y_t6': data_df['L_T6'], 'x_t7': data_df.index, 'y_t7': data_df['L_T7'], }) p = figure(plot_width=1000, plot_height=750, title="Water tanks", tools="pan,wheel_zoom,save,reset", x_axis_type="datetime", y_range=[0, max_y + 2.5], x_axis_label="Time", y_axis_label="Water level (m)") p.xaxis.axis_label_text_font_size = "18pt" p.yaxis.axis_label_text_font_size = "18pt" p_t1 = p.line('x_t1', 'y_t1', source=source, color='red', alpha=0.9, line_width=2, legend="Tank1") p_t2 = p.line('x_t2', 'y_t2', source=source, color='gold', alpha=0.9, line_width=2, legend="Tank2") p_t3 = p.line('x_t3', 'y_t3', source=source, color='blue', alpha=0.9, line_width=2, legend="Tank3") p_t4 = p.line('x_t4', 'y_t4', source=source, color='black', alpha=0.9, line_width=2, legend="Tank4") p_t5 = p.line('x_t5', 'y_t5', source=source, color='mediumspringgreen', alpha=0.9, line_width=2, legend="Tank5") p_t6 = p.line('x_t6', 'y_t6', source=source, color='salmon', alpha=0.9, line_width=2, legend="Tank6") p_t7 = p.line('x_t7', 'y_t7', source=source, color='navy', alpha=0.9, line_width=2, legend="Tank7") p.legend.location = "top_left" tanks = ['Tank ' + str(i) for i in range(1, 8)] checkboxes = CheckboxGroup(labels=tanks, active=[i for i in range(7)]) callback = CustomJS(args=dict(p_t1=p_t1, p_t2=p_t2, p_t3=p_t3, p_t4=p_t4, p_t5=p_t5, p_t6=p_t6, p_t7=p_t7), code=""" f = cb_obj.active; p_t1.visible = false; p_t2.visible = false; p_t3.visible = false; p_t4.visible = false; p_t5.visible = false; p_t6.visible = false; p_t7.visible = false; if (f.includes(0)) { p_t1.visible = true; } if (f.includes(1)) { p_t2.visible = true; } if (f.includes(2)) { p_t3.visible = true; } if (f.includes(3)) { p_t4.visible = true; } if (f.includes(4)) { p_t5.visible = true; } if (f.includes(5)) { p_t6.visible = true; } if (f.includes(6)) { p_t7.visible = true; } """) checkboxes.js_on_click(callback) output_file(logger.get_output_file("tanks.html")) save(row(checkboxes, p))
def trend_chart(returns_series, compounding: bool = False, height: int = 350, width: int = 800): """Trend chart of the result using Bokeh. Parameters ---------- returns_series : Pandas Series Series contains returns. compounding : bool, default False Whether returns are reinvested back into the account. height : int Height of the plot width : int Width of the plot Returns ------- None """ data = returns_series if compounding: cum = (data + 1).cumprod() else: cum = data.cumsum() + 1 cum = pd.DataFrame(cum) source = ColumnDataSource(data=cum) p = figure(x_axis_type="datetime", title="Trend Line", plot_height=height, plot_width=width) p.xgrid.grid_line_color = None p.ygrid.grid_line_alpha = 0.5 p.xaxis.axis_label = 'Time' p.yaxis.axis_label = 'Total Return' lines = [] for i in range(len(cum.columns)): lines.append( p.line("Date", cum.columns[i], source=source, line_width=2, line_alpha=0.8, line_color=Spectral10[i % 10], legend_label=cum.columns[i], muted_color=Spectral10[i % 10], muted_alpha=0.1)) p.legend.location = "top_left" p.legend.click_policy = "mute" LABELS = list(cum.columns) checkbox_group = CheckboxGroup(labels=LABELS) checkbox_group.active = list(range(len(LABELS))) code = """ for (var i = 0; i < lines.length; i++) { lines[i].visible = false; if (cb_obj.active.includes(i)){lines[i].visible = true;} } """ callback = CustomJS(code=code, args={'lines': lines}) checkbox_group.js_on_click(callback) layout = row(p, checkbox_group) show(layout)