2016年5月29日 星期日

程式交易系統(ACTrader)

這個交易系統我執行了差不多四、五年了,一直沒有釋出,只有幾個朋友在玩,因為早期的版本不完善、不容易上手,直到最近感覺各方面似乎都還挺不錯的,才有了釋出的想法。



其實我認知到有程式交易時,還沒聽過MC、AB、MT等知名交易軟體,只是一股腦的想怎麼實現整個交易過程,之後知道這些軟體時,早已經沉醉在寫程式的苦海中了,頭都洗一半了...。所以這套交易系統的規劃算是個人經驗的累積,包含資金控管、績效回測、滑價模擬、限價模擬、轉倉等等,再整合即時報價、盤後回補與下單API做到一條龍的程式交易系統,不需要再安裝第三方軟體即可運作(當然券商的API等還是需要的)。

先看看圖形介面可供設定的選項,對系統有初步認識後,再看交易策略腳本怎麼寫吧。


選單畫面
首先是選擇策略



整體設定 - 資控
點進"中控"可以看到...

第一次看到這個畫面會覺得有些混亂,解說一下。最上方看到[整體策略]跟[周K突破],分別點選後都會看到不同的選單,[整體策略]是針對群體的設定,其他例如[周K突破]是針對個別策略的設定。以這張圖來說,看到的是[整體策略]的設定(因為[整體策略]是以紅字顯示),整個看到的是[整體策略]>>[設定]>>[資控]

記錄檔:實單交易時須給定紀錄名稱,並選定紀錄方式到"不重置"。
執行模式:實單交易時須設定成"實單"。
資控:整體資控主要是設定本金與盈餘的分配比例。


整體設定 - 商品
點進"中控"可以看到...

這些是預設的可操作商品,設計上主要是針對期貨,選擇權也可以下,只有"台股"是不能下實單的,當然日後也是可以擴充的。策略中也可以設定成混和操作的方式。


整體設定 - 查價


當策略分析的商品與實際下單商品不同時就會有查價的需求,通常不用理會,只有在交易"非熱門合約"時需要設定成"以商品合約報價"。

交易撮合延遲可以用來模擬滑價的情形,這段延遲就相當於下單到交易所撮合成交的時間。


整體設定 - 追蹤


可以在特定的時間點暫停腳本,在策略開發期間可以用來檢視每個信號的合理性,也有助於類似覆盤的型態觀察。


整體設定 - 報價群


這裡可以看到所有策略執行需要的報價者,每一個都相當於一個副腳本執行核心(ScriptCore/InnerCore),負責提供報價、指標等數據供策略參考。


個別策略設定 - 策略設定
點選個別策略後可以看到...

這裡邊的設定可以減少開發策略腳本的困擾,自動平倉、轉倉等,減少腳本需要處理的事務。


個別策略設定 - 風險控制


主要是準備金的設定,與交易量的動態調控。


個別策略設定 - 信號規則


主要是抑制信號量,也可以直接在策略腳本中控制,都行。


個別策略設定 - 委託


實單交易時委託下單機構須設定為"康和期貨",這也是ACTrader唯一支援的期貨商,可以再擴充其他家,但暫時沒有需求與必要性,系統還算穩定。


個別策略設定 - 動作


這部分是用來手動干預信號或部位用的,畢竟有時還是會"出槌",像是報價斷線、下單失敗等,這麼多年還是有遇過幾次。


外掛 - 下單API


一樣只支援康和期貨。帳號密碼輸入完記得按下[Enter]鍵,再測試登入,確定沒問題後再勾"自動登入"。
芭樂單的測試會委託一個不可能成交的價位,只要券商軟體有看到委託,即算是有成功。


---

至此,加上先前介紹過的即時報價外掛,與程式交易相關的畫面大概都看完了。這套系統現在最大的限制就是只能下"康和期貨",因為從幼幼一直用到現在,穩定度還可以。

---

系統概述
在講策略怎麼寫前,容我先簡單陳述一下ACTrader的架構。整個系統有三個主要類別:

1.) ACTradeCenter : 如其名,它就是系統的中控,負責協調各個部分,也是MyScript(主腳本)必須繼承的對象。但這個部分已經有一個固定的腳本叫"策略集",會替開發者搜尋"library/策略集"下的所有策略,再透過圖形介面點選即可已加入策略。

2.) ACQuoter : 報價者。負責提供報價、指標等數據供交易策略參考,本身是以InnerCore(副腳本)的方式存在。

3.) ACTrader : 交易(策略)者,相當於交易策略。ACTradeCenter會在適合的時間點讓交易策略執行。


