iT邦幫忙

2022 iThome 鐵人賽

DAY 6
1
Software Development

從 Node.js 開發者到量化交易者:打造屬於自己的投資系統系列 第 6

Day 06 - 法人期貨動向:三大法人臺股期貨未平倉

  • 分享至 

  • xImage
  •  

Day 03 - 由上而下投資法:先看大盤趨勢再選股 的內容中,我們曾經提到 系統性風險不可分散風險,無法靠分散投資來消除,但是透過 期貨選擇權 等衍生性金融商品則可以 避險。舉例來說,如果我們擁有股票的現貨部位,當遇到系統風險時,因「覆巢之下無完卵」,即使是體質好的公司,股價也會被向下修正。如果我們在股市下跌前已經先「賣出臺股期貨」建立避險的空方部位,就可以透過期貨部位的獲利來抵消現貨部位的損失,達到消除系統風險的效果。

臺灣期貨與選擇權市場也有三大法人,即 外資投信自營商。先前我們在 Day 04 - 法人主導的市場:三大法人買賣超 的內容已經說明,外資的買賣方向對於臺股有舉足輕重的影響力,因此三大法人在期貨與選擇權市場的留倉部位,外資也是我們主要的觀察對象。因期貨交易的本質是預期商品未來的價格,而法人在股票市場持有現貨部位,所以在期貨市場主要目的是避險,故外資在臺股期貨的佈局,也就透露出外資對臺股後市的看法。

什麼是期貨?

期貨(Futures)是一種衍生性金融商品,期貨契約是買賣雙方約定於未來某一特定時點,以交易當時約定之價格交付某特定商品的一種標準化合約。期貨的英文名稱是未來,意即期貨的交易的本質就是一種買賣預期未來的交易行為。期貨契約會連結一個現貨標的,臺灣期貨交易所的「臺股期貨」商品,交易標的就是「臺灣證券交易所發行量加權股價指數」。

在股票市場,交易單位通常是 1 股或 1 張(1000 股),因股票發行的數量是固定的,所以實際流通在外股數會影響成交量的大小。期貨則是契約,計算的單位是「」,每口契約都涉及一個買方與賣方,只要期貨市場上有買方與賣方,就可以共同創造一口契約,所以沒有籌碼流通的限制。

什麼是期貨未平倉?

在期貨市場中,倉位(Position)代表持有期貨契約的部位,以下是期貨市場中常用的術語:

  • 建倉:初次買進(多方)或賣出(空方)部位。
  • 新倉:買進(多方)或賣出(空方)新的部位。
  • 持倉:持有的部位。
  • 平倉:將持有的部位反向沖銷。
  • 轉倉:將到期月份期貨契約賣出或買進沖銷,並買進或賣出次月份期貨契約。

所謂 未平倉(Open Interest)就是指契約到期日前,尚未結束契約的部位數量,也稱為 留倉。需要注意的是,未平倉量代表多方部位或空方部位還沒有平倉的單邊總數量,並不是兩邊的總和,所以:

總未平倉量 = 多方未平倉量 = 空方未平倉量

外資臺股期貨未平倉淨口數

在三大法人中,外資對股市現貨行情的主導性最強,所以我們也會同時關注外資在期貨市場的佈局。未平倉淨口數,也稱為 淨未平倉口數淨部位,計算方式是未平倉多方口數減去未平倉空方口數,即:

未平倉淨口數 = 未平倉多方口數 - 未平倉空方口數

當未平倉淨口數為正數,代表留倉部位是 淨多單;當未平倉淨口數為負數,代表留倉部位是 淨空單。因此,當外資在臺股期貨的部位是淨多單時,表示比較看多臺股後市;當外資在臺股期貨的部位是淨空單時,表示比較看空臺股後市。

下圖表示 2022 年初至 8 月 31 日的加權指數與外資臺股期貨淨口數的關係。我們可以發現,在 2022 年初加權指數仍在 18,000 點時,外資留有 30,000 口以上的避險空單,隨著行情下跌,外資空單也一路回補。

https://ithelp.ithome.com.tw/upload/images/20220906/20150150Qm9W8ikTXk.png

Source:臺灣證券交易所、臺灣期貨交易所

