Stratégie de trading de tendance de sentiment de chandelier basée sur des indicateurs quantitatifs

CEI ADX RSI MACD VOLUME SMA
Date de création: 2025-02-21 13:23:51 Dernière modification: 2025-02-21 13:23:51
Copier: 1 Nombre de clics: 361
2
Suivre
319
Abonnés

Stratégie de trading de tendance de sentiment de chandelier basée sur des indicateurs quantitatifs Stratégie de trading de tendance de sentiment de chandelier basée sur des indicateurs quantitatifs

Aperçu

La stratégie est basée sur l’analyse graphique de l’humeur du marché et quantifie la psychologie du marché à l’aide de trois oscillateurs principaux: oscillateur de réticence, oscillateur de peur et oscillateur de cupidité. La stratégie intègre des indicateurs de dynamique et de tendance, tout en combinant la confirmation de transaction pour construire un système de trading complet.

Principe de stratégie

Le cœur de la stratégie est de construire trois oscillateurs d’émotions en analysant les différentes configurations de l’image:

  1. L’oscillateur de hésitation - mesure de l’incertitude du marché à l’aide de la forme d’une croix et d’un tourbillon
  2. L’oscillateur de la peur - pour suivre les émotions à travers des météorites, des lignes d’ascension et des formes de déglutition de la baisse
  3. L’oscillateur de la cupidité - détecte l’humeur polygame par des rayons de soleil à tête nue, des fils de souris, des engloutissements de guêpes et des trois soldats blancs

La moyenne de ces trois oscillateurs constitue l’indice de l’émotion des bulls ((CEI)). Le signal de négociation de bullish est déclenché lorsque le CEI franchit différents seuils et est confirmé par le volume des transactions.

Avantages stratégiques

  1. L’analyse émotionnelle systématique - la transformation de l’analyse subjective en indicateur objectif par le biais d’une morphologie quantitative
  2. Gestion des risques - incluant des mécanismes tels que la période de détention maximale, le stop loss et la période de refroidissement
  3. Mécanisme de récupération flexible - lorsque la transaction est perdue, la stratégie tente de récupérer en franchissant le point d’équilibre
  4. Utilisation sur plusieurs marchés, tels que les actions, les devises et les crypto-monnaies
  5. Haute fiabilité des signaux - accroissement de l’exactitude grâce à la confirmation du volume de transactions et à la vérification de plusieurs indicateurs techniques

Risque stratégique

  1. Sensibilité des paramètres - les paramètres de toutes les classes de seuils doivent être testés et optimisés
  2. Dépendance aux conditions du marché - peut générer des signaux erronés dans un marché instable
  3. Risque de glissement - risque d’exécution possible dans un marché moins liquide
  4. Risque de sur-transaction - une période de refroidissement raisonnable est nécessaire pour éviter des transactions fréquentes
  5. Risque systémique - risque de pertes élevées lors d’événements majeurs sur le marché

Orientation de l’optimisation de la stratégie

  1. Dépréciation dynamique - ajustement automatique des dépréciations en fonction de la volatilité du marché
  2. Classification de l’état du marché - mécanisme d’identification des marchés à tendance croissante et aux chocs
  3. Optimisation de l’apprentissage automatique - optimisation des combinaisons de paramètres avec des algorithmes d’apprentissage automatique
  4. Amélioration de la gestion des risques - ajout de modules de gestion des fonds et de contrôle des positions
  5. Filtrage des signaux - intégration de plus d’indicateurs techniques pour filtrer les faux signaux

Résumer

Il s’agit d’une stratégie innovante qui combine l’analyse technique et la négociation quantitative. Grâce à une analyse des émotions systématique et à une gestion rigoureuse des risques, la stratégie est capable de fournir aux traders des signaux de négociation fiables. Bien qu’il existe une certaine marge d’optimisation, le cadre de base de la stratégie est robuste et adapté à un développement ultérieur et à une application sur le terrain.

Code source de la stratégie
/*backtest
start: 2024-03-09 18:40:00
end: 2025-02-19 08:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Binance","currency":"SOL_USDT"}]
*/

//@version=6
strategy("Candle Emotion Index Strategy", shorttitle="CEI Strategy", overlay=true)

