Turtle Trading

  • Описание
  • Трендовая стратегия «Черепаха»

Описание

В 1983 году легендарный трейдер Ричард Деннис, который превратил первоначальную долю в размере 5000 долларов в 100 миллионов долларов, заключил пари с деловым партнером Уильямом Экхардтом, что любого человека можно научить торговать или «вырастить» подобно детенышам черепах, которых он наблюдал в Сингапуре.

Таким образом, «Turtle Trading» родилась, с «черепахами», или студентами, обеспеченными серией правил, которые представляли собой полную торговую систему, охватывающую рынки для торговли, размер позиции, входы, выходы и стоп-лоссы.

Основные компоненты черепашьей торговли

Эксперимент был направлен на обеспечение полностью механического подхода, который может не быть успешным в 100% случаев, но обеспечит правила, которые устраняют эмоции и суждения, оставляя трейдеров с правилами и ничем иным:

Рынки — Что купить или продать: Первое решение заключается в том, что покупать и продавать, или, по сути, на каких рынках торговать.

Размер позиции — Сколько купить или продать: Решение о том, сколько покупать или продавать, является фундаментальным, и все же часто игнорируется большинством трейдеров.

Записи — Когда покупать или продавать: Решение о том, когда покупать или продавать, называется решением о входе.

Выходы — Когда выходить из выигрышной позиции: Выход из выигрышных позиций слишком рано является одной из самых распространенных ошибок при торговле системами следования за трендом.

Стоп-лоссы — Когда выходить из убыточной позиции: Самое важное в снижении потерь — это заранее определить точку, где вы «остановитесь», прежде чем войти в позицию.

По словам Ричарда Денниса, правила очень просты, но их трудно применять на практике:

«Я всегда говорю, что вы можете опубликовать мои торговые правила в газете, и никто не будет им следовать. Ключом является последовательность и дисциплина. Почти каждый может составить список правил, которые на 80% лучше, чем то, чему мы научили наших людей. Чего они не могли сделать, так это дать им уверенность в том, чтобы придерживаться этих правил, даже когда дела идут плохо», — из Market Wizards, Джек Д. Швагер.

Торговля черепахами на Python

Начнем с импорта необходимого пакета — Yahoo! Finance, а также импорта библиотек Numpy, Pandas, Matplotlib и Datetime:

# install required packages
!pip install yfinance --upgrade --no-cache-dir

# import required libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt

Давайте используем Datetime для создания функционального набора данных. Будьте осторожны, мы должны использовать аргумент Datetime .isoformat(), чтобы преобразовать его в значение, которое может быть интерпретировано Yahoo! Finance:

# find today's date
today = dt.date.today()
# delta = 1 day time delta
delta = dt.timedelta(days = 1)
# end_delta = 10 years ago
end_delta = dt.timedelta(days = 3652)

# Set the end of the sample to yesterday
end_of_sample = (today - delta)
# Set the start of the sample to 10 years ago
start_of_sample = (end_of_sample - end_delta)

# Change the data format from a 'datetime' element to a string which can be interpreted by Yahoo! Finance
end_of_sample = end_of_sample.isoformat()
start_of_sample = start_of_sample.isoformat()

Теперь мы можем использовать Pandas Datareader для импорта данных S&P 500 (^GSPC) для указанного образца:

# use Datreader to import S&P500 Data within the defined sample period
from pandas_datareader import data as pdr
dataset = pdr.get_data_yahoo("^GSPC", start=start_of_sample, end=end_of_sample).reset_index()

Теперь нам нужно сгенерировать некоторые триггеры, при которых инициируется действие «ордера на покупку» или «ордера на продажу»:

# define the conditions under which the algorithm should trigger a buy order or sell order
count = int(np.ceil(len(dataset) * 0.1))

action = pd.DataFrame(index=dataset.index)
action['trigger'] = 0.0
action['trend'] = dataset['Adj Close']

action['RollingMax'] = (action.trend.shift(1).rolling(count).max())
action['RollingMin'] = (action.trend.shift(1).rolling(count).min())

action.loc[action['RollingMax'] < action.trend, 'trigger'] = -1
action.loc[action['RollingMin'] > action.trend, 'trigger'] = 1

