雖然 mplfinance 套件可以繪製精美的 K 線圖, 但那是沒有互動效果的靜態圖表, 也無法直接佈署在網頁應用中. 繪製互動式 K 線圖可以使用 plotly 套件的低階繪圖模組 graph_objects (注意, plotly.express 模組沒有繪製 K 線圖功能, 它主要用來快速繪製常見統計圖表).
本系列測試文章索引參考 :
關於 plotly.graph_objects 用法參考 :
1. 新版 (v4.0+) Plotly 的輸出方式 :
Plotly 的繪圖輸出方式已與以往不同, v4.0 之前的 Plotly 主要商業模式是線上繪圖, 預設會將圖表上傳到他們的雲端伺服器 (Chart Studio), 如果要離線繪圖必須明確呼叫 plotly.offline 模組; 然而 Plotly v4 對原本分散的繪圖方式 (離線 vs 雲端) 進行重整, 採取了離線優先原則, 繪製圖表時不需要再區分線上或離線 (原本的雲端功能被拆分出去變成一個獨立的套件 chart-studio), 改為直接呼叫 Figure 物件的方法來處理 :
- fig.show() : 用於開發過程中的快速預覽 (依據環境自動選擇方式)
- fig.write_html() : 用於產生最終的報告檔案 (於網頁中繪製圖表)
當呼叫 fig.show() 時, Plotly 會自動偵測程式是在 VS Code, Jupyter Notebook, Google Colab 還是純 Python 腳本中執行, 並選擇最適合的方式來顯示圖表. plotly.offline 的功能已經被 fig.write_html() 取代了, 但為了向下相容, Plotly 官方目前仍保留對 plotly.offline.plot() 的支援.
注意, fig.write_html() 只是單純輸出 HTML 檔, 不會自動開啟瀏覽器顯示繪圖結果, 如果希望在存檔後順便開啟瀏覽器展示繪製結果, 可以傳入 auto_open=True 參數 (預設 False), 例如 :
fig.write_html("plot.html", auto_open=True)
或者先呼叫 write_html() 再呼叫 show() :
fig.write_html("plot.html")
fig.show()
除此之外, Plotly v4.0 也把以前的獨立套件 plotly_express 納入主套件中成為 plotly.express 模組, 確立了 Plotly 未來高階 API 使用 plotly.express; 低階 API 使用 plotly. graph_objects 的雙軌應用模式.
2. 建立 CandleStick 物件繪製 K 線圖 :
首先匯入 plotly.graph_objects 模組, 通常取簡名為 go :
import plotly.graph_objects as go
plotly.graph_objects 模組中有一個 Candlestick 用來繪製 K 線圖 :
>>> import plotly.graph_objects as go
>>> dir(go)
['AngularAxis', 'Annotation', 'Annotations', 'Bar', 'Barpolar', 'Box', 'Candlestick', 'Carpet', 'Choropleth', 'Choroplethmap', 'Choroplethmapbox', 'ColorBar', 'Cone', 'Contour', 'Contourcarpet', 'Contours', 'Data', 'Densitymap', 'Densitymapbox', 'ErrorX', 'ErrorY', 'ErrorZ', 'Figure', 'FigureWidget', 'Font', 'Frame', 'Frames', 'Funnel', 'Funnelarea', 'Heatmap', 'Histogram', 'Histogram2d', 'Histogram2dContour', 'Histogram2dcontour', 'Icicle', 'Image', 'Indicator', 'Isosurface', 'Layout', 'Legend', 'Line', 'Margin', 'Marker', 'Mesh3d', 'Ohlc', 'Parcats', 'Parcoords', 'Pie', 'RadialAxis', 'Sankey', 'Scatter', 'Scatter3d', 'Scattercarpet', 'Scattergeo', 'Scattergl', 'Scattermap', 'Scattermapbox', 'Scatterpolar', 'Scatterpolargl', 'Scattersmith', 'Scatterternary', 'Scene', 'Splom', 'Stream', 'Streamtube', 'Sunburst', 'Surface', 'Table', 'Trace', 'Treemap', 'Violin', 'Volume', 'Waterfall', 'XAxis', 'XBins', 'YAxis', 'YBins', 'ZAxis', 'bar', 'barpolar', 'box', 'candlestick', 'carpet', 'choropleth', 'choroplethmap', 'choroplethmapbox', 'cone', 'contour', 'contourcarpet', 'densitymap', 'densitymapbox', 'funnel', 'funnelarea', 'heatmap', 'histogram', 'histogram2d', 'histogram2dcontour', 'icicle', 'image', 'indicator', 'isosurface', 'layout', 'mesh3d', 'ohlc', 'parcats', 'parcoords', 'pie', 'sankey', 'scatter', 'scatter3d', 'scattercarpet', 'scattergeo', 'scattergl', 'scattermap', 'scattermapbox', 'scatterpolar', 'scatterpolargl', 'scattersmith', 'scatterternary', 'splom', 'streamtube', 'sunburst', 'surface', 'table', 'treemap', 'violin', 'volume', 'waterfall']
呼叫 Candlestick 類別的建構式 Candlestick() 會建立一個 Candlestick 物件, 這在 Plotly 文件中被稱為 Trace 物件 (畫布上的數據內容, 例如一組 K 線). 一個完整的 Plotly 圖表 (Figure) 是由 data 和 layout 兩大部分組成的, 而 Candlestick 物件就是放在 data 清單中的一個成員.
Candlestick() 建構式的參數如下表 :
| 參數名稱 | 說明 |
|---|---|
| x | 時間序列數據(通常為日期字串或 datetime 物件)。 |
| open | 開盤價序列 (Open prices)。 |
| high | 最高價序列 (High prices)。 |
| low | 最低價序列 (Low prices)。 |
| close | 收盤價序列 (Close prices)。 |
| increasing_line_color | 上漲時 K 線外框與影線的顏色(例:'red')。 |
| decreasing_line_color | 下跌時 K 線外框與影線的顏色(例:'green')。 |
| name | 此數據序列在圖例中顯示的名稱。 |
| text | 滑鼠懸停時顯示的額外文字內容。 |
| hoverinfo | 設定懸停顯示的資訊內容(如 'all', 'x+y' 等)。 |
| opacity | 設定 K 線圖層的透明度(0.0 到 1.0)。 |
| whiskerwidth | 設定上下影線相對於 K 線實體寬度的比例。 |
其中前 7 個參數 x, open, high, low, close, 以及 increasing_line_color 與 decreasing_line_color (漲跌顏色, 漲紅跌綠) 最常用, 例如 :
>>> price=go.Candlestick(
x=['2026-05-01', '2026-05-02'],
open=[100, 110],
high=[115, 120],
low=[95, 105],
close=[110, 105],
increasing_line_color='red',
decreasing_line_color='green'
)
>>> type(price)
<class 'plotly.graph_objs._candlestick.Candlestick'>
這樣就建立了一個 CandleStick 物件了. 接下來只要將此 trace 放入串列, 傳給 go.Figure() 的 data 參數即可建立 Figure 畫布物件 :
>>> fig=go.Figure(data=[price])
>>> type(fig)
<class 'plotly.graph_objs._figure.Figure'>
最後呼叫 fig.show() 即可展示所繪製之圖表 :
>>> fig.show()
fig.show() 會開啟一個 127.0.0.1:port 的網頁來繪製圖表 :
可見當滑鼠移到 K 棒上時就會動態地彈出其 OHLC 價格資訊. 注意, Plotly 預設會在 K 線圖底下開啟一個範圍滑桿 (RangeSlider 物件), 可透過滑動或縮放來觀察不同時段的價格細節. 若想取消此預設之範圍滑桿, 可呼叫 fig.update_layout() 並傳入 xaxis_rangeslider_visible=False 參數 :
>>> fig.update_layout(xaxis_rangeslider_visible=False)
Figure({
'data': [{'close': [110, 105],
'decreasing': {'line': {'color': 'green'}},
'high': [115, 120],
'increasing': {'line': {'color': 'red'}},
'low': [95, 105],
'open': [100, 110],
'type': 'candlestick',
'x': [2026-05-01, 2026-05-02]}],
'layout': {'template': '...', 'xaxis': {'rangeslider': {'visible': False}}}
})
>>> fig.show()
fig.update_layout() 是 Plotly 中最核心的佈局控制方法, 它負責處理圖表內除了數據本身以外的所有視覺元素, 例如標題, 座標軸, 圖例及畫布大小等, 常用參數如下 :
| 參數名稱 | 說明 |
|---|---|
| title | 圖表標題。可傳入字串或 dict(包含 text, font, x, y 等屬性)。預設為 None。 |
| width / height | 設定畫布的寬度與高度(像素)。預設通常隨容器自動縮放。 |
| xaxis / yaxis | 設定座標軸屬性(如標題、範圍、網格)。例如 xaxis_title='時間'。 |
| xaxis_rangeslider_visible | 設定 X 軸下方的範圍滑桿是否顯示。預設值 True。 |
| showlegend | 是否顯示圖例。預設值:當有多組數據序列時為 True。 |
| legend | 設定圖例的位置與外觀(如 x, y 位置、orientation 'h' 或 'v')。 |
| margin | 設定圖表與邊界的距離。傳入 dict(l, r, t, b) 分別代表左、右、上、下邊距。 |
| template | 設定圖表主題(如 'plotly_dark', 'ggplot2', 'seaborn' 等)。預設為 'plotly'。 |
| hovermode | 設定懸停資訊的觸發模式('x', 'y', 'closest', False)。預設為 'closest'。 |
| font | 設定圖表全域字體(family, size, color)。預設字體依環境而定。 |
| paper_bgcolor | 設定整張畫布(紙張)的背景顏色。預設為 '#fff'。 |
| plot_bgcolor | 設定繪圖區域(座標軸內)的背景顏色。預設為 '#E5ECF6'。 |
這些參數中以 title, width, heigh, 與 showlegend 等最常用.
下面範例從 yfinance 取得股價資料後用 plotly 繪製 K 線圖 :
# plotly_candlestick_1.py
import yfinance as yf
import plotly.graph_objects as go
if __name__ == "__main__":
df=yf.download('0050.tw', start='2026-03-01', end='2026-04-30', auto_adjust=True)
df.columns=df.columns.map(lambda x: x[0])
price=go.Candlestick(
x=df.index,
open=df['Open'],
high=df['High'],
low=df['Low'],
close=df['Close'],
increasing_line_color='red',
decreasing_line_color='green'
)
fig=go.Figure(data=[price])
fig.update_layout(
title='台灣五十股價',
width=800,
height=600,
xaxis_rangeslider_visible=False
)
fig.show()
此處以 width 與 height 參數設定畫布尺寸, 以 title 設定圖表標題, 結果如下 :
3. 移除 K 線圖中的非交易日空格 :
仔細看上面範例中的 K 線圖, 會發現例假日股市休息, 從 yfinance 取得的收盤資料都會跳過這些日期, 只傳回交易日之資料, 但 Plotly 在繪製 K 線圖時會自動把 X 軸的日期序列補齊, 但因為無 OHLC 欄位值, 所以 K 棒為空格, 看起來不連續, 這可以透過呼叫 fig.update_xaxes() 方法, 並傳入rangebreaks 參數來移除, 其值為一個非交易日的日期串列的字典 (鍵為 values), 例如 :
# plotly_candlestick_2.py
import yfinance as yf
import plotly.graph_objects as go
import pandas as pd
if __name__ == "__main__":
df=yf.download('0050.tw', start='2026-03-01', end='2026-04-30', auto_adjust=True)
df.columns=df.columns.map(lambda x: x[0])
price=go.Candlestick(
x=df.index,
open=df['Open'],
high=df['High'],
low=df['Low'],
close=df['Close'],
increasing_line_color='red',
decreasing_line_color='green'
)
fig=go.Figure(data=[price])
# 移除 X 軸的非交易日
date_range=pd.date_range(start=df.index.min(), end=df.index.max())
breaks=date_range[~date_range.isin(df.index)] # 取出 df 空缺之日期
breaks_list=breaks.tolist() # 轉成串列
fig.update_xaxes(rangebreaks=[{'values': breaks_list}]) # 移除非交易日空缺
fig.update_layout(
title='台灣五十股價',
width=800,
height=600,
xaxis_rangeslider_visible=False
)
fig.show()
此處使用 Pandas 的 date_range() 函式取得 df 起迄日期間的所有連續日期序列, 然後用串列運算與 df 比對抓出 df 中空缺之日期即為非交易日, 轉成串列後做為字典 values 鍵之值. 結果如下 :
可見非交易日的空 K 棒已消失, 整個 K 線圖 X 軸看起來是連續無空缺了.
fig.update_xaxes() 常用參數如下表 :
| 參數名稱 | 說明 |
|---|---|
| title | X 軸標題。可傳入字串或 dict(text='...', font=...)。 |
| type | 座標軸類型:'linear' (數值), 'date' (時間), 'category' (類別), 'log' (對數)。 |
| range | 設定顯示範圍 [min, max],對於時間軸 ['2026-01-01', '2026-05-01']。 |
| rangebreaks | 隱藏特定時間區段(如週末或收盤時段)。常用於金融圖表。 |
| rangeslider_visible | 是否顯示底部的時間範圍滑桿(True/False)。 |
| showgrid | 是否顯示垂直網格線(True/False)。預設為 True。 |
| gridcolor / gridwidth | 設定網格線的顏色與寬度。 |
| tickformat | 設定刻度文字格式(如 '%Y-%m-%d' 顯示日期,'.2f' 顯示兩位小數)。 |
| tickangle | 刻度文字的旋轉角度(例如 -45 代表順時針旋轉 45 度)。 |
| side | X 軸的位置。可設定為 'bottom' (預設) 或 'top'。 |
| nticks | 設定刻度的最大數量(Plotly 會嘗試在此範圍內自動分配)。 |
| fixedrange | 是否鎖定縮放(True 代表禁止使用者縮放該軸)。 |
Y 軸設定函式為 fig.update_yaxes(), 參數結構如下 :
| 參數名稱 | 說明 |
|---|---|
| title | Y 軸標題。可設定為字串或 dict(text='...', font=...)。 |
| type | 座標軸類型:'linear' (預設)、'log' (對數軸)、'date'。 |
| range | 設定 Y 軸顯示數值範圍。例如 [0, 1000]。 |
| autorange | 是否自動縮放範圍:True, False 或 'reversed'(數值由大到小反轉)。 |
| showgrid | 是否顯示水平網格線(True/False)。 |
| zeroline | 是否加粗顯示數值為 0 的那條基準線。預設為 True。 |
| tickformat | 刻度數值格式。例如 ',d' (千分位整數)、'.2f' (兩位小數)、'%' (百分比)。 |
| tickprefix / ticksuffix | 在刻度數值前後加上符號(如 tickprefix='$' 或 ticksuffix='元')。 |
| side | Y 軸的位置。可設定為 'left' (預設) 或 'right' (常見於雙 Y 軸設計)。 |
| secondary_y | 多軸圖表中指定此資料是否為第二個 Y 軸(配合 make_subplots 使用)。 |
| fixedrange | 是否固定 Y 軸。設為 True 時,使用者無法透過滑鼠縮放 Y 軸方向。 |