// User Inputs
length = input.int(14, title="Lookback Period", minval=1)
dojiThreshold = input.float(0.1, title="Doji Threshold", minval=0.01, maxval=0.5)
spinningTopThreshold = input.float(0.3, title="Spinning Top Threshold", minval=0.1, maxval=0.5)
shootingStarThreshold = input.float(0.5, title="Shooting Star Threshold", minval=0.1, maxval=1.0)
hangingManThreshold = input.float(0.5, title="Hanging Man Threshold", minval=0.1, maxval=1.0)
engulfingThreshold = input.float(0.5, title="Engulfing Threshold", minval=0.1, maxval=1.0)
marubozuThreshold = input.float(0.9, title="Marubozu Threshold", minval=0.5, maxval=1.0)
hammerThreshold = input.float(0.5, title="Hammer Threshold", minval=0.1, maxval=1.0)
threeWhiteSoldiersThreshold = input.float(0.5, title="Three White Soldiers Threshold", minval=0.1, maxval=1.0)

// Volume Multiplier Input
volumeMultiplier = input.float(1.5, title="Volume Multiplier", minval=1.0)

// Cooldown Period Input
cooldownPeriod = input.int(10, title="Cooldown Period (Candles)", minval=1)

// Maximum Holding Period Inputs
maxHoldingPeriod = input.int(20, title="Maximum Holding Period (Candles)", minval=1)
lossHoldingPeriod = input.int(10, title="Loss Exit Holding Period (Candles)", minval=1)
lossThreshold = input.float(0.02, title="Loss Threshold (as % of Entry Price)", minval=0.01, maxval=1.0)

