策略的框架和基本語法
第一個策略範例: MovAvg2Line Cross LE,MovAvg2Line Cross LE是兩條均線黃金交叉買進策略,透過這個簡單的策略範例快速了解腳本的框架和基本語法: 宣告、計算規則、進出場邏輯判斷、買進或賣出。
打開PowerLanguage Editor->檔案->開啟檔案->公式類型->訊號(打勾)->MovAvg2Line Cross LE。

下面是MovAvg2Line Cross LE開啟後的程式碼
inputs: Price( Close ), FastLength( 9 ), SlowLength( 18 ) ;
variables: var0( 0 ), var1( 0 ) ;
var0 = AverageFC( Price, FastLength ) ;
var1 = AverageFC( Price, SlowLength ) ;
condition1 = CurrentBar > 1 and var0 crosses over var1 ;
if condition1 then
Buy ( "MA2CrossLE" ) next bar at market ;
I. 宣告
參數(Inputs) 和變數(Variables)
參數(input)和變數 (variable)可以想像成是一個容器(Ex: 瓶子),容器內儲存需要的數值(Ex: 5公升)。
但是在使用這個容器之前,需要先宣告,宣告會告訴編譯器要儲存的數值的型別,編譯器會根據型別分配需要的記憶體大小。
因此,參數和變數分成兩個階段:
第一個階段是宣告,宣告參數或變數的名稱,給予預設值或初始值,同時定義他們的型別,型別可以是數值(Numerical)、字串(String)、真假值(TrueFalse)。
第二個階段是使用階段,在程式碼中使用參數或變數的名稱,當程式執行到名稱時,就會去使用儲存的值。
參數(Inputs)宣告的語法:
inputs: InputName1(DefaultValue1), InputName2(DefaultValue2), etc;
inputs
: 表示宣告參數。InputName
: 參數的名稱,名稱不區分大小寫,不能是數字或句點( . )開頭。DefaultValue
: 參數的預設值,預設值決定參數的型別,型別可以是數值(Numerical)、字串(String)、真假值(TrueFalse)。
註: 參數宣告的結束要加分號(;
),沒有加會編譯錯誤。
你可以從MultiCharts設定訊號腳本和指標腳本參數的預設值,如果沒有從MultiCharts設定新的預設值,參數的預設值會使用腳本中定義的DefaultValue
。
從MultiCharts設定的新預設值直接執行就能套用,不需要重新編譯。
參數值只能透過一開始的預設值設定和改變,設定後,在腳本中無法再透過程式碼更改參數值。
MovAvg2Line Cross LE,第1行:
inputs: Price( Close ), FastLength( 9 ), SlowLength( 18 ) ;
這一行的意思就是:
宣告參數(inputs),參數名稱分別叫做 ,Price且預設值是Close(收盤價)、FastLength且預設值是9、SlowLength且預設值是18。
下圖是在MultiCharts->設定->訊號-> MovAvg2Line Cross LE ->設定可以看到,參數名稱Price、FastLength、SlowLength,就是在腳本中inputs宣告的名稱,因為沒有修改數值設定,所以都是使用宣告中的預設值Close、9、18。

