Bloomberg Automation - (2).Terminal 畫面留存並解析內容

Capture  Bloomberg screen and parsing content

 

本系列的主題如下,所有的程式碼可以從 這裡 下載。

 

上一篇建立 DDE 程式基礎架構後,接下來要思考的問題是透過程式執行Bloomberg的功能後,這對我們有什麼幫助?如果只是顯示查詢的結果,這對操作Bloomberg的人員而言沒有太大的幫助,但是若能自動將畫面複製存檔,就可當作分析的佐證資料,要是能更進一步的將畫面轉成文字內容,這對資料分析將會有莫大的幫助,以下將介紹實際作法。

Bloombertg畫面複製

用程式複製畫面一般有以下作法

  • 用 API 複製畫面
  • 用Bloomberg GRAB指令複製畫面並用 email 傳送

這兩種作法實作時會碰到一些問題,分析如下:

用API必需考量到要複製的畫面可能被其它視窗遮住,所以需先讓視窗跑到最上層(Active Window),另外若只想複製單一視窗,而不是複製整個桌面,這時就要處理要複製畫面的範圍。

用 GRAB指令透過email 傳送畫面的圖片,該圖片是存在email信箱,程式無法直接取得圖片,且這種作法速度較慢,不適合大量資料的處理。

Bloomberg 神奇的COPY指令

Bloomberg 有一個指令,在Bloombeg 鍵盤看不到,在Terminal 也不接受該指令,只有DDE才可接受這個指令,這個指令叫 COPY,顧名思義就是專門複製畫面的指令,這個指令有什麼特點呢?首先它解決畫面被其它視窗遮住的問題,例如我們要複製的Bloomberg 第1個視窗被其它視窗遮住時,COPY指令會先將這個視窗帶到前面成為Active Window,第2個特點是它只會複製指定的視窗,不會複製整個桌面,所以不需特別處理要複製的範圍,第3個特點是複製的圖片會存在Windows 的剪貼簿中,所以程式可以直接抓到圖片,這對於大量資料的處理非常有用。


我們先定義一個存放Bloomberg 指令的Class,目的是讓其它程式可以直接引用定義好的指令,我整理好常用的指令定義如下供各位參考:

public class BloombergKeys
{
  public const string Go = "<GO>";                   // Go
  public const string Cancel = "<CANCEL>";           // Cancel
  public const string TabRight = "<TABR>";           // TAB
  public const string TabLeft = "<TABL>";            // Shift TAB
  public const string CopyScreen = "<COPY>";         // Copy Screen
  public const string PageForword = "<PAGEFWD>";     // Next Page
  public const string PageBack = "<PAGEBACK>";       // Previous Page
}

接下來就是今天主角COPY指令的處理,在BloombergDDEBase Class 加上下列程式

public void CopyScreen(int windowNum)
{
  DDEInputCommand(windowNum, BloombergKeys.CopyScreen);
}

CopyScreen 透過 DDEInputCommand method 指定要使用哪一個視窗執行指令,並將 <COPY> 指令傳送至Bloomberg,這樣就完成了本篇文章所需的功能,沒錯!就是這樣簡單。

接下來寫一支測試程式,我們繼續延用上一篇文章建立的 frmDDE Form , 增加 Copy Screen 按鈕

程式碼如下

private void btnCopyScreen_Click(object sender, EventArgs e)
{
  using (BloombergDDEBase bloombergDDE = new BloombergDDEBase())
  {
    int windowNum = int.Parse(cboWindowNum.Text);

    LogPrint("Before Execute Command: <COPY>");

    bloombergDDE.CopyScreen(windowNum);

    LogPrint("After Execute Command: <COPY>");
  }
}

按下按鈕後,會看到Bloomberg 視窗會成為 Active Window,畫面內容不會有任何變化,因為COPY 指令只是將畫面放到剪貼簿,所以畫面不會有任何變化,此時可開啟小畫家軟體,按下貼上功能,就會出現Bloomberg 畫面的內容。

下圖是Bloomberg 原本的畫面內容

 

在小畫家軟體貼上剪貼簿的內容

從上面兩張圖可以看到剪貼簿的圖片背景是白色,會跟原本的黑色背景不同,另外畫面上的時間,原圖為 12:46:58 ,複製後的時間為12:47:11,不一樣的原因是我先人工剪下Bloomberg 的原圖,然後才用程式執行COPY的功能,所以會有時間落差。

