ストラテジー

From TradingView Wiki
Jump to: navigation, search
Language: English  • 日本語 • 한국어 • Русский

ストラテジーとは、買い注文や売り注文を実行、変更、キャンセルできるスタディ(インジケーター)です。ストラテジーでは、コーディングされたアルゴリズムに従って、バックテスト (過去データでのストラテジーテスト)や フォワードテスト (リアルタイムデータでのストラテジーテスト) を実行することができます。

ストラテジーはPineスクリプトで書かれ、Pineインジケータと同じ機能を備えています。ストラテジーのコードを書くときは、 " study " ではなく " strategy " キーワードから始める必要があります。ストラテジーはチャートへの描画だけでなく、注文の実行、変更、キャンセルができます。特定のキーワードでストラテジーのパフォーマンス情報にアクセスできます。同じ情報が [投資戦略テスター] タブからも利用できます。過去データでストラテジーを実行すれば、どのように注文が実行される可能性があったかを確認できます。

シンプルなストラテジーの例

//@version=2
strategy("test")
if n>4000
    strategy.entry("buy", strategy.long, 10, when=strategy.position_size <= 0)
    strategy.entry("sell", strategy.short, 10, when=strategy.position_size > 0)
plot(strategy.equity)

スクリプトがコンパイルされてチャートに適用されるとすぐに、 オーダー情報やバックテスト中に残高がどのように変化したか(エクイティカーブ)を見ることができます。このストラテジーはすべてのバーで買い注文と売り注文を実行するシンプルな例です。

最初の行 strategy(“test”) でコードがストラテジーである事を宣言しています。ストラテジーの名前は “test”です。 strategy.entry() は買い注文や売り注文を実行するコマンドです。plot(strategy.equity) でエクイティカーブを描画します。

ストラテジーをチャートに追加する方法

ストラテジーをテストする場合、チャートにストラテジーを追加します。テストを実行したい銘柄とタイムフレームを選択します。ストラテジーには、Pineスクリプトで書いた自作のストラテジー、または [インジケーター]の検索画面から内蔵のビルトインストラテジーを利用することができます。

Strategy tester.png

注意事項: (練行足, カギ足, ラインブレイク(新値足), ポイント&フィギュア, 平均足, スプレッドチャート(ペアチャート)) の様な非標準のチャートを利用すると、ストラテジーの結果が異なることがあります。これは注文がそのチャートの価格で実行される為です(例えば平均足の場合、実際の市場価格ではなく平均足の価格が使用されます)。ですからストラテジーには(ローソク足の様な)通常のタイプのチャートを利用することを強く推奨します。

バックテストとフォワードテスト

TradingViewのストラテジーは、チャート上の利用可能なすべての過去データで計算されます。またリアルタイムデータが追加されると自動的に計算が続行されます。

デフォルトでは、過去データとリアルタイムデータのどちらも終値で計算されます。

フォワードテストの場合、リアルタイムにすべてのティックで計算することができます。これを有効にするには、設定で「ティック毎に再計算」にチェックを付けます。もしくはストラテジーのコードにこの記述を追加します: strategy(..., calc_on_every_tick=true, ...)

注文の約定後、追加計算を実行することができます。これを行うには、設定で「注文約定後に再計算」にチェックをいれるか、コードにこちらの記述を追加します: strategy(…, calc_on_order_fills=true, ...)

ブローカーエミュレーター

TradingViewには、ストラテジーをテストできるブローカーエミュレーターがあります。エミュレーターは実際のトレードとは異なりチャート価格だけで約定されます。これはフォワードテストでは次のティックで約定し、バックテストでは次のバー(またはそれ以降)で約定されるという意味です。

上記の通り、バックテストではバーの終値でストラテジーが処理されます。約定のエミュレートには、次のロジックが使用されます。

  1. バーの開始価格が同じバーの高値に近い場合、ブローカーエミュレーターはイントラバーの価格が、始値→高値→安値→終値の流れで推移したと想定します。
  2. バーの開始価格が同じバーの安値に近い場合、ブローカーエミュレーターはイントラバーの価格が、始値→安値→高値→終値の流れで推移したと想定します。
  3. ブローカーエミュレーターは、バーの中にギャップが無い事を想定しています。これはイントラバーのどの価格(たとえギャップで実際には存在しない価格)でも注文が実行可能である事を意味します。
  4. ストラテジーのプロパティにある “ティックごとに再計算”にチェックを付けた場合(もしくはストラテジーのコードでこの記述を追加している場合 strategy(..., calc_on_every_tick=true, ...))でも、ストラテジーは上記のロジックに従い、終値のみで処理されます。

