C# DDE 用戶端(Client) 的範本(含源碼下載與說明)

參考我原來所寫的一篇:「談談 C#.NET 連結 DDE Server 的設計觀」。 使用 NDde 這個開放源碼,來包裹(Wrap) Win32 APIs 連結 DDE 的通訊底層,使得 .NET-based 的應用程式也可以很便利地連結 DDE Server。

利用幾天的時間,我寫了一個算是比較完整的 C# DDE 用戶端(Client)程式,可以確實連結國內券商所提供的看盤軟體(本身即是 DDE Server)。目前測過包括 “永豐金 eLeader”, “元大 Yeswin”, “日盛 HTS”, “康合 全都賺” 等,均可以正常連結並依據連結項目(Item)持續顯示所跳動(Tick)的值(Value)。 這算是一個簡易的範本,旨在展示利用 .NET OOP 語言可以確實連結 Legacy DDE Server,並進而讓有心的程式交易人員,可以再行擴展,自行撰寫包括報表統計、技術線型分析 等應用。

CsDdeClient(Simple)_ScreenShot-02

我寫的這個簡單 DDE Client,基本功能如下:
 o 可以同時連結多個 DDE Server。
 o 可以同時顯示多個項目(Item)所持續跳動(Tick)的數值(Value)。
 o 可以正確顯示傳輸項目值為中文的編碼。
 o 可以任意地刪除 DDE 連線與項目 的相關資訊。

簡單的源碼說明


DDE 的連線

  1. 看盤軟體本身即為 DDE Server! 這點要先弄清楚。 所以看盤軟體連線至券商的報價伺服器,那是另外一回事,DDE Server 作得好不好,是與看盤軟體本身的穩定度與資源管理有關,而不是與遠端的報價伺服器有關。
  2. 看盤軟體需不需要啟動 Excel? 不需要的,Excel 本身就是 DDE 的用戶端(Client),而且也因為 Excel 的關係,使得任一券商的看盤軟體,都必須符合能讓 Excel 這個用戶端正確地顯示資料。 這個有趣,是 Server 端必須符合 Client 端的傳輸規格,而且不能亂搞。 所以相對來說,對於程式開發人員自行要寫 DDE Client 程式來說,就不用擔心能不能正常顯示所傳輸過來的數值,要是有問題,肯定是自己寫的程式有問題,也方便自行 DEBUG。
  3. DDE Client 要能新增一條 DDE 連線(Connection),建立互動的 Conversation,需要有兩個資訊,一為 “Service”,另一為 “Topic”。 所以,所謂的一條 DDE Connection 定義為:
      1 DDE Connection = 1 Service + 1 Topic

    藉此也可以同時觀察,國內諸多看盤軟體他們對於所謂 DDE Connection 的實作方式。 例如 eLeader 是每一支股票代號即為一條 DDE 連線,所以,若要觀察前百大的期指成分股,就需要建立上百條的 DDE 連線;而 YesWin/康合 全都賺等看盤軟體,則是所有金融商品都只建立一條 DDE 連線而已。 這與穩定度及效能是否有關? 事實上,這應該是說牽涉到 DDE Server 內部關於 DDE 連線的資源控管(Resource Management)問題,一般來說,較為先進的應用伺服器(Application Server),都會提供諸如 “Connection Pooling” 的機制,來有效達成伺服器內資源上的協調。

  4. 連線很簡單,片段的程式碼參考如下:

    DdeClient dc = new DdeClient(service, topic);
    try{
    // Connect to the server. It must be running or an exception will be thrown.
    dc.Connect();
    }catch (Exception thrown){
    MessageBox.Show(“無法連結 DDE Server:” + thrown.Message);
    }

