2023年3月23日 星期四

修改 jupyterlab notebooks 起始位置

久久用一次,但常忘記,所以紀錄一下 

  1. 打開 cmd prompt,並執行 jupyter notebook --generate-config
     

  2. 會產生一個  jupyter_notebook_config.py 檔案。 也會告知你存放的路徑,類似                       D:\python\WPy64-31090\python-3.10.9.amd64\etc\jupyter\jupyter_notebook_config.py

  3. 用文字編輯器開啟它
     
  4. 尋找檔案內這行 #c.NotebookApp.notebook_dir = '' 
    移除井字號, 將單引號內輸入你想要的目錄位置,
    例如: c.NotebookApp.notebook_dir = "D:/python/notebooks/"


  5. 重新啟動 jupyter lab 後,起始位置就會改成您指定的目錄 

2023年2月20日 星期一

使用 pythonnet 呼叫群益api

 多年前曾用想要用pythonnet,來載入群益的api ,但最後失敗了。這篇純粹是出自個人好奇,還是想了解是否能用 pythonnet 來載入 dll,最近找到可以使用的步驟了,在windows下 python 可以呼叫群益api,讓熟悉 C# 的開發者,又想用 python 的人多一種選擇。

    目前使用這個方法的好處:

  1. 在 juypterlab 下,可以顯示各個 function 參數有哪些,減少一直翻手冊的時間。
  2. callback 部屬比較直覺快速,但也因此比較冗長。
  3. 熟悉 C# 的人,可以加入 C# 相關的 reference, namespace 當作 python 的模組來使用。
  4. 其他券商的 dll 檔,也有機會用這套方法來呼叫? 

    壞處:

  1. 目前遇到狀況是 callback 出現錯誤時,python沒有任何錯誤通知,除錯比較麻煩。


我的安裝環境:

  • windows 10, 
  • 我使用的是python 3.10.5 
  • visual studio 2022 (只是為了使用它的 tlbimp.exe)

前置工作

1. 用 tlbimp.exe 將 SKCOM.dll 轉成  Type library

    要先將群益的SKCOM.dll 轉成  Type library,我有安裝 visual studio 2022,利用它附帶的 comandline prompt terminal ,下指令 tlbimp.exe 將 SKCOM.dll 轉成 typelib 形式,最終產生 SKCOMLib.dll 的檔案。之後就可以輕鬆用 pythonnet 的 clr 模組取用。




2. 安裝 pythonnet

    Python.NET 模組可以讓 python 使用者無縫整合 .NET Common Language Runtime (CLR)。它讓 Python 可以跟 CLR 互動, 甚至也可以反過來將 Python 包進 .NET 裡.
    在你的 python 環境下用 pip 安裝 pythonnet 即可。詳細操作請看 pythonnet 官網


    pip install pythonnet


使用 pythonnet 的 clr 模組呼叫 SKCOMAPI











2022年11月14日 星期一

群益海期 tick 報價範例

 群益海期 ticks 報價範例,本範例直接在 OnNotifyTicksNineDigitLONG, OnNotifyHistoryTicksNineDigitLONG 裡做一些資料處理,當海期報價資料量很大的時候,處理速度變很慢,kline 轉換也有點慢,日後都還需要改進,朋友呀,如果有什麼更快的方法請教教我。



Notebook 範例版 jupyter notebook 

範例.py

2022年5月9日 星期一

群益 skcom api 海期報價、下單及回報範例

群益海期報價跟下單跟api手冊上寫的有點出入,手冊也沒有明確表示下單的流程,經過一番試誤,可以報價也可以下單了。實在是太少碰海期相關的 api,每次想用的時候都重新經歷一次錯誤,因此寫下來留個紀錄好參考。真的很少用,可能有不少地雷,因此僅供參考,也歡迎大家分享曾經遇過的問題。

幾個容易有錯誤的地方

1. 海期商品與交易所的報價代號跟下單代號有些是不同的,請用 GetOverseaProductDetail 來查詢正確代號。

2. 報價代碼寫法是  "交易所代碼1,商品代碼1#交易所代碼2,商品代碼2", 不同商品間以#字號隔開

3. 海期商品連線報價主機後,只會回應 3001,之後即可查詢報價

3. 海期委託單物件填寫商品代碼跟 GetOverseaProductDetail 查詢的稍有出入,需要加工處理。例如微型小道瓊下單代碼為 MYM_202206,填入委託單物件時事拆成兩個參數,要分別填入商品代碼及年月, 如 bstrStockNo = "MYM" 及 bstrYearMonth = "202206"

4. 要能下單要有幾項前置作業, SKOrderLib_Initialize >> ReadCertByID >> GetUserAccount >> SKOrderLib_LoadOSCommodity

5. "期貨API下單同意書"要記得簽,才能進行海期報價,我都用手機掌中財神 app,下方有個同意書專區,把裡面能簽的都簽了。

6. 有網友詢問如何使用 GetOverSeaFutureOpenInterestGW,手冊寫經由 OnOverSeaFutureOpenInterestGW 回報,測試後發現並沒有反應。深查後發現手冊坑人,原來是經由 OnOFOpenInterestGWReport 來做回報,也一併加入本範例供參考。

Notebook 範例版 jupyter notebook 

py 範例版,僅在 spyder IDE 下測試過

2022年3月7日 星期一

最近留言區被機器人進駐,有問題請到FB版上提問

 最近留言區被機器人進駐,會重複發一些垃圾留言,先暫停留言功能,有問題請到FB版上提問


FB連結

2021年11月2日 星期二

Add Virtual Environment to Jupyter Notebook

確認有安裝 ipykernel 後,terminal 下移動到新建的虛擬環境資料夾下,例如 my_env_name 執行下列指令:

python -m ipykernel install --user --name=<my_env_name>


ref: Create Virtual Environment using “virtualenv” and add it to Jupyter Notebook | by B. Chen | Towards Data Science

2021年10月6日 星期三

群益API SKReplyLib 回報 OnNewData 範例

現在沒有模擬單帳號可以測試了,因此我用群益下單軟體,下了個很遠不會成交的單子當作委託測試單。

另外最近 jupyter lab 開發不知道為什麼當我使用 %matplotlib auto 的 magic function時,會使整個notebook 當機,因此用 asyncio 自製了一個簡易的 event loop 來定時 pump event

ref:
jupyter跑 asyncio 的用法

範例


結果


2020年6月24日 星期三

在 linux 下使用wine python 串接群益 SKCOM API

        群益api 是使用 windows 的 COM 技術,在 linux 下要靠 wine 來模擬 windows 的環境。wine 要使用 32 bit 的相容性比較好,因此本篇 linux 系統 , python, skcom.dll 皆是使用 32 bit版。

操作概念是 在 linux 下裝 wine 註冊 SKCOM.dll, 用 wine 安裝 windows 版本的 python,  再用這個windows 版的 python 安裝 comtypes, pywin32 等套件來使用 skcom。 整個環境會是在 wine 底下執行的,操作起來還是有點隔閡,不是很順暢,我也還在摸索 

linux 我使用 lubuntu 18.04 alternative-i386 這個桌面版本, 執行Wine時建議是要在有XWindow的環境下執行,安裝一些 windows 程式,會需要 GUI 的操作 

linux wine 的安裝跟使用是參考這兩篇, 研究的超仔細,大推!! 

安裝 wine, winetricks

  • 建議使用32位元的作業系統來安裝Wine,因為Wine目前64位元的支援很差,它主要是以執行32位元的Windows程式為主!
  • 建議是透過compile Wine原始碼的方式來安裝Wine,也是為了避免32位元的函式庫裝得不夠完整!
  • winetricks 可以幫助安裝 VC++ runtime 2010 ,註冊 SKCOM.dll 時需要用到 
  • 剛裝好的 lubuntu 環境,把 apt 更新至最新,並裝下列開發套件,編譯 Wine 需要用到
$ sudo apt update; apt upgrade
$ sudo apt install openssh-client openssh-server vim software-properties-common gcc g++ vim subversion automake autoconf perl patch build-essential libtool doxygen bison flex zlib1g-dev gperf tofrodos wget curl screen git samba vsftpd bash-completion ftp colordiff libkrb5-dev rar unrar unzip vnstat libssl-dev
  • 補足所需的套件
$ time apt install gnome-devel libx11-dev flex bison qt5-qmake libjpeg-dev libxslt1-dev libglu1-mesa-dev freeglut3-dev prelink libasound2-dev libfreetype6-dev libpng-dev libxml2-dev libxrender-dev libgl1-mesa-dev libgphoto2-dev libmpg123-dev libtiff-dev libpulse-dev liblcms2-dev libcapi20-dev libldap-dev libopenal-dev libv4l-dev libsane-dev libcups2-dev libgsm1-dev libosmesa6-dev libgnutls28-dev libpcap0.8-dev oss4-dev libcdk5-dev libgstreamer-plugins-base1.0-dev libarrayfire-opencl-dev
$ time apt install libsdl2-dev libvulkan-dev
  • 清除一下apt-get抓下來的殘餘檔
$ apt clean
  • 用root帳號登入
  • 先把Wine的git repository上的code拉下來!
$ mkdir -pv /root/packages ; cd /root/packages
$ time git clone https://github.com/wine-mirror/wine

  • 檢查套件是否足夠
$ cd ./wine
$ ./configure 

 #訊息大概剩下下面這樣,就差不多了。
configure: MinGW compiler not found, cross-compiling PE files won't be supported.
configure: libhal development files not found, no legacy dynamic device support.
configure: libFAudio development files not found, XAudio2 won't be supported.
configure: vkd3d development files not found (or too old), Direct3D 12 won't be supported.
  • 接下來編譯並且安裝!編譯會花大約40-60分鐘
$ time make
$ time make install
  • 接下來安裝winetricks!直接從github wget下來就可以用了!
$ mkdir -pv /opt/bin ; cd /opt/bin
$ wget https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks
$ chmod +x ./winetricks
$ ./winetricks -V  

#檢查版本,出現下列訊息就沒問題了
20190615-next - sha256sum: 47304e177f259d6f9c05af01ab42c06531fd8a9716e2751d2fadcd664130feea

Wine 使用 SKCOM api

  • 設定Wine的windows環境,在 XWindow環境下。第一次使用須初始化一個windows 環境,打開Terminal,執行以下指令以設定Wine的環境!我的環境是建立在 ~./home/使用者/.wine 下,.wine 就是windows 虛擬的系統,底下有個 drive_c 資料夾,等於 C:\  槽
$ wineboot  

  • 群益API的SKCOM.dll檔需要 VC++ 2010可轉散發套件, 可透過winetricks來安裝 vcrun2010
$ winetricks vcrun2010 

  • 下載群益API,將API 資料夾 CapitalAPI_2.13.22 下的x86 資料夾搬到 ~/.wine/drive_c/skcom/x86  這等於是存在 windows 的 C:\\skcom\\x86, 之後使用python 呼叫會方便一點
  • cd 到 ~/.wine/drive_c/skcom/x86資料夾下,執行以下指令以註冊群益API:
$ regsvr32 ./SKCOM.dll

drive_c 下路徑的內容,skcom, python, strategy 是我自己創建的,資料夾名稱不要有空格,減少麻煩



wine下的 python環境

  • 用wine 來安裝 windows版的 python
  • 到 python 官網,我選了 Python3.8.3 的 Windows x86 executable installer 這個版本下載
  • 我有嘗試使用miniconda,但 conda 或 pip 位置不在預設路徑上,我搞不定,導致python套件裝不起來  

#使用 wine安裝windows版的python
#會有GUI跳出,可將python裝在 C:\\python 路徑下
$ wine python-3.8.3.exe   

#安裝 comtypes 及 pywin32 套件,其他python套件也可以如此安裝
$ wine pip install comtypes pywine32    


  • wine的windows版的 python 環境建置完成,可以開始 CODING!!
$ wine python



將寫好的 Script.py 交由 window python 執行, 要加wine 不然會呼叫到 linux系統下的 python, 兩個系統還是不相容的

$ wine python Script.py

附上 Script.py 的內容


import pythoncom, time, os
from comtypes.client import GetModule, GetEvents, CreateObject
from datetime import datetime

#第一次使用需要將 SKCOM 包成python 的package
#SKCOM.dll 在linux 下,我是放在 ~./home/yi/.wine/driv_c/skcom/x86/SKCOM.dll
#但在 wine 下,是放在下列路徑, drive_c 就是windows的C槽
GetModule(r'C:\\skcom\x86\SKCOM.dll')
#GetModule會在comtypes.gen 下產生 SKCOMLib package, 之後就用下面方式引用
import comtypes.gen.SKCOMLib as sk

