国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
基于Python的國(guó)內(nèi)期貨證券解決方案

Python最近幾年已經(jīng)越來(lái)越火,在很多領(lǐng)域已經(jīng)可以完全替代MATLAB,用于金融計(jì)算與交易也不輸MATLAB。

1. 云服務(wù)器上安裝近十GB的MATLAB過(guò)于麻煩,而Python的Anaconda發(fā)布版只有幾百M(fèi)B

2.Python開(kāi)源免費(fèi),而正版MATLAB則價(jià)格不菲。

3. 國(guó)內(nèi)與Quantopian類(lèi)似的在線策略編寫(xiě)網(wǎng)站開(kāi)始流行,Python是它們的策略語(yǔ)言,建立了良性的互動(dòng)交流社區(qū),有大量的案例可參考。

4. Python有大量用于科學(xué)計(jì)算、統(tǒng)計(jì)分析、機(jī)器學(xué)習(xí)的開(kāi)源工具庫(kù),適合用于做量化交易。



因此,已經(jīng)有越來(lái)越多的用戶向Python遷移。我們也緊跟趨勢(shì),在推出MATLAB版XAPI統(tǒng)一行情交易接口后也推出了Python版。在總結(jié)了社區(qū)中常遇到的問(wèn)題后,在本文將進(jìn)行專(zhuān)門(mén)的解答。


1.1  常見(jiàn)金融工具與接口

目前國(guó)內(nèi)可以合法交易的金融工具主要是股票、期貨、黃金T+D等品種,一些電子盤(pán)、比特幣等暫時(shí)不在我們討論范圍內(nèi),有興趣的朋友可以網(wǎng)上查閱相關(guān)資料。一定要選擇國(guó)家承認(rèn)的正規(guī)合法平臺(tái),以免上當(dāng)受騙。表1. 常見(jiàn)金融工具與對(duì)應(yīng)的接口


1.1.1 綜合交易平臺(tái)CTP

綜合交易平臺(tái)CTP(ComprehensiveTransaction Platform)是由上海期貨信息技術(shù)有限公司(上海期貨交易所旗下子公司)開(kāi)發(fā)的經(jīng)紀(jì)業(yè)務(wù)管理系統(tǒng)。

目前除了在期貨市場(chǎng)占有率第一,它還有證券版支持股票,國(guó)際版支持外盤(pán)。

公司網(wǎng)址:http://www.sfit.com.cn/


1.1.2 金仕達(dá)Kingstar

期貨市場(chǎng)占有率第二的老牌柜臺(tái)系統(tǒng),由于開(kāi)放性不夠,被CTP從第一的位置擠下,目前因歷史遺留還有部分期貨公司在使用。

金仕達(dá)所接的市場(chǎng)很多,期貨、個(gè)股期權(quán)、證券,以及貴金屬現(xiàn)貨。

金仕達(dá)證券接口還是老式的不支持主動(dòng)推送的接口,所以在ETF期權(quán)上市時(shí),在期貨公司推擴(kuò)證券柜臺(tái)也不順利。而在貴金屬現(xiàn)貨接口上又推廣不力,現(xiàn)已被飛鼠占去先機(jī)。

公司網(wǎng)址:http:// www.sungard.cn/


1.1.3 飛馬Femas、飛創(chuàng)XSpeed、易勝Esunny

分別由中國(guó)金融期貨信息技術(shù)有限公司(是中國(guó)金融期貨交易所期下子公司)、大連飛創(chuàng)信息技術(shù)有限公司(大連商品交易所旗下子公司)、易盛信息技術(shù)有限公司(鄭州商品交易所期下子公司)。


在2015年股災(zāi)之前,程序化交易監(jiān)管較弱,高頻交易火爆,如果使用每家專(zhuān)用的API,期貨公司可以提供離交易所機(jī)柜更近的主機(jī)托管業(yè)務(wù)。但現(xiàn)在高頻交易策略無(wú)法施展的情況下,用流行的CTP更省事。

他們的公司網(wǎng)址分別為:

Femas:http://www.cffexit.com.cn/

XSpeed:http://www.dfitc.com.cn/

Esunny:http://www.esunny.com.cn/


1.1.4 飛鼠Sgit

上海飛鼠軟件科技有限公司,一家主要提供跨市場(chǎng)交易解決方案的公司,提供了飛鼠API,可以接入期貨、外盤(pán)、黃金現(xiàn)貨。目前需要做黃金T+D程序化交易的用戶一般會(huì)選擇此接口。公司網(wǎng)址:http://www.feishutech.com.cn/


1.1.5 恒生UFX

恒生電子同時(shí)提供了證券、期貨經(jīng)紀(jì)業(yè)務(wù)解決方案的提供商,在機(jī)構(gòu)用戶中占有率極高。機(jī)構(gòu)通過(guò)UFX接入到恒生O32系統(tǒng)中進(jìn)行事前風(fēng)控。

因?yàn)榻鹑诋a(chǎn)品太多、業(yè)務(wù)復(fù)雜,導(dǎo)致字段也多。UFX更多的是類(lèi)似于通訊協(xié)議數(shù)據(jù)包打包器。用戶在開(kāi)發(fā)時(shí)需要對(duì)照數(shù)據(jù)字典一個(gè)個(gè)自己組織請(qǐng)求包,使用起來(lái)比較麻煩。

公司網(wǎng)址:http://www.hundsun.com/


1.2 Python封裝


1.2.1 封裝原理

