Bloomberg Automation - (1).DDE 基礎架構

Bloomberg Automation use DDE

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

 

金融業常會使用 Bloomberg 取得各項商品資料,為了快速取得所需的資料常會透過程式使用Excel VBA或是API的方式讀取Bloomberg的資料,這兩種作法雖然可以抓取資料,但若是碰到所需的資料無法直接抓取,必需在Bloomberg Terminal上輸入指令才可查到資料的情況下,這兩種作法就無法逹到要求。現在要介紹另一種DDE的作法,它雖然跟Excel  VBA 一樣都是透過DDE的方式運作,但是Excel VBA 主要是以抓取資料為主,無法控制Bloomberg執行所需的指令,而這裡介紹的作法是直接傳送指令給Bloomberg,例如輸入DES、ALLQ、HP等指令,這樣就可模擬使用者操作 Terminal ,畫面也會依據輸入的指令顯示對應的內容。

我將會以一系列的文章說明如何用 DDE 傳送指令給 Bloomberg Terminal,並示範抓取 ALLQ 及 HP 畫面的內容並轉成圖片及文字,最後再介紹使用Bloomberg GRAB功能將畫面 email 給指定人員。

本系列以 Visual Studio 2015 的C# 為開發環境,採用 Windows Forms Application 為架構,首先先新增新的專案,名稱為 BloombergAutomation, DDE Library 可從 NetGet安裝,在 NuGet Package Manager 輸入 NDde並安裝此元件, 若需要NDde原始碼可從 這裡 下載。

 

在專案中建立 Infrastructure Folder, 並新增 BloombergDDEBase Class,這個Class是我們與Bloomberg 溝通的核心程式,後續將會陸續增加相關的功能。

public class BloombergDDEBase
{
  private DdeClient _dc;

  public BloombergDDEBase()
  {
    Connect();
  }

  private void Connect()
  {
    _dc = new DdeClient("winblp", "bbk");
    _dc.Connect();
  }
}

首先產生 _dc 變數,所有與Bloomberg溝通的指令都是透過此變數傳遞,Bloomberg DDE 連線的Service 指定為 winblp, Topic 指定為 bbk,最後執行 Connect() 連線Bloomberg 。

執行 Bloomberg 指令

使用Bloomberg 時,會輸入要查詢的Ticker及功能代碼,例如我要查 US594918BT09 這檔債券的基本資料,我會先輸入 US594918BT09,再輸入DES<GO>,出現的畫面如下圖:

透過DDE程式我們也可以直接傳送 US594918BT09 <Corp>DES<GO> 至Bloomberg逹到同樣的結果,在說明如何送指令之前要先了解Bloomberg DDE 運作方式,Bloomberg 總共有4個視窗可顯示資料,如下圖

Bloombeg 這4個視窗分別是1-BLOOMBERG, 2-BLOOMBERG,3-BLOOMBERG,4-BLOOMBERG,這4個視窗可以獨立運作顯示不同的資料,因此我們必需告訴Bloomberg 要用哪一個視窗執行指令,了解這個原理後就可以加上傳送指令的程式碼

 

public void DDEInputCommand(int windowNum, string commandText)
{
  if (_dc == null)
  {
    throw new Exception("DDE Server not connected!");
  }

  _dc.Execute(GetDDEWindowNum(windowNum) + commandText, 5000);
}

private string GetDDEWindowNum(int windowNum)
{
  return "<blp-" + (windowNum - 1) + ">";
}

DDEInputCommand 程式碼執行_dc.Execute 將指令傳送至Bloomberg,第一個參數是要執行的指令,第二個參數 5000 代表Timeout 時間 5000 milliseconds,前面說過Bloomberg 有4個視窗可執行指令,因此我們需要特別注意指令前面要先加上視窗號碼,這樣Bloomberg才知道要用哪一個視窗執行,視窗代碼的格式為 <blp-視窗代碼>,雖然畫面上的視窗代號從1開始(1~4),但DDE的視窗代號是從0開始算(0~3),所以若是要送DES指令給第一個視窗,內容為 <blp-0>DES<GO>,在程式中透過GetDDEWindowNum() 取得正確的視窗代碼編號,再串上 指令(commandText),將指令傳送給Bloombeg,Bloomberg 會依據指定的視窗執行指令。

接下來我們增加一個畫面測試我們寫的功能,在專案新增Forms Folder,再新增一個Form,名稱為 frmDDE,畫面加上Window Num 的ComboBox名稱為 cboWindowNum,一個DDE Command 的 TextBox名稱為txtCommand,一個Button名稱為 btnExecute,最後加上顯示Result的 TextBox,名稱為txtMessage,如下圖

測試的程式碼如下:

public partial class frmDDE : Form
{
  public frmDDE()
  {
    InitializeComponent();
  }

  private void frmDDE_Load(object sender, EventArgs e)
  {
    ComboboxItem[] items = new ComboboxItem[]
    {
	  new ComboboxItem("1", "1"),
	  new ComboboxItem("2", "2"),
	  new ComboboxItem("3", "3"),
	  new ComboboxItem("4", "4"),
	};

	cboWindowNum.Items.Clear();
	cboWindowNum.Items.AddRange(items);

	//Window Num default "1"
	ComboboxItem selectItem = cboWindowNum.Items.Cast<ComboboxItem>().SingleOrDefault(x => x.Value.Equals("1"));
	cboWindowNum.SelectedItem = selectItem;
  }

  private void btnExecute_Click(object sender, EventArgs e)
  {
    using (BloombergDDEBase bloombergDDE = new BloombergDDEBase())
    {
      int windowNum = int.Parse(cboWindowNum.Text);
      LogPrint("Execute Command:" + txtCommand.Text);
      bloombergDDE.DDEInputCommand(windowNum, txtCommand.Text);
    }
  }

  private void LogPrint(string msg)
  {
	txtMessage.AppendText(msg);
	txtMessage.AppendText(Environment.NewLine);
  }
}

在frmDDE_Load中,將Winow Num ComboBox 增加1、2、3、4項目,用來選擇要將指令送到Bloomberg 的哪一個視窗,btnExecute_Click產生BloombergDDEBase物件後,執行 DDEInputCommand將畫面輸入的 DDE指令傳送至指定的Bloomberg視窗。

執行程式按下 Execute 按鈕,會看到Bloomberg 視窗會顯示 US594918BT09 這檔債券的基本資料。