Dash – 股市看盤

      在〈Dash – 股市看盤〉中尚無留言

Dash 不是繪圖套件,而是一個使用 Flask Web 應用框架 + 事件驅動機制 + UI 容器。說的更白話,就是使用 Flask 製作一個網頁,此網頁會因時間觸發而更新裏面的內容,裏面的內容則是由 plotly 等繪圖軟体完成。

Flask 跟 Django 同等地位,都是網頁框架,Flask 屬輕量級的,功能比較陽春。

用途

這種用途就是股市的即時看盤,每秒或每分鐘更新一次。這套件 2017 年推出,被銀行業、証券公司廣泛使用。

官網網址如下 : https://dash.plotly.com/layout

安裝套件

本例需安裝如下套件

pip install dash pandas mysql-connector-python plotly

完整代碼

底下代碼可以每分鐘自動更新美元指標、布蘭特原油、黃金期貨的價格

import time
from datetime import datetime, timedelta

import dash
import yfinance as yf
import plotly.graph_objects as go
from plotly.subplots import make_subplots

from dash import dcc, html
from dash.dependencies import Input, Output
import pandas as pd
# Dash App
#app = Dash(__name__)
app = dash.Dash()
rows=3
cols=2
height=400
app.layout = html.Div([
    html.H2("美元指數 / 布蘭特原油 / 美債 / 黃金期貨"),

    dcc.Graph(
        id="chart",
        style={"height": "900px"}
    ),

    # 每分鐘更新一次
    dcc.Interval(
        id="interval-component",
        interval=60 * 1000,  # 毫秒
        n_intervals=0
    )
])

# 更新圖表
@app.callback(
    Output("chart", "figure"),
    Input("interval-component", "n_intervals")
)
def update_chart(n):
    names = ["美元指數", "布蘭特原油", "黃金期貨", "台股大盤","美債10年期殖利率"]
    tickers = ["DX-Y.NYB", "BZ=F", "GC=F","^TWII","^TNX"]
    colors = ["green", "blue", "#B8860B","brown","orange"]

    fig = make_subplots(
        rows=rows,
        cols=cols,
        subplot_titles=names,
        shared_xaxes=False,
        vertical_spacing=0.08,
        row_heights=[height]*rows,
    )

    for i, ticker in enumerate(tickers):
        current = datetime.now()
        if current.hour >= 14 and i == 3 or i == 4: continue
        row, col=divmod(i, 2)
        df = yf.download(
            ticker,
            period="5d",
            interval="1m",
            progress=False,
            auto_adjust=True
        )
        time.sleep(2)
        if len(df) == 0:continue

        # 移除 MultiIndex
        if hasattr(df.columns, "levels"):
            df.columns = df.columns.droplevel(1)

        # 轉台北時間
        if df.index.tz is not None:
            df.index = df.index.tz_convert("Asia/Taipei")

        current = pd.Timestamp.now(tz="Asia/Taipei")
        if i != 3:
            start = current - timedelta(days=1)
        else:
            year = current.year
            month = current.month
            day = current.day
            start = pd.Timestamp(year = year, month = month, day = day, hour = 9,minute = 0,second = 0, tz = "Asia/Taipei")
        df = df.query("index >= @start")

        print(df)

        fig.add_trace(
            go.Scatter(
                x = df.index,
                y = df["Close"],
                mode = "lines",
                name = names[i],
                line = dict(
                     color=colors[i],
                     width=2
                )
            ),
            row = row + 1,
            col = col + 1
        )
    fig.update_layout(
        height = height * rows,
        showlegend = False,
        hovermode = "x unified",
        #title=f"更新次數:{n}"
        title = f"更新時間:{datetime.now().strftime("%Y-%m-%d %H:%M")}",
    )
    fig.update_xaxes(matches='x')
    return fig

# 啟動
if __name__ == "__main__":
    app.run(
        host="0.0.0.0",
        port=8050,
        debug=True
    )

執行

執行時,只會啟動 Web Server,沒有任何結果,需於瀏覽器輸入如下網址查看

http://localhost:8085

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *