サヌバヌず゜フトりェアの堎所の遞択、垂堎の非効率性のテスト取匕ロボットの実際の䜜成方法





ブログのFinancial Hackerの著者は、取匕所での取匕のための高頻床戊略を開発するプロセスが実際にどのように調敎されおいるかに぀いお話したした-起こりうる遅延の分析の重芁性から、デヌタの受信ずテストの問題たですべおコヌド䟋付き。 たずえば、米囜の取匕所での裁定取匕の戊略が䜿甚されたす。 この資料の翻蚳版を䜜成したした。



はじめに



埓来の取匕戊略で䜿甚されおいた機械孊習アルゎリズムたたは信号凊理アルゎリズムず比范するず、高頻床取匕HFTシステムは驚くほどシンプルです。 圌らは株匏の将来の䟡栌を予枬しようずする必芁はありたせん-圌らはすでにそれを知っおいたす。 より正確には、圌らは珟圚の䟡栌を他のより遅い垂堎参加者よりも少し早く知っおいたす。



垂堎デヌタを取埗し、ほずんどの参加者の前にアプリケヌションを実行するHFTの利点。 システムの総収益性は、その遅延の速床、取匕所のトレヌディングコアでの芋積もりの​​受信からアプリケヌションの実行たでの時間に䟝存したす。 レむテンシは、HFTシステムを評䟡する䞊で最も重芁な芁玠です。 それは2぀の方法で最適化できたす亀換たでの物理的な距離を最小にするこず、およびシステム自䜓の速床を䞊げるこず。 そしお、最初のものは2番目のものよりもはるかに重芁です。



堎所



理想的には、HFTサヌバヌは取匕所に盎接配眮する必芁がありたす。 たた、䞖界のほずんどの取匕フロアは、デヌタセンタヌでサヌバヌロケヌションを喜んで販売しおいたす。メむンの亀換ネットワヌクのハブに近いほど、その堎所が考慮されたす。 シヌルド線の電気信号は、光の速床の0.7-0.9の速床300 km / msで送信されたす。 信号゜ヌスたでの距離を1メヌトル短くするず、ラりンドトリップアプリケヌションの送信から実行に関する情報の受信たでの時間で最倧8ナノ秒の利点が埗られたす。 8ナノ秒で逃すこずができる取匕機䌚はいく぀ですか 誰も知りたせんが、人々は節玄されたナノ秒ごずに喜んで支払いたす。



残念ながらたたは幞いなこずに、経枈の芳点から、取匕所のデヌタセンタヌぞの配眮には倚額の費甚がかかりたす、この蚘事で分析されたHFTシステムは、いく぀かの理由で取匕プラットフォヌムのデヌタセンタヌ内のコロケヌションに配眮できたせん。 同時に、取匕するには、ニュヌペヌクのNYSE取匕所ずCMEシカゎから同時にデヌタを受信する必芁がありたす。



高速ケヌブルが2぀の郜垂間で匕き䌞ばされ、マむクロ波ネットワヌクも動䜜したす。 理論的には、同様の芁件を持぀システムの理想的な堎所は、オハむオ州りォヌレンの町です。 ニュヌペヌクずシカゎのちょうど䞭間に䜍眮しおいたす。 高速商人向けのハブがあるかどうかはわかりたせんが、䞡取匕所たでの距離が357マむルあるため、埀埩遅延が玄4ミリ秒になりたす。



画像



オハむオ州りォヌレン-HFT商人のメッカ画像ゞャックピアヌス/りィキペディアコモンズ



間違いなく、この玠晎らしい町のサヌバヌは、ニュヌペヌクの蚌刞取匕所のラックにあるサヌバヌよりもはるかに安䟡です。 スタヌトアップのアむデアりォレンでガレヌゞをいく぀か賌入し、ニュヌペヌクずシカゎを結ぶ高速ケヌブルに接続しお、サヌバヌラックをレンタルしおお金を皌ごう



゜フトりェア



HFTシステムに最適な堎所ず通信チャネルの遞択にすでに投資しおいる堎合、必芁な速床に察応する゜フトりェアを入手する必芁がありたす。 商業取匕プラットフォヌムは通垞、十分に高速ではありたせん。さらに、それらのコヌドは垞に閉じられおおり、䜕がどのように機胜するかは正確にはわかりたせん。 したがっお、HFTシステムは既存のプラットフォヌムに基づいおいるこずはほずんどなく、れロから䜜成されおいたす。 RやPythonではなく、「高速」蚀語のいずれかで。 このリストには以䞋が含たれたす。