Filled stategy.png

こちらはブローカーエミュレーターで注文がどのように約定されるかを示すストラテジーです。

strategy("History SAW demo", overlay=true, pyramiding=100, calc_on_order_fills=true)
strategy.entry("LE", strategy.long)

このコードは、デフォルトでは1つのバーの終値で1度処理されます。しかし約定するとすぐに追加処理が行われます。その為すべてのバーには4つの約定があります: 2つの注文は始値、1つは高値、もう1つは安値です。なおこれはバックテストです。リアルタイムの場合注文は毎回新しいティックで実行されます。

指値注文の様な注文を待つケースもエミュレートできます。この設定は「指値の価格確認」と呼ばれ、ストラテジーのプロパティにあります。もしくはスクリプト自体で次の様に設定することができます strategy(... backtest_fill_limits_assumption=X, ...) 。設定は(最小価格変動)のPoints/Pipsを指定します、デフォルト値は0です。現在の価格が、設定したPoints/Pipsよりも良い条件(売り注文の場合はより高い価格、買い注文の場合はより低い価格)であれば指値注文が約定されます。しかしこの場合、約定価格は指値価格と一致します。


例:

backtest_fill_limits_assumption = 1. Minimum price movement(最小価格変動) = 0.25.

指値買い注文は価格12.50に置かれます。

現在の価格は12.50です

注文は現在値では約定されません。これは backtest_fill_limits_assumption = 1 である為です。約定する為には、価格が 0.25*1 低くなる必要があります。注文はキューに入れられます。

次のティックで価格が12.00になったと考えてください。これは2ポイント低い価格であり、条件“backtest_fill_limits_assumption = 1”が満たされます。ですから注文が約定します。しかしこの時たとえ価格が既に有効でなくても、注文は(元の注文価格)の12.50で約定されます。

注文コマンド

すべてのストラテジー用コマンドは、prefix "strategy" で始まります。次のコマンドは、発注に使用されます。 strategy.entrystrategy.orderstrategy.exit

  • strategy.entry — このコマンドはエントリー注文だけを発注します。(ストラテジーの設定)の「ピラミッディング」の設定や キーワード strategy.risk.allow_entry_in の影響を受けます。マーケットポジションがある状態で、反対方向の注文を行う時、現在オープン中のポジション数(スクリプトでは strategy.position_size + quantity)により contracts/shares/lots/units の数は増加します。結果、オープンするポジションサイズは、コマンド strategy.entry で指定されたオーダーサイズと等しくなります。
  • strategy.order — このコマンドは、エントリー注文とエグジット注文の双方を発注します。ピラミッディングの設定やキーワード strategy.risk.allow_entry_in の影響は受けません。strategy.entrystrategy.exit の機能で不足する場合に、このコマンドで複雑なエントリー注文とエグジット注文構造を作成できます。
  • strategy.exit — このコマンドは1つもしくは複数のエグジット注文(損切り、利益確定、トレーリングストップ)を作成してマーケットポジションを閉じることができます。それらすべての注文は、strategy.oca.reduce と同じグループの一部です。ポジションが無いか、または有効なエントリー注文が無ければ、エグジット注文は発注できません(エグジット注文は、エントリー注文のIDに結び付けられます)。strategy.exit コマンドでは成行注文は行えません。成行注文でポジションを閉じる場合には strategy.closestrategy.close_all を利用します。もし strategy.exit で指定された contracts/shares/lots/units の数が、現在のオープンしているポジションのサイズより少ない場合は、部分的に閉じられます。同じIDのエグジット注文で、同じエントリー注文を複数回閉じることはできません。複数レベルでのエグジットを作成できます。複数のエントリー注文(ピラミッディング)でポジションが構築された場合、それぞれのエグジット注文は各エントリー注文に個別に結び付けられます。