向 DDE Server 索取資料

  • 建立可以相互對話的連線後,該條連線即為 “Stateful” 的狀態,Client 與 Server 可以互相傳遞資料。 Client 端向 DDE Server 要求資料有包括 “Request(同步)”, “OnBeginRequest(非同步)”, “Advise(通告)” 等幾種方式。 對於看盤軟體來說,最必要的就是 “Advise” 這個要求了,當 Client 發出 “StartAdvise” 這個訊息後,DDE Server 爾後只要針對該項目的值一有變更時,就會通知已註冊的 Client 來取得變更的值。

    至於另外兩種需求的訊息,”Poke” 是 Client 端主動送資料給 DDE Server;”Command” 是 Client 端發出命令要求 DDE Server 執行某個指令。 對於看盤軟體來說,是沒有使用到的,所以在我的源碼內,並沒有實作。

  • 國內幾個主要的看盤軟體,對於傳輸資料的實作,似乎有些差異 (但是在 Excel 都可以正常顯示)。 它們必然都有支援 “Advise” 這個訊息(Message),所以才能爾後持續地取得跳動的值。但是,我發現到,YesWin/HTS 這兩個兩個看盤軟體,如果盤後停止跳動時,DDEClient 只利用 “Advise” 這個訊息要求資料的話,是無法取得資料的(但也沒有錯誤);而相對 eLeader 與 全都賺來說,只利用這個訊息,就可以取得資料。 前面說過,Excel 卻都是可以正常顯示的,所以,我後來才加上 “Request” 這個同步要求資料的訊息,才使得所有的看盤軟體都能顯示當停止跳動時,也能取得第一次的值。

    衍生的一個小問題是,eLeader/全都賺 並沒有支持 “Request” 這個訊息的實作,所以若發出 “Request”,會出現錯誤。 這裡我使用的一個小技巧就是,讓它 “throw” 一個例外錯誤(Exception)的 事件(Event),但捕捉(catch)了這個事件後,忽略並不處理它。

  • Client 端首先發出 “StartAdvise”,通告 DDE Server 準備要求索取資料。 所帶的參數隻有一個,就是項目(Item)名稱。 至於 “Service”, “Topic”, “Item” 的名稱如何取得? 一般只要從看盤軟體中,對某個表單的畫面欄位,右鍵 Excel DDE 複製到 Excel 中,即可察看到。

    Client 端另外要做的一件事就是,註冊可以取得來自 DDE Server 所傳來事件(Event)的相關資訊,包括連線資訊與變動的資料等。 註冊的方式就是在 Client 端的程式碼內宣告並實作 Advise 的處理函式。部分的片段程式碼參考如下:


    dc.Advise += client_Advise; //register the Advise process event.
    dc.StartAdvise(item, 1, true, 60000); // Advise Loop

    private void client_Advise(object sender, DdeAdviseEventArgs args) {
    chg_value_row.Cells[“col_iteminfo_value”].Value = args.Text; //顯示變動後的 Item 值.
    }

  • 事實上,後來請生魚片測試時,才發現到,中文編碼有問題! 我並沒有注意到,因為一般看盤軟體的數值都是純數字,但是 “康合 全都賺” 若要求如 期指的合約名稱,會傳回中文。 這裡相當感謝生魚片,他幫我解決了編碼傳輸的問題。 可以參考他寫的一篇:「在.NET正確顯示透過DDE傳送的文字編碼」。 所以在 client_Adivse() 這裡要改為:


    private void client_Advise(object sender, DdeAdviseEventArgs args) {
    int codepage = Encoding.Default.CodePage; //取得編碼的 codpage. 中文 Default: 950
    string data = Encoding.GetEncoding(codepage).GetString(args.Data, 0, args.Data.Length);
    chg_value_row.Cells[“col_iteminfo_value”].Value = data;
    }

UI 的實作問題

老實說,真正困擾我的,是關於 UI 的實作,這對我可以說是相當陌生的。 UI 要能設計的好,大概有兩個重點, 一為對 事件(Event)的控管處理,另一個就是如何讓 UI元件(Component)與所繫結(Binding)的一到多個資料源(Data Source),並保持展示與資料變動的一致性。

