MultiCharts | PowerLanguage語法教學 | CH2:策略的框架和基本語法

策略的框架和基本語法

第一個策略範例: MovAvg2Line Cross LEMovAvg2Line Cross LE兩條均線黃金交叉買進策略,透過這個簡單的策略範例快速了解腳本的框架和基本語法: 宣告計算規則進出場邏輯判斷買進或賣出

打開PowerLanguage Editor->檔案->開啟檔案->公式類型->訊號(打勾)->MovAvg2Line Cross LE

打開PowerLanguage Editor->檔案->開啟檔案->公式類型->訊號(打勾)->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設定的新預設值直接執行就能套用,不需要重新編譯。

參數值只能透過一開始的預設值設定和改變,設定後,在腳本中無法再透過程式碼更改參數值。

參數(inputs)和變數(variables)

MovAvg2Line Cross LE,第1行:

inputs: Price( Close ), FastLength( 9 ), SlowLength( 18 ) ;   

這一行的意思就是:
宣告參數(inputs),參數名稱分別叫做 ,Price且預設值是Close(收盤價)、FastLength且預設值是9SlowLength且預設值是18

下圖是在MultiCharts->設定->訊號-> MovAvg2Line Cross LE ->設定可以看到,參數名稱PriceFastLengthSlowLength,就是在腳本中inputs宣告的名稱,因為沒有修改數值設定,所以都是使用宣告中的預設值Close918

MultiCharts->設定->訊號-> MovAvg2Line Cross LE ->設定
MultiCharts->設定->訊號-> MovAvg2Line Cross LE ->設定

變數(Variables)的宣告語法:

variables: VariableName1(InitialValue1), VariableName2(InitialValue2),etc;

variables: 表示宣告變數。
VariableName – 變數的名稱,名稱可以是字母、底線、數字、句點( . )組成,名稱英文不分大小寫。名稱不可以是數字或句點( . )起頭。
InitialValue – 變數的初始值,初始值決定變數的型別,型別可以是數值(numerical)、字串(string)和真假值(TrueFalse)。
註: 變數宣告的結束要加分號(;),沒有加會編譯錯誤。

您不能從 MultiCharts 設定變數的初始值。
變數值透過初始值設定,設定後,可以在腳本中再透過程式碼更改變數值(指派其他的值)。

參數(inputs)和變數(variables)

MovAvg2Line Cross LE,第2行:

variables: var0( 0 ), var1( 0 ) ;

這一行的意思就是:
宣告變數(variables),變數名稱分別叫做,var0並給予初始值是0var1並給予初始值是0

保留字(Reserved Word)

保留字是在PowerLanguage中,具有特殊意義或是本身是語法的單字,他們不能被拿來當作參數或變數的名稱。

宣告用的inputsvariables本身是語法的字因此是保留字。
MovAvg2Line Cross LE,第一行,參數宣告中出現的Close也是保留字,他代表的意思是收盤價,其他類似的保留字還有Open(開盤價)、High(最高價)、Low(最低價)。

PowerLanguage還有其他保留字,可以遇到時再查詢。

II. 計算規則

函數(Function)

函數跟參數和變數一樣,可以想像成是一個容器,只是這個容器裡面放的不是數值,而是一連串的程式碼,當我們想要重複使用這段程式碼時,可以不用全部重寫一次,只需要使用函數名稱,程式在執行到函數名稱的時候,就會知道要去執行對應的程式碼。
通常會將常用到的功能寫成函數,這樣就不用每次同樣的計算或功能的都要重寫,只需要使用對應的函數名稱就可以了。

函數跟參數和變數一樣,也分成兩個階段:
第一個階段稱作定義(實作): 將想要當作函數使用的程式碼寫好和編譯。
第二個階段是使用(呼叫): 使用函數名稱和給予參數值,當程式執行到函數名稱時,就會代入參數值和執行對應的程式碼。

由於這篇只是簡單的入門介紹,因此只先說明函數的使用(呼叫),函數的定義(實作)詳細見 函數

函數的使用(呼叫)語法:

FunctionName(input1, input2, ...)

where
FunctionName: 要使用的函數名稱。
input: 傳給參數的值。

PowerLanguage提供許多常用功能或計算的內建函數。
AverageFC( PriceValue, Len)是PowerLanguage提供的內建函數之一,這個函數使用兩個參數: PriceValueLen,計算 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的平均值

PriceFastLengthSlowLength這三個字,是第一行程式碼宣告的參數:

inputs: Price( Close ), FastLength( 9 ), SlowLength( 18 );

如果將PriceFastLengthSlowLength的預設值代入,
得到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: ifelse ifwhile等)一起出現的時候,才是數學的等於。
在一般出現的時候,是指派的意思,先從等號(=)的右邊開始計算,再將計算後的結果指派給左邊。

下面是一個簡單的例子:

variables: BottleA(5), BottleB(3), BottleC(5);
BottleA=BottleB+BottleC;

第一行是宣告變數,而第二行: BottleA=BottleB+BottleC; ,如果從數學的角度來看很奇怪, BottleA的值是5,而BottleBBottleC的值相加是8,5怎麼會等於8?
因為等號(=)在這裡的意思並不是”等於”,而是”指派”,要先從等號(=)的右邊開始運算,運算結束後,再將運算後的值指派給左邊。
因此,這一行為:
BottleB(5)和BottleC(3)相加,再將相加後的值(8)指派給BottleABottleA原來的值(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棒的移動平均線,var0var1是兩條不同長度(快慢)的移動平均線。

III. 進出場邏輯判斷

分支(Branch)

PowerLanguage提供了if分支語法,來決定程式執行的方向,當滿足某些條件時,執行某些指令,否則執行其他指令。
這裡分成兩個步驟:
第一個步驟,是將要判斷(滿足)的條件,利用andor邏輯運算子(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是保留字表示向上穿越。
var0var1從上一個小節知道,是代表兩條不同長度的移動平均線,var0代表快線,var1代表慢線。

因此,等號(=)的右邊可以理解為:
CurrentBar大於 1var0(移動平均線-快線) 向上穿越 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:
– 邏輯陳述句。
I1 – 邏輯陳述句為真時,會執行的指令。

MovAvg2Line Cross LE,第8行、第9行:

if condition1 then                                                                    
	Buy ( "MA2CrossLE" ) next bar at market ;

這兩句為:
如果 condition1true,則執行 Buy ( “MA2CrossLE” ) next bar at market ;

由前一小節得知 condition1var0(移動平均線) 向上穿越 va1(移動平均線)
因此,得到:
如果 var0(移動平均線) 向上穿越 va1(移動平均線) true,則執行 Buy ( “MA2CrossLE” ) next bar at market ;

分支(Branch)

IV. 買進或賣出

買賣指令

PowerLanguage提供了BuySellSellShortBuyToCover買賣下單指令。
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

發佈留言