一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

#IB TWS編程手記——02.提交你的第一個(gè)Hello World!

 AIANT 2020-07-04

關(guān)于IB的錯(cuò)誤碼

在我們進(jìn)一步深入IB的工作機(jī)理前,需要回到Wrapper中error函數(shù),如果善用error函數(shù)提供的錯(cuò)誤信息,將能幫助我們快速定位到錯(cuò)誤,并且修正我們的代碼。

關(guān)于IB錯(cuò)誤Code,具體的編碼,請(qǐng)查考網(wǎng)站 https://interactivebrokers./tws-api/message_codes.html。

這里,我重點(diǎn)說(shuō)一下error函數(shù)中,帶有id函數(shù),這是我們繼續(xù)開發(fā)客戶端算法非常重要的基礎(chǔ)。

public void error(int id, int errorCode, string errorMsg) { Console.WriteLine('TWS Error: id:{0} code:{1} message:{2}', id, errorCode, errorMsg); }
  • 1
  • 2
  • 3
  • 4

它包含3個(gè)返回參數(shù),整數(shù)型的id,整數(shù)型的errorCode,以及string型的errorMsg。這里的id是我們提交到TWS的任務(wù)id,也就是OrderId,當(dāng)它為-1時(shí),這個(gè)函數(shù)得到的信息,會(huì)有點(diǎn)類似一些Debug里面的Info級(jí)別消息,也就是告訴你當(dāng)前TWS的工作狀態(tài),你的客戶端與TWS連接情況,TWS與IB自身,交易所的連接情況等基礎(chǔ)信息。

所以,上一篇文章里,我們啥也沒干,在Console里一下子打出了一堆信息,就是這樣的原因。

運(yùn)行結(jié)果

而errorCode,就是比較有用的錯(cuò)誤信息了,它是不同的預(yù)定義的編碼,具體編碼信息,你可以從上面的連接里對(duì)照著找,比如這個(gè)截圖里出現(xiàn)的2104,在IB自己的官網(wǎng)定義就是:

codeTWS messageAdditional notes
2104Market data farm connection is OKA notification that connection to the market data server is ok. This is a notification and not a true error condition, and is expected on first establishing connection.

至于message,就是返回的消息咯。

另一個(gè)帶Exception的error,指的是你調(diào)用IB API時(shí)產(chǎn)生的錯(cuò)誤。比如你試圖發(fā)送一個(gè)訂單,但是你并未建立起跟TWS的連接,這個(gè)時(shí)候就會(huì)出現(xiàn)TCP連接錯(cuò)誤的問(wèn)題,而這個(gè)錯(cuò)誤,就會(huì)通過(guò)

    public void error(Exception e)    {        Console.WriteLine('API Error: thrown exception: {0}', e);    }
  • 1
  • 2
  • 3
  • 4

這個(gè)回調(diào)函數(shù)告訴你。因此,你可以使用調(diào)用棧信息,找出錯(cuò)誤的代碼位置,或者直接打印異常信息本身。

提交命令

在IB API的架構(gòu)設(shè)計(jì),所有向IB Server提交的命令,都是通過(guò)EClient封裝好的API來(lái)提交。啥玩意是EClient?

EclientSocket繼承關(guān)系

EclientSocket繼承了Eclient和EClientMsgSink,這個(gè)類自身所擔(dān)負(fù)的主要工作就是創(chuàng)建和維護(hù)與TWS通信的TCP信道。而任務(wù)命名請(qǐng)求,則全部交由EClient負(fù)責(zé)。

因此,對(duì)于TWS來(lái)說(shuō),你提交任務(wù)的基本方式,大體上是這樣的:

clientSocket.reqXXXXX(id, ...);
  • 1

因此,你能做什么,不能做什么,基本上就看Eclient是否封裝了對(duì)應(yīng)的API,以及API里需要的參數(shù)是什么樣子的,所以具體的你可以看看API手冊(cè)上是怎么寫的。

