Mi compare l'errore 'Impossibile creare un ordine con quantità negativa' ('Cannot create an order with negative quantity')

Questo errore compare se l'equity della strategia diventa negativo ed il numero totale di contratti calcolati con le funzioni strategy.entry() o strategy.order() è un numero intero e negativo (qtà <0). Può essere evitato modificando le impostazioni della strategia dal menù delle Proprietà o dal codice stesso.

Origine dell'errore

Diamo un'occhiata ad uno script in cui la quantità dell'ordine viene calcolata come percentuale dell'equity, che sia tramite l'impostazione Dimensione ordine della strategia o tramite la costante strategy_percent_of_equity nel codice della strategia. Ad ogni barra, la funzione strategy.entry() viene chiamata per aprire la posizione:

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

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

Applicando lo script al grafico NASDAQ:AAPL con timeframe 1D, questo va in crash con il seguente errore di runtime:

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

Per comprendere la ragione di questo errore, dovresti raffigurare il capitale utilizzando la variabile strategy.equity. Aggiungendo un vincolo alla funzione strategy.entry() con un qualsiasi operatore condizionale, la funzione smetterà di essere chiamata per aprire una posizione ad ogni barra ed eviterà quindi di causare l'errore alla radice dell'interruzione dello 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) 

All'apertura della seconda barra, (bar_index = 1), la strategia inserisce una posizione short. Ma con la crescita del valore di AAPL, il profitto (ovvero il valore della variabile strategy.openprofit) della posizione short diminuisce, portando eventualmente ad un capitale totale negativo (strategy.equity = strategy.initial_capital + strategy.netprofit + strategy.openprofit).

Il numero di contratti calcolati dalla strategia è ottenuto tramite la formula qty = (order size * equity / 100) / close. L'area in cui il capitale della strategia diventa negativo può essere mostrata come segue:

//@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)

Lo screenshot mostra l'etichetta posizionata nella sezione negativa dell'equity, dove il numero risultante di contratti è - 2 (nell'area verde si ha un numero superiore allo 0):

Se, durante il calcolo di una strategia, strategy.entry() viene chiamato su una barra in corrispondenza di un equity negativo (con conseguente numero di contratti negativo), il calcolo si interrompe e la strategia mostra un messaggio di errore.

Come si può risolvere?

In linea generale, questo errore non compare se la strategia è codificata correttamente. Per evitare errori, dovrebbero essere sempre imposti dei vincoli per entrare e uscire dal mercato.

Se si manifesta un errore, i metodi corretti per risolvere sono i seguenti:

1. Usare la leva a margine ("Margine per posizioni long/short" nelle Proprietà della strategia o i parametri margin_long e margin_short nella funzione strategy()). Se è specificato, una parte di una posizione sarà liquidata automaticamente nel caso in cui non ci sia l'equity sufficiente a mantenerla. Per saperne di più sulla funzionalità, puoi consultare l'articolo nel Manuale utente o nel blog.

//@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. Controllare il valore dell'equity per verificare che sia superiore allo zero prima di chiamare le funzioni strategy.entry() o strategy.order() o ridefinire il numero dei contratti di entrata.

//@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. Usare le variabili della categoria strategy.risk per la gestione del rischio. Puoi saperne di più leggendo il nostro Manuale utente.