如何使用破折图绘制设置范围(不变)为1小时的OHLC图表?

时间:2019-05-01 15:58:07

标签: python-3.x plotly-dash

这是我的代码:

import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import plotly.graph_objs as go
from dash.dependencies import Input, Output
from datetime import timedelta

file_name = 'temp_copy.csv'
file_path = 'C:\\Users\\xxx\\' + str( file_name )
df = pd.read_csv( 'file_path' )
df['period_close'] = pd.to_datetime( df.period_close )
df['year'] = pd.DatetimeIndex( df['period_close'] ).year
df['month'] = pd.DatetimeIndex( df['period_close'] ).month
df['month_str'] = df.month.apply(str).str.zfill(2)
df['slider_id'] = ( df.year - 2017 ) * 12 + df.month # has to be linear
df['slider_label'] = df.year.apply(str).str.cat( df.month_str ).apply(int)

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

ids = df.slider_id.unique().tolist()
labels = [{ 'label': str( i ) } for i in df.slider_label.unique().tolist() ]

marks = dict(zip( ids, labels )) 

app.layout = html.Div(children=[
    html.H1(children='Hello Dash'),

    html.Div(children='''
        Dash: A web application framework for Python.
    '''),

    dcc.Graph(id="my-graph"),

    html.Div([
        dcc.RangeSlider(id="select-range",
                        marks=marks,
                        min=df.slider_id.min(),
                        max=df.slider_id.max(),
                        value=[7, 8]
                        )
        ], 
        style={"padding-top": 100,}
    )
], className="container")

@app.callback(
    Output("my-graph", 'figure'),
    [Input("select-range", 'value')]
)

def update_figure(selected):
    print( selected[0] )
    fromYear = int( selected[0] / 12 + 2017 )
    fromMonth = int( selected[0] % 12 )
    toYear = int( selected[1] / 12 + 2017 )
    toMonth = int( selected[1] % 12 )

    dff = df[
          ( df.year >= fromYear ) 
        & ( df.month >= fromMonth ) 
        & ( df.year <= toYear )
        & ( df.month <= toMonth )
    ]

    trace = go.Candlestick(x=dff['period_close'],
                           open=dff['price'],
                           high=dff['high'],
                           low=dff['low'],
                           close=dff['close'],
                           increasing={'line': {'color': '#00CC94'}},
                           decreasing={'line': {'color': '#F50030'}}
            )
    return {
        'data': [trace],
        'layout': go.Layout(
            title=f"Prices",
            xaxis={
                'rangeslider': {
                    'visible': True, 
                    'range': [ df.period_close.min(), df.period_close.min() + timedelta(hours=1) ]
                },
                'autorange': True,
            },
            yaxis={
                "title": f'Price'
            }
        )}

server = app.server # the Flask app

if __name__ == '__main__':
    app.run_server(debug=True)

我无法为您提供数据,但数据始于2017年,并提供以下列:开盘价,最高价,最低价,收盘价,期间结束价。我发现Rangeslider不会做我想要的事情,尽管我可能做错了什么。它需要一个int值,以等间距的线性格式表示,因此我只获得了2017年+月的线性范围。

我的问题详细说明: 我有一个庞大的数据集,其中包含从2017年(7月)到2019年1月的1分钟OHLC数据。我希望能够在屏幕上绘制一个1小时(大约)的窗口,下面有一个范围滑块,可以拖动以获取不同的值时间范围。如果可能的话,我希望滑块的宽度不可变(约1小时左右)。

1 个答案:

答案 0 :(得分:0)

我不知道使范围滑块锁定宽度的方法。但是,您可以只使用普通滑块。

dcc.Slider(
        min=0,
        max=19,
        marks={
            x: '{} to {}'.format(x, x+1)
            for x in range(20)
        },
        value=0
    )

当然,您必须更改它,但这是总的想法。那行得通吗?