Inventor Quantitative PINE 言語入門チュートリアル

作成日:: 2022-05-30 16:23:43, 更新日:: 2022-09-28 17:10:21
comments   0
hits   8860

strategy(“test”, overlay=true)

a = close b = close[1] c = b[1]

plot(a, title=“a”) plot(b, title=“b”) plot(c, title=“c”)


しかし,`a = close[1][2]`記事の内容はこうです.

```pine
b = close[1]
c = b[1]

文字列の定義は,文字列の定義の定義の定義の定義の定義の定義の定義の定義の定義です.b = close[1]しかし,bは,bが,bが,bが,bが,bが,bが,bが,bが,bが,bが,bが,bが,bが,bが,bが,c = b[1],b は,歴史操作で再び歴史値を引用することができる.Pine言語の系列 (series) の概念は,数列ほど単純ではないことがわかります. close の上Bar上の歴史値 (b に与えられた値) として理解できます.b は,時間序列構造 (time series) であるため,その歴史値を引用し続けることができます.

図の左端を引っ張って,最初の K 線で b と c の値が空値 ((na) であることを確認できます. それは,スクリプトが最初の K 線 BAR で実行するときに,前へ引用する 1 または 2 周期の歴史値は存在しないからです. だから,歴史データを引用するときに空値が引用されるかどうか,戦略を記述する際に常に注意する必要があります. 慎重でない場合,空値を使用すると,一連の計算の違いが生じ,実際の BAR にさえ影響を与える可能性があります. 通常,私たちはコードで使用します.nanzこの関数は,この関数と関数関数で割り切れます.nzna函数,どの章を覚えていますか?) のような空の値の扱いを具体化します.

close > nz(close[1], open)    // 当引用close内置变量前一个BAR的历史值时,如果不存在,则使用open内置变量

これは, null に引用される可能性のある ((na) の処理である.


オペレーターの優先順位

私たちは,Pine言語の多くの演算子を学びました.これらの演算子は,演算数と様々な組み合わせによって表現を形成します. では,表現で計算するときに,これらの演算の優先順位はどのようなものですか?

優先する オペレーター
9 []
8 一元演算子で +- `
7 */%
6 バイナリオペレータでは +-`
5 ><>=<=
4 ==!=
3 and
2 or
1 ?:

優先度が高い表現の部分で最初に操作し,優先度が同じなら,左から右に操作する.()この部分の式は,まずその部分の演算を強制的に行なうように包み込まれる.

変数について

変数の宣言

変数の名前として変数に名前を付けます. だから,変数は保存値の識別子です. では,変数を宣言するにはどうすればよいですか? 宣言変数はどのようなルールを持っていますか?

  • 声明の形式: 変数を宣言するときに最初に書くのは”宣言モード”です.変数の宣言モードは以下の3種類があります.
    1. キーワードを使うvar。 2 キーワードを使うことvarip。 3つ目は何も書かないこと.

varvarip変数の宣言パターンは何も書かない場合,例えば,文:i = 1変数を指定し,その値を与えると,K行BARで実行されます.

  • タイプ FMZ上のPine言語は,型に関する要求は厳格ではないため,一般的には省略できる。しかし,Trading View上のスクリプト戦略に適合するため,変数を宣言する際にも型を付けることができる。例えば:
  int i = 0 
  float f = 1.1

トレーディングビューのタイプはより厳格な要求であり,以下のコードを使用すると,Trading Viewでエラーが返されます.

  baseLine0 = na          // compile time error!

変数の定義は次のように書けます.

// [<declaration_mode>] [<type>] <identifier> = value 
   声明模式             类型     标识符       = 值

代入演算子を使って=変数宣言時に変数に付与する.付与時に,値は文字列,数値,式,関数呼び出し,ifforwhileまたはswitch構造等 ((これらの構造のキーワード,文の用法については,後回のレッスンで詳しく説明します.実際は,私たちは,以前のレッスンで,簡単なif文の赋值を学んできたので,見直してみてください) 。

ここで,input関数について説明します. これは,設計策の策定時に頻繁に使用される関数です. 設計策の策定時に非常に重要な関数です.

入力関数:

input函数,参数defval、title、tooltip、inline、group

FMZ上のinput関数は,Trading View上の関数とは少し異なるが,この関数は,策略パラメータの付加値入力として使用されている.以下は,input関数のFMZ上の使用を例で詳しく説明する.

param1 = input(10, title="参数1名称", tooltip="参数1的描述信息", group="分组名称A")
param2 = input("close", title="参数2名称", tooltip="参数2的描述信息", group="分组名称A")
param3 = input(color.red, title="参数3名称", tooltip="参数3的描述信息", group="分组名称B")
param4 = input(close, title="参数4名称", tooltip="参数4的描述信息", group="分组名称B")
param5 = input(true, title="参数5名称", tooltip="参数5的描述信息", group="分组名称C")

ma = ta.ema(param4, param1)
plot(ma, title=param2, color=param3, overlay=param5)

変数を宣言する際に変数に値を与えるのは,input関数である.FMZ上のinput関数はFMZのポリシーインターフェイスで,ポリシーパラメータを設定するためのコントロールを自動的に描画する.FMZ上のサポートされているコントロールは,現在,数値入力ボックス,テキスト入力ボックス,下落ボックス,ブール値の勾選がある.また,ポリシーパラメータのグループを設定し,パラメータを設定するための提示テキスト情報などの機能を設定することができます.

Inventor Quantitative PINE 言語入門チュートリアル

入力関数の主要パラメータは以下の通りです.

  • defval: パイン言語の組み込み変数,数値,文字列をサポートする,入力関数として設定されたポリシーパラメータオプションのデフォルト値
  • title: リアルディスク/反測のポリシーインターフェイスで表示されるパラメータの名前
  • tooltip: 策略パラメータの提示メッセージ,マウスが策略パラメータにハグされたときに,このパラメータの設定に関するテキスト情報が表示されます.
  • group: ポリシーのパラメータグループ名,パラメータグループに与えることができる。

単一の変数宣言,赋值に加えて,Pine言語には,変数の集合を宣言し,付与する書き方もある.

[变量A,变量B,变量C] = 函数 或者 ```if```、 ```for```、```while```或```switch```等结构

言語は 言語とは違うta.macd関数が MACD インデクタを計算するとき,MACD インデクタは多線インデクタであるため,三組のデータを計算する.したがって,次のように書ける:

[dif,dea,column] = ta.macd(close, 12, 26, 9)

plot(dif, title="dif")
plot(dea, title="dea")
plot(column, title="column", style=plot.style_histogram)

このコードを使って MACD グラフを描くことは簡単です. 組み込み関数は複数の変数を返します. 書き込み関数は複数のデータを返します.

twoEMA(data, fastPeriod, slowPeriod) =>
    fast = ta.ema(data, fastPeriod)
    slow = ta.ema(data, slowPeriod)
    [fast, slow]

[ema10, ema20] = twoEMA(close, 10, 20)
plot(ema10, title="ema10", overlay=true)
plot(ema20, title="ema20", overlay=true)

ifなどの構造を複数の変数として赋值する記述も,上記のカスタム関数方式に似ており,興味のある方は試すこともできます.

[ema10, ema20] = if true
    fast = ta.ema(close, 10)
    slow = ta.ema(close, 20)
    [fast, slow]

plot(ema10, title="ema10", color=color.fuchsia, overlay=true)
plot(ema20, title="ema20", color=color.aqua, overlay=true)

条件構造

条件分岐のローカルコードブロックに書き込むことができない関数には,主に以下のいくつかの関数があります.

barcolor(), fill(), hline(), indicator(), plot(), plotcandle(), plotchar(), plotshape()

Trading Viewでは誤報をコンパイルする。FMZの制限はそれほど厳格ではないが,Trading Viewの規範に従って書くこともお勧めする。例えば,FMZでは誤報は行わないが,こんな書き方はお勧めしない。

strategy("test", overlay=true)
if close > open 
    plot(close, title="close")
else 
    plot(open, title="open")

if 文について

ビデオの”つで

var lineColor = na

n = if bar_index > 10 and bar_index <= 20
    lineColor := color.green
else if bar_index > 20 and bar_index <= 30
    lineColor := color.blue
else if bar_index > 30 and bar_index <= 40
    lineColor := color.orange
else if bar_index > 40
    lineColor := color.black
else 
    lineColor := color.red
    
plot(close, title="close", color=n, linewidth=5, overlay=true)
plotchar(true, title="bar_index", char=str.tostring(bar_index), location=location.abovebar, color=color.red, overlay=true)

重点:判断用式は,ブール値を返します。縮小注意。最大1つのelse分岐のみがあります。すべての分岐式は真ではないし,else分岐もなければ,naを返します。

x = if close > open
    close
plot(x, title="x")

K線BARが陰線であるとき,つまりclose < openであるとき,if文の後に表される式はfalseであるため,ifのローカルコードブロックは実行されません。このときもelseの分岐はありませんので,if文はnaを返します。xがnaに代入されます。この点を図面で描画することはできません.また,図面の反測でも見ることができます。

switch 文について

switch文は,また,特定の条件に応じて異なる経路を実行するように設計するために使用される分岐構造の文である. スイッチ文には,一般的に以下のいくつかの重要な知識点があります.

1 ,switch 文は if 文と同様に,値を返します。 2. 他の言語のswitch文とは異なり,switch構造を実行するときは,そのコードの1つのローカルブロックのみを実行するので,break宣言は不要である (つまり,breakなどのキーワードを書く必要はありません). 3. switch の各分支は 1 つのローカルブロックを書き込むことができます. このローカルブロックの最後の行は,返される値 ((これは 1 つの値の元群である) になります). もし,分支が実行されたローカルブロックがなければ,返されるのは na になります. 4. スイッチ構造内の表現判断位置,文字列,変数,表現または関数呼び出しを記述できる. 5. switch は,構造で他の状況がない場合に使用するデフォルト値として返される値を指定します.

switchは2つの形式に分かれていますが,例を一つずつ見ていきましょう.

1 表現されたswitch記事の内容は以下の通りです.

// input.string: defval, title, options, tooltip
func = input.string("EMA", title="指标名称", tooltip="选择要使用的指标函数名称", options=["EMA", "SMA", "RMA", "WMA"])

// input.int: defval, title, options, tooltip
// param1 = input.int(10, title="周期参数")
fastPeriod = input.int(10, title="快线周期参数", options=[5, 10, 20])
slowPeriod = input.int(20, title="慢线周期参数", options=[20, 25, 30])

data = input(close, title="数据", tooltip="选择使用收盘价、开盘价、最高价...")
fastColor = color.red
slowColor = color.red

[fast, slow] = switch func
    "EMA" =>
        fastLine = ta.ema(data, fastPeriod)
        slowLine = ta.ema(data, slowPeriod)
        fastColor := color.red
        slowColor := color.red
        [fastLine, slowLine]
    "SMA" =>
        fastLine = ta.sma(data, fastPeriod)
        slowLine = ta.sma(data, slowPeriod)
        fastColor := color.green
        slowColor := color.green
        [fastLine, slowLine]
    "RMA" =>
        fastLine = ta.rma(data, fastPeriod)
        slowLine = ta.rma(data, slowPeriod)
        fastColor := color.blue
        slowColor := color.blue
        [fastLine, slowLine]
    =>
        runtime.error("error")
        
plot(fast, title="fast" + fastPeriod, color=fastColor, overlay=true)
plot(slow, title="slow" + slowPeriod, color=slowColor, overlay=true)

このビデオでは,inputの2つの関数について学びます.input.stringinput.int関数。 input.string文字列を返します.input.intこの関数は整数値を返します.options参数を使うことoptions参数は,選択可能な値で構成される配列に転送できます.例えば,例のoptions=["EMA", "SMA", "RMA", "WMA"]そしてoptions=[5, 10, 20](注: 1 つは文字列型, 1 つは数値型) 。 このように,ポリシーインターフェースのコントロールは,特定の数値を入力する必要がなく,コントロールは,optionsパラメータで提供されるこれらのオプションを選択する下方ドラッグボックスになります。

変数funcの値は,switchの表現である (((変数,関数呼び出し,表現) の変数funcという文字列で,switchのどの支部が実行されているかを決定します.変数funcが,switchのどの支部の表現と一致しない場合 (つまり等しい場合),デフォルトの支部コードブロックを実行し,実行されます.runtime.error("error")この関数は, 策略が例外を投げるのを停止させる.

runtime.errorの最後の行に,switchのデフォルト分岐のコードブロックに runtime.errorの最後の行に,switchのデフォルト分岐のコードブロックに runtime.errorの最後の行に,switchのデフォルト分岐のコードブロックに runtime.errorの最後の行に,switchのデフォルト分岐のコードブロックに runtime.errorの最後の行に,switchのデフォルト分岐のコードブロックに runtime.errorの最後の行に,switchのデフォルト分岐のコードブロックに runtime.errorの最後の行に runtime.errorの最後の行に,switchのデフォルト分岐のコードブロックに runtime.errorの最後の行に runtime.errorの最後の行に,switchのデフォルト分岐のコードブロックに runtime.errorの最後の行に runtime.errorの最後の行に runtime.errorの最後の行に runtime.errorの最後の行に runtime.errorの最後の行に runtime.erに runtime.[na,na] のようなコードが返値を互換にするには,trading view でこの問題を考慮する必要があり,タイプが一致しない場合はエラーが報われる。しかし,FMZ で厳格に要求されるタイプがないので,この互換性コードを省略することができます。したがって,FMZ で if,switch 分岐返値のタイプ互換性問題を考慮する必要はありません。

strategy("test", overlay=true)
x = if close > open
    close
else
    "open"
plotchar(true, title="x", char=str.tostring(x), location=location.abovebar, color=color.red)

FMZではエラーが表示されないが,Trading Viewではエラーが表示される.ifの分岐が返されるタイプが一致しないからです.

2 表現されていないswitch

このビデオでは,switch表現を伴わない書法である.

up = close > open     // up = close < open 
down = close < open 
var upOfCount = 0 
var downOfCount = 0 

msgColor = switch
    up  => 
        upOfCount += 1 
        color.green 
    down => 
        downOfCount += 1
        color.red

plotchar(up, title="up", char=str.tostring(upOfCount), location=location.abovebar, color=msgColor, overlay=true)
plotchar(down, title="down", char=str.tostring(downOfCount), location=location.belowbar, color=msgColor, overlay=true)

テストコード例では,switchが実行分岐条件で実在するローカルコードブロックにマッチする事がわかります.一般的には,switch文の後に続く分岐条件は相互排斥的である必要があります.つまり,例ではupとdownが同時にtrueであることはできません.switchが1つの分岐のローカルコードブロックのみを実行できるので,興味のある方は,次の文をコードで行えます.up = close > open // up = close < openコメントの内容を書き換えて,観察した結果を反省します。switch 支部は最初の支部のみを実行することがわかります。さらに注意が必要なのは,関数呼び出しをswitch の支部に書き込まないようにすること.関数は,各 BAR に呼び出されることがないため,いくつかのデータ計算問題を引き起こす可能性があります.switch“例では,実行分岐は確定し,戦略の実行中に変更されません.

循環構造

for 文について

返回值 = for 计数 = 起始计数 to 最终计数 by 步长
    语句                                            // 注释:语句里可以有break,continue
    语句                                            // 注释:最后一条语句为返回值

for 文は非常にシンプルで, for ループは最終的に 1 つの値 (() を返すか,複数の値を返すか,[a,b,c] のような形式) 。上記の偽コードで”返り値”の位置に値を割り当てている変数。for文の後には,ループ回数を制御する,他の値を引用するなどに使われる”カウント”の変数。”カウント”の変数は,ループが始まる前に”初期カウント”に値が付けられ,それから”ペース”の設定に従って増加し”,カウント”の変数が”最終カウント”より大きいときにループが停止する。

for ループで使用されるbreakキーワード:実行されたときbreak文が終わると,循環は止まります. for ループで使用されるcontinueキーワード:実行されたときcontinue文の後に,ループは無視されます.continueその後のコードは,次のループを直接実行する。for 文は,最後のループの実行時に返された値を返します。もしコードが実行されていなければ, null を返します。

簡単な例を挙げてみましょう.

ret = for i = 0 to 10       // 可以增加by关键字修改步长,暂时FMZ不支持 i = 10 to 0 这样的反向循环
    // 可以增加条件设置,使用continue跳过,break跳出
    runtime.log("i:", i)
    i                       // 如果这行不写,就返回空值,因为没有可返回的变量
    
runtime.log("ret:", ret)
runtime.error("stop")

for … in 文について

for ... in文には2つの形式があり,以下の偽コードで説明する。

返回值 = for 数组元素 in 数组 
    语句                        // 注释:语句里可以有break,continue
    语句                        // 注释:最后一条语句为返回值
返回值 = for [索引变量, 索引变量对应的数组元素] in 数组
    语句                        // 注释:语句里可以有break,continue
    语句                        // 注释:最后一条语句为返回值 

2つの形式の主な違いは,forキーワードの後に続く内容にあることがわかります.一つは,変数を使用して配列要素を引用する変数である。一つは,インデックス変数を含む配列要素変数の元組の構造を使用して引用する。もう一つは,返値ルール,break,continueなどのルールとforループに一致している。また,簡単な例で説明します。

testArray = array.from(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
for ele in testArray            // 修改成 [i, ele]的形式:for [i, ele] in testArray , runtime.log("ele:", ele, ", i:", i)
    runtime.log("ele:", ele)

runtime.error("stop")

インデックスを必要とする場合for [i, ele] in testArray書き方について

for 循環利用

パイン言語で提供される内置関数を使っていくつかの循環論理計算を行うとき,循環構造を使って直接書き込むことも,内置関数を使って処理することもできます. 例を2つ挙げましょう.

1 平均値を計算する

循環構造の設計では

length = 5
var a = array.new(length)
array.push(a, close)

if array.size(a) >= length
	array.remove(a, 0)
	
sum = 0 	
for ele in a
    sum += ele 

avg = sum / length
plot(avg, title="avg", overlay=true)

この例では,for 回転加算を用いて,平均値を計算した.

平均線は,内置関数を使って直接計算します.

plot(ta.sma(close, length), title="ta.sma", overlay=true)

組み込みの関数を使用するta.sma平均線指標を計算するには,明らかに平均線を計算するために内置関数を使用することがより簡単である。グラフ上の対比では,計算された結果が完全に一致していることがわかります。

2 求和する

上の例を使って説明しましょう.

循環構造の設計では

length = 5
var a = array.new(length)
array.push(a, close)

if array.size(a) >= length
	array.remove(a, 0)
	
sum = 0 	
for ele in a
    sum += ele 

avg = sum / length
plot(avg, title="avg", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)

配列のすべての要素の和を計算するには,ループを使用することもできます.array.sum計算してみましょう 組み込み関数を直接使って加算を計算する:

length = 5
var a = array.new(length)
array.push(a, close)

if array.size(a) >= length
	array.remove(a, 0)
	
plot(array.sum(a) / length, title="avg", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)

計算したデータを見れば,プロット図を用いてグラフに完全に一致していることがわかります.

ループの設計は,主に以下の3つの用途に基づいています. 1. 配列のいくつかの操作,計算について. 2. 過去を振り返り,例えば,現在のBARの高点より過去の高点がどのくらい高いかを調べる.現在のBARの高点は,スクリプトが実行しているBARでしか知られていないので,過去BARにタイムリーで戻り,分析するためにループが必要である. 3. パイン言語の内置関数が過去BARの計算を完了できない場合.

while 文について

while文は,ループ部分のコードが,while構造の判断条件が false (false) であるまで実行されるようにします.

返回值 = while 判断条件
    语句                    // 注释:语句里可以有break,continue
    语句                    // 注释:最后一条语句为返回值

whileの他のルールはforループに似ており,ループ体ローカルコードブロックの最後の行が返値であり,複数の値を返せます。”ループ条件”が真である場合にループを実行し,条件が偽である場合にループを停止します。ループ体内でbreak,continue文も使用できます。

平均線を計算した例で説明します.

length = 10

sma(data, length) => 
    i = 0 
    sum = 0 
    while i < 10 
        sum += data[i]
        i += 1
        sum / length

plot(sma(close, length), title="sma", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)

循环の利用も非常に簡単であり,組み込み関数で代替できない計算論理を設計することもできます.例えば,階乗を計算する:

counter = 5
fact = 1

ret = while counter > 0
    fact := fact * counter
    counter := counter - 1
    fact

plot(ret, title="ret")  // ret = 5 * 4 * 3 * 2 * 1

グループ

Pine言語の数列は,他のプログラミング言語の数列の定義に似ています.Pineの数列は,一次元数列である。通常,連続した一連のデータを格納するために使用される。数列の格納される単一のデータは,数列の要素と呼ばれます.これらの要素のタイプは,整型,浮点型,文字列,色値,ブル値である。FMZのPine言語は,型をあまり厳格に要求しないし,一つの数列の中に文字列と数値を同時に格納することもできます。数列の底層も連続構造であるため,もし歴史演算符を用いた場合,前 BAR上の数列の状態が引用されている。したがって,数列の特定の要素を引用するときに歴史演算子は使用されません.[]必要なものなのですarray.get()そしてarray.set()函数。 配列内の要素のインデックス順序は,配列の最初の要素のインデックスが0で,次の要素のインデックスが増加して1。

簡単なコードで説明します.

var a = array.from(0)
if bar_index == 0 
    runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1])
else if bar_index == 1 
    array.push(a, bar_index)
    runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1])
else if bar_index == 2
    array.push(a, bar_index)
    runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1], ", 向前数2根BAR上的a,即a[2]值:", a[2])
else if bar_index == 3 
    array.push(a, bar_index)
    runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1], ", 向前数2根BAR上的a,即a[2]值:", a[2], ", 向前数3根BAR上的a,即a[3]值:", a[3])
else if bar_index == 4 
    // 使用array.get 按索引获取元素,使用array.set按索引修改元素
    runtime.log("数组修改前:", array.get(a, 0), array.get(a, 1), array.get(a, 2), array.get(a, 3))
    array.set(a, 1, 999)
    runtime.log("数组修改后:", array.get(a, 0), array.get(a, 1), array.get(a, 2), array.get(a, 3))

定義された配列

使用array<int> afloat[] b宣言された配列または1つの変数のみを宣言する配列が代入される,例えば:

array<int> a = array.new(3, bar_index)
float[] b = array.new(3, close)
c = array.from("hello", "fmz", "!")
runtime.log("a:", a)
runtime.log("b:", b)
runtime.log("c:", c)
runtime.error("stop")

配列変数を初期化するために一般に使用されるarray.newそしてarray.from函数。Pine言語には,array.newに類似した,型に関連した関数がたくさんあります.array.new_int()array.new_bool()array.new_color()array.new_string()待って。

var キーワードは,配列の宣言パターンにも作用し,var キーワードで宣言された配列は,最初の BAR にのみ初期化されます.

var a = array.from(0)
b = array.from(0)

if bar_index == 1
    array.push(a, bar_index)
    array.push(b, bar_index)
else if bar_index == 2 
    array.push(a, bar_index)
    array.push(b, bar_index)
else if barstate.islast
    runtime.log("a:", a)
    runtime.log("b:", b)
    runtime.error("stop")

aの配列の変更は,継続的に決定され,再置かれていないことがわかります。bの配列は,各BARで初期化されます。最終的にbarstate.islastリアルタイムで印刷する場合は,数値0の要素のみが残ります.

配列の要素を読み書きする

array.get を使って,配列内のインデックス位置指定の要素を取得し,array.set を使って,配列内のインデックス位置指定の要素を変更する.

array.get の最初のパラメータは処理する配列で,第二のパラメータは指定されたインデックスである. array.set の最初のパラメータは処理する数列,第二のパラメータは指定されたインデックス,第三のパラメータは書き込むべき要素である.

この簡単な例で説明します.

lookbackInput = input.int(100)
FILL_COLOR = color.green

var fillColors = array.new(5)
if barstate.isfirst
    array.set(fillColors, 0, color.new(FILL_COLOR, 70))
    array.set(fillColors, 1, color.new(FILL_COLOR, 75))
    array.set(fillColors, 2, color.new(FILL_COLOR, 80))
    array.set(fillColors, 3, color.new(FILL_COLOR, 85))
    array.set(fillColors, 4, color.new(FILL_COLOR, 90))

lastHiBar = - ta.highestbars(high, lookbackInput)
fillNo = math.min(lastHiBar / (lookbackInput / 5), 4)

bgcolor(array.get(fillColors, int(fillNo)), overlay=true)
plot(lastHiBar, title="lastHiBar")
plot(fillNo, title="fillNo")

この例では,基底色である緑を初期化し,色を保存するための配列を宣言し,初期化し,色値に異なる透明性を付与する (color.new関数を使用する).現在のBAR距離が100回レビュー周期内highの最大値の距離を計算することによって,色級を計算する.最近100回レビュー周期内highの最大値の距離が近いほど,等級が高く,対応する色値はより深い (透明度が低い).多くの類似策は,この方法で現在の価格をN回レビュー周期内レベルに表現する.

配列の要素を巡る

単に”for in”と”for in/while”を組み合わせた数列を”for in”と”while”で表すことができます.

a = array.from(1, 2, 3, 4, 5, 6)

for i = 0 to (array.size(a) == 0 ? na : array.size(a) - 1)
    array.set(a, i, i)
    
runtime.log(a)
runtime.error("stop")
a = array.from(1, 2, 3, 4, 5, 6)

i = 0
while i < array.size(a)
    array.set(a, i, i)
    i += 1

runtime.log(a)
runtime.error("stop")
a = array.from(1, 2, 3, 4, 5, 6)

for [i, ele] in a 
    array.set(a, i, i)

runtime.log(a)
runtime.error("stop")

この3つの巡回方法は,同じ結果が得られます.

配列は,スクリプトの全域域で宣言され,関数または if 支部のローカル範囲で宣言され得る.

歴史的データ引用

配列内の要素の使用については,次の方法が等価である.以下の例によって,図に2つの線を描くことがわかります.各グループに2つの線があり,各グループの2つの線の数値はまったく同じである。

a = array.new_float(1)
array.set(a, 0, close)
closeA1 = array.get(a, 0)[1]
closeB1 = close[1]
plot(closeA1, "closeA1", color.red, 6)
plot(closeB1, "closeB1", color.black, 2)

ma1 = ta.sma(array.get(a, 0), 20)
ma2 = ta.sma(close, 20)
plot(ma1, "ma1", color.aqua, 6)
plot(ma2, "ma2", color.black, 2)

配列の追加・削除関数

1 , 配列の加算操作に関連する関数:

array.unshift()array.insert()array.push()

2 配列の削除操作に関連する関数:

array.remove()array.shift()array.pop()array.clear()

この数列の加減関数をテストするには,次の例を使用します.

a = array.from("A", "B", "C")
ret = array.unshift(a, "X")
runtime.log("数组a:", a, ", ret:", ret)

ret := array.insert(a, 1, "Y")
runtime.log("数组a:", a, ", ret:", ret)

ret := array.push(a, "D")
runtime.log("数组a:", a, ", ret:", ret)

ret := array.remove(a, 2)
runtime.log("数组a:", a, ", ret:", ret)

ret := array.shift(a)
runtime.log("数组a:", a, ", ret:", ret)

ret := array.pop(a)
runtime.log("数组a:", a, ", ret:", ret)

ret := array.clear(a)
runtime.log("数组a:", a, ", ret:", ret)

runtime.error("stop")

追加・削除のアプリケーション:配列として配列

配列と配列の追加・削除関数を使って”列”のデータ構造を構成できます. 列は,tick価格の移動平均値の計算に使用できます. クラスメイトが尋ねるかもしれません:なぜ配列の構造を構成するのか?

配列は,プログラミングでよく使われる構造であり,配列の特徴は以下の通りである.

列に入ると列から出る.

この方法で,キューブ内のデータが最新のデータであることを確認し,キューブの長さが無限に膨張しないことを確認できます (無限膨張のコードは,昼間のみで書くことができます,なぜなら,早,晩が問題になるからです).

以下の例では,各ティックの価格を記録するキュー構造を用いて,ティックレベルの移動平均値を計算し,1分間のK線レベルの移動平均と比較した.

strategy("test", overlay=true)

varip a = array.new_float(0)
var length = 10

if not barstate.ishistory
    array.push(a, close)

    if array.size(a) > length
        array.shift(a)

sum = 0.0
for [index, ele] in a 
    sum += ele

avgPrice = array.size(a) == length ? sum / length : na

plot(avgPrice, title="avgPrice")
plot(ta.sma(close, length), title="ta.sma")

キーワードを指定します.varip│ │ │ │ │ │ │ │ │ │ │ │ │ │ │

よく使われる数列計算,操作関数

関連関数を計算する:

array.avg()配列の全ての要素の平均値を求めます.array.min()配列の最小の要素を探します.array.max()配列の最大の要素を探してarray.stdev()配列の全ての要素の標準差を求めます.array.sum()配列内のすべての要素の和を求めます.

関連関数操作: array.concat()2つの配列を結合または接続する. array.copy()配列を複製する array.join配列内のすべての要素を 1 つの文字列に接続します. array.sort()順序を順番上り下りして並べます. array.reverse()逆転数列 array.slice()配列を切断する. array.includes()判断の要素 array.indexof()参数入力された値が最初に出現したインデックスを返します. 値が見つからない場合は -1 を返します. array.lastindexof()最後に表示された値を見つけます

配列計算に関連する関数のテスト例:

a = array.from(3, 2, 1, 4, 5, 6, 7, 8, 9)

runtime.log("数组a的算数平均:", array.avg(a))
runtime.log("数组a中的最小元素:", array.min(a))
runtime.log("数组a中的最大元素:", array.max(a))
runtime.log("数组a中的标准差:", array.stdev(a))
runtime.log("数组a的所有元素总和:", array.sum(a))
runtime.error("stop")

これらは,比較的によく使われる数列計算関数である。

関連関数の例:

a = array.from(1, 2, 3, 4, 5, 6)
b = array.from(11, 2, 13, 4, 15, 6)

runtime.log("数组a:", a, ", 数组b:", b)
runtime.log("数组a,数组b连接在一起:", array.concat(a, b))
c = array.copy(b)

runtime.log("复制一个数组b,赋值给变量c,变量c:", c)

runtime.log("使用array.join处理数组c,给每个元素中间增加符号+,连接所有元素结果为字符串:", array.join(c, "+"))
runtime.log("排序数组b,按从小到大顺序,使用参数order.ascending:", array.sort(b, order.ascending))     // array.sort函数修改原数组
runtime.log("排序数组b,按从大到小顺序,使用参数order.descending:", array.sort(b, order.descending))   // array.sort函数修改原数组

runtime.log("数组a:", a, ", 数组b:", b)
array.reverse(a)   // 此函数修改原数组
runtime.log("反转数组a中的所有元素顺序,反转之后数组a为:", a)    

runtime.log("截取数组a,索引0 ~ 索引3,遵循左闭右开区间规则:", array.slice(a, 0, 3))
runtime.log("在数组b中搜索元素11:", array.includes(b, 11))
runtime.log("在数组a中搜索元素100:", array.includes(a, 100))
runtime.log("将数组a和数组b连接,搜索其中第一次出现元素2的索引位置:", array.indexof(array.concat(a, b), 2), " , 参考观察 array.concat(a, b):", array.concat(a, b))
runtime.log("将数组a和数组b连接,搜索其中最后一次出现元素6的索引位置:", array.lastindexof(array.concat(a, b), 6), " , 参考观察 array.concat(a, b):", array.concat(a, b))

runtime.error("stop")

関数

定義された関数

Pine言語は,カスタム関数を設計することができる.一般的には,Pine言語のカスタム関数は以下のルールを持つ.

  1. すべての関数は,スクリプトの全域で定義される. 一つの関数を別の関数で宣言することはできません.
  2. 函数には自前のコードで自らを呼び出すことを許さない. 3 原則としてすべてのPINE言語に内蔵された図形関数 (()barcolor()、 fill()、 hline()、plot()、 plotbar()、 plotcandle()) は,カスタム関数の中で呼び出せない。 4 ,関数は単行または複数行で記述できる.最後の文の返される値は,現在の関数の返される値であり,返される値は元組形式で返される.

単行で設計されたカスタム関数のようなものもあります.

barIsUp() => close > open

この関数は,現在のBARが陽線であるかどうかを返します.

複数の行に指定された関数として設計:

sma(data, length) => 
    i = 0 
    sum = 0 
    while i < 10 
        sum += data[i]
        i += 1
        sum / length

plot(sma(close, length), title="sma", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)

定義された関数で実行した SMA 均線関数です.

また,2つの変数のカスタム関数の例を返します.

twoEMA(data, fastPeriod, slowPeriod) =>
    fast = ta.ema(data, fastPeriod)
    slow = ta.ema(data, slowPeriod)
    [fast, slow]

[ema10, ema20] = twoEMA(close, 10, 20)
plot(ema10, title="ema10", overlay=true)
plot(ema20, title="ema20", overlay=true)

一つの関数は,快線,慢線,二つのEMA均線指標を計算できる.

組み込み関数

任意の関数で定義できます.FMZ PINE 文書検索する

Pine言語の内置関数分類:

1 文字列処理関数str.シリーズ 2 色の値処理関数color.シリーズ 3 参数入力関数input.シリーズ 4 指標計算関数ta.シリーズ グラフ関数plot.シリーズ 6 配列処理関数array.シリーズ 7 取引に関する関数strategy.シリーズ 8 算数関数math.シリーズ 9 ,他の関数 ((時間処理,非プロット系列画図関数,request.シリーズ関数,型処理関数など) 。

トランザクション関数

strategy.シリーズ関数は,設計策略でよく使う関数であり,この関数と策略の具体的実行時に取引操作を実行する関数に関連している.


1、strategy.entry

strategy.entry函数とは,策略を書き込む際により重要な命令関数であり,その関数のより重要な数値は以下の通りである.id, direction, qty, when待って。

パラメータ:

  • id: 特定の取引ポジションに名前を与えることを参照として使用する. このid を引用して,注文を撤回,修正,平仓する.
  • direction: 注文方向が”多めにやる (買おう) “ならこのパラメータが伝わります.strategy.longこの内置変数は,空白の場合は,strategy.shortこの変数は
  • qty: 注文量を指定し,このパラメータを転送しない場合は,デフォルトの注文量となります.
  • when実行条件: このパラメータは,現在の下位操作がトリガーされるかどうかを制御するために指定できます.
  • limit: 指定注文制限価格
  • stopストップ・ロスト・プライス

strategy.entryこの関数の実行詳細はstrategy函数呼び出しのパラメータ設定の制御は,“Pine言語の取引クラスデータベースの模擬版パラメータ”設定制御,Pine言語取引クラスのデータベースモデルのパラメータ制御の取引詳細は,リンクされたドキュメントを参照してください.

この記事では,strategyこの関数では,pyramidingdefault_qty_valueパラメータ: 次のコードでテストします.

/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/

strategy(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true)

ema10 = ta.ema(close, 10)

findOrderIdx(idx) =>
    if strategy.opentrades == 0 
        false 
    else 
        ret = false 
        for i = 0 to strategy.opentrades - 1 
            if strategy.opentrades.entry_id(i) == idx
                ret := true 
                break
        ret 
        

if not findOrderIdx("long1")
    strategy.entry("long1", strategy.long)

if not findOrderIdx("long2")
    strategy.entry("long2", strategy.long, 0.2, when = close > ema10)

if not findOrderIdx("long3")
    strategy.entry("long3", strategy.long, 0.2, limit = low[1])
    strategy.entry("long3", strategy.long, 0.3, limit = low[1])

if not findOrderIdx("long4")
    strategy.entry("long4", strategy.long, 0.2)

plot(ema10, title="ema10", color=color.red)

コード開始/*backtest ... */パッケージの一部は反測設定であり,その時の反測設定時間などの情報を記録するために,デビューを容易にするために,策略コードではありません.

コードで:strategy(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true)指定したときにpyramidingこのパラメータが3なら,同じ方向で最大3回取引をします.strategy.entryこの操作は実行されませんでした.default_qty_valuelong1のIDは,この場合,この関数は0.1です.strategy.entry下の命令操作の下の命令数は,0.1。というデフォルトで設定されています.strategy.entryこの関数は,関数で定義される関数です.direction平均でstrategy.longテストの返信は,すべての注文が支払われるのです.

コードに注意してくださいstrategy.entry("long3", ...下のコマンド操作は,同じID:long3に対して,2回呼び出されます.strategy.entry下の操作は成功せず,第2回呼び出しstrategy.entry関数は,このIDの注文を修正する ((回測テストで表示されるデータも,この限度注文の下の注文量が0.3のために修正されたことを見ることができる).別の場合,例えば,最初のIDがlong3の注文で取引された場合,この取引されたIDlong3に従って使用し続けます.strategy.entry函数が注文すると,その注文のポジションはIDlong3に累積されます.


2、strategy.close

strategy.closeこの関数は,平仓指定のIDの入場保有ポジションに使用されます.主なパラメータは以下のとおりです.idwhenqtyqty_percent

パラメータ:

  • idこのページでは,この2つのグループが,この2つのグループで,strategy.entry入場等下場関数開設時に指定されたID。
  • when実行条件:
  • qty:平仓数
  • qty_percent持株率について.

この関数の使い方については,以下の例で説明します. コードでは/*backtest ... */FMZ.COMの国際ステーションの回測時の設定情報であり,削除し,自分がテストしたい市場,品種,時間範囲などの情報を設定できます.

/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/

strategy("close Demo", pyramiding=3)

var enableStop = false 
if enableStop
    runtime.error("stop")

strategy.entry("long1", strategy.long, 0.2)
if strategy.opentrades >= 3 
    strategy.close("long1")                   // 多个入场订单,不指定qty参数,全部平仓
    // strategy.close()                          // 不指定id参数,会平掉当前的持仓
    // strategy.close("long2")                   // 如果指定一个不存在的id则什么都不操作
    // strategy.close("long1", qty=0.15)         // 指定qty参数平仓
    // strategy.close("long1", qty_percent=50)   // qty_percent设置50即为平掉long1标识仓位的50%持仓
    // strategy.close("long1", qty_percent=80, when=close<open)  // 指定when参数,修改为close>open就不触发了
    enableStop := true

テスト戦略は,入場IDをlong1とする3回連続で多入場を開始し,その後使用することを示した.strategy.close函数の異なるパラメータを平仓に設定したときに反測される異なる結果が見られます.strategy.closeこの関数は,平仓の下位注文価格を指定するパラメータがありません.この関数は,主に,即座に現在の市場価格で平仓するために使用されます.


3、strategy.close_all

strategy.close_allこの関数は,現在所有しているすべてのポジションを平らにするため,Pine言語のスクリプトはポジションを1つの方向しか持たないため,つまり,現在のポジションの方向と逆の信号がトリガーされれば,現在のポジションを平らにして,信号に基づいてポジションを開く.strategy.close_all呼び出されると,現在の方向にあるすべてのポジションをクリアする.strategy.close_allこの関数の主要パラメータは:when

パラメータ:

  • when実行条件:

この例を参考にしましょう.

/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/

strategy("closeAll Demo")

var enableStop = false 
if enableStop
    runtime.error("stop")

strategy.entry("long", strategy.long, 0.2, when=strategy.position_size==0 and close>open)
strategy.entry("short", strategy.short, 0.3, when=strategy.position_size>0 and close<open)

if strategy.position_size < 0 
    strategy.close_all()
    enableStop := true 

テストコードは0でスタートします.strategy.position_size==0true) であるため,whenパラメータの設定条件を満たす場合のみ,IDをlongとして実行します.strategy.entry入場関数。多ポジション後strategy.position_size0 以上の場合,ID が short の入場関数として実行される可能性があります.このとき,多頭ポジションの位置が保持されているため,この空白反転信号が発生し,多頭ポジションの位置が平らになった後に空白を反転させます.strategy.position_size < 0持った空頭持ったとき,現在の持った方向の持った全額を平らにする. そして,マークenableStop := true≫ ≫ ≫ ≫ ≫ ≫

発見しましたstrategy.close_allこの関数は,平仓の下位注文価格を指定するパラメータがありません.この関数は,主に,即座に現在の市場価格で平仓するために使用されます.


4、strategy.exit

strategy.exitこの関数は,入場保有の平仓操作に使用され,この関数とは異なり,strategy.closeそしてstrategy.close_allこの関数は,現在の市場価格で即座に平仓する.strategy.exit関数は,パラメータ設定に基づいて計画平仓を行う.

パラメータ:

  • id: この平仓条件の注文ID.
  • from_entry: 平仓操作を指定するための入口ID。
  • qty:平仓数
  • qty_percent:平仓パーセント,範囲:0~100。
  • profit収益目標はポイントで表されます.
  • lossポイント数で表す.
  • limit収益目標,価格指定について
  • stopストップ・ロズ・ターゲットは,価格で指定する.
  • when実行条件:

各パラメータの使用を理解するためにテスト戦略を使用します.

/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
args: [["RunMode",1,358374],["ZPrecision",0,358374]]
*/

strategy("strategy.exit Demo", pyramiding=3)

varip isExit = false 

findOrderIdx(idx) =>
    ret = -1 
    if strategy.opentrades == 0 
        ret
    else 
        for i = 0 to strategy.opentrades - 1 
            if strategy.opentrades.entry_id(i) == idx
                ret := i 
                break
        ret

strategy.entry("long1", strategy.long, 0.1, limit=1, when=findOrderIdx("long1") < 0)
strategy.entry("long2", strategy.long, 0.2, when=findOrderIdx("long2") < 0)
strategy.entry("long3", strategy.long, 0.3, when=findOrderIdx("long3") < 0)

if not isExit and strategy.opentrades > 0
    // strategy.exit("exitAll")          // 如果仅仅指定一个id参数,则该退场订单无效,参数profit, limit, loss, stop等出场条件也至少需要设置一个,否则也无效
    strategy.exit("exit1", "long1", profit=50)                    // 由于long1入场订单没有成交,因此ID为exit1的出场订单也处于暂待状态,直到对应的入场订单成交才会放置exit1
    strategy.exit("exit2", "long2", qty=0.1, profit=100)          // 指定参数qty,平掉ID为long2的持仓中0.1个持仓
    strategy.exit("exit3", "long3", qty_percent=50, limit=strategy.opentrades.entry_price(findOrderIdx("long3")) + 1000)   // 指定参数qty_percent,平掉ID为long3的持仓中50%的持仓
    isExit := true 

if bar_index == 0 
    runtime.log("每点价格为:", syminfo.mintick)    // 每点价格和Pine语言模板参数上「定价货币精度」参数设置有关

リアルタイム価格モデルの反響テストを使用して,このテスト戦略は,3つの入場操作を実行し始めます.strategy.entry函数), long1 を意図的に設定したlimitパラメータは,掛札価格が1で,取引を不可能にします. そして,条件出場関数テストstrategy.exit┃ ポイント数ストップ,価格ストップ,平定定量ポジション,平定比率ストップを使用。 ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