Stratégie de combinaison d'indicateurs d'oscillation quantitative

Auteur:ChaoZhang est là., Date: le 27 février 2024 16h46
Les étiquettes:

img

Résumé

Cette stratégie combine l'oscillateur élégant d'Ehlers, le décycleur d'Ehlers, la ligne de tendance instantanée d'Ehlers et le coefficient de corrélation de rang d'Ehlers Spearman en une seule stratégie, formant une stratégie de trading quantitative qui capture pleinement les tendances, les oscillations, l'élan et les caractéristiques de prix et de volume.

Principes de stratégie

Cette stratégie utilise 4 indicateurs clés pour le jugement.

Premièrement, l'oscillateur élégant d'Ehlers, où la différence entre la ligne d'origine et la ligne de signal lissée par une moyenne mobile exponentielle peut déterminer la direction et la force de la tendance actuelle. Deuxièmement, le décyclateur d'Ehlers, qui peut identifier efficacement les points bas du cycle et déterminer si la tendance majeure est en train de s'inverser. Ensuite, la ligne de tendance instantanée d'Ehlers suit les moyennes mobiles rapides pour juger des directions de tendance à court terme. Enfin, le coefficient de corrélation de rang d'Ehlers Spearman juge la relation prix-volume, qui peut filtrer efficacement les fausses ruptures.

Plus précisément, les quatre conditions d'entrée de la stratégie sont les suivantes: la ligne de signal de l'oscillateur élégant et la ligne de signal du décycleur franchissant simultanément au-dessus de 0, la ligne d'origine franchissant au-dessus de la ligne du décycleur, la ligne d'origine étant supérieure à la ligne de tendance instantanée en hausse et un coefficient de corrélation de rang Spearman positif.

Les conditions de sortie sont beaucoup plus simples: sortie lorsque la ligne d'origine tombe en dessous de la ligne de tendance instantanée.

Les conditions courtes sont similaires aux conditions longues, seulement inversées.

Analyse des avantages

Le plus grand avantage de cette stratégie réside dans la combinaison appropriée d'indicateurs, qui peuvent tirer efficacement parti des points forts de chaque indicateur, se vérifier mutuellement, éviter les faux positifs, filtrer beaucoup de bruit et générer des signaux plus fiables.

Plus précisément, l'oscillateur élégant peut juger de la direction et de la force de la tendance, le décycleur peut juger des points tournants du cycle, la ligne de tendance instantanée peut juger des tendances à court terme et le classement Spearman juge la relation prix-volume.

En outre, en utilisant uniquement les prix à moyen terme comme référence, la stratégie évite les interférences du bruit de marché à court terme et réduit les opérations de renversement inutiles.

Analyse des risques

Le plus grand risque de cette stratégie est l'absence d'un mécanisme de stop loss. En cas de mouvements violents du marché, l'incapacité d'arrêter la perte à temps peut entraîner de plus grandes pertes. Il manque également de filtres supplémentaires tels que les canaux de Donchian et les indicateurs d'énergie qui peuvent conduire à un certain degré de transactions faussement positives.

Pour atténuer ces risques, un stop loss protecteur peut être configuré pour arrêter automatiquement les pertes lorsque les pertes dépassent certains niveaux.

Directions d'optimisation

La stratégie peut être optimisée dans les aspects suivants:

  1. Ajoutez un mécanisme de gestion des risques de stop loss. Calculer le retrait historique maximum pour définir les niveaux de stop loss appropriés.

  2. Ajoutez plus de filtres, des indicateurs comme le MACD, les bandes de Bollinger pour plus de filtrage pour réduire encore les faux signaux.

  3. Incorporer plus de délais. Actuellement, un seul ensemble de paramètres est utilisé. Plus de délais peuvent être ajoutés pour la vérification à plusieurs délais pour améliorer la stabilité.

  4. Ajustez dynamiquement les paramètres. Ajoutez l'optimisation des paramètres pour ajuster dynamiquement les paramètres des indicateurs en fonction des conditions changeantes du marché afin d'améliorer l'adaptabilité.

  5. Arbitrage croisé des actifs: appliquer une stratégie sur différents actifs pour rechercher des opportunités d'arbitrage afin de mieux contrôler les risques.

Conclusion

Cette stratégie combine habilement 4 indicateurs Ehlers majeurs pour former une stratégie qui juge les tendances, les cycles, l'élan et le volume des prix dans tous les aspects. Elle possède d'excellentes capacités de filtrage du bruit et peut produire des signaux de haute qualité. Mais l'absence d'un stop loss et de filtrage d'indicateur auxiliaire l'expose à certains risques. En ajoutant des stop losses, des filtres, plus de délais, etc., elle peut être efficacement optimisée pour une plus grande stabilité et fiabilité.


