Stratégie de négociation quantitative multi-indicateur dynamique

Auteur:ChaoZhang est là., Date: 2024-02-04 14:42:05 Je vous en prie.
Les étiquettes:

img

Résumé

Cette stratégie utilise les signaux combinés de plusieurs indicateurs techniques pour négocier dynamiquement les actifs sous-jacents tels que les actions et les crypto-monnaies.

Principaux

Cette stratégie tire principalement parti des moyennes mobiles, de l'indice de force relative (RSI), de la plage moyenne réelle (ATR) et de l'indice de mouvement directionnel (ADX) pour générer des signaux de trading.

Le système est basé sur la méthode de l'optimisation de la longueur de la tendance à long terme. Il est basé sur la méthode de l'optimisation de la longueur de la tendance à long terme. Il est basé sur la méthode de l'optimisation de la longueur de tendance à long terme.

En plus des doubles MAs, le RSI est introduit pour confirmer les signaux de tendance et éviter les fausses ruptures.

En outre, ATR est utilisé pour ajuster automatiquement le niveau de stop loss. ATR peut refléter efficacement la volatilité des marchés. Lorsque la volatilité augmente, un stop loss plus large sera réglé pour réduire la probabilité d'être arrêté.

Enfin, l'ADX mesure la force de la tendance. L'ADX utilise la divergence entre l'indicateur positif DI+ et l'indicateur négatif DI- pour mesurer la force de la tendance.

En combinant des signaux provenant de plusieurs indicateurs, la stratégie peut être plus prudente dans l'envoi de signaux de trading, en évitant l'interférence de faux signaux et en obtenant ainsi un taux de gain plus élevé.

Les avantages

Les avantages de cette stratégie sont les suivants:

  1. La combinaison de plusieurs indicateurs améliore la précision des décisions

La combinaison de MA, RSI, ATR, ADX et plus peut améliorer la précision et éviter des jugements erronés dus à un seul indicateur.

  1. Risques liés aux contrôles automatiques de l'ajustement des pertes par arrêt

L'ajustement du stop loss en fonction de la volatilité du marché peut réduire la probabilité d'être arrêté et gérer efficacement les risques.

  1. Le jugement de la force de la tendance évite de négocier contre tendance

En évaluant la force de la tendance avec l'ADX avant la négociation réelle, les pertes résultant de la négociation contre tendance peuvent être réduites.

  1. Grand espace de réglage des paramètres

Les paramètres tels que les longueurs de MA, la longueur du RSI, la période ATR et la période ADX peuvent tous être ajustés et optimisés pour différents marchés.

  1. Protéger les bénéfices à long terme

L'identification des tendances à long terme à l'aide du système de MA rapide et lent et la réduction des bruits à court terme avec des indicateurs tels que l'indicateur RSI permettent de maintenir les tendances à long terme pour obtenir des bénéfices plus élevés.

Risques et solutions

Il existe également quelques risques associés à cette stratégie:

  1. Difficulté d'optimisation des paramètres

Plus de paramètres signifie plus de difficulté dans l'optimisation. Des ensembles de paramètres inappropriés peuvent détériorer les performances de la stratégie. Un backtesting et un réglage des paramètres plus adéquats peuvent atténuer ce risque.

  1. Risque de défaillance de l'indicateur

Tous les indicateurs techniques ont des états de marché applicables. Lorsque les marchés entrent dans des états particuliers, les indicateurs utilisés peuvent échouer simultanément. Les risques de tels événements BLACK SWAN nécessitent une attention particulière.

  1. Risque de perte illimité lié à la mise à court

La stratégie permet de négocier à découvert. Les positions à découvert comportent par nature le risque de pertes illimitées. Cela peut être réduit en définissant un stop loss approprié.

  1. Risque d'inversion de tendance

Les indicateurs ne peuvent pas réagir rapidement aux renversements. Des positions directionnelles erronées entraînent souvent des pertes lors des renversements.

Optimisation

Il est possible d'optimiser davantage:

  1. Poids adaptatif de l'indicateur

Analyser les corrélations entre les indicateurs et l'état du marché et concevoir des mécanismes permettant d'ajuster dynamiquement les pondérations des indicateurs en fonction de l'évolution des conditions du marché afin d'améliorer les décisions.

  1. Augmentation par apprentissage profond

Utiliser des modèles d'apprentissage en profondeur pour prédire les orientations du mouvement des prix et augmenter le système basé sur des règles pour améliorer la précision.

  1. Adaptation des paramètres

