前面兩篇文章所描述的狀態(tài)機,思維的基礎(chǔ)是:對一個訂單施加動作,將委托回報或成交回報歸納為若干對此訂單施加動作后的回饋,在等待動作回饋時設(shè)置此訂單狀態(tài)。因此,我們跟蹤狀態(tài)的對象是一個訂單。也就是當(dāng)這個訂單從委托開始,對可能發(fā)生的各種情況加以跟蹤和控制。這樣的話,我們在各個狀態(tài)就只能對一個訂單的狀態(tài)加以維護,然后根據(jù)這一個訂單的狀態(tài)變化用程序控制狀態(tài)的流轉(zhuǎn)。在交易信號出現(xiàn)頻率比較低的時候,我們可以處理完一個訂單,比如開倉報單之后,再等待其平倉信號的出現(xiàn),然后做平倉報單的操作。然而,在交易信號出現(xiàn)頻率比較高的情況下,往往在一個訂單還沒有處理完的時候,又需要下新的訂單,這時候按照這種思路的狀態(tài)機就難以處理了。此時,狀態(tài)機就不能嚴(yán)格的將開平各個狀態(tài)分開,比如,在單合約狀態(tài)機的示例中,當(dāng)訂單處于可平狀態(tài)時又出現(xiàn)了開倉信號,程序會丟失掉這個信號。
那么,在信號出現(xiàn)頻率較高的時候,單合約的狀態(tài)機應(yīng)該是這樣的:
也就是說,處于“可交易”狀態(tài)時,不論是出現(xiàn)開倉條件開倉,平倉條件平倉,還是超時撤單的情況,狀態(tài)都流轉(zhuǎn)到自己,以便接收新的信號做出相應(yīng)動作。
不過,在這樣的狀態(tài)機下面,同一個狀態(tài)要處理的邏輯就相當(dāng)多。比如,平倉信號出現(xiàn)時,到底有沒有持倉可平?到底是開倉報單正在等待成交還是已經(jīng)撤單?不同的情況,程序的控制完全不一樣;沒有持倉,則平倉動作要忽略;開倉報單在等待成交,則要先撤單,再平倉;開倉報單已經(jīng)撤單且有成交或者完全成交的情況,則直接平倉。更重要的是,當(dāng)前一個訂單還沒有撤單或者完全成交的時候,新的報單必須要根據(jù)前一個報單當(dāng)時的具體情況,才能決定其操作,所以還需要維護前一個報單的狀態(tài)。所有的程序控制都寫到這個狀態(tài)里,可讀性會變得相當(dāng)差,并且極易出錯。
為了解決上述問題,可以將這部分訂單處理的工作抽離出來,把所有的開倉平倉撤單的工作,以及處理的邏輯單獨用一個線程來處理,這就是所謂的訂單管理線程;這樣,和策略管理線程分離開來,使策略管理線程的著眼點在合約上,讓其狀態(tài)機僅僅按照對合約持倉操作的業(yè)務(wù)邏輯來處理,而不去管業(yè)務(wù)操作下訂單的具體實現(xiàn)。如下圖:
策略管理線程按照業(yè)務(wù)邏輯給訂單管理線程兩個參數(shù),一個是目標(biāo)倉位,一個是達到這個目標(biāo)倉位所需要的時間;訂單管理線程給策略管理線程兩個回饋,一個是合約的持倉情況,一個是操作完結(jié)的提示,操作完結(jié)分兩種情況:一是在操作時間限制內(nèi)完成了操作,二是超過了操作時間限制而撤銷了操作。而至于要怎么完成業(yè)務(wù)操作,完全交給訂單管理線程去做。這樣的話,高頻交易下的合約狀態(tài)機的代碼控制就變得很簡單。