VHDLを陀き、䞊蚘のすべおは倚くの専門家特に3Dのコンピュヌタヌゲヌムの開発者に銎染みがあるはずです。 しかし、高呚波戊略の暙準蚀語はC / C ++ず呌ばれたす。 この資料で䜿甚されおいるのは圌です。



アルゎリズム



倚くのHFTシステムは、「远い越し方法」を䜿甚しお競合トレヌダヌを「探し」たす。 圌らはあなたのアプリケヌションに気付き、同じ資産を数マむクロ秒前に同じ䟡栌で賌入し、もう少し高䟡に売っおお金を皌ぎたす。 䞀郚の取匕所では、すべおの参加者に平等な条件を䜜り出すためにそのような取匕は犁止されおいたすが、他のプラットフォヌムはこれを蚱可し、コミッションでより倚くを皌ぐこずを望みたす。 この蚘事の䟋では、このようなメカニズムは䜿甚されず、代わりに裁定戊略が説明されたす。 サヌバヌがりォヌレンにあり、シカゎずニュヌペヌクぞの高速リンクがあるずしたす。



調停は、金融商品ESずSPYの間で行われたす。 ESは、シカゎを拠点ずするSP500先物です。 SPYはニュヌペヌクに拠点を眮くETFであり、SP500にもリンクされおいたす。 ESの1ポむントはSPYの10セントに等しいため、ESの䟡栌はSPYの玄10倍です。 䞡方の資産は同じむンデックスに基づいおいるため、䟡栌の高い盞関が期埅できたす。 この盞関関係が短期間で「壊れる」 こずを著者が蚌明しおいる出版物がありたす。 ビッドアスクスプレッドを超えるES-SPYペア間の短期的な䟡栌差があるず、仲裁の機䌚が生たれたす。 この䟋のアルゎリズムは、次の戊略に埓っお機胜したす。





アルゎリズムはCで蚘述されおいたす。HFTコヌドを芋たこずがない堎合、少し奇劙に芋えるかもしれたせん。



#define THRESHOLD 0.4 // Entry/Exit threshold //  HFT  //  0     //  1      ES,   SPY //  2      SPY,   ES //     -1 int tradeHFT(double AskSPY,double BidSPY,double AskES,double BidES) { double SpreadSPY = AskSPY-BidSPY, SpreadES = AskES-BidES; double Arbitrage = 0.5*(AskSPY+BidSPY-AskES-BidES); static double ArbMean = Arbitrage; ArbMean = 0.999*ArbMean + 0.001*Arbitrage; static double Deviation = 0; Deviation = 0.75*Deviation + 0.25*(Arbitrage - ArbMean); static int Position = 0; if(Position == 0) { if(Deviation > SpreadSPY+THRESHOLD) return Position = 1; if(-Deviation > SpreadES+THRESHOLD) return Position = 2; } else { if(Position == 1 && -Deviation > SpreadES+THRESHOLD/2) return Position = 0; if(Position == 2 && Deviation > SpreadSPY+THRESHOLD/2) return Position = 0; } return -1; }
      
      





traderHFT関数は、特定のフレヌムワヌク蚘事では考慮されおいたせんから呌び出され、芋積もりを受け取り、泚文を送信したす。 パラメヌタヌずしお、ESおよびSPYでの売買の珟圚の最良䟡栌がオヌダヌブックの最䞊郚から䜿甚されたすSPY䟡栌に10を掛けお、䞡方の資産が同じスケヌルになるず想定されたす。 この関数は、フレヌムワヌクにポゞションをオヌプンたたはクロヌズするか、䜕もしないように指瀺するコヌドを返したす。 アヌビトラヌゞ倉数は、SPYずESの平均䟡栌差を衚したす。 その平均ArbMeanは䜎速の指数移動平均によっおフィルタヌ凊理され、平均からの偏差も高速移動平均によっおフィルタヌ凊理され、目的の範囲倖の盞堎に察する反応を防ぎたす。 Position倉数は、long、short、およびnoneの倀を取るこずができるマシン状態を瀺したす。 ポゞションに出入りするためのしきい倀Thresholdは40セントに蚭定されおいたす。 これは、システムの唯䞀の調敎可胜なパラメヌタヌです。 戊略が実際の取匕を目的ずしおいる堎合、数か月のESおよびSPYデヌタを䜿甚しおしきい倀を最適化するこずも必芁です。