Concevoir des modules de réglage adaptatif pour les paramètres des indicateurs basés sur des données historiques de fenêtres coulissantes afin que la stratégie puisse mieux s'adapter.

  1. Incorporer une analyse à période variable

Intégrer l'analyse des périodes variables comme la théorie des ondes d'Elliott pour aider à juger des tendances à moyen et long terme et à améliorer la rentabilité.

Conclusion

En résumé, cette stratégie intègre MA, RSI, ATR, ADX et plus encore dans un système relativement complet, qui peut identifier les tendances à plus long terme via le système MA et réduire les interférences sonores avec des indicateurs à court terme comme le RSI.


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

// This source code to my testing
// © sgb

//@version=5


strategy(title='Soren test 2', overlay=true, initial_capital=100, pyramiding=1, calc_on_order_fills=true, calc_on_every_tick=true, default_qty_type=strategy.percent_of_equity, default_qty_value=50, commission_value=0.04)

//SOURCE =============================================================================================================================================================================================================================================================================================================

src = input(open)

// INPUTS ============================================================================================================================================================================================================================================================================================================



//ADX --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

ADX_options = input.string('MASANAKAMURA', title='Adx Type', options=['CLASSIC', 'MASANAKAMURA'], group='ADX')
ADX_len = input.int(38, title='Adx lenght', minval=1, group='ADX')
th = input.float(23, title='Adx Treshold', minval=0, step=0.5, group='ADX')

// Volume ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

volume_f = input.float(1.2, title='Volume mult.', minval=0, step=0.1, group='Volume')
sma_length = input.int(35, title='Volume lenght', minval=1, group='Volume')

//RSI----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

len_3 = input.int(25, title='RSI lenght', group='Relative Strenght Indeks')
src_3 = input.source(low, title='RSI Source', group='Relative Strenght Indeks')
RSI_VWAP_length = input(25, title='Rsi vwap lenght')

// Range Filter ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

per_ = input.int(26, title='SAMPLING PERIOD', minval=1, group='Range Filter')
mult = input.float(2.3, title='RANGE MULTIPLIER', minval=0.1, step=0.1, group='Range Filter')

// Cloud --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

len = input.int(1, title='Cloud Length', group='Cloud')

//RMI ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

RMI_len = input.int(26, title='Rmi Lenght', minval=1, group='Relative Momentum Index')
mom = input.int(17, title='Rmi Momentum', minval=1, group='Relative Momentum Index')
RMI_os = input.int(33, title='Rmi oversold', minval=0, group='Relative Momentum Index')
RMI_ob = input.int(68, title='Rmi overbought', minval=0, group='Relative Momentum Index')


// Indicators Calculations ========================================================================================================================================================================================================================================================================================================

// Range Filter ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

var bool L_RF = na
var bool S_RF = na

Range_filter(_src, _per_, _mult) =>
    var float _upward = 0.0
    var float _downward = 0.0
    wper = _per_ * 2 - 1
    avrng = ta.ema(math.abs(_src - _src[1]), _per_)
    _smoothrng = ta.ema(avrng, wper) * _mult
    _filt = _src
    _filt := _src > nz(_filt[1]) ? _src - _smoothrng < nz(_filt[1]) ? nz(_filt[1]) : _src - _smoothrng : _src + _smoothrng > nz(_filt[1]) ? nz(_filt[1]) : _src + _smoothrng
    _upward := _filt > _filt[1] ? nz(_upward[1]) + 1 : _filt < _filt[1] ? 0 : nz(_upward[1])
    _downward := _filt < _filt[1] ? nz(_downward[1]) + 1 : _filt > _filt[1] ? 0 : nz(_downward[1])
    [_smoothrng, _filt, _upward, _downward]
[smoothrng, filt, upward, downward] = Range_filter(src, per_, mult)
hband = filt + smoothrng
lband = filt - smoothrng
L_RF := high > hband and upward > 0
S_RF := low < lband and downward > 0

//ADX-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

calcADX(_len) =>
    up = ta.change(high)
    down = -ta.change(low)
    plusDM = na(up) ? na : up > down and up > 0 ? up : 0
    minusDM = na(down) ? na : down > up and down > 0 ? down : 0
    truerange = ta.rma(ta.tr, _len)
    _plus = fixnan(100 * ta.rma(plusDM, _len) / truerange)
    _minus = fixnan(100 * ta.rma(minusDM, _len) / truerange)
    sum = _plus + _minus
    _adx = 100 * ta.rma(math.abs(_plus - _minus) / (sum == 0 ? 1 : sum), _len)
    [_plus, _minus, _adx]
