# システムの書き方

トップ > システムの書き方

ここではPtSimで実行できるシステムをProtra言語で記述する方法を説明します。

## システムの置き場所

PtSimはsystemディレクトリ以下に置かれた、拡張子.ptのファイルをシステムとして認識します。systemディレクトリ以下にプログラムを置くと、自動的にシステムの一覧に追加されます。

## 実行の仕組み

システムとして記述するのは、基本的に1銘柄の1日分の処理だけです。PtSimは銘柄リストに含まれる銘柄ごとに、その銘柄の株価データの一番古い日付から最新のものまで、銘柄と日付を指定してプログラムを繰り返し実行します。

グローバル変数の値は日付をまたいで引き継がれますが、銘柄の間では引き継がれません。プログラムが指示した売買は実行履歴に記録されて、これを利用してシステムの成績計算や履歴表示が行われます。

1度実行してから株価データを更新して再度実行すると、銘柄リストに含まれる銘柄ごとに、更新されたデータについて実行が再開されます。グローバル変数の値は前回の実行から引き継がれます。実行履歴を削除すると、前回実行した日付とグローバル変数の値も削除されます。

## サンプルプログラム

以下のサンプルプログラムは、1000円以下になったら1000株買って2000円以上になったら1000株売ります。

    if !$hold && Close < 1000
        $hold = 1000
        Buy(Close, $hold)
    elsif $hold && Close > 2000
        Sell(Close, $hold)
        $hold = 0
    end

Closeは終値を返す組み込み関数です。対象となる銘柄と日付はPtSimが暗黙的に指定します。BuyとSellは売買を指示する組み込み関数です。実行すると実行履歴に売買が記録されます。組み込み関数については後述の組み込み関数を参照してください。最初の引数が価格で2番目の引数が数量です。$holdはグローバル変数で保有株数を保持します。

## 銘柄を横断するシステム

前述したとおり、システムはPtSimによって銘柄ごとに実行されます。グローバル変数の値は銘柄をまたいで引き継がれません。そのため、複数の銘柄で同日に発生したシグナルから、実際にエントリーするものを選ぶシステムや、すべての銘柄の投資額を計算して予算を超えていたらエントリーしないシステムを、普通の方法では記述できません。

しかしかなり難解になりますが、銘柄を横断して情報を共有するシステムを記述する方法も提供しています。以下がその例で、先のサンプルプログラムに予算の上限を付けたものです。

    # loop-type: date-only
    len = Length(CodeList) # 銘柄リストの長さ
    if !$hold
        $hold = [len]
        $budget = 10000000 # 投資総額
    end

    def Main(i)
        if Index == null # まだ上場していない場合
            return
        end
        consid = Close * 1000
        if !$hold[i] && Close < 1000 && consid <= $budget
            $hold[i] = 1000
            Buy(Close, $hold[i])
            $budget = $budget - consid
        elsif $hold[i] && Close > 2000
            Sell(Close, $hold[i])
            $budget = $budget - consid
            $hold[i] = 0
        end
    end

    i = 0
    while i < len
        {CodeList[i]}Main(i) # 文字列型at作用素で証券コードを与える。
        i = i + 1
    end

通常の実行方法ではPtSimは銘柄ごとにシステムの実行を繰り返しますが、1行目のコメントはこれを抑制します。このコメントは必ず1行目に書かなければなりません。このコメントを書くと、PtSimは保有しているすべての株価データのうち、一番古い日付から最新の日付まで一度だけシステムを実行します。

銘柄ごとに繰り返し実行するのはシステム自身で行います。実行時に指定された銘柄リストの内容は、組み込み関数CodeListで取得できます。組み込み関数の対象となる銘柄は、文字列型@作用素で指定します。組み込み関数の詳細は後述の組み込み関数を参照してください。銘柄ごとにグローバル変数の値を保持するのもシステム自身で行います。これは上の例のように配列を使って行います。

## 成績計算

PtSimは実行履歴に記録された売買を元に成績計算を行います。成績計算では銘柄ごとにポジションを調べて、スクエアからポジションが生じたときと、ドテンしてポジションが反転したときをトレードの開始と見なします。そしてポジションをクローズしたときと、やはりドテンをトレードの終了と見なします。

買い増したり一部売却したりするトレードでは、ポジションを取ってからクローズするかドテンするまでの一連の売買を、一つのトレードとして扱います。トレードの成績は、トレード開始から終了までの買い注文の総金額と売り注文の総金額を元に計算します。

成績計算の都合上、同一銘柄を同一日に一回しか売買できません。二回目のBuyやSellの実行はエラーになります。ドテンするときはポジションのクローズと反対売買を1回のBuyかSellにまとめてください。つまりドテン売りは保有株式の売却と空売りを1回のSellで、ドテン買いは空売りの返済と買いを1回のBuyで行ってください。具体例は添付のMA Cross Dotenシステムを参照してください。

成績計算のサマリーに表示される最大ポジションは、ショートとロングの合計で計算しています。必要資金は簿価のポジションが最大のときの簿価の利益との差です。ショートの場合の必要資金は委託保証金率に基づいて行う必要がありますが、そういう計算をしていないのでショートするシステムの必要資金の値は意味がありません。