例1:

//@version=2
strategy("revers demo")
if n > 4000
    strategy.entry("buy", strategy.long, 4, when=strategy.position_size <= 0)
    strategy.entry("sell", strategy.short, 6, when=strategy.position_size > 0)
plot(strategy.equity)

上記のストラテジーは、描画で示されるように、常にマーケットポジションを行ったり来たり、+4 (Long) から -6 (Short) にドテンさせます。

例2:

strategy("exit once demo")
strategy.entry("buy", strategy.long, 4, when=strategy.position_size <= 0)
strategy.exit("bracket", "buy",  2, profit=10, stop=10)

このストラテジーは、マーケットポジションが開いていれば、1度だけエグジット注文を行い、ポジションを部分的に閉じる例です。もしエグジットの行を複数書いた場合、ポジションは完全に閉じられます。

例3:

//@version=2
strategy("Partial exit demo")
if n > 4000
    strategy.entry("buy", strategy.long, 4, when=strategy.position_size <= 0)
strategy.exit("bracket1", "buy",  2, profit=10, stop=10)
strategy.exit("bracket2", "buy",  profit=20, stop=20)

このコードでは2段階のエグジット処理(2つの利益確定/損切り注文)を行います。2段階のエグジットレベルは同時に有効になります。最初のレベルでは2つのポジションを閉じ、次のレベルでは残りすべてのポジションを閉じます。

Levels brackets.png

最初の利益確定/損切り注文(レベル1)がひとつのOCAグループに属します。残りの注文(レベル2)は別のOCAグループに属します。これはレベル1の注文が約定されても、レベル2の注文はキャンセルされずそのまま有効のままという事を意味します。

注文を行うすべてのコマンドには、一意の注文識別子として ID(文字列)が必要です。既に同じIDの注文が(約定はされていない状態で)発注されている場合、現在のコマンドは既存の注文を変更します。もし(買いを売りにドテンするなど)変更ができない場合は、古い注文はキャンセルされ、新しい注文が発注されます。strategy.entrystrategy.order は同じIDで動作します(同じエントリー注文を変更可能)。strategy.exit は別のIDで動作します(エントリー注文とエグジット注文で同じIDを持つことは可能)。

特定の注文を(IDで)キャンセルするにはコマンド strategy.cancel(string id) を用います。全ての待ち注文をキャンセルするにはコマンド strategy.cancel_all() を利用します。

ストラテジーの注文は、条件が満たされ、コードでコマンドが呼び出されると、すぐに発注されます。ブローカーエミュレーターではコードが計算された後、次のティックが来る前までは注文が約定しませんが、実際のブローカーとのライブトレードでは、注文はすぐに約定されます。これは成行注文が現在のバーの終値で作成された場合、次のバーの始値で約定されることを意味します。

例:

//@version=2
strategy("next bar open execution demo")
if n > 4000
    strategy.order("buy", strategy.long, when=strategy.position_size == 0)
    strategy.order("sell", strategy.short, when=strategy.position_size != 0)

このコードをチャートに適用すると、各バーの始値ですべての注文が約定されます。

スクリプトが計算される時に、オーダー発注の条件 (when, pyramiding, strategy.risk) がチェックされます。すべての条件が満たされると注文が発注されます。もし何らかの条件が満たされない場合、注文は発注されません。これは指値/逆指値注文 (limit, stop, stop-limit) のキャンセルに重要です。

例(MSFT 日足):

//@version=2
strategy("Priced Entry demo")
c = year > 2014 ? nz(c[1]) + 1 : 0
if c == 1
    strategy.entry("LE1", strategy.long, 2, stop = high + 35 * syminfo.mintick)
    strategy.entry("LE2", strategy.long, 2, stop = high + 2 * syminfo.mintick)

ピラミッディングが無効かに関わらず、ロングポジションが無ければ、バックテストではこれら2つの注文は約定されます。2つの注文が出され、どちらかの価格が満たされると、2つの注文が共に約定されます。strategy.oca.cancel を使って、1つの OCA グループで注文を出す事をオススメします。この場合どちらか一つの注文が約定されると、残りの注文はキャンセルされます。