calcADX_Masanakamura(_len) =>
    SmoothedTrueRange = 0.0
    SmoothedDirectionalMovementPlus = 0.0
    SmoothedDirectionalMovementMinus = 0.0
    TrueRange = math.max(math.max(high - low, math.abs(high - nz(close[1]))), math.abs(low - nz(close[1])))
    DirectionalMovementPlus = high - nz(high[1]) > nz(low[1]) - low ? math.max(high - nz(high[1]), 0) : 0
    DirectionalMovementMinus = nz(low[1]) - low > high - nz(high[1]) ? math.max(nz(low[1]) - low, 0) : 0
    SmoothedTrueRange := nz(SmoothedTrueRange[1]) - nz(SmoothedTrueRange[1]) / _len + TrueRange
    SmoothedDirectionalMovementPlus := nz(SmoothedDirectionalMovementPlus[1]) - nz(SmoothedDirectionalMovementPlus[1]) / _len + DirectionalMovementPlus
    SmoothedDirectionalMovementMinus := nz(SmoothedDirectionalMovementMinus[1]) - nz(SmoothedDirectionalMovementMinus[1]) / _len + DirectionalMovementMinus
    DIP = SmoothedDirectionalMovementPlus / SmoothedTrueRange * 100
    DIM = SmoothedDirectionalMovementMinus / SmoothedTrueRange * 100
    DX = math.abs(DIP - DIM) / (DIP + DIM) * 100
    adx = ta.sma(DX, _len)
    [DIP, DIM, adx]
[DIPlusC, DIMinusC, ADXC] = calcADX(ADX_len)
[DIPlusM, DIMinusM, ADXM] = calcADX_Masanakamura(ADX_len)

DIPlus = ADX_options == 'CLASSIC' ? DIPlusC : DIPlusM
DIMinus = ADX_options == 'CLASSIC' ? DIMinusC : DIMinusM
ADX = ADX_options == 'CLASSIC' ? ADXC : ADXM
L_adx = DIPlus > DIMinus and ADX > th
S_adx = DIPlus < DIMinus and ADX > th

// Volume -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Volume_condt = volume > ta.sma(volume, sma_length) * volume_f

//RSI------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

up_3 = ta.rma(math.max(ta.change(src_3), 0), len_3)
down_3 = ta.rma(-math.min(ta.change(src_3), 0), len_3)
rsi_3 = down_3 == 0 ? 100 : up_3 == 0 ? 0 : 100 - 100 / (1 + up_3 / down_3)
L_rsi = rsi_3 < 70
S_rsi = rsi_3 > 30
RSI_VWAP = ta.rsi(ta.vwap(close), RSI_VWAP_length)
RSI_VWAP_overSold = 13
RSI_VWAP_overBought = 68

L_VAP = ta.crossover(RSI_VWAP, RSI_VWAP_overSold)
S_VAP = ta.crossunder(RSI_VWAP, RSI_VWAP_overBought)

//Cloud --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

PI = 2 * math.asin(1)
hilbertTransform(src) =>
    0.0962 * src + 0.5769 * nz(src[2]) - 0.5769 * nz(src[4]) - 0.0962 * nz(src[6])
computeComponent(src, mesaPeriodMult) =>
    hilbertTransform(src) * mesaPeriodMult