Мы можем вызвать столбец «триггер» фрейма данных действия, чтобы проверить, когда действия рекомендуются для выполнения. Однако этот алгоритм не учитывает чистые короткие позиции — если запасы равны 0, мы не можем продать индекс. Теперь мы можем определить функцию принятия решения:

# this executable is a decision function for the algorithm
def trade(price_change, trigger, capital = 10_000, maximum_long = 1, maximum_short = 1,):
    """
    price_change = S&P500 price change (Absolute Value)
    trigger = 1 initiates a buy order, -1 initiates sell order
    capital = The initial capital committed to algorithm (the _ acts as a comma for large values)
    maximum_long = the maximum quantity that can be purchased in any one action
    maximum_short = maximum quantity that can be sold in any one action (note the shortselling restriction)
    """
    starting_capital = capital
    sell_states = []
    buy_states = []
    inventory = 0

    def buy(i, capital, inventory):
        shares = capital // price_change[i]
        if shares < 1:
            print(
                'day %d: total balances %f, not enough capital to buy a unit price %f'
                % (i, capital, price_change[i])
            )
        else:
            if shares > maximum_long:
                buy_units = maximum_long
            else:
                buy_units = shares
            capital -= buy_units * price_change[i]
            inventory += buy_units
            print(
                'day %d: buy %d units at price %f, total balance %f'
                % (i, buy_units, buy_units * price_change[i], capital)
            )
            buy_states.append(0)
        return capital, inventory

    for i in range(price_change.shape[0] - int(0.025 * len(dataset))):
        state = trigger[i]
        if state == 1:
            capital, inventory = buy( i, capital, inventory)
            buy_states.append(i)
        elif state == -1:
            if inventory == 0:
                    print('day %d: cannot sell anything, inventory 0' % (i))
            else:
                if inventory > maximum_short:
                    sell_units = maximum_short
                else:
                    sell_units = inventory
                inventory -= sell_units
                total_sell = sell_units * price_change[i]
                capital += total_sell
                try:
                    invest = (
                        (price_change[i] - price_change[buy_states[-1]])
                        / price_change[buy_states[-1]]) * 100
                except:
                    invest = 0
                print(
                    'day %d, sell %d units at price %f, investment %f %%, total balance %f,'
                    % (i, sell_units, total_sell, invest, capital))
            sell_states.append(i)
            
    invest = ((capital - starting_capital) / starting_capital) * 100
    total_gains = capital - starting_capital
    return buy_states, sell_states, total_gains, invest

Когда мы выполняем эту функцию, выходные данные не получаются. Это связано с тем, что мы должны передать аргументы функции принятия решения:

# we must pass arguments to the decision function
buy_states, sell_states, total_gains, invest = trade(dataset['Adj Close'], action['trigger'])

Теперь, когда мы передали аргументы нашей функции «торговля», каждое действие, которое пытается выполнить код, печатается вместе с соответствующим результатом. Прежде чем визуализировать выходные данные алгоритма, мы можем определить функцию, называемую Index_Returns, которая обеспечивает простой возврат индекса в течение периода выборки.

Первое скорректированное значение close и окончательное значение adjusted close передаются функции, генерируя Benchmark для измерения производительности алгоритма:

# Let's define a quick function which generates the Index returns, to allow benchmarking
def Index_Returns(start_value, end_value):
    return (((end_value - start_value) / start_value) -1) * 100

# We can pass this function the required arguments to calculate a simple return
SP_500_Returns = Index_Returns(dataset['Adj Close'].iloc[0], dataset['Adj Close'].iloc[-1])

Мы можем добавить производительность benchmark в заголовок диаграммы и визуализировать производительность алгоритма в примере:

# Plot the S&P500 Closing Price
value = dataset['Adj Close']
fig = plt.figure(figsize = (15,5))
plt.plot(value, color='b', lw=2.)

# Plot the Entry and Exit Signals generated by the algorithm
plt.plot(value, '^', markersize=8, color='g', label = 'Trigger Entry', markevery = buy_states)
plt.plot(value, 'v', markersize=8, color='r', label = 'Trigger Exit', markevery = sell_states)

# Chart Title displaying the Absolute Returns, Return on Capital & Benchmark Returns
plt.title('Absolute Returns: $%f, Return on Capital: %f%%, Benchmark Return: %f%%'%(round(total_gains,2), round(invest,2), round(SP_500_Returns,2)))
plt.legend()
plt.show();

