如何學習盈透 api 的開發?

你好,我想學習盈透api的開發,從而實現自動化交易。

關於編程本人只有過matlab編程和mql語言的一點經驗,對盈透api開發一無所知,網上的資源很少 大多是官網tws的使用手冊,看不很懂,對api開發是怎麼一回事還不是很了解。

  1. 能不能解釋一下 什麼是盈透api的開發 ?

  2. 盈透api的開發過程是怎麼樣的?

  3. 我該怎麼學習盈透api的開發,並成功實現程序化交易,學習過程中有沒有相關的書籍參考?

  4. 有沒有盈透api開發的源代碼讓我參考?

謝謝謝謝


2016-9-4: 挖坑

2016-10-03 19:01:更新問答

2016-10-03 20:39:讓更多人看到,修改了下問題的話題範圍,希望題主不介意

2016-10-10 12:36:上知乎推薦了,補充一些代碼相關的內容

謝邀,前段時間開發vn.ib的介面封裝花了挺久研究ib介面的底層細節,這個問題先留個名,後面來細答。

為啥IB API這麼火?

這段純屬個人的一些瞎BB,沒興趣的可以跳過,2008年剛進大學的時候就聽說過了Interactive Brokers的大名(當時對量化還是一竅不通),和曾經一度熱火但是現在幾乎已經淡出主流量化圈的MT4平台不同,IB API的用戶數量和相關的項目數量都是有增無減:

AlgoTrader:應該算是對接IB的最有名的開源量化交易平台,使用CEP作為核心策略引擎,主要應用領域是極為複雜的交易策略(比如全自動的Volatility Arbitrage)

Glean(過去的tradelink):使用圖形化的方式來開發策略,同樣對接IB實現量化交易,偏向於速度較快的日內交易策略

Matlab Trading Toolbox:Mathworks官方提供的量化交易工具

Quantopian:當下最火的在線量化交易平台,最近支持了實盤交易,也是首先選擇對接了IB

究其原因,IB API能成為許多量化平台的首選對接通道,不外乎一個原因:Created by traders, for traders。 公司創始人Thomas Peterffy的傳奇背景就不多介紹了,關鍵在於IB背後的高頻交易公司TimberHill,有這麼一家市場上頂尖的玩家在為公司經紀相關的業務提供建議和各種技術支持,IB才可能同時給客戶提供:

  • 提供強到變態的交易平台TWS

  • 多到變態的全球產品覆蓋

  • 低到變態的交易費用

以上三點能做得比IB好的不能說沒有,但是三點同時都能和IB競爭的似乎就不多見了:

  • 高盛之類的投行太過高大上,不夠親民

  • E*Trade之類的零售經紀商,費用較貴的同時,交易軟體的功能還十分有限
  • FXCM之類的外匯公司,經常留點頭寸不對沖跟客戶對賭,點差還特別高

所以綜合來看,其實IB成功的原因和其他行業成功的公司也沒多大區別,能夠抓住客戶的痛點並且長期提供高質來那個的服務才是關鍵。

背景介紹

時隔一個月終於有時間來填坑了。

IB API的開發是一個非常大的話題,儘管如此看到這個問題時立馬決定無論如何要給出一個比較全面的回答,簡單做一些背景介紹吧(一段痛苦的折騰經歷)。

問題1的答案: API是由Interactive Brokers為了量化交易推出的一套交易介面,結合IB廣泛的市場覆蓋,使用IB API的用戶可以輕鬆實現全球市場的量化交易,也是世界上應用最廣泛的量化交易介面之一(或許這裡都沒必要說「之一」)

本人目前在開發vn.py項目中的IB API的Python封裝介面vn.ib,目的是為了替代之前使用的IbPy項目。IbPy已經若干年沒有更新了,且因為其純Python實現的關係很多地方存在設計不合理的情況(比如底層socket觸發異常就直接斷開,不拋出任何錯誤或者異常)。

vn.ib選擇基於IB官方推出的最新9.72 C++ API來開發,和vn.py框架中的其他介面一樣使用boost.python封裝的形式,以提供更好的穩定性和遠勝IbPy的性能。在開發過程中掉坑無數,花了大約兩周的時間才勉強把程序給跑通起來,所以大家如果在具體開發過程中遇到什麼問題歡迎提問,大概率我之前也遇到過了。

IB API的特點

