赫茲股票量化軟件:從網(wǎng)絡(luò)中獲取債券收益率數(shù)據(jù)

自動(dòng)交易幾乎完全基于技術(shù)指標(biāo),這些指標(biāo)使用過去的價(jià)格行為來預(yù)測未來的價(jià)格行為。然而,忽略市場運(yùn)動(dòng)的基本力量的交易者對將基本數(shù)據(jù)納入其交易決策的交易者不利?;谧詣?dòng)收集的基礎(chǔ)數(shù)據(jù)的指標(biāo)可以提高專家顧問的效率。對匯率影響最大的基礎(chǔ)數(shù)據(jù)是利率,它影響貨幣的感知價(jià)值,雖然央行的利率沒有波動(dòng),但美國等政府債券的收益率、0年期國債,在全球債券市場的所有時(shí)間框架內(nèi)波動(dòng)。這些收益率反映了市場對未來央行利率走向的預(yù)期。債券收益率通常是利率和匯率的主要指標(biāo)。在金融市場中,適用于貨幣對的度量標(biāo)準(zhǔn)是不同時(shí)間段的利率差,特別是delta或利率差變化本文介紹了如何從網(wǎng)絡(luò)中收集債券收益率數(shù)據(jù),并從利率差和增量的數(shù)據(jù)表達(dá)式中推導(dǎo)出債券收益率數(shù)據(jù)。

編輯切換為居中
抓取的基礎(chǔ)
瀏覽器中顯示的網(wǎng)頁通常由許多元素組成:格式化的文本、圖形、圖像、聲音和視頻。所有這些元素都存在于Web服務(wù)器上的文件中,并由瀏覽器使用特定地址或URL按順序下載以訪問它們。但是,程序可以下載頁面的一個(gè)元素,而忽略其余元素,因?yàn)樵撛鼐哂杏杏玫男畔?。以這種方式獲取信息被稱為“抓取”。要做到這一點(diǎn),抓取程序必須具有包含元素的文件的URL,該元素可能是顯示在網(wǎng)頁上的數(shù)字。它可以下載該文件,搜索代表數(shù)字的文本,并將該文本轉(zhuǎn)換為數(shù)值。

