Feed-Server行情導入介面與Feed-API

張貼日期:Aug 28, 2012 4:25:19 AM

PatsRaw 與 PatsEmu 程式皆可含有Feed Server服務介面, 透過Feed-API輕鬆完成行情導入系統之工作,

可以獨立運行規劃其他市場行情或介接其他資訊源, 也可用來擴展特定商品(例如指數)或衍伸商品(例如指標),

整合進GMDS架構後, 透過GMDS強大之通訊與架構功能快速相容於原本發展在以GMDS為中台架構的各種應用系統中,

立即享用GMDS簡單便利的介接與開發功能, 同時系統提供可擴展自訂欄位的強悍功能, 應用上之變化與自由超乎想像!

PatsEmu-OBG

這邊以PatsEmu-OBG作介紹, 因為PatsEmu-OBG本身亦是GMDS的一種行情導入規格介面,

PatsEmu-OBG使用 /Source 參數 指定來源 TSHS-TfsRaw, 經由 TcpRDS 收取OBG格式的任意TCP Socket Server來源,

Socket Server透過OBG的通訊格式(五檔/十檔)提供資料, 便可將所需行情導入GMDS架構中

OBG Socket Server <-- TcpRDS <-- TSHS-TfsRaw <-- PatsEmu-OBG

由於PatsEmu-OBG指定 /Source 也是行情導入的功能, 因此搭配具有Feed-Server功能時,

若同時設立 /Source 和 /FeedPort 則是混合模式, 也可僅設立其中一種, 若不設 /Source 則是最基本的 Feed-Server 服務程式,

其它具有Feed-Server功能的PatsEmu與PatsRaw則於啟用 /FeedPort 時, 一律為混合模式運行

Feed-Server

所有PatsEmu(含PatsRaw)可使用 /FeedPort 參數功能 指定服務埠號 啟動 Feed-Server 服務

具有Feed-Server功能的PatsEmu/PatsRaw會含有修改行情之介面功能

Feed 命令

透過Feed命令, 可以針對已存在之商品進行欄位資料修改, 其輸入內容格式完全同Feed-API

SaveFieldList 命令

透過SaveFieldList此命令, 可將現行系統的欄位設定定義輸出到指定的檔案, 檔案為.csv檔格式

FieldList

"1","0","S-----------------------------","Symbol","商品代碼"

"92","0","S-------------------","ExtOriSymbol","原始商品代碼"

"93","0","S---------","ExchangeName","交易所別"

"94","0","S---------","ContractName","契約代碼"

"95","0","S---------------","ContractDate","契約日期"

"96","2","I","Quote Bias","時差"

"97","4","U","Quote Date(Dec)","日期"

"98","4","U","Quote Time(Dec)","時間"

"2","3","U","TPP","TicksPerPoint"

"3","0","S---------","TickSize","TickSize"

"4","4","U","ExpiryDate","到期日"

"5","4","U","LastTradeDate","最後交易日"

"6","0","S-------------------","Open","開盤價"

"8","0","S-------------------","High","最高價"

"10","0","S-------------------","Low","最低價"

"12","0","S-------------------","Close","收盤價"

"13","4","U","OpenInterest","未平倉"

"14","0","S-------------------","Reference","參考價"

"16","4","U","Price Time by GMT","報價時間"

"17","4","U","Tick Time by GMT","明細時間"

"60","4","U","Trade Date From Source","來源交易日期"

"61","4","U","Trade Time From Source","來源成交時間"

"18","0","S-------------------","Bid","買價"

"19","4","U","BidVol","買量"

"20","0","S-------------------","Offer","賣價"

"21","4","U","OfferVol","賣量"

"22","0","S-------------------","Last","現價"

"23","4","U","LastVol","現量"

"25","4","U","RFQ","RFQ Volume"

"27","4","U","TotalVol","總量"

"99","3","U","TickCount","成交筆"

"30","0","S-------------------","LimitUp","漲停價"

"32","0","S-------------------","LimitDown","跌停價"

"34","0","S-------------------","ExecutionUp","ExecutionUp"

"36","0","S-------------------","ExecutionDown","ExecutionDown"

"40","0","S-------------------","ImpliedBid","ImpliedBid"

"41","4","U","ImpliedBidVol","ImpliedBidVol"

"42","0","S-------------------","ImpliedOffer","ImpliedOffer"

"43","4","U","ImpliedOfferVol","ImpliedOfferVol"

"44","0","S-------------------","IndBid","IndBid"

"45","4","U","IndBidVol","IndBidVol"

"46","0","S-------------------","IndOffer","IndOffer"

"47","4","U","IndOfferVol","IndOfferVol"

"50","0","S-------------------","CurrStl","CurrStl"

"51","4","U","CurrStlVol","CurrStlVol"

"52","0","S-------------------","SODStl","SODStl"

"53","4","U","SODStlVol","SODStlVol"

"54","0","S-------------------","NewStl","NewStl"

"55","4","U","NewStlVol","NewStlVol"

"10264","1","U","DepthLimit","行情深度"

"100","0","S-------------------","Bid01","買價01"