基本上,所有官方提供的接口都是C++接口,少量老的證券接口還提供C接口。C++接口導(dǎo)出了C++類(lèi),而其它語(yǔ)言中的類(lèi)都是自己語(yǔ)言中經(jīng)過(guò)特殊設(shè)計(jì)的,無(wú)法直接利用C++類(lèi)。因此必須將C++接口轉(zhuǎn)換成簡(jiǎn)單的C接口,將原接口函數(shù)中隱式的this指針改成顯式的void*指針傳入,這樣才能在其它語(yǔ)言中進(jìn)行調(diào)用。

還需要解決結(jié)構(gòu)體的傳入、傳出與回調(diào)函數(shù)的實(shí)現(xiàn),然后再進(jìn)一步簡(jiǎn)單的用各種語(yǔ)言封裝調(diào)用時(shí)的請(qǐng)求與響應(yīng),使用起來(lái)就方便了。


1.2.2 vn.py與XAPI

目前市面上主要的開(kāi)源Python封裝有vn.py與XAPI兩款,其它的Python開(kāi)源項(xiàng)目,已經(jīng)不再維護(hù)或用戶量極少,所以這就不再介紹了,有興趣的朋友請(qǐng)網(wǎng)上搜索。



由于vn.py在官網(wǎng)已經(jīng)有齊全的文檔,本人對(duì)它也沒(méi)有更深入的研究,所以在這只介紹自己開(kāi)源的XAPI。


1.2.3 XAPI的迭代歷史

一開(kāi)始是為了對(duì)接OpenQuant3這款軟件的個(gè)人項(xiàng)目,參考了海風(fēng)開(kāi)源的CTP C#版接口,不同的地方是將一些復(fù)雜的邏輯由C#層移動(dòng)到C層,簡(jiǎn)化上層的開(kāi)發(fā)。

為了推廣OpenQuant3,所以決定將代碼整理轉(zhuǎn)成開(kāi)源項(xiàng)目。由于Femas和XSpeed的推出,當(dāng)時(shí)參考了CTP的封裝方法,封裝了其它幾個(gè)接口和OpenQuant3的插件。但這種老式的封裝方法工作量大,C#層和應(yīng)用層有多少種接口就需要封裝多少套,難于維護(hù)。

2015年同樣是海風(fēng)推出的新版封裝里有動(dòng)態(tài)延遲加載dll的示例,學(xué)習(xí)研究后,決定對(duì)接口進(jìn)行重新設(shè)計(jì),統(tǒng)一不同API的結(jié)構(gòu)體為同一套,命名為XAPI。

后來(lái)根據(jù)網(wǎng)友的建議,對(duì)項(xiàng)目的命名空間、目錄結(jié)構(gòu)重新調(diào)整,升級(jí)為XAPI2。

專(zhuān)門(mén)設(shè)計(jì)的C接口,所以各種語(yǔ)言版本的封裝陸續(xù)推出,.NET、Java、MATLAB、COM、Python。


1.2.4 XAPI設(shè)計(jì)思想:

1. 能接入主要的接口。根據(jù)流行程序來(lái)考慮是否優(yōu)先接入;

2. 滿足基本的交易功能。拋棄了不常用的功能,如銀期轉(zhuǎn)賬功能;

3. 能支持不同的語(yǔ)言。一定要導(dǎo)出C接口;

4. 簡(jiǎn)化上層代碼的開(kāi)發(fā)。將流控,請(qǐng)求ID,請(qǐng)求發(fā)送隊(duì)列等各項(xiàng)基本功能都封裝在C層。


XAPI的核心就是隊(duì)列。XAPI的隊(duì)列數(shù)據(jù)格式與只有一個(gè)XRequest導(dǎo)出函數(shù)的dll風(fēng)格完全一樣。一個(gè)字節(jié)大小的數(shù)據(jù)包類(lèi)型,兩個(gè)指針,兩個(gè)雙精度數(shù)字,三個(gè)內(nèi)存區(qū)指針和三個(gè)內(nèi)存區(qū)大小數(shù)值,在目前的行情交易接口開(kāi)發(fā)中基本夠用。

上層的函數(shù)調(diào)用被封裝成數(shù)據(jù)包,添加到請(qǐng)求隊(duì)列中,另一線程從請(qǐng)求隊(duì)列中取內(nèi)容,然后調(diào)用API的各種函數(shù),用這種方法來(lái)解決流控,請(qǐng)求ID遞增等問(wèn)題。

收到的響應(yīng)也復(fù)制打包好后放入響應(yīng)隊(duì)列,另一線程從響應(yīng)隊(duì)列中取內(nèi)容,調(diào)用注冊(cè)好的回調(diào)函數(shù)通知到上層,解決應(yīng)用層策略耗時(shí)過(guò)久可能導(dǎo)致底層崩潰的問(wèn)題。


1.3 安裝


1.3.1 Python環(huán)境

由于大部分接口只推出了32位版,而在Windows中同一進(jìn)程中32位與64位不能相互調(diào)用,所以Python也只能選擇32位的進(jìn)行安裝。目前CTP接口有64位版,有興趣的朋友可以自行編譯XAPI項(xiàng)目為64位版。

Python2.7不再推薦,推薦使用3.6及以上版本,做量化交易要用到的庫(kù)基本都已經(jīng)支持Python3。


1.3.2 XAPI安裝

訪問(wèn)https://github.com/QuantBox/XAPI2/,點(diǎn)擊Clone or download按鈕,選擇Download ZIP進(jìn)行下載。

下載比同步repo的方式要快,對(duì)于沒(méi)有能力貢獻(xiàn)代碼的朋友來(lái)說(shuō),zip方式最快速直接。

解壓zip文件,目錄眾多,對(duì)于Python用戶來(lái)說(shuō),如果不自行編譯,只需要關(guān)注languages\Python這個(gè)文件夾即可,如果涉及需要編譯dll的工作才需要其它文件夾下的項(xiàng)目。由于編譯工作對(duì)一些用戶來(lái)說(shuō)有難度,還得下載安裝VisualStudio 2015,用戶可以加入Readme.md中提到的QQ群,到群中下載已經(jīng)編譯打包好的dll。

“缺少依賴(lài)庫(kù)”是很多用戶遇到最基礎(chǔ)最常見(jiàn)的問(wèn)題,本項(xiàng)目為了接入不同的API,每套API都要做一套C封裝,這些封裝都需要C++運(yùn)行時(shí)庫(kù),為了減少發(fā)布包的大小,運(yùn)行時(shí)庫(kù)使用的動(dòng)態(tài)編譯,這樣C++運(yùn)行時(shí)庫(kù)就能共享一套,它們默認(rèn)放在了C:\Windows\System32或C:\Windows\SysWOW64\。這就導(dǎo)致在一臺(tái)電腦上能正常使用,復(fù)制到另一臺(tái)電腦上由于忘記復(fù)制C++運(yùn)行時(shí)庫(kù)就不能用了。

其實(shí)還有XAPI下還有一個(gè)隊(duì)列庫(kù)Queue_x86.dll/Queue_x86d.dll也是每個(gè)C封裝都需要用到,并且它還有Debug與Release版本,由于C++中的new/delete必須與C++運(yùn)行時(shí)庫(kù)Debug/Release對(duì)應(yīng)的問(wèn)題,所以這兩個(gè)版本不能混用。

不能運(yùn)行一定是缺少依賴(lài)庫(kù)導(dǎo)致嗎?網(wǎng)上下載depends(http://www.dependencywalker.com/)查看CTP_Trade_x86.dll,從能正常運(yùn)行的電腦上將缺少的庫(kù)復(fù)制到其它電腦相應(yīng)系統(tǒng)文件夾下即可。

同時(shí)也需要注意32位與64位的問(wèn)題,很多同名文件是是同時(shí)存在32位與64位的區(qū)別的,32位版本放C:\Windows\SysWOW64\下,64位版本放C:\Windows\System32下。


圖1.depends查看dll示例


圖中演示的是用depends查看CTP_Trade_x86.dll,由于缺少Q(mào)ueue_x86d.dll, Python在調(diào)用它時(shí)會(huì)提示“找不到指定的模塊”。CTP_Trade_x86.dll是32位的dll,圖中顯示的c:\windows\system32路徑實(shí)際上是訪問(wèn)的c:\windows\syswow64。將Queue_x86d.dll文件復(fù)制到C:\Windows\SysWOW64下即可。

對(duì)這些細(xì)節(jié)不想了解的用戶直接運(yùn)行群共享提供的安裝包(統(tǒng)一接口完整版.zip)中的“X1.復(fù)制bin和System32目錄_需右鍵以管理員身份運(yùn)行.bat”就可以省去以上所有麻煩。


1.4 運(yùn)行測(cè)試


默認(rèn)提供了test_ctp_api.py/test_tdx_api.py兩個(gè)完整的腳本用來(lái)測(cè)試,它們分別實(shí)現(xiàn)了期貨和股票的目標(biāo)調(diào)倉(cāng)功能,只要在文件中設(shè)置好每個(gè)金融產(chǎn)品的目標(biāo)持倉(cāng)、多空方向和數(shù)量,就能以最快的速度調(diào)整成指定的倉(cāng)位。

對(duì)于每天交易頻率不高,使用日線數(shù)據(jù)計(jì)算策略,然后第二天早上進(jìn)行交易的機(jī)構(gòu)用戶來(lái)說(shuō),這兩個(gè)腳本完全可以直接使用。


1.4.1 配置賬號(hào)與服務(wù)器

目錄下出現(xiàn)了config.py、config_default.py、config_override.py和config_tdx.py四個(gè)以config開(kāi)頭的文件。

config_default.py/config_override.py:分別是CTP的默認(rèn)配置和CTP的特殊配置,為了實(shí)現(xiàn)特殊配置覆蓋默認(rèn)配置,config.py中實(shí)現(xiàn)了覆蓋重復(fù)字段的功能。

config_tdx.py中沒(méi)有CTP配置中那么復(fù)雜,直接就是配置信息。


#!/usr/bin/env python

# -*- coding: utf-8 -*-

configs = {

    # 根據(jù)目錄,存放交易清單和中間文件等信息

   'root_dir': r'd:' + '\\test_tdx',

    # 交易,這下面的配置要求需要參考每種API的說(shuō)明文檔

    'td': {

        #TDX安裝目錄,注意最后有一個(gè)\

       'ExtInfoChar128': br'D:\new_hbzq' + b'\\',

        # 登錄腳本。注意路徑出現(xiàn)中文需要轉(zhuǎn)碼

        'Address':r'd:\test_tdx\Login_東方財(cái)富證券.lua'.encode('GBK'),

        # 資金賬號(hào)

       'UserID': b'123456',

        # 用戶密碼

       'Password': b'654321',

        # 通迅密碼。注意,不是驗(yàn)證碼,不需要通迅密碼的券商請(qǐng)留空

       'ExtInfoChar64': br'',

    },

}


注意配置文件中很多字符串出現(xiàn)了b前綴。這是因?yàn)閄API的結(jié)構(gòu)體對(duì)應(yīng)字段就是C中的字?jǐn)?shù)數(shù)組,b就是原始的bytes,我們將字符串直接傳入。中文路徑不能直接使用b前綴,需要先encode轉(zhuǎn)換成bytes后才能使用。


