有網(wǎng)友,在前兩個Demo的基礎(chǔ)上,開發(fā)了一個可實盤的Demo,剛好有代碼,就一并學(xué)習(xí)一下。
同樣是VC++的控制臺程序,程序可以實現(xiàn)一個品種的交易,如果連續(xù)TICK數(shù)據(jù)創(chuàng)新高的話,實現(xiàn)開倉,以及相應(yīng)的止贏和止損。
我們看文件,除了紅色外,其余都是在前面兩個Demo里認識的。所以,重點在于Common.h,DataSniffer.h和MyTrader.h文件,Common.h定義了一些共用函數(shù),DataSniffer負責交易數(shù)據(jù)的處理和計算(tick或是K線),并給出開倉信號。MyTrader是交易處理,開平倉和止贏止損。
![[轉(zhuǎn)載]CTP初次接觸四:網(wǎng)友的可實盤DEMO [轉(zhuǎn)載]CTP初次接觸四:網(wǎng)友的可實盤DEMO](http://image105.360doc.com/DownloadImg/2017/04/1315/96556701_2)
還要做點準備工作,先申請一個模擬帳戶,我可不想直接用實盤來測試。
上海期貨信息技術(shù)有限公司 提供的仿真注冊地址 http://www./index.jsp
這樣,我可以獲得CTP需要的一些地址、用戶名、密碼。注冊后要第二天,才能正常測試登陸。
char FRONT_ADDR_3A[] = "tcp://180.168.146.187:10000"; // 前置地址3交易:模擬交易
char FRONT_ADDR_3B[] = "tcp://180.168.146.187:10010"; // 前置地址3行情:模擬交易
//我的模擬號
TThostFtdcBrokerIDType BROKER_ID = "9999"; // 經(jīng)紀公司代碼:模擬
TThostFtdcInvestorIDType INVESTOR_ID = "******"; // 投資者代碼:模擬
TThostFtdcPasswordType PASSWORD = "******"; // 用戶密碼:模擬
我們要看看他們是如何工作的。程序入口在AutoTrader.cpp
一:先起來打掃衛(wèi)生:Erasefiles,清理流文件(臨時文件,存放系統(tǒng)數(shù)據(jù)),然后休息了一下 Sleep(2000)。
二:生成CThostFtdcTraderApiCTraderSpi交易類實體,CThostFtdcMdApiCThostFtdcMdSpi行情類實體
三:讀取一些默認的配置信息,ReadConfiguration,初始化工作完成。
四:然后進入行情跟蹤, Sniffer(),數(shù)據(jù)、信息的處理應(yīng)該在這里,策略和信號也寫在這里;
五:進入交易處理,Trading(),委托下單等處理在這里;
Erasefiles();
Sleep(2000);
cerr << "--->>> " << "Welcom MyAutoTrader System!" << endl;
cerr << "--->>> " << "Version 1.0.0!" << endl;
// 初始化UserApi
pUserApi = CThostFtdcTraderApi::CreateFtdcTraderApi("./thosttraderapi.dll"); // 創(chuàng)建UserApi//"./thosttraderapi.dll"
CTraderSpi* pUserSpi = new CTraderSpi();
pUserApi->RegisterSpi((CThostFtdcTraderSpi*)pUserSpi); // 注冊事件類
pUserApi->SubscribePublicTopic(THOST_TERT_RESTART); // 注冊公有流
pUserApi->SubscribePrivateTopic(THOST_TERT_RESTART); // 注冊私有流
pUserApi->RegisterFront(FRONT_ADDR_1A); // connect
pUserApi->Init();
cerr << "--->>> " << "Initialing UserApi" << endl;
// 初始化MdApi
pMdApi = CThostFtdcMdApi::CreateFtdcMdApi("./thostmduserapi.dll"); // 創(chuàng)建MdApi//"./thostmduserapi.dll"
CThostFtdcMdSpi* pMdSpi = new CMdSpi();
pMdApi->RegisterSpi(pMdSpi); // 注冊事件類
pMdApi->RegisterFront(FRONT_ADDR_1B); // connect 優(yōu)先行情地址
pMdApi->RegisterFront(FRONT_ADDR_2B); // connect 備用行情地址,1B斷開,自動連接2B地址
pMdApi->Init();
cerr << "--->>> " << "Initialing MdApi" << endl;
//pMdApi->Join();
//pMdApi->Release();
Sleep(6000);
ReadConfiguration("./AutoTrader.dat"); //自定義數(shù)據(jù),如持倉數(shù)據(jù)等均可
cerr << "--->>> " << "初始化完成!" << endl;
while(1)
{
//指標計算,下面只是個簡單例子
//可自建函數(shù),進行復(fù)雜處理 見DataSniffer.h
Sniffer();
//下單控制
//可自建函數(shù),單獨復(fù)雜處理 見MyTrader.h
Trading();
Sleep(050);
}
我們看看Sniffer的行情處理,相當于計算行情出交易信號,Sniffer在DataSniffer.h里。這個函數(shù)里,寫了一個高頻策略,他取得3次的TICK數(shù)據(jù),如果連續(xù)3個TICK上漲,他認為是一次好的買入機會,把某個標志改成“需要買入”狀態(tài)。同理,還有“需要賣出”狀態(tài)。
void Sniffer() //監(jiān)聽Tick數(shù)據(jù)已經(jīng)指標計算
{
if (RunMode && Q_BarTime_2>=0.1500 && CloseAll==false)
{
cerr << "--->>> " <<TradingDay<<"準備收盤!" << endl;
cerr << "--->>> " <<"WriteConfiguration!" << endl;
WriteConfiguration("./AutoTrader.cfg"); //備份數(shù)據(jù)
Sleep(3000);
//ErasingTradeConfiguration();
cerr << "--->>> " <<TradingDay<<"收盤!" << endl;
CloseAll=true;
}
if (TickAPrice[0]>TickAPrice[1] && TickAPrice[1]>TickAPrice[2] && TickAPrice[2]>TickAPrice[3])
{
TickABS=1; //連續(xù)3個TICK漲,buy
}
else if (TickAPrice[0]
{
TickABS=2; //連續(xù)3個TICK跌,Sell
}
else
{
TickABS=0;
}
}
我們看看Trading的交易處理,根據(jù)行情信號
Sniffer,進行下單
Trading。
1、他先看看,前面有沒有單了,如果有單子,看看是否需要止贏和止損不。StopLoss(),里面代碼的細節(jié)和我們平時說的止贏止損是一樣的;
2、然后他就讀了前面Sniffer給出的買賣信號。以買信息為例:先看看有沒有空單,有的話,先平掉SendOrder(INSTRUMENT_ID, 0, 3)。買平成功后,下買開倉委托單:SendOrder(INSTRUMENT_ID, 0, 0);
3、sendorder是一個在Common.h里自定義的一個函數(shù)。根據(jù)參數(shù)不同,他可以實現(xiàn)買開、賣開、買平、賣平這些功能。它相當于對CTP-API的ReqOrderInsert封裝吧,這個函數(shù)參數(shù)很復(fù)雜,封裝起來使用方便多了。
至此,代碼一個循環(huán)就結(jié)束了。系統(tǒng)繼續(xù)監(jiān)測行情的變化、判斷計算信息、并做出交易處理。
幾個細節(jié),我們需要再看一下。
細節(jié)1、之前行情處理時,用到3個tick數(shù)據(jù)的比較,這些數(shù)據(jù)存在一個數(shù)組里TickAPrice[]。CMdSpi類在接到服務(wù)器的數(shù)據(jù)后,會觸發(fā)函數(shù)OnRtnDepthMarketData,這個函數(shù)將最新的tick數(shù)據(jù)保存到數(shù)組里,并將之前3個tick的數(shù)據(jù)也保存起來,供后面策略進行tick數(shù)據(jù)比較。
同時,將tick數(shù)據(jù)保存到了txt文件里。./TickData/ag1512_20151102.txt
ofstream o_file(TickFileWritepaths,ios::app);
o_file <<......<<endl;
細節(jié)2、OnRtnDepthMarketData這個函數(shù)還做了一件重要的事情,就是生成了1分鐘K線,這個demo沒有保存1分鐘數(shù)據(jù)。在第三方交易平臺上,使用K線數(shù)據(jù)是很自然的事情,但是自已開發(fā)的平臺,則需要自己維護K線數(shù)據(jù)了,這是一件很基礎(chǔ)、很重要、很繁瑣的事情。
細節(jié)3、因為軟件是控制臺的程序,所以需要下載一個快期的交易程序進行對比,看看下單、交易是否正常。
控制臺程序跑起來的樣子
![[轉(zhuǎn)載]CTP初次接觸四:網(wǎng)友的可實盤DEMO [轉(zhuǎn)載]CTP初次接觸四:網(wǎng)友的可實盤DEMO](http://image105.360doc.com/DownloadImg/2017/04/1315/96556701_3)
控制臺下單時的輸出情況
![[轉(zhuǎn)載]CTP初次接觸四:網(wǎng)友的可實盤DEMO [轉(zhuǎn)載]CTP初次接觸四:網(wǎng)友的可實盤DEMO](http://image105.360doc.com/DownloadImg/2017/04/1315/96556701_4)
快期的交易程序進行對比,控制臺下單后,快期就可以看到持倉(數(shù)據(jù)太快了,下了委托直接就成交了)
![[轉(zhuǎn)載]CTP初次接觸四:網(wǎng)友的可實盤DEMO [轉(zhuǎn)載]CTP初次接觸四:網(wǎng)友的可實盤DEMO](http://image105.360doc.com/DownloadImg/2017/04/1315/96556701_5)
注:我沒有深入調(diào)試他開倉和止贏止損的代碼,執(zhí)行結(jié)果看,有些不太如意的地方。但這不妨礙我們理解這個demo。
如果我們想對下單、撤單等等交易動作有深入了解,那就得進入細節(jié),了解DLL里有哪些功能和函數(shù)了。某論壇的ID"用python的交易員"說了函數(shù)的分類,
Api類包括的主動函數(shù)通常分為以下三種:
1、Create…,類的靜態(tài)方法,用于創(chuàng)建API對象,傳入?yún)?shù)是用來保存API通訊.con文件的文件夾路徑。
2、Req…開頭的函數(shù),可以由用戶主動調(diào)用的業(yè)務(wù)邏輯請求,傳入?yún)?shù)通常包括2個:業(yè)務(wù)請求結(jié)構(gòu)體指針和一個請求號的整數(shù)。
3、其他非Req…開頭的函數(shù),包括初始化、訂閱數(shù)據(jù)流等等參數(shù)較為簡單的功能,傳入?yún)?shù)的數(shù)量和類型視乎函數(shù)功能不一定。
Spi(包括MdSpi和TraderSpi)類的回調(diào)函數(shù)基本上可以分為以下四種:
1、以O(shè)n…開頭,這種回調(diào)函數(shù)通常是返回API連接相關(guān)的信息內(nèi)容,與業(yè)務(wù)邏輯無關(guān),返回值(即回調(diào)函數(shù)的參數(shù))通常為空或是簡單的整數(shù)類型。
2、以O(shè)nRsp…開頭,這種回調(diào)函數(shù)通常是針對用戶的某次特定業(yè)務(wù)邏輯操作返回信息內(nèi)容,返回值通常會包括4個參數(shù):業(yè)務(wù)邏輯相關(guān)結(jié)構(gòu)體的指針,錯誤信息結(jié)構(gòu)體的指針,本次操作的請求號整數(shù),是否是本次操作最后返回信息的布爾值。其中OnRspError主要用于一些通用錯誤信息的返回,因此返回的值中不包含業(yè)務(wù)邏輯相關(guān)結(jié)構(gòu)體指針,只有3個返回值。
3、以O(shè)nRtn…開頭,這種回調(diào)函數(shù)返回的通常是由柜臺向用戶主動推送的信息內(nèi)容,如客戶報單狀態(tài)的變化、成交情況的變化、市場行情等等,因此返回值通常只有1個參數(shù),為推送信息內(nèi)容結(jié)構(gòu)體的指針。
4、以O(shè)nErrRtn…開頭,這種回調(diào)函數(shù)通常由于用戶進行的某種業(yè)務(wù)邏輯操作請求(掛單、撤單等等)在交易所端觸發(fā)了錯誤,如用戶發(fā)出撤單指令、但是該訂單在交易所端已經(jīng)成交,返回值通常是2個參數(shù),即業(yè)務(wù)邏輯相關(guān)結(jié)構(gòu)體的指針和錯誤信息的指針。
至此,我們大致了解這個程序的邏輯。它實現(xiàn)了:用CTP登陸服務(wù)器、獲取和保存tick數(shù)據(jù)、實現(xiàn)了tick策略,計算1分鐘K線、下單和止贏止損。已經(jīng)很不錯了。
1、策略原代碼在這里下載
http://download.csdn.net/download/u014691164/7452351
2、模擬賬號在這里申請
http://www./index.jsp