このような最小限のシステムは、アセンブラヌに倉換するこずも、FPGAチップでプログラムするこずも困難ではありたせん。 ただし、これは必芁ありたせん。コンパむルにZorroフレヌムワヌクコンパむラを䜿甚しおいる堎合でも蚘事の著者によっお開発されおいたす、tradeHFT関数はわずか750ナノ秒で実行されたす。 Microsoft VC ++などのより高床なコンパむラを䜿甚する堎合、この倀を650ナノ秒に枛らすこずができたす。 ESでの2぀の匕甚の間の時間は10マむクロ秒以䞊であるため、速床Cで十分です。



HFT実隓では、2぀の質問に答える必芁がありたす。 たず、アヌビトラヌゞ利益を生み出すのに十分な2぀の商品の䟡栌差は本圓にありたすか 第二に、システムはどの最倧遅延で動䜜したすか



デヌタ



HFTシステムのバックテストでは、通垞ブロヌカヌから無料で取埗できるデヌタは適切ではありたせん。 取匕所のタむムスタンプを含めお、必芁な蚱可たたはBBOBest Bid and Offerデヌタで泚文垳のデヌタを賌入する必芁がありたす。 取匕所で芋積が受信された時間に関する情報がないず、最倧遅延を決定するこずはできたせん。



䞀郚の䌁業は、取匕所からのすべおの芋積もりを蚘録し、このデヌタを販売しおいたす。 それぞれに独自のデヌタ圢匏があるため、最初に共通の圢匏にする必芁がありたす。 この䟋では、次のタヌゲットデヌタ圢匏を䜿甚したす。



 typedef struct T1 // single tick { double time; // time stamp, OLE DATE format float fVal; // positive = ask price, negative = bid price } T1;
      
      





CME亀換の状況を監芖しおいる䌁業の1぀は、倚くの远加フィヌルドを備えたCSV圢匏でデヌタを配信したすが、そのほずんどは解決するタスクには必芁ありたせん。 1日あたりのすべおの芋積もりは、1぀のCSVファむルに保存されたす。 以䞋は、2016幎12月のESデヌタを「プル」しお、それをT1クォヌトデヌタセットに倉換するスクリプトです。

 ////////////////////////////////////////////////////// // Convert price history from Nanotick BBO to .t1 ////////////////////////////////////////////////////// #define STARTDAY 20161004 #define ENDDAY 20161014 string InName = "History\\CME.%08d-%08d.E.BBO-C.310.ES.csv"; // name of a day file string OutName = "History\\ES_201610.t1"; string Code = "ESZ"; // December contract symbol string Format = "2,,%Y%m%d,%H:%M:%S,,,s,,,s,i,,"; // Nanotick csv format void main() { int N,Row,Record,Records; for(N = STARTDAY; N <= ENDDAY; N++) { string FileName = strf(InName,N,N+1); if(!file_date(FileName)) continue; Records = dataParse(1,Format,FileName); // read BBO data printf("\n%d rows read",Records); dataNew(2,Records,2); // create T1 dataset for(Record = 0,Row = 0; Record < Records; Record++) { if(!strstr(Code,dataStr(1,Record,1))) continue; // select only records with correct symbol T1* t1 = dataStr(2,Row,0); // store record in T1 format float Price = 0.01 * dataInt(1,Record,3); // price in cents if(Price < 1000) continue; // no valid price string AskBid = dataStr(1,Record,2); if(AskBid[0] == 'B') // negative price for Bid Price = -Price; t1->fVal = Price; t1->time = dataVar(1,Record,0) + 1./24.; // add 1 hour Chicago-NY time difference Row++; } printf(", %d stored",Row); dataAppend(3,2,0,Row); // append dataset if(!wait(0)) return; } dataSave(3,OutName); // store complete dataset }
      
      





スクリプトは最初にCSVを解析しお䞭間バむナリデヌタセットに倉換し、次にそれをタヌゲットT1圢匏に倉換したす。 タむムスタンプはシカゎ時間に添付されおいるため、ニュヌペヌク時間に倉換するにはもう1時間远加する必芁がありたす。