1.4.2 編輯目標(biāo)倉(cāng)位文件

前面在config_default.py中已經(jīng)配置了root_dir文件路徑為d:\test_ctp。編輯其中的target_position.csv文件,下單時(shí)將從這它讀取目標(biāo)倉(cāng)位。

不知道配置怎么辦?登錄成功后先輸入2查詢當(dāng)前持倉(cāng),然后輸入12將當(dāng)前持倉(cāng)保存到target_position.csv。


Symbol,InstrumentID,HedgeFlag,Side,Position,InstrumentName

i1709.,i1709,0,1,5.0,

i1709.,i1709,0,-1,0.0,

rb1710.,rb1710,0,-1,6.0,


Symbol:合約唯一代碼,XAPI內(nèi)部使用。由InstruemntID與ExchangeID組合而成;

InstrumentID:合約代碼,供API使用,必須與對(duì)應(yīng)API的合約代碼完全一樣,如果對(duì)應(yīng)API區(qū)分大小寫(xiě),這里也得區(qū)分;

HedgeFlag:投機(jī)套保標(biāo)志,默認(rèn)為0,這個(gè)功能一般是機(jī)構(gòu)使用,機(jī)構(gòu)可能出現(xiàn)同時(shí)持有投機(jī)倉(cāng)位與套保倉(cāng)位的情況;

Side:多空方向,1表示多,-1表示空;

Position:持倉(cāng)數(shù)量,正數(shù);

InstrumentName:合約名稱(chēng)。只用于顯示,可為空,股票中表示股票名稱(chēng)。


Symbol,InstrumentID,HedgeFlag,Side,Position,InstrumentName

000001,000001,0,1,400.0,平安銀行

000002,000002,0,1,200.0,萬(wàn) 科A

300001,300001,0,1,300.0,特銳德

300024,300024,0,1,200.0,機(jī)器人

 

對(duì)于前面提到的csv文件,如何清倉(cāng)、反手、鎖倉(cāng)呢?

清倉(cāng):即沒(méi)有項(xiàng)目,或?qū)?yīng)的Position為0即可

Symbol,InstrumentID,HedgeFlag,Side,Position,InstrumentName

 

反手:只要改對(duì)應(yīng)項(xiàng)目的Side的正負(fù)號(hào)即可

Symbol,InstrumentID,HedgeFlag,Side,Position,InstrumentName

i1709.,i1709,0,-1,5.0,

rb1710.,rb1710,0,1,6.0,

鎖倉(cāng):同合約多空持倉(cāng)數(shù)量相等即可

Symbol,InstrumentID,HedgeFlag,Side,Position,InstrumentName

i1709.,i1709,0,1,5.0,

i1709.,i1709,0,-1,5.0,

rb1710.,rb1710,0,1,6.0,

rb1710.,rb1710,0,-1,6.0,


1.4.3 運(yùn)行腳本

直接運(yùn)行會(huì)打印一個(gè)選擇菜單,然后等待用戶輸入。菜單的主要內(nèi)容如下:


1 - 讀取目標(biāo)倉(cāng)位

2 - 查詢實(shí)盤(pán)倉(cāng)位

3 - 訂閱行情

4 - 計(jì)算交易清單

5 - 批量下單

6 - 需延遲通過(guò)回報(bào)批量撤單


它就是目標(biāo)倉(cāng)位調(diào)整的主要流程:

1 - 首先從本地的target_position.csv讀取設(shè)置的目標(biāo)倉(cāng)位;

2 - 從實(shí)盤(pán)柜臺(tái)上查詢當(dāng)前的持倉(cāng);

3 - 根據(jù)目標(biāo)倉(cāng)位和實(shí)盤(pán)持倉(cāng)合并得到要下單的合約集合,訂閱合約的行情,后面下單時(shí)需要用到最新的行情價(jià)格;

4 - 對(duì)比目標(biāo)倉(cāng)位和實(shí)盤(pán)持倉(cāng),得到交易清單,這個(gè)清單已經(jīng)處理好了買(mǎi)賣(mài)方向與開(kāi)平方向等問(wèn)題,對(duì)于上期所的的今倉(cāng)與昨倉(cāng)分兩筆下單;

5 - 根據(jù)上一步生成的交易清單直接下單;

6 - 下單后并不是瞬間成交,還需要等待幾秒,然后撤單。

人工循環(huán)執(zhí)行2到6步,直到交易清單為空。注意有些情況下可能成交失敗,交易清單永遠(yuǎn)不為空。例如:

1.    資金不夠

2.    漲跌停,買(mǎi)入或賣(mài)出無(wú)法成交

3.    進(jìn)入交割月了,交易手限制為整數(shù)倍,而下單手?jǐn)?shù)不合要求

4.    股票停牌

 

有時(shí)輸入這些數(shù)字也可能輸入錯(cuò)誤,我們提供了一個(gè)更簡(jiǎn)化的選項(xiàng):

7 - 順序執(zhí)行1-6

 

只要輸入7,就會(huì)自動(dòng)執(zhí)行1至6三次,直到交易清單為空或出錯(cuò)。


1.4.4 輔助菜單

這些是相當(dāng)重要的菜單,也需要關(guān)注一下。