儘管都交交易介面,但是IB API和國內常見的介面(CTP類,恒生等)有著諸多不同,先來介紹幾個比較關鍵的點:

  1. 使用IB API連接上的不是IB的交易伺服器,而是運行於本機的TWS(帶圖形的交易平台)或者IB Gateway(只提供簡單日誌的交易路由,適合量化),即使對於FIX介面也是如此

    (IB網關,由於沒有複雜的圖形界面,能夠提供比TWS更高的交易性能)
  2. IB API提供了所有的底層源代碼,用戶在使用時需要自行編譯底層API介面部分的組件,提供了一定靈活性的同時,也導致項目開發過程中容易遇到額外的編譯問題

  3. IB API內建了一個比較大的內存緩衝區,回調函數即使阻塞一段時間也基本不會導致API崩潰,所以CTP類API開發時常用的一個回調函數推送的數據必須先進緩衝隊列的設計模式就沒有必要了,可以把一些可能耗時較長的邏輯直接寫在回調函數中(出於程序代碼架構的原因仍然不建議這麼做,不過對於API封裝來說省了很大的力氣)

  4. 最大的坑:IB API里回調函數(負責向用戶的程序中推送數據)的工作線程需要用戶自行創建和管理(國內幾乎所有的API都是內部實現的),提供了極大的靈活性(比如用戶可以使用類似協程的模式輕鬆實現一個線程同時管理8個API連接的推送),但是由於官方文檔和Demo的缺失導致用戶一上來幾乎不知道怎麼去寫這個線程!!!只能靠一步步試錯的方式折騰,無比浪費時間。

使用IB API的開發流程(問題2的答案)

這裡的內容針對使用Visual Studio開發C++介面,其他語言的大同小異:

  1. 從這裡http://interactivebrokers.github.io下載最新的IB API,選擇9.72 beta(比起9.71有了很大的改進,比如取消了Win32 C++ 介面,統一提供POSIX標準的C++介面)
  2. 安裝後,進入TWS API文件夾下的source/CppClient, 把ssl lib client三個文件夾統一複製到你自己項目的文件夾中
  3. 把client文件夾下的.h和.cpp文件添加到你自己的Visual Studio項目中
  4. 在C++項目配置中的Preprocessor中添加_CRT_SECURE_NO_DEPRECATE和_WINSOCK_DEPRECATED_NO_WARNINGS,否則編譯時會觸發警告
  5. 在項目的General配置中,把Character Set設置為Use Multi-Byte Character Set,這裡有可能報錯,或者編譯時報這個Character Set錯誤,提示用戶需要安裝一個補丁包,去Microsoft官網搜索後下載安裝就行
  6. 後面就可以寫自己程序的代碼了,如果你不幸遇到各種問題,歡迎在評論里提問......

IB API的結構簡介(問題3的答案)

據我所知目前市面上是沒有關於IB API的開發書籍的,最好的參考資料就是官方的Reference Guide:TWS API v9.72: Trader Workstation API

這裡簡單介紹一下IB API的結構:

  • EWrapper:類似CTP中的SPI類,提供回調函數
  • EClientSocket:類似CTP中的API類,提供主動函數
  • EReaderOSSignal:一個信號量,回調函數管理線程需要監聽該信號量,當socket收到數據後該信號量會被觸發
  • EReader:當上面的信號量被觸發後,用戶需要調用EReader中的處理信息函數,來觸發EWrapper中對應的回調函數

