I see 'Cannot create an order with negative quantity' error

This error appears when the strategy calculates the size of its entry as the percentage of its equity. If the equity falls below 0, the size of the position also becomes negative, which is not possible and results in a runtime error.

The best way to fix this issue is to convert the strategy to Pine Script v6. In Pine v6, the strategy by default enforces limits on position size. If the equity of the strategy starts falling too much, the existing positions will be forcibly liquidated by margin calls, and if the funds run out fully, the strategy will not attempt to create new orders with negative quantity, avoiding this error.

If you want to learn more about the source of this error and how to avoid it in earlier Pine versions, consult the text below.

if the strategy equity becomes negative and the total number of contracts calculated for the strategy.entry() or strategy.order() functions is a negative. It can be avoided by tweaking the strategy settings from the Properties menu or by directly changing the logic of the strategy.

Source of the error

Let’s take a look at the script where the order quantity is calculated as a percentage of equity, either through the Order Size setting in the strategy settings, or via the strategy_percent_of_equity constant in the Pine source of the strategy. On each bar, the strategy.entry() function is called to enter the position:

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

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

When adding the script to a NASDAQ:AAPL chart for 1D timeframe, the script crashes with a runtime error:

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

To understand the reason for this error, you should plot the capital using the strategy.equity variable and add a constraint on the call to the strategy.equity() function using any condition operator. That way, the function for entering a position will not be called on each bar (and will not cause additional recalculation of parameters, including the qty value) and the script will be calculated successfully:

Pine Script®
//@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)

At the opening of the second bar (bar_index = 1), the strategy enters a short position. But with the growth of the AAPL value, the profit (the value of the strategy.openprofit variable) from the open short position Short plummets, and in the end the capital of the strategy (strategy.equity = strategy.initial_capital + strategy.netprofit + strategy.openprofit) becomes negative.

The number of contracts calculated by the strategy engine is calculated as qty = (order size * equity / 100) / close. The area where the strategy capital turns into negative values can be displayed as follows:

Pine Script®
//@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)

The screenshot shows the label located on the negative equity section, where the resulting number of contracts is - 2. The number of contracts on the green section is >= 0:

If, when calculating a strategy, strategy.entry() is called on a bar with negative equity (and on which the number of contracts is negative), the calculation of the strategy stops with an error.

How do I fix this?

As a rule, this error does not appear in a correctly implemented strategy. To avoid mistakes, the strategy should use conditions for entering and exiting a position, stops, and margin.

If an error occurs, the correct methods for debugging the strategy are:

1. Using margin leverage (Margin For Long/Short positions in the Properties of the strategy or margin_long and margin_short parameters in the strategy() function). If specified, a part of a position will be automatically liquidated if the strategy does not have enough equity to maintain it. You can find out more about this functionality in the article in our User Manual or in a blog post.

Pine Script®
//@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. Checking the equity value to see if it’s above zero before calling strategy.entry() or strategy.order() functions or additionally redefining the number of entry contracts.

Pine Script®
//@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. Using variables of the strategy.risk category for risk management. You can read more about these in our User Manual.