Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

LsYueh/templar

Open more actions menu

Repository files navigation

TeMPlar

TMP是臺灣證券交易所(TWSE)所使用的專屬傳輸協定,全名為Transaction Message Protocol,用於證券交易相關的訊息傳輸。此工具用於解析TMP提供的委託/成交/申報/檔案傳輸服務訊息內容,將序列化的字串資料轉為非序列化的資料物件後再加以利用。非序列化的資料亦可使用此工具轉換成COBOL可處理的序列化字串資料以用於系統間的資料交換。


流程圖 流程圖


使用方式

const templar = require('templar');

檔案傳輸

const message = templar.parse('20020508595900000084500003M01', { category: 'file-transfer' }

console.log(message);

// Message_t {
//   body: [ { FileCode: 'M01', ResponseMessage: '' } ],
//   raw: Uint8Array('20000008595900845000000011T3000000100'),
//   header: {
//     SubsystemName: '20',
//     FunctionCode: '02',
//     MessageType: '05',
//     MessageTime: 2025-08-17T00:59:59.000Z,
//     StatusCode: '00',
//     SourceId: '0000',
//     ObjectId: '8450',
//     BodyLength: 3
//   },
//   id: 'F060',
//   remained: Uint8Array('')
// }
const message = {
  id: 'F050',
  header: {
    SubsystemName: '20',
    FunctionCode: '02',
    MessageType: '05',
    MessageTime: new Date('2025-08-15T00:59:59.000Z'),
    StatusCode: '00',
    SourceId: '8450',
    ObjectId: '0000',
    // BodyLength: 3, // 會自動根據body變化
  },
  body: [ { FileCode: 'M01', RequestMessage: '' } ],
};

console.log(templar.stringify(message, { category: 'file-transfer' });

// 20020508595900845000000003M01

成交回報

const message = templar.parse('500000085959008450000001', { category: 'report' });

console.log(message);

// Message_t {
//   body: [ { BrokerId: '8450', StartSeq: 1 } ],
//   raw: Uint8Array('500000085959008450000001'),
//   header: {
//     SubsystemName: '50',
//     FunctionCode: '00',
//     MessageType: '00',
//     MessageTime: 2025-08-15T00:59:59.000Z,
//     StatusCode: '00'
//   },
//   id: 'R1',
//   remained: Uint8Array('')
// }
const message = {
  id: 'R1',
  header: {
    SubsystemName: '50',
    FunctionCode: '00',
    MessageType: '00',
    MessageTime: new Date('2025-08-15T00:59:59.000Z'),
    StatusCode: '00'
  },
  body: [ { BrokerId: '8450', StartSeq: 1 } ],
};

console.log(templar.stringify(message, { category: 'report' }));

// '500000085959008450000001'



訊息處理

中文字

交易所的TMP訊息採ASCII編碼,而中文字常用CP950的編碼方式傳入,故在字串切割上一個中文字實算兩個字元空間。

const { parse } = require('./lib/field/parse.js');

test('Parse CP950', async (t) => {
    const buffer = iconv.encode('中文字', 'cp950')
    t.equal(parse({ picStr: 'X(4)', dataType: DATA_TYPE.String, buffer }), '中文');
    t.equal(parse({ picStr: 'X(5)', dataType: DATA_TYPE.String, buffer }), '中文�');
    t.equal(parse({ picStr: 'X(6)', dataType: DATA_TYPE.String, buffer }), '中文字');
});

數字

復刻COBOL文字與數字不同的對齊方式 (文字靠左,數字靠右)。

const { parse } = require('./lib/field/parse.js');

test('Parse PIC 9', async (t) => {
    t.equal(parse({ picStr: '9(5)', dataType: DATA_TYPE.Unsigned, buffer: Buffer.from('12345') }), 12345);
    t.equal(parse({ picStr: '9(5)', dataType: DATA_TYPE.Unsigned, buffer: Buffer.from('123456') }), 23456);
});



COBOL PICTURE (PIC) 子句

目前支援的解析格式

基本:

  • PIC X
  • PIC X(4)
  • PIC 9999
  • PIC 9(4)

混合:

  • PIC 99V99
  • PIC 9(3)V9(2)
  • PIC 9(3)V99
  • PIC S99V99
  • PIC S9(3)V9(2)
  • PIC S9(3)V99



資料型態對照表

字串

COBOL PIC 說明 Node 對應
PIC X(n) 任意字元,長度 n String
PIC A(n) 只允許字母 String
PIC AN(n) 字母 + 數字 String
PIC G(n) 雙位元組字元 (DBCS, EBCDIC) String

整數/小數

COBOL PIC 說明 Node 對應
PIC 9(n) 無號小數,整數 n 位 Number
PIC S9(n) 有號小數,整數 n 位 Number
PIC 9(n)V9(m) 無號小數,整數 n 位,小數 m 位 Number
PIC S9(n)V9(m) 有號小數,整數 n 位,小數 m 位 Number

時間/日期

COBOL PIC 用途 Node 對應
PIC X(8) (YYYYMMDD) 日期 Date
PIC X(6) (HHmmss) 時間 Date
PIC X(9) (HHmmssSSS) 時間 Date
PIC X(14) (YYYYMMDDHHmmss) 時間戳記 Date

JS時間格式表示

在交易所提供的文件中,X(8)對應YYYYMMDDDATE型別,而X(6)X(9)分別對應HHmmss/HHmmssSSSTIME型別。目前Node 22尚未支援Temporal.PlainTimeTemporal.PlainDate,故對於上述資料型態的轉換會統一轉換至JS的Date型別,其中X(6)X(9)會自動補上當下執行的日期。



正負號數字S9字串轉換

Signed overpunch源自Hollerith(赫爾曼·何樂禮)打孔卡編碼,為解決正負號帶來的字元浪費與孔位長度變動的問題,將數字正負號整併至一個孔位解讀。目前已知COBOL的對應關係有:

數 字 ca,
cb,
cm,
cr
Positive
ci,
cn
Positive
ca,
ci,
cn
Negative
cb
Negative
cm
Negative
cr
Negative
0 '0' '{' '}' '@' 'p' ' ' (space)
1 '1' 'A' 'J' 'A' 'q' '!'
2 '2' 'B' 'K' 'B' 'r' '"' (double-quote)
3 '3' 'C' 'L' 'C' 's' '#'
4 '4' 'D' 'M' 'D' 't' '$'
5 '5' 'E' 'N' 'E' 'u' '%'
6 '6' 'F' 'O' 'F' 'v' '&'
7 '7' 'G' 'P' 'G' 'w' ''' (single-quote)
8 '8' 'H' 'Q' 'H' 'x' '('
9 '9' 'I' 'R' 'I' 'y' ')'

選 項 對 應 COBOL
ca RM/COBOL (not RM/COBOL-85)
cb MBP COBOL
ci IBM COBOL (RM/COBOL-85)
cm Micro Focus COBOL
cn NCR COBOL
cr Realia COBOL
cv VAX COBOL

COBOL的S9對正負號數字表示範例 (IBM COBOL)

PIC S9(3) VALUE -123.
TRAILING                 '1'   '2'   'L'
TRAILING SEPARATE  '1'   '2'   '3'   '-'
LEADING                  'J'   '2'   '3'
LEADING SEPARATE   '-'   '1'   '2'   '3'

PIC S9(5)V9 VALUE -12345.6.
TRAILING                '1'  '2'  '3'  '4'  '5'  'O'
TRAILING SEPARATE  '1'  '2'  '3'  '4'  '5'  '6'  '-'
LEADING                 'J'  '2'  '3'  '4'  '5'  '6'
LEADING SEPARATE   '-'  '1'  '2'  '3'  '4'  '5'  '6'

// IBM COBOL (-dci) and Trailing

'S9(3)V9': '12C' >> 12.3
'S9(3)V9': '12L' >> -12.3

'S9(1)V9': '12C' >> 2.3
'S9(1)V9': '12L' >> -2.3

雖然支援Leading解析,但是會跟某些Overpunch查表定義衝突

// IBM COBOL (-dci) and Leading

'S9(3)V9': 'J23' >> -12.3

'S9(1)V9': 'J23' >> `Exception: Unknown overpunch char: '2'`
// Micro Focus COBOL (-dcm) and Leading

'S9(1)V9': 'J23' >> 2.3



交易所TMP連線架構

PVC:Permanent Virtual Circuit(永久虛擬電路)

實體線

一條實體線上可建立多條PVC,每10條PVC為一組。

PVC

PORT NO
執行功能
01 FT送
02 FT收
03 成交回報
04 委託輸入
05 委託輸入
06 委託輸入
07 委託輸入
08 委託輸入
09 委託輸入

PVC作業時間表

PVC 時 間 執 行 業 務
(01)
FT 送
07:30-19:00 單筆訊息及檔案傳輸
(證券商的傳送線路)
(02)
FT 收
07:30-19:00 單筆訊息及檔案傳輸
(證券商的傳送線路)
(03)
成交回報
08:30-14:40 成交回報接收
(04~09)
委託輸入
08:30-13:30
09:00-12:10
09:00-13:30
13:40-14:30
14:00-14:30
14:30-15:00
15:00-16:00
15:00-16:00
普通股交易
標借交易
盤中零股交易
盤後零股交易
盤後定價交易
證金標購交易
拍賣交易
標購交易

連線子系統

時 間 證 券 商 與 證 交 所
07:30

08:20
1.開機通知作業
2.登錄作業
 準備進入連線狀態
08:20以後 完成連線進入各應用子統統
08:30

19:00
1.進行各項業務
2.若在各項業務處理中發現有任何異常狀況時
 (1)開機通知作業
 (2)登錄作業
  重新進入連線狀態
19:00以後 1.完成各項業務
2.離線作業
 雙方進入離線狀態

訊息格式

MESSAGE ID︰L010、L020、L030、L040、L050、L060、L070、L080


單筆訊息與檔案傳輸通訊協定

時 間 系 統 功 能
07:30

08:00
連線子系統 建立證交所與證券商的電腦連線作業,並進入業務系統。
08:00

19:00
單筆訊息與檔案傳輸子系統
結算作業
申購作業
投資人管理作業
提供交易報表。
補送成交回報資料給證券商。
申購作業。
處理結算業務。
處理申購業務。
處理與投資人管理有關之業務。
19:00 連線子系統 離線

訊息格式 (傳送功能)

MESSAGE ID︰F010、F020、F030(F210)、F040(F220)、F050、F060、F070、F080

訊息格式 (接收功能)

MESSAGE ID︰F090、F100、F110(F230)、F120(F240)、F130、F140、F150、F160

訊息格式

MESSAGE ID︰F170、F180、F190、F200


委託輸入通訊協定

時 間 系 統 功 能
08:00-08:30 連線子系統 建立證交所與證券商的電腦連線作業,並進入業務系統。
08:30-13:30
09:00-12:10
09:00-13:30
13:40-14:30
14:00-14:30
14:30-15:00
15:00-16:00
15:00-16:00
普通股交易子系統
標借交易子系統
盤中零股交易子系統
盤後零股交易子系統
盤後定價交易子系統
證金標購交易子系統
拍賣交易子系統
標購交易子系統
證券商輸入買賣委託,並接受證交所的委託回報。
16:00 連線子系統 結束委託輸入,回到連線子系統。
離線

訊息格式

MESSAGE ID︰T1、T2、T3、T4、T5、T6、T7


成交回報通訊協定

時 間 系 統 功 能
08:00

08:30
連線子系統 建立證交所與證券商的電腦連線作業,並進入業務系統。
08:30

14:00
成交回報接收子系統 接收普通股、盤中零股成交回報資料。
14:00

14:40
成交回報接收子系統 接收盤後定價、盤後零股成交回報資料。
14:40 連線子系統 結束委託輸入,回到連線子系統。
離線

訊息格式

MESSAGE ID︰R1、R2、R3、R4、R5、R6



專案結構

{project-root}
 ├─ cli <-------------------- CLI工具
 │   └─ ...
 ├─ lib
 │   ├─ copybook  <---------- 文件內容轉換
 │   ├─ field  <------------- 欄位轉換
 │   ├─ message  <----------- 訊息解析
 │   ├─ spec
 │   │   ├─ copybook  <------ 各類FILE-CODE檔案內容定義
 │   │   ├─ field  <--------- 欄位基本資料結構
 │   │   ├─ fields  <-------- 欄位組成後定義
 │   │   │   ├─ body
 │   │   │   └─ header.js
 │   │   └─ message  <------- 訊息種類定義
 │   │       ├─ otc.js
 │   │       └─ tse.js
 │   └─ meta.js
 └─ templar.js

結構圖



發布函式庫

  • 打包

    npm pack
    > npm pack
    ...
    ...
    npm notice Tarball Details
    npm notice name: templar
    npm notice version: X.Y.Z
    npm notice filename: templar-X.Y.Z.tgz
    npm notice package size: 374.7 kB
    npm notice unpacked size: 1.6 MB
    npm notice shasum: ba2890224935e4a6a0ecdf91d9585c287a4c3073
    npm notice integrity: sha512-3I975LfONtGXo[...]K22YKPtY5EZcQ==
    npm notice total files: 61
    npm notice
    templar-X.Y.Z.tgz
  • 安裝

    npm install ./templar-X.Y.Z.tgz



其他

參考資料

Morty Proxy This is a proxified and sanitized view of the page, visit original site.