/*backtest
start: 2024-01-01 00:00:00
end: 2024-01-31 23:59:59
period: 2h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © simwai

//@version=5
strategy('Ehlers Elegant Oscillator + Ehlers Decycler + Ehlers Instantaneous + Ehlers Spearman Rank', 'Ehlers Combo', overlay=true, margin_long=100, margin_short=100)

// -- Inputs --
inp = input(title='Source', defval=close)
res = input.timeframe(title='Resolution', defval='')
bar = input(title='Allow Bar Color Change?', defval=true)
src = inp
length = input.int(title='Length', defval=20, minval=2, maxval=300)
rmsLength = input.int(title='Rms Length', defval=50, minval=2)
decyclerLength = length

// -- Calculation --
// Ehlers Elegant Oscillator
a1 = math.exp(-1.414 * math.pi / length)
b1 = 2 * a1 * math.cos(1.414 * math.pi / length)
c2 = b1
c3 = -a1 * a1
c1 = 1 - c2 - c3

deriv = src - nz(src[2])
rms = math.avg(math.pow(deriv, 2), rmsLength)
rms := rms != 0 ? math.sqrt(rms) : 0
nDeriv = rms != 0 ? deriv / rms : 0
iFish = nDeriv != 0 ? (math.exp(2 * nDeriv) - 1) / (math.exp(2 * nDeriv) + 1) : 0

ss = 0.0
ss := bar_index < 3 ? 0 : (c1 * ((iFish + nz(iFish[1])) / 2)) + (c2 * nz(ss[1])) + (c3 * nz(ss[2]))
ssSig = ta.wma(ss, length)

slo = ss - ssSig
sig = slo > 0 ? slo > nz(slo[1]) ? 2 : 1 : slo < 0 ? slo < nz(slo[1]) ? -2 : -1 : 0
eoColor = sig > 1 ? color.green : sig > 0 ? color.lime : sig < -1 ? color.maroon : sig < 0 ? color.red : color.black

hline(0)
plot(ssSig, title='EO', color=eoColor, linewidth=2)

// Ehlers Decycler
pi = 2 * math.asin(1)
twoPiPrd = 2 * pi / decyclerLength
alpha = (math.cos(twoPiPrd) + math.sin(twoPiPrd) - 1) / math.cos(twoPiPrd)

dec = 0.0
dec := ((alpha / 2) * (src + nz(src[1]))) + ((1 - alpha) * nz(dec[1]))

decyclerSig = src > dec ? 1 : src < dec ? -1 : 0
decColor = decyclerSig > 0 ? color.green : decyclerSig < 0 ? color.red : color.black
plot(dec, title='Decycler', color=decColor, linewidth=2)

// Ehlers Instantaneous Trendline
getItrend(src, alpha) =>
    Price = src
    Smooth = 0.0
    ITrend = 0.0
    Trigger = 0.0
    
    ITrend := (alpha - alpha * alpha / 4) * Price + .5 * alpha * alpha  * Price[1] - (alpha - .75 * alpha * alpha) * Price[2] + 2 * (1 - alpha) * nz(ITrend[1]) - (1 - alpha) * (1 - alpha) * nz(ITrend[2])
    if(bar_index < 7)
        ITrend := (Price + 2 * Price[1] + Price[2]) / 4
    Trigger := 2 * ITrend - ITrend[2]
    [ITrend, Trigger]

itrendAlpha = 2 / (length + 1) / 2
[iT, Tr] = getItrend(src, itrendAlpha)

iTColor = Tr > iT ? color.aqua : color.maroon
plot(iT, 'Instantaneous Trend', iTColor, 2)

// Ehlers Spearman Rank
priceArray = array.new_float(300, 0.0)
rank = array.new_float(300, 0.0)
for i = 1 to length
    array.set(priceArray, i, nz(src[i - 1]))
    array.set(rank, i, i)

for i = 1 to length
    count = length + 1 - i
    for j = 1 to length - count
        if array.get(priceArray, j + 1) < array.get(priceArray, j)
            tempPrice = array.get(priceArray, j)
            tempRank = array.get(rank, j)
            array.set(priceArray, j, array.get(priceArray, j + 1))
            array.set(rank, j, array.get(rank, j + 1))
            array.set(priceArray, j + 1, tempPrice)
            array.set(rank, j + 1, tempRank)
         
sum = 0.0   
for i = 1 to length
    sum := sum + math.pow(i - array.get(rank, i), 2)
signal = 2 * (0.5 - (1 - ((6 * sum) / (length * (math.pow(length, 2) - 1)))))
spearmanSlo = signal - nz(signal[1])
spearmanSig = spearmanSlo > 0 or signal > 0 ? spearmanSlo > nz(spearmanSlo[1]) ? 2 : 1 : spearmanSlo < 0 or signal < 0 ? spearmanSlo < nz(spearmanSlo[1]) ? -2 : -1 : 0

// -- Signals --
bool enterLong = ta.crossover(sig, 0) and ta.crossover(decyclerSig, 0) and ta.crossover(src, dec) and (src > iT) and iT[1] < iT and spearmanSig > 0
bool enterShort = ta.crossunder(sig, 0) and ta.crossunder(decyclerSig, 0) and ta.crossunder(src, dec) and (src < iT) and iT[1] > iT and spearmanSig < 0
bool exitLong = ta.crossunder(src[100], iT) 
bool exitShort = ta.crossover(src[100], iT)

barcolor(bar and strategy.position_size > 0 ? color.green : bar and strategy.position_size < 0 ? color.red : color.gray)

// -- Long Exits --
strategy.close('long', when=exitLong and strategy.position_size > 0, comment='EXIT_LONG')

// -- Short Exits --
strategy.close('short', when=exitShort and strategy.position_size < 0, comment='EXIT_SHORT')

bool isStrategyEntryEnabled = true
// -- Long Entries --
if (isStrategyEntryEnabled)
    strategy.entry('long', strategy.long, when=enterLong, comment='ENTER_LONG')
else
    strategy.order('long', strategy.long, when=enterLong, comment='ENTER_LONG')

// -- Short Entries --
if (isStrategyEntryEnabled)
    strategy.entry('short', strategy.short, when=enterShort, comment='ENTER_SHORT')
else
    strategy.order('short', strategy.short, when=enterShort, comment='ENTER_SHORT')



Plus de