当缺少某些值时,如何在烛台图表中添加带有注释的线条?

Posted

技术标签:

【中文标题】当缺少某些值时,如何在烛台图表中添加带有注释的线条?【英文标题】:How to add lines with annotations to candlestick charts when some values are missing? 【发布时间】:2021-04-23 19:04:39 【问题描述】:

我正在尝试使用 Plotly 在我的 OHLC 蜡烛图上叠加一个标记/折线图。

代码

import plotly.graph_objects as go
import pandas as pd
from datetime import datetime

    df = pd.DataFrame(
'index': 0: 0,
  1: 1,
  2: 2,
  3: 3,
  4: 4,
  5: 5,
  6: 6,
  7: 7,
  8: 8,
  9: 9,
  10: 10,
  11: 11,
  12: 12,
  13: 13,
  14: 14,
  15: 15,
  16: 16,
  17: 17,
  18: 18,
  19: 19,
  20: 20,
  21: 21,
  22: 22,
  23: 23,
  24: 24,
 'Date': 0: '2018-09-03',
  1: '2018-09-04',
  2: '2018-09-05',
  3: '2018-09-06',
  4: '2018-09-07',
  5: '2018-09-10',
  6: '2018-09-11',
  7: '2018-09-12',
  8: '2018-09-13',
  9: '2018-09-14',
  10: '2018-09-17',
  11: '2018-09-18',
  12: '2018-09-19',
  13: '2018-09-20',
  14: '2018-09-21',
  15: '2018-09-24',
  16: '2018-09-25',
  17: '2018-09-26',
  18: '2018-09-27',
  19: '2018-09-28',
  20: '2018-10-01',
  21: '2018-10-02',
  22: '2018-10-03',
  23: '2018-10-04',
  24: '2018-10-05',
 'Open': 0: 1.2922067642211914,
  1: 1.2867859601974487,
  2: 1.2859420776367188,
  3: 1.2914056777954102,
  4: 1.2928247451782229,
  5: 1.292808175086975,
  6: 1.3027958869934082,
  7: 1.3017443418502808,
  8: 1.30451238155365,
  9: 1.3110626935958862,
  10: 1.3071041107177734,
  11: 1.3146650791168213,
  12: 1.3166556358337402,
  13: 1.3140604496002195,
  14: 1.3271400928497314,
  15: 1.3080958127975464,
  16: 1.3117163181304932,
  17: 1.3180439472198486,
  18: 1.3169677257537842,
  19: 1.3077707290649414,
  20: 1.3039510250091553,
  21: 1.3043931722640991,
  22: 1.2979763746261597,
  23: 1.2941633462905884,
  24: 1.3022021055221558,
 'High': 0: 1.2934937477111816,
  1: 1.2870012521743774,
  2: 1.2979259490966797,
  3: 1.2959914207458496,
  4: 1.3024225234985352,
  5: 1.3052103519439695,
  6: 1.30804443359375,
  7: 1.3044441938400269,
  8: 1.3120088577270508,
  9: 1.3143367767333984,
  10: 1.3156682252883911,
  11: 1.3171066045761108,
  12: 1.3211784362792969,
  13: 1.3296104669570925,
  14: 1.3278449773788452,
  15: 1.3166556358337402,
  16: 1.3175750970840454,
  17: 1.3196094036102295,
  18: 1.3180439472198486,
  19: 1.3090718984603882,
  20: 1.3097577095031738,
  21: 1.3049719333648682,
  22: 1.3020155429840088,
  23: 1.3036959171295166,
  24: 1.310753345489502,
 'Low': 0: 1.2856279611587524,
  1: 1.2813942432403564,
  2: 1.2793285846710205,
  3: 1.289723515510559,
  4: 1.2918561697006226,
  5: 1.289823293685913,
  6: 1.2976733446121216,
  7: 1.298414707183838,
  8: 1.3027619123458862,
  9: 1.3073604106903076,
  10: 1.3070186376571655,
  11: 1.3120776414871216,
  12: 1.3120431900024414,
  13: 1.3140085935592651,
  14: 1.305841088294983,
  15: 1.3064552545547483,
  16: 1.3097233772277832,
  17: 1.3141123056411743,
  18: 1.309706211090088,
  19: 1.3002548217773438,
  20: 1.3014055490493774,
  21: 1.2944146394729614,
  22: 1.2964619398117063,
  23: 1.2924572229385376,
  24: 1.3005592823028564,
 'Close': 0: 1.292306900024414,
  1: 1.2869019508361816,
  2: 1.2858428955078125,
  3: 1.2914891242980957,
  4: 1.2925406694412231,
  5: 1.2930254936218262,
  6: 1.302643060684204,
  7: 1.3015578985214231,
  8: 1.304546356201172,
  9: 1.311131477355957,
  10: 1.307326316833496,
  11: 1.3146305084228516,
  12: 1.3168463706970217,
  13: 1.3141123056411743,
  14: 1.327087163925171,
  15: 1.30804443359375,
  16: 1.3117333650588991,
  17: 1.3179919719696045,
  18: 1.3172800540924072,
  19: 1.3078734874725342,
  20: 1.3039000034332275,
  21: 1.3043591976165771,
  22: 1.2981956005096436,
  23: 1.294062852859497,
  24: 1.3024225234985352,
 'Pivot Price': 0: 1.2934937477111816,
  1: np.nan,
  2: 1.2793285846710205,
  3: np.nan,
  4: np.nan,
  5: np.nan,
  6: np.nan,
  7: np.nan,
  8: np.nan,
  9: np.nan,
  10: np.nan,
  11: np.nan,
  12: np.nan,
  13: 1.3296104669570925,
  14: np.nan,
  15: np.nan,
  16: np.nan,
  17: np.nan,
  18: np.nan,
  19: np.nan,
  20: np.nan,
  21: np.nan,
  22: np.nan,
  23: 1.2924572229385376,
  24: np.nan)