在 Windows Form,大概就是 .NET 的 DataGridView 這個 UI 元件最為多樣變化了,如何與 資料源 “Binding” 在一起,維護展示與資料變動的一致性更是個學問。 目前我算是用 “硬作” 的方式,並沒有採取 “Auto Binding” 的自動同步,而是自己利用 HashTable,以 “Service+Topic”, “Item” 當成主要的索引鍵(key),來找出相關於 DDE Connection, DataGridView 所在變動列(或欲刪除列)的位置。

這裡我就是利用 DataGrideView 元件來展示連線與項目等相關資訊的。 一個 Connection 可以 “Hold” 住多個 Item, 所以必然是 “Master/Detail” 這樣的呈現。

※ 執行檔與原始程式碼:
我是上傳至 「聚財網」給有需要的程式交易人員參考研究。若需要該源碼,則需加入成為該網站的會員。
http://www.wearn.com/bbs/topic.asp?topic_id=139666&forum_id=5295&cat_id=19

原來是把該範例的程式碼放置於聚財網,但好像該論壇文章已過期而無法下載。 故改上傳至「程式交易聚寶盆」,供免費下載。

文章導覽

   

共有 60 則迴響

  1. 我也是用C#+NDde.dll去抓期貨商的DDE 遇到了下面這個問題 不知道能否勞駕版大給我點建議或指點

    我個人不喜歡用.StartAdvise這個方法 我有些功能需要把DDE關掉(例如進入市價自動下單的迴圈) 重新叫起會有delay 有時後還會當掉

    我之前引用日盛的DDE 都是用.Request這個方法 需要再去抓 抓日盛的DDE資料都沒問題 抓凱基(台証)的就抓不到了 出現 fail to request訊息 請問版大有什麼辦法可以克服嗎? 用.StartAdvise去抓凱基資料是沒問題的 就.Request失敗

    • 每一家盤商的 DDE 提供方式並不盡相同,好像要個別實驗過才可以。

      也沒有所謂喜好的問題,能連得上讀取資料就好了。

    • 好奇Excel或MC的Universal DDE,為什麼可以在盤後使用Request抓到資料,測試許久,發現單用Request還不足,可以搭配BeginRequest多次異步Request,約嘗試一到二次就都能取得值。

      猜測為了省資源,DDE Server不維護非盤中時時更新的資料
      而程序間通訊又比網路間通訊快,故

      給akai,在同樣情境下Excel或MC的Universal DDE抓得到資料但NDde則否,可以試試改用BeginRequest,也許能改善,否則就要去挖DdemlException裡回傳的Code是什麼樣的DDE錯誤了!

  2. 版大您好,
    爬文爬了好多天感覺您是這方面的專家, 因此向您請較:
    一直在找是否有辦法將 yeswin 的即時資料傳到 excel 做一些即時運算. 但是一些固定欄位的值每天都在變動, 例如我想即時記錄成交量排行前 10 大的股票, 但是滑鼠右鍵按下去只能帶出某支股票的名字, 但下一秒也許成交量第1名就不是他了, 是不是有什麼方法可以達到這個目的? 懇請指導.

  3. 你好~問題改一下~目前跑第一筆ITEM 有值了 ~但第二筆就抓不到了一直顯示(1101.PRICE)!怪怪的~望大大賜教!謝謝~

  4. 您好~想請問在執行時~可新增連線(正常)~但是到了新增項目時~
    發生這段的ERROR ,
    PS:(我的連線字串)STTRADE|DSC!’1101.PRICE’
    ———————————————————
    chg_value_row.Cells[“col_iteminfo_value”].Value = data;

    ERROR:並未將物件參考設定為物件的執行個體
    ——————————————————–
    PS:設中斷時,我看到data 是有值.

  5. Kenming大您好:
    我這邊試著用各期貨商的看盤軟體,但是只有元x的yexxxx可以正常的連線,其它期貨商的都連線失敗,請問板上或是大大有這方面的錯誤訊息嗎?
    謝謝大大!

  6. 您好,拜讀您的文章感到莫大的幫助,謝謝您無私分享。

    想請教您一個問題,關於service, topic, item項目,我是使用永豐e-leader,按您教的方法到Excel抓取三個值,分別填入CATDDE, FUTOPTMXFL0, ShellPrice,然後按「新增連線」即出現錯誤訊息:「無法連結DDE Server:The client failed to connect…Make sure the server application is running and that it supports the specified service name and topic name pair」,我有開啟e-leader,在e-leader上右鍵->dde也能得到即時報價,但為何總是出現錯誤訊息,請問我哪裡錯了呢,謝謝您 (我跑Win 7,會有影響嗎)

    • 顯然就是 topic/service/item 字串有誤,這你用 Excel 連結就可以知道正確性了。

      跑 Win7 不會有任何問題。

  7. 請教Kenming大;
    在日盛HTS中按右鍵,未見Excel DDE功能,是否有其它方法可取得 “Service”, “Topic”, “Item” ?

    Thanks!

  8. 非常感謝您能大方的分享C# DDE的程式碼和說明,我目前也對程式交易有興趣,您的文章對我現在的幫助很大,感謝您!

  9. 能否請kenming兄在通化街開一場收費的下午茶會,直接講授DDE的這一部分?

    • DDE 這一塊實在沒啥好講的勒。

      如果有機會,我到昰想把自己研究開發的工具打包成套件,附在書本上出版,然後有機會辦講座課程,可能更實在些。 !^^

  10. Dear Kenming

    感謝您,Email是我所留的這個msa帳號,昨日也剛好使用NDde.dll,

    嘗試用1 connection (1 service 1 topic)多個item的方式,

    苦思許久,仍尚未試出來,您範例程式中都有提到,

    再麻煩您寄給我了,感恩。

  11. Dear Kenming

    您的詳細解說,對於程式新手的我來說,受益良多,感謝您的無私分享,目前我正在寫DDE 用 vb.net來實作,

    碰到您上面所提的windows Form 的UI難題,剛好您有範例在聚財網上,但,可能時間比較久了,該網址找不到您的文章,

    可否幫忙ㄧ下,感恩。

  12. 請問~
    為什麼,用VB.net接DDE,還是要開EXCEL才行?而且在excel裡,還得要有想連結的資料?
    照理來說,就像您文中所述,應該是VB直接可以接到DDE,而不是透過excel才對
    這是為甚麼?

    同樣的,為了瞭解是不是VB的問題,還是我哪裡弄錯了
    我有下載聚才網的程式碼,執行bin\下的執行檔
    也是一樣,要開excel,數值才會顯示&跳動

    請教有甚麼方式可以不透過EXCEL直接接到DDE嗎?

    • Hello~
      1. 該程式我是用 C#.NET 寫的,與 VB.NET 應該無關吧。
      2. 在範例圖上應該表達算很清楚,並不需要透過 Excel,報價 Server 即為 DDE Server,並不再需要透過 Excel 當為中介的。

  13. Kenming:

    不好意思,把你大名誤植了!
    如果以第一點” DDE Client 主動向 DDE Server 取得最新的資料”,那我是在迴圈中一直重複下”Request”,迴圈執行幾次,tick就會抓幾次回來,這部分似乎很難跟server同步。一天下來,至少也有30000個ticks以上。
    我是使用台證的Office Quote當資料源,我有查到資料說他是一種COM傳輸技術,小弟學淺,實在沒聽過,不知道Kenming是否有聽過這樣的技術呢?
    謝謝

    • 1. 所以本來就不是用 Request 取資料的啊。 我在文內有提及,那是為了第一次能抓到資料而實做的。

      2. 先前才剛爬網查過這個。 反正簡單的說,就是依循它的通訊協定來取得 Tick 資料。 我想應該是比 DDE 的傳輸好上太多了。 可惜,台證有最低口數限制,我也沒有帳號,無法取得來測測看。 🙁

  14. DK你好:想請教幾個問題。
    1. 當我使用的是這個 “Request(同步)” 的指令時,是代表跟DDE Server端的資料變動同步嗎?不管是不是有成交,也都會將資料回傳給我?
    2. 若使用 “Advise(通告)” 的方式。如同你文中所說的,只要針對該項目的值一有變更時,就會通知已註冊的 Client 來取得變更的值。那今日如果我要抓取的是”成交時間”、”價格”與”數量”3種數值的話,我需要針對這3個不同的item各自去下”Advise”嗎?
    3. 我目前遇到最大問題是,抓取的tick數量,與期交所公布的成交資訊有落差。所以,特來請教。

    感恩

    • 我不是 D.K ?

      1. 不是喔,是 DDE Client 主動向 DDE Server 取得最新的資料。
      2. Yes, 每個數值都是個別獨立的 Item.
      3. 必然會有誤差的,DDE 並不是穩定的傳輸規格。

      另, 使用 NDDE 這個 APIs 最近我在測試時,發生了非常嚴重的問題, 當有太多連線時,DDE 連線會遺失! 一直找不出問題。 🙁

      現在不得已又轉回 Excel 尋求解決方法,實在很麻煩。 🙁

    • Hi~
      我最近都是使用 eLeader,並且常以 Excel 開啟 DDE 測試,一切均安好。

      應該是可能你的 Excel 設定有問題吧。 (設定問題請勿問我)

  15. 小弟我用VB6 ,要直接讀 eLeader,全都賺的資料有辦法嗎

    現在透過EXCEL

    最近遇到一個問題,用eLeader或全都賺軟體
    DDE link data直接拉到 EXCEL,會發生EXCEL無反應
    不知版大猜測可能是什麼錯誤ㄚ

    感謝ㄡ 

  16. 克明大,
    請問一下,您的文中提到”
    “至於 “Service”, “Topic”, “Item” 的名稱如何取得? 一般只要從看盤軟體中,對某個表單的畫面欄位,右鍵 Excel DDE 複製到 Excel 中,即可察看到。”
    我試了用寶來的點金靈還有hts,都還是不了解你說的方式,
    還是說要在盤中有資料的時候,才能試呢? 還是說有什麼其他的方法,
    可以取得 “Service”, “Topic”, “Item” ?

    另外您寫到”右鍵 Excel DDE “這是在看盤軟體中嗎?還是在 excel 裡?
    感謝您的回答 ^^

    • 如果可以透過 Excel 連線至你的看盤軟體並可以即時顯示跳動的資訊,那就代表著設定是沒有問題的。 然後就是在 Excel 的每一個欄位,觀察其上方的公式欄,即可取得 Service. Topic, Item 的欄位值。

      這一些問題,你可以至「聚財網」的程式交易區提問討論的。

  17. 克明大,好久沒上來你的基地了,
    才發現已經改名囉! :-p,

    最近正好在找程式交易的資料,
    結果就找到您這來了!
    哈哈,真是有緣!

    想像您請教一下,我對 c# 不熟,
    如果要學習的話,可以推薦幾本好書嗎?
    另外不知道克明大,對下單機的部份,
    是否也有研究?

    • Hello~

      學 C# 不用買書的,就是透過 Google 查詢範例;以及利用 MSDN 查詢語法即可的。 🙂

      我到目前為止,對於寫程式自動下單這事,一直興趣缺缺的。 ^^
      這方面想研究參考的話,可以至聚財網的程式交易區參考的,其實也不會太難的。 ^^

  18. Hello dancer:
    這到挺難得的,我是因為 “股票看盤軟體” 的關係,才 “不得不” 研究這個 DDE 連結。
    沒想到您還會有其他需求喔。 !^^

  19. 這個好!!!
    我一直在找C#寫DDE的文件跟範例
    感謝版主整理這麼清楚!

  20. Hello D.K.
    其實這個算是給會寫 .NET 的程式交易人員參考用的,然後再據此擴展,寫出更具應用價值的分析模型。 然後若能再行分享出來的話,那就會更好。 ^^

  21. 這個東西真是不錯啊…看來可以應用到同時接二到三家的 DDE 同商品資料..然後判斷哪個正常再丟給 TradeStation 作判斷來下單了..雖然用 Excel 也是可以…不過 Excel 用起來就是不太好用…

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *