Pokazuje się błąd „Nie można utworzyć zamówienia z ujemną ilością”

Ten błąd pojawia się, gdy kapitał strategii staje się ujemny, a łączna liczba kontraktów obliczona dla funkcji strategy.entry() lub strategy.order() jest ujemną liczbą całkowitą (qty <0). Można tego uniknąć, dostosowując ustawienia strategii w menu Właściwości lub bezpośrednio zmieniając logikę strategii.

Źródło błędu

Przyjrzyjmy się skryptowi, w którym wielkość zlecenia jest obliczana jako procent kapitału własnego za pomocą ustawienia Wielkość Zlecenia w ustawieniach strategii lub za pomocą stałej  strategy_percent_of_equity  w źródle strategii Pine. Na każdym słupku funkcja  strategy.entry()  jest wezwaniem do wejścia na pozycję:

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

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

Podczas dodawania skryptu do wykresu NASDAQ:AAPL dla 1D , skrypt zawiesza się z błędem dotyczącym czasu wykonania: 

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

Aby zrozumieć przyczynę tego błędu, należy wykreślić kapitał za pomocą zmiennej strategy.equity i dodać ograniczenie na wywołanie do funkcji strategy.entry() za pomocą dowolnego operatora warunku. Dzięki temu na każdym słupku nie zostanie wywołana funkcja wprowadzenia pozycji (i nie spowoduje dodatkowego przeliczenia parametrów, w tym wartości  qty ) a skrypt zostanie obliczony pomyślnie:

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

Na otwarciu drugiego słupka (bar_index = 1), strategia otwiera pozycję krótką. Jednak wraz ze wzrostem wartości AAPL , spada zysk (wartość zmiennej strategy.openprofit ) z otwartej pozycji krótkiej Short , a ostatecznie bilans strategii (strategy.equity = strategy.initial_capital + strategy.netprofit + strategy.openprofit) staje się ujemny.

Liczba kontraktów obliczona przez silnik strategii jest obliczana jako qty = (order size * equity / 100) / close. Obszar, w którym kapitał strategii zamienia się w wartości ujemne, można wyświetlić w następujący sposób:

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

Zrzut ekranu pokazuje etykietę znajdującą się w sekcji ujemnego kapitału, gdzie wynikowa liczba kontraktów wynosi - 2. Liczba kontraktów na zielonej sekcji wynosi >= 0:

Jeśli przy obliczaniu strategii, strategy.entry() zostanie wywołane na słupku z ujemnym kapitałem (i na którym liczba kontraktów jest ujemna), obliczanie strategii zatrzymuje się z błędem.

Jak to naprawić?

Z reguły ten błąd nie pojawia się w prawidłowo realizowanej strategii. Aby uniknąć błędów, strategia powinna wykorzystywać warunki wejścia i wyjścia z pozycji, stop i, jako ostatnią granicę, depozyt zabezpieczający.

Jeśli wystąpi błąd, prawidłowe metody debugowania strategii to:

1. Korzystanie z dźwigni depozytu zabezpieczającego (Margin na pozycje długie/krótkie w Właściwościach strategii, lub parametrów margin_long i margin_short  w funkcji strategy() ). Jeśli zostanie określony, część pozycji zostanie automatycznie zlikwidowana, jeśli strategia nie ma wystarczającego kapitału, aby ją utrzymać. Możesz dowiedzieć się więcej o tej funkcjonalności w artykule w  Instrukcjach lub na blogu.

//@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. Sprawdzenie wartości kapitału, aby sprawdzić, czy jest powyżej zera przed sprawdzeniem funkcji strategy.entry() lub strategy.order()  lub dodatkowo przedefiniowanie liczby kontraktów wejściowych.

//@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. Korzystanie ze zmiennych z kategorii  strategy.risk dla zarządzania ryzykiem. Możesz przeczytać więcej na ten temat w  Instrukcjach.