def create_range_slider(range: Range1d, title: str, step: float) -> RangeSlider: slider = RangeSlider( start=range.start, end=range.end, step=step, value=(range.bounds[0], range.bounds[1]), title=title, ) slider.js_link("value", range, "start", attr_selector=0) slider.js_link("value", range, "end", attr_selector=1) return slider
def page(): # create plot with circle glyphs p = figure(x_range=(1, 9), plot_width=500, plot_height=250) points = p.circle(x=x, y=y, size=15, fill_color="#21a7df") # set up textarea (div) div = Div( text=""" <p>Select the circle's size using this control element:</p> """, width=200, height=30, ) # set up spinner spinner = Spinner( title="Circle size", low=0, high=60, step=5, value=points.glyph.size, width=200, ) spinner.js_link("value", points.glyph, "size") # set up RangeSlider range_slider = RangeSlider( title="Adjust x-axis range", start=0, end=10, step=1, value=(p.x_range.start, p.x_range.end), ) range_slider.js_link("value", p.x_range, "start", attr_selector=0) range_slider.js_link("value", p.x_range, "end", attr_selector=1) # create layout return layout([ [div, spinner], [range_slider], [p], ])
def index(request, code): User = request.user title = f'股票' today = date.today().strftime("%Y-%m-%d") begin_date = today end_date = today stock_df = pd.read_excel('djangoapp/stockapp/files/上市、上櫃(股本、產業、產業地位).xlsx') stock_df['代碼名稱'] = stock_df['代碼'].astype(str) + ' ' + stock_df['商品'] default_stock_list = stock_df['代碼名稱'].values.tolist() for i in range(len(default_stock_list)): if default_stock_list[i][:4] == str(code): full_code_name = default_stock_list[i] title = f'{full_code_name}' break stock_list = models.StockModel.objects.filter(Owner=User) get_stock = models.StockModel.objects.filter(Code=code) if request.POST.get('search'): begin_date = request.POST.get('begin-date') begin_datatime = datetime.strptime(begin_date, "%Y-%m-%d") end_date = request.POST.get('end-date') end_datatime = datetime.strptime(end_date, "%Y-%m-%d") if end_datatime.isoweekday() > 5: end_date = (end_datatime + timedelta( days=(5 - end_datatime.isoweekday()))).strftime("%Y-%m-%d") if begin_datatime.isoweekday() > 5: begin_date = (begin_datatime + timedelta( days=(5 - begin_datatime.isoweekday()))).strftime("%Y-%m-%d") if begin_date > end_date: begin_date, end_date = end_date, begin_date begin_date_split = begin_date.split('-') new_begin_date = f"{begin_date_split[0]}-{int(begin_date_split[1])}-{int(begin_date_split[2])}" end_date_split = end_date.split('-') new_end_date = f"{end_date_split[0]}-{int(end_date_split[1])}-{int(end_date_split[2])}" broker_table = esun.crawler(code, new_begin_date, new_end_date) df = pd.read_csv( f'djangoapp/stockapp/files/historical-daily-candlesticks/{code}.csv') df = df[::-1].reset_index() df = df.drop(columns=['index']) df.columns = ['date', 'open', 'high', 'low', 'close', 'volume'] df['date'] = pd.to_datetime(df['date']) df['MA5'] = df['close'].rolling(5).mean() df['MA10'] = df['close'].rolling(10).mean() df['MA20'] = df['close'].rolling(20).mean() df['MA60'] = df['close'].rolling(60).mean() df['MA100'] = df['close'].rolling(100).mean() df['MA240'] = df['close'].rolling(240).mean() inc = df.close > df.open dec = df.open > df.close date_length = 60 x_end = len(df) x_start = x_end - date_length y_start = df['close'][-date_length:].min() * 0.95 y_end = df['close'][-date_length:].max() * 1.05 plot_width = 1545 hover = HoverTool(tooltips=[('date', '@date{%F}'), ('open', '@open'), ('high', '@high'), ('low', '@low'), ('close', '@close'), ('volume', '@volume')], formatters={ '@date': 'datetime', 'open': 'numeral', 'high': 'numeral', 'low': 'numeral', 'close': 'numeral', }, mode='vline') p1 = figure(title=f'{full_code_name} K線圖', tools=[hover, 'save'], x_range=(x_start, x_end), y_range=(y_start, y_end), plot_width=plot_width, toolbar_location='above') p1.xaxis.major_label_overrides = { i: date.strftime('%Y-%m-%d') for i, date in enumerate(pd.to_datetime(df['date'])) } df_source = ColumnDataSource(df) inc_data = df[inc] dec_data = df[dec] inc_source = ColumnDataSource(inc_data) dec_source = ColumnDataSource(dec_data) p1.segment('index', 'high', 'index', 'low', color='black', source=df_source) vbar1 = p1.vbar('index', 0.5, 'open', 'close', fill_color='#eb2409', line_color='black', source=inc_source) vbar2 = p1.vbar('index', 0.5, 'open', 'close', fill_color='#00995c', line_color='black', source=dec_source) p1.hover.renderers = [vbar1, vbar2] ma_legend_items = [] color = ('#4286F5', '#FEBD09', '#E65596', '#83BF0A', '#834BEB', '#FC7742') for ma_name, color in zip( ['MA5', 'MA10', 'MA20', 'MA60', 'MA100', 'MA240'], color): ma_df = df[['date', 'close', 'open', 'high', 'low', 'volume', ma_name]] source = ColumnDataSource(ma_df) ma_line = p1.line(x='index', y=ma_name, line_width=2, color=color, alpha=0.8, muted_color=color, muted_alpha=0.2, source=source) ma_legend_items.append((ma_name, [ma_line])) legend = Legend(items=ma_legend_items, location=(50, 50)) p1.add_layout(legend) p2 = figure(x_range=(0, x_end), y_range=(df['close'].min(), df['close'].max()), plot_width=plot_width, plot_height=100, toolbar_location=None) p2.xaxis.major_label_overrides = { i: date.strftime('%Y-%m-%d') for i, date in enumerate(pd.to_datetime(df["date"])) } p2.line(x='index', y='close', line_width=2, color="black", alpha=0.8, source=df_source) p2.yaxis.major_label_text_color = None p2.yaxis.major_tick_line_color = None p2.yaxis.minor_tick_line_color = None p2.grid.grid_line_color = None box = BoxAnnotation(fill_alpha=0.5, line_alpha=0.5, level='underlay', left=x_start, right=x_end) p2.add_layout(box) range_slider = RangeSlider(title=None, start=0, end=x_end, value=(x_start, x_end), default_size=plot_width - 30, step=1) range_slider.js_link('value', p1.x_range, 'start', attr_selector=0) range_slider.js_link('value', p1.x_range, 'end', attr_selector=1) range_slider.js_link('value', box, 'left', attr_selector=0) range_slider.js_link('value', box, 'right', attr_selector=1) callback = CustomJS(args=dict(xr=p1.x_range, yr=p1.y_range, data=source.data), code=""" let begin = Math.floor(xr.start); let end = Math.floor(xr.end); let array = data.close.slice(begin, end); let y_start = Math.min(...array) * 0.95; let y_end = Math.max(...array) * 1.05; yr.start = y_start; yr.end = y_end; """) p1.x_range.js_on_change('start', callback) stock_layout = layout([[p1], [p2], row(Spacer(width=20), range_slider)]) script, div = components(stock_layout) return render(request, 'stock.html', locals())
spinner = Spinner( title="圆点大小", low=0, high=60, step=5, value=points.glyph.size, width=200, ) spinner.js_link("value", points.glyph, "size") # set up RangeSlider range_slider = RangeSlider( title="调整 x轴的范围", start=2010, end=2020, step=1, value=(p.x_range.start, p.x_range.end), ) range_slider.js_link("value", p.x_range, "start", attr_selector=0) range_slider.js_link("value", p.x_range, "end", attr_selector=1) # create layout layout = layout([ [div, spinner], [range_slider], [p], ]) # show result show(layout)
def generate_graph(code, name): df = pd.read_csv( f'djangoapp/stockapp/files/historical-daily-candlesticks/{code}.csv') df = df[::-1].reset_index() df = df.drop(columns=['index']) df.columns = ['date', 'open', 'high', 'low', 'close', 'volume'] df['date'] = pd.to_datetime(df['date']) df['MA5'] = df['close'].rolling(5).mean() df['MA10'] = df['close'].rolling(10).mean() df['MA20'] = df['close'].rolling(20).mean() df['MA60'] = df['close'].rolling(60).mean() df['MA120'] = df['close'].rolling(120).mean() df['MA240'] = df['close'].rolling(240).mean() inc = df.close > df.open dec = df.open > df.close date_length = 60 x_end = len(df) x_start = x_end - date_length y_start = df['close'][-date_length:].min() * 0.95 y_end = df['close'][-date_length:].max() * 1.05 plot_width = 1545 hover = HoverTool(tooltips=[('date', '@date{%F}'), ('open', '@open'), ('high', '@high'), ('low', '@low'), ('close', '@close'), ('volume', '@volume')], formatters={ '@date': 'datetime', 'open': 'numeral', 'high': 'numeral', 'low': 'numeral', 'close': 'numeral', }, mode='vline') p1 = figure(title=f'{code} {name} K線圖', tools=[hover, 'crosshair, save'], x_range=(x_start, x_end), y_range=(y_start, y_end), plot_width=plot_width, toolbar_location='above') p1.xaxis.major_label_overrides = { i: date.strftime('%Y-%m-%d') for i, date in enumerate(pd.to_datetime(df['date'])) } df_source = ColumnDataSource(df) inc_data = df[inc] dec_data = df[dec] inc_source = ColumnDataSource(inc_data) dec_source = ColumnDataSource(dec_data) p1.segment('index', 'high', 'index', 'low', color='black', source=df_source) vbar1 = p1.vbar('index', 0.5, 'open', 'close', fill_color='#eb2409', line_color='black', source=inc_source) vbar2 = p1.vbar('index', 0.5, 'open', 'close', fill_color='#00995c', line_color='black', source=dec_source) p1.hover.renderers = [vbar1, vbar2] ma_legend_items = [] color = ('#4286F5', '#FEBD09', '#E65596', '#83BF0A', '#834BEB', '#FC7742') for ma_name, color in zip( ['MA5', 'MA10', 'MA20', 'MA60', 'MA120', 'MA240'], color): ma_df = df[['date', 'close', 'open', 'high', 'low', 'volume', ma_name]] source = ColumnDataSource(ma_df) ma_line = p1.line(x='index', y=ma_name, line_width=2, color=color, alpha=0.8, muted_color=color, muted_alpha=0.2, source=source) ma_legend_items.append((ma_name, [ma_line])) legend = Legend(items=ma_legend_items, location=(50, 50)) p1.add_layout(legend) p2 = figure(x_range=(0, x_end), y_range=(df['close'].min(), df['close'].max()), plot_width=plot_width, plot_height=100, toolbar_location=None) p2.xaxis.major_label_overrides = { i: date.strftime('%Y-%m-%d') for i, date in enumerate(pd.to_datetime(df["date"])) } p2.line(x='index', y='close', line_width=2, color="black", alpha=0.8, source=df_source) p2.toolbar.active_drag = None p2.yaxis.major_label_text_color = None p2.yaxis.major_tick_line_color = None p2.yaxis.minor_tick_line_color = None p2.grid.grid_line_color = None box = BoxAnnotation(fill_alpha=0.5, line_alpha=0.5, level='underlay', left=x_start, right=x_end) p2.add_layout(box) range_slider = RangeSlider(title=None, start=0, end=x_end, value=(x_start, x_end), default_size=plot_width - 30, step=1) range_slider.js_link('value', p1.x_range, 'start', attr_selector=0) range_slider.js_link('value', p1.x_range, 'end', attr_selector=1) range_slider.js_link('value', box, 'left', attr_selector=0) range_slider.js_link('value', box, 'right', attr_selector=1) callback = CustomJS(args=dict(xr=p1.x_range, yr=p1.y_range, data=source.data), code=""" let begin = Math.floor(xr.start); let end = Math.floor(xr.end); let array = data.close.slice(begin, end); let y_start = Math.min(...array) * 0.95; let y_end = Math.max(...array) * 1.05; yr.start = y_start; yr.end = y_end; """) p1.x_range.js_on_change('start', callback) stock_layout = layout([[p1], [p2], row(Spacer(width=20), range_slider)]) return components(stock_layout)