python - 如何将带有偏移量的箭头注释添加到带有日期时间 x 轴的散景图中
问题描述
我想在 2 ma 相互交叉时画一个箭头或点,就像当短 ma 交叉在 long ma 上方时会有向上箭头等,但我不知道如何在日期时间绘制。我尝试使用此代码,但它只会给我错误。
#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
我发布了我期望 结果的图像
绘制烛台图并在 2 EMA 交叉时添加箭头的代码
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)
解决方案
- 对于
Arrow
,x_start
并且x_end
必须是datetime
格式,而不是 astring
或 adataframe
。x_start=pd.to_datetime('2010-10-09')
- 箭头的坐标不能作为数据框传递,它们必须作为单独的值传递,这是在下面的循环中完成的。
x_
是日期时间索引中的日期。y_
是 y 交点,+5
可以向其添加偏移量(例如 )
- 使用了这个例子,并在其中添加了箭头
- 请参阅文本注释的标签
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)
更新
- 在以下部分中:
x_start=df['Date']
&x_end=df['Date']
用于代替x_
,它应该是单个日期值,而不是Series
日期。- 选择不正确的
for-loop
值是x_
和y_
。在我原来match
的 中,日期在索引中,但您match
在列中有日期。
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))
更正的代码
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)
推荐阅读
- mvvm - 模型设计与 DTO
- python - 为什么 (inf + 0j)*1 评估为 inf + nanj?
- jquery - jQuery粘贴在contenteditable中时,防止Chrome文本换行
- iis-express - 使用 IIS Express 进行调试会在 Windows 1809 上启动错误的应用程序
- jenkins - Jenkins 管道上的电子邮件插件
- java - 带有错误消息的单元测试信息
- r - 迭代R中矩阵的列
- arrays - Spark -Scala 嵌套数组 DF - 如何在不改变结构的情况下根据条件更新值?
- angular - ng-bootstrap 点击处理程序在下拉列表中不起作用
- python - 通过 HTTP POST 请求发送文本