//@version=2
strategy("Priced Entry demo")
c = year > 2014 ? nz(c[1]) + 1 : 0
if c == 1
    strategy.entry("LE1", strategy.long, 2, stop = high + 35 * syminfo.mintick, oca_type = strategy.oca.cancel, oca_name = "LE")
    strategy.entry("LE2", strategy.long, 2, stop = high + 2 * syminfo.mintick, oca_type = strategy.oca.cancel, oca_name = "LE")

コマンドが実行された時に、もし何らかの理由で注文条件が満たされない場合、エントリー注文は発注されません。例えば、既存の2つのポジションがある状態で、ピラミッディングの設定で2を設定すると、ストラテジーは3つ目の注文を出そうと試みますが、それは発注されません。全ての条件は、約定段階ではなく注文作成段階で評価されます。したがってピラミッディングを無効にして、2つの指値/逆指値注文のエントリーを発注する場合、一旦それらのひとつが約定しても、もうひとつは自動的にキャンセルされません。この問題を防ぐ為に、エントリー注文に、OCA-Cancel グループを利用することをオススメします。そうすれば、どちらかひとつの注文が約定された時に、残りの注文は自動的にキャンセルされます。

これはエグジット注文でも同様です。条件が満たされると注文が行われます(つまりそれぞれのIDを持つエントリオーダーが約定する)。

例:

strategy("order place demo")
counter = nz(counter[1]) + 1
strategy.exit("bracket", "buy", profit=10, stop=10, when = counter == 1)
strategy.entry("buy", strategy.long, when=counter > 2)

この例をチャートに適用すると、エグジット注文はエントリオーダーの前に一度だけ生成されたにもかかわらず、エグジット注文が約定されることがわかります。しかしエグジットコマンドが既に呼び出されている為、次のエントリーは閉じられません。

ポジションを閉じる

コードで特定のエントリーを閉じることは可能です。しかしまた注文が [投資戦略テスター] タブのトレード一覧に表示されている時、それらはすべてFIFO(先入れ先出し (first in, first out)) ルールに従って処理されています。エントリー注文のIDをエグジット注文のコードで指定しない場合、エグジット注文はポジションを開いた最初のエントリー注文を閉じます。

次の例で確認してみます。

strategy("exit Demo", pyramiding=2, overlay=true)
strategy.entry("Buy1", strategy.long, 5, 
               when = strategy.position_size == 0 and year > 2014)
strategy.entry("Buy2", strategy.long, 
               10, stop = strategy.position_avg_price +
               strategy.position_avg_price*0.1,
               when = strategy.position_size == 5)
strategy.exit("bracket", loss=10, profit=10, when=strategy.position_size == 15)

上記のコードでは、2つの注文が順に並べられています。"Buy1" は成行注文で "Buy2" は10% 高い価格での逆指値注文です。エグジット注文は すべての注文が約定された後にのみ出されます。このコードをチャートに適用すると、エントリー注文のIDを strategy.exit("bracket", loss=10, profit=10, when=strategy.position_size == 15) の行では指定していませんが、それぞれすべての注文がエグジット注文で閉じられることがわかります。

別の例:

strategy("exit Demo", pyramiding=2, overlay=true)
strategy.entry("Buy1", strategy.long, 5, when = strategy.position_size == 0)
strategy.entry("Buy2", strategy.long, 
               10, stop = strategy.position_avg_price + 
               strategy.position_avg_price*0.1,
               when = strategy.position_size == 5)
strategy.close("Buy2",when=strategy.position_size == 15)
strategy.exit("bracket", "Buy1", loss=10, profit=10, when=strategy.position_size == 15)
plot(strategy.position_avg_price)
  • 注文 "Buy1" で5つのロングポジションを開く
  • 注文 "Buy2" によって、10%高い価格でさらに10のロングポジションを開き、ロングポジションを(15に)拡大
  • エグジット注文 (strategy.close) で("ID" が "Buy2" の)10のロングポジションに対する売り注文が約定