#建立COM物件
if 'skC' not in globals(): skC=CreateObject(sk.SKCenterLib, interface=sk.ISKCenterLib)
if 'skQ' not in globals(): skQ=CreateObject(sk.SKQuoteLib, interface=sk.ISKQuoteLib)
if 'skR' not in globals(): skR=CreateObject(sk.SKReplyLib, interface=sk.ISKReplyLib)

#輸入身分證與密碼
ID=''
PW=''
#股票代號
strStock="TX00" 

print(str(datetime.now())[0:-4], 'ID & PW entered')

#建立事件類別
class skQ_events:                                
    def OnConnection(self, nKind, nCode):
        print(datetime.now(), 'OnConnection', nKind, nCode)
        if nKind == 3003:
            #nKind==3003 表連線報價主機就緒
            print("quoate server connected..., nkind= ", nKind)
            ncode=skQ.SKQuoteLib_RequestStocks(1, strStock)
            if ncode==0:
                print(strStock, 'requested')    
    
    def OnNotifyQuote(self, sMarket, sIndex):
        ts=sk.SKSTOCK()
        skQ.SKQuoteLib_GetStockByIndex(sMarket, sIndex, ts)
        print(ts.bstrStockName, ts.bstrStockNo,  ts.nClose/10**ts.sDecimal)
    
class skR_events:
    def OnReplyMessage(self, bstrUserID, bstrMessage, sConfirmCode=0xFFFF):
        print('OnReplyMessage', bstrMessage)
        return sConfirmCode
                            
#Event sink, 事件實體  
EventQ=skQ_events()
EventR=skR_events()

#make connection to event sink
ConnectionQ = GetEvents(skQ, EventQ)
ConnectionR = GetEvents(skR, EventR)

if __name__=='__main__':
    #登入
    nCode=skC.SKCenterLib_Login(ID, PW)
    print("Login,", skC.SKCenterLib_GetReturnCodeMessage(nCode))
    #連線報價主機
    print(f"{datetime.now()}, EnterMonitor,", skC.SKCenterLib_GetReturnCodeMessage(skQ.SKQuoteLib_EnterMonitor()))
    # Event loop, 持續檢查有沒有event產生
    pythoncom.PumpMessages()



輸出結果,大概類似下圖,夾雜很多 fixme的警告,但不影響使用







2020年4月27日 星期一

群益API 2.13.22 登入海期報價主機錯誤

最近群益API更新,有好多小bug, 搞得好頭大...

用python呼叫群益API 2.13.22 登入海期報價主機發生錯誤, 會出現

OSError: exception: access violation writing 0x000000000000009C

經多方詢問後, 應該是api bug, 下個版本應該就會修正. 目前非官方的解法,創建 skcom 元件的時候,將海期及海選元件同時建立即可。目前測試可以 正常SKOSQuoate_Entermonitor(), 其他的還沒試過,給大家試試看吧。也不知道其他語言會有這個問題嗎?

skOSQ = CreateObject(sk.SKOSQuoteLib, interface=sk.ISKOSQuoteLib)
# 只要多下面這列就可以正常使用了
skOOQ = CreateObject(sk.SKOOQuoteLib, interface=sk.ISKOOQuoteLib)



2019年10月13日 星期日

群益api 選擇擇權代碼規則

群益API 選擇權代碼規則
感謝 FB 網友提供

Call option : A~L代表1~12月
Put option  : M~X代表1~12月。
群益的編碼邏輯都是 TX+@+strike+$+到期年分。 

@:  可以是O代表一般月結算的選擇權,若以是數字則代表為 1~4 的週選。
$  : 是選擇權到期的月份,所以call跟put是不同的。

ex.
TXO10700L2     台指選, 履約價 10700,  12 月, 2022年 的 call  
TXO10700X2     台指選, 履約價 10700, 12 月, 2022年 的 put

TXO14800A3      台指選, 履約價 14800,  1 月, 2023年 的 call  
TXO14800M3     台指選, 履約價 14800,  1 月, 2023年 的 put

TX213000L2 台指週選 W2, 履約價 13000,  12 月, 2022年 的 call
TX213000X2    台指週選 W2, 履約價 13000,  12 月, 2022年 的 put



Ref:

2019年7月27日 星期六

群益API python 下單範例