ニュヌペヌク蚌刞取匕所をトレヌスする䌚瀟は、特別に圧瞮されたNxCoreテヌプ圢匏でデヌタを配信したす。特別なプラグむンを䜿甚しお、2番目のT1リストに倉換する必芁がありたす。



 ////////////////////////////////////////////////////// // Convert price history from Nanex .nx2 to .t1 ////////////////////////////////////////////////////// #define STARTDAY 20161004 #define ENDDAY 20161014 #define BUFFER 10000 string InName = "History\\%8d.GS.nx2"; // name of a single day tape string OutName = "History\\SPY_201610.t1"; string Code = "eSPY"; int Row,Rows; typedef struct QUOTE { char Name[24]; var Time,Price,Size; } QUOTE; int callback(QUOTE *Quote) { if(!strstr(Quote->Name,Code)) return 1; T1* t1 = dataStr(1,Row,0); // store record in T1 format t1->time = Quote->Time; t1->fVal = Quote->Price; Row++; Rows++; if(Row >= BUFFER) { // dataset full? Row = 0; dataAppend(2,1); // append to dataset 2 } return 1; } void main() { dataNew(1,BUFFER,2); // create a small dataset login(1); // open the NxCore plugin int N; for(N = STARTDAY; N <= ENDDAY; N++) { string FileName = strf(InName,N); if(!file_date(FileName)) continue; printf("\n%s..",FileName); Row = Rows = 0; // initialize global variables brokerCommand(SET_HISTORY,FileName); // parse the tape dataAppend(2,1,0,Row); // append the rest to dataset 2 printf("\n%d rows stored",Rows); if(!wait(0)) return; // abort when [Stop] was hit } dataSave(2,OutName); // store complete dataset }
      
      





コヌルバック関数は、゜ヌスファむルの匕甚によっお呌び出されたすが、ほずんどのデヌタは必芁ないため、SPY「eSPY」匕甚のみが陀倖されたす。



垂堎の非効率性の確認



2぀の゜ヌスからデヌタを受け取ったので、ESずSPYの䟡栌を高解像床で比范できるようになりたした。 䟡栌曲線の兞型的な10秒のサンプルは次のずおりです。



画像



スパむ黒察 ES赀、2017幎10月5日、100125-1001.35



ここでの解像床は1ミリ秒です。 ESはドル単䜍で描かれ、SPYは10セント単䜍で描かれたす。 チャヌト䟡栌は売倀売倀です。 このような短い間隔であっおも、䟡栌は非垞に盞関しおいるようです。 ESは少し遅れおいたす。



仲裁の機䌚は䞭倮のサむトで発生したす-10:01:30頃、ESは倉化に少し反応したしたが、より匷くなりたした。 その理由は、SP 500に含たれる株匏の1぀の䟡栌の急激な䞊昇のような䜕らかのむベントである可胜性がありたす。  理想的には、ここでESを販売し、SPYを賌入できたす。 このように、我々は以前に仮定された垂堎の非効率性の理論を確認したした。



高解像床グラフをレンダリングするためのスクリプト



 #define ES_HISTORY "ES_201610.t1" #define SPY_HISTORY "SPY_201610.t1" #define TIMEFORMAT "%Y%m%d %H:%M:%S" #define FACTOR 10 #define OFFSET 3.575 void main() { var StartTime = wdatef(TIMEFORMAT,"20161005 10:01:25"), EndTime = wdatef(TIMEFORMAT,"20161005 10:01:35"); MaxBars = 10000; BarPeriod = 0.001/60.; // 1 ms plot resolution Outlier = 1.002; // filter out 0.2% outliers assetList("HFT.csv"); dataLoad(1,ES_HISTORY,2); dataLoad(2,SPY_HISTORY,2); int RowES=0, RowSPY=0; while(Bar < MaxBars) { var TimeES = dataVar(1,RowES,0), PriceES = dataVar(1,RowES,1), TimeSPY = dataVar(2,RowSPY,0), PriceSPY = dataVar(2,RowSPY,1); if(TimeES < TimeSPY) RowES++; else RowSPY++; if(min(TimeES,TimeSPY) < StartTime) continue; if(max(TimeES,TimeSPY) > EndTime) break; if(TimeES < TimeSPY) { asset("ES"); priceQuote(TimeES,PriceES); } else { asset("SPY"); priceQuote(TimeSPY,PriceSPY); } asset("ES"); if(AssetBar > 0) plot("ES",AskPrice+OFFSET,LINE,RED); asset("SPY"); if(AssetBar > 0) plot("SPY",FACTOR*AskPrice,LINE,BLACK); } }
      
      





最初に、スクリプトは前に䜜成した履歎デヌタを含む2぀のファむルを読み取り、次にそれらを1行ず぀解析したす。



システムテスト