除了觀察外資在臺股期貨的未平倉淨口數,還可以注意外資在臺股期貨的每日 未平倉淨口數增減。如果未平倉淨口數增加,代表多單增加,當日籌碼面偏多看待;如果未平倉淨口數減少,代表空單增加,當日籌碼面偏空看待。

提供一個有趣的數據,下表是政府宣布第 8 次國安基金進場(2022 年 7 月 12 日)前後三天的外資臺股期貨淨未平倉數據:

日期 加權指數 漲跌 漲跌幅 外資買賣超(億) 外資臺股期貨淨未平倉(口) 淨未平倉增減(口)
2022-07-15 14550.62 112.10 0.78% -111.62 -568 -111
2022-07-14 14438.52 113.84 0.79% 10.84 -457 -3,930
2022-07-13 14324.68 374.06 2.68% 57.87 3,473 -4,061
2022-07-12 13950.62 -389.91 -2.72% -96.85 7,534 4,800
2022-07-11 14340.53 -124.00 -0.86% -30.60 2,734 2,891
2022-07-08 14464.53 128.26 0.89% -39.36 -157 6,391
2022-07-07 14336.27 350.76 2.51% 159.82 -6,548 2,046

Source:臺灣證券交易所、臺灣期貨交易所

在 2022 年 7 月 11 日這天,外資臺股期貨部位已經轉為淨多單。7 月 12 日加權指數大跌 -389.91 點,指數摜破萬四關卡,外資卻在臺股期貨逆勢加碼 4,800 口多單,當日傍晚國安基金發布新聞稿決定啟動安定市場任務。隔日受護盤消息激勵,7 月 12 日加權指數大漲 374.06 點,外資臺股期貨多單也適時獲利了結。此舉可以說是外資「神操作」,也有人認為「凡事有人先知道」,這是市場有趣的地方,就看人們怎麼解讀囉!

查詢三大法人臺股期貨交易資訊

在期交所網站的 交易資訊-三大法人-查詢-區分各期貨契約-依日期 頁面,可以按日查詢三大法人在各期貨契約的交易資訊。

期交所首頁 > 交易資訊 > 三大法人 > 查詢 > 區分各期貨契約 > 依日期

在「交易資訊-三大法人-查詢-區分各期貨契約-依日期」頁面,選取要查詢的「日期」,「契約」選擇「臺股期貨」送出查詢後,就會列出該日三大法人在臺股期貨的交易資訊。

https://ithelp.ithome.com.tw/upload/images/20220906/20150150FeyOGlT1jP.png

我們可以找到外資在臺股期貨的交易口數與契約金額,其中「未平倉餘額」的「多空淨額口數」,就是「未平倉淨口數」。

下載三大法人臺股期貨交易資訊

在期交所網站的 交易資訊-三大法人-下載-區分各期貨契約-依日期 頁面,可以按日期範圍下載三大法人在各期貨契約的交易資訊,期交所以 CSV 檔案格式提供。

期交所首頁 > 交易資訊 > 三大法人 > 下載 > 區分各期貨契約 > 依日期

https://ithelp.ithome.com.tw/upload/images/20220906/20150150RMJVb8AGAg.png

在「交易資訊-三大法人-下載-區分各期貨契約-依日期」頁面,選取「日期(起)」、「日期(迄)」的日期範圍,「契約」選擇「臺股期貨」後,然後點擊下載,就可以取得查詢結果的 CSV 檔案。實際上,這個 HTML Form 表單是使用 POST 方法,向以下位址提交表單請求:

https://www.taifex.com.tw/cht/3/futContractsDateDown

這個表單可設定的欄位如下:

  • queryStartDate:日期(起)。接受的日期格式為 yyyy/MM/dd,如 2022/07/01
  • queryEndDate:日期(迄)。接受的日期格式為 yyyy/MM/dd,如 2022/07/01
  • commodityId:商品契約代號。臺股期貨為 TXF

我們可以打開終端機使用 curl 指令模擬表單請求:

$ curl --request POST \
    --url https://www.taifex.com.tw/cht/3/futContractsDateDown \
    --header 'Content-Type: multipart/form-data' \
    --form queryStartDate=2022/07/01 \
    --form queryEndDate=2022/07/01 \
    --form commodityId=TXF

