'Cannot create an order with negative quantity' のエラーが表示されます

このエラーは、ストラテジーの資産がマイナスになり、strategy.entry() 関数や strategy.order() 関数で計算された取引数の合計が、負の整数値 (qty < 0) になった場合に表示されます。このエラーは、プロパティメニューからストラテジーの設定を変更するか、コードでストラテジーのロジックを直接変更することで回避できます。

エラーの原因

ストラテジー設定の発注サイズの設定、またはストラテジーのPineコードで strategy_percent_of_equity 定数を使用して、注文数量が資産のパーセンテージとして計算されるスクリプトを見てみましょう。各バーで、ポジションを取るために strategy.entry() 関数が呼び出されます:

//@version=5
strategy("negative_qty", default_qty_type = strategy.percent_of_equity)

strategy.entry("Short", strategy.short)
plot(strategy.equity)

このスクリプトを NASDAQ:AAPL の日足チャートに追加すると、ランタイムエラーでスクリプトはクラッシュします:

Cannot create an order with negative quantity.
Current qty_type is percent_of_equity and equity is less than 0

このエラーの原因を理解するためには、strategy.equity 変数を使って、資金をプロットし、任意の条件演算子を使って strategy.entry() 関数の呼び出しに制約を加える必要があります。これにより、ポジションを取るための関数が各バーで呼び出されなくなり(また qty 値を含むパラメーターの再計算も行われなくなり)スクリプトの計算は正常に行われます:

//@version=5
strategy("negative_qty", default_qty_type = strategy.percent_of_equity)

if strategy.equity > 0
    strategy.entry("Short", strategy.short)

hline(0, "zero line", color = color.black, linestyle = hline.style_dashed)
plot(strategy.equity, color = color.black, linewidth = 3) 

2本目のバー (bar_index = 1) の開始時に、ストラテジーはショートポジションを取ります。しかし、AAPLの価格の上昇に伴い、そのショートポジション "Short" から得られる利益 (strategy.openprofit 変数の値) は急減し、最終的にストラテジーの資金 (strategy.equity = strategy.initial_capital + strategy.netprofit + strategy.openprofit) がマイナスになります。

ストラテジーエンジンが算出する取引数は、qty = (order size * equity / 100) / close として算出され、ストラテジーの資金がマイナスになった部分は、以下のように表示されます:

//@version=5
strategy("negative_qty", default_qty_type = strategy.percent_of_equity)

if strategy.equity > 0
    strategy.entry("Short", strategy.short)

hline(0, "zero line", color = color.black, linestyle = hline.style_dashed)
plot(strategy.equity, color = color.black, linewidth = 3)

equity_p = 1  // percents of equity  order size value (1% is default)
qty = (equity_p * strategy.equity / 100) / close

if qty <= -1
    var l1  = label.new(bar_index, strategy.equity, text = "Negative qty_value at \n bar index: " + str.tostring(bar_index) + ".\n" +  "Order size: " + str.tostring(math.round(qty)), color = color.white)
    var l2 = label.new(bar_index - 1, strategy.equity[1], text = "Order size : " + str.tostring(math.round(qty[1])), color = color.white)
    var l3 = label.new(bar_index - 2, strategy.equity[2], text = "Order size: " + str.tostring(math.round(qty[2])), color = color.white)

bgcolor(qty > -1 ? color.green : color.red)

このスクリーンショットでは、マイナスの資産の位置にラベルが表示されており、結果として取引数は-2となっています。緑の部分の取引数は >= 0 です:

ストラテジーを計算する際に、strategy.entry() が資産がマイナスのバー(かつ取引数がマイナスのバー)で呼び出された場合、ストラテジーの計算はエラーで停止します。

問題を修正するにはどうすればいいですか?

正しく実装されたストラテジーでは、原則としてこのエラーは発生しません。ストラテジーで、ポジションのエントリー/エグジット条件、ストップ、証拠金などを使用することでエラーを回避することができます。

このエラーが発生した場合、ストラテジーをデバッグするための正しい方法は以下の通りです:

1. 証拠金のレバレッジを使用します(ストラテジーのプロパティにあるロング/ショートポジションの証拠金の項目、または strategy() 関数の margin_long と margin_short パラメーター)。これを指定した場合、ストラテジーがポジションを維持するために十分な資産がない場合、ポジションの一部は自動的に清算されます。 この機能の詳細については、ユーザーマニュアルブログの記事をご覧ください。

//@version=5
strategy("", default_qty_type = strategy.percent_of_equity, default_qty_value = 10, margin_long = 100, margin_short = 100)

longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
if (longCondition)
    strategy.entry("Long", strategy.long)

shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28))
if (shortCondition)
    strategy.entry("Short", strategy.short)

2. strategy.entry() または strategy.order() 関数を呼び出す前に、またはエントリーの取引数を追加で再定義する前に、資産の値がゼロを超えているかどうかをチェックします:

//@version=5
strategy("", default_qty_type = strategy.percent_of_equity, default_qty_value = 10)

if strategy.equity > 0
    strategy.entry("Short", strategy.short)  // enter at 10 % of currently available equity
else
    strategy.entry("Long", strategy.long, qty = 1) // Reverse position with fixed contract size

3. リスク管理の為に strategy.risk カテゴリーの変数を使用します。詳細については、ユーザーマニュアルをご覧ください。