今天來示範下單, 請務必搞懂每個參數後在下單喔
我自己不放心所以去申請了模擬平台帳號,在來試試看下單的功能,不過模擬帳號目前沒有提供夜盤的功能,就加減用吧!! 之前介紹模擬平台的文章,大家參考一下囉
模擬平台有練功跟競賽兩種帳號,我沒有研究,隨便拿一個來用



 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
from comtypes.client import GetModule, CreateObject, GetEvents
GetModule('C:\\skcom\\CapitalApi_2.13.17\\x64\\SKCOM.dll')
import comtypes.gen.SKCOMLib as sk
from datetime import datetime
import getpass

#建立物件,避免重複 createObject
#登錄物件
if 'skC' not in globals(): skC=CreateObject(sk.SKCenterLib, interface=sk.ISKCenterLib)
#下單物件
if 'skO' not in globals(): skO=CreateObject(sk.SKOrderLib , interface=sk.ISKOrderLib)   
#回報物件
if 'skR' not in globals(): skR=CreateObject(sk.SKReplyLib , interface=sk.ISKReplyLib)   

#輸入身分證與密碼

ID=''
PW=''
print(datetime.now(), 'ID & PW')

#建立事件類別             
class skO_events:
    def __init__(self):
        self.TFAcc=[]
        
    def OnAccount(self, bstrLogInID, bstrAccountData):
        strI=bstrAccountData.split(',')
        #找出期貨帳號
        if len(strI) > 3 :
            if strI[0] == 'TF' :
                self.TFAcc = strI[1]+strI[3]
            
class skR_events:        
    def OnReplyMessage(self, bstrUserID, bstrMessage, sConfirmCode=0xFFFF):
        '''API 2.13.17 一定要返回 sConfirmCode=0xFFFF'''
        print('skR_OnReplyMessage', bstrMessage)
        return sConfirmCode
    
    def OnData(self, bstrUserID, bstrData):
         #成交回報
        self.bstrOnData.append(datetime.now().strftime('%H:%M:%S,') + bstrData)
        strI = bstrData.split(",")
        print("skR_OnData", strI)
                        
    def OnNewData(self, bstrUserID , bstrData):
        print('skR_OnNewData', bstrData)

#Event sink, 事件實體
EventO=skO_events()
EventR=skR_events()

#make connection to event sink
ConnO = GetEvents(skO, EventO) 
ConnR = GetEvents(skR, EventR) 

print(datetime.now(), 'Making event objects')

%matplotlib auto
#登入模擬帳號
nCode=skC.SKCenterLib_ResetServer ("morder1.capital.com.tw")
print('set server to morder1.capital.com.tw', skC.SKCenterLib_GetReturnCodeMessage(nCode))

#login
nCode=skC.SKCenterLib_Login(ID,PW)
print('Login', skC.SKCenterLib_GetReturnCodeMessage(nCode))

#初始 Order 物件
nCode=skO.SKOrderLib_Initialize()
print("Initialize ", skC.SKCenterLib_GetReturnCodeMessage(nCode))

#初始 Cert by ID 物件,模擬平台不需要這個,會出現錯誤
nCode=skO.ReadCertByID(ID)
print("ReadCertByID ", skC.SKCenterLib_GetReturnCodeMessage(nCode))

#Get User TF Account
nCode=skO.GetUserAccount()
print("GetUserAccount ", skC.SKCenterLib_GetReturnCodeMessage(nCode), EventO.TFAcc)

#設定期貨單參數,請自行調整囉,注意參數的資料型別,例如 bstr開頭的是要輸入文字型態
#以下請再jupyter 裡用另外一個cell 跑
fo=sk.FUTUREORDER()
fo.bstrFullAccount=EventO.TFAcc      #TF 帳號
fo.bstrStockNo='MTX00'
fo.sBuySell=0                         #0 buy, 1 sell
fo.bstrPrice='10700'               #委託價格,「M」表示市價,{移動停損、MIT皆無須價格}
fo.nQty=1                              #交易口數
fo.sDayTrade=0                     #當沖0:否 1:是,可當沖商品請參考交易所規定。 
fo.sNewClose=2                     #新平倉,0:新倉 1:平倉 2:自動{新期貨、選擇權使用}
fo.sTradeType=1                    #0:ROD  1:IOC  2:FOK
fo.sReserved=0                     #盤別,0:盤中(T盤及T+1盤);1:T盤預約{新期貨、停損單使用}

#下單
nCode=skO.SendFutureOrder(ID, False, fo)
print(nCode)