fig = go.Figure(data=[go.Candlestick(x=df['Date'],
                open=df['Open'],
                high=df['High'],
                low=df['Low'],
                close=df['Close'])])

fig.add_trace(
    go.Scatter(mode = "lines+markers",
        x=df['Date'],
        y=df["Pivot Price"]
    ))

fig.update_layout(
    autosize=False,
    width=1000,
    height=800,)

fig.show()

这是当前图片

这是所需的输出/图像

我想要标记(枢轴)之间的黑线。理想情况下,我还希望每条线旁边有一个值,显示每个枢轴之间的距离,但我不知道该怎么做。

例如,前两个枢轴之间的距离round(abs(1.293494 - 1.279329),3) 返回0.014,所以理想情况下我会喜欢这条线。

第二个是round(abs(1.279329 - 1.329610),3),所以值是0.05。我已经手动编辑了图像并为前两个值添加了线条,以直观地表示我试图实现的目标。

【问题讨论】:

【参考方案1】:

问题似乎是缺失值。所以只需将pandas.Series.interpolate 与fig.add_annotation 结合使用即可:

我还添加了差异注释。肯定有比for loops 更优雅的方法来做到这一点,但它确实可以完成这项工作。如果有什么不清楚的地方请告诉我!

import pandas as pd
import numpy as np
import plotly.graph_objects as go

