函數跟參數和變數一樣,可以想像成是一個容器,只是這個容器裡面放的不是數值,而是一連串的程式碼,當我們想要重複使用這段程式碼時,可以不用全部重寫一次,只需要使用函數名稱,程式在執行到函數名稱的時候,就會知道要去執行對應的程式碼。
通常會將常用到的功能寫成函數,這樣就不用每次同樣的計算或功能的都要重寫,只需要使用對應的函數名稱就可以了。
函數跟參數和變數一樣,也分成兩個階段:
第一個階段稱作定義(實作): 將想要當作函數使用的程式碼寫好和編譯。
第二個階段是使用(呼叫): 使用函數名稱和給予參數值,當程式執行到函數名稱時,就會代入參數值和執行對應的程式碼。
定義(實作)函數
新增一個函數腳本
PowerLanguage Editor->檔案->開新檔案->函數
回傳類型就是型別,分成數值(數值型別)、TrueFalse(真假值型別)、字串(字串型別),詳見型別。
函數儲存進一步決定回傳類型是簡單數值(NumericSimple)還是時序數值(NumericSeries)、簡單真假值(TrueFalseSimple)還是時序真假值(TrueFalseSerise)、簡單字串(StringSimple)還是時序字串(StringSeries),詳見型別。
撰寫功能和編譯
函數腳本除了參數(inputs)語法不一樣和多了回傳語法之外,其他的語法: 變數、分支、迴圈、陣列和註解都和訊號與指標腳本的寫法一樣。
函數的參數和訊號指標或指標腳本的參數不一樣,無法從Multicharts傳入參數值。在使用(呼叫)函數時,將數值傳入給函數的參數。
函數腳本寫好後需要進行編譯,編譯成功後,就可以使用自己寫的函數。
函數腳本的語法框架
[inputs: InputName1(InputType), InputName2(InputType)...;] //Write Functionality [FunctionName=ReturnValue;]
where
inputs: 宣告參數。
InputName: 參數的名稱。
InputType: 參數的型別,見下表 函數的參數型別。
Functionality: 函數的功能。
FunctionName: 指示這個函數的回傳值為ReturnValue。
參數型別
NumericSimple | 意義 | 宣告input型別是Numeric Simple。 宣告為Simple的參數,數值在每一根K棒都一樣,因此沒有歷史數值。 |
語法 | Input: InputName(NumericSimple); | |
Example | Input: Length(NumericSimple); | |
NumericSeries | 意義 | 宣告input型別是Numeric Series。 宣告為Series的參數,數值會隨K棒可能不同,因此有歷史數值可以參照。 |
語法 | Input: InputName(NumericSeries) | |
Example | Input: Price(NumericSeries); | |
Numeric | 意義 | 宣告input型別是Numeric。 傳入參數為NumericSimple或NumerisSeries。 |
語法 | Input: InputName(Numeric) | |
Example | Input: Length(Numeric); | |
NumericRef | 意義 | 宣告input型別是Passing by Reference Numeric。 傳入的參數值如果在函數中有被修改,函數執行結束後,參數值為修改值,見Passing by reference。 |
語法 | Input: InputName(NumericRef) | |
Example | Input: BarCount(NumericRef); | |
NumericArray | 意義 | 宣告input型別是Numeric Array。 傳入指定大小和維度的Numeric Array。 |
語法 | Input: InputName[M1,M2,M3,etc.](NumericArray) where InputName – 參數的名稱。 M – 陣列每個維度的最大索引值。 | |
Example | Input: Table[X,Y,Z](NumericArray); X、Y、Z值為傳入的陣列的每個對應維度的最大索引值。 | |
NumericArrayRef | 意義 | 宣告input型別是Passing by Reference Numeric Array。 傳入指定大小和維度的Numeric Array。 傳入的參數值如果在函數中有被修改,函數執行結束後,參數值為修改值,見Passing by reference。 |
語法 | Input: InputName[M1,M2,M3,etc.](NumericArrayRef) where InputName – 參數的名稱。 M – 陣列每個維度的最大索引值。 | |
Example | Input: Table[X,Y,Z](NumericArrayRef); X、Y、Z值為傳入的陣列的每個對應維度的最大索引值。 |
StringSimple | 意義 | 宣告input型別是String Simple。 宣告為Simple的參數,數值在每一根K棒都一樣,因此沒有歷史數值。 |
語法 | Input: InputName(StringSimple) | |
Example | Input: Name(StringSimple); | |
StringSeries | 意義 | 宣告input型別是String Series。 宣告為Series的參數,數值會隨K棒可能不同,因此有歷史數值可以參照。 |
語法 | Input: InputName(StringSeries) | |
Example | Input: Messages(StringSeries); | |
String | 意義 | 宣告input型別是String。 傳入參數為StringSimple或StringSeries。 |
語法 | Input: InputName(String) | |
Example | Input: Name(String); | |
StringRef | 意義 | 宣告input型別是Passing by Reference String。 傳入的參數值如果在函數中有被修改,函數執行結束後,參數值為修改值,見Passing by reference。 |
語法 | Input: InputName(StringRef) | |
Example | Input: Message(StringRef); | |
StringArray | 意義 | 宣告input型別是String Array。 傳入指定大小和維度的String Array。 |
語法 | Input: InputName[M1,M2,M3,etc.](StringArray) where InputName – 參數的名稱。 M – 陣列每個維度的最大索引值。 | |
Example | Input: MessageTable[X,Y,Z](StringArray); X、Y、Z值為傳入的陣列的每個對應維度的最大索引值。 | |
StringArrayRef | 意義 | 宣告input型別是Passing by Reference String Array。 傳入指定大小和維度的String Array。 傳入的參數值如果在函數中有被修改,函數執行結束後,參數值為修改值,見Passing by reference。 |
語法 | Input: InputName[M1,M2,M3,etc.](StringArrayRef) where InputName – 參數的名稱。 M – 陣列每個維度的最大索引值。 | |
Example | Input: CommentsTable[X,Y,Z](StringArrayRef); X、Y、Z值為傳入的陣列的每個對應維度的最大索引值。 |
TrueFalseSimple | 意義 | 宣告input型別是TrueFalse Simple。 宣告為Simple的參數,數值在每一根K棒都一樣,因此沒有歷史數值。 |
語法 | Input: InputName(TrueFalseSimple) | |
Example | Input: Overnight(TrueFalseSimple); | |
TrueFalseSeries | 意義 | 宣告input型別是TrueFalse Series。 宣告為Series的參數,數值會隨K棒可能不同,因此有歷史數值可以參照。 |
語法 | Input: InputName(TrueFalseSeries) | |
Example | Input: UpTrend(TrueFalseSeries); | |
TrueFalse | 意義 | 宣告input型別是TrueFalse。 傳入參數為TrueFalseSimple或TrueFalseSeries。 |
語法 | Input: InputName(TrueFalse) | |
Example | Input: Overnight(TrueFalse); | |
TrueFalseRef | 意義 | 宣告input型別是Passing by Reference TrueFalse。 傳入的參數值如果在函數中有被修改,函數執行結束後,參數值為修改值,見Passing by reference。 |
語法 | Input: InputName(TrueFalseRef) | |
Example | Input: Flag(TrueFalseRef); | |
TrueFalseArray | 意義 | 宣告input型別是TrueFalse Array。 傳入指定大小和維度的TrueFalse Array。 |
語法 | Input: InputName[M1,M2,M3,etc.](TrueFalseArray) where InputName – 參數的名稱。 M – 陣列每個維度的最大索引值。 | |
Example | Input: FlagTable[X,Y,Z](TrueFalseArray); | |
TrueFalseArrayRef | 意義 | 宣告input型別是Passing by Reference TrueFalse Array。 傳入指定大小和維度的TrueFalse Array。 傳入的參數值如果在函數中有被修改,函數執行結束後,參數值為修改值,見Passing by reference。 |
語法 | Input: InputName[M1,M2,M3,etc.](TrueFalseArrayRef) where InputName – 參數的名稱。 M – 陣列每個維度的最大索引值。 | |
Example | Input: TrendTable[X,Y,Z](TrueFalseArrayRef); |
使用(呼叫)函數
FunctionName(input1, input2, ...);
where
FunctionName: 要使用的函數名稱。
input: 呼叫函數時,要傳給參數的值,又稱作引數。
Example
內建的函數: AerageFC。
檔案->開啟檔案->函數(checkbox打勾)->AverageFC
AverageFC本身是函數實作,同時也呼叫另一個函數SummationFC完成實作功能。
AverageFC函數宣告兩個參數,一個叫PriceValue為numericseries型別,一個叫Len為numericsimple型別。
接著,呼叫SummationFC函數做計算,PriceValue和Len作為引數傳給SummationFC的參數。
最後,AverageFC回傳SummationFC計算後的結果除以Len。
Passing By Value和Passing By Reference
在呼叫函數時,放在參數位置、要傳入給參數的值稱作引數,引數傳給參數的方式分成Passing by value和Passing by reference兩種。
Passing by value
沒有Ref結尾的參數型別,引數傳給參數的方式用Passing By Value:
NumericSimple、NumericSeries、Numeric、NumericArray、StringSimple、StringSeries、String、StringArray、TrueFalseSimple、TrueFalseSeries、TrueFalse、TrueFalseArray。
用Passing by value的方式將引數的值傳給函數的參數時,函數的參數會有自己的記憶體位置,程式會將引數值複製和存到函數參數的記憶體位置,在函數中無法改變宣告為Passing By Value的參數值,如果嘗試改變Passing By
Value的參數值,會造成compile error: Array, variable or refinput expected。
如下範例: 引數值為12,存在記憶體0x1000位置,程式會將引數值12複製和存到函數參數的記憶體位置0x1004。
Memory | ||
address | value | |
引數–> | 0x1000 | 12 |
函數的參數–> | 0x1004 | 12 |
Example
swapByValFunc函數的參數ValueA(NumericSimple)和ValueB(NumericSimple)是Passing By Value,第6行和第7行嘗試改變ValueA和ValueB的值,造成compile error: Array, variable or refinput expected。
函數: swapByValFunc
inputs: ValueA(NumericSimple), ValueB(NumericSimple); Print("In sawpFunc, before swap ValueA: ", ValueA, ", ValueB: ", ValueB); temp = ValueA; ValueA = ValueB; //compile error: Array, variable or refinput expected ValueB = temp; //compile error: Array, variable or refinput expected Print("In sawpFunc, after swap ValueA: ", ValueA, ", ValueB: ", ValueB);
Passing by reference
有Ref結尾的參數型別,引數傳給參數的方式用Passing By Reference:
NumericRef、NumericArrayRef、StringRef、StringArrayRef、TrueFalseRef、TrueFalseArrayRef。
用passing by reference的方式將引數的值傳給函數的參數時,函數的參數是使用引數的記憶體位置,由於和引數存取同一個記憶體位置上的值,當改變函數的參數值時,也會改變引數值。
如下範例: 引數值為12,存在記憶體0x1000位置,函數的參數是使用引數的記憶體位置0x1000得到參數值12。
Memory | ||
address | value | |
引數–> 函數的參數–> | 0x1000 | 12 |
Passing by reference最多的應用就是拿來當函數的輸出,由於PowerLanguage的函數語法,一個函數只有一個回傳值,因此一個函數只有一個輸出,當函數需要有多個輸出的情形時,就可以使用Passing by reference的方式。
Example
範例testSwapFunc訊號呼叫swapByRefFunc函數,swapByRefFunc會將輸入的ValueA和ValueB的值互換,因為swapByRefFunc的參數: ValueA(NumericRef)和ValueB(NumericRef)是Passing by reference,因此呼叫swapByRefFunc結束後,testSwapFunc的ValueA和ValueB會得到互換後的值。
呼叫Print來將ValueA和ValueB的值印出,從Output可以看到在呼叫swapByRefFunc函數後,ValueA和ValueB的值互相交換。
訊號: testSwapFunc
var: ValueA(12), ValueB(34); //ValueA: 12.00, ValueB: 34.00 Print("Before call swap, Func, ValueA: ", ValueA, ", ValueB: ", ValueB); swapByRefFunc(ValueA, ValueB); //ValueA: 34.00, ValueB: 12.00 Print("After call swap, Func, ValueA: ", ValueA, ", ValueB: ", ValueB);
函數: swapByRefFunc
inputs: ValueA(NumericRef), ValueB(NumericRef); var: temp(0); //ValueA: 12.00, ValueB: 34.00Print("In sawpFunc, before swap ValueA: ", ValueA, ", ValueB: ", ValueB); //swap ValueA and ValueB temp = ValueA; ValueA = ValueB; ValueB = temp; //ValueA: 34.00, ValueB: 12.00Print("In sawpFunc, after swap ValueA: ", ValueA, ", ValueB: ", ValueB);
Reference
//www.multicharts.com/trading-software/index.php?title=Category:Declaration
//www.multicharts.com/trading-software/index.php?title=Passing_values_to_and_from_a_function