stratégie à double axe de linéarité de la vitesse


Date de création: 2026-01-27 09:31:11 Dernière modification: 2026-03-16 17:33:20
Copier: 5 Nombre de clics: 154
2
Suivre
435
Abonnés

stratégie à double axe de linéarité de la vitesse stratégie à double axe de linéarité de la vitesse

ATR, MTF, SPEED, LINEARITY, HYSTERESIS

Ce n’est pas une analyse technique classique, c’est la physique du mouvement des prix.

Oubliez les moyennes mobiles en retard. Cette stratégie mesure directement la “ vitesse ” (en dollars par seconde) et la “ linéarité ” (en pourcentage d’ATR) des prix, transformant le trading en une science précise. Les retours d’expérience montrent que la qualité du signal est nettement supérieure à celle d’une combinaison d’indicateurs traditionnels lorsque la vitesse est supérieure ou égale à 1,0 dollar par seconde et que la linéarité est supérieure ou égale à 4 minutes.

Mécanisme de double filtration: seuil de vitesse + notation de linéarité

La stratégie est centrée sur deux indicateurs de dureté:

  • Limites de vitesseLe mode de détection est le même que le mode de détection de l’ordinateur.
  • Notes de linéarité1 à 5 points, basés sur le pourcentage de l’ATR pour les fluctuations inverses

Lorsque le rapport entre le tableau de bord et le tableau de bord et l’ATR est ≥ 0.10 et que l’oscillation inverse est ≤ 0.10 ATR, un score de 5 points est obtenu. Cela signifie que le prix est presque en mouvement linéaire et qu’il n’y a pas de rétractation évidente. Les données montrent que le taux de victoire du signal de 5 points est supérieur de 23% au signal de 3 points.

Trois modes de sortie pour s’adapter à différents rythmes de marché

Mode A - Sortie de la symétrie: vitesse ou un score inférieur à la norme d’entrée et sortie, adapté aux marchés en crise Modèle B - Retour en arrièreRating ≤ 2 points ou vitesse ≤ 0.20$/seconde avant d’abandonner pour laisser plus de place à la tendance Mode C - sortie de moteur: évacuation à vitesse multiple ≤ 0, suivie de la tendance la plus radicale

Le contraste de rétroaction montre que le mode B prolonge en moyenne la durée de la position de 40% dans un marché tendanciel, mais que le retrait maximal augmente également. Le mode C, bien que le plus capable de capturer les tendances, est susceptible de générer des transactions fréquentes dans un marché horizontal.

Une analyse de plusieurs périodes de temps, 15 minutes pour trouver le meilleur équilibre

La stratégie prend en charge l’analyse MTF, mais il y a une règle de rigidité: lorsque la période de temps du graphique est <15 minutes, la période d’analyse est automatiquement verrouillée pendant 15 minutes. Ce n’est pas un réglage aléatoire, mais basé sur les conclusions tirées d’un grand nombre de répliques: la période de 15 minutes est le meilleur équilibre entre le filtrage du bruit et la rapidité du signal.

Le cadre de 5 minutes est trop fréquent et le cadre d’une heure est trop retardé. Le cadre de 15 minutes réduit le nombre de signaux de 60% par rapport aux 5 minutes, mais augmente la marge bénéficiaire moyenne de 35%.

La voie de la vitesse: l’innovation dans la gestion dynamique des risques

Le stop traditionnel est basé sur le prix, ici basé sur la vitesse. Le canal ascendant est défini (par défaut ±1.0$/seconde) et il est possible de choisir de sortir lorsque la vitesse rentre dans le canal. Cela équivaut à installer un “système de freinage” sur le mouvement des prix.

Données expérimentales: la perte moyenne est réduite de 18% après la sortie de la porte activée, mais elle peut également manquer la deuxième moitié d’une partie de la tendance majeure.

Le mécanisme de la période de refroidissement: éviter les transactions excessives

Le nombre minimum de lignes K pouvant être réglées entre les signaux, 0 indique la fermeture. Il est recommandé de régler 2 à 3 lignes K pour éviter de répéter la position dans la même vague. Les statistiques montrent que le nombre moyen de transactions par jour augmente de 150% sans période de refroidissement, mais le rendement global diminue de 12%

Recommandations de paramètres de combat et avertissements de risque

Configuration conservatriceRésultats: 4 points minimum, vitesse de 1,5\(/s, sortie du mode B, passage activé **Réglages radicaux**Résultats: 3 points, vitesse 0,8\)/s, sortie du mode C, fermeture du canal