21 - 查合約列表(至少執(zhí)行一次)

22 - 查資金

23 - 取消訂閱行情

24 - 打印訂單

 

33– 切換行情顯示

 

q - 退出

21 - 從柜臺(tái)上查詢合約列表,并保存在本地。它保存了每個(gè)合約的最小變動(dòng)價(jià)位,用于計(jì)算買(mǎi)賣(mài)時(shí)加幾跳時(shí)具體加的是多少價(jià)格。如果不查詢默認(rèn)最小變動(dòng)價(jià)位為1。對(duì)于某些合約使用默認(rèn)1將產(chǎn)生錯(cuò)誤。

對(duì)于cu銅,最小變動(dòng)價(jià)位是10,如果使用默認(rèn)1,加2跳,價(jià)格將不滿足最小變動(dòng)價(jià)格整數(shù)倍的條件。

對(duì)于IF滬深300,最小變動(dòng)價(jià)位是0.2,如果使用默認(rèn)1,加2跳,價(jià)格實(shí)際上加了10跳。

所以這個(gè)地方至少要執(zhí)行一次,每次有新品種上市時(shí)也得查一次。

22 - 查賬號(hào)資金

33 – 切換行情顯示。對(duì)于CTP的主推行情,由于行情一直在界面中打印,干擾使用,所以提供了一個(gè)開(kāi)關(guān)進(jìn)行切換。

q – 人工輸入模式會(huì)一直等待用戶輸入,輸入‘q’可以退出


1.4.4 倉(cāng)位相關(guān)菜單

11 - 合并對(duì)沖多個(gè)組合到目標(biāo)持倉(cāng)

12 - 回寫(xiě)查詢持倉(cāng)到目標(biāo)持倉(cāng)

13 - 合并對(duì)沖目標(biāo)持倉(cāng)和增量倉(cāng)到目標(biāo)持倉(cāng)

 

1 - 讀取目標(biāo)倉(cāng)位

2 - 查詢實(shí)盤(pán)倉(cāng)位


是否覺(jué)得要自己手工編寫(xiě)target_position.csv很麻煩呢?只要運(yùn)行菜單2后再運(yùn)行12就會(huì)將前一步查詢出來(lái)的持倉(cāng)寫(xiě)入到target_position.csv,然后再手工編輯少量即可。

一個(gè)實(shí)盤(pán)賬號(hào)下跑了N個(gè)策略,分別生成了不同的持倉(cāng)文件,能否先內(nèi)部對(duì)沖一下?我們提供了11這個(gè)菜單項(xiàng),它能將portfolio_1.csv/portfolio_2.csv/portfolio_3.csv三個(gè)文件中的持倉(cāng)合并,對(duì)沖,然后寫(xiě)入到target_position.csv中。

如果投資組合數(shù)超過(guò)3個(gè),請(qǐng)自己手工編輯代碼支持更多組合。

每天的投資組合清單都已經(jīng)生成,但我盤(pán)中想改總持倉(cāng)怎么辦?這個(gè)改動(dòng)是算在哪個(gè)策略對(duì)應(yīng)的投資組合呢?建議根據(jù)策略數(shù)量N創(chuàng)建N+1個(gè)投資組合,第N+1個(gè)組合文件中內(nèi)容為空,當(dāng)需要人工調(diào)整時(shí)倉(cāng)位都放在第N+1個(gè)投資組合中。

如果我的策略邏輯并不是根據(jù)持倉(cāng)數(shù)來(lái)計(jì)算,而是根據(jù)買(mǎi)賣(mài)數(shù)量呢?例如今天買(mǎi)入2手,而不是今天倉(cāng)位是2手。這時(shí)就要用到菜單項(xiàng)13了,它會(huì)將target_position.csv和incremental_position.csv的持倉(cāng)合并,不對(duì)沖,然后再寫(xiě)回target_position.csv。

用戶一定要根據(jù)自己的實(shí)際情況靈活運(yùn)用以上倉(cāng)位相關(guān)的菜單,建議大家策略邏輯使用目標(biāo)倉(cāng)位法,而不是買(mǎi)賣(mài)法。


1.4.5股票相關(guān)功能

目前Tdx接口沒(méi)有實(shí)現(xiàn)查詢股票列表功能,所以菜單項(xiàng)21無(wú)效。股票無(wú)法賣(mài)空,所以target_position.csv中的Side都只能填1。

原本Tdx柜臺(tái)就沒(méi)有實(shí)現(xiàn)主動(dòng)推送委托回報(bào)和成交回報(bào)的功能,只能過(guò)一會(huì)后去主動(dòng)查詢委托列表,所以股票接口只能等待一會(huì)后直接撤單,然后直接查持倉(cāng),不再關(guān)心委托回報(bào)這些細(xì)節(jié)。


1.5 無(wú)人值守(自動(dòng)化)


無(wú)人值守是每個(gè)程序化交易員的目標(biāo)。這里提供一個(gè)可用的參考。每天晚上數(shù)據(jù)都自動(dòng)下載到服務(wù)器上,策略程序定時(shí)加載數(shù)據(jù)生成交易清單,第二天早上開(kāi)盤(pán)自動(dòng)全下,下完后日志自動(dòng)發(fā)郵件到QQ郵箱,微信立即在手機(jī)上提醒新郵件??梢詤⒖纪夸浵聄unme_auto2.bat等文件。


1.5.1 命令行參數(shù)

test_ctp_api.py/test_tdx_api.py默認(rèn)在運(yùn)行時(shí)都是手工輸入,其實(shí)還提供了一個(gè)參數(shù)“—input”。