// --- Indecision Oscillator Functions ---
isDoji(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    rangeSize = high - low
    bodySize / rangeSize < threshold

isSpinningTop(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    rangeSize = high - low
    bodySize / rangeSize < threshold and bodySize / rangeSize >= dojiThreshold

indecisionOscillator() =>
    var float dojiScore = 0.0
    var float spinningTopScore = 0.0
    for i = 1 to length
        if isDoji(open[i], close[i], high[i], low[i], dojiThreshold)
            dojiScore := dojiScore + 1.0
        if isSpinningTop(open[i], close[i], high[i], low[i], spinningTopThreshold)
            spinningTopScore := spinningTopScore + 1.0
    dojiScore := dojiScore / length
    spinningTopScore := spinningTopScore / length
    (dojiScore + spinningTopScore) / 2

// --- Fear Oscillator Functions ---
isShootingStar(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    upperWick = high - math.max(open, close)
    lowerWick = math.min(open, close) - low
    upperWick / bodySize > threshold and lowerWick < bodySize

isHangingMan(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    upperWick = high - math.max(open, close)
    lowerWick = math.min(open, close) - low
    lowerWick / bodySize > threshold and upperWick < bodySize

isBearishEngulfing(open, close, openPrev, closePrev, threshold) =>
    bodySize = math.abs(close - open)
    prevBodySize = math.abs(closePrev - openPrev)
    close < openPrev and open > closePrev and bodySize / prevBodySize > threshold

fearOscillator() =>
    var float shootingStarScore = 0.0
    var float hangingManScore = 0.0
    var float engulfingScore = 0.0
    for i = 1 to length
        if isShootingStar(open[i], close[i], high[i], low[i], shootingStarThreshold)
            shootingStarScore := shootingStarScore + 1.0
        if isHangingMan(open[i], close[i], high[i], low[i], hangingManThreshold)
            hangingManScore := hangingManScore + 1.0
        if isBearishEngulfing(open[i], close[i], open[i+1], close[i+1], engulfingThreshold)
            engulfingScore := engulfingScore + 1.0
    shootingStarScore := shootingStarScore / length
    hangingManScore := hangingManScore / length
    engulfingScore := engulfingScore / length
    (shootingStarScore + hangingManScore + engulfingScore) / 3

// --- Greed Oscillator Functions ---
isMarubozu(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    totalRange = high - low
    bodySize / totalRange > threshold

isHammer(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    lowerWick = math.min(open, close) - low
    upperWick = high - math.max(open, close)
    lowerWick / bodySize > threshold and upperWick < bodySize

isBullishEngulfing(open, close, openPrev, closePrev, threshold) =>
    bodySize = math.abs(close - open)
    prevBodySize = math.abs(closePrev - openPrev)
    close > openPrev and open < closePrev and bodySize / prevBodySize > threshold

isThreeWhiteSoldiers(open, close, openPrev, closePrev, openPrev2, closePrev2, threshold) =>
    close > open and closePrev > openPrev and closePrev2 > openPrev2 and close > closePrev and closePrev > closePrev2

greedOscillator() =>
    var float marubozuScore = 0.0
    var float hammerScore = 0.0
    var float engulfingScore = 0.0
    var float soldiersScore = 0.0
    for i = 1 to length
        if isMarubozu(open[i], close[i], high[i], low[i], marubozuThreshold)
            marubozuScore := marubozuScore + 1.0
        if isHammer(open[i], close[i], high[i], low[i], hammerThreshold)
            hammerScore := hammerScore + 1.0
        if isBullishEngulfing(open[i], close[i], open[i+1], close[i+1], engulfingThreshold)
            engulfingScore := engulfingScore + 1.0
        if isThreeWhiteSoldiers(open[i], close[i], open[i+1], close[i+1], open[i+2], close[i+2], threeWhiteSoldiersThreshold)
            soldiersScore := soldiersScore + 1.0
    marubozuScore := marubozuScore / length
    hammerScore := hammerScore / length
    engulfingScore := engulfingScore / length
    soldiersScore := soldiersScore / length
    (marubozuScore + hammerScore + engulfingScore + soldiersScore) / 4

// --- Final Calculations ---
indecision = indecisionOscillator()
fear = fearOscillator()
greed = greedOscillator()

// Calculate the average of the three oscillators
averageOscillator = (indecision + fear + greed) / 3

// --- Combined Strategy Logic ---
var float entryPriceLong = na
var float entryPriceShort = na
var int holdingPeriodLong = 0
var int holdingPeriodShort = 0
var int cooldownCounter = 0

// Buy Signal Logic for Long and Short
longBuySignal = ta.crossover(averageOscillator, 0.1)
shortBuySignal = ta.crossover(averageOscillator, 0.2)

// Calculate average volume over the lookback period
avgVolume = ta.sma(volume, length)

// Take Profit Conditions
longTakeProfitCondition = close > open and volume > avgVolume * volumeMultiplier
shortTakeProfitCondition = close < open and volume > avgVolume * volumeMultiplier

// Buy Logic for Long Positions
if longBuySignal and strategy.position_size == 0 and cooldownCounter <= 0
    entryPriceLong := close
    strategy.entry("Long Entry", strategy.long)
    cooldownCounter := cooldownPeriod
    holdingPeriodLong := 0

// Increment holding period if in a long position
if strategy.position_size > 0
    holdingPeriodLong := holdingPeriodLong + 1

// Sell Logic for Long Positions
if longTakeProfitCondition and strategy.position_size > 0 and close > entryPriceLong
    strategy.close_all()
    cooldownCounter := cooldownPeriod

if holdingPeriodLong >= maxHoldingPeriod and strategy.position_size > 0 and close >= entryPriceLong
    strategy.close_all()
    cooldownCounter := cooldownPeriod

if holdingPeriodLong >= lossHoldingPeriod and strategy.position_size > 0 and close < entryPriceLong * (1 - lossThreshold)
    strategy.close_all()
    cooldownCounter := cooldownPeriod

// Short Logic for Short Positions
if shortBuySignal and strategy.position_size == 0 and cooldownCounter <= 0
    entryPriceShort := close
    strategy.entry("Short Entry", strategy.short)
    cooldownCounter := cooldownPeriod
    holdingPeriodShort := 0

// Increment holding period if in a short position
if strategy.position_size < 0
    holdingPeriodShort := holdingPeriodShort + 1

// Cover Logic for Short Positions
if shortTakeProfitCondition and strategy.position_size < 0 and close < entryPriceShort
    strategy.close_all()
    cooldownCounter := cooldownPeriod

if holdingPeriodShort >= maxHoldingPeriod and strategy.position_size < 0 and close <= entryPriceShort
    strategy.close_all()
    cooldownCounter := cooldownPeriod

if holdingPeriodShort >= lossHoldingPeriod and strategy.position_size < 0 and close > entryPriceShort * (1 + lossThreshold)
    strategy.close_all()
    cooldownCounter := cooldownPeriod

// Decrement the cooldown counter each candle
if cooldownCounter > 0
    cooldownCounter := cooldownCounter - 1