對策略開發者而言,要知道一個ACTrader(交易者)一定要配一個ACQuoter(報價者),之後衍生出另一種整合ACQuoter與ACTrader的類別,叫ACTactic,本身是一個ACQuoter,開發者需在其類別內建立一個ACTrader,即ACTrader宣告在ACQuoter內,也是現在最常用的方式。

ACQuoter的部分其實就相當於一個繼承了CustomCore的MyScript,照樣像以前一樣建立需要的指標即可。而交易動作的部分則集中在ACTrader上,為因應期貨、選擇權的操作屬性,又做了一個叫TWFOTrader的類別來繼承ACTrader,這個類別中附加了平倉的方式與時間,還可以選定交易商品、模式等,減少開發者的工作,若有不足時,也可以改寫另一個適合的類別,這就是物件導向繼承的好處。

策略範例
所以現在我們可以看一下策略要怎麼寫了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class BREAK_WEEK extends ACTactic
{
 static String nickname = "周K突破";

 //指標宣告(程式碼與參數從UI導出)
 MA ma = addIdct("K線", "均線", new MA("N[0]=100.0&_color[0]=4291020916&_paint_width[0]=2.0&_cut_daily[0]=false")); 
 TIMEFRAME week = addIdct("K線", "周K", new TIMEFRAME("period=5&validsize=10&_syncz[1]=true&_show[1]=true&_syncz_sft[1]=1.0&_syncz[2]=true&_syncz_sft[2]=1.0&_show[2]=true&_paint_width[2]=2.0&_color[2]=4278216345&_color[1]=4294927872&_paint_width[1]=2.0&_cut_daily[1]=true&_cut_daily[2]=true")); 

 public BREAK_WEEK()
 {
  //給定預設值,不給也可以,之後再透過UI修改
  CFG_PERIOD_N = 15;
  CFG_PERIOD_TYPE = PERIOD_MIN;
 }

 class MyTrader extends TWFOTrader
 {
  public MyTrader()
  {
   //給定預設值,不給也可以,之後再透過UI修改
   CFG_BAR_SIGCNT = 1;
   CFG_DAY_SIGCNT = 1;
  }

  //交易策動
  public void trader_trade()
  {
   //確保能參考到需要的資料
   if (ma.isNullRef(1) || week.high.isNullRef(5))
    return;

   double week3HL = ???;

   if (getSig() != D.STYPE_LONG && ???)
   {
    if (week3HL < ??? && ???)
     setSig(D.STYPE_LONG); //建立多方信號
    else
     setSig(D.STYPE_CLS); //建立平倉信號
   }

   if (getSig() != D.STYPE_SHORT && ???)
   {
    if (week3HL < ??? && ???)
     setSig(D.STYPE_SHORT); //建立空方信號
    else
     setSig(D.STYPE_CLS); //建立平倉信號
   }
  }
 }
}


這裡面可以看到兩個類別(class)的宣告,分別繼承(extends)了ACTactic、TWFOTrader,其中ACTactic相當於ACQuoter,TWFOTrader相當於ACTrader,也就是一個"交易者"包在一個"報價者"裡面的架構。

寫好後只需把這個腳本放在"library/策略集"下即可,之後再將圖格中腳本切換到"策略集",就可以看到寫好的策略選項。

---

接著大概看一下需要認識的API有哪些。對於一般的投資人,其實透過方才的範例就已經學到了足夠的API可以編寫策略了(即getSig與setSig)。

API - 中控(ACTradeCenter)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public abstract class ACTradeCenter extends ScriptCore
{
 //當中控準備完成會呼叫這個函數,通常會在此時建立策略
 public abstract void center_ready();

 //加入一個ACTactic
 public void addTactic(String ID, ACTactic tactic)

 //寄信(gmail). 寄收件人由UI設定. RTQOnly為true表示只有在盤中寄送.
 public void mailNotice(boolean RTQOnly, String title, String content)

 //暫停執行. 偵測交易狀況用. 繼續執行的按鈕在除錯視窗中.
 public void pause(ACTrader trader)

 //取得某ACTrader的初始資本
 public double getInitPrincipal(ACTrader trader)

 //取得某ACTrader的可再投資資本
 public double getReinvest(ACTrader trader)

 //取得某ACTrader的可投資資本 (即InitPrincipal+Reinvest)
 public double getInvestableFund(ACTrader trader)
}

在ACTrader中可以用"center"這個變數名稱對應到ACTradeCenter。

還有些跟選股回測相關的沒列出來,手上也沒有好的範例,暫時就別徒增困擾了。