“--input=11;7”表示先運(yùn)行菜單項(xiàng)11,然后運(yùn)行菜單項(xiàng)7。即先從幾個(gè)子組合csv文件中合并持倉(cāng),然后循環(huán)下單,下完單后退出。


REM 11 合并持倉(cāng)

REM 22 查資金

REM 7 循環(huán)下單

set date_Ymd=%date:~0,4%%date:~5,2%%date:~8,2%

python.exe test_ctp_api.py --input=11;22;7;221>log/%date_Ymd%.log 2>&1


如何自動(dòng)保存日志呢?我們使用到了DOS重定向。

<>

>:新建模式輸出到文件

>>:追加模式輸出到文件

>&:將一個(gè)句柄輸出寫(xiě)入到另一個(gè)句柄的輸入中

<>

0:標(biāo)準(zhǔn)輸入,令在執(zhí)行時(shí)所要的輸入數(shù)據(jù)通過(guò)它來(lái)取得

1:標(biāo)準(zhǔn)輸出,命令執(zhí)行后的輸出結(jié)果從該端口送出

2:標(biāo)準(zhǔn)錯(cuò)誤,命令執(zhí)行時(shí)的錯(cuò)誤信息通過(guò)該端口送出

1>log/%date_Ymd%.log2>&1 表示將標(biāo)準(zhǔn)輸出指向log日志文件,然后將標(biāo)準(zhǔn)錯(cuò)誤都輸出到標(biāo)準(zhǔn)輸出中。這樣標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤就都輸出到log文件了。如果將2>&1放到前面,則達(dá)不到效果,錯(cuò)誤還是輸出到了窗口中,因?yàn)檫@時(shí)標(biāo)準(zhǔn)輸出還沒(méi)有被重定向。


1.5.2  發(fā)送郵件


python mail.py --username=123456--password=654321 --from=123456@qq.com

    --to=123456@qq.com;654321@qq.com--log=log --bat=%~f0


推薦使用QQ郵箱來(lái)收發(fā)通知郵件,收件箱使用QQ郵箱是因?yàn)槭盏洁]件后微信能立即提醒。發(fā)件箱與收件箱使用同一家是因?yàn)檫@樣郵件到達(dá)更快。

--username=用戶名

--password=密碼/授權(quán)碼。QQ郵箱為了防止在第三方客戶端登錄時(shí)密碼被盜,使用授權(quán)碼來(lái)代替密碼進(jìn)行登錄。

--from=發(fā)件箱。username賬號(hào)所對(duì)應(yīng)的發(fā)件箱

--to=收件箱??梢詫?xiě)多個(gè)郵箱。使用英文“;”進(jìn)行分隔

通過(guò)QQ郵箱的,設(shè)置->賬戶->SMTP服務(wù),開(kāi)啟SMTP發(fā)信功能,同時(shí)申請(qǐng)授權(quán)碼。


1.5.3  計(jì)劃任務(wù)

按Win鍵后,輸入taskschd就會(huì)定位到“任務(wù)計(jì)劃程序”。

1.    創(chuàng)建基本任務(wù)

2.    觸發(fā)器選擇“每周”,將“星期一”至“星期五”都選上,開(kāi)始時(shí)間選擇正確,比如8:59:55開(kāi)始,這樣算上登錄和查持倉(cāng)的時(shí)間,差不多9點(diǎn)正好下到柜臺(tái)。請(qǐng)保證服務(wù)器時(shí)間與互聯(lián)網(wǎng)時(shí)間同步。

3.    操作選擇“啟動(dòng)程序”,“程序或腳本”填為bat文件路徑,“起始于”填為bat文件所在路徑。由于bat和python代碼中大量用到了相對(duì)路徑,所以“起始于”這一項(xiàng)絕對(duì)不能為空。

4.    注意。計(jì)劃任務(wù)中不能出現(xiàn)阻塞進(jìn)程的代碼,比如不能在bat中加入pause或調(diào)用的python代碼長(zhǎng)時(shí)間不返回。否則任務(wù)運(yùn)行中,第二天的計(jì)劃任務(wù)不會(huì)觸發(fā)。


1.6 代碼解讀


前面介紹了基本的使用方法,對(duì)于很多用戶來(lái)說(shuō)就已經(jīng)完全足夠,但這里還是要對(duì)代碼簡(jiǎn)單解讀一下,方便遇到問(wèn)題時(shí)自行處理。

XApi.py/XSpi.py/XStruct.py/XEnum.py是核心代碼,使用ctypes模塊實(shí)現(xiàn)Python調(diào)用C。

XEnum.py中定義了枚舉類(lèi)型,包含值以及對(duì)應(yīng)的英文名。當(dāng)在結(jié)構(gòu)體中取到枚舉數(shù)值時(shí),通過(guò)這里的定義得到對(duì)應(yīng)的英文名。

XStruct.py中定義了結(jié)構(gòu)體,與C接口的結(jié)構(gòu)體一一對(duì)應(yīng),同時(shí)還為結(jié)構(gòu)體添加了一些函數(shù),方便使用,如__str__等。

XApi.py進(jìn)行API的各項(xiàng)調(diào)用,對(duì)收到的響應(yīng)進(jìn)行轉(zhuǎn)發(fā),如登錄、查詢、下單等。

XSpi.py回調(diào)接口,提供給第三方繼承使用。

MySpy.py繼承了XSpi的類(lèi),目前用來(lái)進(jìn)行實(shí)際目標(biāo)持倉(cāng)調(diào)整功能。