那么明白了這一點(diǎn),我們可以進(jìn)入到下一個(gè)內(nèi)容,向TWS提交合約信息。

合約

所謂合約,如果從金融專業(yè)出發(fā),指的是合同,或者更俠義的說(shuō)是商品交割合同,也就是期貨、股指等商品的交易合同。

IB把絕大部分的交易請(qǐng)求行為定義為合約(Contract),這意味著用戶要提交具體的數(shù)據(jù)請(qǐng)求時(shí),需要像填表一樣,把相關(guān)任務(wù)的信息填入到Contract中,因此,不同類型的任務(wù),需要填寫的關(guān)鍵字是不一樣的。

IB將很多操作,比如查股價(jià),查期貨合約等任務(wù),都視為一個(gè)合約任務(wù),不知道這種定義更偏向金融系統(tǒng)的人還是更偏向IT系統(tǒng)的,如果用我們IT的行話說(shuō),那一個(gè)Contract其實(shí)就是一個(gè)Request。

你要是還不明白這個(gè)是什么意思,那么容許我引入一下網(wǎng)絡(luò)開發(fā)常提到的HTTP協(xié)議。在HTTP中,我們通過(guò)GET/POST命名,并附帶各種參數(shù),以此告知遠(yuǎn)程服務(wù)器對(duì)應(yīng)的任務(wù)形式。

Contract也是類似的,只不過(guò)是用類進(jìn)行表示的。所以要做什么事,能做什么事,兩件函數(shù)相同但功能不同的任務(wù)如何區(qū)分,思路也基本一樣,就是依靠提交的Contract類的不同參數(shù)定義來(lái)區(qū)分。

這其實(shí)也可以理解,因?yàn)镮B涵蓋的交易產(chǎn)品太多太廣泛,必然會(huì)出現(xiàn)很多重復(fù)的地方,所以一個(gè)交易產(chǎn)品,需要多個(gè)不同的字段去縮小它的定義。

舉例來(lái)說(shuō),當(dāng)你告知IB,幫我查找“蘋果”。如果不告知它具體的其他信息,它可能會(huì)以為你要查找蘋果現(xiàn)貨合約,蘋果股票期權(quán)合約,或者蘋果股票合約;它會(huì)完全confused。

所以要怎么去查找具體的商品合約信息呢?

IB給出的建議是讓我們直接在TWS中找具體的信息(通過(guò)雙擊,或者在Contract Info -> Description):

ContractInfo

然后我們可以得到這樣的信息:

Details

這個(gè)框里的東西,告知了我們對(duì)應(yīng)的合約信息,包含交易所代碼,合約代碼,貨幣單位等重要的信息。所以如果你需要TWS告訴你蘋果公司的股票合約信息,而不是期權(quán)合約信息,甚至不是蘋果現(xiàn)貨合約信息,那么你需要通過(guò)這個(gè)方法,找到蘋果股票的合約信息。

接下來(lái)怎么做?

還記得上一篇文章《#IB TWS編程手記——01.TWS建立基礎(chǔ)連接》中怎樣建立與TWS的連接么?

