2014年8月3日

股市自動交易系統(半完成品) - JavaATS程式架構 - DataManager

這篇來描述另一個簡單的部份,Data Manager,取得歷史資料的元件,
在JavaATS架構圖如下:
這裡的Data Manager,主要就是從SQL Server裡面把資料撈出來,
目前的Data Manager只有實做撈Candle(K線資料),
每筆資料包含:

  • ID (代號)
  • Name (名稱)
  • Date (日期時間)
  • Open (開盤價)
  • Close (收盤價)
  • High (最高價)
  • Low (最低價)
  • Volume (成交價)

Data Manager程式碼結構:
Data Manager結構非常簡單,只有1個建構子+2個method,如下:

  • 建構子:載入JDBC驅動程式,設定SQL Server的資訊(IP、Port、DB Name、Account、Password)
  • getCandle:取出特定市場、代號的歷史資料(所有時間,從最早到最新)
  • setCandle:傳入SQL Code,直接寫入或更新資料到SQL Server

Candle與CANDLES變數:
這裡唯一需要解釋的是,Candle和CANDLES這2個變數,和它的命名原因。

  • Candle:就是K線資料,但它代表1個時間的K線資料
  • CANDLES:表示一整串Candle,它的原型是個Candle的陣列

大小寫命名原因:
這和之後會提到的StockAPI有關連,
為了讓StockAPI便於使用和區別,
我在StockAPI內,統一使用「大寫+底線」的method名稱,
例如:
取得歷史資料的API叫GET_HISTORY
取得Quote的API叫GET_QUOTE

一整串的Candle因為很常被StockAPI使用,因此它的命名變為大寫。

2014年8月2日

股市自動交易系統(半完成品) - JavaATS程式架構 - Config Manager

這篇要來描述Config Manager的部份,在JavaATS的架構圖如下藍色框框部份:
ConfigManager是屬於比較單純的部份,
它主要功能就是XML的Parser,負責將XML資訊讀出成變數。

ConfigManager功能與呼叫方式:
JavaATS會在一開始時透過ConfigManager載入所有變數,
之後JavaATS所有變數的取得,都是透過ConfigManager。

例如:
xml設定檔檔名為:configs.xml

則在JavaATS一開始時,會呼叫:
CONFIG = new ConfigManager(configs.xml);

之後所有設定都會讀入CONFIG當中。

例如要取得MySQL設定的IP,如下:
String ip = CONFIG.getMySQLIP();

ConfigManager程式結構:
Java的XML Parser有2套,是:

  • DOM XML Parser
  • SAX XML Parser
DOM的優點是程式碼比較容易結構化,缺點是操作比較麻煩,
SAX的優點是,操作單純,但程式碼比較不好結構化。

在寫這部份時,正好就學習SAX XML Parser使用方式,
因此,JavaATS的XML Parser,原則上都是用SAX XML Parser。

SAX XML Parser:
這裡不得不稍微提下Java SAX XML Parser的使用方式,
Java SAX XML Parser程式碼結構大致如下:
File f = new File(configs.xml);
DefaultHandler XMLHandler = new DefaultHandler() {}

SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser saxParser = spf.newSAXParser();
saxParser.parse(f, XMLHandler);
原則上,SAXParser的設計是:

  1. 先建立並初始化SAXParserFactory物件
  2. 從SAXParserFactory取出Parser
  3. 設定Parser的XML檔案和Handler

上述的程式碼結構,就是先建立出XML的File和Parser Handler,
然後按設計,建立並設定到Parser內,就會開始Parse XML了。

Handler的實做包括:
public void startElement(String uri, String localName,String qName, Attributes attributes)
public void endElement(String uri, String localName, String qName)
public void characters(char[] ch, int start, int length)

SAX Parser會從頭一行一行讀XML,
當讀到StartElement時,就會跳入startElement()的Handler function,
要開始讀內容時,就會跳入characters()的Handler function,
當讀到EndElement時,就會跳入endElement()。

例如:
<Config>
HelloWorld
</Config>
當讀到<Config>時,就會跳入startElement(),
在startElement()內,就會取得Config這個標籤名稱是開頭。

當讀到Hello World時,就會跳入characters(),
在characters()內,就可以取得Hello World。

當讀到</Config>時,就會跳入endElement(),
在endElement()內,就會取得Config這個標籤名稱是結尾。

ConfigManager程式碼結構:
ConfigManager程式碼依循SAX設計,
在Handler內,將Config XML的載入透過startElement()、characters()、endElement()分開。

原則上,每個項目的參數,都會包括:

  • 變數Element:用在startElement()時,標記目前要讀取的變數,在endElement()時,標記變數已讀取完畢
  • 變數本身:用在characters()時,實際讀出並紀錄變數

例如:
MySQL的IP資訊

SQLElement:紀錄是否要讀取SQL資訊
MySQLIP:紀錄MySQL的IP

在startElement()時,當標籤是SQL,就將SQLElement設為true,
在characters()時,檢查到SQLElement == true,就讀取標籤內容,並設定到MySQLIP。

程式碼大致如下:
public void startElement()
{
  if(qName.equals("SQLElement"))
    SQLElement = true;
}
public void characters()
{
  if(SQLElement == true)
    MySQLIP = new String(ch, start, length);
}

public void endElement()
{
  if(qName.equals("SQLElement"))
    SQLElement = false;
}