Таким образом, этот алгоритм по-прежнему генерирует положительную отдачу по выборке, однако он значительно отстает от теста. Это может быть связано с использованием низкочастотных данных, но более вероятно, что параметры требуют настройки.

Трендовая стратегия «Черепаха»

Обзор

Стратегия Turtle Trend является усовершенствованной версией знаменитой стратегии Turtle Trading. Он использует торговые сигналы, генерируемые двойными скользящими средними, для реализации торговли по тренду с низким уровнем риска. Стандартизированные правила входа и выхода позволяют эффективно контролировать торговые риски и добиваться стабильного роста капитала.

Логика стратегии

Стратегия Turtle Trend рассчитывает 20-дневный максимум, 20-дневный минимум, 55-дневный максимум и 55-дневный минимум в сочетании с индикатором ATR для установки стоп-лосса и цели по прибыли. Он генерирует сигналы на покупку, когда цена превышает 20-дневный максимум, и короткие сигналы, когда цена пробивает 20-дневный минимум. Кроме того, настроен механизм пропуска торговых сигналов, если цены пробивают 20-дневный максимум/минимум, но не могут пробить 55-дневный максимум/минимум.

После входа в рынок стратегия использует значения ATR для установки стоп-лосса и цели пирамидинга. Он останавливается, когда убытки достигают уровня стоп-лосса, и увеличивает размер позиции, когда прибыль достигает цели пирамидинга. Это максимизирует потенциальную прибыль на трендовых рынках, контролируя риски отдельных сделок.

Анализ преимуществ

Самое большое преимущество стратегии Turtle Trend заключается в ее отличных возможностях контроля рисков. Стандартизированные правила входа и выхода позволяют эффективно контролировать убытки по отдельным сделкам. Механизм пропуска позволяет избежать застревания в неблагоприятных рыночных условиях. Стратегия стабильного стоп-лосса также ограничивает последовательные убытки.

Кроме того, стратегия Turtle Trend использует индикатор ATR для динамической установки стоп-лосса, что позволяет линии стоп-лосса автоматически адаптироваться к изменениям волатильности рынка. Это гарантирует, что стоп-лосс не будет ни слишком свободным, чтобы вызвать огромные убытки, ни слишком узким, чтобы его можно было спровоцировать нормальными колебаниями рынка.

Наконец, механизм пирамидинга позволяет стратегии полностью фиксировать прибыль на трендовых рынках, закладывая основу для устойчивого роста капитала.

Анализ риска

Основной риск стратегии Turtle Trend заключается в том, что она не приносит прибыли на рынках, ограниченных диапазоном. Когда рынок колеблется в диапазоне в течение длительных периодов, стоп-лосс может часто срабатывать, что приводит к убыткам. Кроме того, механизм пропуска может привести к недостаточному количеству сигналов и, таким образом, упустить потенциальные торговые возможности.

Кроме того, чрезмерная зависимость от технических индикаторов игнорирует фундаментальный анализ. Он может не обнаружить серьезных изменений в политике и привести к ненужным потерям.

Оптимизация

Стратегия Turtle Trend может быть оптимизирована в следующих аспектах:

  1. Отрегулируйте чувствительность механизма пропуска, комбинируя индикаторы волатильности, чтобы увеличить частоту торговли на флэтовых рынках.
  2. Добавьте фундаментальные сигналы в качестве фильтра, чтобы избежать срабатывания стоп-лосса из-за спорадических событий.
  3. Оптимизируйте настройки параметров ATR, чтобы линия стоп-лосса более точно соответствовала фактическому колебанию.
  4. Комбинируйте индикаторы объема, чтобы избежать входа в неэффективный откат после убытка.

Заключение

Таким образом, стратегия Turtle Trend улучшает возможности прибыльности и контроля рисков оригинальной стратегии Turtle Trading. Это алгоритмическая стратегия с низким уровнем риска, подходящая для отслеживания трендовых рынков. При дальнейшей оптимизации он может стать важной частью построения долгосрочного стабильного прибыльного портфеля.

Исходный код стратегии