描画されたラインを見ると、平均エントリー価格と "Buy2" の実行価格が同じであり、ストラテジーは正確にこのエントリー注文を閉じている事がわかります。一方 [トレード一覧] タブでは、最初の "Buy1" 注文と 2番目の "Buy2" の半分が閉じられた事がわかります。これはストラテジーでのエントリー注文のクローズの指定に関係なく、ブローカエミュレータは(FIFOルールに従って)最初のものを閉じる事を意味します。ブローカーでトレードを行う場合と同じように動作します。

OCA グループ

Pineスクリプトでは2つの異なる OCA グループで注文を出す事が可能です。

  • strategy.oca.cancel - グループの注文が(部分的にでも)約定またはキャンセルされるとすぐに、同じグループの他の注文もキャンセルされます。一点注意が必要なのは、注文価格が同じか近い場合、同じグループの1つ以上の注文が約定される可能性があることです。この OCA グループタイプはエントリー注文の時のみ有効です。すべてのエグジット注文は、strategy.oca.cancel ではなく strategy.oca.reduce で行われます。

例:

//@version=2
strategy("oca_cancel demo")
if year > 2014 and year < 2016
    strategy.entry("LE", strategy.long, oca_type = strategy.oca.cancel, oca_name="Entry")
    strategy.entry("SE", strategy.short, oca_type = strategy.oca.cancel, oca_name="Entry")

ピラミッドが許可されていないため、これはポジションをドテンさせるストラテジーだと思うかもしれません。しかし実際には2つの注文が約定します。2つの注文が成行注文である為、現在の価格でどちらも即時に約定します。2番目の注文はキャンセルされません。これは2つの注文がほぼ同時に約定され、システムが、最初の注文の処理を約定し、2番目の注文をキャンセルする時間がない為です。価格が同じか近い価格の注文であれば、同じことが起こります。

ストラテジーは(マーケットポジションの状況などに応じて)すべての注文を発注します。ストラテジーはルールに反しないすべての注文を出します(このケースでは、マーケットポジションはスクエアであるため、エントリー注文はどれでも約定します)。各ティックでの処理は、まず最初に条件を満たす注文がすべて実行され、続いて注文が実行されたグループの他の注文がキャンセルされます。

  • strategy.oca.reduce - このグループタイプではグループ内で複数注文が約定できます。グループ内の注文が約定すると、他の注文のサイズは約定した数量に応じて減らされます。これはストラテジーのエグジットに非常に便利です。一度価格が利益確定注文に到達し約定すると、損切り注文はキャンセルされませんが、合計数量は約定した数量に従い減らされて、他のオープンポジションを保護します。
  • strategy.oca.none - 注文はグループ外に置かれます(strategy.orderstrategy.entry コマンドのデフォルト値)。

すべてのグループには(注文同様に)一意のIDがあります。もし2つのグループが同じIDを持ち、タイプが異なる場合、それらは異なるグループと見なされます。

例:

//@version=2
strategy("My Script")
if year > 2014 and year < 2016
    strategy.entry("Buy", strategy.long, oca_name="My oca", oca_type=strategy.oca.reduce)
    strategy.exit("FromBy", "Buy", profit=100, loss=200, oca_name="My oca")
    strategy.entry("Sell", strategy.short, oca_name="My oca", oca_type=strategy.oca.cancel)
    strategy.order("Order", strategy.short, oca_name="My oca", oca_type=strategy.oca.none)

"Buy" と "Sell" は、OCA タイプが異なるため、異なるグループに配置されます。"Order" は strategy.oca.none のタイプが設定されているため、グループ外になります。また "Buy" はエグジットグループに配置されます。これはエグジット注文は常に strategy.oca.reduce_size タイプのグループに置かれるためです。

リスク管理

いかなる状況でも常に機能し収益を上げるストラテジーを作ることは容易ではありません。通常は特定のマーケット条件に対してストラテジーは作成されます。その為ストラテジーを他の銘柄で動作させると、コントロール不能な損失が発生することがあります。したがって何か問題が起きたときに自動トレードを停止することは重大な課題です。Pineにはリスク管理を行う為の特別なストラテジーコマンドのグループがあります。それらはプレフィックス strategy.risk.* で始まります。

