2013年5月9日 星期四

備份期交所歷史報價

 

接著上一篇取得期交所每日行情資料,將下載來的zip檔解壓縮後可以得到一份rpt檔,這個檔案是當日的報價資料,我們要來處理它了,目標是將報價存入資料庫中,讓我們以後可以隨時整理輸出報價文字檔給前端系統使用。

 

以下用到的資料庫是SQL SERVER 2005,有點久遠的版本,不過已經非常夠用,L 也已經用這個架構收資料很多年了,運作正常。不過話說回來,用資料庫的好處除了報價的儲存整理外,日後的進出紀錄和損益報表也用的上,寫第一次都是麻煩的,不過就是一次工夫。

 

在rpt檔裡的格式有以下欄位,

交易日期,商品代號,交割年月,成交時間,成交價格,成交數量(B+S),近月價格,遠月價格,開盤集合競價,如下圖,

 

期交所RPT

 



那我們就照這個規格來建立資料庫的table,並命名為Daily,用來存每日資料,如下圖,

 

table_daily

 

 

接著要設計一個轉檔程式,先將rpt檔從原本包含日期的檔名改成Daily.rpt,在資料庫選匯入資料,將一般檔案來源的Daily.rpt與TABLE的Daily作對應,如下圖,

rtp與table對應

 

選擇匯入之後,有個設定是儲存封裝,可以利用作為之後的排程,如下圖,

 

儲存SSIS封裝

 

儲存SSIS封裝2

 

將資料轉到TABLE裡後要作些處理,這份原始資料商品種類很多,但我們需要的其實只有台指、電指、金指,其他很少會用到,所以我們將之分類,先設計三個TABLE,TX_Tick、TE_Tick 及 TF_Tick,這三個TABLE的結構如下圖,

 

TX_Tick

 

然後再處理從Daily轉資料到TX_Tick,這邊有些地方要注意,影響我們自己未來使用報價的特性,小小的細節,卻對我們可能有不小的影響,L認為如果不是自己處理報價資料,也不會考慮到這麼多,所以還是自己動手作一次吧。

 

以20130507這一天的資料為例,近月台指期在084500這一秒鐘裡的資料有50筆成交紀錄,084501這一秒鐘裡有12筆成交紀錄。截取部份如圖,

 

084500

 

084500是開盤,有個最大量,那可以直接用作開盤價,084501開始就需要考慮合理性,我們知道期交所公布的TICK檔,比我們實際接收報價的資料要多的多,這表示實際接收時很多會是遺漏的,所以我們在製作上考量而每一秒鐘最具代表性的價格應該是成交量最大的價格,而不是公布的價格順序。

 

以084501為例,如下圖,原始檔資料是上方,若是以原始檔作為報價來源,那這一秒K是收在8170,而下方是L採用的方式,先將同價格的量SUM起來再排序,得到最有代表性的價格是8172,和原始檔就不同了。

 

084501

 

一秒K不同,就等於一分K、五分K,N分K都不同,當然價格都是差一點點,但這個差一點點有沒差,當然有,差很多,報價的原因造成同一個策略在不同機器上會跑出不同結果就是這樣來的,但是我們這樣的方法有沒比較好? 實際上我們接受報價會遺漏的程度如何? 真正會影響多少? 這些很難去評估,只是我們認為這樣的作法比較合理,作到我們該做的調整,也歡迎各位朋友分享建議,交流一下。

 

OK,整理Tick,除了算出比較有代表性的價格外,還可以讓資料數不那麼肥大,接下來要將TABLE Daily匯入資料到TX_Tick裡,就是簡單的語法了,以台指期的為例,

 
select top 1 expireDate,count(*) num 
into #tmp from daily
where commodity = 'TX'
group by expiredate
order by num desc

select Date,dealtime,dealprice,sum(cast(dealvolume as int)) dealvolume
into #tmp1 from Daily
where commodity = 'TX' and NearPrice = '-'
and expiredate = (select expireDate from #tmp) and dealtime = '084500'
group by Date,Commodity,expiredate,dealtime,dealprice
order by Date,Commodity,expiredate,dealtime,dealvolume desc

insert #tmp1
select Date,dealtime,dealprice,sum(cast(dealvolume as int)) dealvolume
from Daily
where commodity = 'TX' and NearPrice = '-'
and expiredate = (select expireDate from #tmp) and dealtime > '084500'
group by Date,Commodity,expiredate,dealtime,dealprice
order by Date,Commodity,expiredate,dealtime,dealvolume

insert TX_Tick(Date,DealTime,dealPrice,Dealvolume)
select * from #tmp1 order by dealtime

 

我們希望在TX_Tick裡只存近月的資料,所以交割年月要知道是近月的,但需要那麼麻煩另外寫TABLE紀錄結算日嗎?

 

L用的是另一個想法,把當天各月份的成交筆數相比,多的那個就是近月了,要注意的是,結算日當天,用的就是遠月的價格,如果這不符合你的需求,就應該再想邏輯判斷近遠月的方式。

 

判斷近月的SQL程式如第一區塊。接著我們先特別把084500的價格先分價加總,將最大量的價格排在第一位,做為開盤價,先存到暫存TABLE #tmp1中,而084500之後的價格也是分價加總,在同一秒中的價格,將最大量的排在最後,作為收盤價。程式碼為第二及第三區塊,其中有個NearPrice = '-',是指它不是跨月價差單。

 

最後,將TABLE #tmp1的資料,存入TX_Tick中,終於完成。之後,要取得歷史資料時匯出的語法也很容易,其中dealvolume/2,是因為期交所的原始量是2口的,我們就再除2,(這也可以在匯入資料時就先處理掉),匯出的SQL程式如下,

 
select date,left(dealtime,6)as dealtime,dealprice,dealvolume/2 dealvolume 
from TX_Tick order by date,serial

 

以上,備份期交所歷史資料完成。若有疑問請輕鬆留言,下一篇會作個整合,讓全部動作自動化。

 

 

沒有留言:

張貼留言