Динамическая стратегия торговли с корректировкой риска и импульса

Автор:Чао Чжан, Дата: 2024-01-24 11:13:39
Тэги:

img

Обзор

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

Механика стратегии

нормализованная цена представляет собой ряд скорректированных на волатильность накопленных ежедневных доходов. Ежедневная обратная связь корректировки волатильности определяется пользователем. В качестве основного индикатора тренда используется скользящая средняя стоимость нормализованной цены. Период обратной связи HMA также определяется пользователем, с периодом по умолчанию 100 дней для реагирующего сигнала без возбуждения переторговли.

Основные сделки просты, длинные при нормализованном ценовом перекрестном HMA, короткие при перекрестном HMA.

Размер позиции динамически корректируется на основе недавней волатильности цен и установленной пользователем годовой цели риска. Позиции взвешены по риску, больший размер с меньшей волатильностью и меньший с более высокой волатильностью. Недавняя волатильность - это стандартное отклонение доходности за последние 14 периодов, а затем экстраполируется в годовую волатильность в качестве ожидаемой доходности. Годовая цель риска используется в качестве ссылки для регулируемого по волатильности размера позиции. Цель по умолчанию составляет 10% от общего капитала. Первоначальный капитал должен устанавливаться как максимальный убыток за сделку. Максимальный рычаг позволяет достичь цели риска, если основная естественная волатильность недостаточна, и смягчает чрезмерно низкую волатильность.

Твёрдые остановки основаны на кратнике среднего истинного диапазона цены, настраиваемом пользователем.

Преимущества

  • Нормализация цен снижает ложные сигналы
  • Динамическое регулирование размеров позиций эффективно
  • Жесткие остановки предотвращают беглые потери
  • Простая тенденция, следующая логике прозрачности

Риски

  • Проблемы с отставанием с скользящей средней по Халлу
  • Ограничение прибыли при одновременном снижении риска за счет регулирования размеров позиций, скорректированных по изменчивости
  • Слишком плотный, подвержен колючим колючкам

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

Усовершенствования

  • Эффективность испытаний других типов скользящих средних
  • Оптимизация параметров скользящих средних
  • Попробуйте только длинные или короткие варианты
  • Диапазоны прекращения потерь тонкой настройки
  • Эксперимент с другими механизмами остановки потерь

Заключение

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