1つのストラテジー内でリスクコマンドを、任意の数、任意の組み合わせで利用することができます。ストラテジー設定の calc_on_order_fills にの値に関わらず、すべてのリスクカテゴリのコマンドは、すべのティック、すべての注文実行イベント時に処理されます。スクリプト実行時にリスクルールを無効にすることはできません。スクリプトのどこにリスクルールが書かれているかにかかわらず、ルールを含む行が削除され、スクリプトが再コンパイルされない限り、リスクルールは常に適用されます。

いずれかのルールがトリガーされた場合、注文は出されません。したがってストラテジーにパラメーターの異なる同様の複数のルールがある場合、最も厳密なパラメーターのルールがトリガーされた時に処理が中止されます。ストラテジーが停止すると、未実行の注文はすべて取り消され、ポジションがあれば、市場に注文を出してポジションを閉じます。

さらにプレフィックス "strategy.risk.max_intraday_" で始まるルールは、日足以上ではすべてのバーを1日と見なすことを覚えておく必要があります。

例(MSFT 1):

//@version=2
strategy("multi risk demo", overlay=true, pyramiding=10, calc_on_order_fills = true)
if year > 2014
    strategy.entry("LE", strategy.long)
strategy.risk.max_intraday_filled_orders(5)
strategy.risk.max_intraday_filled_orders(2)

上の例では、2番目のリスクルールが最初のルールに優先して発動し、トレードセッションの終わりまで有効です。2番目のルールは、トレードセッション内で2つの注文が実行された後に、ポジションをクローズし、トレードセッションの終了までトレードを停止します。

strategy.risk.allow_entry_in ルールは strategy.entry にのみ適用されることに注意してください。したがって entry コマンドではない strategy.order コマンドを用いてトレードを行うことは可能です。また strategy.risk.allow_entry_in ルールが有効な時、「禁止されたトレード」のエントリーではドテンではなくクローズを行います。

例(MSFT 1D):

//@version=2
strategy("allow_entry_in demo", overlay=true)
if year > 2014
    strategy.entry("LE", strategy.long, when=strategy.position_size <= 0)
    strategy.entry("SE", strategy.short, when=strategy.position_size > 0)
strategy.risk.allow_entry_in(strategy.direction.long)

つまりリスクルールによってショートエントリーが禁止されているので、ドテンではなく、ロングポジションがクローズされます。

通貨

TradingViewのストラテジーでは、チャートの通貨とは異なる通貨で運用することができます。純利益と未実現損益は口座通貨で再計算されます。口座通貨はストラテジーのプロパティで設定します。ドロップダウンリストの Base Currency またはスクリプト の strategy(..., currency=currency.*, ...) キーワードで。同時にパフォーマンスレポートの値が選択された通貨で計算されます。

トレードの利益(オープンまたはクローズ)は、チャート通貨の利益に(ストラテジーが計算されるバーの)前の取引日の終値のクロスレートを乗算したもので計算されます。

例: EURUSDの日足で、ストラテジー通貨にユーロ (EUR) を選択。ストラテジーは1ポイントの利益確定と損切りを用いて、ロングポジションのエントリーとエグジットを行います。

//@version=2
strategy("Currency test", currency=currency.EUR)
if year > 2014
    strategy.entry("LE", true, 1000)
    strategy.exit("LX", "LE", profit=1, loss=1)
profit = strategy.netprofit
plot(abs((profit - profit[1])*100), "1 point profit", color=blue, linewidth=2)
plot(1 / close[1], "prev usdeur", color=red)

このストラテジーをチャートに追加すると、青と赤の2つの描画されたラインが一致することがわかります。これはすべてのトレードにおいて、 利益を計算するレートが前日終値に基づいていることを示しています。

時間足や分足といったイントラデイでのトレードでは、ストラテジーが計算されたバーの、前の取引日の終値のクロスレートが使用され、同じトレードセッションの間は変更されません。

日足を超えるトレードでは、ストラテジーが計算されるバーの終値の、前の取引日の終値のクロスレートが使用されます。例えば週足のトレードでは、利益計算に木曜日のセッション終値のクロスレートが常に用いられます。

リアルタイムでは、昨日のセッションの終値のレートが使用されます。


前の項目: カスタムバー、カスタムローソク足, 次の項目: ハウツー, メニューに戻る: Pineスクリプトチュートリアル