Stratégie de négociation dynamique ajustée au risque et à l'élan

Auteur:ChaoZhang est là., Date: 2024-01-24 11:13:39 Je vous en prie.
Les étiquettes:

img

Résumé

Cette stratégie unique de trading basée sur des règles est dans la catégorie suivante. Elle utilise des séries de prix normalisées transformées du prix de ticker brut aux signaux de trading générateur. Des techniques avancées de dimensionnement des positions et de gestion des risques, généralement réservées à la gestion de portefeuille institutionnel, sont utilisées dans cette stratégie - des technologies de positionnement et de contrôle des risques éprouvées utilisées par les conseillers financiers tels que les conseillers en négociation de matières premières et les fonds à terme gérés.

Mécanique de la stratégie

Le prix normalisé est une série de rendements quotidiens cumulés ajustés à la volatilité. Le lookback de l'ajustement de la volatilité quotidienne est défini par l'utilisateur. La moyenne mobile de l'échelle du prix normalisé est utilisée comme indicateur principal de tendance. La période de lookback de la HMA est également définie par l'utilisateur, avec une période par défaut de 100 jours pour un signal réactif sans induire de sur-trading.

Les opérations de base sont simples, longues lorsque le prix est normalisé sur le HMA, courtes lorsque le prix est croisé sur le HMA.

La taille de la position est ajustée dynamiquement en fonction de la volatilité des prix récente et de l'objectif de risque annuel défini par l'utilisateur. Les positions sont pondérées en fonction du risque, de taille plus grande avec une volatilité plus faible et plus petite avec une volatilité plus élevée. La volatilité récente est l'écart type des rendements au cours des 14 dernières périodes, puis extrapolée en volatilité annuelle en tant que rendements attendus. La cible de risque annuelle est utilisée comme référence pour la taille de la position ajustée à la volatilité. L'objectif par défaut est de 10% du capital total. Le capital initial doit être défini comme la perte maximale par transaction.

Les arrêts durs sont basés sur le multiplicateur récent de la moyenne de prix, configurable par l'utilisateur.

Les avantages

  • Les prix normalisés réduisent les faux signaux
  • Les contrôles de dimensionnement de position dynamique sont efficaces en cas de risque
  • Les arrêts durs empêchent les pertes en fuite
  • Une tendance simple suivant la logique de la transparence

Les risques

  • Problèmes de retard avec la moyenne mobile de Hull
  • Limiter les bénéfices tout en réduisant les risques grâce à la dimensionnement des positions ajustée à la volatilité
  • Il est trop serré, vulnérable aux pointes.

Les mesures de contrôle des risques comprennent des sélections alternatives de moyennes mobiles et l'ajustement des objectifs de risque.

Améliorations

  • Efficacité des essais d'autres types de moyennes mobiles
  • Optimiser les paramètres des moyennes mobiles
  • Essayez les variantes longues ou courtes
  • Distances de perte d'arrêt de réglage
  • Expérience avec d'autres mécanismes de stop loss

Conclusion

La stratégie intègre diverses techniques telles que la normalisation, l'ajustement dynamique de la position, les arrêts durs pour contrôler les risques. Le trading est basé sur des règles de suivi de tendance simples. Les paramètres peuvent être ajustés en fonction des préférences personnelles et des régimes du marché.


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

Plus de