變數(Variables)的宣告語法:
variables: VariableName1(InitialValue1), VariableName2(InitialValue2),etc;
variables
: 表示宣告變數。VariableName
– 變數的名稱,名稱可以是字母、底線、數字、句點( . )組成,名稱英文不分大小寫。名稱不可以是數字或句點( . )起頭。InitialValue
– 變數的初始值,初始值決定變數的型別,型別可以是數值(numerical)、字串(string)和真假值(TrueFalse)。
註: 變數宣告的結束要加分號(;
),沒有加會編譯錯誤。
您不能從 MultiCharts 設定變數的初始值。
變數值透過初始值設定,設定後,可以在腳本中再透過程式碼更改變數值(指派其他的值)。
MovAvg2Line Cross LE,第2行:
variables: var0( 0 ), var1( 0 ) ;
這一行的意思就是:
宣告變數(variables),變數名稱分別叫做,var0並給予初始值是0、var1並給予初始值是0。
保留字(Reserved Word)
保留字是在PowerLanguage中,具有特殊意義或是本身是語法的單字,他們不能被拿來當作參數或變數的名稱。
宣告用的inputs、variables本身是語法的字,因此是保留字。
在MovAvg2Line Cross LE,第一行,參數宣告中出現的Close也是保留字,他代表的意思是收盤價,其他類似的保留字還有Open(開盤價)、High(最高價)、Low(最低價)。
PowerLanguage還有其他保留字,可以遇到時再查詢。
II. 計算規則
函數(Function)
函數跟參數和變數一樣,可以想像成是一個容器,只是這個容器裡面放的不是數值,而是一連串的程式碼,當我們想要重複使用這段程式碼時,可以不用全部重寫一次,只需要使用函數名稱,程式在執行到函數名稱的時候,就會知道要去執行對應的程式碼。
通常會將常用到的功能寫成函數,這樣就不用每次同樣的計算或功能的都要重寫,只需要使用對應的函數名稱就可以了。
函數跟參數和變數一樣,也分成兩個階段:
第一個階段稱作定義(實作): 將想要當作函數使用的程式碼寫好和編譯。
第二個階段是使用(呼叫): 使用函數名稱和給予參數值,當程式執行到函數名稱時,就會代入參數值和執行對應的程式碼。
由於這篇只是簡單的入門介紹,因此只先說明函數的使用(呼叫),函數的定義(實作)詳細見 函數。
函數的使用(呼叫)語法:
FunctionName(input1, input2, ...)
whereFunctionName
: 要使用的函數名稱。input
: 傳給參數的值。
PowerLanguage提供許多常用功能或計算的內建函數。
AverageFC( PriceValue, Len)是PowerLanguage提供的內建函數之一,這個函數使用兩個參數: PriceValue和Len,計算 Len根K棒的PriceValue的平均值。
MovAvg2Line Cross LE,第4行、第5行:
var0 = AverageFC( Price, FastLength ) ;
var1 = AverageFC( Price, SlowLength ) ;
AverageFC( Price, FastLength )為:
計算FastLength根K棒的Price的平均值
AverageFC( Price, SlowLength )為:
計算SlowLength根K棒的Price的平均值
Price、FastLength、SlowLength這三個字,是第一行程式碼宣告的參數:
inputs: Price( Close ), FastLength( 9 ), SlowLength( 18 );
如果將Price、FastLength、 SlowLength的預設值代入,
得到AverageFC( Close, 9),意思就是:
計算 9根 K棒的 收盤價 的平均值
得到AverageFC( Close, 18),意思就是:
計算 18根 K棒的 收盤價 的平均值。
由於在章節: MultiCharts如何執行策略,我們知道腳本是每一根K棒結束執行一次,所以每一根K棒結束計算一次9根K棒收盤價的平均值,而這個也是9根K棒的移動平均線(9MA)的計算。
因此,AverageFC( PriceValue, Len)函式,如果PriceValue的預設值是Close的話,其實就是在計算Len根K棒的移動平均線。
見 函數(Function)。
指派(Assignment)
在PowerLanguage中,等號(=)有兩個意思: 指派(assignment)或是等於(就是數學的等於)。
只有在跟條件判斷的保留字(Ex: if、else if、while等)一起出現的時候,才是數學的等於。
在一般出現的時候,是指派的意思,先從等號(=)的右邊開始計算,再將計算後的結果指派給左邊。
下面是一個簡單的例子:
variables: BottleA(5), BottleB(3), BottleC(5);
BottleA=BottleB+BottleC;
第一行是宣告變數,而第二行:
BottleA=BottleB+BottleC; ,如果從數學的角度來看很奇怪, BottleA的值是5,而BottleB和 BottleC的值相加是8,5怎麼會等於8?
因為等號(=)在這裡的意思並不是”等於”,而是”指派”,要先從等號(=)的右邊開始運算,運算結束後,再將運算後的值指派給左邊。
因此,這一行為:
將BottleB(5)和BottleC(3)相加,再將相加後的值(8)指派給BottleA,BottleA原來的值(5)被覆蓋掉,BottleA的值變成了8。
MovAvg2Line Cross LE,第4行、第5行:
var0 = AverageFC( Price, FastLength ) ;
var1 = AverageFC( Price, SlowLength ) ;
將Price的預設值是Close代入,這兩行的意思為:
將AverageFC( Close, FastLength )的值指派給 var0
將AverageFC( Close, SlowLength )的值指派給 var1
由上一小節結論得知AverageFC( Close, Len)函式,其實就是在計算Len根K棒的移動平均線。
所以var0就是 FastLength根K棒的移動平均線, var1就是SlowLength根K棒的移動平均線,var0和var1是兩條不同長度(快慢)的移動平均線。
III. 進出場邏輯判斷
分支(Branch)
PowerLanguage提供了if分支語法,來決定程式執行的方向,當滿足某些條件時,執行某些指令,否則執行其他指令。
這裡分成兩個步驟:
第一個步驟,是將要判斷(滿足)的條件,利用and、or等邏輯運算子(Logical Operator)組成邏輯陳述句(Logical Expression)。
第二個步驟,是將邏輯陳述句(Logical Expression)搭配if分支語法決定要執行的方向。
邏輯運算子(Logical Operator)
and: 數學邏輯的and,當兩邊為真時,回傳true,否則回傳false。
or: 數學邏輯的or,只要其中一邊為真時,回傳ture,否則回傳false。
邏輯陳述句(Logical Expression)
邏輯陳述句是回傳值為真假值型別的陳述句。
例如:
5<3: 為邏輯陳述句,5小於3,值為false。
8<>9: 為邏輯陳述句,8不等於9,值為true。
8<>9 and 5<3: 為邏輯陳述句, 8不等於9 且 5小於3,值為false。
第一個步驟,組織邏輯陳述句
MovAvg2Line Cross LE,第7行:
condition1 = CurrentBar > 1 and var0 crosses over var1 ;
這裡的等號(=)是指派,所以先運算等號(=)的右邊。
CurrentBar > 1 and var0 crosses over var1為邏輯陳述句。
CurrentBar是一個保留字, 他的意義是,回傳目前K棒的編號,K棒編號從Maximum Bars Back後,開始算第一根。
例如: 如果 Maximum Bars Back 設定20,第21根K棒,會是編號1。
Maximum Bars Back 的詳細說明,請見章節。
目前可以先將 CurrentBar > 1 視為true,他不影響對這個策略的理解。
crosses over是保留字,表示向上穿越。
var0和var1從上一個小節知道,是代表兩條不同長度的移動平均線,var0代表快線,var1代表慢線。
因此,等號(=)的右邊可以理解為:
CurrentBar大於 1 且 var0(移動平均線-快線) 向上穿越 va1(移動平均線-慢線)
將CurrentBar > 1 視為true,等號(=)的右邊就可以變為:
true 且 var0(移動平均線-快線) 向上穿越 va1(移動平均線-慢線)
等同:
var0(移動平均線-快線) 向上穿越 va1(移動平均線-慢線)
condition1是一個保留字,他是PowerLanguage內建提供的變數,因為是內建提供,所以可以不用宣告就直接使用。
因此,這一整句程式碼可以理解為:
將var0(移動平均線-快線) 向上穿越 va1(移動平均線-慢線)的邏輯結果指派給 condition1
Note: condition1是內建變數,不建議使用內建的變數,因為名稱不夠明確和有意義,在寫程式的習慣上,建議使用有意義的變數名稱。
第二個步驟,邏輯陳述句搭配if分支語法
PowerLanguage提供了if分支語法,讓程式根據邏輯陳述句的結果,決定要執行的方向。
if 分支語法:
If E Then I1;
Where:
E
– 邏輯陳述句。
I1
– 邏輯陳述句為真時,會執行的指令。
MovAvg2Line Cross LE,第8行、第9行:
if condition1 then
Buy ( "MA2CrossLE" ) next bar at market ;
這兩句為:
如果 condition1 是true,則執行 Buy ( “MA2CrossLE” ) next bar at market ;
由前一小節得知 condition1 是 var0(移動平均線) 向上穿越 va1(移動平均線)。
因此,得到:
如果 var0(移動平均線) 向上穿越 va1(移動平均線) 是true,則執行 Buy ( “MA2CrossLE” ) next bar at market ;
見 分支(Branch)。
IV. 買進或賣出
買賣指令
PowerLanguage提供了Buy、Sell、SellShort和BuyToCover買賣下單指令。
MultiCharts在執行到這些指令時,就會執行下單買進或賣出。
Buy(買進)指令的語法:
Buy[("EntryLabel")] [TradeSize] EntryType;
Where:EntryLabel
– 命名買進名稱,買進名稱會顯示在圖表上,賣出時可以用買進名稱指定要賣出哪一筆買進。
如果沒有指定,預設名稱第一筆為”Buy”,第二筆”Buy#2″,第三筆”Buy#3″,以此類推。
[]代表可省略的參數。TradeSize
– 指定要下單的股數(口數)。
如果沒有指定,預設使用 設定->策略屬性->屬性->固定委託股數(口數)的設定值。
[]代表可省略的參數。EntryType
– 指定下單時間點和類型。
註: 買進指令送出委託單後,如果委託單在K棒結束時沒有成交,委託單會被取消。
MovAvg2Line Cross LE,第9行:
Buy ( "MA2CrossLE" ) next bar at market ;
next是保留字,與bar連用,next bar,表示下一根k棒。
at是保留字,無意義,單純增加程式碼可讀性,可省略。
market是保留字,代表市價單。
因此,這一行的意思是:
在下一根K棒以市價單買進,且給予這次買進訊號一個名稱叫做”MA2CrossLE“。
見 買賣指令。
結論
這篇用腳本 MovAvg2Line Cross LE 簡略介紹腳本的框架和基本語法: 宣告、計算規則、進出場邏輯判斷、買進或賣出。
Appendix
註解(Comment)
註解的用途是增加程式碼的可讀性,使用註解說明某一段程式碼,在開發和維護時,更容易了解這段程式碼的用途。
當程式執行到註解時會跳過執行註解,註解不影響程式的邏輯。
腳本MovAvg2Line Cross LE並沒有使用到註解語法,但是為了語法說明的完整,放在這邊說明註解語法。
註解語法分成單行註解和多行註解兩種。
單行註解
以//表示註解開始,從//開始到當行結束視為註解。
//comments...
多行註解
以{表示註解開始,}表示註解結束,包在{和}中間的文字都視為註解。
{
comment1
comment2
...
}
Reference
https://www.multicharts.com/trading-software/index.php?title=Category:Declaration
https://www.multicharts.com/trading-software/index.php?title=Input
https://www.multicharts.com/trading-software/index.php?title=Variable
https://www.multicharts.com/trading-software/index.php?title=Category:Comparisons_and_Loops
https://www.multicharts.com/trading-software/index.php?title=If
https://www.multicharts.com/trading-software/index.php?title=Category:Strategy_Orders
https://www.multicharts.com/trading-software/index.php?title=Buy