以CTP期貨交易接口封裝為例,CTP_Trade_x86.dll只導(dǎo)出了一個(gè)接口XRequest,需要對(duì)XRequest請(qǐng)求格式特別了解才能正確的調(diào)用,所以又在這之上套了一層X(jué)API_CPP_x86.dll,它導(dǎo)出了一些常用的C函數(shù)。接口封裝人員可以按自己的能力選擇合適自己的調(diào)用方式。

目前XApi.py中提供的方式是通過(guò)XAPI_CPP_x86.dll來(lái)調(diào)用CTP_Trade_x86.dll。


1.6.1 登錄


    # 創(chuàng)建XApi對(duì)象,設(shè)置服務(wù)器地址與賬號(hào)

td = XApi(r'C:\Program Files\SmartQuantLtd\OpenQuant 2014\XAPI\x86\XAPI_CPP_x86.dll')

td.ServerInfo.Address = config['td']['Address']

td.ServerInfo.BrokerID = config['td']['BrokerID']

td.UserInfo.UserID = config['td']['UserID']

td.UserInfo.Password = config['td']['Password']

 

# 指定加載的是CTP的交易模塊,設(shè)置不同的路徑可以加載其它模塊

ret = td.init(br'C:\Program Files\SmartQuantLtd\OpenQuant 2014\XAPI\x86\CTP\CTP_Trade_x86.dll')

if not ret:

    print(td.get_last_error())

    exit(-1)

print(ord(td.get_api_type()))

print(td.get_api_name())

print(td.get_api_version())

 

# 關(guān)鍵一步,注冊(cè)回調(diào)事件處理函數(shù)

td.register_spi(self)

# 連接并登錄

td.connect()


init()中的路徑如果加載的是CTP_Quote_x86.dll那實(shí)現(xiàn)的就是期貨行情相關(guān)功能,如果加載的是Tdx_Trade_x86.dll實(shí)現(xiàn)的就是股票交易功能。

register_spi()中需要傳入繼承了XSpi的類(lèi),在test_ctp_api.py中當(dāng)前類(lèi)MySpi繼承了XSpi。

connect()時(shí)會(huì)異步收到登錄狀態(tài)回報(bào),MySpi.OnConnectionStatus最先得到觸發(fā)。某一交易接口的登錄日志如下,最后的Done表示登錄的所有動(dòng)作都已經(jīng)執(zhí)行完,可以用來(lái)下單了。


OnConnectionStatus=Initialized

OnConnectionStatus=Connecting

OnConnectionStatus=Connected

OnConnectionStatus=Logining

OnConnectionStatus=Logined

[TradingDay=20170905;LoginTime=205957;SessionID=1:1314163388;InvestorName=;XErrorID=0;RawErrorID=0;Text=]

OnConnectionStatus=Confirming

OnConnectionStatus=Confirmed

OnConnectionStatus=Done


1.6.2 代碼調(diào)試

OnConnectionStatus等一些事件響應(yīng)函數(shù)中能下斷點(diǎn)調(diào)試嗎?實(shí)測(cè)在PyCharm中下斷點(diǎn),有輸出日志,但斷點(diǎn)完全不生效。

Stack Overflow上的網(wǎng)友是這樣解答的:在非Python線程中,你必須設(shè)置調(diào)試器機(jī)制才能正常工作(在Python線程創(chuàng)建時(shí)自動(dòng)設(shè)置了,但在非Python線程創(chuàng)建時(shí)沒(méi)有任何構(gòu)造函數(shù)鉤子,所以得自己做)。在你需要下斷點(diǎn)的代碼前加入如下代碼即可。


import pydevd

pydevd.settrace(suspend=False,trace_only_current_thread=True)


你需要使用pip install pydevd先安裝pydevd。


1.6.3 行情訂閱

創(chuàng)建行情XAPI實(shí)例,對(duì)它設(shè)置行情接口庫(kù)CTP_Quote_x86.dll,設(shè)置行情服務(wù)器的地址和端口號(hào)。不要弄混,對(duì)交易接口訂閱行情是無(wú)效的。

 

ret = md.init(br'C:\Program Files\SmartQuantLtd\OpenQuant 2014\XAPI\x86\CTP\CTP_Quote_x86.dll')


訂閱行情傳入的合約代碼也必須是有b前綴。

# 可直接傳字一個(gè)用;分隔的字符串

md.subscribe(b'cu1709;SR801',b'')

 

# 或做一次轉(zhuǎn)碼再傳入

symbols_ = pd.Series(symbols).str.encode('gbk')

for i in range(len(symbols_)):

    md.subscribe(symbols_[i],b'')

 

會(huì)在OnRtnDepthMarketData(self,ptr1, size1)中收到行情回報(bào),ptr1是行情數(shù)據(jù)指針,size1是行情數(shù)據(jù)大小。其它OnXxx事件,輸出的參數(shù)都是Python對(duì)象,只有行情接口特殊輸出的是內(nèi)存指針。因?yàn)闉榱酥С侄鄼n行情,行情結(jié)構(gòu)體設(shè)計(jì)成了可變內(nèi)存塊。就算是股票的五檔行情,在漲跌停時(shí),這個(gè)內(nèi)存塊的大小都是不一樣的。

那如何取數(shù)據(jù)呢?使用的ctypes的cast即可


obj = cast(ptr1,POINTER(DepthMarketDataNField)).contents

# 打印行情,一般情況下都是關(guān)閉,因?yàn)閮?nèi)容太多了

print(obj)

 

#賣(mài)五價(jià)