我們接下來(lái)要做的,就是在Main函數(shù)里先增加這么一個(gè)指令:

    static void Main()    {        /// 創(chuàng)建Wrapper,并且獲取創(chuàng)建好的clientSocket以及readerSignal        IBWrapper wrapper = new IBWrapper();        EClientSocket clientSocket = wrapper.ClientSocket;        EReaderSignal readerSignal = wrapper.Signal;        // 連接至服務(wù)器,IP地址,端口號(hào),本客戶端ID,默認(rèn)為0        // 關(guān)于0有什么用,我們?cè)诤竺娴奈恼吕镌僭敿?xì)說(shuō)明        clientSocket.eConnect('127.0.0.1', 7497, 0);        // 創(chuàng)建一個(gè)reader,用于處理消息事件        var reader = new EReader(clientSocket, readerSignal);        reader.Start();        // 創(chuàng)建后臺(tái)線程,監(jiān)控來(lái)自TWS的消息        new Thread(() => {            while (clientSocket.IsConnected()) {                readerSignal.waitForSignal();                reader.processMsgs();            }        }) { IsBackground = true }.Start();        // 這一步會(huì)一直循環(huán),直到我們獲得了可用的OrderID,>0 時(shí)表示著此時(shí)開始,可以向TWS發(fā)送命名了。        while (wrapper.NextOrderId <= 0) { }        ////////////////        // 新增加的指令        clientSocket.reqMatchingSymbols(wrapper.NextOrderId, 'IB');        // 然后啥事也不干,就睡10s        Thread.Sleep(10000);        // 關(guān)閉連接        Console.WriteLine('Disconnecting from TWS...');        clientSocket.eDisconnect();        // 類似于斷點(diǎn),我們可以查看到代碼的輸出        Console.ReadKey();    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

我們注意下這個(gè)新增的代碼:

clientSocket.reqMatchingSymbols(wrapper.NextOrderId, 'IB');
  • 1

這個(gè)指令的意思,是讓TWS幫我們查找合約中,合約代碼為“IB”的交易產(chǎn)品信息。還記得我們的Wrapper中,只實(shí)現(xiàn)了屈指可數(shù)的幾個(gè)函數(shù)嗎?

現(xiàn)在回到Wrapper的實(shí)現(xiàn)類,我們需要把回調(diào)函數(shù)“symbolSamples”實(shí)現(xiàn)它的方法:

    public void symbolSamples(int reqId, ContractDescription[] contractDescriptions)    {        string derivSecTypes;        Console.WriteLine('Symbol Samples. Request Id: {0}', reqId);        foreach (var contractDescription in contractDescriptions)        {            derivSecTypes = '';            foreach (var derivSecType in contractDescription.DerivativeSecTypes)            {                derivSecTypes += derivSecType;                derivSecTypes += ' ';            }            Console.WriteLine('Contract: conId - {0}, symbol - {1}, secType - {2}, primExchange - {3}, currency - {4}, derivativeSecTypes - {5}',                contractDescription.Contract.ConId, contractDescription.Contract.Symbol, contractDescription.Contract.SecType,                contractDescription.Contract.PrimaryExch, contractDescription.Contract.Currency, derivSecTypes);        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

然后你再重新執(zhí)行一遍代碼,看看有什么效果?然后再去跟TWS的信息做一下對(duì)比?

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    亚洲成人精品免费在线观看| 爱草草在线观看免费视频| 日韩中文字幕有码午夜美女| 亚洲淫片一区二区三区| 日韩黄片大全免费在线看| 国产av一区二区三区久久不卡| 一个人的久久精彩视频| 国产麻豆一区二区三区在| 免费黄色一区二区三区| 丝袜av一区二区三区四区五区| 国语对白刺激高潮在线视频| 内射精子视频欧美一区二区| 亚洲国产性生活高潮免费视频| 亚洲一区二区久久观看| 日本一本不卡免费视频| 亚洲视频一区二区久久久| 日本女人亚洲国产性高潮视频| 成人精品一级特黄大片| 黄片免费播放一区二区| 日韩国产亚洲一区二区三区| 国产高清三级视频在线观看| 搡老熟女老女人一区二区| 中文字幕熟女人妻视频| 中日韩美女黄色一级片| 在线免费观看黄色美女| 中文字幕欧美视频二区| 久久经典一区二区三区| 中文字幕一区二区三区大片| 国产精品尹人香蕉综合网| 综合久综合久综合久久| 日韩一区二区三区有码| 亚洲性日韩精品一区二区| 亚洲日本中文字幕视频在线观看 | 亚洲国产一区精品一区二区三区色| 欧美日韩国产一级91| 国产成人精品一区二区三区| 色婷婷在线视频免费播放| 91久久国产福利自产拍| 国产一区二区三区丝袜不卡| 日本不卡在线视频你懂的| 成人精品视频在线观看不卡|