結構後是一個API的大體工作順序:

  1. 繼承EWrapper並實現回調函數

    //步驟1

    class IbWrapper : public EWrapper
    {
    private:
    VnIbApi *api;

    public:
    IbWrapper(VnIbApi *api)
    {
    this-&>api = api;
    };

    ~IbWrapper()
    {

    };

    void tickPrice(TickerId tickerId, TickType field, double price, int canAutoExecute);

    ......

  2. 創建EWrapper對象wrapper
  3. 創建EReaderOSSignal對象signal
  4. 創建EClientSocket對象client,傳入wrapper和client的對象指針作為構造參數

    //步驟2、3、4

    class VnIbApi
    {
    private:
    //EClientSocket *client;
    IbWrapper *wrapper;
    EReaderOSSignal signal;
    EReader *reader;

    thread *worker;

    public:
    EClientSocket *client;

    VnIbApi()
    {
    this-&>signal = EReaderOSSignal();
    this-&>wrapper = new IbWrapper(this);
    this-&>client = new EClientSocket(this-&>wrapper, this-&>signal);
    };

    ......

  5. 調用client的eConnect方法,連接TWS程序
  6. 連接成功後,創建EReader對象reader,傳入client和signal的對象指針作為構造函數
  7. 調用reader的start方法,啟動reader中的socket埠數據監聽線程

    //步驟5、6、7

    bool VnIbApi::eConnect(string host, int port, int clientId, bool extraAuth)
    {
    bool r = this-&>client-&>eConnect(host.c_str(), port, clientId, extraAuth);

    if (r)
    {
    //啟動EReader從socket讀取信息
    this-&>reader = new EReader(this-&>client, this-&>signal);
    this-&>reader-&>start();

    //啟動數據推送線程
    function0& f = boost::bind(VnIbApi::run, this);
    thread t(f);
    this-&>worker = t;
    };

    return r;
    };

  8. 啟動回調函數管理線程,進入無限循環,首先調用signal的waitForSignal等待信號的觸發
  9. socket收到數據後,信號被觸發,調用reader的processMsgs函數,激發wrapper中對應的回調函數

    //步驟8、9

    void VnIbApi::run()
    {
    while (this-&>client-&>isConnected())
    {
    this-&>reader-&>checkClient();
    signal.waitForSignal();
    this-&>reader-&>processMsgs();
    }
    };

  10. 用戶可以調用client中的主動函數來實現其他的工作任務

    //步驟10

    void IbWrapper::nextValidId(OrderId orderId)
    {
    PyLock lock;
    this-&>api-&>nextValidId(orderId);
    };

IB API的參考源代碼(問題4的答案)

我這裡主要介紹下Github上IB相關的一些項目吧:

  1. GitHub - blampe/IbPy: Python API for the Interactive Brokers on-line trading system., 著名的IbPy介面,歐美很多關於IB開發交易策略的文章都使用IbPy,但是問題上面也提過了

  2. GitHub - jamesmawm/High-Frequency-Trading-Model-with-IB: A high-frequency trading model using Interactive Brokers API with pairs and mean-reversion in Python, 一個關於使用IB實現高頻交易模型的項目,策略本身只是展示目的,沒有實際應用個價值,使用IbPy作為交易介面

  3. GitHub - Komnomnomnom/swigibpy: Third party Interactive Brokers Python API generated from TWS C++ API using SWIG.,使用SWIG開發的IB API的Python封裝

  4. GitHub - JanBoonen/TwsApiCpp: Improved TWS API POSIX C++ library for the Interactive Brokers (IB) TWS (same project as TwsApiC++ in Yahoo TWSAPI).,這個項目改進了官方提供的C++ API代碼,號稱是降低了開發難度,同時提供更高的並發性能

  5. https://github.com/jamesmawm/IB-Trading-Models-And-Backtester,對於2中的策略模型的改進版
  6. GitHub - brotchie/ib-zmq: Interactive Brokers API to ZeroMQ proxy,把IB API和ZMQ進行對接實現了一個消息代理,用戶可以直接使用ZMQ來進行交易
  7. vnpy/vn.ib at dev · vnpy/vnpy · GitHub,本人開發的vn.ib介面,目前尚未完成,不過自認代碼質量還過得去,同時以上回答中提到的內容都基於該代碼

  8. Trading with Interactive Brokers using Python,一個同樣基於IB官方的C++介面做的Python封裝項目,提供了和Quantopian兼容的策略開發API,但是github上的倉庫里沒有底層的封裝代碼,猜測可能作者是想做商業項目?

暫時想到的就是以上內容,還是回到開始的一句話;IB介面的開發是個非常大的話題,但是如果能掌握,基本國內大部分介面的開發也都沒什麼問題了。有問題歡迎在評論里提問,本答案預計後續還會有很多內容上的更新,歡迎關注吧。


Update:解釋起來太複雜,搞點封裝 盈透API的一個極簡單SDK - 許哲的文章 - 知乎專欄

謝邀。

這就是我天天在乾的活,讓盈透TWS里的市場數據放到Matlab寫的函數里,然後跑出結果來後扔到TWS里做交易,並且在資料庫里留個底。

首先你得選擇一個語言SDK,有些是官方的,有些是開發者自己寫的。這個主要看你自己熟悉哪門語言。

在官網的介紹里有羅列官方的實現版本IB API | Interactive Brokers

這裡不推薦ActiveX和DDE兩種,性能上比較弱。ActiveX 不談了,這個主要用於一些特殊場合,就算要在你的網站上嵌入盈透相關的東西,我認為也完全沒必要,且不說ActiveX插件經常被禁掉,這類應用場景完全可以用其他牢靠技術實現。DDE主要用來在Excel 表格里插入不斷變化的價格數據,期權希臘值,債券收益率等等,用於公式做頭寸計算,報表自動生成,也不推薦,非常容易出錯。如果工作非得要以Excel的形式輸出,我依然推薦使用.NET介面對接盈透,並且用.NET框架里的Excel組件。

如果你不是非要在非Windows環境下工作的話,我推薦你使用C#作為主語言。如果你非得在非windows環境下的話,推薦使用Java。當然,如果你有特別心儀的語言,比如上面有位朋友本命語言Python,你就選自己最喜歡的語言。

盈透的軟體基本上是全Java的,C++和C#的實現風格也非常Java,對於Java程序員而言,非常好上手。性能上,如今CLR和JVM都足夠足夠了。

與Matlab的橋接,也推薦用官方的SDK過一道。我用的方式是C# SDK讀取盈透TWS上的數據,然後用MathWorks提供的COM+插件C#代碼直接操作Matlab,這樣子做是最好的。而不要用Matlab直接和TWS硬接,調試起來很會痛苦,這都是血的教訓。有VS和沒VS完全是兩個工種。

這個是MathWorks 官方的C#操作Matlab 介面的使用辦法。

https://cn.mathworks.com/help/matlab/matlab_external/call-matlab-function-from-a-c-client.html

官方文檔里沒用到,但其實最爽的是可以直接在C#里執行Matlab命令。

添加組件:

MLApp.MLApp matlab = new MLApp.MLApp();

// Change to the directory where the function is located
matlab.Execute($"cd {txtMatlabPath.Text}");

把C#程序內存里的數據,導入到Matlab里,和Matlab函數執行結果讀回來超容易。Matlab的矩陣可以和double數組無縫切換。

double[,] pr = new double[60, 8];
double[,] pi = new double[60, 8];

for (int i = 0; i &< 60; i++) for (int j = 0; j &< 8; j++) { pr[i, j] = Convert.ToDouble(dgv.Rows[i].Cells[j + 2].Value); pi[i, j] = 0; } matlab.PutFullMatrix("input", "base", pr, pi);

一個PutFullMatrix 就OK了,base是Matlab里WorkSpace的名字。值得注意的是,放的數組是複數的,也就是一定要有虛數部分。如果你的應用里沒有用到複數,都只是實數的話,虛數部分全部填0(也就是我上面那種做法)就OK了。

讀取結果

matlab.Execute($"[F]=FuncName(input....)");
double[,] res_martix = matlab.GetVariable("F", "base");

結果放回一個double數組裡,就好像調用一個本地的函數一樣簡單。Execute方法基本上是萬能的,就好比嵌入了個Matlab的REPL一樣。

其他語言和Matlab的混合編程參考:

https://cn.mathworks.com/help/matlab/programming-interfaces-for-c-c-fortran-com.html

C++,Java,Python 等等都有。

原則是:有官方的SDK用官方的,少自己造輪子。等實現完全沒問題了,用得滾瓜爛熟了,再想著自己造輪子。

下載地址:Interactive Brokers

Linux用戶不用教,自覺選右邊的。大家不要去下載Beta版,我遇到過幾次坑,就是Beta裡面的Bug。這玩意的Bug,那真是分分鐘鍾幾百萬上下不開玩笑。代碼都在Github上,造輪子特別溜得可以去貢獻貢獻,說不定哪個金融巨鱷土豪受益了,一開心,賞你個小目標什麼的。

與盈透TWS的對接有點複雜,文檔在TWS API v9.72: Trader Workstation API這裡,確實不是很友好。特別是題主如果是從mql轉過來的話,適應會比較難。

但這依然是最重要的參考資料,好比盈透API開發的MSDN,完成度當然和MSDN差得不是一個等量級了。你們看看哪個圈最大,明顯是C#對吧,大家就明白哪個最完整啦。

TWS API v9.72: Initial Setup 開始盈透API開發前,先把安裝設置部分的看清楚。這些看清楚了之後再開始操作。接下來我講講整個框架的邏輯,和MT4/MT5這類玩具是完全不一樣的。

我還是拿我自己用的C#做例子,下載SDK後,有兩個官方完整的Demo,我建議學習者從例子開始著手,結合文檔來學。一個例子簡單,一個例子複雜。簡單的那個例子叫做IBSamples。

上面的CSharpAPI是API的工程,這個部分沒事不要去修改它,下面那個IBSamples是一個最簡單的例子。

整個盈透API寫的應用可以看作是對EWrapper介面的一個實現。你可以不精確得理解為,這個是TWS給你的程序的一個輸出窗口。

而你對TWS的輸入窗口,則要通過創建一個EClientSocket類的對象來實現。

如果不是很明白的話,不精確的認為一個是向TWS發布請求,一個從TWS那裡接受消息就可以了。

我們看官方的例子里 EWrapperImpl.cs 文件,就是一個對EWrapper介面非常基本的實現。

你可以以後慢慢去體會這個結構的設計模式,暫時咱們先用官方的實現用著。我們回到Main函數。

有了基本的實現後,我們新建一個對象然後使用對象里的ClienSocket成員的方法,讓C#程序連接上TWS,方法名字是eConnect。具體的參考在TWS API v9.72: EClientSocket Class Reference

這是我推薦的學習方式,一邊看事例代碼,一邊看參考。當然我們有VS的話,也可以F12一下。反正代碼都就在同一個解決方案里。

下面的先不管他,他們先運行一下連接部分。這裡要注意的是,默認的實盤TWS介面是7496,而模擬盤的默認介面是7497。我現在開一個TWS的模擬賬戶,並且運行該程序的結果是:

程序去嘗試連接127.0.0.1地址上的7496埠,而模擬賬戶開的是7497埠。所以我們是返回一個錯誤。而這個錯誤的輸出內容

Exception throw:System.Net..... 不是系統默認的,是自己定義的。

public virtual void error(Exception e)
{
Console.WriteLine("Exception thrown: "+e);
throw e;
}

就是剛剛說的那個EWrapperImpl.cs文件里,對於錯誤的實現。發生錯誤了,就會調用這個介面里處理錯誤的實現方法。

也就是說,這個EWrapperImpl的實現里的種種方法,你可以當作是mql語言里的一個個事件。這個public virtual void error(Exception e)可以理解為 OnError()。

那我們再來看幾個實現。

public virtual void tickPrice(int tickerId, int field, double price, int canAutoExecute)
{
Console.WriteLine("Tick Price. Ticker Id:"+tickerId+", Field: "+field+", Price: "+price+", CanAutoExecute: "+canAutoExecute+"
");
}

這個實現的意思是,當價格變動的時候,tikerId是資產的編號,field是Ask還是Bid或者是深度數據,price是價格,後面是能否自動執行的標誌位。

這個相當於題主熟悉是mql里的OnTick()事件。

這裡的實現只是簡單的輸出里一下。

ublic virtual void updatePortfolio(Contract contract, int position, double marketPrice, double marketValue, double averageCost, double unrealisedPNL, double realisedPNL, string accountName)
{
Console.WriteLine("UpdatePortfolio. "+contract.Symbol+", "+contract.SecType+" @ "+contract.Exchange
+": Position: "+position+", MarketPrice: "+marketPrice+", MarketValue: "+marketValue+", AverageCost: "+averageCost
+", UnrealisedPNL: "+unrealisedPNL+", RealisedPNL: "+realisedPNL+", AccountName: "+accountName+"
");
}

這個是當檢查頭寸命令發出後的回應,哪些個合約現在倉位多少,市場價多少,市值多少,建倉平均價多少,浮虧浮盈多少,已經實現的盈虧多少,哪個賬號。

可以粗淺類比成 OnTrade() 事件。

我們把埠號改成模擬賬戶的7497,返回的結果:

返回了TWS時間等等,這些就表明我們的程序和TWS連接上了。連接上後,我們要做的第一件事情是獲取行情數據,所有的事情都是在有行情的基礎上做的。代理里有豐富的例子,就下下面testIBMethods里,幾乎囊括了所有功能。

這個在main函數里也調用過了,所有都被注釋掉了,慢慢解掉注釋,我們就能感受一個個功能怎麼寫的了。

比如我們把這兩行代碼解除注釋。

wrapper.ClientSocket.reqMarketDataType(2);
wrapper.ClientSocket.reqMktData(1001, ContractSamples.getEurUsdForex(), "", false, GetFakeParameters(3));

意思是我們要請求獲取一個市場數據,第二個參數是要獲取哪個合約,這裡返回的合約是 ContractSamples.getEurUsdForex(),是一個EURUSD即期匯率的合約。

public static Contract getEurUsdForex()
{
Contract contract = new Contract();
contract.Symbol = "EUR";
contract.SecType = "CASH";
contract.Currency = "USD";
//we can also give the conId instead of the whole description
//but we still need the exchange though
contract.ConId = 12087792;
contract.Exchange = "IDEALPRO";
return contract;
}

Contract 類是用來描述一個合約的,這裡的細節先不討論,總之這列返回了一個EURUSD的即期匯率合約的Contract對象,交給reqMktData方法來發送給TWS。我們來看看解注掉這兩行後的結果。

這裡的結果事實上,是觸發了兩個實現的方法。一個是 tickPrice,另外一個是tickSize

public virtual void tickPrice(int tickerId, int field, double price, int canAutoExecute)
{
Console.WriteLine("Tick Price. Ticker Id:"+tickerId+", Field: "+field+", Price: "+price+", CanAutoExecute: "+canAutoExecute+"
");
}

這個方法上面介紹過,就是價格變化時會發生的,輸出前綴是。這裡的輸出:

Tick Price.Ticker Id:1001,Field:2,Price:1.11624,CanAutoExecute:1

的意思是,Ticker Id編號為1001(我們解注的代碼的第二行里自己定義的)的資產的Field為2的價格(等效於Ask)為 1.11624。也就是意味著那一瞬間,EURUSD的Ask報價是 1.11624。彼時Bid沒動的話,Field:1的就不更新。

TickSize. Ticker Id:1001,Field:0,Size:3000000

這條輸出是因為觸發了方法 tickSize方法

public virtual void tickSize(int tickerId, int field, int size)
{
Console.WriteLine("Tick Size. Ticker Id:" + tickerId + ", Field: " + field + ", Size: " + size+"
");
}

意味著那一個瞬間,EURUSD 這一層的可交易對手量是3000000美元,超過這個的話,就會滑點了。

這些信息會不斷得刷屏,因為EURUSD是非常活躍的品種,市場深度和容量結構一致在變化的。

相當於TWS上這個界面(Book Trader)里的信息的輸出。

這一個簡單的小例子,涵蓋了整個SDK的運行邏輯。用EClienSocket類的方法去向TWS提出要求,比如 reqMarketData 就是要求一個合約的市場數據。

TWS 應該有的回應會調用那個EWrapper介面里你實現的方法。所以學習的方法是,將下面那些注釋掉的內容解注掉後多看看,然後那個EWrapperImpl里的實現多看看,邏輯都是一樣的。

(未完待續)

不用原生庫慢慢解釋了,還是封裝好再說吧: 盈透API的一個極簡單SDK - 許哲的文章 - 知乎專欄


何必這樣麻煩,不要浪費時間在通道上,策略本身更重要

mulitcharts,amibroker 都可以連接ib交易


IB自帶Java, C++, C#的API, 此處有reference: https://www.interactivebrokers.com/en/software/api/api.htm

第三方Python的庫IbPy,其實就是是Java API的wrapper,也就是說function signature可以基本參照上面的鏈接,GitHub - blampe/IbPy: Python API for the Interactive Brokers on-line trading system.

如何用IbPy下單:Using Python, IBPy and the Interactive Brokers API to Automate Trades

如何用IbPy調取歷史數據:GitHub - busygin/ib_data_loader: A python script to download daily futures market data from Interactive Brokers using IbPy

然而IbPy下歷史數據也有諸多limitations,某些很嚴格某些似乎不存在:https://www.interactivebrokers.com/en/software/api/apiguide/tables/historical_data_limitations.htm

交易系統:實時歷史數據 -&> 分析併產生買賣信號 -&> 下單,就這麼簡單,不需要太複雜的封裝。

研究框架:長期歷史數據 -&> 提取優質信號 -&> 設計策略 -&> 回測

目前本人正在搭建交易系統(下載歷史數據,測試交易信號,向量化+事件驅動回測系統)一條龍,已經完成80%。如果對這方面感興趣,有IB的賬戶,有較好的Python編程經驗,有空餘時間,或者有成功手動交易經驗,歡迎私信並一起折騰。


大約1年前一個朋友在搞盈透,讓我看下搞個黃金白銀的套利,我當時看的是官方C++的demo,代碼各種爛。

前幾天放假,正好又說他搞的C#demo越跑與慢(必然是bug),讓我幫忙看下Java怎麼搞。我最近估計會抽出時間研究下這塊,大家可以一起討論:)

人生苦短,我用Java.

API:Interactive Brokers

9.72beta document:TWS API v9.72: Trader Workstation API 文檔很短,沒什麼卵用。

剛剛上傳了一個Java samples,在官方版本上修復一些錯誤:GitHub - philsong/ibjts

中文文檔,這個看了下很有用:https://github.com/philsong/ibjts/blob/master/APIprintable_CN.pdf

10.2號申請註冊了個號,讓我提交住宅證明,暫時還沒通過(然而就收到北京3個電話說相關方推送她們說我最近股票開戶,給我推薦股票,我懷疑盈透透露了我註冊手機,沒想到啊,國際大券商啊!!!)

代碼解析:

com.ib.client的是對ib協議的核心封裝

com.ib.contracts只是繼承com.ib.client.Contract實現的幾個具體類

com.ib.controller只是對com.ib.client中EWrapper的一層封裝實現。

sample分析:

TestJavaClient直接調用com.ib.client,加上GUI進行測試。

apidemo用了com.ib.controller, 然後加上GUI進行測試。

samples直接調用com.ib.client且沒有涉及GUI部分。

總體來說,代碼很簡單,我從10.2號看了兩個晚上基本上明白就那麼回事了。剩餘的就是熟悉下業務的邏輯,重點就是搞策略了,比如抓下數據用stata搞個高大尚的統計套利:)

package com.ib.client,其包含以下classes:

EWrapper

該介面負責從TWS接收信息。

ComboLeg

該class包含用於描述組合邊的屬性。

Contract

該class包括用於描述合約的屬性。

ContractDetails

該class包括用於描述合約詳細的屬性,包括債券詳細。

EClientSocket

該class負責向TWS發送信息。

Execution

該class包含用於描述交易的屬性。

ExecutionFilter

該class包含用於描述執行過濾器條件的屬性。

Order

該class包含用於描述定單的屬性

OrderState

該class包含用於描述定單狀態的屬性。

ScannerSubscription

該class包含用於描述市場掃描元素的屬性。

TickType

該class定義通用跳動類型和其跳動值

使用Java API連接TWS

1. 將com.ib.client.*輸入到您的源代碼文件。

2. 實施EWrapper介面。這個class將從插口接收信息。

3. 取代下列方法:

Ewrapper方法

tickPrice()

tickSize()

tickOptionComputation()

tickGeneric()

tickString()

tickEFP()

處理市場數據。

orderStatus()

接收定單狀態。

openOrder()

接收開放定單。

error()

接收出錯信息。

connectionClosed()

在TWS終止連接時發出通知。

updateAccountValue()

接收當前賬戶值。

updateAccountTime()

接收最後一次賬戶更新信息。

updatePortfolio()

接收當前投資組合信息。

nextValidId()

接收連接時的下一個有效定單代號。

contractDetails()

接收合約信息。

contractDetailsEnd()

確認一個給定合約細節請求的結束。

bondContractDetails()

接收債券合約信息。

exectDetails()

接收執行報告信息。

updateMktDepth()

接收市場深度信息。

updateMktDepthL2()

接收二級市場深度信息。

updateNewsBulletin()

接收IB新聞公告。

managedAccounts()

接收金融顧問(FA)管理的賬戶列表。

receiveFA()

接收FA配置信息。

historicalData()

接收歷史數據結果。

scannerParameters()

接收描述掃描儀訂閱的有效參數的XML文件。

scannerData()

接收市場掃描儀結果。

realTimeBar()

接收實時柱。

currentTime()

接收伺服器的當前系統時間。

fundamentalData()

接收路透社全球基本面市場數據。

4. 實例EClientSocket class。該對象將被用於發送信息到TWS。

5. 調用下列方法:

EClientSocket方法

eConnect()

連接TWS。

eDisconnect()

斷開TWS。

reqMktData()

請求市場數據。

cancelMktData()

取消市場數據。

reqMktDepth()

請求市場深度。

cancelMktDepth()

取消市場深度。

reqContractDetails()

請求合約詳細。

placeOrder()

下達定單。

cancelOrder()

取消定單。

reqAccountUpdates()

請求賬戶值、投資組合、和賬戶更新時間信
息。

reqExecutions()

請求日執行報告列表。

reqOpenOrders()

請求關於請求客戶的當前開放定單列表和
將TWS開發定單與客戶相連。 相連僅在請求
客戶的客戶代號為0時發生。

reqAllOpenOrders()

請求所有開放定單的列表。

reqAutoOpenOrders()

自動將新的TWS運作與客戶相連。 相連僅在
請求客戶的客戶代號為0時發生。

reqNewsBulletin()

請求IB新聞公告。

cancelNewsBulletins()

取消IB新聞公告。

setServerLogLevel()

設置API請求和處理記錄的級別。

reqManagedAccts()

請求金融顧問(FA)管理的賬戶編碼列表。

requestFA()

請求TWS的FA配置信息。

replaceFA()

修改API的FA配置信息。

reqScannerParameters()

請求描述掃描儀訂閱有效參數的XML文件。

reqScannerSubscription()

請求市場掃描儀結果。

cancelScannerSubscription()

取消掃描儀訂閱。

reqHistoricalData()

請求歷史數據。

cancelHistoricalData()

取消歷史數據。

reqRealTimeBars()

請求實時柱。

cancelRealTimeBars()

取消實時柱。

exerciseOptions()

行使期權。

reqCurrentTime()

請求當前伺服器時間。

serverV ersion()

反饋API應用程序連接的TWS實例的版本。

TwsConnectionTime()

反饋API應用程序連接到TWS的時間

reqFundamentalData()

請求路透社全球基本面數據。 必須通過賬戶
管理訂閱路透社基本面才可以接收數據。

cancelFundamentalData()

取消路透社全球基本面數據。

可以認為samples文件夾中的testbed是入門最佳之選。他演示實現了EWrapper介面 ,如EWrapperImpl,基本看懂這個就可以跑自動化程序了。至於程序化,分享一個我內部培訓的文檔 https://pan.baidu.com/s/1hr909wg

本人程序狗野路子,沒去過什麼銀行證券,策略都是實戰總結的,大家笑笑就好,要是賜教下就更好了

apidemo昨晚跑起來,待續。。。


學習學習~希望儘早可以有成熟的交易介面可以使用


這個問題對於盈透api初使用者有很大的幫助,尤其是用python的交易員的回答很棒,但這個問題的回答還缺少了一些踩坑的經歷,我這裡補充一些盈透api開發需要注意的點:

  • 盈透有賬戶和用戶的概念,比如申請一個模擬賬戶,賬戶名大概是DUXXX,而用戶名不一樣,一個賬戶可以分配多個用戶。
  • 盈透行情是分用戶的(不是賬戶),每個用戶的行情需要單獨登錄tws軟體,交易可以由主賬戶給子賬戶下單 但是行情不可以 行情數據都是獨立的 子賬戶訂閱的付費行情,主賬戶並不能取得。
  • 盈透證券上海支持電話:021 6086 8586
  • 註冊賬號後,在賬號管理頁面有個支持菜單,裡面有在線聊天,在這裡可以快速的和相關客服聊天,有中文支持。
  • 使用API下達一個新的定單時,定單代號數字必須大於前一個使用的數字。例如,如果你用定單代號11下達一個定單,則下一個定單的定單代號應該至少為12 。
  • 使用API修改定單,需要使用相同的定單代號重新提交你希望修改的定單,但使用依據需要修改的價格或數量。 僅某些區域,比如價格或數量可以使用這個方法來更改。 如果你想改變定單類型或行動,你將需要取消定單然後重新提交一個新的定單。
  • 賬戶名:aedemo 密碼:demouser,這個用戶可以訂閱模擬期貨數據,但是不可以用市場掃描儀。
  • C++ API市場掃描儀使用時aboveVolume和averageOptionVolumeAbove的值需要送INT_MAX,不然掃描不到數據。
  • 使用api連接tws時,一連接就斷開,如果是在別的機器連的,則需取消tws設置中的「僅允許來自本地主機的連接」
  • api連接有50 tps的限制。
  • API新聞出錯:Source code unchecked in API news Settings:BZ,這種錯誤估計是使用reqMktData介面的第三個參數送了,傳空就好。
  • 先關掉tws, 然後觸發connectionClosed()回調, 然後再回調里去調用eDisconnect,再eConnect,然後我就去掃描市場 這時候報市場掃描超時,這是怎麼回事呢?(特別說明: 我專門開了個線程循環去checkClient,waitForSignal,processMsgs )

    答:問題已經定位到了,是在tws軟體重啟過程中,如果tws沒有完全啟動好,api是可以連接上的,但是這時候如果你去使用m_pReader-&>checkClient();,m_osSignal.waitForSignal(),m_pReader-&>processMsgs()這一系列操作,會直接導致連接斷開。

    解決辦法就是在重連成功的時候等待一段時間,待tws軟體完全啟動後之後再去操作信號,然後再去重新訂閱行情,這樣就沒有問題了。
  • IB行情api接入是有限制的,就是一個帳號只能夠訂閱100個代碼行情,可以買擴展包,但一個賬戶最多也就能訂閱1100個產品行情
  • 對於「持倉量」這個行情(盈透里叫未平倉合約),22是指期權的未平倉合約id,86是期貨的未平倉合約id,但是如果要86返回的話一定要在Generic Tick Type中加上588,也就是reqMktData第三個參數genericTicks要送"588",這個地址http://interactivebrokers.github.io/tws-api/tick_types.html可以看到可用的行情欄位。
  • tws的api日誌在C:Jtsapi.0.Mon.log這種形式。而tws的日誌,在TWS中,您按鍵盤上的Ctrl+Alt+U即可知道對應路徑,另外您這邊也要將設置中的logging level 從error 改成Detail。


Interactive Brokers 盈透專門為廣大的Python愛好者舉辦了一次網路研討會。時間是2016年11月10日。 有興趣的朋友可以登錄到盈透官方網站看看當時的視頻。網路研討會的內容是介紹如何用IBridgePy,一個Python 工具,用盈透API做自動交易。IBridgePy模仿了著名的quantopian的程序格式,但是提供了更加豐富多樣的功能。不僅可以處理股票,還可以處理期貨,期權,外匯等所有盈透的標的物。

https://www.interactivebrokers.com/en/index.php?f=2227


昨天工作需要自己也測了一下IB介面,照著C++ demo 擼了一個測試小程序,自己照葫蘆畫瓢吧

kangseung/IBtest


介紹一個直接用Matlab連IB的介面IB4m,GitHub - softwarespartan/IB4m: Interactive Brokers API for Matlab , 對只熟悉Matlab的量化小白是個不錯的工具。作者已經將底層API用Java封裝好,只需要用Matlab調用即可。裡面可以實現一些基本的操作,比賬戶信息查詢,委託單查詢,市場數據獲取,下單等。裡面也提供了事件驅動模塊,應該能夠實現一些簡單的程序化交易,不過穩定性如何還有待測試。


訂閱 L2 似乎需要對 contract 中的 symbol 和 exchange 進行組合, 只有在正確的情況下才能返回 L2的數據. AAPL+ISLAND. 但是這個組合應該從哪裡去找呢?

Deep market data is not supported for this combination of security type/exchange


剛剛準備試一下,這個api裡面如果算均線布林線的值的話,是要自己算還是有引用的介面?


IB API是非常簡單的API,你只要幾百行代碼任意語言就可以自己搭出來,無非是自己寫一些事件(event)的處理函數(handler)

如果樓主只要簡單的市場數據和下單撤單,個么只要寫幾個回調和幾個簡單的factory就可以:

1. order的factory, 生成IB需要的各類訂單類型

比如

Contract ContractSamples::EuropeanStock(){

Contract contract;

contract.symbol = "SMTPC";

contract.secType = "STK";

contract.currency = "EUR";

contract.exchange = "BATEEN";

return contract;

}

2. 市場訂單的下單,狀態回調,查詢

Client::placeOrder()

Client::reqOpenOrders()

Client::reqExecutions()

Client::placeOrder()

Client::on_order_status()

3. 市場數據的訂閱和接受

Client::reqMktData()

Client::cancelMktData()

4. IB的connect和dicsconnect

Client::on_connected(), on_disconnected()


很想知道IB的訂單有沒有和MT4的magic number類似的東西,可以用來區分訂單?


api的使用參考常式,業務不明白的地方問在線客服。


ibkr有手冊和常式的,例如c和java


高度封裝起來的東西都很簡單,會編程,看官方文檔就能完成


推薦閱讀:

為什麼說信達資產變成了中國最大的影子銀行機構?
你的交易系統是根據哪些常識、理論或哲學而建立的?
如何系統地學習行為金融學?
如何培養把握經濟大趨勢的能力?
2014年如何用我的10萬塊在上海賺錢?

TAG:投資 | Python | C | 金融 | 量化交易 |