Я вижу ошибку 'Cannot create an order with negative quantity'

Данная ошибка появляется в том случае, если баланс стратегии ушёл в минус и итоговое количество контрактов, рассчитанное для функций strategy.entry() или strategy.order() является целочисленным отрицательным значением  (qty < 0). Её можно избежать, поменяв параметры стратегии в её настройках или напрямую в исходном коде.

Причины появления ошибки

Рассмотрим скрипт, в котором объём заявки считается как процент от баланса (настройка 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 с таймфреймом 1D скрипт падает с ошибкой времени выполнения:

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) 

На открытии второго бара (bar_index = 1) стратегия входит в короткую позицию. Но с ростом стоимости AAPL прибыль (значение переменной strategy.openprofit) от открытой короткой позиции Short падает, и в конце концов баланс стратегии (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. Использование маржинального плеча через соответствующие настройки в окне параметров стратегии или через параметры margin_long, и margin_short в функции strategy(), чтобы закрыть части позиции, в случае, если у стратегии недостаточно средств для ее поддержания. Подробнее про этот функционал можно узнать в статье нашего Руководства Пользователя или посте в блоге.

//@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 для управления рисками. Подробнее об этом можно прочитать в нашем руководстве пользователя.