2014年7月20日

股市自動交易系統(半完成品) - NDDEAgent

開發背景:
在台灣的程式交易中,DDE可以說是無人不知無人不曉,
這鬼東西在我一開始接觸程式交易時,
對大家講的DDE...TS...資料源,根本一頭霧水,
一查資料,乖乖不得了,這鬼東西的書竟然是1994年,
要特別到圖書館借舊書才找得到,電腦書店根本沒有這東西。

用DDE+linux為關鍵字Google,想當然,什麼鬼都沒有,
有一樣疑問的人當然有,有人有發問,但答案就是......No answer.....
因此最終放棄在Linux上呼叫或連結DDE,改在Windows上開發個Agent來做。

一開始,我期望統一用Java來開發,畢竟同語言開發有一致性,好維護,
我當時比較熟的也只有Java,但不幸的,Java的DDE只有JDDE,而且似乎要收費,
因此轉而用跟Java比較相近的c#和NDDE開發。

最早,DDE Agent的開發是一回事,證券軟體的操作是另一回事,
為了自動操作證券軟體,最早我用AutoIt另外寫了一個Stock Server
AutoIt的Stock Server專門用來操作Windows軟體,
DDE Agent則專門透過DDE取得和廣播DDE資訊,
這樣的設計實在太複雜,2個TCP Server各自運作,卻還互相關聯,
因此我將證券軟體啟動的AutoIt程式加入到DDE Agent,
成為了目前版本的NDDE Agent v1.5Beta。

一些網友會問(包括最開始的我),
DDE除了用Excel之外,怎麼接收?
DDE有辦法轉成其他Protocol嗎?
除了TS外,有沒有什麼程式可以同時設定、接收多個資料源?
NDDE Agent就是答案。

NDDE Agent功能與需求:

  1. 要能夠接收DDE訊息
  2. 要能透過TCP廣播DDE訊息
  3. 要能被控制,需要能下指令給NDDE Agent
  4. 要能將DDE註冊到證券軟體
  5. 要能啟動證券軟體(寶來點金靈)
  6. 能否提供個Web介面供呼叫?


NDDE Agent與Java ATS Server架構:

NDDE Agent基本設計:
為了能達到若干需求,NDDE Agent包括下面3個Server:
NDDE Agent的Server基本設計是Telnet Server。

所謂的常駐型Server,意思是Client端連上後,就會保持連線狀態,
直到下指令斷線離開,或者任一方斷線為止。

所謂的問答式Server,意思是這個Server是和Web Server一樣,
用一問一答方式設計,每次連上後詢問,得到答案後,會自動斷線。

在NDDE Agent中,目前裡面包裹了3個TCP Server,作用如下:
Data Server:
負責廣播所有DDE訊息。
Client連上後,所有DDE訊息都會透過它收到,它沒有指令控制,
Client連上後只能被動的接收訊息,要離開,由Client自行斷線即可。

Admin Server:
負責下指令給NDDE Agent。
Client連上後,會保持登入狀態,直到Client下exit指令離開,
Client可以透過它下DDE註冊指令,
Client也可以透過它下啟動點金靈指令,
Client也可以透過它下開啟元大寶來的B2CAPI指令。

Http Admin Server:
負責下指令、詢問NDDE Agent。
這個Server是應朋友需要加上的,透過它可以用Http URL的方式下指令給NDDE Agent,
因為它模擬Http Server,因此每次詢問或下指令後,都會回應並斷線,
它可以提供DDE訊息,但只能透過詢問方式取得,沒有即時性。

NDDE Agent特色:
1. DDE轉Socket程式
2. 支援多DDE註冊
3. Data Server用non-blocking方式開發,理論上在多Client同時接收時,能盡量降低延遲時間

NDDE Agent各部份設計:


NDDE Agent整個程式只有1個.cs檔案,算是整個Java ATS裡面數一數二醜又難看的程式,
好消息是,程式算單純,而且一段一段,分得還算清楚。

程式碼說明:
Admin Server、Http Admin Server各自是一個獨立的Thread,
Admin Server和Http Admin Server都是以TcpListener實做。

