隨著開始使用XS寫交易策略的朋友們愈來愈多,我們愈來愈常被求救,問題看多了,歸納整理後,我寫了一個撰寫交易策略的SOP,我認為在撰寫交易腳本時,有四大步驟,嚴謹且按步就班地作好每個步驟,應該可以協助我們完成交易策略的撰寫。
這四個步驟如下圖
茲分項說明之
一,準備數據
程式交易語法跟其他如C++,Java等不同之處,是在於它的目標很明確~透過大量金融數據的運算,作成交易決策,所以在一個程式交易腳本中,最基本的課題是: “要拿那些金融數據進來運算?”
每個腳本,都像一道食譜,每個食譜,都會要我們先準備食材,腳本的食材,就是我們要拿下去運算的每個元素,在XS的腳本中,這些要拿來加減乘除作運算的元素,可以歸類為以下幾種
1. 即時行情的數據。包括單量,當日漲幅,內盤量,外盤量,五檔委買賣的價與委託量等等,我們可以用 Getquote的語法把它們拉出來使用。
2. 盤後數據。包括法人進出,資券變化,主力進出等等數據,我們用Getfield的語法把這些欄位拿到腳本中來使用
3. 回傳值。開高低收成交量等語法中最基本的元素,在以K棒為基礎的架構裡,我們可以用Close[n]之類的語法,把K棒中 的每一個被存下來的值拿來運算。
4. 參數。為了更改參數方便而由使用者以INPUT的語法所設定的參數,也是可以被拿來腳本中作運算。
5. 變數。為了運算方便,由使用者自行宣告的變數,也是腳本中常見的元素。
6. 常數。有的時候,就是會運用到簡單的阿拉伯數字,或是True及false這兩個布林值,這些都是腳本運算中常用的元素。當我們要要撰寫一個腳本時,就像食譜要先準備的食材一樣,我們得先決定要用上述六大類裡的那些元素,這個決定的工作,就像是煮一道菜之前,先把相關的食材從冰箱裡取出來。
決定好之後,接下來要做的是事情有兩個
第一個是宣告: 我們先透過宣告的方式,把要用的變數及參數先準備好,我們為它們取名字,設初始值。
第二個是指定: 然後接下來我們用getquote及getfield的語法,把盤後資料及盤中資料指定到特定的某個變數
二,建構演算
以上的這兩個步驟,就好像是煮菜之前的備料工作。備完料,接下來就是建構演算的機制,在這當中,若是有需要,會使用到系統或自訂的 函數。 大家可以透過先前學會的流程控,以及各種函數,透過數學及邏輯運算,完成各種運算。
這部份主要是看個人的功力,只能多看多寫,多看別人寫過的好語法。
三,設定輸出條件
接下來,就是建立輸出條件,我們用if ……..then ret=1; 來指定策略雷達的觸發條件,以及選股的符合條件,用if………then plot1…;來輸出自訂指標。
我與個例子來說明以上的流程
我們希望電腦在個股符合下列三個條件時通知我們,
- 十日法人買超的移動平均超過1000張
- 當日外盤量佔成交量超過五成
- 當日股價比前一日上漲
那麼我們可以寫下一個腳本如下:
各位可以看到,我們依以下的步驟在完成一個警示腳本
步驟一: 宣告參數
步驟二: 宣告變數
步驟三: 取得盤後資料
步驟四: 取得即時數據
步驟五: 建構運算關係
步驟六: 設立觸發,畫指標或確認 函數的敘述式
當然在實作上,步驟一到步驟五的任何一項 ,都可能因為沒有用到相關數據而被省略,最簡單的警示腳本如if close=high then ret=1;就只有步驟六而已。
但如果大家記得這六個基本的步驟,應該可以很快的把各式各樣的數據,同步放在一個警示腳本中來使用。
四,編譯與勘誤
接下來的編譯及勘誤,是另一個重點,很多朋友就算是提供了中文的勘誤,還是無法自行找出程式碼的問題之所在,所以我把大家常見的程式上的疏誤,以及在勘誤時系統會出現的訊息做了一個對照表如下,供大家參考。
XS的勘誤方式,跟其他的IDE類似,在使用者按下編譯按鈕之後,如果程式有Bug,會在訊息視窗中,以表格的方式來呈現錯誤的地方,其呈現方式如下:
物件名稱 | 行號 | 字元 | 錯誤描述 |
呈現腳本的名稱 | 顯示錯誤的敘述在第幾行 | 錯誤的地方是從該行的第幾個字元開始 | 表達錯誤的可能原因,俾使用者正確地找到錯誤。 |
根據我自己使用的經驗,User通常會出現的錯誤,以及XS編輯器對應會出現的勘誤訊息,大致有以下幾類。
文字上的小失誤
錯誤描述 | 原因說明及備註 |
未知的關鍵字 “xxx”,請檢查是否有宣告此變數或是拼字是否有誤。 | 可能是自己宣告的參數或變數的名稱打字時打錯了,造成電腦無法理解這個字代表的意思 |
需要輸入更多參數。 | 通常是像plot1之類的忘了把裡頭的參數輸進去,如果是函數忘了輸入正確的參數個數,系統會直接呈現”需要輸入x個參數” |
需要輸入 x ~ y 個參數。 | 輸入的參數比系統要求的多時會出現這個message |
在 “xxxxxx” 之前可能少了”;”, “DOWNTO”, “TO”, “OR”, “XOR”, “AND”, “=”, “<>”, “<“, “>”, “<=”, “>=”, “Crosses Above”, “Crosses Over”, “Crosses Below”, “Crosses Under”, “+”, “-“, “*”, “/” | 最有可能的是前一行忘了打分號。 |
編譯器看到了一個無法辨認的字 “x”,請檢查這個字有沒有寫錯。 | 這種情況通常是輸入了之前沒有宣告過的文字格式內容 |
流程的錯誤
錯誤描述 | 原因說明及備註 |
for 迴圈的變數型態應為數值。 | for的用法為for 某變數=xx to xxxxx及xxx必須都是數值 |
「IF/Once/While/Repeat」後面需要一個真偽值或是真偽值的判斷式。 | 這些流程的後面必須是一個布林值的判斷式,不能是一個結果是特定數值的運算式 |
函數的錯誤使用
錯誤描述 | 原因說明及備註 |
需要輸入x個參數 | 這代表使用這函數所需要輸入的參數的個數與user實際輸入的參數並不相符,可能是漏打或是多打了某個參數。 |
函數 xxxxx:第 x 個參數應該是 Numeric(string)。 | 這代表使用者輸入的函數參數格式錯了,該是數字的地方使用了文字,或是該是文字的地方使用了數字。 |
函數宣告的輸入型態有誤,應該是 Numeric,NumericSimple,NumeircSeries, String,StringSimple,StringSeries,TrueFalse,TrueFalseSimple,TrueFalseSeries。 | 在自訂函數宣告參數時必須宣告資料的型態而不是直接使用初始值 |
函數 xxxxx:第 x 個參數應該是 Numeric 。 | 函數裡每一個參數的格式(type)必須是對的,不能把文字放到該填數值的函數去 |
參數的數值不可以在函數中被修改,如果有需修改參數值,請將參數型態改為 NumericRef(數值)或是 NumericArray(陣列)。 | 在函數中的參數,它的數值是不能在宣告後直接被賦予特定值的,例如不能寫input:abc(numeric);abc=1; |
用到不該用的欄位
錯誤描述 | 原因說明及備註 |
在「警示」腳本中無法使用「plot」 | 在警示類的腳本中不能使用plot |
此欄位無法使用 [ ](無法索引前期值)。 | 例如在getquote的欄位裡使用前期值的語法 |
在「指標」腳本中無法使用「xxxxx」。 | 在指標類型的腳本中不能使用getquote的欄位 |
數值與布林值使用上的混淆
錯誤描述 | 原因說明及備註 |
“=” 左右兩邊的型態不同。 | 數值是無法等於布林值的,例如不能寫value1=true; 因為value1是數值變數,true是布林值,應該要寫成condition1=true; |
“+” 左右兩邊的型態不同。 | 數值跟布林值是無法相加的 |
“AND” 與左右兩邊的型態不同。 | and的兩邊必須都是布林值的敘述,不能有數值 |
“-” 與右邊的型態不同 | 減號的兩邊都必須是數值 |
“not” 與右邊的型態不同。 | not的兩邊都必須是布林值 |
宣告參數時容易發生的失誤
錯誤描述 | 原因說明及備註 |
在指標跟警示裡面不用型態的方式,請修正。 | 在指標跟警示裡,使用input宣告參數時直接用初始值,而不是宣告資料型態。 |
變數使用上的錯誤
錯誤描述 | 原因說明及備註 |
變數 “xxx” 為系統保留文字,請更改變數名稱。 | 宣告變數時用到了其他關鍵字, 或是重覆宣告了同名字的變數 |
變數 “xxx” 沒有宣告,請用 Vars: 的方式宣告,冒號後面是變數名稱再用括號填入預設值。例如: Vars:varA(100); 如果要宣告陣列請用 Arrays: 冒號後面是名稱再用 [] 設定維度與大小,括號填入預設值。例如 Arrays:arr1[10](0);。 | 直接使用了某個電腦看不懂的英文字詞,電腦會提醒把這個字詞宣告成變數後再來使用 |
xxxx不是陣列,不能在後面加 [ ],請把 [ ] 與裡面的數字移除掉。 | 在使用變數前一期值時要小心,不要直接指定特定一期值為某常數,因為這是陣列才會有的行為,例如可以寫value1=value1[1]+value1[2];但不能寫value1[1]=5; |
陣列使用上出現的疏誤
錯誤描述 | 原因說明及備註 |
變數宣告為 Array 但沒有宣告陣列維度,例:Array:arr[X](numericarray); | 使用陣列時只記得宣告是陣列卻忘了宣告陣列的維度 |
有宣告陣列維度但變數並不是宣告為 Array。 | 宣告了陣列的參數,但忘了宣告陣列格式的變數,兩邊對不起來 |
陣列參照不正確。 | 宣告陣列後,必須按陣列的格式來assign值或變數,而不能像非陣列的assign方式,例如宣告了一個陣列如下:array:arr1[5](0);arr1[1]=1; 這樣寫是可以的,但不能寫成
arr1=1; 因為在陣列中的每一個變數都是獨立的,不能透過這種語法想要一次assign所有陣列的值都是1 同樣的,也不能寫成 value1=arr1; 因為左邊是一個變數,右邊是一個陣列。 |
陣列(Array)宣告不支援超過9維的維度。 | 這種情況代表使用者宣告的陣列維度超過九個,這超出了系統所能提供的上限。 |
當編譯後出現錯誤訊息後,即可根據上面表格的說明,找出錯誤的原因並且加上修正,如此一來可以縮短程式開發的速度,並且讓程式可以忠實呈現使用者的想法。