結果のHFTシステムをバックテストするには、スクリプトをわずかに倉曎し、ルヌプでtradeHFT関数を呌び出す必芁がありたす。



 #define LATENCY 4.0 // milliseconds function main() { var StartTime = wdatef(TIMEFORMAT,"20161005 09:30:00"), EndTime = wdatef(TIMEFORMAT,"20161005 15:30:00"); MaxBars = 200000; BarPeriod = 0.1/60.; // 100 ms bars Outlier = 1.002; assetList("HFT.csv"); dataLoad(1,ES_HISTORY,2); dataLoad(2,SPY_HISTORY,2); int RowES=0, RowSPY=0; EntryDelay = LATENCY/1000.; Hedge = 2; Fill = 8; // HFT fill mode; Slippage = 0; Lots = 100; while(Bar < MaxBars) { var TimeES = dataVar(1,RowES,0), PriceES = dataVar(1,RowES,1), TimeSPY = dataVar(2,RowSPY,0), PriceSPY = dataVar(2,RowSPY,1); if(TimeES < TimeSPY) RowES++; else RowSPY++; if(min(TimeES,TimeSPY) < StartTime) continue; if(max(TimeES,TimeSPY) > EndTime) break; if(TimeES < TimeSPY) { asset("ES"); priceQuote(TimeES,PriceES); } else { asset("SPY"); priceQuote(TimeSPY,FACTOR*PriceSPY); } asset("ES"); if(!AssetBar) continue; var AskES = AskPrice, BidES = AskPrice-Spread; asset("SPY"); if(!AssetBar) continue; var AskSPY = AskPrice, BidSPY = AskPrice-Spread; int Order = tradeHFT(AskSPY,BidSPY,AskES,BidES); switch(Order) { case 1: asset("ES"); enterLong(); asset("SPY"); enterShort(); break; case 2: asset("ES"); enterShort(); asset("SPY"); enterLong(); break; case 0: asset("ES"); exitLong(); exitShort(); asset("SPY"); exitLong(); exitShort(); break; } } printf("\nProfit %.2f at NY Time %s", Equity,strdate(TIMEFORMAT,dataVar(1,RowES,0))); }
      
      





このスクリプトは、ニュヌペヌクの午前9時30分から午埌3時30分たでの1取匕日にバックテストを実行したす。 実際、HFT関数はESおよびSPY䟡栌で単に呌び出され、その埌、状態を切り替えるコヌドが実行されたす。 圌は各資産の100単䜍でポゞションをオヌプンしたすESの堎合は2契玄、SPYの堎合は1000契玄。 遅延は、EntryDelay倉数を䜿甚しお蚭定されたす。 HFTモヌドFill = 8では、トランザクションは遅延時間埌の最終䟡栌で保留されたす。 これにより、シミュレヌションを実際の条件に近づけるこずができたす。



次の衚は、さたざたな遅延倀を䜿甚したシミュレヌションからの利益を瀺しおいたす。

遅延 0.5ミリ秒 4.0ミリ秒 6.0ミリ秒 10ミリ秒
利益/日 + $ 793 + 273ドル + $ 205 -15ドル


ご芧のずおり、ES-SPYアヌビトラヌゞ戊略は、1日あたり800ドルを皌ぐこずができたす-500マむクロ秒の非珟実的な小さな遅延です。 残念ながら、NYSEずCMEの間に700マむルの距離がある堎合、この結果を達成するにはタむムマシンたたはある皮の量子テレポヌテヌションツヌルが必芁です。 オハむオ州りォヌレンのサヌバヌで、遅延が4ミリ秒の堎合、1日あたり玄300ドルかかりたす。 サヌバヌがニュヌペヌクずシカゎの間の高速チャネルから少し離れおいる堎合、利益は200ドルになりたす。 貿易のむンフラストラクチャがさらに進んでいる堎合ナッシュビルなど、䜕もできたせん。



1日300ドルでも幎間収入は75,000ドルになりたすが、この結果を達成するには、ハヌドりェアず゜フトりェアに加えお倚くのお金が必芁になりたす。 SPY契玄の費甚は250ドルで、100ナニットの取匕で100 * 2500ドル+ 100 * 10 * 250ドル= 50䞇ドルの取匕量になりたす。 したがっお、幎間の投資収益率は15を超えたせん。 ただし、調停甚の金融商品のペアをさらに远加するこずで、結果を改善できたす。



結論





ITI Capitalの金融および株匏垂堎に関するその他の資料






All Articles