"101","4","U","Bid01Vol","買量01"

"102","0","S-------------------","Bid02","買價02"

"103","4","U","Bid02Vol","買量02"

"104","0","S-------------------","Bid03","買價03"

"105","4","U","Bid03Vol","買量03"

"106","0","S-------------------","Bid04","買價04"

"107","4","U","Bid04Vol","買量04"

"108","0","S-------------------","Bid05","買價05"

"109","4","U","Bid05Vol","買量05"

"110","0","S-------------------","Bid06","買價06"

"111","4","U","Bid06Vol","買量06"

"112","0","S-------------------","Bid07","買價07"

"113","4","U","Bid07Vol","買量07"

"114","0","S-------------------","Bid08","買價08"

"115","4","U","Bid08Vol","買量08"

"116","0","S-------------------","Bid09","買價09"

"117","4","U","Bid09Vol","買量09"

"118","0","S-------------------","Bid10","買價10"

"119","4","U","Bid10Vol","買量10"

"200","0","S-------------------","Offer01","賣價01"

"201","4","U","Offer01Vol","賣量01"

"202","0","S-------------------","Offer02","賣價02"

"203","4","U","Offer02Vol","賣量02"

"204","0","S-------------------","Offer03","賣價03"

"205","4","U","Offer03Vol","賣量03"

"206","0","S-------------------","Offer04","賣價04"

"207","4","U","Offer04Vol","賣量04"

"208","0","S-------------------","Offer05","賣價05"

"209","4","U","Offer05Vol","賣量05"

"210","0","S-------------------","Offer06","賣價06"

"211","4","U","Offer06Vol","賣量06"

"212","0","S-------------------","Offer07","賣價07"

"213","4","U","Offer07Vol","賣量07"

"214","0","S-------------------","Offer08","賣價08"

"215","4","U","Offer08Vol","賣量08"

"216","0","S-------------------","Offer09","賣價09"

"217","4","U","Offer09Vol","賣量09"

"218","0","S-------------------","Offer10","賣價10"

"219","4","U","Offer10Vol","賣量10"

欄位定義檔格式

a. 欄位內容不可同時含有半形之單引號( ' )與雙引號 ( " )

b. 欄位內容如果有逗號或單引號,則首尾須以雙引號包起來

c. 欄位內容如果有逗號或雙引號,則首尾須以單引號包起來

d. 每行定一個Tag Field, 各欄欄內容以逗號( , )作分隔, 共須5欄依序為

1. Tag代碼, 例如 123 或 "123" 或 '123' 之設定方式皆可

2. 欄位長度, 依欄位格式設定長度

I: 1~8, 如為1代表數值範圍 -128~127

U: 1~8, 如為1代表數值範圍 0~255

S: 須設0, 實際欄位保留長度則是於欄位格式中填足對應長度

3. 欄位格式

I: 有號整數

U: 無號整數

S: 字串

4. 欄位說明1 (會秀在PatsEmu/PatsEmu的商品資料檢視表中)

5. 欄位說明2 (保留,但須存在)

可修改欄位定義檔擴增所需欄位, 透過 /FieldList 參數 可讓PatsEmu/PatsRaw改以指定的檔案作為欄位定義來源

原已定義之欄位與順序儘可能不作變動, 例如#1 固定是全域性的商品代碼作為唯一的識別Key用不應該被調整,

而10檔買賣#100~#119,#200~#219則是順序上已應用中的程式會透過欄位ID計算檔位所以也不應該被調整

Feed-API

與API PktEvCdll.dll 完全相同, 透過指定Feed-Server之Host後便可進行Data Feed了!

使用API函數

//fnPktEvCdll_SendPacket(char cType, const char *cpMessage, int len, bool bRealPush)

//    cType : 僅允許 0x20 ~ 0x7F , 配合Server端定義之配對設計

//    bRealPush : 是否即時發送, true 立即發送, false 儘可能即時發送

例:

char caData[] = "AAA,92=ABC,93=CME,6=156.50,8=158.00,10=155.80";

fnPktEvCdll_SendPacket('F', caData, strlen(caData) + 1, false);

例中參數說明:

bRealPush : 都設 false 即可

cType : 必須設 'F'

caData : AAA為#1商品代碼,後面為針對此商品,各Tag所想更新的內容, 所設商品若不存在系統自動新增

len : caData長度, 須含ZE

API範例程式

產生虛擬資料的程式範例

time_t    currentTime = 0;

struct tm *TM = NULL;

bool bIsConnectionOK = false;

void WWXWinDLLAPI MessageProcessFunction(char cType, const char *cpMessage, int len)

{

    static char buf[8192];

    if (len < sizeof(buf))

    {

        memcpy(buf, cpMessage, len);

        buf[len] = 0;//為了安全,放個ZE,預防資料不是ZE-String

    }

    switch (cType)

    {

        case 'M':

            if ((len == 7) && (strcmp(buf, "Hello~") == 0))

            {

                printf("\r                                                            \r");

                printf("Connection Start\n");

                //這裡設計初連上線(包括有斷線重連)後的一些重置動作

                {//模擬個資料發送

                    static unsigned long uCount = 0; //每次斷線再連會變成一個新商品

                    char caData[4096];

                    sprintf(caData, "ConnectUp(%lu),97=%d%02d%02d,98=%d", ++uCount, (TM->tm_year + 1900), (TM->tm_mon + 1), TM->tm_mday, ((TM->tm_hour * 3600) + (TM->tm_min * 60) + TM->tm_sec));

                    fnPktEvCdll_SendPacket('F', caData, strlen(caData) + 1, false);

                }

                break;

            }

        default:

            printf("\r                                                            \r");

            printf("[%c]len=%d,%s     \n", cType, len, buf);

            break;

    }

}

int main(int argc, char* argv[])

{

//................

        {

            fnPktEvCdll_SetupAppName("TestFeed");

            fnPktEvCdll_Start(caHost, MessageProcessFunction);    //啟動連線

            {

                unsigned long count = 0;

                char *cpConnectionStatus = fnPktEvCdll_GetConnectionStatus();

                //while (count < 1000) //約運行100秒自動結束,Console程式可以按<Ctrl>+'C'中斷

                while (1)

                {

                    time(&currentTime);

                    TM = localtime(&currentTime);

                    cpConnectionStatus = fnPktEvCdll_GetConnectionStatus();

                    bIsConnectionOK = (cpConnectionStatus[1] == 'O');

                    if (!bIsConnectionOK) //未正確連線的狀態才顯示

                        printf("\r%u %s\r", ++count, cpConnectionStatus);

                    else //if (bIsConnectionOK)

                    {//Feed測試, 模擬一些資料來丟

                        static unsigned long uCount = 0;//計次,單純有個資料看

                        char caData[4096];

                        sprintf(caData, "LastUpdate,92=Send%02dTestCount", TM->tm_sec);

                        fnPktEvCdll_SendPacket('F', caData, strlen(caData) + 1, false);

                        //"Send%02dTestCount"用秒產生不同商品的模擬資料(最多會有60個)

                        {//模擬買賣價

                            sprintf(caData, "Send%02dTestCount,18=1.%06d,19=%u", TM->tm_sec, (GetTickCount() % 1000) - 3, GetTickCount() % 29);

                            fnPktEvCdll_SendPacket('F', caData, strlen(caData) + 1, false);

                            sprintf(caData, "Send%02dTestCount,20=1.%06d,21=%u", TM->tm_sec, (GetTickCount() % 1000) + 3, GetTickCount() % 31);

                            fnPktEvCdll_SendPacket('F', caData, strlen(caData) + 1, false);

                        }

                        sprintf(caData, "Send%02dTestCount,13=%lu,22=1.%06d,61=%d%02d%02d%02d,27=%u", TM->tm_sec, ++uCount, GetTickCount() % 10000, TM->tm_hour, TM->tm_min, TM->tm_sec, (GetTickCount() % 1000), GetTickCount() % 1000000);

                        fnPktEvCdll_SendPacket('F', caData, strlen(caData) + 1, false);

                    }

                    Sleep(100);//短暫釋放資源, 由於是CallBack模式這裡並沒有須處理的部份, 只是不讓程式結束而已

                }

            }

            fnPktEvCdll_Stop();

        }

//................

}

範例程式產生之PatsEmu內容

Multi-DB功能

Server設定參見 GroupMap設定 API指定功能參見 2014-07-09

特別欄位說明

#97, #60

十進制數字日期 YYYYMMDD (前端連續0之位數會省略)

#98

十進制數字時間, hhmmss (前端連續0之位數會省略)

#61

十進制數字時間, hhmmssnnn (前端連續0之位數會省略)

#16, #17

日期時間, Unix time(or POSIX time, UTC), 數值內容為自1970-01-01 00:00:00開始所對應的日期時間之總秒數

#96

Bias時區設定, 當Feed API提供 #93 #94 的資料時, 系統會透過Bias設定檔規則, 自動提供該商品所需之 #96 數據內容

因此 #96 應避免透過Feed API來提供數據, 而是於系統上透過Bias設定檔來提供規則 (參考 時區表 , Bias設定檔說明 )

此欄位的提供能透過合適的偏差值設定, 當行情運作時能讓商品有對應交易日(#97)可以參考

#97, #98, #16

此三欄位於任何資料更新時, 系統會同時連帶更新

#97, #98 為依據更新當時之系統時間與 #96 之Bias設定換算所得之結果, 因此 #96必須在所有數據需求之前先提供

#27 TotalVol

當發送此欄位異動時, 系統會連帶更新 #23, #97, #98, #16, #17

如果想另外提供 #23 資訊作取代時, 若發送訊息時將 #23 置於 #27 之前將被系統之計算結果給覆蓋, 可將 #23 置於 #27 之後則能正確取代為所提供之數據

應用實例

市面上投顧最常用的行情系統(證期權股匯市全市場即時行情) 透過Feed-API很容易就可完成轉換...參考Feed-API(AGVS)

延伸架構

MultiSrc多重數據整合程式

延伸應用

機房服務狀態監測