/*backtest
start: 2023-01-17 00:00:00
end: 2024-01-23 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Crunchster1

//@version=5
strategy(title="Crunchster's Normalised Trend Strategy", shorttitle="Normalised Trend Strategy", overlay=false )

// Inputs and Parameters
src = input(close, 'Source', group='Strategy Settings')
length = input.int(title="Lookback period for price normalisation filter", defval=14, minval=2, group='Strategy Settings', tooltip='This sets the lookback period for the volatility adjustment of returns, which is used to transform the price series into the "real price"')
hlength = input.int(title="Lookback period for Hull Moving Average", defval=100, minval=2, group='Strategy Settings')
offset = input.int(title="HMA Offset", defval=0, minval=0, group='Strategy Settings')
long = input(true, 'Long', inline='08', group='Strategy Settings')
short = input(true, 'Short', inline='08', group='Strategy Settings', tooltip='Toggle long/short strategy on/off')

stopMultiple = input.float(1, 'Stop multiple', step=0.25, group='Risk Management Settings', tooltip='Multiple for ATR, setting hard stop loss from entry price')
lev = input.float(1, 'Max Leverage', step=0.5, group='Risk Management Settings', tooltip='Max leverage sets maximum allowable leverage of total capital (initial capital + any net profit), capping maximum volatility adjusted position size')
riskT = input.float(10, maxval=75, title='Annualised Volatility Target %', group='Risk Management Settings', tooltip='Specify annual risk target, used to determine volatility adjusted position size. Annualised daily volatility is referenced to this value and position size adjusted accordingly')
comp = input(false, 'Compounding', inline='09', group='Risk Management Settings')
Comppct = input.float(50, '%', step=5, inline='09', group='Risk Management Settings', tooltip='Toggle compounding of profit, and set % of profit to compound')

// Backtesting period
FromDay = input.int(defval=1, title='From Day', minval=1, maxval=31, inline='04', group='Backtest range')
FromMonth = input.int(defval=1, title='From Mon', minval=1, maxval=12, inline='04', group='Backtest range')
FromYear = input.int(defval=2018, title='From Yr', minval=1900, inline='04', group='Backtest range', tooltip='Set start of backtesting period')
ToDay = input.int(defval=1, title='To Day', minval=1, maxval=31, inline='05', group='Backtest range')
ToMonth = input.int(defval=1, title='To Mon', minval=1, maxval=12, inline='05', group='Backtest range')
ToYear = input.int(defval=9999, title='To Yr', minval=1900, inline='05', group='Backtest range', tooltip='Set end of backtesting period')

start = timestamp(FromYear, FromMonth, FromDay, 00, 00)
finish = timestamp(ToYear, ToMonth, ToDay, 23, 59)
window = true

// Normalised returns calculation
nRet = (src - src[1]) / ta.stdev((src - src[1]), length)

nPrice = ta.cum(nRet)

//Hull Moving Average - using normalised price series
fHMA = ta.wma(2 * ta.wma(nPrice[offset], hlength / 2) - ta.wma(nPrice[offset], hlength), math.round(math.sqrt(hlength)))

//Risk Management formulae
strategy.initial_capital = 50000
tr = math.max(high - low, math.abs(high - close), math.abs(low - close)) //True range
stopL = ta.sma(tr, 14) //Average true range
stdev = ta.stdev(close-close[1], 14) //volatility of recent returns
maxcapital = strategy.initial_capital+strategy.netprofit //Maximum capital available to invest - initial capital net of profit
annvol = 100*math.sqrt(365)*stdev/close //converts recent volatility of returns into annualised volatility of returns - assumes daily timeframe

risk = 1.1
if comp
    risk := (strategy.initial_capital+(Comppct*strategy.netprofit/100))//adjust investment capital to include compounding
else
    risk := strategy.initial_capital

shares = (risk * (riskT/annvol)) / close //calculates volatility adjusted position size, dependent on user specified annualised risk target
if ((shares*close) > lev*maxcapital) //ensures position size does not exceed available capital multiplied by user specified maximum leverage
    shares := lev*maxcapital/close

//To set the price at the entry point of trade
Posopen() =>
    math.abs(strategy.position_size[1]) <= 0 and math.abs(strategy.position_size) > 0

var float openN = na
if Posopen()
    openN := stopL

// Strategy Rules
if long
    longCondition = ta.crossover(nPrice, fHMA) and window
    exitlong = ta.crossunder(nPrice, fHMA)
    if (longCondition)
        strategy.entry('Go Long!', strategy.long, qty=shares)
    if strategy.position_size > 0    
        strategy.exit('Stop Long', from_entry = 'Go Long!', stop=(strategy.opentrades.entry_price(0) - (openN * stopMultiple)))
    if (exitlong)
        strategy.close('Go Long!', immediately = true)

if short
    shortCondition = ta.crossunder(nPrice, fHMA) and window
    exitshort = ta.crossover(nPrice, fHMA)
    if (shortCondition)
        strategy.entry('Go Short!', strategy.short, qty=shares)
    if strategy.position_size < 0   
        strategy.exit('Stop Short', from_entry = 'Go Short!', stop=(strategy.opentrades.entry_price(0) + (openN * stopMultiple)))
    if (exitshort)
        strategy.close('Go Short!', immediately = true)

// Visuals of trend and direction
plot(nPrice, title='Real Price', color=color.black)

MAColor = fHMA > fHMA[3] ? #00ff00 : #ff0000
MA1 = plot(fHMA, title='Hull MA', color=MAColor)
MA2 = plot(fHMA[3], title='Hull MA Offset', color=MAColor)
fill(MA1, MA2, title='Band Filler', color=MAColor)

Больше