聊聊 C# 實作 Excel 選擇權報價交易系統

前兩個月有位委託人希能協助在 Excel 實現台指期選擇權契約報價暨自動交易決策系統。他說原來已有透過一位獨立開發者利用 Excel VBA 撰寫,但無論如何都無法符合他的需求,甚至連正常執行顯示報價都有問題。

直覺聽來,我是不可能考慮使用 Excel VBA 來實作選擇權報價的,它需要動態處理即時資訊的更新太多也太過頻繁,且實現邏輯可能比想像得還複雜,要能動態處理運算並處理選擇權契約月份與履約價格,這非得使用 OOP 語言來實現會容易許多相對也比較有擴展的彈性。

原來是不打算接受這個委託的,因為要克服相關技術的難點預期應該不少。不過後來想想,反正早有計畫要利用 C#.NET 實現包括報價資料源的連接、當沖策略的設計、自動下單等功能,並直接以 Excel 當使用者介面 (GUI),可以直接利用其簡便的圖形報表呈現所需的結果。

由於幾乎是從無到有,且個人對即時性 (real-time)系統的設計實現並不熟悉,包括從研讀大量相關文件到寫碼實作,整整花了約有一個月 part-time 時間,總算能實現在 Excel 畫面上呈現選擇權履約價的報價表。

Excel 實現選擇權報價

初步實現的功能包括有:

  • 自動判斷每個月星期三的結算日,由此可決定起始的契約月份。
  • 可動態選擇選擇權契約月份。
  • 可任意排序選擇權項目。
  • 可自動判斷與更新台指期近月份報價暨昨日收盤價。
  • 由於委託人只需要連續近三個月的選擇權契約月份,以及台指期昨日收盤價上下約 10% 的履約價格序列,所以相對實作上簡單很多。不過後續的版本我還是會要能達成可動態選擇權五個月的契約月,以及完整的價格序列。但完整的價格序列目前我仍搞不清楚計算的邏輯,參考這裡-期交所選擇權契約規格,近月契約的價格範圍涵蓋為基準指數的上下 15%,但我以此來計算的結果卻又與各券商的價格範圍有差,這條邏輯屆時問問看曾有在券商資訊部門工作過的學員,或乾脆打電話問期交所。

    C#.NET 實現 Excel 邏輯運算處理其實比想像得簡單,反正就是原來 Excel 預設的 VBA 實作,轉成為 C#.NET 的實作而已,差別當然就是物件化的設計與實作。所以當有物件導向 (object-oriented)的觀念就相對更容易上手,甚至當打通 Excel 與 C# 的管道後,以 C#.NET 實現還來得比 VBA 更簡單。

    一個最基本的觀念就是:整個 Excel 工作簿 (Workbook)就是一個完整的物件模型,其內包括工作表 (Worksheet)、Range、Cell 等都是物件,而且它們全都屬於 Presentation-tier (展示層)物件類型,所以我另外會再設計控制型 (Control)的物件與邊界 (Boundary)物件,以符合 MVC (Model-View-Control)基本的分層結構框架。

    Excel MVC 分層結構框架

    預設 Excel 的物件模型會有四個類別:Sheet1, Sheet2, Sheet3 與 ThisWorkbook。前三個其實就是反應預設的工作表1~3,而最後一個則代表是工作簿本身,這四個類別彼此可以使用 Global 共用類別來相互引用 (例如呼叫 Globals.Sheet1.Range)。這裡我是把 ThisWorkbook 當成 Form Controller,由它來控制三個工作表的展現;而個別的工作表只有實作畫面的展示以及接收與觸發事件的邏輯處理。

    所有相關的業務邏輯 (business logic)是由所設計的控制物件來實現的。在這個案例我設計了一顆「處理交易Control」物件,業務邏輯包括「建構OP商品()」、「計算OP契約月份()」、「判斷是否為期指結算日()」、「更新商品資訊()」...等,都絕對從 Excel 抽離出來,交由該控制物件實作或委派給其它物件處理。

    至於報價連線部分,我會設計各種連線類型的 Adapter 邊界物件,例如 DDE_Adapter,專職連接 DDE Server;報價API_Adapter,專職連接各券商所提供的 API 直接連接至券商的報價系統。

    由於委託人尚未申請報價API的權限 (元大券商),所以目前仍僅以 DDE 方式連接 Easywin 交易暨報價系統。參考幾年前我寫的一篇-「C# DDE 用戶端(Client) 的範本(含源碼下載與說明)」。截至目前為止,我使用原來這樣透過 NDDE 連接實作選擇權契約商品有數百個 Item,在效能上仍舊是相當穩定。

    當然,在設計上我還是先保留可以抽離 DDE 連接,改以其它連接 (透過券商專屬 API)方式的彈性,未來的版本即是要能達成可動態抽換 (PnP, Plug-and-Play) 連線Adapter 資料源必要的功能。

    實作的工具當然就是利用 Visual Studio.NET 2010/2012,在 New 專案時選擇的範本為 Office Excel 2010 Workbook 即可自動載入並引用 Excel 物件模型,其餘則是與一般 C# 專案無異,相當簡單。

    UI 方面我並沒有利用 Excel 傳統的儲存格,因為選擇權並無法固定契約商品價格序列。要能動態運算並呈現選擇權商品價格序列,還可以動態切換契約月份,那非 DataGridView 不可。

    VS.NET 2012 實作 Excel

    我以為微軟在 Windows Form UI 這部分最佳的複雜資料型態呈現,DataGridView 可說是絕佳的 UI 物件模型,它的 Data Binding 技術,大幅減輕了程式設計人員需要手動維護 UI 元件與資料源的一致性。

    Excel 內的 DataGridView 元件的 Name space 為「Microsoft.Office.Tools.Excel.Worksheet」,它可以 Binding 包括實體資料庫與 DataSet、List 等物件。原來我 Binding 至 List 集合物件,其內儲存了選擇權各契約價的物件;但 DataGridView 卻無法自動更新 (網路上有許多文章討論如何解決,但仍嫌麻煩),後來改為使用 DataTable,以關聯式的資料物件儲存於記憶體,而後報價資料有任一欄位變更而更新了 DataTable,UI 端的 DataGridView 即會自動反應更新 (Refresh),相當方便。

    實作上我花最多時間是關於事件的處理 (event-handling),因為要能符合物件的結構設計框架,也就是 Adpater 不得反向呼叫 Controller、Controller 不得引用 Form Controller (ThisWorkBook);而當 DDE Adpater 接收更新的資料後,必須通知 (notify)向它註冊的 Subscriber (也就是 Controller),然後 Controller 處理或轉型後也要再通知 UI Form Controller 處理更新事宜。

    在細節上就要能建立傳遞的商品項目 (也就是商品代碼)與對應的物件以及對應的 DataTable,簡單的說就是要能實作一個資料字典 (Dictionary),來對應商品代碼與物件、DataTable 等的動態關係。DataTable 是要展示至 Excel 的報價 UI,而物件則是未來為了作策略交易計算所誕生的,各自有不同的職掌。

    細節上的處理的確相當繁瑣,還包括了對商品代碼的 parsing 與 mapping 等解析與運算設計,並且由於是即時性系統,多少要能兼顧到效能的考量。

    當然要完成委託不會只有報價部分而已,最重要的還是策略邏輯的實作以及最終能達成自動化的下單需求。不過目前可說是把技術難點最困難的部分給克服了,再來反而較不會是技術的問題,而是邏輯實現的問題,以及連接券商下單系統的 API 規格解讀問題。

    ※ 延伸參考
     o 開放「Excel 即時報價暨分析圖表」小型程式交易委製開發專案