這裡使用 curl 指令作為範例,也可以透過 PostmanInsomnia 等工具來模擬表單請求。

瞭解下載 CSV 檔案的方式後,我們就可以實作程式取得資料。

以上透過 curl 指令取得的資料在中文部分可能會呈現亂碼,不過別擔心,我們在實作程式時會處理編碼問題。

實作:取得三大法人臺股期貨淨未平倉口數

在期交所取得的盤後資訊大都是 CSV 檔案,因此我們先安裝 csvtojson 套件,方便將 CSV 格式資料轉為 JSON 格式。

$ npm install --save csvtojson

套件安裝完成後,我們新增一個 TaifexScraperService 表示從期交所取得資料的服務。打開終端機使用 Nest CLI 建立 TaifexScraperService

$ nest g service scraper/taifex-scraper --flat --no-spec

Nest CLI 會在 src/scraper 目錄下建立 taifex-scraper.service.ts 檔案,並且將 TaifexScraperService 加入至 ScraperModuleproviders 設定。

開啟 src/scraper/taifex-scraper.service.ts 檔案,在 TaifexScraperService 實作 fetchInstInvestorsTxfTrades() 方法,取得三大法人臺股期貨交易資訊:

import * as csvtojson from 'csvtojson';
import * as iconv from 'iconv-lite';
import * as numeral from 'numeral';
import { DateTime } from 'luxon';
import { Injectable } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { firstValueFrom } from 'rxjs';

@Injectable()
export class TaifexScraperService {
  constructor(private httpService: HttpService) {}

  async fetchInstInvestorsTxfTrades(date: string) {
    // 將 `date` 轉換成 `yyyy/MM/dd` 格式
    const queryDate = DateTime.fromISO(date).toFormat('yyyy/MM/dd');

    // 建立 FormData
    const form = new URLSearchParams({
      queryStartDate: queryDate,  // 日期(起)
      queryEndDate: queryDate,    // 日期(迄)
      commodityId: 'TXF',         // 契約-臺股期貨
    });
    const url = 'https://www.taifex.com.tw/cht/3/futContractsDateDown';

    // 取得回應資料並將 CSV 轉換成 JSON 格式及正確編碼
    const responseData = await firstValueFrom(this.httpService.post(url, form, { responseType: 'arraybuffer' }))
      .then(response => csvtojson({ noheader: true, output: 'csv' }).fromString(iconv.decode(response.data, 'big5')));

    // 若該日期非交易日或尚無資料則回傳 null
    const [ fields, dealers, sitc, fini ] = responseData;
    if (fields[0] !== '日期') return null;

    // 合併三大法人交易數據並將 string 型別數字轉換成 number
    const raw = [ ...dealers.slice(3), ...sitc.slice(3), ...fini.slice(3) ]
      .map(data => numeral(data).value());

    const [
      dealersLongTradeVolume,   // 自營商-多方交易口數
      dealersLongTradeValue,    // 自營商-多方交易契約金額(千元)
      dealersShortTradeVolume,  // 自營商-空方交易口數
      dealersShortTradeValue,   // 自營商-空方交易契約金額(千元)
      dealersNetTradeVolume,    // 自營商-多空交易口數淨額
      dealersNetTradeValue,     // 自營商-多空交易契約金額淨額(千元)
      dealersLongOiVolume,      // 自營商-多方未平倉口數
      dealersLongOiValue,       // 自營商-多方未平倉契約金額(千元)
      dealersShortOiVolume,     // 自營商-空方未平倉口數
      dealersShortOiValue,      // 自營商-空方未平倉契約金額(千元)
      dealersNetOiVolume,       // 自營商-多空未平倉口數淨額
      dealersNetOiValue,        // 自營商-多空未平倉契約金額淨額(千元)
      sitcLongTradeVolume,      // 投信-多方交易口數
      sitcLongTradeValue,       // 投信-多方交易契約金額(千元)
      sitcShortTradeVolume,     // 投信-空方交易口數
      sitcShortTradeValue,      // 投信-空方交易契約金額(千元)
      sitcNetTradeVolume,       // 投信-多空交易口數淨額
      sitcNetTradeValue,        // 投信-多空交易契約金額淨額(千元)
      sitcLongOiVolume,         // 投信-多方未平倉口數
      sitcLongOiValue,          // 投信-多方未平倉契約金額(千元)
      sitcShortOiVolume,        // 投信-空方未平倉口數
      sitcShortOiValue,         // 投信-空方未平倉契約金額(千元)
      sitcNetOiVolume,          // 投信-多空未平倉口數淨額
      sitcNetOiValue,           // 投信-多空未平倉契約金額淨額(千元)
      finiLongTradeVolume,      // 外資-多方交易口數
      finiLongTradeValue,       // 外資-多方交易契約金額(千元)
      finiShortTradeVolume,     // 外資-空方交易口數
      finiShortTradeValue,      // 外資-空方交易契約金額(千元)
      finiNetTradeVolume,       // 外資-多空交易口數淨額
      finiNetTradeValue,        // 外資-多空交易契約金額淨額(千元)
      finiLongOiVolume,         // 外資-多方未平倉口數
      finiLongOiValue,          // 外資-多方未平倉契約金額(千元)
      finiShortOiVolume,        // 外資-空方未平倉口數
      finiShortOiValue,         // 外資-空方未平倉契約金額(千元)
      finiNetOiVolume,          // 外資-多空未平倉口數淨額
      finiNetOiValue,           // 外資-多空未平倉契約金額淨額(千元)
    ] = raw;

    return {
      date,
      finiLongTradeVolume,
      finiLongTradeValue,
      finiShortTradeVolume,
      finiShortTradeValue,
      finiNetTradeVolume,
      finiNetTradeValue,
      finiLongOiVolume,
      finiLongOiValue,
      finiShortOiVolume,
      finiShortOiValue,
      finiNetOiVolume,
      finiNetOiValue,
      sitcLongTradeVolume,
      sitcLongTradeValue,
      sitcShortTradeVolume,
      sitcShortTradeValue,
      sitcNetTradeVolume,
      sitcNetTradeValue,
      sitcLongOiVolume,
      sitcLongOiValue,
      sitcShortOiVolume,
      sitcShortOiValue,
      sitcNetOiVolume,
      sitcNetOiValue,
      dealersLongTradeVolume,
      dealersLongTradeValue,
      dealersShortTradeVolume,
      dealersShortTradeValue,
      dealersNetTradeVolume,
      dealersNetTradeValue,
      dealersLongOiVolume,
      dealersLongOiValue,
      dealersShortOiVolume,
      dealersShortOiValue,
      dealersNetOiVolume,
      dealersNetOiValue,
    };
  }
}

