クロスの章では、平均がクロスした位置に指標で印を描きました。今度は同じイベントから、シミュレーションの注文を出します。上抜けで買いポジションを開き、下抜けで決済します。

ストラテジーがすること

指標は計算と表示を行います。ストラテジーはそれに加え、バックテストのシミュレーターへ注文を出します。シミュレーターは、過去のローソク足と指定したルールに従い、注文、ポジション、損益を追跡します。

この過去データでの検証をバックテストと呼びます。この章の注文はすべてシミュレーションです。Run Pyne codeを実行しても、実際の取引口座に注文は出しません。

ポジションは、エントリーが約定した後に保有している建玉です。注文は指示であり、約定はポジションを作ったり変えたりする出来事です。この3つは区別して使います。

先にルールを文章にする

今回のルールは次のとおりです。

  • 各ローソク足で長さ5と20のSMAを求める。
  • 上抜けで、1単位のロングポジションのエントリー注文を出す。
  • 下抜けで、Longというエントリーに対応するポジションを決済する。
  • 計算には、確定済みの過去のローソク足を使う。

ロングは、価格が上がると価値が増え、下がると減るポジションです。この例ではショートは開きません。

すべての上抜けが利益になるというルールではありません。この操作を指定したデータで行ったらどうなったかを調べるのが、バックテストです。

プログラム全体

crossover_strategy.pyを作ります。

"""
@pyne edge
"""
from pynecore.lib import close, color, input, plot, script, strategy, ta


@script.strategy(
    "Average Crossing Strategy",
    overlay=True,
    initial_capital=10000,
    default_qty_type=strategy.fixed,
    default_qty_value=1,
    pyramiding=1,
)
def main(
    fast_length: int = input.int(5, title="Fast length", minval=1, maxval=200),
    slow_length: int = input.int(20, title="Slow length", minval=1, maxval=200),
):
    fast_average = ta.sma(close, fast_length)
    slow_average = ta.sma(close, slow_length)
    crosses_up = ta.crossover(fast_average, slow_average)
    crosses_down = ta.crossunder(fast_average, slow_average)
    if crosses_up:
        strategy.entry("Long", strategy.long)
    if crosses_down:
        strategy.close("Long")
    plot(fast_average, "Fast average", color=color.blue, linewidth=2)
    plot(slow_average, "Slow average", color=color.orange, linewidth=2)

@script.strategyは、main()がストラテジーであることを指定します。計算と2本の線はそのまま使えます。新しくインポートするstrategyには、注文操作やストラテジーのデータがあります。

デコレーターの呼び出しは複数行です。こちらの設定がストラテジーの実行を定め、main()のパラメーターは自分の計算の入力です。

初期資金と数量

initial_capital=10000は、シミュレーションの開始残高です。単位や価格水準は、デモデータに付属する市場メタデータに従います。

default_qty_type=strategy.fixedは固定数量です。default_qty_value=1で1単位を注文します。資金の1%でも、必ず1通貨単位というわけでもありません。

pyramiding=1は、同方向のエントリーを最大1つに制限します。この例では、すでにあるポジションにロングを追加しません。

学習では小さな固定数量を使い、操作を追います。数量計算の違いを同時にいくつも考えずに、結果の変化を調べられます。

エントリーと決済の名前

strategy.entry("Long", strategy.long)の最初の引数は注文IDです。Longという文字列はプログラムで決めた名前で、方向は2つ目の引数が指定します。

strategy.close("Long")は、同じIDを参照します。名前は一致させます。"Buy"でエントリーした場合、"Long"の決済はそのエントリーを対象にしません。

ここでの下抜けは決済であり、ショートのエントリーではありません。その名前のポジションがなければ、決済するものもありません。

PyneIDEで実行する

  1. プログラム全体を保存します。
  2. Run Pyne codeでdemoを選びます。
  3. 2本のSMAと取引マーカーを確認します。
  4. チャート下のパネルを開き、Tradesタブを選びます。
crossover_strategy.pyの横に2本のSMAと、ストラテジーのエントリーおよび決済マーカーが表示されている。
SMAのクロスで注文を出し、約定した取引はチャートにも表示されます。

取引がない場合は、ストラテジーのファイルを実行したか、@script.strategyが残っているか確認してください。2つの入力の実際の値も確認します。同じデータから同じ長さで計算するSMA同士は、クロスしません。

シグナルと約定の時点

ここで使う既定設定では、足の終値データから成行注文を出します。通常、次の足の始値で約定します。そのため、シグナルの足とエントリーの足が異なる場合があります。

成行決済も同じです。下抜けで出した決済注文が、次の始値でポジションを閉じます。

最後の足で注文しても、ファイルには次の足がありません。約定しない場合があります。また、前に開いたポジションが最後まで残る場合もあります。

約定方法は設定の一部です。次の章ではPropertiesでも確認します。結果は常に、その実行で使った約定方法と合わせて読み取ってください。

自分で試す

ストラテジーの入力を開き、短期と長期を両方20にします。2本の線の位置関係と、クロスによる取引が何回あるかを予想してください。

解答

同じ価格と同じウィンドウを使うため、SMAは一致します。一方が他方を上抜け、下抜けする足はありません。このルールからはエントリーしません。

入力を保存し、再計算が完了して初めて、チャートがその結果を示します。確認後は5と20に戻してください。

エントリーを1つ選ぶ

約定したエントリーを探し、前の足の2つの平均を調べます。上抜けはシグナルの足で起きているはずです。取引価格は、シグナルの終値だと思い込まず、エントリーした足の始値と比較してください。