Я видел этот 3D сюжет. он был анимирован и добавлял новое значение каждый день. я не нашел пример, чтобы воссоздать его с помощью сюжета в python.
График должен начинаться со значения из первой строки (100). Начальное значение должно остаться (без скользящих значений). График должен быть анимирован таким образом, чтобы каждое значение строки добавлялось одно за другим, а ось x расширялась. следующий фрейм данных содержит значения (df_stocks) и даты для построения графика. назначение цветов было бы отличным дополнением. чем больше положительного, тем глубже зеленый, чем больше отрицательного, тем темнее красный.
import yfinance as yf
import pandas as pd
stocks = ["AAPL", "MSFT"]
df_stocks = pd.DataFrame()
for stock in stocks:
df = yf.download(stock, start = "2022-01-01", end = "2022-07-01", group_by='ticker')
df['perct'] = df['Close'].pct_change()
df_stocks[stock] = df['perct']
df_stocks.iloc[0] = 0
df_stocks += 1
df_stocks = df_stocks.cumprod()*100
df_stocks -= 100
Вы можете использовать список go.Frame объектов, как показано в этом примере. Поскольку вы хотите, чтобы линейный график постоянно расширялся наружу, каждый кадр должен включать данные, которые на одну строку длиннее, чем предыдущий кадр, поэтому мы можем использовать понимание списка, например:
frames = [go.Frame(data=
## ...extract info from df_stocks.iloc[:i]
for i in range(len(df_stocks))]
Чтобы добавить цвета к вашим линиям в зависимости от их значения, вы можете использовать биннинг и метки (как в этом ответе), чтобы создать новые столбцы с именами AAPL_color и MSFT_color, которые содержат строку цвета css (например, 'darkorange' или 'green'). Затем вы можете передать информацию из этих столбцов, используя аргумент line=dict(color=...) в каждом go.Scatter3d объекте.
import yfinance as yf
import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
stocks = ["AAPL", "MSFT"]
df_stocks = pd.DataFrame()
for stock in stocks:
df = yf.download(stock, start = "2022-01-01", end = "2022-07-01", group_by='ticker')
df['perct'] = df['Close'].pct_change()
df_stocks[stock] = df['perct']
df_stocks.iloc[0] = 0
df_stocks += 1
df_stocks = df_stocks.cumprod()*100
df_stocks -= 100
df_min = df_stocks[['AAPL','MSFT']].min().min() - 1
df_max = df_stocks[['AAPL','MSFT']].max().max() + 1
labels = ['firebrick','darkorange','peachpuff','palegoldenrod','palegreen','green']
bins = np.linspace(df_min,df_max,len(labels)+1)
df_stocks['AAPL_color'] = pd.cut(df_stocks['AAPL'], bins=bins, labels=labels).astype(str)
df_stocks['MSFT_color'] = pd.cut(df_stocks['MSFT'], bins=bins, labels=labels).astype(str)
frames = [go.Frame(
data=[
go.Scatter3d(
y=df_stocks.iloc[:i].index,
z=df_stocks.iloc[:i].AAPL.values,
x=['AAPL']*i,
name='AAPL',
mode='lines',
line=dict(
color=df_stocks.iloc[:i].AAPL_color.values, width=3,
)
),
go.Scatter3d(
y=df_stocks.iloc[:i].index,
z=df_stocks.iloc[:i].MSFT.values,
x=['MSFT']*i,
name='MSFT',
mode='lines',
line=dict(
color=df_stocks.iloc[:i].MSFT_color.values, width=3,
)
)]
)
for i in range(len(df_stocks))]
fig = go.Figure(
data=list(frames[1]['data']),
frames=frames,
layout=go.Layout(
# xaxis=dict(range=[0, 5], autorange=False),
# yaxis=dict(range=[0, 5], autorange=False),
# zaxis=dict(range=[0, 5], autorange=False),
template='plotly_dark',
legend = dict(bgcolor = 'grey'),
updatemenus=[dict(
type = "buttons",
font=dict(color='black'),
buttons=[dict(label = "Play",
method = "animate",
args=[None])])]
),
)
fig.show()
@Alex рад слышать, что мой ответ был полезен! вы определенно можете внести некоторые эстетические изменения — я считаю, что частотой кадров можно управлять с помощью параметра "duration", как показано здесь
@ Дерек О. Я разделил цвета в отдельный фрейм данных и пытаюсь перебрать акции, чтобы добавить каждую с помощью go.Scatter3d. Мне нужно добавить более 10 акций (что было бы утомительно делать вручную). Где я должен разместить цикл в моем коде? Спасибо за помощь.
@ Алекс, я думаю, вы можете использовать понимание списка внутри аргумента data, когда вы определяете frames. что-то вроде: frames = [go.Frame(data=[go.Scatter3d(...use col as needed...) for col in col_names]) for i in range(len(df_stocks))]
О, круто! сделал мой день! Я играю, чтобы сделать это быстрее, помещая линии ближе к центру и меняя галочки по оси X...