接下來我們可以用C# 的 Clipboard.GetImage() 抓剪貼簿的圖片,就可以做到自行存成圖檔留存的功能。可是除此之外若可以作到解析畫面圖片的內容,成為文字格式供進一步的分析,如果能做到這樣就太完美了,在此要公布一個小技巧,要做到畫面的解析不需寫複雜的文字辦識OCR功能,也不用寫任何一行程式碼,是的,你沒看錯,真的不用寫程式,Bloomberg 已經為我們考慮到這個需求,在執行COPY指令複製畫面到剪貼簿的同時,也幫我們將畫面的內容以文字的格式存到剪貼簿,上面示範用小畫家軟體從剪貼簿取得圖片,現在你也可以另外開啟記事本(Notepad)軟體,再將剪貼簿內容貼上,你會發現貼上的內容就是Bloomberg畫面的文字內容,酷吧。

貼上的文字內容如下:

 



MSFT 3.7 08/08/46 Corp	Stop Monitoring	Settings	All Quotes
12:47:11	ALLX Mode	Overlay Axes	Split Bid/Offer	94) Switch	95) Buy	96) Sell
Spreads vs	T 2 ?08/15/47 Govt	100-05	/	100-06	2.742	/	2.741	77.9	/	72.3
Filter By	All	Execution Venue	BGM	Legend
 	PCS	Firm Name	Bid Px	/	Ask Px	Bid Spd	/	Ask Spd	 	BSz(M)	x	ASz(M)	 	TimeDn
 	BGN	BLOOMBERG GENERIC	103.117	/	104.262	79.4	/	73.1	 	 	x	 	 	05:59
 	TRAC	FINRA - TRACE	103.176	 	Last Trd	78.2	 	Last Trd	 	7	 	Last Trd	 	12/13
 	BVAL	BVAL (Score: 7)	103.546	/	103.932	75.9	/	73.9	 	 	x	 	 	05:00
 	EXCH	EXCHANGE TRADED	103.176	/	Last Trd	77.9	/	 	 	 	x	Last Trd	 	12/13
 	BMRK	BBG REALTIME EVAL	103.675	/	103.988	76.3	/	74.6	 	2000	 	Indic Sz	 	12/13
 	 	 	 	 	 	 	 	 	 	 	 	 	 	 
 	USBC	U.S. Bancorp	103.155	/	 	78.0	/	 	 	3170	x	 	 	12:46
 	DAIW	Daiwa CapMkts AM	101.009	/	 	90.0	/	 	 	300	x	 	 	12:46
 	EDFA	ED&F MAN	98.370	/	 	105.1	/	 	 	500	x	 	 	12:46
 	GSFO	Global Securities	102.774	/	102.981	80.1	/	79.1	 	1000	x	1000	 	12/13
 	ODSB	ODDOSEYDLER BANK AG	102.880	/	103.850	79.5	/	74.3	 	100	x	100	 	12/13
 	GETX	GETTEX	102.733	/	103.650	80.3	/	75.4	 	100	x	100	 	12/13
 	TRMT	FINRA TRACE (>=250M)	103.549	 	Last Trd	74.6	 	Last Trd	 	600	 	Last Trd	 	12/13
 	TRMB	FINRA TRACE (>=500M)	103.549	 	Last Trd	74.6	 	Last Trd	 	600	 	Last Trd	 	12/13
 	TRST	FINRA TRACE (<=1MM)	103.176	 	Last Trd	78.2	 	Last Trd	 	7	 	Last Trd	 	12/13
 	FRNK	FRANKFURT EXCH	102.880	/	103.850	79.5	/	74.3	 	 	x	 	 	12/13
 	MNCH	MUNICH EXCHANGE	102.733	/	103.650	80.3	/	75.4	 	 	x	 	 	12/13
 	HMBG	HAMBURG EXCHANGE	102.670	/	103.650	80.7	/	75.4	 	 	x	 	 	12/13
 	HNVR	HANOVER EXCHANGE	102.670	/	103.650	80.7	/	75.4	 	 	x	 	 	12/13
 	BRLN	BERLIN EXCHANGE	102.622	/	103.854	81.0	/	74.3	 	 	x	 	 	12/13
 	DWZH	DWZ - HAMBURG FIXING	102.500	/	Last Trd	81.6	/	 	 	 	x	Last Trd	 	12/13
 	DWZG	DWZ - GERMAN FIXING	102.500	/	Last Trd	81.6	/	 	 	 	x	Last Trd	 	12/13
 	STGT	STUTTGART EXCHANGE	102.490	/	103.580	81.7	/	75.8	 	 	x	 	 	12/13

文字內容看起來好像很雜亂,其實是因為每個欄位之間是用 TAB 當作分隔符號,所以畫面有點亂,只要知道這個規則就可拆解內容取出你所需的資料。之後在說明 ALLQ功能時會再說明剪貼簿中圖片與文字的處理。

下一篇文章將會說明用 DDE 達到 Login 及 Logout 的功能。