ask_count = obj.get_ask_count()

if ask_count > 0:

    ask =obj.get_ask(ptr1, ask_count - 1)

 

# 買(mǎi)五價(jià)

bid_count = obj.get_bid_count()

if bid_count > 0:

    bid = obj.get_bid(ptr1, bid_count - 1)


對(duì)于CTP這種主動(dòng)行情推送的接口,只要訂閱了,行情有變化就會(huì)推送,OnRtnDepthMarketData會(huì)不停的被調(diào)用。而Tdx這種查詢模式的接口,查一次推送一次,所以需要根據(jù)策略需求查詢,不能高頻率查詢,否則嚴(yán)重影響服務(wù)器。


1.6.4 查詢持倉(cāng)


# 查詢持倉(cāng)請(qǐng)求

query =ReqQueryField()

td.req_query(QueryType.ReqQryInvestorPosition, query)

 

# 持倉(cāng)響應(yīng)

def OnRspQryInvestorPosition(self, pPosition,size1, bIsLast):

    if size1<=>

        return

 

    # 一定要用copy,不然最后一個(gè)會(huì)覆蓋前面的

    self.position_dict[pPosition.get_id()]= copy.copy(pPosition)

    if notbIsLast:

        return


當(dāng)賬號(hào)上沒(méi)有持倉(cāng),但還是需要通知到客戶端請(qǐng)求已經(jīng)得到響應(yīng)了,所以會(huì)傳回一個(gè)空數(shù)據(jù),所以需要對(duì)size1進(jìn)行判斷。


1.6.5 查詢資金

# 查資金請(qǐng)求

query = ReqQueryField()

td.req_query(QueryType.ReqQryTradingAccount,query)

 

# 資金響應(yīng)

def OnRspQryTradingAccount(self, pAccount, size1,bIsLast):

    if size1<=>

        return

    print(pAccount)

1.6.6 下單

# 提供臨時(shí)變量用于下單

order = (OrderField * 1)()

orderid = (OrderIDTypeField * 1)()

orderid[0].OrderIDType = b''

 

# 訂單參數(shù)

order[0].InstrumentID = b'IF1710'

order[0].ExchangeID = b''

order[0].Type = OrderType.Limit

order[0].Side = OrderSide.Buy

order[0].Qty = 1

order[0].OpenClose = OpenCloseType.Open

order[0].Price = 3500.0

 

# 下單

ret = td.send_order(order[0], orderid[0], 1)

 

# 打印

print('LocalID:%s'% ret)


注意,涉及到字符串的地方都需要b前綴。有關(guān)OrderType、OrderSide、OpenCloseType的取值,可以參考XEnum.py文件中對(duì)應(yīng)部分。

下完單后回收到委托回報(bào)和成交回報(bào),委托回報(bào)可以存儲(chǔ)起來(lái)用于立即撤單。


# 委托回報(bào)

def OnRtnOrder(self, pOrder):

    self.order_dict[pOrder.get_id()]= copy.copy(pOrder)

    print(pOrder)

 

# 成交回報(bào)

def OnRtnTrade(self, pTrade):

    print(pTrade)


1.6.7 撤單


在CTP接口中撤單需要三個(gè)字段,而XSpeed需要兩個(gè)字段,Tdx一個(gè)字段,由于每種接口都不一樣,為了簡(jiǎn)化,在XAPI中統(tǒng)一設(shè)計(jì)成通過(guò)一個(gè)唯一字段進(jìn)行撤單。這需要XAPI內(nèi)部維護(hù)一張映射表,在登錄時(shí)底層會(huì)查詢委托列表進(jìn)行映射表重建。所以如果今天下單極多,重新登錄時(shí)要等映射表重建完才能成功撤單。

OrderField中有三個(gè)字段跟識(shí)別訂單有關(guān):

OrderID是由交易所傳回來(lái)的id。如果想比較不同柜臺(tái)的速度,可以同時(shí)報(bào)單相同合約后比較OrderID的大小。

ID是XAPI維護(hù)的唯一ID,可用于撤單。需要保證在下一次重新登錄后還能通過(guò)委托回報(bào)計(jì)算出這個(gè)唯一ID。

LocalID是本地XAPI在下單時(shí)立即返回的id,它只供內(nèi)部臨時(shí)映射時(shí)使用,Tdx這類(lèi)的接口是下單返回后才能知道ID值,所以在柜臺(tái)返回之前XAPI維護(hù)一個(gè)臨時(shí)LocalID,等收到回報(bào)后就棄用LocalID。CTP接口中LocalID與ID是相等的,在Tdx中他們不相等


# 臨時(shí)變量

orderid = (OrderIDTypeField * 2)()

orderid[0].OrderIDType = b''

orderid[1].OrderIDType = b''

 

# 設(shè)置要撤單的ID

orderid[0].OrderIDType = order.ID

# 撤單

td.cancel_order(orderid[0],orderid[1], 1)


撤單ID最好從委托回報(bào)中取,而不是手工填,因?yàn)椴糠諥PI的ID前后可能出現(xiàn)空格,如果缺失了空格會(huì)導(dǎo)致找不到訂單。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
基于python的開(kāi)源交易平臺(tái)開(kāi)發(fā)框架
【其他】通達(dá)信程序化交易新發(fā)現(xiàn),通達(dá)信dll下單
Python 爬蟲(chóng)代理池
買(mǎi)到回家的票了嗎?用python刷票,還不快試試
Python接口自動(dòng)化之接口依賴(lài)
接口自動(dòng)化筆記
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服