computeAlpha(src, fastLimit, slowLimit) =>
    mesaPeriod = 0.0
    mesaPeriodMult = 0.075 * nz(mesaPeriod[1]) + 0.54
    smooth = 0.0
    smooth := (4 * src + 3 * nz(src[1]) + 2 * nz(src[2]) + nz(src[3])) / 10
    detrender = 0.0
    detrender := computeComponent(smooth, mesaPeriodMult)
    I1 = nz(detrender[3])
    Q1 = computeComponent(detrender, mesaPeriodMult)
    jI = computeComponent(I1, mesaPeriodMult)
    jQ = computeComponent(Q1, mesaPeriodMult)
    I2 = 0.0
    Q2 = 0.0
    I2 := I1 - jQ
    Q2 := Q1 + jI
    I2 := 0.2 * I2 + 0.8 * nz(I2[1])
    Q2 := 0.2 * Q2 + 0.8 * nz(Q2[1])
    Re = I2 * nz(I2[1]) + Q2 * nz(Q2[1])
    Im = I2 * nz(Q2[1]) - Q2 * nz(I2[1])
    Re := 0.2 * Re + 0.8 * nz(Re[1])
    Im := 0.2 * Im + 0.8 * nz(Im[1])
    if Re != 0 and Im != 0
        mesaPeriod := 2 * PI / math.atan(Im / Re)
        mesaPeriod
    if mesaPeriod > 1.5 * nz(mesaPeriod[1])
        mesaPeriod := 1.5 * nz(mesaPeriod[1])
        mesaPeriod
    if mesaPeriod < 0.67 * nz(mesaPeriod[1])
        mesaPeriod := 0.67 * nz(mesaPeriod[1])
        mesaPeriod
    if mesaPeriod < 6
        mesaPeriod := 6
        mesaPeriod
    if mesaPeriod > 50
        mesaPeriod := 50
        mesaPeriod
    mesaPeriod := 0.2 * mesaPeriod + 0.8 * nz(mesaPeriod[1])
    phase = 0.0
    if I1 != 0
        phase := 180 / PI * math.atan(Q1 / I1)
        phase
    deltaPhase = nz(phase[1]) - phase
    if deltaPhase < 1
        deltaPhase := 1
        deltaPhase
    alpha = fastLimit / deltaPhase
    if alpha < slowLimit
        alpha := slowLimit
        alpha
    [alpha, alpha / 2.0]
er = math.abs(ta.change(src, len)) / math.sum(math.abs(ta.change(src)), len)
[a, b] = computeAlpha(src, er, er * 0.1)
mama = 0.0
mama := a * src + (1 - a) * nz(mama[1])
fama = 0.0
fama := b * mama + (1 - b) * nz(fama[1])
alpha = math.pow(er * (b - a) + a, 2)
kama = 0.0
kama := alpha * src + (1 - alpha) * nz(kama[1])

L_cloud = kama > kama[1]
S_cloud = kama < kama[1]

// RMI -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

RMI(len, m) =>
    up = ta.ema(math.max(close - close[m], 0), len)
    dn = ta.ema(math.max(close[m] - close, 0), len)
    RMI = dn == 0 ? 0 : 100 - 100 / (1 + up / dn)
    RMI
L_rmi = ta.crossover(RMI(RMI_len, mom), RMI_os)
S_rmi = ta.crossunder(RMI(RMI_len, mom), RMI_ob)



//STRATEGY ==========================================================================================================================================================================================================================================================================================================

L_1 = L_VAP and L_RF and not S_adx
S_1 = S_VAP and S_RF and not L_adx
L_2 = L_adx and Volume_condt and L_rsi and L_cloud
S_2 = S_adx and Volume_condt and S_rsi and S_cloud
L_3 = L_rmi and L_RF and not S_adx
S_3 = S_rmi and S_RF and not L_adx
L_basic_condt = L_1 or L_2 or L_3
S_basic_condt = S_1 or S_2 or S_3

var bool longCondition = na
var bool shortCondition = na
var float last_open_longCondition = na
var float last_open_shortCondition = na
var int last_longCondition = 0
var int last_shortCondition = 0
longCondition := L_basic_condt
shortCondition := S_basic_condt
last_open_longCondition := longCondition ? close : nz(last_open_longCondition[1])
last_open_shortCondition := shortCondition ? close : nz(last_open_shortCondition[1])
last_longCondition := longCondition ? time : nz(last_longCondition[1])
last_shortCondition := shortCondition ? time : nz(last_shortCondition[1])
in_longCondition = last_longCondition > last_shortCondition
in_shortCondition = last_shortCondition > last_longCondition

// SWAP-SL ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

var int last_long_sl = na
var int last_short_sl = na
sl = input.float(2, 'Swap % period', minval=0, step=0.1, group='strategy settings')
long_sl = ta.crossunder(low, (1 - sl / 100) * last_open_longCondition) and in_longCondition and not longCondition
short_sl = ta.crossover(high, (1 + sl / 100) * last_open_shortCondition) and in_shortCondition and not shortCondition
last_long_sl := long_sl ? time : nz(last_long_sl[1])
last_short_sl := short_sl ? time : nz(last_short_sl[1])
var bool CondIni_long_sl = 0
CondIni_long_sl := long_sl ? 1 : longCondition ? -1 : nz(CondIni_long_sl[1])
var bool CondIni_short_sl = 0
CondIni_short_sl := short_sl ? 1 : shortCondition ? -1 : nz(CondIni_short_sl[1])
Final_Long_sl = long_sl and nz(CondIni_long_sl[1]) == -1 and in_longCondition and not longCondition
Final_Short_sl = short_sl and nz(CondIni_short_sl[1]) == -1 and in_shortCondition and not shortCondition
var int sectionLongs = 0
sectionLongs := nz(sectionLongs[1])
var int sectionShorts = 0
sectionShorts := nz(sectionShorts[1])