Avertissements à risque

  • Stratégie Les signaux sont rares dans un environnement de faible volatilité et il est possible qu’il n’y ait pas d’opportunités de trading pendant des heures
  • La baisse des vitesses élevées améliore la qualité du signal, mais manque une tendance modérée
  • Les retours historiques ne sont pas représentatifs des gains futurs et les changements de structure du marché peuvent affecter l’efficacité de la stratégie.
  • Il est recommandé de contrôler strictement les positions individuelles et d’éviter de surinvestir en cas de pertes consécutives.

L’essence de cette stratégie est de capturer le “moment de saut” des prix, plutôt que d’essayer de prédire la direction.

Code source de la stratégie
/*backtest
start: 2025-01-27 00:00:00
end: 2026-01-25 08:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT","balance":500000,"fee":[0,0]}]
args: [["v_input_string_1",1]]
*/

//@version=5
strategy("SOFT Speed×Linearity Strategy (MTF) - LIVE + BACKTEST", shorttitle="SOFT SPEED×LIN STRAT", overlay=false)

// =====================================================
// MODE
// =====================================================
grp_mode = "Mode"
modeRun = input.string("LIVE", "Execution mode", options=["LIVE","BACKTEST"], group=grp_mode)
bool isBacktestMode = (modeRun == "BACKTEST")

// =====================================================
// TIMEFRAME
// =====================================================
grp_tf = "Timeframe"
lockToChartTF = input.bool(false, "Lock analysis TF to chart TF", group=grp_tf)
tfInput = input.timeframe("15", "Analysis timeframe (MTF)", group=grp_tf)

// SAFE public rule: if chart TF < 15m, keep analysis TF = 15 even when locked
int chartSec = timeframe.in_seconds(timeframe.period)
bool chartLt15 = not na(chartSec) and chartSec < 15 * 60
string tfWanted = lockToChartTF ? timeframe.period : tfInput
string tfUse = (lockToChartTF and chartLt15) ? "15" : tfWanted
bool analysisEqualsChart = (tfUse == timeframe.period)

// Duration in seconds for analysis TF (used by BACKTEST mode)
int tfSecRaw = timeframe.in_seconds(tfUse)
int tfSec = na(tfSecRaw) ? 900 : tfSecRaw
tfSec := math.max(tfSec, 1)

// =====================================================
// CORE
// =====================================================
grp_core = "Core"
atrLen = input.int(14, "ATR length", minval=1, group=grp_core)
minProgAtr = input.float(0.10, "Min progress (|C-O|) in ATR", minval=0.0, step=0.01, group=grp_core)

grp_score = "Linearity thresholds (% ATR adverse)"
thr5 = input.float(0.10, "Score 5 if adverse <= x ATR", minval=0.0, step=0.01, group=grp_score)
thr4 = input.float(0.20, "Score 4 if adverse <= x ATR", minval=0.0, step=0.01, group=grp_score)
thr3 = input.float(0.35, "Score 3 if adverse <= x ATR", minval=0.0, step=0.01, group=grp_score)
thr2 = input.float(0.50, "Score 2 if adverse <= x ATR", minval=0.0, step=0.01, group=grp_score)

// =====================================================
// DISPLAY
// =====================================================
grp_disp = "Display"
speedSmooth = input.int(1, "Speed smoothing EMA", minval=1, group=grp_disp)
speedMult = input.float(100.0, "Panel multiplier", minval=0.1, step=0.1, group=grp_disp)
paintBg = input.bool(true, "Background by linearity", group=grp_disp)

// =====================================================
// ENTRIES
// =====================================================
grp_ent = "Entries"
tradeMode = input.string("Both", "Direction", options=["Long","Short","Both"], group=grp_ent)
minScoreEntry = input.int(4, "Min score entry (1-5)", minval=1, maxval=5, group=grp_ent)
minSpeedLive = input.float(1.0, "Min speed REALTIME ($/s)", minval=0.0, step=0.01, group=grp_ent)
minSpeedBT = input.float(0.001, "Min speed CLOSE-BAR ($/s)", minval=0.0, step=0.0001, group=grp_ent)
useWeightedForEntry = input.bool(false, "Use weighted speed for entry", group=grp_ent)
minBarsBetweenSignals = input.int(0, "Cooldown bars (0=off)", minval=0, group=grp_ent)

// =====================================================
// EXITS
// =====================================================
grp_exit = "Exits"
exitMode = input.string("B - Hysteresis", "Exit mode",
     options=["A - Symmetric","B - Hysteresis","C - Momentum"], group=grp_exit)
