-2

这是一张财务图表。 我希望在画布(图形)图表上绘制数字,将 x 轴作为时间序列,将 y 轴作为价格,我在照片编辑器上设计的示例图像以说明我的观点也共享将用于绘图的数据。

谁能帮助我如何实现这个结果。下面的原始数据在 15 分钟内重新采样,也按价格分组(LTP - 最后交易价格)。

共享原始数据 要绘制的示例图表

4

1 回答 1

1
  • 你所描述的是Scatter(mode="text")这是下面代码中的第二个跟踪
  • 您的模拟图片还会在画布上的文本周围显示线条。这是通过条形跟踪完成的
  • 大部分代码都在模拟您未提供的数据
import pandas as pd
import numpy as np
import plotly.graph_objects as go

# generate some sample data
df = (
    pd.DataFrame(
        index=pd.MultiIndex.from_product(
            [
                np.arange(326.75, 324.95, -0.05),
                pd.date_range("24-sep-2021 09:00", freq="15min", periods=6),
            ],
            names=["LTP", "Time"],
        )
    )
    .reset_index()
    .pipe(
        lambda d: d.assign(
            BuyVolume=np.random.choice(
                np.concatenate([[0], np.random.randint(0, 1000, (len(d)))]),
                len(d),
                p=[0.9] + [0.1 / len(d) for _ in range(len(d))],
            ),
            SellVolume=np.random.choice(
                np.concatenate([[0], np.random.randint(0, 1000, (len(d)))]),
                len(d),
                p=[0.9] + [0.1 / len(d) for _ in range(len(d))],
            ),
        )
    )
)

print(df.head(20).to_markdown())

# create text to appear on chart
df = df.assign(
    plotText=lambda d: d["BuyVolume"].astype(str) + "x" + d["SellVolume"].astype(str)
)
# only rows that have either a buy or sell volume
dfp = df.loc[df["plotText"].ne("0x0")]
# ranges for bars around the text
dfx = dfp.groupby("Time").agg(min=("LTP", "min"), max=("LTP", "max"))
fig = go.Figure(
    [
        go.Bar(
            x=dfx.index,
            y=dfx["max"] - dfx["min"],
            base=dfx["min"],
            marker={"color":"white", "line":{"color":"black", "width":3}}
        ),
        go.Scatter(x=dfp["Time"], y=dfp["LTP"], text=dfp["plotText"], mode="text"),
    ],
)
fig.update_layout(showlegend=False, template="plotly_white")


样本数据

LTP 时间 购买量 卖出量
0 326.75 2021-09-24 09:00:00 0 0
1 326.75 2021-09-24 09:15:00 0 983
2 326.75 2021-09-24 09:30:00 0 74
3 326.75 2021-09-24 09:45:00 0 0
4 326.75 2021-09-24 10:00:00 0 0
5 326.75 2021-09-24 10:15:00 705 0
6 326.7 2021-09-24 09:00:00 0 0
7 326.7 2021-09-24 09:15:00 0 0
8 326.7 2021-09-24 09:30:00 0 0
9 326.7 2021-09-24 09:45:00 0 0
10 326.7 2021-09-24 10:00:00 0 0
11 326.7 2021-09-24 10:15:00 0 593
12 326.65 2021-09-24 09:00:00 0 630
13 326.65 2021-09-24 09:15:00 0 0
14 326.65 2021-09-24 09:30:00 0 968
15 326.65 2021-09-24 09:45:00 0 0
16 326.65 2021-09-24 10:00:00 0 0
17 326.65 2021-09-24 10:15:00 213 0
18 326.6 2021-09-24 09:00:00 0 0
19 326.6 2021-09-24 09:15:00 0 0

阴谋

在此处输入图像描述

堆叠条和悬停

  • 有太多文本无法在图表上绘制
  • 将数据编码成堆积条形图
  • 使用rangeslider,rangeselector来导航xaxis
  • 第一个栏是必需的,因此清楚rangeslider
import pandas as pd
import numpy as np
import plotly.graph_objects as go
import plotly.express as px
from pathlib import Path
import itertools

df = pd.read_csv(
    Path.home().joinpath("Downloads").joinpath("security_chart_WIPRO-EQ.csv")
)
df["Time"] = pd.to_datetime(df["Time"])
# df = df.sort_values("Time").head(200)

fig = px.bar(
    df.groupby("Time", as_index=False).agg(
        base=("LTP", "min"), y=("LTP", lambda s: s.max() - s.min())
    ),
    x="Time",
    y="y",
    base="base",
).update_traces(
    hoverinfo="none",
    hovertemplate="",
    marker={"color": "white", "line": {"color": "black", "width": 1}},
)
fig.add_traces(
    px.bar(
        df.sort_values(["Time", "LTP"])
        .groupby("Time")
        .apply(
            lambda d: d.assign(
                y=(d["LTP"] - d["LTP"].shift()), color=np.linspace(0, 1, len(d))
            )
        ),
        x="Time",
        y="y",
        base="LTP",
        hover_name="volume",
        color="color",
        hover_data={"color": False, "y": False},
    ).data
)
fig.update_layout(
    xaxis={
        "rangeselector": {
            "buttons": [
                dict(count=n, label=f"{n}hrs", step="hour", stepmode="backward")
                for n in [2, 4, 6, 8]
            ]
        },
        "rangeslider": {"visible": True},
        "range": [
            df["Time"].min() - pd.Timedelta(minutes=15),
            df["Time"].min() + pd.Timedelta(hours=4),
        ],
        "rangebreaks": [
            dict(bounds=[16, 9], pattern="hour"),
            dict(bounds=["sat", "mon"]),
        ],
    },
    coloraxis={"showscale": False},
    margin={"l": 0, "r": 0, "t": 0, "b": 0},
    height=800,
)

在此处输入图像描述

于 2021-09-26T09:12:13.553 回答