// RE-ENTRY ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

if longCondition or Final_Long_sl
    sectionLongs += 1
    sectionShorts := 0
    sectionShorts
if shortCondition or Final_Short_sl
    sectionLongs := 0
    sectionShorts += 1
    sectionShorts
var float sum_long = 0.0
var float sum_short = 0.0

if longCondition
    sum_long := nz(last_open_longCondition) + nz(sum_long[1])
    sum_short := 0.0
    sum_short
if Final_Long_sl
    sum_long := (1 - sl / 100) * last_open_longCondition + nz(sum_long[1])
    sum_short := 0.0
    sum_short
if shortCondition
    sum_short := nz(last_open_shortCondition) + nz(sum_short[1])
    sum_long := 0.0
    sum_long
if Final_Short_sl
    sum_long := 0.0
    sum_short := (1 + sl / 100) * last_open_shortCondition + nz(sum_short[1])
    sum_short

var float Position_Price = 0.0
Position_Price := nz(Position_Price[1])
Position_Price := longCondition or Final_Long_sl ? sum_long / sectionLongs : shortCondition or Final_Short_sl ? sum_short / sectionShorts : na

//TP_1 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

tp = input.float(1.2, 'Tp-1 ', minval=0, step=0.1, group='strategy settings')
long_tp = ta.crossover(high, (1 + tp / 100) * fixnan(Position_Price)) and in_longCondition and not longCondition
short_tp = ta.crossunder(low, (1 - tp / 100) * fixnan(Position_Price)) and in_shortCondition and not shortCondition
var int last_long_tp = na
var int last_short_tp = na
last_long_tp := long_tp ? time : nz(last_long_tp[1])
last_short_tp := short_tp ? time : nz(last_short_tp[1])
Final_Long_tp = long_tp and last_longCondition > nz(last_long_tp[1])
Final_Short_tp = short_tp and last_shortCondition > nz(last_short_tp[1])
fixnan_1 = fixnan(Position_Price)
ltp = Final_Long_tp ? fixnan_1 * (1 + tp / 100) : na
fixnan_2 = fixnan(Position_Price)
stp = Final_Short_tp ? fixnan_2 * (1 - tp / 100) : na
if Final_Short_tp or Final_Long_tp
    sum_long := 0.0
    sum_short := 0.0
    sectionLongs := 0
    sectionShorts := 0
    sectionShorts
if Final_Long_tp
    CondIni_long_sl == 1
if Final_Short_tp
    CondIni_short_sl == 1


// COLORS & PLOTS --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

ADX_COLOR = L_adx ? color.lime : S_adx ? color.red : color.orange
barcolor(color=ADX_COLOR)
hbandplot = plot(hband, title='RF HT', color=ADX_COLOR, transp=50)
lbandplot = plot(lband, title='RF LT', color=ADX_COLOR, transp=50)
fill(hbandplot, lbandplot, title='RF TR', color=ADX_COLOR, transp=90)
plotshape(longCondition, title='Long', style=shape.triangleup, location=location.belowbar, color=color.new(color.blue, 0), size=size.tiny)
plotshape(shortCondition, title='Short', style=shape.triangledown, location=location.abovebar, color=color.new(color.red, 0), size=size.tiny)

plot(ltp, style=plot.style_circles, linewidth=5, color=color.new(color.fuchsia, 0), editable=false)
plot(stp, style=plot.style_circles, linewidth=5, color=color.new(color.fuchsia, 0), editable=false)

//BACKTESTING--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Q = 50
SL = input.float(0.4, 'StopLoss ', minval=0, step=0.1)

strategy.entry('long', strategy.long, when=longCondition)
strategy.entry('short', strategy.short, when=shortCondition)

strategy.exit('TP', 'long', qty_percent=Q, limit=fixnan(Position_Price) * (1 + tp / 100))
strategy.exit('TP', 'short', qty_percent=Q, limit=fixnan(Position_Price) * (1 - tp / 100))


strategy.exit('SL', 'long', stop=fixnan(Position_Price) * (1 - SL / 100))
strategy.exit('SL', 'short', stop=fixnan(Position_Price) * (1 + SL / 100))


//
//
//
//
//
//

// By SGB







Plus de