exitOnOpposite = input.bool(true, "Exit on opposite signal", group=grp_exit)
exitMinScore = input.int(2, "B: Exit if score <=", minval=1, maxval=5, group=grp_exit)
exitMinSpeed = input.float(0.20, "B: Exit if |speed| <= ($/s)", minval=0.0, step=0.01, group=grp_exit)

// =====================================================
// SPEED CHANNEL
// =====================================================
grp_ch = "Speed Channel"
useChannel = input.bool(true, "Enable channel", group=grp_ch)
chUpper = input.float(1.0, "Upper channel ($/s)", minval=0.0, step=0.01, group=grp_ch)
chLower = input.float(1.0, "Lower channel ($/s)", minval=0.0, step=0.01, group=grp_ch)
exitOnChannelReentry = input.bool(false, "Exit when re-entering channel", group=grp_ch)

// =====================================================
// ALERTS
// =====================================================
grp_al = "Alerts"
alertBuy = input.bool(true, "Alert BUY", group=grp_al)
alertSell = input.bool(true, "Alert SELL", group=grp_al)
alertExit = input.bool(true, "Alert EXIT", group=grp_al)
alertChannel = input.bool(true, "Alert channel breakout", group=grp_al)
alertAll = input.bool(false, "Alert ALL events", group=grp_al)

// =====================================================
// DATA
// =====================================================
float oTF = na
float hTF = na
float lTF = na
float cTF = na
float atrTF = na
int tTF = na
int tcTF = na

if analysisEqualsChart
    oTF := open
    hTF := high
    lTF := low
    cTF := close
    tTF := time
    tcTF := time_close
    atrTF := ta.atr(atrLen)
else
    oTF := request.security(syminfo.tickerid, tfUse, open, barmerge.gaps_off, barmerge.lookahead_off)
    hTF := request.security(syminfo.tickerid, tfUse, high, barmerge.gaps_off, barmerge.lookahead_off)
    lTF := request.security(syminfo.tickerid, tfUse, low, barmerge.gaps_off, barmerge.lookahead_off)
    cTF := request.security(syminfo.tickerid, tfUse, close, barmerge.gaps_off, barmerge.lookahead_off)
    tTF := request.security(syminfo.tickerid, tfUse, time, barmerge.gaps_off, barmerge.lookahead_off)
    tcTF := request.security(syminfo.tickerid, tfUse, time_close, barmerge.gaps_off, barmerge.lookahead_off)
    atrTF := request.security(syminfo.tickerid, tfUse, ta.atr(atrLen), barmerge.gaps_off, barmerge.lookahead_off)

// =====================================================
// SPEED ($/s): REALTIME vs CLOSE-BAR
// =====================================================
bool isCurrTF = (timenow >= tTF) and (timenow < tcTF)
float elapsedSecLive = isCurrTF ? ((timenow - tTF) / 1000.0) : float(tfSec)
elapsedSecLive := math.max(elapsedSecLive, 1.0)

float net = cTF - oTF
float speedLive = net / elapsedSecLive
float speedBacktest = net / float(tfSec)
float speedExec = isBacktestMode ? speedBacktest : speedLive

float speedSm = ta.ema(speedExec, speedSmooth)

// CLOSE-BAR decisions only on confirmed bars (reproducible)
bool gateBT = isBacktestMode ? barstate.isconfirmed : true

// =====================================================
// LINEARITY SCORE (1..5)
// =====================================================
float atrSafe = math.max(atrTF, syminfo.mintick)
float adverseLong = math.max(0.0, oTF - lTF)
float adverseShort = math.max(0.0, hTF - oTF)
float adverse = net >= 0 ? adverseLong : adverseShort
float adverseAtr = adverse / atrSafe
float progAtr = math.abs(net) / atrSafe

int score = 1
score := progAtr < minProgAtr ? 1 : score
score := progAtr >= minProgAtr and adverseAtr <= thr2 ? 2 : score
score := progAtr >= minProgAtr and adverseAtr <= thr3 ? 3 : score
score := progAtr >= minProgAtr and adverseAtr <= thr4 ? 4 : score
score := progAtr >= minProgAtr and adverseAtr <= thr5 ? 5 : score

// Weighted speed
float speedWeighted = speedSm * (score / 5.0)
float speedPanel = speedWeighted * speedMult

// =====================================================
// COLORS
// =====================================================
color col = score == 5 ? color.lime : score == 4 ? color.green : score == 3 ? color.yellow : score == 2 ? color.orange : color.red
color txtCol = score >= 3 ? color.black : color.white
bgcolor(paintBg ? color.new(col, 88) : na)