編輯切換為居中
取得 URL
抓取的第一個(gè)任務(wù)是獲取包含要下載元素的文件的URL。如果元素嵌入到頁面的HTML文本中,那么它可以是網(wǎng)頁的URL,在這種情況下,可以從頁面的HTML文本分析元素?;蛘?,URL可以嵌入到頁面上的鏈接中,瀏覽器使用該鏈接來獲取元素,而scraper程序可以使用該鏈接來獲取要分析元素的HTML文本?;蛘撸梢酝ㄟ^鏈接到頁面上的腳本將URL傳遞給瀏覽器,瀏覽器將在下載頁面和腳本后運(yùn)行該腳本。在這種情況下,scraper程序不必運(yùn)行腳本,但可以使用腳本生成的URL,使用Internet Explorer或Google Chrome中提供的開發(fā)工具可以發(fā)現(xiàn)該URL。無論URL的來源是什么,抓取程序都會使用它從Web服務(wù)器下載一個(gè)文件,并對其進(jìn)行解析以獲取所需的信息。有幾個(gè)金融網(wǎng)站報(bào)告?zhèn)找媛剩掌澒善绷炕紫葢?yīng)該看看 來創(chuàng)建抓取的例子。首先,讓赫茲股票量化看看當(dāng)單擊上面的鏈接時(shí)瀏覽器從Web服務(wù)器下載的HTML文件。當(dāng)頁面顯示在Chrome瀏覽器中時(shí),單擊右上角的“工具”按鈕,將鼠標(biāo)光標(biāo)移動(dòng)到“更多工具”,選擇“將頁面另存為”,下載HTML文件,并在文本編輯器(如記事本)中打開它。很明顯,這個(gè)網(wǎng)站使抓取程序很容易獲得報(bào)價(jià),因?yàn)樗贖TML文件頭部的一系列元標(biāo)記中。元數(shù)據(jù)不由瀏覽器顯示,對顯示的內(nèi)容沒有影響,但任何下載HTML文件的程序都可以訪問它。報(bào)價(jià)出現(xiàn)在元標(biāo)簽<meta name=“price”content=“3.066”>中,距標(biāo)簽開頭28個(gè)字符,與瀏覽器在頁面上突出顯示的值相同。抓取程序可以在文件中搜索文本字符串[<meta name=“price”content=],在meta標(biāo)記開頭的索引中增加28,并將結(jié)果位置的文本轉(zhuǎn)換為浮點(diǎn)數(shù)字。為了避免混淆,本文中使用方括號引用HTML文本,HTML文本經(jīng)常使用引號。
構(gòu)建一個(gè)更好的程序
鏈接到上面的HTML文件從服務(wù)器下載時(shí),包含大量樣式表信息,總大小為295千字節(jié)。但是,感興趣的meta標(biāo)記與文件開頭的距離僅為3千字節(jié)。一個(gè)表現(xiàn)較好的抓取程序下載的數(shù)據(jù)不會超過它所需要的數(shù)量,所以每次獲取報(bào)價(jià)時(shí)只下載前四個(gè)千字節(jié)是合理的。不幸的是,mql 函數(shù) WebRequest()無法限制要下載的數(shù)據(jù)量。包含服務(wù)器響應(yīng)數(shù)據(jù)的數(shù)組必須是動(dòng)態(tài)數(shù)組。如果使用指定大小的靜態(tài)數(shù)組,程序?qū)⒖梢哉>幾g,但在運(yùn)行時(shí)發(fā)生錯(cuò)誤,導(dǎo)致終端崩潰??梢园趯Ψ?wù)器的請求中包含 Range 頭,但大多數(shù)服務(wù)器不支持 Range 頭。所以,從Web服務(wù)器下載的數(shù)據(jù)量幾乎總是所請求的HTML文件的大小。更好的方法是使用wininet.dll中的函數(shù),wininet.dll是Windows的一個(gè)組件。其中一個(gè)函數(shù) InternetReadFile()可以下載指定數(shù)量的字節(jié),即使不支持范圍頭并且下載從文件開頭開始。WinINet 函數(shù)可以導(dǎo)入到 MQL 腳本或 EA 交易中。本文所附的 ScraperBot01.mq5 文件是一個(gè)腳本,它下載HTML文件的前4千字節(jié),定位所下載文本中感興趣的元標(biāo)記,查找該標(biāo)記中表示10年 T-note上最后一次引用的收益率的文本,將該文本轉(zhuǎn)換為浮點(diǎn)數(shù),并將其值打印到終端。
ScraperBot 01
源代碼文件 ScraperBot01.mq5 首先導(dǎo)入wininet.dll 并原型化將調(diào)用的函數(shù),將所有參數(shù)聲明為具有與 mql5 兼容的類型。
#import "wininet.dll" ?int InternetCheckConnectionW(string& lpszUrl, uint dwFlags, uint dwReserved); ?int InternetOpenW(string& lpszAgent, uint dwAccessType, string& lpszProxyName, string& lpszProxyBypass, uint dwFlags); ?int InternetOpenUrlW(int hInternetSession, string& lpszUrl, string& lpszHeaders, uint dwHeadersLength, uint dwFlags, uint dwContext); ?int InternetReadFile(int hFile, uchar& lpBuffer[], uint dwNumberOfBytesToRead, uint& lpdwNumberOfBytesRead); ?int InternetCloseHandle(int hInternet); #import uchar uc_Buffer[4096]; // InternetReadFile() 需要靜態(tài)的緩沖區(qū). float f_US;
靜態(tài)數(shù)組 uc_Buffer 將用于接收從網(wǎng)絡(luò)服務(wù)器上下載的 html 文本,而 f_US 變量用于設(shè)置從文本中分析到的數(shù)字值,它們在全局范圍內(nèi)聲明。本文和本文附加的其他文件中的約定是通過類型說明符和名稱之間的下劃線來表示全局變量。uc_Buffer的大小設(shè)置為適應(yīng)將要下載的特定字節(jié)數(shù)。
在 OnStart()的頂部聲明了一些局部變量,其他變量則根據(jù)需要聲明,以明確它們的用途。首先,赫茲股票量化檢查一下互聯(lián)網(wǎng)連接是否可用。此腳本中調(diào)用的函數(shù)的返回值將打印到終端,以指示成功或失敗,如果發(fā)生錯(cuò)誤,則關(guān)閉打開的句柄,并使用“返回”語句終止腳本。如果有可用的Internet連接,則初始化句柄 iNet1,以便隨后調(diào)用 WinINet函數(shù)。有效的句柄值大于零。
void OnStart() { bool bResult; ?int i, iNet1, iNet2; ? ?string stURL = "http://www.msn.com"; ?bResult = InternetCheckConnectionW(stURL, 1, 0); // 1 == FLAG_ICC_FORCE_CONNECTION ?Print("InternetCheckConnectionW() returned ", bResult); ?if(!bResult) return; ? ?string stAgent = "Mozilla/5.0", stNull = ""; ?iNet1 = InternetOpenW(stAgent, // _In_ LPCTSTR lpszAgent ? ? ? ? ? ? ? ? ? ? ? ?1, ? ? ? // 1 == INTERNET_OPEN_TYPE_DIRECT ? ? ? ? ? ? ? ? ? ? ? ?stNull, ?// _In_ LPCTSTR lpszProxyName ? ? ? ? ? ? ? ? ? ? ? ?stNull, ?// _In_ LPCTSTR lpszProxyBypass ? ? ? ? ? ? ? ? ? ? ? ?NULL); ? // _In_ DWORD dwFlags ?Print("iNet1 == ", iNet1); ?if(iNet1==0) return;
接下來建立到Web服務(wù)器的連接,初始化句柄 iNet2 以下載 html 文件。
?stURL = "https://www.marketwatch.com/investing/bond/tmubmusd10y?countrycode=bx"; ?string stHdr = "Accept: text/*"; ?iNet2 = InternetOpenUrlW(iNet1, ? ? ? ? ? ?// HINTERNET hInternet, ? ? ? ? ? ? ? ? ? ? ? ? ? stURL, ? ? ? ? ? ?// LPCWSTR ? lpszUrl, ? ? ? ? ? ? ? ? ? ? ? ? ? stHdr, ? ? ? ? ? ?// LPCWSTR ? lpszHeaders, ? ? ? ? ? ? ? ? ? ? ? ? ? StringLen(stHdr), // DWORD ? ? dwHeadersLength, ? ? ? ? ? ? ? ? ? ? ? ? ? 0x00080000, ? ? ? // DWORD ? ? dwFlags, 0x00080000 == INTERNET_FLAG_NO_COOKIES ? ? ? ? ? ? ? ? ? ? ? ? ? NULL); ? ? ? ? ? ?// DWORD_PTR dwContext ?Print("iNet2 == ", iNet2); ?if(iNet2==0) ?{ InternetCloseHandle(iNet1); ? ?return; ?}
現(xiàn)在赫茲股票量化可以從Web服務(wù)器下載數(shù)據(jù)。
?uint uGet, uGot; ?uGet = 4080; // 要下載的字節(jié)數(shù) ?bResult = InternetReadFile(iNet2, ? ? // _In_ ?HINTERNET hFile ? ? ? ? ? ? ? ? ? ? ? ? ? ? uc_Buffer, // _Out_ LPVOID lpBuffer ? ? ? ? ? ? ? ? ? ? ? ? ? ? uGet, ? ? ?// _In_ ?DWORD dwNumberOfBytesToRead ? ? ? ? ? ? ? ? ? ? ? ? ? ? uGot); ? ? // _Out_ LPDWORD lpdwNumberOfBytesRead ?Print("InternetReadFile() returned ", bResult, ". Number of bytes read: ", uGot); ?InternetCloseHandle(iNet2); ?// download done ?if(!bResult) {InternetCloseHandle(iNet1); return;} ?uc_Buffer[uGot] = 0; // Terminate string in uc_Buffer by appending a null character.
現(xiàn)在赫茲股票量化在下載的文本中搜索感興趣的meta標(biāo)簽,如果找到了它,在偏移量中添加28,這樣我們就可以使用它作為 uc_Buffer 中表示數(shù)字的文本的索引。通過調(diào)用 StringSubstr()訪問該文本,并在變量“i”中將索引傳遞給它。如果該索引處的文本不代表數(shù)字,則StringToDouble()將返回零,指示錯(cuò)誤,除非債券收益率恰好為零。請注意,字符串中的引號被編碼為\“,以將其與字符串開頭和結(jié)尾的引號區(qū)分開來。
?i = StringFind(CharArrayToString(uc_Buffer), "<meta name=\"price\" content=", 0); // 0 == 開始搜索的位置 ?Print("Offset of \'<meta name=\"price\" content=\' == ", i); ?if(i == -1) {Print("String not found."); ?InternetCloseHandle(iNet1); ?return;} ?i += 28; // 將索引提前到表示債券收益的文本的已知位置。 ?f_US = StringToDouble(StringSubstr(CharArrayToString(uc_Buffer), i, 8)); ?Print("US 10-year T-note yield, stored in variable f_US: ", f_US); ?InternetCloseHandle(iNet1); // wininet 完成. }//END void OnStart()
腳本 ScraperBot01可以在任何圖表上運(yùn)行,在終端中報(bào)告其進(jìn)度,并打印從Web上獲取的值。
另一種情況
既然已經(jīng)演示了從網(wǎng)頁中獲取數(shù)據(jù)的過程,那么讓我們考慮一下如果債券收益率數(shù)據(jù)不在元標(biāo)記中,該怎么做。在這種情況下,赫茲股票量化將檢查網(wǎng)頁的HTML文件,以查找該網(wǎng)頁上顯示的數(shù)字的來源。了解債券收益率的最新報(bào)價(jià)后,我們可以使用文本編輯器的搜索功能來查找表示數(shù)字的文本字符串。在我們下載的HTML文件中,除了meta標(biāo)簽,還可以在其他三個(gè)位置找到報(bào)價(jià)。這三個(gè)元素中的第一個(gè)是 JSON-LD 結(jié)構(gòu)化數(shù)據(jù)片段,它是一個(gè)HTML元素,旨在使搜索引擎和網(wǎng)絡(luò)爬蟲很容易訪問網(wǎng)頁信息。 這里是一部分?jǐn)?shù)據(jù),為了更清晰表示使用了分行顯示。
<script type="application/ld+json"> { "@context":"http://schema.org/", ?"@type":"Intangible/FinancialQuote", ?"url":"https://www.marketwatch.com/investing/bond/tmubmusd10y?countrycode=bx", ?"name":"U.S. 10 Year Treasury Note", ?"tickerSymbol":"TMUBMUSD10Y", ?"exchange":"Tullett Prebon", ?"price":"3.061", ?"priceChange":"0.007", ?"priceChangePercent":"0.22%", ?"quoteTime":"Sep 28, 2018 5:07 p.m.", ?"priceCurrency":"PERCENT" } </script>
算法將首先搜索標(biāo)記的偏移量<script type=“application/ld+json”>,然后從該位置查找“[”price“:”]和的偏移量。如果[“price”:“]的偏移量小于</script>的偏移量,表明它在數(shù)據(jù)段內(nèi),則赫茲股票量化將9添加到[“price”:“]的偏移量中,以到達(dá)表示報(bào)價(jià)的數(shù)字的偏移量。該過程在附加的腳本 ScraperBot02.mq5中演示。
ScraperBot 02
此腳本下載的HTML文件的大小可以達(dá)到umax指定的大小。首次運(yùn)行時(shí),umax應(yīng)設(shè)置為遠(yuǎn)大于預(yù)期下載大小的值,例如100萬。腳本報(bào)告下載的字節(jié)數(shù),如果該字節(jié)數(shù)位于或接近uMax,則應(yīng)增加uMax的值。腳本還報(bào)告標(biāo)記<script type=\“application/ld+json\”>文件中的偏移量,然后,可以將 uMax 的值設(shè)置為略高于標(biāo)記的偏移量。在這種情況下,偏移量為166696,因此uMax設(shè)置為180224以下載足夠的文件,以包含 JSON-LD 片段,而不是整個(gè)文件。該腳本使用靜態(tài)數(shù)組下載16千字節(jié)的塊,這些塊被復(fù)制到動(dòng)態(tài)數(shù)組中并累積到動(dòng)態(tài)數(shù)組中,這些數(shù)組是用全局范圍聲明的。
uchar uc_Buffer[16400], uc_DynBuf[];
然后,ScraperBot02 與 ScraperBot01 相同,直到從Web服務(wù)器下載數(shù)據(jù)的部分,該部分將數(shù)據(jù)分塊打包。在 do-while 循環(huán)中反復(fù)調(diào)用 InternetReadFile,直到下載所需的數(shù)據(jù)量。
?uint uGet, uGot, uDst, uMax; ?uGet = 16384; ? ?// 每次調(diào)用InternetReadFile時(shí)要下載的字節(jié)數(shù),必須至少比 uc_Buffer 大小小1個(gè)字節(jié)。 ?uGot = uDst = 0; // uGot是調(diào)用 InternetReadFile 時(shí)下載的字節(jié)數(shù);uDst 是下載的字節(jié)總數(shù)。 ?uMax = 180224; ? // 最大下載字節(jié)數(shù) ?do ?{ bResult = InternetReadFile(iNet2, ? ? // _In_ ?HINTERNET hFile ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? uc_Buffer, // _Out_ LPVOID lpBuffer ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? uGet, ? ? ?// _In_ ?DWORD dwNumberOfBytesToRead ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? uGot); ? ? // _Out_ LPDWORD lpdwNumberOfBytesRead ? ?uc_Buffer[uGot] = 0; // 使用空字符來結(jié)束 uc_Buffer 中的字符串。 ? ?ArrayCopy(uc_DynBuf, // 目標(biāo)數(shù)組 ? ? ? ? ? ? ?uc_Buffer, // 源數(shù)組 ? ? ? ? ? ? ?uDst, ? ? ?// 開始寫到目標(biāo)數(shù)組的索引 ? ? ? ? ? ? ?0, ? ? ? ? // 開始從源數(shù)組復(fù)制的索引 ? ? ? ? ? ? ?uGot); ? ? // 要復(fù)制的元素?cái)?shù)量 ? ?uDst += uGot; // 為了下一次循環(huán)調(diào)整索引 ?}while(bResult && uGot > 0 && uDst < uMax); ?Print("Size of uc_DynBuf == ", ArraySize(uc_DynBuf)); ?Print("Bytes downloaded ?== ", uDst);
ScraperBot02 現(xiàn)在定位標(biāo)簽<script type=\“application/ld+json\”> 并將偏移存儲在索引變量i中,從該偏移量開始,它定位到[“price”:“]并將該偏移量存儲在j中,然后它在代碼段的末尾找到</script>并將該偏移量存儲在k中。如果j小于k,則將9添加到j(luò)中,這將成為表示數(shù)字的文本的偏移量,然后在f_US中轉(zhuǎn)換為浮點(diǎn)值并打印到終端。
?int i, j, k; // 索引 ?i = StringFind(CharArrayToString(uc_DynBuf), "<script type=\"application/ld+json\">", 0); // 0 == 開始搜索的位置 ?Print("Offset of <script type=\"application/ld+json\"> == ", i); ?if(i == -1) {Print("<script type=\"application/ld+json\"> not found."); ?InternetCloseHandle(iNet1); ?return;} ?j = StringFind(CharArrayToString(uc_DynBuf), "\"price\":\"", i); // i == 開始搜索的位置 ?if(j == -1) {Print("\"price\":\" not found."); ?InternetCloseHandle(iNet1); ?return;} ?Print("Offset of \"price\":\" == ", j); ?k = StringFind(CharArrayToString(uc_DynBuf), "</script>", i); // i == 開始搜索的位置 ?Print("Offset of </script> == ", k); ?if(j > k) {Print("Offset of \"price\":\" is greater than offset of </script>"); ?InternetCloseHandle(iNet1); ?return;} ?j += 9; // 將索引提前到表示債券收益的文本的已知位置。 ?f_US = StringToDouble(StringSubstr(CharArrayToString(uc_DynBuf), j, 8)); ?Print("US 10-year T-note yield, stored in variable f_US: ", f_US); ?InternetCloseHandle(iNet1); // wininet 結(jié)束. }//END void OnStart()
使用開發(fā)者工具
使用Chrome瀏覽器中的開發(fā)人員工具可以找到該Web服務(wù)器報(bào)價(jià)的另一個(gè)來源。從右上角的菜單按鈕,打開開發(fā)者工具并輸入進(jìn)入地址欄。選擇中間窗格中的網(wǎng)絡(luò)選項(xiàng)卡,并選擇“XHR”作為要監(jiān)視的事件類型。選擇這些事件中的任何一個(gè)將打開右側(cè)的窗格,其中顯示諸如標(biāo)題和響應(yīng)等詳細(xì)信息。標(biāo)記為“quoteByDialect…”的事件有一個(gè)有趣的響應(yīng),右鍵單擊該窗格并選擇“全選”可突出顯示該響應(yīng)。按Ctrl+C將突出顯示的文本復(fù)制到剪貼板,然后將其粘貼到文本編輯器中。在字符串 ["CompositeTrading":{"Last":{"Price":{"Iso":"PERCENT","Value":] 后的文本塊中可以找到報(bào)價(jià)??梢栽凇皹?biāo)題”選項(xiàng)卡下找到獲取該文本塊的URL。在這種情況下它有些長: https://api.wsj.net/api/dylan/quotes/v2/comp/quoteByDialect?dialect=official&needed=CompositeTrading|BluegrassChannels&MaxInstrumentMatches=1&accept=application/json&EntitlementToken=cecc4267a0194af89ca343805a3e57af&ckey=cecc4267a0&dialects=Charting&id=Bond-BX-TMUBMUSD10Y,Bond-BX-TMBMKDE-1. 單擊本文右側(cè)的鏈接將在瀏覽器窗口中顯示文本塊。它實(shí)際上是兩塊文本,一塊接一塊,因?yàn)樵赨RL的末尾有兩個(gè)由逗號分隔的斷續(xù)器符號字符串。第一個(gè)“Bond-BX-TMUBMUSD10Y”用于美國10年期國債,第二個(gè)“Bond-BX-TMBMKDE-10Y”用于德國10年期國債。從URL中刪除第二個(gè)斷續(xù)器符號字符串會將下載文本的大小從7.1千字節(jié)減少到3.6千字節(jié)。
隨附的腳本 ScraperBot03 下載了滾動(dòng)條符號“TMUBMUSD10Y”的文本塊,找到字符串["CompositeTrading":{"Last":{"Price":{"Iso":"PERCENT","Value":],,在字符串開頭的偏移量中添加61,將其用作表示數(shù)字的文本的索引,將文本轉(zhuǎn)換為浮點(diǎn)數(shù)并把它打印到終端中。該腳本是根據(jù)ScrapterBot01建模的,因此此處不引用代碼。這個(gè)資源的一個(gè)優(yōu)點(diǎn)是下載的規(guī)模很小,由于URL所尋址的文件只有3.6千字節(jié),因此可以使用mql5函數(shù)WebRequest(而不是wininet.dll中的函數(shù))來下載該文件,而無需下載遠(yuǎn)遠(yuǎn)超過需要的數(shù)據(jù)。
ScraperBot 04
此腳本使用 WebRequest 而不是 WinINet函數(shù)下載與 ScraperBot 03相同的數(shù)據(jù)。為了使 WebRequest工作,服務(wù)器的基本URL(在本例中為“https://api.wsj.net”)需要包含在 MetaTrader平臺的“工具\(yùn)選項(xiàng)\專家顧問”下的允許服務(wù)器列表中。全局 char 數(shù)組 ch_Data 不會將任何數(shù)據(jù)傳遞給 WebRequest,它的存在只是為了滿足對該類型參數(shù)的要求。
char ch_Buffer[], ch_Data[16]; float f_US; void OnStart() { int i; ? ?string stURL = "https://api.wsj.net/api/dylan/quotes/v2/comp/quoteByDialect?dialect=official&needed=CompositeTrading|BluegrassChannels&" ? ? ? ? ? ? ? ? "MaxInstrumentMatches=1&accept=application/json&EntitlementToken=cecc4267a0194af89ca343805a3e57af&ckey=cecc4267a0&" ? ? ? ? ? ? ? ? "dialects=Charting&id=Bond-BX-TMUBMUSD10Y"; ?string stHdr = "Accept: text/*, User-Agent: Mozilla/5.0"; ?string stRspHdr; // 回應(yīng)頭 ? ?i = WebRequest("GET", ? ? // const string ?method, ? ?HTTP 方法 ? ? ? ? ? ? ? ? stURL, ? ? // const string ?url, ? ? ? URL ? ? ? ? ? ? ? ? stHdr, ? ? // const string ?headers, ? ? ? ? ? ? ? ? ? 1024, ? ? ?// int ? ? ? ? ? timeout, ? ? ? ? ? ? ? ? ch_Data, ? // const char ? ?&data[], ?HTTP 消息體的數(shù)組 ? ? ? ? ? ? ? ? ch_Buffer, // char ? ? ? ? ?&result[], 包含服務(wù)器回應(yīng)數(shù)據(jù)的數(shù)組 ? ? ? ? ? ? ? ? stRspHdr); // string ? ? ? ?&result_headers ?Print("Server response code: ", i); ?if(i == -1) {Print("GetLastError == ", GetLastError()); ?return;} ?Print("Size of ch_Buffer (bytes downloaded) == ", ArraySize(ch_Buffer)); ?Print("Response header:\n", stRspHdr); ? ?string stSearch = "\"CompositeTrading\":{\"Last\":{\"Price\":{\"Iso\":\"PERCENT\",\"Value\":"; ?i = StringFind(CharArrayToString(ch_Buffer), stSearch, 0); // 0 == 開始搜索的位置 ?Print("Offset of ", stSearch, " == ", i); ?if(i == -1) {Print(stSearch, " not found."); ?return;} ?i += 61; // 將索引提前到表示債券收益的文本的已知位置。 ?f_US = StringToDouble(StringSubstr(CharArrayToString(ch_Buffer), i, 8)); ?Print("US 10-year T-note yield, stored in variable f_US: ", f_US); }//END void OnStart()