API - 報價者(ACQuoter)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public class ACQuoter extends CustomCore implements ParamIns
{
 //指定報價符號
 public String CFG_SYMBOL = "";

 //指定結算商品
 public String CFG_SELLTE_COMM = "";

 //指定K線週期N
 public int CFG_PERIOD_N = 10;

 //指定K線週期
 public int CFG_PERIOD_TYPE = PERIOD_MIN;

 //指定報價刻度
 public int CFG_PRECISE_TYPE = PERIOD_AUTO;

 //指定K棒保留數量 (避免多策略時造成記憶體不足)
 public int CFG_VALID_KSIZE = 10000;

//---

 //報價者ID
 public String QID = null;

 //中控
 public ACTradeCenter center;

 //K線圖層
 Layer lay_k = null;

 //信號圖層
 Layer lay_sig = null;

//---

 //報價init()
 public void quoter_init() {}

 //報價run()
 public void quoter_run() {}

 //取得報價對應合約的剩餘天數
 public int getValidDays()

 //檢查時間是否已過合約收盤時間-backward_time(ms)
 public boolean timesup(long backward_time) //ms

 //檢查時間是否穿越hhmmss
 public boolean timecross(int hhmmss)

 //檢查時間是否在hhmmss1與hhmmss2之間
 public boolean timeinside(int hhmmss1, int hhmmss2)
}

有初始值設定(CFG_開頭)的部分,以及getValidDays()用來取得距離結算的天數。如果還有額外的指標或變數要運算可以寫在quoter_run()中。

API - 交易者(ACTrader)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
public abstract class ACTrader extends ScriptBasic implements CorePartner, ParamIns
{
//---信號限制設定主要是基於安全性 更細部的動作控制還是要寫到策略中

 //設定一日的信號數量
 public int CFG_DAY_SIGCNT = 99;
 //設定一根K棒的信號數量
 public int CFG_BAR_SIGCNT = 1;

//---

 //交易者ID
 public String TID;

 //中控
 public ACTradeCenter center = null;

 //監視的報價者
 public ACQuoter quoter = null;

 //統計
 public STATS stats = null;

 //當下信號
 public RecSig curr_sig = null;

//---(事件類型,供複寫(Override))

 //策略部分.
 public void trader_init(){};
 public void trader_run(){};
 public void trader_eop(int type){};
 public void trader_menu(HtmlInputHelper html){};
 //策略處理.
 public abstract void trader_trade();

 //信號部分.
 public void sighd_init(){};
 public void sighd_run(){};
 public void sighd_eop(int type){};
 public boolean sighd_trade(){return true;};
 public void sighd_menu(HtmlInputHelper html){};
 //信號處理 (產生標的物及目標口數)
 public abstract void sighd_sig(final int stype);

//---

 //設定信號
 public boolean setSig(int stype) {return setSig(stype, null);};
 public boolean setSig(int stype, String desc)

 //取得當下信號
 public int getSig()

//---

 //取得交易合約
 public Contract getContract(String comm_key, int cont_shift)

 //取得選擇權交易合約
 public Contract getContract(String comm_key, int cont_shift, int cp, double price, int p_shift)

//---

 //信號發生的t點
 public int sigT = -1;

 //信號清除(平倉)的t點
 public int clsT = -1;

 //信號發生或清除的t點
 public int actT = -1;
}

大致比較有機會用上的有這些。在前面的範例中我們只用到了trader_trade()、getSig()、setSig()就足以完成一個策略,其他像是交易商品、結算、準備金、口數控制等都可以透過圖形介面修改,除非要做比較特別的交易方式,不然這樣差不多夠了。


擴充類別

有兩個功能是可以擴充的,分別是風險控制(交易量調控、RiskCtrl)與停損停利(StopCtrl),只要分別繼承(extends)這兩個類別放在程式碼中,就可以在UI選單中找到,若放在library中就可以讓所有策略共同使用這些功能,不用一直重寫,也方便嘗試不同搭配。詳細的寫法在library/ACTrader中都可以找到範例(搜尋關鍵字類似"extends RiskCtrl")。


總結

本著童叟無欺的理念,最後還是要很客觀的評價自己的東西。如果你是一個放眼世界的投資人,AC不會是一個好選擇,甚至不會是一個選項,這是可以理解的,畢竟小弟隻身一人、沒有團隊支援、沒有財經背景,也是盡了很大的努力才只有這樣的進度。

---

2017-05-07更新

花了幾個月的時間熟悉了一下Multicharts,很快就進入狀況了,報價與下單也都整合的不錯,我的程式交易平台已經完全轉移到MC上了,也就是說我已經放棄AC程式交易的部分了,以一個程式開發者而言我感到有些遺憾,但以一個交易者而言我感覺得到了解脫,終於能夠認真地從事交易了.


沒有留言:

張貼留言

本人僅以個人知識經驗分享,多所無知,難免有錯,還請見諒。