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,並進而讓有心的程式交易人員,可以再行擴展,自行撰寫包括報表統計、技術線型分析 等應用。
我寫的這個簡單 DDE Client,基本功能如下:
o 可以同時連結多個 DDE Server。
o 可以同時顯示多個項目(Item)所持續跳動(Tick)的數值(Value)。
o 可以正確顯示傳輸項目值為中文的編碼。
o 可以任意地刪除 DDE 連線與項目 的相關資訊。
簡單的源碼說明
DDE 的連線
- 看盤軟體本身即為 DDE Server! 這點要先弄清楚。 所以看盤軟體連線至券商的報價伺服器,那是另外一回事,DDE Server 作得好不好,是與看盤軟體本身的穩定度與資源管理有關,而不是與遠端的報價伺服器有關。
- 看盤軟體需不需要啟動 Excel? 不需要的,Excel 本身就是 DDE 的用戶端(Client),而且也因為 Excel 的關係,使得任一券商的看盤軟體,都必須符合能讓 Excel 這個用戶端正確地顯示資料。 這個有趣,是 Server 端必須符合 Client 端的傳輸規格,而且不能亂搞。 所以相對來說,對於程式開發人員自行要寫 DDE Client 程式來說,就不用擔心能不能正常顯示所傳輸過來的數值,要是有問題,肯定是自己寫的程式有問題,也方便自行 DEBUG。
- 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” 的機制,來有效達成伺服器內資源上的協調。
- 連線很簡單,片段的程式碼參考如下:
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 Loopprivate 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
原來是把該範例的程式碼放置於聚財網,但好像該論壇文章已過期而無法下載。 故改上傳至「程式交易聚寶盆」,供免費下載。
sh18gao
請問這個源碼哪裏可以下載,非常感謝
simon
你好 !!
我已經有一個excel寫好的程式原本是套用在國票的看盤系統
我現在想把這個程式 套用在 台新的看盤系統
但不知道如何去改
國票系統 與 台新的系統 都是用嘉實的
聽朋友說要去改券商的程式碼 等等等
但不知道如何更改
不知線上有誰知道 可否告知
謝謝
Wang Kenming
1. 先了解下台新報價/下單系統使用的連線方式為何。
2. 現在 DDE 這種老舊不穩定的連線是非常不建議,最好能直接連結券商提供的 API 報價源。
keven
Imports System.Text
Imports NDde.Client’去網路上找到別人寫的類別
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
‘1.NEW 一個DdeClient實體
Dim myclient As New DdeClient(“CATDDE”, “FUTOPTTXFD6 “, Me)’永豐的topic要留5個空白才能作用
‘2.連接CATDDE,就是券商給的免費報價軟體,也就是DDE伺服器
myclient.Connect()
‘3.啟動通知
myclient.StartAdvise(“CurPrice”, 1, True, 60000)
‘4.委派
AddHandler myclient.Advise, AddressOf client_advise
Label2.Text = “IsConnected= ” & myclient.IsConnected
End Sub
Sub client_advise(ByVal sender As Object, ByVal e As NDde.Client.DdeAdviseEventArgs)
Dim mydata As String = Encoding.Default.GetString(e.Data, 0, e.Data.Length)
Label1.Text = mydata
End Sub
End Class
這段程式碼在XP上是可以用的,不知為何在Win10下,myclient.connect會報錯,說找不到
CATDDE,明明就有開說,盼仁人君子解惑,謝謝!
Frantz
謝謝板主
目前剛剛嘗試套用您的版本調整
學到的是需要按CLICK才會有資料出來。
其它的還在上網邊搜尋資料一個個學習中。
另外也發現台灣這邊相關文章不好找。
從您之前留下的網站去搜尋也是。
最後還是回到微軟的MSDN及大陸或者國外網站慢慢爬文中。
Frantz
謝謝版主
近日研究後,已經有些小突破了。
但在運算上。
我參考了您一篇文章:
[交易系統] C#.NET 開發海外期貨部位策略管理系統
從文中看到一套程式開發的目錄名單。
想跟請您
假設
server、topic_name、item_name
分別建議資料庫歸類的話
分別在DdeClient中Requset→Advise過程中分別[靜態]及[動態更新]
這樣子執行上,會比直接指定server、topic_name、item_name快很多嗎?
因為我在思考選擇權每周、月的這item_name的判斷及履約價的新增。
Kenming Wang
啊,我已經幾乎不考慮使用 DDE 了耶。
因為買了 Multicharts,報價的問題就不用自己再行客製化,簡單太多了。
Frantz
謝謝板主
主要我需要版型已經在excel成型了,
一般券商並沒有。
但使用excel 時,當快市或者波動大時,容易當機。
因此需要換個方式調整導入或者直接另行開發一個工具套版型上去才行。
Frantz
版本您好,
很謝謝您分享這麼有用的文章
目前在才接觸C#跟VBNET。
有機會參考到了您的寫法。
嘗試改用textbox或者label要呈現value時(想製作成上下五檔方式的ui呈現),沒有反應,不會秀出來。
另外想詢問您
如果topic及item很多話。
是不是要一次先建好多條的topic及item才行?
Kenming Wang
你的問題很明顯是對 Form ui 元件的基本設計觀念沒有基礎。
MSDN, How-to example 等,最好先翻閱與實際練習過會比較有感覺。
Frantz
謝謝板主
目前正在翻閱這些文章進一步瞭解中。
邊著手一步步龜速學習。
Kenming Wang
主要是你問的問題是屬於 Coding 很基本 how-to 的實作問題。
這類問題現在很難去伸手要答案,而是要逐漸懂得如何自行透過 Google 找這類實作議題。
初期學習速度很慢,未來就會倒吃甘蔗般,會很快就找到實作的答案。
文哲 蔡
Hi 版大I:
請問如何撰寫 YESWIN DDE,個股融資融融券餘額!?
TKS
傑西 陳
大大, 可以問您元大字串連接的問題嗎? 在excel中呼叫元大DDE取得台積電報價是這樣寫 YES|DQ!’2330.price’,但是要用到下面程式,是否我字串哪邊有問題呢? 呼叫都無法成功,可否幫我看一下呢! 謝謝
mytopic.AddRange(New String() {“DQ!”})
myitem.AddRange(New String() {“2330.price”})
topicCount = mytopic.Count – 1
ReDim myClient(topicCount)
For i As Integer = 0 To topicCount
myClient(i) = New DdeClient(“YES”, mytopic.Item(i).ToString, Me)
Try
myClient(i).Connect()
If i = topicCount Then
Me.GroupBox1.Text = “報價視窗-連線成功”
Me.Button1.Enabled = False
End If
Catch ex As Exception
If ex.GetType.ToString = “System.InvalidOperationException” Then
MsgBox(“已連線”)
Me.Button1.Enabled = False
Else
MsgBox(ex.Message)
Me.Button1.Enabled = True
End If
End Try
Next
cflai
Hi 版大你好,
聚寶盆一直沒有辦辦法進行註冊的動作,
是否方便提供一個新載點或mail給我,謝謝!!!
roger
最近因為公司需求也需要碰到這個部分
爬了許多文章發現這篇打的最詳細
但是聚寶盆那邊我試過好多次都沒有辦法進行註冊的動作
能否麻煩大大您能夠在提供一個新的載點呢?
感謝~
akai
我也是用C#+NDde.dll去抓期貨商的DDE 遇到了下面這個問題 不知道能否勞駕版大給我點建議或指點
我個人不喜歡用.StartAdvise這個方法 我有些功能需要把DDE關掉(例如進入市價自動下單的迴圈) 重新叫起會有delay 有時後還會當掉
我之前引用日盛的DDE 都是用.Request這個方法 需要再去抓 抓日盛的DDE資料都沒問題 抓凱基(台証)的就抓不到了 出現 fail to request訊息 請問版大有什麼辦法可以克服嗎? 用.StartAdvise去抓凱基資料是沒問題的 就.Request失敗
vincentt
好奇Excel或MC的Universal DDE,為什麼可以在盤後使用Request抓到資料,測試許久,發現單用Request還不足,可以搭配BeginRequest多次異步Request,約嘗試一到二次就都能取得值。
猜測為了省資源,DDE Server不維護非盤中時時更新的資料
而程序間通訊又比網路間通訊快,故
給akai,在同樣情境下Excel或MC的Universal DDE抓得到資料但NDde則否,可以試試改用BeginRequest,也許能改善,否則就要去挖DdemlException裡回傳的Code是什麼樣的DDE錯誤了!
Kenming Wang
每一家盤商的 DDE 提供方式並不盡相同,好像要個別實驗過才可以。
也沒有所謂喜好的問題,能連得上讀取資料就好了。
淡然
您好,给我一份程式吧,那个网址下载不了!
ooph
版大您好,
爬文爬了好多天感覺您是這方面的專家, 因此向您請較:
一直在找是否有辦法將 yeswin 的即時資料傳到 excel 做一些即時運算. 但是一些固定欄位的值每天都在變動, 例如我想即時記錄成交量排行前 10 大的股票, 但是滑鼠右鍵按下去只能帶出某支股票的名字, 但下一秒也許成交量第1名就不是他了, 是不是有什麼方法可以達到這個目的? 懇請指導.
blue_ST
你好~問題改一下~目前跑第一筆ITEM 有值了 ~但第二筆就抓不到了一直顯示(1101.PRICE)!怪怪的~望大大賜教!謝謝~
blue_ST
您好~想請問在執行時~可新增連線(正常)~但是到了新增項目時~
發生這段的ERROR ,
PS:(我的連線字串)STTRADE|DSC!’1101.PRICE’
———————————————————
chg_value_row.Cells[“col_iteminfo_value”].Value = data;
ERROR:並未將物件參考設定為物件的執行個體
——————————————————–
PS:設中斷時,我看到data 是有值.
rushdie
Kenming大您好:
我這邊試著用各期貨商的看盤軟體,但是只有元x的yexxxx可以正常的連線,其它期貨商的都連線失敗,請問板上或是大大有這方面的錯誤訊息嗎?
謝謝大大!
Alex
您好,拜讀您的文章感到莫大的幫助,謝謝您無私分享。
想請教您一個問題,關於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,會有影響嗎)
Kenming Wang
顯然就是 topic/service/item 字串有誤,這你用 Excel 連結就可以知道正確性了。
跑 Win7 不會有任何問題。
Michael Yu
請教Kenming大;
在日盛HTS中按右鍵,未見Excel DDE功能,是否有其它方法可取得 “Service”, “Topic”, “Item” ?
Thanks!
Kenming Wang
Google 請打: hts excel dde 字串。 保證你可以找到很多。
阿呆
非常感謝您能大方的分享C# DDE的程式碼和說明,我目前也對程式交易有興趣,您的文章對我現在的幫助很大,感謝您!
Kenming Wang
非常好,也希望屆時您可以分享更多的心得。 ^^
kevenpeter
能否請kenming兄在通化街開一場收費的下午茶會,直接講授DDE的這一部分?
Kenming Wang
DDE 這一塊實在沒啥好講的勒。
如果有機會,我到昰想把自己研究開發的工具打包成套件,附在書本上出版,然後有機會辦講座課程,可能更實在些。 !^^
Kenming Wang
諸位有興趣原始程式碼的讀者們:
請至:「程式交易聚寶盆」免費下載。
網址: http://www.programtrading.tw/viewtopic.php?f=4&t=2890
我是阿丁
Dear Kenming您好:
小弟近日正在學著以C#來撰寫DDE程式, 大大的文章對我幫助很大
然而在截取日盛報價的過程中, 還是遇到一些困難
不曉得能否厚顏的請大大也寄一份範例檔給小弟當作參考, 謝謝!!
我是阿丁
MAIL: chaser1213@yahoo.com.tw
BLOG: http://blog.xuite.net/chaser1213/autotx
PLURK: http://www.plurk.com/ding1213
Chiller
Dear Kenming
感謝您,Email是我所留的這個msa帳號,昨日也剛好使用NDde.dll,
嘗試用1 connection (1 service 1 topic)多個item的方式,
苦思許久,仍尚未試出來,您範例程式中都有提到,
再麻煩您寄給我了,感恩。
Chiller
Dear Kenming
您的詳細解說,對於程式新手的我來說,受益良多,感謝您的無私分享,目前我正在寫DDE 用 vb.net來實作,
碰到您上面所提的windows Form 的UI難題,剛好您有範例在聚財網上,但,可能時間比較久了,該網址找不到您的文章,
可否幫忙ㄧ下,感恩。
Kenming Wang
我去查的確不見了 !^^
這樣的話,我寄給你好了。 Email 是你現在這個所留的嗎?
nickcatwang
我也是覺得很奇怪,或許是VB的問題,謝謝囉~
nickcatwang
請問~
為什麼,用VB.net接DDE,還是要開EXCEL才行?而且在excel裡,還得要有想連結的資料?
照理來說,就像您文中所述,應該是VB直接可以接到DDE,而不是透過excel才對
這是為甚麼?
同樣的,為了瞭解是不是VB的問題,還是我哪裡弄錯了
我有下載聚才網的程式碼,執行bin\下的執行檔
也是一樣,要開excel,數值才會顯示&跳動
請教有甚麼方式可以不透過EXCEL直接接到DDE嗎?
Kenming Wang
Hello~
1. 該程式我是用 C#.NET 寫的,與 VB.NET 應該無關吧。
2. 在範例圖上應該表達算很清楚,並不需要透過 Excel,報價 Server 即為 DDE Server,並不再需要透過 Excel 當為中介的。
Max
Kenming:
不好意思,把你大名誤植了!
如果以第一點” DDE Client 主動向 DDE Server 取得最新的資料”,那我是在迴圈中一直重複下”Request”,迴圈執行幾次,tick就會抓幾次回來,這部分似乎很難跟server同步。一天下來,至少也有30000個ticks以上。
我是使用台證的Office Quote當資料源,我有查到資料說他是一種COM傳輸技術,小弟學淺,實在沒聽過,不知道Kenming是否有聽過這樣的技術呢?
謝謝
Kenming Wang
1. 所以本來就不是用 Request 取資料的啊。 我在文內有提及,那是為了第一次能抓到資料而實做的。
2. 先前才剛爬網查過這個。 反正簡單的說,就是依循它的通訊協定來取得 Tick 資料。 我想應該是比 DDE 的傳輸好上太多了。 可惜,台證有最低口數限制,我也沒有帳號,無法取得來測測看。 🙁
Max
DK你好:想請教幾個問題。
1. 當我使用的是這個 “Request(同步)” 的指令時,是代表跟DDE Server端的資料變動同步嗎?不管是不是有成交,也都會將資料回傳給我?
2. 若使用 “Advise(通告)” 的方式。如同你文中所說的,只要針對該項目的值一有變更時,就會通知已註冊的 Client 來取得變更的值。那今日如果我要抓取的是”成交時間”、”價格”與”數量”3種數值的話,我需要針對這3個不同的item各自去下”Advise”嗎?
3. 我目前遇到最大問題是,抓取的tick數量,與期交所公布的成交資訊有落差。所以,特來請教。
感恩
Kenming Wang
我不是 D.K ?
1. 不是喔,是 DDE Client 主動向 DDE Server 取得最新的資料。
2. Yes, 每個數值都是個別獨立的 Item.
3. 必然會有誤差的,DDE 並不是穩定的傳輸規格。
另, 使用 NDDE 這個 APIs 最近我在測試時,發生了非常嚴重的問題, 當有太多連線時,DDE 連線會遺失! 一直找不出問題。 🙁
現在不得已又轉回 Excel 尋求解決方法,實在很麻煩。 🙁
ker lin
沒呢,我都試過了,包含了安全性的設定
Kenming Wang
Hi~
我最近都是使用 eLeader,並且常以 Excel 開啟 DDE 測試,一切均安好。
應該是可能你的 Excel 設定有問題吧。 (設定問題請勿問我)
ker lin
小弟我用VB6 ,要直接讀 eLeader,全都賺的資料有辦法嗎
現在透過EXCEL
最近遇到一個問題,用eLeader或全都賺軟體
DDE link data直接拉到 EXCEL,會發生EXCEL無反應
不知版大猜測可能是什麼錯誤ㄚ
感謝ㄡ
Kenming Wang
是否是 Excel 的巨集與安全設定等有沒有開啟呢?
Victor
克明大,
請問一下,您的文中提到”
“至於 “Service”, “Topic”, “Item” 的名稱如何取得? 一般只要從看盤軟體中,對某個表單的畫面欄位,右鍵 Excel DDE 複製到 Excel 中,即可察看到。”
我試了用寶來的點金靈還有hts,都還是不了解你說的方式,
還是說要在盤中有資料的時候,才能試呢? 還是說有什麼其他的方法,
可以取得 “Service”, “Topic”, “Item” ?
另外您寫到”右鍵 Excel DDE “這是在看盤軟體中嗎?還是在 excel 裡?
感謝您的回答 ^^
Kenming Wang
如果可以透過 Excel 連線至你的看盤軟體並可以即時顯示跳動的資訊,那就代表著設定是沒有問題的。 然後就是在 Excel 的每一個欄位,觀察其上方的公式欄,即可取得 Service. Topic, Item 的欄位值。
這一些問題,你可以至「聚財網」的程式交易區提問討論的。