fetchInstInvestorsTxfTrades() 方法中,需要指定 date 參數,表示要取得三大法人臺股期貨交易資訊的日期。我們定義回傳的物件欄位包含如下:

  • date:日期
  • finiLongTradeVolume:外資-多方交易口數
  • finiLongTradeValue:外資-多方交易契約金額(千元)
  • finiShortTradeVolume:外資-空方交易口數
  • finiShortTradeValue:外資-空方交易契約金額(千元)
  • finiNetTradeVolume:外資-多空交易口數淨額
  • finiNetTradeValue:外資-多空交易契約金額淨額(千元)
  • finiLongOiVolume:外資-多方未平倉口數
  • finiLongOiValue:外資-多方未平倉契約金額(千元)
  • finiShortOiVolume:外資-空方未平倉口數
  • finiShortOiValue:外資-空方未平倉契約金額(千元)
  • finiNetOiVolume:外資-多空未平倉口數淨額
  • finiNetOiValue:外資-多空未平倉契約金額淨額(千元)
  • sitcLongTradeVolume:投信-多方交易口數
  • sitcLongTradeValue:投信-多方交易契約金額(千元)
  • sitcShortTradeVolume:投信-空方交易口數
  • sitcShortTradeValue:投信-空方交易契約金額(千元)
  • sitcNetTradeVolume:投信-多空交易口數淨額
  • sitcNetTradeValue:投信-多空交易契約金額淨額(千元)
  • sitcLongOiVolume:投信-多方未平倉口數
  • sitcLongOiValue:投信-多方未平倉契約金額(千元)
  • sitcShortOiVolume:投信-空方未平倉口數
  • sitcShortOiValue:投信-空方未平倉契約金額(千元)
  • sitcNetOiVolume:投信-多空未平倉口數淨額
  • sitcNetOiValue:投信-多空未平倉契約金額淨額(千元)
  • dealersLongTradeVolume:自營商-多方交易口數
  • dealersLongTradeValue:自營商-多方交易契約金額(千元)
  • dealersShortTradeVolume:自營商-空方交易口數
  • dealersShortTradeValue:自營商-空方交易契約金額(千元)
  • dealersNetTradeVolume:自營商-多空交易口數淨額
  • dealersNetTradeValue:自營商-多空交易契約金額淨額(千元)
  • dealersLongOiVolume:自營商-多方未平倉口數
  • dealersLongOiValue:自營商-多方未平倉契約金額(千元)
  • dealersShortOiVolume:自營商-空方未平倉口數
  • dealersShortOiValue:自營商-空方未平倉契約金額(千元)
  • dealersNetOiVolume:自營商-多空未平倉口數淨額
  • dealersNetOiValue:自營商-多空未平倉契約金額淨額(千元)

完成後,我們只要呼叫 TaifexScraperServicefetchInstInvestorsTxfTrades() 方法,就可以按日期取得三大法人臺股期貨交易資訊。以日期 2022-07-01 為例:

{
  date: '2022-07-01',
  finiLongTradeVolume: 130389,
  finiLongTradeValue: 376680348,
  finiShortTradeVolume: 127583,
  finiShortTradeValue: 368923214,
  finiNetTradeVolume: 2806,
  finiNetTradeValue: 7757134,
  finiLongOiVolume: 35244,
  finiLongOiValue: 99897182,
  finiShortOiVolume: 50537,
  finiShortOiValue: 143119489,
  finiNetOiVolume: -15293,
  finiNetOiValue: -43222307,
  sitcLongTradeVolume: 536,
  sitcLongTradeValue: 1518576,
  sitcShortTradeVolume: 2468,
  sitcShortTradeValue: 6985785,
  sitcNetTradeVolume: -1932,
  sitcNetTradeValue: -5467209,
  sitcLongOiVolume: 24963,
  sitcLongOiValue: 70770105,
  sitcShortOiVolume: 26366,
  sitcShortOiValue: 74747610,
  sitcNetOiVolume: -1403,
  sitcNetOiValue: -3977505,
  dealersLongTradeVolume: 16391,
  dealersLongTradeValue: 47197126,
  dealersShortTradeVolume: 17189,
  dealersShortTradeValue: 49499983,
  dealersNetTradeVolume: -798,
  dealersNetTradeValue: -2302857,
  dealersLongOiVolume: 11621,
  dealersLongOiValue: 32791290,
  dealersShortOiVolume: 7373,
  dealersShortOiValue: 20772017,
  dealersNetOiVolume: 4248,
  dealersNetOiValue: 12019273
}

本日小結

  • 期貨契約是買賣雙方約定於未來某一特定時點,以交易當時約定之價格交付某特定商品的一種標準化合約。
  • 臺股期貨的交易標的是臺灣證券交易所發行量加權股價指數。
  • 期貨未平倉是指期貨契約到期日前,尚未結束契約的部位數量。
  • 外資在臺股期貨未平倉淨口數為正數,表示持淨多單,比較看多臺股後市;外資在臺股期貨未平倉淨口數為負數,表示持淨空單,比較看空臺股後市。
  • 外資在臺股期貨未平倉淨口數增加時,代表多單增加,籌碼偏多看待;外資在臺股期貨未平倉淨口數減少時,代表空單增加,籌碼偏空看待。
  • 瞭解如何在期交所網站上查詢並實作取得三大法人臺股期貨交易資訊的方法。

Node.js 量化投資全攻略:從資料收集到自動化交易系統建構實戰
本系列文已正式出版為《Node.js 量化投資全攻略:從資料收集到自動化交易系統建構實戰》。本書新增了全新內容和實用範例,為你提供更深入的學習體驗!歡迎參考選購,開始你的量化投資之旅!
天瓏網路書店連結:https://www.tenlong.com.tw/products/9786263336070


上一篇
Day 05 - 散戶指標:融資融券餘額
下一篇
Day 07 - 法人動向再確認:三大法人臺指選擇權未平倉
系列文
從 Node.js 開發者到量化交易者:打造屬於自己的投資系統31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言