2013年3月4日 星期一

[DDE]Python3抓取DDE資料


DDE是一個很古老的傳輸格式,想不到直到win8 64bit版都還見的到蹤跡,根本是殭屍技術了吧!  不過在win8上卻意外地穩,似乎有做過改進。
就網路查詢到python想要連結DDE只能使用pywin32,然而該模組早在好幾年前就已經宣布不再維護其DDE功能,使得它只能是個做到一半的半成品。根據網友測試,似乎只能使用request,但大部分的券商軟體只支援Advise(廣播,這功能也比前者好用,只要資料有變動立即通知,前者是定期查看資料)。而且在python3,尤其是64位元環境就連連線都是一個困難點。
經過幾年漫漫追尋,終於找到另一個網友做的DDE client端,可支援常見的Advise模式,而且不需安裝其他模組可獨立使用。不過他是用python2寫的,因此我幫他改寫了一下,另外新增可為各別item指定處理函式(callback),經測試可在win8 64bit+python3.3 64bit正常運行
下載位置如下:
https://www.dropbox.com/s/wx6xbgjxuko7do7/PyWinDDE.py
(位置已失效,詳情請見下面留言)
不用安裝,直接放到跟你的專案同目錄或者丟進x:\Python33\Lib\site-packages以便日後使用。
使用方式很簡單,以下用全球理財王作為範例,目標是取得韓股綜合指數

import PyWinDDE

# 初始化DDE的service及topic
dde = PyWinDDE.DDEClient("XQKGIAP", "Quote")

# 設定使用advise(廣播)取的所需的item
dde.advise("KS11.FS-Price")

# 進入訊息循環,以便持續不斷接收訊息(這部分若有用pyqt、tk等視窗模組便不需要)
PyWinDDE.WinMSGLoop()
執行後如果一直噴資料出來就是正常了,當然你也可以自己指定處理資料的函式,而不要這樣一直在畫面上亂吐。

我們修改第7行,指定newcall為處理資料的函數

dde.advise("KS11.FS-Price",callback = newcall)

注意,該函數必須依序有value,item作為參數,DDE會回傳item及資料過去。

以下是利用PyQt來做為範例,這個程式開啟後就會開始接收指定的DDE資料,若按下OK會自動將抓取的資料存成csv檔做後續使用:

import sys,csv,PyWinDDE
from PyQt4.QtGui import *

app = QApplication(sys.argv)

txtEdit = QTextEdit()
ok = QPushButton("&OK")
layout = QVBoxLayout()
widget = QWidget()

layout.addWidget(txtEdit)
layout.addWidget(ok)

widget.setLayout(layout)
widget.show()

tick = []
def recTick(value,item):
    tick.append(value)
    txtEdit.append(value)

def writeRec():
    with open("test.csv","w") as f:
        c = csv.writer(f)
        for d in tick:
            c.writerow(d)
    widget.close()

dde = PyWinDDE.DDEClient("XQKGIAP", "Quote")
dde.advise("KS11.FS-Price", callback = recTick)

ok.clicked.connect(writeRec)

app.exec_()

今天就先到這裡,有機會再多聊一些吧。也歡迎大家提出問題。