NestJS x Fugle API x TradingView Webhooks:讓富果交易 API 與 TradingView Webhooks 共舞
前言
在當今迅速發展的金融科技領域,程式交易正逐漸成為投資者追求更有效利用市場的重要手段。透過程式化的交易策略,投資者能夠快速做出反應,降低人為因素的介入,並提高交易的效率與準確性。
本文將介紹如何運用 NestJS 整合富果交易 API 與 TradingView Webhooks,打造一個強大的自動化交易平台。透過富果 API,我們能夠執行下單委託,而 TradingView Webhooks 則提供即時的技術分析信號。將這兩者結合,可實現更智慧、更靈活的交易策略。此外,搭配 LINE Notify 應用,可即時接收交易通知,達到全自動、即時的交易決策。
目錄
事前準備
在開始實作前,請先準備好你的開發環境,正如俗話說:「工欲善其事,必先利其器。」
安裝開發環境時,請留意不同作 業系統和版本之間的差異,為確保安裝工具能順利運作,請先確認你的本機執行環境,詳細閱讀官方文件和教學後,再進行安裝及相關設定。
安裝 Node.js
Node.js 是基於 Chrome V8 JavaScript 引擎的開放原始碼、跨平台、可用於伺服器端應用程式的執行環境,它提供事件驅動、非阻塞的I/O 模型,讓你能有效率地建立可擴展的網路應用程式。

首先,你需要安裝 Node.js 環境,請前往 Node.js 官方網站 下載適合你作業系統的安裝檔,通常建議選擇 LTS(Long Term Support)版本,這是官方提供長期支援的穩定版本。當然,如果你想體驗 Node.js 最新功能,也可以選擇下載最新版。

安裝 Nest CLI
Nest(NestJS)是基於 Node.js 和 TypeScript 開發的框架,能幫助你打造高效、可靠且易於擴展的應用程式,它提供了多種實用功能,支援常用的伺服端技術。透過模組化的結構,你能更方便地管理和組織程式碼。

Nest CLI 是由 NestJS 提供的命令列工具,能讓你輕鬆地建立、執行和管理 Nest 應用程式的各種操作。只要你已安裝好 Node.js,打開終端機並執行以下指令,即可安裝 Nest CLI:
$ npm install -g @nestjs/cli
安裝完成後,你可以輸入以下指令,查看 Nest CLI 提供的指令及其使用方式:
$ nest -h

申請 Fugle 交易 API
富果交易 API 是由富果技術團隊與玉山證券合作開發的程式交易 API,你可以在 Windows、Mac 和 Linux 平台上利用富果提供的 SDK,在台灣股票市場進行程式交易,只要你完成開立 玉山證券富果帳戶,並簽署「API 服務申請同意書」,就可以透過線上申請取得交易權限。富果交易 API 同時提供了 Node.js SDK 以及 NestJS 模組,你可以很輕鬆地將它整合至應用程式。

在進行正式交易前,你需要先完成富果交易 API 文件中的 事前準備,包含申請使用交易 API 服務,並且進行模擬測試,以確保程式運作正常;完成這些步驟後,即可獲得正式環境交易權限,開始體驗程式交易所帶來的便捷與效率。
註冊 TradingView 帳號
TradingView 是一個廣受歡迎的金融市場視覺化平台,提供了豐富的圖表和分析工具,以協助交易者進行技術分析和制定交易策略。該平台不僅支援股票市場,還包括外匯、加密貨幣、商品等多種金融市場。

如果你還沒有,請至 TradingView 網站 註冊 一個帳號。
取得 LINE Notify 存取權杖
請確認你已經註冊並認證了你的 LINE 帳號。如果沒有,請先在你的行動裝置下載 LINE App 來完成註冊和認證。
STEP 1:前往 LINE Notify 首頁(notify-bot.line.me),登入你的 LINE 帳號後,點選「個人頁面」。

STEP 2:跳轉頁面後,選擇「發行權杖」。

LINE Notify 授權是基於 OAuth 2.0 的授權碼(Authorization Code)模式。這種授權機制能讓你的應用程式能夠安全地取得其他使用者的同意。如果你只需要將訊息透過 LINE Notify 推播給自己,則直接選擇「發行權杖」即可。
STEP 3:接著會跳出一個表單視窗。請填寫權杖名稱,然後接收通知的聊天室請選擇「透過1對1聊天接收Line Notify的通知」,然後點選「發行」。

STEP 4:LINE Notify 將產生你的個人存取權杖(Access Token)。因為這段代碼只會出現一次,請務必記住這組權杖代碼。

STEP 5:完成後,在「連動的服務」清單裡,就會出現我們剛剛所設定的服務。

建立股票下單程式
我們將建立一個整合富果交易 API 的功能的股票下單程式,你可以透過它進行委託下單、查詢帳務,同時也能隨時收到主動回報通知,這讓你能方便進行股票交易,並即時獲得相關的資訊回應。
股票下單程式的運作
在開始實作前,我們先瞭解股票下單程式如何運作。如系統環境圖(見圖 12)所示,主要包含以下元件:
- 股票下單 API:透過 REST 風格的 HTTP API,進行下單委託與帳務查詢。
- 股票下單服務:整合富果交易 SDK 功能,並且處理 API 請求。當收到富果交易系統的資訊回報時,透過 LINE Notify 傳送通知。

當使用者透過股票下單程式進行下單委託時,其資料處理流程如下:
- ① 使用者向股票下單 API 發送請求,進行下單委託。
- ② 股票下單服務處理使用者向股票下單 API 發送的請求。
- ③ 股票下單服務向富果交易 API 發送下單委託請求。
- ④ 股票下單服務接收富果交易 API 的主動回報訊息。
- ⑤ 收到委託或成交回報時,股票下單服務向 LINE Notify 請求推播訊息。
- ⑥ LINE Notify 收到推播請求後,將訊息發送給使用者。
建立 Nest 應用程式
首先,請打開終端機,使用 Nest CLI 建立一個名為 fugle-tradingview-webhooks 的 Nest 應用程式:
$ nest new fugle-tradingview-webhooks
應用程式建立後,我們需要調整 Nest CLI 預設產生的內容。請將應用程式 AppModule 修改如下:
import { Module } from '@nestjs/common';
@Module({})
export class AppModule {}
我們不會用上預設建立的 AppController 與 AppService,你可以移除相關檔案。
安裝依賴模組
請在終端機輸入以下指令安裝相關套件:
$ npm install --save @fugle/trade @fugle/trade-nest @nestjs/config nest-line-notify class-validator class-transformer
以下是各個套件的簡要說明:
@fugle/trade: 富果交易 API 客戶端函式庫。@fugle/trade-nest: 提供在 NestJS 應用程式中整合@fugle/trade的模組。@nestjs/config: NestJS 的配置模組,可用於管理應用程式中的配置參數。nest-line-notify: 在 NestJS 應用程式中整合 Line Notify 服務的套件,可用於發送 Line 通知。class-validator: 用於驗證和確保類別實例符合特定的規則。class-transformer: 用於在 TypeScript/JavaScript 中實現物件轉換和序列化。
安裝完成後,請在 AppModule 中匯入相關模組:
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { FugleTradeModule } from '@fugle/trade-nest';
import { LineNotifyModule } from 'nest-line-notify';
@Module({
imports: [
ConfigModule.forRoot(),
FugleTradeModule.forRoot({
config: {
apiUrl: process.env.FUGLE_TRADE_API_URL,
certPath: process.env.FUGLE_TRADE_CERT_PATH,
apiKey: process.env.FUGLE_TRADE_API_KEY,
apiSecret: process.env.FUGLE_TRADE_API_SECRET,
aid: process.env.FUGLE_TRADE_AID,
password: process.env.FUGLE_TRADE_PASSWORD,
certPass: process.env.FUGLE_TRADE_CERT_PASS,
},
}),
LineNotifyModule.forRoot({
accessToken: process.env.LINE_NOTIFY_ACCESS_TOKEN,
}),
],
})
export class AppModule {}
設定環境變數
請在專案目錄下建立 .env 檔案,新增以下內容:
FUGLE_TRADE_CERT_PATH=
FUGLE_TRADE_API_URL=
FUGLE_TRADE_API_KEY=
FUGLE_TRADE_API_SECRET=
FUGLE_TRADE_AID=
FUGLE_TRADE_PASSWORD=
FUGLE_TRADE_CERT_PASS=
LINE_NOTIFY_ACCESS_TOKEN=
這些變數所代表的意義與用途如下:
FUGLE_TRADE_API_URL:富果交易 API URL。FUGLE_TRADE_API_KEY:富果交易 API 金鑰。FUGLE_TRADE_API_SECRET:富果交易 API 私鑰。FUGLE_TRADE_AID:證券帳號。FUGLE_TRADE_PASSWORD:帳號密碼。FUGLE_TRADE_CERT_PASS:憑證密碼。FUGLE_TRADE_CERT_PATH:憑證路徑。LINE_NOTIFY_ACCESS_TOKEN:LINE Notify 存取權杖。
你需要將這些環境變數的值填入,才能讓應用程式正常運作。
這些環境變數的值可以從設定檔中取得。你需要從富果交易 API 網站,申請 API 金鑰,並且取得設定檔與憑證。
實作股票下單服務
完成應用程式的基本設定後,我們建立一個模組來整合富果交易 API 的下單功能與帳務服務。請打開終端機,使用 Nest CLI 建立 TraderModule:
$ nest g module trader
我們將在這個模組實作相關功能,讓你能透過SDK操作你的證券帳戶。
整合下單與帳戶服務
我們建立一個服務來負責整合富果交易 SDK 功能。請使用 Nest CLI建立 TraderService:
$ nest g service trader --no-spec
執行後,請開啟建立的檔案,在 TraderServic 中使用 @InjectFugleTrade() 裝飾器依賴注入 FugleTrade,並且新增以下方法:
...
@Injectable()
export class TraderService {
constructor(@InjectFugleTrade() private readonly fugle: FugleTrade) {}
async getOrders() {
return this.fugle.getOrders()
.then(orders => orders.map(order => order.payload))
.catch(err => {
throw new InternalServerErrorException(err.message);
});
}
async placeOrder(placeOrderDto: PlaceOrderDto) {
const payload = placeOrderDto as OrderPayload;
const order = new Order(payload);
return this.fugle.placeOrder(order)
.catch(err => {
throw new InternalServerErrorException(err.message);
});
}
async replaceOrder(id: string, replaceOrderDto: ReplaceOrderDto) {
const orders = await this.fugle.getOrders();
const order = orders.find(order =>
[order.payload.ordNo, order.payload.preOrdNo].includes(id)
);
if (!order) throw new NotFoundException('order not found');
return this.fugle.replaceOrder(order, replaceOrderDto)
.catch(err => {
throw new InternalServerErrorException(err.message);
});
}
async cancelOrder(id: string) {
const orders = await this.fugle.getOrders();
const order = orders.find(order =>
[order.payload.ordNo, order.payload.preOrdNo].includes(id)
);
if (!order) throw new NotFoundException('order not found');
return this.fugle.cancelOrder(order)
.catch(err => {
throw new InternalServerErrorException(err.message);
});
}
async getTransactions(getTransactionsDto: GetTransactionsDto) {
const { range } = getTransactionsDto;
return this.fugle.getTransactions(range)
.catch(err => {
throw new InternalServerErrorException(err.message);
});
}
async getInventories() {
return this.fugle.getInventories()
.catch(err => {
throw new InternalServerErrorException(err.message);
});
}
async getSettlements() {
return this.fugle.getSettlements()
.catch(err => {
throw new InternalServerErrorException(err.message);
});
}
async getBalance() {
return this.fugle.getBalance()
.catch(err => {
throw new InternalServerErrorException(err.message);
});
}
...
}
這些方法對應了富果交易 SDK 提供的下單委託以及帳務查詢等功能:
getOrders():查詢當日證券帳戶內的所有委託,包含預約單、進行中、已成交或已取消的委託單。placeOrder():下一筆交易委託單。非交易時段內下單則為預約單。replaceOrder():修改指定的預約單或進行中委託單的價格或數量。cancelOrder():取消指定的預約單或進行中委託單。getTransactions():取得證券帳戶的交易明細。可選擇不同時間範圍查詢交易記錄。getInventories():查詢證券帳戶的庫存股票資訊。getSettlements():查詢證券帳戶的交割資訊,包含應收及應付款項。getBalance():查詢交割銀行帳戶餘額。
關於這些方法的參數以及回傳內容,請參考 @fugle/trade 的 文件 說明。
處理主動回報訊息
整合富果交易 SDK 功能後,還必須處理主動回報訊息;主動回報是指證券商系統即時向你提供委託或成交回報、異常情況和錯誤訊息等資訊。
為了處理這些主動回報,你可以使用 @fugle/trade-nest 提供的 @Streamer 裝飾器來監聽事件,並執行相應的處理。請在 TraderService 中新增以下方法:
...
@Injectable()
export class TraderService {
...
@Streamer.OnConnect()
async onConnect() {
...
}
@Streamer.OnDisconnect()
async onDisconnect() {
...
}
@Streamer.OnOrder()
async onOrder(data) {
...
}
@Streamer.OnTrade()
async onTrade(data) {
...
}
@Streamer.OnError()
async onError(err) {
...
}
}
這些方法用於處理主動回報事件,包含:
onConnect():當 Streamer 連線建立時的處理。onDisconnect():當 Streamer 連線關閉時的處理。onOrder():收到委託回報時的處理。可根據委託回報的資料組合一個訊息,然後透過 LINE Notify 推播訊息。onTrade()
