MUKI AI Summary
「股票小特助」第五篇介紹如何串接 TradingView 圖表套件,並透過 Server 端呼叫富果 API。首頁功能包括一年內的大盤指數及台股即時報價。使用富果 API 提供的行情和交易 API,並建議未開戶者使用台灣證券交易所的 openAPI。
使用 TradingView 的 Lightweight Charts 套件,方便地將富果 API 的股市資料轉換成圖表。Next.js 的 Server Components 用於從 Server 端呼叫 API,提高首次繪製速度及 SEO。兩種 API 呼叫方法:'use client' 和 'use server',分別適用於前後端的資料處理與畫面渲染。...
我的「股票小特助」系列文,終於來到了第五篇,要正式開始寫 code 啦!
首頁畫面與功能
首頁預期會長這樣,有兩個功能:
- 一年內的大盤指數
富果 API 撈取資料的範圍,最多就是一年,所以我只能放一年的資料 XD - 台股即時報價
目前是先撈出當前的所有價格,並且要「手動」點按鈕更新,還沒串 WebSocket
但在串 WebSocket 之前,會先處理資料,預計加入搜尋、頁碼 ... 等功能。
而今天要分享的,就是首頁上方的圖表,包含我是怎麼用 TradingView 套件製作的,以及怎麼從 client 端 call API 到用 server 端 call 外部 API (富果 API)
富果 API
我使用的股票 API 是富果股市 API,富果 API 分兩塊:
- 行情 API
所有人只要註冊成為富果會員,都能使用 - 交易 API
僅限玉山證券富果帳戶的顧客使用,因為他要串接證券資料。
如果有想要開戶,歡迎使用我的推薦碼,可以一起賺現金回饋唷:f-03feb04
我的股票小特助會同時用到行情 API 與交易 API,但只要不牽扯到交易,大部分的功能都能用行情 API 解決,所以有興趣的朋友可以直接註冊成為富果會員
如果你沒有富果帳戶也不想開戶的話,可以考慮用台灣證券交易所的 openAPI 串接,但我還是會用富果 API 串接,因此如果你想跟著一起練習,可能要請你自行去對照與選擇台灣證券交易所的 API 了唷 QQ。
使用歷史行情 API 取得一年內的股市資料
我在首頁使用的 API 是 Historical Candles,他可以取得 1 年內的上市櫃歷史股價,富果的文件寫得非常詳細,我這邊就不贅述了,直接跟大家分享我使用的參數與股票代碼。
// API 位置,股票代碼 IX0001 const apiTSEIndexUrl = 'https://api.fugle.tw/marketdata/v1.0/stock/historical/candles/IX0001' const fetchTSEIndex = async () => { try { const headers = { 'X-API-KEY': { 你的金鑰 }, 'Content-Type': 'application/json' } const payload = { from: '2023-01-01', to: '2023-06-30', fields: 'open,high,low,close,volume' } const response = await axios.get(apiTSEIndexUrl, { headers: headers, params: payload, }) return response.data.data } catch (error) { console.error('error', error) } }
▼ 用 postman 試打,成功取得資料
使用 TradingView 圖表套件:Lightweight Charts
我之前比較常用 Apache ECharts 圖表套件,但這次要接的是股市資料,所以我就在想,那用 TradingView 提供的圖表套件,會不會不需要太多的設定,就能輕鬆達成我要的圖表資訊呢?
有了這樣的想法,我就決定改用 TradingView 圖表套件試試看,初步試用下來,因為股市資料的格式算通用?所以我從富果 API 拿到的資料,幾乎不需要處理,就能放到 Lightweight Charts 使用,還蠻方便的。不過老實說,Apache ECharts 的文件還是寫得比較清楚,而且還有很多範例可以看 XD
安裝 TradingView Lightweight Charts
▼ 可用 npm 快速安裝,我安裝的版本是 v4.1.1
$ npm install lightweight-charts
▼ 取得股市資料後,用 createChart 初始化圖表,再帶入資料即可
'use client' import { createChart } from 'lightweight-charts' const TSE = () => { const [tseIndex, setTSEIndex] = useState<any>([]) useEffect(() => { // 取得股市資料 setTSEIndex(response) }, []) useEffect(() => { const parentElement = document.getElementById('TSE') as HTMLElement const chartWidth = parentElement.clientWidth const chartHeight = parentElement.clientHeight const chart = createChart(parentElement, { width: chartWidth, height: chartHeight }) const data = tseIndex.map((item) => { // 這邊要做 key mapping,但不複雜 return { time: item.date, open: item.open, close: item.close, high: item.high, low: item.low, value: item.close } } data.reverse() const candlestickSeries = chart.addCandlestickSeries({ upColor: '#EF5350', downColor: '#26A69A', borderVisible: false, wickUpColor: '#EF5350', wickDownColor: '#26A69A' }) candlestickSeries.setData(data) }, [tseIndex]) return ( <> <div id="TSE"></div> </> ) } export default TSE
透過以上程式碼可以發現,處理數據那一段真的簡便很多,也不需要像 Apache ECharts,需要額外寫 function
處理資料
▼ 如果要改成黑底或調整其他的樣式,可以在 createChart()
設定。
改用 Server 端呼叫外部 API
我之所以使用 Next.js 來做 Side Project,就是看中他的 Server Components 功能,我不需要從 Client Call API,資料的事情就交給 Server 端,前端專注處理畫面即可。
接下來要分享的是,我如何把富果的股票 API,改成用 Server 端呼叫
從 Server 端呼叫 API
在 Next.js 裡,我們可以使用 'use client'
以及 'use server'
告訴 Next.js 現在走的是 client component 或是 server component。
你可以往上翻,看到前面我呼叫 api 時的頁面第一行用的是 'use client'
,表示我用 client component;而現在我要使用的是 'use server'
▼ 在 app 資料夾底下,新增檔案 api/TSE.action.tsx
'use server' const apiTSEIndexUrl = 'https://api.fugle.tw/marketdata/v1.0/stock/historical/candles/IX0001' export async function fetchTSEIndex() { try { const headers = { 'X-API-KEY': { 你的金鑰 }, 'Content-Type': 'application/json' } const payload = new URLSearchParams({ from: '2023-01-01', to: '2023-06-30', fields: 'open,high,low,close,volume' }) const response = await fetch(`${apiTSEIndexUrl}?${payload}`, { headers: headers, }) if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json() console.log('data', data) return data.data } catch (error) { console.error('API 請求錯誤:', error) } }
▼ 再回到一開始的 app/component/TSE.tsx 檔案,將原本呼叫 API 的 function
整個拿掉,改從 server 端撈取
'use client' import React, { useEffect, useState, useTransition } from 'react' import { fetchTSEIndex } from '../api/TSE.action' const TSE = () => { const [isPending, startTransition] = useTransition() const [tseIndex, setTSEIndex] = useState<any>([]) useEffect(() => { startTransition(async () => { const response = await fetchTSEIndex() setTSEIndex(response) }) }, []) }
從 fetchTSEIndex 取得資料後,後面的步驟都一樣:將資料處理完成,並用圖表渲染出來
從 Server 端取資料的好處
我們讓網站內容先在 Server 端生成,再傳送至 Client 端,可以加快首次繪製的速度 (First Contentful Paint,FCP),並改善 SEO。
另外我們也能在 Next.js 建立 API,所以可以在同個應用程式中,處理前後端的邏輯,可以有效減少開發的複雜性,例如前面所說,後端專注資料處理,前端專注畫面,讓我們提高開發效率。
後記
在這篇文章中,跟大家分享了如何使用 Next.js 和富果 API 來建立一個股票資訊網站,並分享了兩種呼叫 API 的方法:'use client'
以及 'use server'
,以及 TradingView 的圖表套件:Lightweight Charts 是怎麼接這些資料的。
如果有任何問題或想法,都歡迎留言給我,感謝你的閱讀!