Estrategia de negociación dinámica ajustada al riesgo y al impulso

El autor:¿ Qué pasa?, Fecha: 2024-01-24 11:13:39
Las etiquetas:

img

Resumen general

Esta estrategia de negociación basada en reglas sistemática única se encuentra en la siguiente categoría de tendencia. Utiliza series de precios normalizadas transformadas de precio de ticker en bruto a señales de negociación de generación. Se utilizan técnicas avanzadas de tamaño de posición y gestión de riesgos, generalmente reservadas para la gestión de carteras institucionales, en esta estrategia - tecnologías probadas de posicionamiento y control de riesgos utilizadas por asesores financieros como asesores de comercio de productos básicos y fondos de futuros gestionados.

Mecánica de la estrategia

El precio normalizado es una serie de rendimientos diarios acumulados ajustados a la volatilidad. La revisión de ajuste de volatilidad diaria es definida por el usuario. El promedio móvil del casco del precio normalizado se utiliza como el principal indicador de tendencia. El período de revisión de la HMA también es definido por el usuario, con un período predeterminado de 100 días para una señal de respuesta sin inducir un exceso de operaciones.

Las operaciones básicas son simples: largas cuando el precio se cruza con el HMA normalizado, cortas cuando se cruza con el HMA.

El tamaño de la posición se ajusta dinámicamente en función de la volatilidad de precios reciente y el objetivo de riesgo anual definido por el usuario. Las posiciones están ponderadas por riesgo, de mayor tamaño con menor volatilidad y más pequeñas con mayor volatilidad. La volatilidad reciente es la desviación estándar de los rendimientos en los últimos 14 períodos, luego extrapolada a la volatilidad anual como rendimientos esperados. El objetivo de riesgo anual se utiliza como referencia para el tamaño de posición ajustado por volatilidad. El objetivo predeterminado es el 10% del capital total. El capital inicial debe establecerse como la pérdida máxima por operación. El apalancamiento máximo permite lograr el objetivo de riesgo si la volatilidad natural subyacente es insuficiente y alivia la volatilidad excesivamente baja.

Las paradas duras se basan en el multiplicador de rango verdadero del precio promedio reciente, configurable por el usuario.

Ventajas

  • Los precios normalizados reducen las señales falsas
  • Los controles de dimensionamiento de posición dinámica corren el riesgo de ser eficaces.
  • Las paradas duras evitan las pérdidas por fuga.
  • Tendencia simple siguiendo la lógica de la transparencia

Los riesgos

  • Problemas de retraso con la media móvil de Hull
  • Limitar las ganancias al tiempo que se reduce el riesgo mediante el tamaño de las posiciones ajustado a la volatilidad
  • Se detiene demasiado apretado vulnerable a los picos

Las medidas de control de riesgos incluyen alternativas de selección de medias móviles y ajustes de los objetivos de riesgo.

Mejoras

  • Eficacia de los ensayos de otros tipos de medias móviles
  • Optimización de los parámetros de las medias móviles
  • Pruebe las variantes largas o cortas
  • Intervalos de pérdida de parada de sintonía fina
  • Experimentación con otros mecanismos de stop loss

Conclusión

La estrategia integra varias técnicas como la normalización, el ajuste dinámico de la posición, las paradas duras para controlar los riesgos. El comercio se basa en reglas simples de tendencia. Los parámetros se pueden ajustar para las preferencias personales y los regímenes del mercado. Vale la pena probar y verificar más para una aplicación viable en el mundo real.


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

Más.