df = pd.DataFrame(
'index': 0: 0,
  1: 1,
  2: 2,
  3: 3,
  4: 4,
  5: 5,
  6: 6,
  7: 7,
  8: 8,
  9: 9,
  10: 10,
  11: 11,
  12: 12,
  13: 13,
  14: 14,
  15: 15,
  16: 16,
  17: 17,
  18: 18,
  19: 19,
  20: 20,
  21: 21,
  22: 22,
  23: 23,
  24: 24,
 'Date': 0: '2018-09-03',
  1: '2018-09-04',
  2: '2018-09-05',
  3: '2018-09-06',
  4: '2018-09-07',
  5: '2018-09-10',
  6: '2018-09-11',
  7: '2018-09-12',
  8: '2018-09-13',
  9: '2018-09-14',
  10: '2018-09-17',
  11: '2018-09-18',
  12: '2018-09-19',
  13: '2018-09-20',
  14: '2018-09-21',
  15: '2018-09-24',
  16: '2018-09-25',
  17: '2018-09-26',
  18: '2018-09-27',
  19: '2018-09-28',
  20: '2018-10-01',
  21: '2018-10-02',
  22: '2018-10-03',
  23: '2018-10-04',
  24: '2018-10-05',
 'Open': 0: 1.2922067642211914,
  1: 1.2867859601974487,
  2: 1.2859420776367188,
  3: 1.2914056777954102,
  4: 1.2928247451782229,
  5: 1.292808175086975,
  6: 1.3027958869934082,
  7: 1.3017443418502808,
  8: 1.30451238155365,
  9: 1.3110626935958862,
  10: 1.3071041107177734,
  11: 1.3146650791168213,
  12: 1.3166556358337402,
  13: 1.3140604496002195,
  14: 1.3271400928497314,
  15: 1.3080958127975464,
  16: 1.3117163181304932,
  17: 1.3180439472198486,
  18: 1.3169677257537842,
  19: 1.3077707290649414,
  20: 1.3039510250091553,
  21: 1.3043931722640991,
  22: 1.2979763746261597,
  23: 1.2941633462905884,
  24: 1.3022021055221558,
 'High': 0: 1.2934937477111816,
  1: 1.2870012521743774,
  2: 1.2979259490966797,
  3: 1.2959914207458496,
  4: 1.3024225234985352,
  5: 1.3052103519439695,
  6: 1.30804443359375,
  7: 1.3044441938400269,
  8: 1.3120088577270508,
  9: 1.3143367767333984,
  10: 1.3156682252883911,
  11: 1.3171066045761108,
  12: 1.3211784362792969,
  13: 1.3296104669570925,
  14: 1.3278449773788452,
  15: 1.3166556358337402,
  16: 1.3175750970840454,
  17: 1.3196094036102295,
  18: 1.3180439472198486,
  19: 1.3090718984603882,
  20: 1.3097577095031738,
  21: 1.3049719333648682,
  22: 1.3020155429840088,
  23: 1.3036959171295166,
  24: 1.310753345489502,
 'Low': 0: 1.2856279611587524,
  1: 1.2813942432403564,
  2: 1.2793285846710205,
  3: 1.289723515510559,
  4: 1.2918561697006226,
  5: 1.289823293685913,
  6: 1.2976733446121216,
  7: 1.298414707183838,
  8: 1.3027619123458862,
  9: 1.3073604106903076,
  10: 1.3070186376571655,
  11: 1.3120776414871216,
  12: 1.3120431900024414,
  13: 1.3140085935592651,
  14: 1.305841088294983,
  15: 1.3064552545547483,
  16: 1.3097233772277832,
  17: 1.3141123056411743,
  18: 1.309706211090088,
  19: 1.3002548217773438,
  20: 1.3014055490493774,
  21: 1.2944146394729614,
  22: 1.2964619398117063,
  23: 1.2924572229385376,
  24: 1.3005592823028564,
 'Close': 0: 1.292306900024414,
  1: 1.2869019508361816,
  2: 1.2858428955078125,
  3: 1.2914891242980957,
  4: 1.2925406694412231,
  5: 1.2930254936218262,
  6: 1.302643060684204,
  7: 1.3015578985214231,
  8: 1.304546356201172,
  9: 1.311131477355957,
  10: 1.307326316833496,
  11: 1.3146305084228516,
  12: 1.3168463706970217,
  13: 1.3141123056411743,
  14: 1.327087163925171,
  15: 1.30804443359375,
  16: 1.3117333650588991,
  17: 1.3179919719696045,
  18: 1.3172800540924072,
  19: 1.3078734874725342,
  20: 1.3039000034332275,
  21: 1.3043591976165771,
  22: 1.2981956005096436,
  23: 1.294062852859497,
  24: 1.3024225234985352,
 'Pivot Price': 0: 1.2934937477111816,
  1: np.nan,
  2: 1.2793285846710205,
  3: np.nan,
  4: np.nan,
  5: np.nan,
  6: np.nan,
  7: np.nan,
  8: np.nan,
  9: np.nan,
  10: np.nan,
  11: np.nan,
  12: np.nan,
  13: 1.3296104669570925,
  14: np.nan,
  15: np.nan,
  16: np.nan,
  17: np.nan,
  18: np.nan,
  19: np.nan,
  20: np.nan,
  21: np.nan,
  22: np.nan,
  23: 1.2924572229385376,
  24: np.nan)