/*backtest
start: 2024-01-29 00:00:00
end: 2024-02-28 00:00:00
period: 3h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5
strategy("TURTLE STRATEGY", precision=2, overlay=true, initial_capital=1000, commission_type=strategy.commission.percent, commission_value=0.18, slippage=3, pyramiding=5, close_entries_rule="ANY", margin_long=100, margin_short=100)



//------------------------------TOOL TIPS--------------------------------//

t1 = "Percentage of the account the trader is willing to lose. This percentage is used to define the position size based on previous gains or losses. Turtle traders default to 1%."
t2 = "ATR Length"
t3 = "ATR Multiplier to fix the Stop Loss"
t4 = "Pyramiding : ATR Multiplier to set a profit target to increase position size"
t5 = "System 1 enter long if there is a new high after this selected period of time"
t6 = "System 2 enter long if there is a new high after this selected period of time"
t7 = "Exit Long from system 1 if there is a new low after this selected period of time"
t8 = "Exit Long from system 2 if there is a new low after this selected period of time"
t9 = "System 1 enter short if there is a new low after this selected period of time"
t10 = "System 2 enter short if there is a new low after this selected period of time"
t11 = "Exit short from system 1 if there is a new high after this selected period of time"
t12 = "Exit short from system 2 if there is a new high after this selected period of time"


//----------------------------------------FUNCTIONS---------------------------------------//

//@function Displays text passed to `txt` when called.
debugLabel(txt, color) =>
label.new(bar_index, high, text=txt, color=color, style=label.style_label_lower_right, textcolor=color.black, size=size.small)

//@function which looks if the close date of the current bar falls inside the date range
inBacktestPeriod(start, end) => (time >= start) and (time <= end)


//---------------------------------------USER INPUTS--------------------------------------//

//Risk Management and turtle system input
percentage_to_risk = input.float(1, "Risk % of capital", maxval=100, minval=0, group="Turtle Parameters", tooltip=t1)
atr_period = input.int(20, "ATR period", minval=1, group="Turtle Parameters", tooltip=t2)
stop_N_multiplier = input.float(1.5, "Stop ATR", minval=0.1, group="Turtle Parameters", tooltip=t3)
pyramid_profit = input.float(0.5, "Pyramid Profit", minval=0.01, group="Turtle Parameters", tooltip=t4)
S1_long = input.int(20, "S1 Long", minval=1, group="Turtle Parameters", tooltip=t5)
S2_long = input.int(55, "S2 Long", minval=1, group="Turtle Parameters", tooltip=t6)
S1_long_exit = input.int(10, "S1 Long Exit", minval=1, group="Turtle Parameters", tooltip=t7)
S2_long_exit = input.int(20, "S2 Long Exit", minval=1, group="Turtle Parameters", tooltip=t8)
S1_short = input.int(15, "S1 Short", minval=1, group="Turtle Parameters", tooltip=t9)
S2_short = input.int(55, "S2 Short", minval=1, group="Turtle Parameters", tooltip=t10)
S1_short_exit = input.int(7, "S1 Short Exit", minval=1, group="Turtle Parameters", tooltip=t11)
S2_short_exit = input.int(20, "S2 Short Exit", minval=1, group="Turtle Parameters", tooltip=t12)
//Backtesting period
startDate = input(title="Start Date", defval=timestamp("1 Jan 2020 00:00:00"), group="Backtesting Period")
endDate = input(title="End Date", defval=timestamp("1 July 2034 00:00:00"), group="Backtesting Period")


//----------------------------------VARIABLES INITIALISATION-----------------------------//

//Turtle variables
atr = ta.atr(atr_period)
var float buy_price_long = na
var float buy_price_short = na
var float stop_loss_long = na
var float stop_loss_short = na
float account = na
//Entry variables
day_high_syst1 = ta.highest(high, S1_long)
day_low_syst1 = ta.lowest(low, S1_short)
day_high_syst2 = ta.highest(high, S2_long)
day_low_syst2 = ta.lowest(low, S2_short)
var bool skip = false
var bool unskip_buffer_long = false
var bool unskip_buffer_short = false
//Exit variables
exit_long_syst1 = ta.lowest(low, S1_long_exit)
exit_short_syst1 = ta.highest(high, S1_short_exit)
exit_long_syst2 = ta.lowest(low, S2_long_exit)
exit_short_syst2 = ta.highest(high, S2_short_exit)
float exit_signal = na
//Backtesting period
bool inRange = na


//------------------------------CHECKING SOME CONDITIONS ON EACH SCRIPT EXECUTION-------------------------------//

//Checking if the date belong to the range
inRange := true
strategy.initial_capital = 50000
//Checking if the current equity is higher or lower than the initial capital to adjusted position size
if strategy.equity - strategy.openprofit < strategy.initial_capital
account := (strategy.equity-strategy.openprofit)*(strategy.equity-strategy.openprofit)/strategy.initial_capital
else
account := strategy.equity - strategy.openprofit

//Checking if we close all trades in case where we exit the backtesting period
if strategy.position_size!=0 and not inRange
strategy.close_all()
debugLabel("END OF BACKTESTING PERIOD : we close the trade", color=color.rgb(116, 116, 116))


//--------------------------------------SKIP MANAGEMENT------------------------------------//

//Checking if a long signal has been skiped and system2 is not triggered
if skip and high>day_high_syst1[1] and high<day_high_syst2[1]
unskip_buffer_long := true

//Checking if a short signal has been skiped and system2 is not triggered
if skip and low<day_low_syst1[1] and low>day_low_syst2[1]
unskip_buffer_short := true

//Checking if current high is lower than previous 20_day_high after a skiped long signal to set skip to false
if unskip_buffer_long
if high<day_high_syst1[1]
skip := false
unskip_buffer_long := false

//Checking if current low is higher than previous 20_day_low after a skiped short signal to set skip to false
if unskip_buffer_short
if low>day_low_syst1[1]
skip := false
unskip_buffer_short := false

//Checking if we have an open position to reset skip and unskip buffers
if strategy.position_size!=0 and skip
skip := false
unskip_buffer_long := false
unskip_buffer_short := false


//--------------------------------------------ENTRY CONDITIONS--------------------------------------------------//

//We calculate the position size based on turtle calculation
unit = (percentage_to_risk/100)*account/atr*syminfo.pointvalue

//Long order for system 1
if not skip and not (strategy.position_size>0) and inRange and unit>0
strategy.cancel("Long Syst 2")
//We check that position size doesn't exceed available equity
if unit*day_high_syst1>account
unit := account/day_high_syst1
stop_loss_long := day_high_syst1 - stop_N_multiplier*atr
//We adjust SL if it's greater than 10% of trade value and fix it to 10%
if stop_loss_long < day_high_syst1*0.9
stop_loss_long := day_high_syst1*0.9
strategy.order("Long Syst 1", strategy.long, unit, stop=day_high_syst1)
buy_price_long := day_high_syst1

//Long order for system 2
if skip and not (strategy.position_size>0) and inRange and unit>0
//We check that position size doesn't exceed available equity
if unit*day_high_syst2>account
unit := account/day_high_syst2
stop_loss_long := day_high_syst2 - stop_N_multiplier*atr
//We adjust SL if it's greater than 10% of trade value and fix it to 10%
if stop_loss_long < day_high_syst2*0.9
stop_loss_long := day_high_syst2*0.9
strategy.order("Long Syst 2", strategy.long, unit, stop=day_high_syst2)
buy_price_long := day_high_syst2

//Short order for system 1
if not skip and not (strategy.position_size<0) and inRange and unit>0
strategy.cancel("Short Syst 2")
//We check that position size doesn't exceed available equity
if unit*day_low_syst1>account
unit := account/day_low_syst1
stop_loss_short := day_low_syst1 + stop_N_multiplier*atr
//We adjust SL if it's greater than 10% of trade value and fix it to 10%
if stop_loss_short > day_low_syst1*1.1
stop_loss_short := day_low_syst1*1.1
strategy.order("Short Syst 1", strategy.short, unit, stop=day_low_syst1)
buy_price_short := day_low_syst1

//Short order for system 2
if skip and not (strategy.position_size<0) and inRange and unit>0
//We check that position size doesn't exceed available equity
if unit*day_low_syst2>account
unit := account/day_low_syst2
stop_loss_short := day_low_syst2 + stop_N_multiplier*atr
//We adjust SL if it's greater than 10% of trade value and fix it to 10%
if stop_loss_short > day_low_syst2*1.1
stop_loss_short := day_low_syst2*1.1
strategy.order("Short Syst 2", strategy.short, unit, stop=day_low_syst2)
buy_price_short := day_low_syst2


//-------------------------------PYRAMIDAL------------------------------------//

//Pyramid for long orders
if close > buy_price_long + (pyramid_profit*atr) and strategy.position_size>0
//We calculate the remaining capital
remaining_capital = account - strategy.position_size*strategy.position_avg_price*(1-0.0018)
//We calculate units to add to the long position
units_to_add = (percentage_to_risk/100)*remaining_capital/atr*syminfo.pointvalue
if remaining_capital > units_to_add and units_to_add>0
//We set the new Stop loss
stop_loss_long := stop_loss_long + pyramid_profit*atr
strategy.entry("Pyramid Long", strategy.long, units_to_add)
buy_price_long := close

//Pyramid for short orders
if close < buy_price_short - (pyramid_profit*atr) and strategy.position_size<0
//We calculate the remaining capital
remaining_capital = account + strategy.position_size*strategy.position_avg_price*(1-0.0018)
//We calculate units to add to the short position
units_to_add = (percentage_to_risk/100)*remaining_capital/atr*syminfo.pointvalue
if remaining_capital > units_to_add and units_to_add>0
//We set the new Stop loss
stop_loss_short := stop_loss_short - pyramid_profit*atr
strategy.entry("Pyramid Short", strategy.short, units_to_add)
buy_price_short := close


//----------------------------EXIT ORDERS-------------------------------//

//Checking if exit_long_syst1 is higher than stop_loss_long
if strategy.opentrades.entry_id(0)=="Long Syst 1"
if exit_long_syst1[1] > stop_loss_long
exit_signal := exit_long_syst1[1]
else
exit_signal := stop_loss_long

//Checking if exit_long_syst2 is higher than stop_loss_long
if strategy.opentrades.entry_id(0)=="Long Syst 2"
if exit_long_syst2[1] > stop_loss_long
exit_signal := exit_long_syst2[1]
else
exit_signal := stop_loss_long

//Checking if exit_short_syst1 is lower than stop_loss_short
if strategy.opentrades.entry_id(0)=="Short Syst 1"
if exit_short_syst1[1] < stop_loss_short
exit_signal := exit_short_syst1[1]
else
exit_signal := stop_loss_short

//Checking if exit_short_syst2 is lower than stop_loss_short
if strategy.opentrades.entry_id(0)=="Short Syst 2"
if exit_short_syst2[1] < stop_loss_short
exit_signal := exit_short_syst2[1]
else
exit_signal := stop_loss_short

//If the exit order is configured to close the position at a profit, we set 'skip' to true (we substract commission)
if strategy.position_size*exit_signal>strategy.position_size*strategy.position_avg_price*(1-0.0018)
strategy.cancel("Long Syst 1")
strategy.cancel("Short Syst 1")
skip := true
if strategy.position_size*exit_signal<=strategy.position_size*strategy.position_avg_price*(1-0.0018)
skip := false

//We place stop exit orders
if strategy.position_size > 0
strategy.exit("Exit Long", stop=exit_signal)

if strategy.position_size < 0
strategy.exit("Exit Short", stop=exit_signal)


//------------------------------PLOTTING ELEMENTS-------------------------------//

plotchar(atr, "ATR", "", location.top, color.rgb(131, 5, 83))
//Plotting enter threshold
plot(day_high_syst1[1], "20 day high", color.rgb(118, 217, 159))
plot(day_high_syst2[1], "55 day high", color.rgb(4, 92, 53))
plot(day_low_syst1[1], "20 day low", color.rgb(234, 108, 108))
plot(day_low_syst2[1], "55 day low", color.rgb(149, 17, 17))
//Plotting Exit Signal
plot(exit_signal, "Exit Signal", color.blue, style=plot.style_circles)
//Plotting our position
exit_long_syst2_plot = plot(exit_long_syst2[1], color=na)
day_high_syst2_plot = plot(day_high_syst2[1], color=na)
exit_short_syst2_plot = plot(exit_short_syst2[1], color=na)
day_low_syst2_plot = plot(day_low_syst2[1], color=na)
fill(exit_long_syst2_plot, day_high_syst2_plot, color=strategy.position_size>0 ? color.new(color.lime, 90) : na)
fill(exit_short_syst2_plot, day_low_syst2_plot, color=strategy.position_size<0 ? color.new(color.red, 90) : na)

Параметры стратегии

Исходный адрес: FMZ — Торговая платформа FMZ Quant

Источник

Источник