# Protra言語の文法

トップ > Protra言語の文法

Protraではチャートの描画方法とトレーディングシステムの売買ルールの記述に、独自のプログラミング言語であるProtra言語を使用します。

## プログラムの構成

Protra言語のプログラムは文を並べたものです。文と文の間は`;`または改行で区切ります。ただし、`\`または`_`に続く改行は無視されます。また、行の`#`か`//`より後ろは無視されます。

文は式や制御文や関数定義からなります。式は定数、変数、関数呼び出し、配列の生成、配列の参照、@作用素と、これらを演算子で組み合わせたものです。

libディレクトリ以下に置かれたライブラリを読み込むときには、`require "`ライブラリ名`"`を用います。ライブラリ名はライブラリのファイル名から拡張子.ptを除いたものです。

## データ型

Protra言語で扱う型はint, float, string, null, 配列の5種類です。intは32bit符号付き整数、floatは倍精度浮動小数点、stringはShift_JISの文字列型、nullは空値`null`のみの型、配列は任意の型の値を格納可能な1次元の配列の参照型です。

## リテラル

プログラム中で各型の値を表すための記法(リテラル)は以下の通りです。文字列型のリテラルに日本語を用いる際にはShift_JISを使ってください。配列型のリテラルはありません。

int | 0 | 12 | 123
float | 0.0 | 12.0 | 12.345
string | "program"
null | null

## 変数

変数には任意の型の値を代入できます。変数にはグローバル変数とローカル変数があります。グローバル変数は$から始まる名前でなければなりません。ローカル変数は小文字のアルファベットから始まる名前でなければなりません。以下に例を挙げます。

グローバル変数 | $global | $Global | $g_val
ローカル変数 | local | local2 | l_val

関数の中でローカル変数に値を代入すると、その値は関数の中だけで参照できます。関数の外でローカル変数に代入した場合は、その値は関数の外でだけ参照できます。一度も代入していないローカル変数を参照するとエラーになります。グローバル変数の値はプログラムのどこからでも参照できます。一度も代入していないグローバル変数を参照するとnullが返ります。

## 演算子

演算子は基本的にC言語やJavaと同じです。+=などの複合代入演算子や++や--は使えません。ビット演算子も使えません。floatとintの間の演算結果は常にfloatになります。stringの加算は結合した文字列を返します。stringと数値の加算は、数値を文字列に変換して結合したものを返します。

int、float、stringについてキャスト演算子が使えます。floatからintへキャストすると小数点以下は切り捨てられます。intやfloatをstringにキャストすると文字列に変換されます。stringからintやfloatにキャストすると数値へ変換され、変換に失敗すると0か0.0になります。nullと配列はキャストできません。

## 論理値

0、0.0、nullは偽、その他はすべて真として扱われます。

## 制御文

繰り返しや条件分岐を表現するためにwhile文とif文が使えます。

### while文

while文は以下のように記述します。条件式が真である間、処理が繰り返し実行されます。処理には関数定義以外の文を書けます。複数の文を記述するときは、改行か`;`で区切ります。

    while 条件式
        処理
    end

while文の処理の中に、繰り返しを制御するbreak文とcontinue文を書けます。while文はbreakを実行したときに、残りの処理を実行せずに繰り返しを中断します。continueを実行したときには、残りの処理を実行せずに繰り返しの条件判定に移ります。

### if文

if文は以下のように記述します。各処理には関数定義以外の文を書けます。

    if 条件式1
        処理1
    elsif 条件式2
        処理2
    else
        処理3
    end

1. 条件式1が真ならば処理1のみが実行される。
2. 条件式1が偽のとき条件式2が真ならば処理2のみが実行される。
3. 条件式1が偽のとき条件式2が偽ならば処理3のみが実行される。

以上のような動作をします。ただし、elseは省略できます。elsifはいくつでも追加できますし、省略することもできます。

## 配列

配列は以下のように生成します。指定した要素数の配列が生成されて配列型の値が返ります。生成された配列のすべての要素はnullです。

    [要素数]

配列の要素を参照するには以下のようにします。int型の式の値は0〜要素数-1でなければなりません。この範囲外の値を指定するとエラーになります。

    配列型の式[int型の式]

例として100個の要素を用意して、1から100を順に代入するプログラムを示します。

    arr = [100]
    i = 0
    while i < 100
        arr[i] = i + 1
        i = i + 1
    end

配列の長さを求めるときは組み込み関数Lengthを用います。上のプログラムはLengthを使って以下のように書けます。

    arr = [100]
    i = 0
    while i < Length(arr)
        arr[i] = i + 1
        i = i + 1
    end