import plotly.graph_objects as go
import pandas as pd
from datetime import datetime

# df=pd.read_csv("for_so.csv")
fig = go.Figure(data=[go.Candlestick(x=df['Date'],
# fig = go.Figure(data=[go.Candlestick(x=df.index,
                open=df['Open'],
                high=df['High'],
                low=df['Low'],
                close=df['Close'])])

# some calculations
df_diff = df['Pivot Price'].dropna().diff().copy()
df2 = df[df.index.isin(df_diff.index)].copy()
df2['Price Diff'] = df['Pivot Price'].dropna().values

fig.add_trace(
    go.Scatter(mode = "lines+markers",
        x=df['Date'],
        y=df["Pivot Price"]
    ))

fig.update_layout(
    autosize=False,
    width=1000,
    height=800,)

fig.add_trace(go.Scatter(x=df['Date'], y=df['Pivot Price'].interpolate(),
# fig.add_trace(go.Scatter(x=df.index, y=df['Pivot Price'].interpolate(),
                         mode = 'lines',
                         line = dict(color='black')))


def annot(value):
#     print(type(value))
    if np.isnan(value):
        return ''
    else:
        return value
    

j = 0
for i, p in enumerate(df['Pivot Price']):
#      print(p)
#     if not np.isnan(p) and not np.isnan(df_diff.iloc[j]):
    if not np.isnan(p):
#         print(not np.isnan(df_diff.iloc[j]))
        
        fig.add_annotation(dict(font=dict(color='rgba(0,0,200,0.8)',size=12),
                                        x=df['Date'].iloc[i],
#                                          x=df.index[i],
#                                         x = xStart
                                        y=p,
                                        showarrow=False,
                                        text=annot(round(abs(df_diff.iloc[j]),3)),
                                        textangle=0,
                                        xanchor='right',
                                        xref="x",
                                        yref="y"))
        j = j + 1
fig.update_xaxes(type='category')
fig.show()

【讨论】:

【参考方案2】:

问题似乎缺少值,情节难以处理。有了这个技巧,你只能画点;

has_value = ~df["Pivot Price"].isna()

import plotly.graph_objects as go
import pandas as pd
from datetime import datetime

df=pd.read_csv("notebooks/for_so.csv")
fig = go.Figure(data=[go.Candlestick(x=df['Date'],
                open=df['Open'],
                high=df['High'],
                low=df['Low'],
                close=df['Close'])])

fig.add_trace(
    go.Scatter(mode = 'lines',
               x=df[has_value]['Date'],
        y=df[has_value]["Pivot Price"], line='color':'black', 'width':1
    ))

fig.add_trace(
    go.Scatter(mode = "markers",
        x=df['Date'],
        y=df["Pivot Price"]
    ))

fig.update_layout(
    autosize=False,
    width=1000,
    height=800,)

fig.show()

这是为我做的。

【讨论】:

以上是关于当缺少某些值时,如何在烛台图表中添加带有注释的线条?的主要内容,如果未能解决你的问题,请参考以下文章

谷歌图表:向烛台图表添加点

Python matlibplot无法一起构建烛台和ichimoku图表

在烛台图顶部绘制热图

当y轴值较小时,烛台不能很好地显示

使用 PHP 和 SQL 在 highstock 烛台图表中未显示 JSON 数据

使用核心图的气泡图、散点图、烛台图