from comtypes.client import GetModule, GetEvents, CreateObject
GetModule('C:\\SKCOM\\CapitalAPI_2.13.13\\x64\\SKCOM.dll')
import comtypes.gen.SKCOMLib as sk
skC = CreateObject(sk.SKCenterLib, interface=sk.ISKCenterLib)
skO = CreateObject(sk.SKOrderLib, interface=sk.ISKOrderLib)
#使用jupyter notebook magic function,這句可以讓 Event Pump 出來
%matplotlib auto
ID=''
PW=''
#建立事件類別
class skO_events:
def __init__(self):
#初始化,可以設定一些變數供使用
self.Acc=''
self.Balance=[]
def OnBalanceQuery(self, bstrData):
#將Balance 回傳資訊存在 event instance 的 Balance 屬性中
self.Balance.append(bstrData)
print('OnBalanceQuery', bstrData)
def OnMarginPurchaseAmountLimit(self, bstrData):
print('OnMargin', bstrData)
def OnAccount(self, LogInID, AccountData):
if AccountData.split(',')[0]=='TS':
self.Acc=AccountData.split(',')[2] + AccountData.split(',')[3]
print(LogInID, AccountData)
EventO=skO_events()
EventO_handler=GetEvents(skO, EventO)
#Login
skC.SKCenterLib_Login(ID,PW)
#Order object initialize
skO.SKORderLib_Initialize()
skO.GetUserAccount()
skO.GetBalanceQuery(ID, EventO.Acc, '')
#查看 Balance
print(EventO.Balance)
skO.GetMarginPurchaseAmountLimit(ID, '', '')
網頁
▼
2018年9月19日 星期三
測試 SKOrderLib 的 GetBalanceQuery, GetMarginPurchaseAmountLimit 功能
一點範例測試 GetBalanceQuery, GetMarginPurchaseAmountLimit 功能
2018年9月18日 星期二
python 接群益api callback / event 沒反應,常見問題
沒有順序之分,想到過去有哪些經驗就寫什麼
1. python 跟 API 的位元版本要一樣,python 是64 bit,API 就裝 x64,網友指出 64位元版好像問題比較多,可以試試 32位元版本
2. 缺少 event loop, 在 IDE 或 GUI 介面下一般都會自帶有 eventloop 功能,比較不用煩惱。 如果用 jupyter notebook 開發,可用 magic function: %matplotlib auto, 也會幫你準備一個 eventloop。
如果在 terminal 下開發,需要用 pythoncom.PumpWaitingMessages() / PumpMessages() 之類的方法讓 callback出來。如:
while Ture:
pythoncom.PumpWaitingMessages()
或是直接用 pythoncom.PumpMessages() 等同上面的 while loop
最近發現,使用 juypter notebook 的 magic function '%matplotlob auto' 來推動 eventloop,可能要注意 '%matplotlob auto' 放置的位置,太早使用,可能 eventloop 沒有反應,可以嘗試調整 '%matplotlob auto' 出現的位置。
3. Event class 的定義有錯誤,像是 class 定義 def 的名稱都要參照 API 文件裡事件的名稱
例如: SKQuotelib 的事件
class skQ_events:
def OnConnect(self, nKind, nCode):
print('nKind, nCode=', nKind, nCode)
def OnNotifyServerTime(self, sHour, sMinute, sSecond, nTotal):
print(sHour, sMinute, sSecond)
記得 def 裡第一個參數是 self,這個一開始寫常忘記
4. 如果是更新API 後有問題,可以考慮清空 comtypes.gen下的資料
請參考 https://easontseng.blogspot.com/2018/05/api-python-comtypes.html
我常用 OnNotifyServerTime 這個 callback 來看 eventloop 正不正常,連上群益報價主機後,每隔5秒主機會發送一個時間,可以藉此觀察 eventloop 有沒有問題。
以上是我的經驗,如果你有遇到其它情況,也歡迎在下面留言分享
1. python 跟 API 的位元版本要一樣,python 是64 bit,API 就裝 x64,網友指出 64位元版好像問題比較多,可以試試 32位元版本
2. 缺少 event loop, 在 IDE 或 GUI 介面下一般都會自帶有 eventloop 功能,比較不用煩惱。 如果用 jupyter notebook 開發,可用 magic function: %matplotlib auto, 也會幫你準備一個 eventloop。
如果在 terminal 下開發,需要用 pythoncom.PumpWaitingMessages() / PumpMessages() 之類的方法讓 callback出來。如:
while Ture:
pythoncom.PumpWaitingMessages()
或是直接用 pythoncom.PumpMessages() 等同上面的 while loop
最近發現,使用 juypter notebook 的 magic function '%matplotlob auto' 來推動 eventloop,可能要注意 '%matplotlob auto' 放置的位置,太早使用,可能 eventloop 沒有反應,可以嘗試調整 '%matplotlob auto' 出現的位置。
3. Event class 的定義有錯誤,像是 class 定義 def 的名稱都要參照 API 文件裡事件的名稱
例如: SKQuotelib 的事件
class skQ_events:
def OnConnect(self, nKind, nCode):
print('nKind, nCode=', nKind, nCode)
def OnNotifyServerTime(self, sHour, sMinute, sSecond, nTotal):
print(sHour, sMinute, sSecond)
記得 def 裡第一個參數是 self,這個一開始寫常忘記
4. 如果是更新API 後有問題,可以考慮清空 comtypes.gen下的資料
請參考 https://easontseng.blogspot.com/2018/05/api-python-comtypes.html
我常用 OnNotifyServerTime 這個 callback 來看 eventloop 正不正常,連上群益報價主機後,每隔5秒主機會發送一個時間,可以藉此觀察 eventloop 有沒有問題。
以上是我的經驗,如果你有遇到其它情況,也歡迎在下面留言分享
2018年7月25日 星期三
等不到Onconnection 回報 3003
最近發現登錄報價後常常等不到 Onconnection 回報 3003,困擾了很久,後來才發現這個問題原來我很久之前就記錄過了,不過一時忘記了,特此紀錄一下,下次比較好找問題。
原來如果我先呼叫 SKReplyLib_ConnectByID後,馬上乎叫 SKQuoteLib_EnterMonitor的話就會出現上述問題。安全做法是先EnterMonitor,再執行 SKReplyLib_ConnectByID,問題就可迎刃而解。細部原理我沒有深究,就先這樣吧!!
原來如果我先呼叫 SKReplyLib_ConnectByID後,馬上乎叫 SKQuoteLib_EnterMonitor的話就會出現上述問題。安全做法是先EnterMonitor,再執行 SKReplyLib_ConnectByID,問題就可迎刃而解。細部原理我沒有深究,就先這樣吧!!
上完hahow 課程 "用 Python 理財:打造小資族選股策略" 心得
最近剛聽完 hahow 的線上課程 "用 Python 理財:打造小資族選股策略",覺得實在是蠻超值的。很完整的課程,個人覺得很適合剛開始接觸python,想要用python 進行理財的人入門,由淺入深,手動打造完整選股策略,條理清晰,很好懂。不過很多資訊都是點到為止,給你一點提示,想要更精進則需要自己再花更多時間去研究,找資料。如果沒有半點程式基礎的人,則需要另外花點時間熟悉python,熟悉程式語言的邏輯。
哇 我買到早鳥票真是太超值了,已經回復原價了!!
哇 我買到早鳥票真是太超值了,已經回復原價了!!
2018年5月1日 星期二
群益api, 模擬平台申請
在群益api附的範例中看到模擬平台的選項,打勾後卻登陸失敗,google 了解後,原來是要先跟群益申請模擬帳號,google "群益 模擬主機"應該就可以看到申請網頁了
https://www.capital.com.tw/Activity/20150128_futures/default.asp
填入資料後,會給一組密碼。下載群益的模擬平台軟體,先登陸後再修改密碼,才能在群益API裡使用。
申請好後
用SKCenterLib_ResetServer,將主機位置改為 morder1.capital.com.tw,即可登陸模擬單伺服器主機
skC.SKCenterLib_ResetServer ("morder1.capital.com.tw")
skC.SKCenterLib_Login(Id, Pw)
目前模擬單主機沒有台指電子盤資訊
模擬帳號3個月以上沒使用,會被刪除,需要重新申請!!!
群益 api 升級後,python comtypes 某些功能無作用
#debug 小記事
我把群益 api 2.13.9 升級成2.13.11 後,python comtypes 某些功能無作用。今天終於發現問題所在:
import comtypes.client as cc
cc.GetModule('C:\SKCOM\x86\SKCOM.dll')
GetModule 這一步會在 comtypes資料夾下自動產生一個 gen 資料夾,裡面有comtypes 生成的 skcom 相關的.py 檔。 第一次呼叫後會再產生一個__pycache__資料夾,並將這些code編譯成 .pyc 檔加速運行速度。
我的comtypes資料夾路徑,給大家參考,可以去相關路徑下找找
Python\Lib\site-packages\comtypes\gen
問題似乎就在這哩,當把api升級後,重新呼叫 GetModule 後,python並沒有重新編譯。因此我把 __pycache__ 裡相關的 .pyc 刪除後,再重新呼叫 GetModule ,新版的 api 就又可以正確執行了。
我把群益 api 2.13.9 升級成2.13.11 後,python comtypes 某些功能無作用。今天終於發現問題所在:
import comtypes.client as cc
cc.GetModule('C:\SKCOM\x86\SKCOM.dll')
GetModule 這一步會在 comtypes資料夾下自動產生一個 gen 資料夾,裡面有comtypes 生成的 skcom 相關的.py 檔。 第一次呼叫後會再產生一個__pycache__資料夾,並將這些code編譯成 .pyc 檔加速運行速度。
我的comtypes資料夾路徑,給大家參考,可以去相關路徑下找找
Python\Lib\site-packages\comtypes\gen
問題似乎就在這哩,當把api升級後,重新呼叫 GetModule 後,python並沒有重新編譯。因此我把 __pycache__ 裡相關的 .pyc 刪除後,再重新呼叫 GetModule ,新版的 api 就又可以正確執行了。
2018年4月6日 星期五
安裝 pytorch
想用 AI 預測走勢,AI模組選了pytorch當作入門,主要是因為他的語法跟python一致,比較容易上手。今天在 windows 安裝了pytorch, 因為沒有nv顯卡,所以選了 cpu 版
這樣就安裝完了
# for CPU only packages
conda install -c peterjc123 pytorch-cpu
然後在python命令列下
import torch
沒有報錯就安裝成功了,繼續練功!
參考:
#pytorch easy installation on windows
#Windows支持Pytorch?如何在windows10中使用Pytorch?
#PyTorch還是TensorFlow?這有一份新手指南
#pytorch.org tutorials
#Neural networks for algorithmic trading. Correct time series forecasting + backtesting
這樣就安裝完了
# for CPU only packages
conda install -c peterjc123 pytorch-cpu
然後在python命令列下
import torch
沒有報錯就安裝成功了,繼續練功!
#pytorch easy installation on windows
#Windows支持Pytorch?如何在windows10中使用Pytorch?
#PyTorch還是TensorFlow?這有一份新手指南
#pytorch.org tutorials
#Neural networks for algorithmic trading. Correct time series forecasting + backtesting
2018年3月7日 星期三
嘗試用 wx, python 實做 群益附的範例 SKCOMtester 的功能
2021 edit: 群益的 python demo 範例已經提供 tkinter 很好的實作範例了
初次使用python GUI, 不太孰悉,未來GUI的layout 應該要單獨一個檔,才會比較好管理,目前已能動為優先。
很多人跟我說 Event 出不來,我覺得有GUI介面的話,很高機率可以解決這個問題!
使用流程,
1. 輸入ID&PW後Login,會等個幾秒,console出現一串錯誤訊息
2. 按 Connect 登錄報價伺服器,當出現 nCode=3003後, 表示完成登錄
3. 在Quote 欄填寫代碼,按下 Request 即可取得報價,預設是取台指近月期貨(TX00)
環境:
WinXP 32 bit, Capital API 2.3.9, python 3.4.3
#demoGUI code
import wx, time import comtypes.client as cc cc.GetModule('C:\\SKCOM\\2.13.9\\x86\\SKCOM.dll') import comtypes.gen.SKCOMLib as sk #Event class class skQ_events: def __init__(self): tc1.write('skQ event class created'+ '\n') def OnConnection(self, nKind, nCode): tc1.write('SKQ_OnConnection, ' + 'nKind= ' + str(nKind) + ', nCode= ' + str(nCode) + '\n') def OnNotifyQuote(self, sMarketNo, sStockIdx): getStock(sMarketNo, sStockIdx, ts) class skR_events: def __init__(self): tc1.write('skR event class created' + '\n') def OnConnect(self, bstrUserID, bstrData): tc1.write(str(bstrUserID) + ", skR_OnConnect" + '\n') def OnComplete(self, bstrUserID): tc1.write('skR OnCompleted' + '\n') def OnSolaceReplyConnection(self, bstrUserID, nErrorCode): tc1.write('skR OnSolaceReplyConnection, ' + str(bstrUserID) + ', nErrorCode= '+ str(nErrorCode) + '\n') #custom functions def getStock(nMarket, nIndex, ts): nCode=skQ.SKQuoteLib_GetStockByIndex(nMarket, nIndex, ts) tc2.write(str(ts.bstrStockNo) + ' ' + str(ts.nClose/10**ts.sDecimal) + '\n') #GUI class Example(wx.Frame): def __init__(self, *args, **kw): super(Example, self).__init__(*args, **kw) self.InitUI() self.CreatSKCOMObject() self.CreatSKCOMEvent() def InitUI(self): pnl = wx.Panel(self) vbox = wx.BoxSizer(wx.VERTICAL) hbox1 = wx.BoxSizer(wx.HORIZONTAL) hbox2 = wx.BoxSizer(wx.HORIZONTAL) hbox3 = wx.BoxSizer(wx.HORIZONTAL) #labels st1 = wx.StaticText(pnl, label='ID ') st2 = wx.StaticText(pnl, label='PW ') st3 = wx.StaticText(pnl, label='Quote') #text input self.tcID = wx.TextCtrl(pnl, size=(80, -1)) self.tcPW = wx.TextCtrl(pnl, size=(80, -1), style=wx.TE_PASSWORD) self.tcQuery = wx.TextCtrl(pnl, size=(80, -1), value="TX00") global tc1, tc2 tc1 = wx.TextCtrl(pnl, style=wx.TE_MULTILINE) tc2 = wx.TextCtrl(pnl, style=wx.TE_MULTILINE) self.bt_login = wx.Button(pnl, label='1. Login') self.bt_connect = wx.Button(pnl, label='2. Connect') self.bt_request = wx.Button(pnl, label='3. Request') #layout hbox1.Add(st1, flag=wx.LEFT, border=10) hbox1.Add(self.tcID, flag=wx.LEFT, border=35) hbox1.Add(self.bt_login, flag=wx.LEFT, border=35) hbox1.Add(self.bt_connect, flag=wx.LEFT, border=35) hbox2.Add(st2, flag=wx.LEFT, border=10) hbox2.Add(self.tcPW, flag=wx.LEFT, border=35) hbox3.Add(st3, flag=wx.LEFT, border=10) hbox3.Add(self.tcQuery, flag=wx.LEFT, border=35) hbox3.Add(self.bt_request, flag=wx.LEFT, border=35) vbox.Add(hbox1, flag=wx.TOP, border=10) vbox.Add(hbox2, flag=wx.TOP, border=10) vbox.Add(hbox3, flag=wx.TOP, border=10) vbox.Add(tc1, proportion=1, flag=wx.EXPAND | wx.TOP | wx.RIGHT | wx.LEFT, border=15) vbox.Add(tc2, proportion=1, flag=wx.EXPAND | wx.TOP | wx.RIGHT | wx.LEFT, border=15) #Set event handlers self.Bind(wx.EVT_BUTTON, self.OnLogin, self.bt_login) self.Bind(wx.EVT_BUTTON, self.OnConnect, self.bt_connect) self.Bind(wx.EVT_BUTTON, self.OnRequest, self.bt_request) pnl.SetSizer(vbox) self.SetSize((400,600)) self.SetTitle('pySKCOMtester') self.Centre() self.Show(True) def CreatSKCOMObject(self): global ts, skC, skQ, skR #股票物件 ts=sk.SKSTOCK() #SKCOM object skC=cc.CreateObject(sk.SKCenterLib,interface=sk.ISKCenterLib) skQ=cc.CreateObject(sk.SKQuoteLib,interface=sk.ISKQuoteLib) skR=cc.CreateObject(sk.SKReplyLib,interface=sk.ISKReplyLib) def CreatSKCOMEvent(self): global EveQ, EveR, ConQ, ConR #instant of event sinks EveQ=skQ_events() EveR=skR_events() #make connection to event sink ConQ = cc.GetEvents(skQ, EveQ) ConR = cc.GetEvents(skR, EveR) #Callback def OnLogin(self, e): ID=self.tcID.GetValue() PW=self.tcPW.GetValue() nCode=skC.SKCenterLib_Login( ID, PW) tc1.write('Login, nCode= ' + str(nCode) + '\n') nCode=skR.SKReplyLib_ConnectByID(ID) tc1.write('skR Connected, nCode= ' + str(nCode) + '\n') e.Skip() def OnConnect(self, e): nCode=skQ.SKQuoteLib_EnterMonitor() tc1.write('skQ EnterMonitor, nCode= ' + str(nCode) + '\n') def OnRequest(self, e): Stocks=self.tcQuery.GetValue() nCode=skQ.SKQuoteLib_RequestStocks(1, Stocks) tc1.write('skQ RequestStocks ' + Stocks + ', nCode= ' + str(nCode[1])+ '\n') e.Skip() def main(): ex = wx.App() Example(None) ex.MainLoop() if __name__ == '__main__': main()