Data Server就是NDDE Agent的主程式。

NDde和EWinner的B2CAPI,它們都是設計成Event Handle的形式,
因此裡面像是objEwinner_OnDataResponse、DDEOnAdvise,
就是它們各自的Event Handler function。

DDE Connect Table和DDE Item Table,為了紀錄所有註冊的DDE連線,
因此設計2個Hash Table,各自儲存所有的DDE Connect和所有的DDE Item,
新增、刪除都會紀錄在這2個Hash Table內,然後才下function去註冊和刪除DDE。

AutoIt程式操作,AutoIt本身大概可以寫上一整篇,
先前為了寫AutoIt版的Stock Server,可以說是遇到很多麻煩,
這裡只是為了啟動點金靈,用的不多,就不細說了,
程式裡面有用到的只有2個片段,用au3為關鍵字查詢,就能看到那段內容。
這2段程式功能大意是:
登入:輸入帳號密碼、按確定、等公告、按確定
登出:關閉點金靈程式、按確定

程式啟動說明:
程式啟動後,畫面如下:

它會顯示NDDEAgent的版本號碼和Admin Server、Http Admin Server、Data Server的Port。

Admin Server指令說明:
確定NDDE Agent啟動後,此時用telnet連Admin Server,如下:

此時輸入help指令,按下Enter,如下:

會看到所有指令的一覽、說明、範例。

Http Admin Server指令說明:
和Admin Server類似,但改為瀏覽器輸入,所有指令的格式都如下:
http://[Server IP]:58892/command?[指令]

例如我這邊的環境:
NDDEAgent的IP是192.168.1.12
我要呼叫help指令,瀏覽器輸入如下:
http://192.168.1.12:58892/command?help

截圖如下:

Data Server說明:
程式啟動後,telnet到58888 Port,畫面如下:

當有DDE訊息進入後,就會直接收到,例如:


DDE語法說明:
在NDDE Agent中,針對DDE註冊,需要下指令,語法如下:
add conn DDEService|DDETopic
add item DDEService|DDETopic!DDEItem
add item DDEService|DDETopic!DDEItem
add item DDEService|DDETopic!DDEItem

以點金靈要註冊「中鋼」(2002)的成交價格、開盤價格、最高價格為例,如下:
add conn EWinner|RQ
add item EWinner|RQ!2002.Price
add item EWinner|RQ!2002.Open
add item EWinner|RQ!2002.High

截圖:


要刪除,直接刪除Connect,我記得程式會自動把item統統刪掉。
remove conn EWinner|RQ

程式需求:
執行時,程式需要下面幾個.dll檔案:

  1. 元大寶來的B2CAPI dll檔
  2. AutoIt dll檔
  3. Ndde dll檔和1個xml檔案
  4. 程式使用前,要確定AutoIt的dll有正確註冊
  5. 目前點金靈自動登入的分公司選擇無效,需手動勾選「記憶帳號」,並成功登入,讓點金靈記住分公司資訊後,才能使用NDDEAgent做自動登入的功能


使用平台是選WinXP,理論上應該適用大部分Windows系統,
選WinXP的原因是,它的使用空間最小、系統資源吃得最少。

為何不用Win2K?Win98?
之前一直是Win2K,但Win2K現在證券軟體支援很差了,只能換到WinXP。
Win98,嗯......VirtualBox的支援都很差了,不用說證券軟體了。

程式下載:
講這麼多,程式在哪?程式碼在哪?
http://www.openfoundry.org/of/projects/1818

2 則留言:

Unknown 提到...

http://blog.udn.com/wldtw2008/4124343
這是小弟開發的工具,用telnet 127.0.0.1 4568 就可以收到源源不絕的報價。可以提供給您參考(DDE太老掉牙了,不要自己做,有現成的能用就用,把時間拿去花在更有意義的地方)

Cody 提到...

我沒用過TS,但看起來你的工具很方便。
我會先找TS的快樂版或試用版裝看看,把你的工具環境建立起來玩玩看。