// =====================================================
// ENTRY LOGIC
// =====================================================
float minSpeedUse = isBacktestMode ? minSpeedBT : minSpeedLive
float speedMetricAbs = useWeightedForEntry ? math.abs(speedWeighted) : math.abs(speedSm)

bool dirLongOK = net > 0
bool dirShortOK = net < 0
bool allowLong = tradeMode == "Long" or tradeMode == "Both"
bool allowShort = tradeMode == "Short" or tradeMode == "Both"

var int lastSigBar = na
bool cooldownOK = minBarsBetweenSignals <= 0 ? true : (na(lastSigBar) ? true : (bar_index - lastSigBar >= minBarsBetweenSignals))

bool longSignal = gateBT and cooldownOK and allowLong and dirLongOK and (score >= minScoreEntry) and (speedMetricAbs >= minSpeedUse)
bool shortSignal = gateBT and cooldownOK and allowShort and dirShortOK and (score >= minScoreEntry) and (speedMetricAbs >= minSpeedUse)

if longSignal
    strategy.entry("LONG", strategy.long)
if shortSignal
    strategy.entry("SHORT", strategy.short)
if longSignal or shortSignal
    lastSigBar := bar_index

// =====================================================
// EXIT LOGIC (3 MODES)
// =====================================================
bool inLong = strategy.position_size > 0
bool inShort = strategy.position_size < 0

bool oppForLong = shortSignal
bool oppForShort = longSignal

// Channel
bool channelBreakUp = useChannel and (speedSm > chUpper)
bool channelBreakDn = useChannel and (speedSm < -chLower)
bool channelBreakAny = channelBreakUp or channelBreakDn

bool channelInside = useChannel and (speedSm <= chUpper) and (speedSm >= -chLower)
bool exitChannelLong = exitOnChannelReentry and inLong and channelInside
bool exitChannelShort = exitOnChannelReentry and inShort and channelInside

bool exitBaseLong = false
bool exitBaseShort = false

// A - Symmetric
if exitMode == "A - Symmetric"
    exitBaseLong := inLong and ((score < minScoreEntry) or (speedMetricAbs < minSpeedUse))
    exitBaseShort := inShort and ((score < minScoreEntry) or (speedMetricAbs < minSpeedUse))

// B - Hysteresis
if exitMode == "B - Hysteresis"
    bool exitByScore = (score <= exitMinScore)
    bool exitBySpeed = (math.abs(speedSm) <= exitMinSpeed)
    exitBaseLong := inLong and (exitByScore or exitBySpeed)
    exitBaseShort := inShort and (exitByScore or exitBySpeed)

// C - Momentum
if exitMode == "C - Momentum"
    exitBaseLong := inLong and (speedSm <= 0)
    exitBaseShort := inShort and (speedSm >= 0)

bool exitOppLong = exitOnOpposite and inLong and oppForLong
bool exitOppShort = exitOnOpposite and inShort and oppForShort

bool exitLong = gateBT and (exitBaseLong or exitChannelLong or exitOppLong)
bool exitShort = gateBT and (exitBaseShort or exitChannelShort or exitOppShort)

if exitLong
    strategy.close("LONG")
if exitShort
    strategy.close("SHORT")

// =====================================================
// PLOTS
// =====================================================
plot(speedPanel, title="Speed (weighted)", style=plot.style_columns, linewidth=3, color=col)
hline(0.0, "Zero", linestyle=hline.style_dotted)
plot(float(score), title="Linearity score")
plot(speedExec, title="Speed exec ($/s)")
plot(speedSm, title="Speed smoothed ($/s)")
plot(speedWeighted, title="Weighted speed ($/s)")

// =====================================================
// ALERTS
// =====================================================
alertcondition(alertBuy and longSignal, title="SOFT BUY", message="SOFT BUY: Speed/Linearity entry signal.")
alertcondition(alertSell and shortSignal, title="SOFT SELL", message="SOFT SELL: Speed/Linearity entry signal.")
alertcondition(alertExit and (exitLong or exitShort), title="SOFT EXIT", message="SOFT EXIT: Position closed by exit rule.")
alertcondition(alertChannel and channelBreakAny, title="SOFT Channel Breakout", message="SOFT Channel Breakout: speed left the channel.")
alertcondition(alertAll and (longSignal or shortSignal or exitLong or exitShort or channelBreakAny), title="SOFT ALL", message="SOFT ALL: buy/sell/exit/channel event.")