データ型で述べたように配列は参照型です。つまり以下のように、ある変数から別の変数へ配列型の値を代入したときには、配列はコピーされずに2つの変数が同じ配列を指します。

    arr1 = [100]
    arr2 = arr1
    arr1[0] = 10    ←arr2[0]も10になる
    arr2[1] = 20    ←arr1[1]も20になる

配列の要素に配列型の値を代入することもできるので、これを利用すると多次元の配列を作れます。

    arr1 = [2]
    arr1[0] = [100]
    arr1[1] = [100]
    arr1[0][10] = 100
    arr1[1][20] = 200

## 関数

関数の定義は以下のように記述します。処理には関数定義以外の1つ以上の文を書けます。関数名の最初は大文字のアルファベットでなければなりません。同じ名前で引数の数が異なる関数を定義できます。引数がない場合は()を省略できます。

    def 関数名(仮引数1, 仮引数2, ...)
        処理
    end

関数の返す値はreturn文で指定します。return文が実行されると、関数は処理を中断して式の値を返します。return文の式を省略すると関数はnullを返します。処理にreturn文がない場合は関数はnullを返します

    return 式

関数呼び出しは以下のように行います。引数がない関数は()を省略して関数名だけで呼ぶこともできます。

    関数名(実引数1, 実引数2, ...)

以下のサンプルプログラムでは、1から100までの和を計算する関数Sum100を定義して、Sum100を呼び返値をローカルを変数sumに代入しています。

    def Sum100
        i = 1
        sum = 0
        while i <= 100
            sum = sum + i
            i = i + 1
        end
        return sum
    end
    sum = Sum100

以下のサンプルプログラムでは、1からnまでの和を計算する関数Sumを定義して、引数に100を指定してSumを呼び出してローカル変数sumに代入しています。

    def Sum(n)
        i = 1
        sum = 0
        while i <= n
            sum = sum + i
            i = i + 1
        end
        return sum
    end
    sum = Sum(100)

## @作用素

後述する株価の終値を返すCloseなどの組み込み関数には、日付や銘柄を指定する引数がありません。銘柄や日付はProtraかPtSimによって暗黙的に指定されます。これを変更するためには@作用素を使います。

### int型@作用素

int型@作用素は、以下のようにint型の式を{}で囲って式に対して指定します。対象の式に組み込み関数があると、組み込み関数の対象の日付が指定した値の営業日だけ前後にずれます。

    {int型の式}対象の式

以下の例では前営業日の株価の終値を取得できます。

    {-1}Close

int型@作用素は式全体に作用し、関数呼び出しの中にも波及します。また、int型@作用素を指定した式でint型@作用素を使用すると、作用素の値が加算されます。

たとえば、当日を含む3営業日の終値を平均する関数を以下のように定義します。

    def AverageClose
        return (Close + {-1}Close + {-2}Close) / 3
    end

以下のように、この関数に-3のint型@作用素を与えると、3営業日前から5営業日前までの3営業日の終値の平均が求まります。この機能は、テクニカル指標を求める関数を定義したり、それを利用したりする際に役立ちます。

    {-3}AverageClose

ユーザーが定義した関数には、定義された引数のほかにatという引数があります。この引数の値は通常は0ですが、int型@作用素が指定されるとその値が入ります。これを利用すると、int型@作用素の値で動作の変わる関数を記述できます。

以下の例のSum100は、int型@作用素の指定がないと1～100までの合計を計算しますが、int型@作用素で100を指定すると101～200までの合計を計算します。

    def Sum100
        i = 1 + at
        sum = 0
        while i <= 100 + at
            sum = sum + i
            i = i + 1
        end
        return sum
    end
    sum = {100}Sum100

### string型@作用素

string型@作用素は、以下のようにstring型の式を{}で囲って式に対して指定します。対象の式に組み込み関数があると、組み込み関数の対象となる銘柄が値で指定した証券コードの銘柄になります。

    {文字列型の式}対象の式

以下の例では日経平均の終値を取得できます。1001はProtraが日経平均に割り当てた仮の証券コードです。

    {"1001"}Close

string型@作用素も式全体に作用するので、関数呼び出しの中にも波及します。string型@作用素を指定した式でstring型@作用素を使用すると、あとに指定したものが優先されます。

先に定義したAverageCloseにstring型@作用素で"1001"を指定して呼び出すと、日経平均の当日を含む3営業日の終値の平均が求まります。

    {"1001"}AverageClose

int型@作用素を併用して-3も指定すると、3営業日前から5営業日前までの日経平均の終値の平均が求まります。@作用素の順序はどちらが先でもかまいません。

    {-3}{"1001"}AverageClose