如何使用日期时间x轴向散景图中添加具有偏移量的Arrow注释 [英] How to add Arrow annotations with an offset to a bokeh plot with a datetime x-axis

查看:38
本文介绍了如何使用日期时间x轴向散景图中添加具有偏移量的Arrow注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在2 ma彼此相交时绘制箭头或点,例如当short ma高于long ma等时会出现向上箭头,但是我不知道如何绘制它的日期时间.我尝试使用此代码,但它只会给我错误.

  #plot短码ma和长码map.line(df ['Date'],df ['short_ma'],color ='red')p.line(df ['Date'],df ['long_ma'],color ='black')p.add_layout(Arrow(end = VeeHead(size = 35),line_color ="red",x_start = df ['Date'],y_start = df ['crossabove'] + 5,x_end = df ['Date'],y_end = df ['Date']))#交叉上方+ 5,所以箭头在交叉发生的位置上方绘制 

我发布了我期望得到的结果的图像

解决方案

  • 对于 Arrow x_start x_end 必须为 datetime 格式,而不是 string dataframe .
    • x_start = pd.to_datetime('2010-10-09')
    • 箭头的坐标可能不会作为数据框传递,而必须作为单个值传递,这在下面的循环中完成.
      • x _ 是日期时间索引中的日期.
      • y _ 是y交点,可能会向其添加偏移量(例如 +5 )
  • 使用了

    更新

    • 在以下部分中:
      • x_start = df ['Date'] &使用 x_end = df ['Date'] 代替 x _ ,它应该是单个日期值,而不是日期的 Series .
      • for循环将错误的值选择为 x _ y _ .在我原来的 match 中,日期在索引中,但是您的 match 在列中有日期.

      match = df [(((df.short_ema.shift(1)&d; df.long_ema.shift(1))&(df.short_ema.shift(2)< df.long_ema.shift(2)))]对于match _ [['Date','long_ema']].iterrows()中的x_,(y_,_):打印(x_,y_)p.add_layout(Arrow(end = VeeHead(line_color ="blue",line_width = 4,fill_color ='blue'),line_color =蓝色",line_width = 4,x_start = df ['Date'],y_start = y_ + 3,x_end = df ['Date'],y_end = y_ + 1)) 

    更正的代码

     匹配_,(x_,y_)在match [[''Date','long_ema']].iterrows()中:打印(x_,y_)p.add_layout(Arrow(end = VeeHead(line_color ="blue",line_width = 4,fill_color ='blue'),line_color =蓝色",line_width = 4,x_start = x_,y_start = y_ + 3,x_end = x_,y_end = y_ + 1))显示(p) 

    I want to draw an arrow or dots when 2 ma cross each other like there will up arrow when short ma cross above long ma etc. but I don't know how to plot when it is datetime. I try to use this code and it just give me errors.

    #plot short ma and long ma
    p.line(df['Date'], df['short_ma'], color='red')
    p.line(df['Date'], df['long_ma'], color='black')
    
    p.add_layout(Arrow(end=VeeHead(size=35), line_color="red",x_start=df['Date'], y_start=df['crossabove']+5, x_end=df['Date'], y_end=df['Date']))
    #the crossabove + 5 so the arrow draw above where the cross occur 
    

    I post an image for the result i was expect the result i expect

    code to plot candlestick chart and add arrow when 2 ema cross

    import pandas as pd
    import numpy as np
    import timeit
    import talib as tb
    import datetime
    import random
    from bokeh.models import Arrow, NormalHead, OpenHead, VeeHead
    from bokeh.plotting import figure, output_file, show
    
    df =  pd.read_csv("D:/testdata/msft.csv") #open csv
    df['short_ema'] = tb.EMA(df['Close'], 100) # short ema
    df['long_ema'] = tb.EMA(df['Close'], 200)  #long ema
    df = df.round(2)    #round to 2
    df['Date']=pd.to_datetime(df['Date'])
    #print(df.dtypes)
    #chart figures
    p = figure(plot_width=1400, plot_height=860,
               x_axis_type='datetime',)
    
    #candle
    inc = df.Close > df.Open
    dec = df.Open > df.Close
    w = 12*60*60*1000 # half day in ms
    p.segment(df['Date'], df['High'], df.Date, df.Low, color="black")
    p.vbar(df['Date'][inc], w, df.Open[inc], df.Close[inc], fill_color="#D5E1DD", line_color="black")
    p.vbar(df['Date'][dec], w, df.Open[dec], df.Close[dec], fill_color="#F2583E", line_color="black")
    
    #ma lines
    p.line(df['Date'], df['short_ema'], color='red')
    p.line(df['Date'], df['long_ema'], color='black')
                                         
    #df.to_csv("D:/testdata/msft result.csv")
    
    #loop for cross add arrow
    match = df[((df.short_ema.shift(1) > df.long_ema.shift(1)) & (df.short_ema.shift(2)< df.long_ema.shift(2)))]
    
    for x_, (y_, _) in match[['Date', 'long_ema']].iterrows():
        print(x_,y_)
        p.add_layout(Arrow(end=VeeHead(line_color="blue", line_width=4, fill_color='blue'),
                           line_color='blue', line_width=4,
                           x_start=df['Date'], y_start= y_ + 3,
                           x_end=df['Date'], y_end=y_ + 1))
    
    show(p)
    

    解决方案

    • For an Arrow, x_start and x_end must be a datetime format, not a string or a dataframe.
      • x_start=pd.to_datetime('2010-10-09')
      • The coordinates for the arrow may not be passed as a dataframe, they must be passed as individual values, which is done in a loop below.
        • x_ is the date from the datetime index.
        • y_ is the y intersection point, to which an offset (e.g. +5) may be added
    • This example was used, and arrows were added to it
    • See Labels for text annotations

    import pandas as pd
    from bokeh.models import Arrow, NormalHead, OpenHead, VeeHead, Label
    from bokeh.plotting import figure, show
    from bokeh.sampledata.glucose import data
    from bokeh.io import output_notebook, curdoc  # output_file
    output_notebook()
    
    # for a file, uncomment the next line and output_file in the imports
    # output_file("box_annotation.html", title="box_annotation.py example")
    
    TOOLS = "pan,wheel_zoom,box_zoom,reset,save"
    
    #reduce data size
    data = data.loc['2010-10-06':'2010-10-13'].copy()
    
    # test line to show where glucose and line cross each other
    data['line'] = 170
    
    # determine where the lines cross
    match = data[data.glucose == data.line]
    
    p = figure(x_axis_type="datetime", tools=TOOLS)
    
    p.line(data.index.to_series(), data['glucose'], line_color="gray", line_width=1, legend_label="glucose")
    p.line(data.index.to_series(), data['line'], line_color="purple", line_width=1, legend_label="line")
    
    # add arrows to all spots where the lines are equal
    for x_, (y_, _) in match[['glucose', 'line']].iterrows():
        
        p.add_layout(Arrow(end=VeeHead(line_color="blue", line_width=4, fill_color='blue'),
                           line_color='blue', line_width=4,
                           x_start=x_, y_start= y_ + 130,
                           x_end=x_, y_end=y_ + 5))
    
    p.title.text = "Glucose Range"
    p.xgrid[0].grid_line_color=None
    p.ygrid[0].grid_line_alpha=0.5
    p.xaxis.axis_label = 'Time'
    p.yaxis.axis_label = 'Value'
    
    show(p)
    

    Update

    • In the following section:
      • x_start=df['Date'] & x_end=df['Date'] are used instead of x_, which should be a single date value, not a Series of dates.
      • The for-loop selects the incorrect values to be x_ and y_. In my original match, the dates are in the index, but your match has dates in a column.

    match = df[((df.short_ema.shift(1) > df.long_ema.shift(1)) & (df.short_ema.shift(2)< df.long_ema.shift(2)))]
    
    for x_, (y_, _) in match[['Date', 'long_ema']].iterrows():
        print(x_,y_)
        p.add_layout(Arrow(end=VeeHead(line_color="blue", line_width=4, fill_color='blue'),
                           line_color='blue', line_width=4,
                           x_start=df['Date'], y_start= y_ + 3,
                           x_end=df['Date'], y_end=y_ + 1))
    

    Corrected Code

    for _, (x_, y_) in match[['Date', 'long_ema']].iterrows():
        print(x_,y_)
        p.add_layout(Arrow(end=VeeHead(line_color="blue", line_width=4, fill_color='blue'),
                           line_color='blue', line_width=4,
                           x_start=x_, y_start= y_ + 3,
                           x_end=x_, y_end=y_ + 1))
    
    show(p)
    

    这篇关于如何使用日期时间x轴向散景图中添加具有偏移量的Arrow注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