Stratégie quantitative de suivi des tendances basée sur le SAR


Date de création: 2023-11-23 16:26:17 Dernière modification: 2023-11-23 16:26:17
Copier: 0 Nombre de clics: 593
1
Suivre
1617
Abonnés

Stratégie quantitative de suivi des tendances basée sur le SAR

Aperçu

La stratégie de gouffre de spéculation est une stratégie de trading quantitatif qui suit une tendance. Elle utilise la courbe d’aplatissement SAR comme signal de trading principal, accompagnée d’un ensemble de filtres tels que les EMA, les mouvements d’extrusion et les oscillateurs de volatilité, et permet un suivi de tendance à faible risque en configurant des paramètres SAR pour identifier les points de retournement de tendance.

Principe de stratégie

La stratégie utilise le SAR parallèle comme principal indicateur de signaux de négociation. Le SAR permet de déterminer efficacement le point d’inversion de la tendance des prix, et une modification du symbole SAR signifie un renversement de tendance. La stratégie envoie généralement un signal d’achat ou de vente lorsque le SAR se retourne.

En outre, la stratégie offre également l’option de rupture du SAR. C’est-à-dire que le prix a franchi la dernière valeur du SAR avant que le SAR ne soit complètement inversé. Cela permet de poursuivre la sensibilité de la stratégie.

Afin de filtrer les faux signaux, la stratégie a également introduit trois filtres auxiliaires, l’EMA, le moment d’extrusion et l’oscillateur de volatilité, qui peuvent être utilisés séparément ou en combinaison pour confirmer la fiabilité des tendances des prix et des signaux de négociation.

Enfin, la stratégie offre trois types de stop-loss, à savoir un stop-loss fixe, un stop-stop fixe et un stop-stop sur le ratio de risque à rendement. Cela permet à la stratégie de s’adapter de manière flexible aux caractéristiques de différents types de variétés de transactions.

Analyse des avantages

  1. Le SAR est capable de détecter avec précision le renversement de tendance des prix et de capturer en temps opportun les nouvelles tendances des prix, ce qui est approprié pour le suivi des tendances de la ligne moyenne et longue.

  2. Le réglage des filtres multiples réduit la probabilité de fausses percées et améliore la fiabilité du signal.

  3. La configuration est simple et flexible, et les paramètres peuvent être personnalisés pour s’adapter à différentes variétés de transactions.

  4. Il existe de nombreuses méthodes de stop-loss qui permettent de rechercher un équilibre entre le risque et le rendement.

  5. Les robots de trading peuvent être connectés directement pour automatiser les transactions.

Analyse des risques

  1. Dans un marché non tendanciel, il est possible que de faux signaux et des transactions invalides soient plus fréquents.

  2. La mauvaise configuration des paramètres SAR peut également affecter l’exactitude du jugement des signaux.

  3. Le stop loss est une stratégie de suivi des tendances qui permet d’atteindre facilement la ligne de perte lors d’une forte volatilité.

Les paramètres SAR ou les paramètres de filtrage peuvent être ajustés de manière appropriée pour réduire la probabilité d’une transaction inefficace. Les limites de stop-loss peuvent également être assouplies de manière appropriée pour supporter une plus grande volatilité du marché.

Direction d’optimisation

  1. Optimisation des paramètres de SAR. Optimisation des paramètres d’étape et d’augmentation du SAR grâce à des données de retracement historique pour des stratégies de trading plus stables et plus efficaces.

  2. Introduction d’indicateurs de jugement de tendance. Ajouter des indicateurs de jugement auxiliaires tels que le MACD, le DMI, etc. à la stratégie pour améliorer la capacité de jugement de tendance.

  3. Optimiser le rapport risque/rendement. Ajuster le pourcentage de stop-loss fixe et les paramètres du rapport risque/rendement pour prendre des risques plus élevés de manière appropriée pour obtenir des rendements plus élevés.

  4. Ajout de variétés de devises. Actuellement, la stratégie ne prend en charge que les transactions en devises numériques et peut être étendue pour prendre en charge les variétés de devises, de marchandises et de marchés boursiers.

Résumer

Le gouffre de spéculation est une stratégie de quantification de type tendance très pratique. Il est sensible à la réponse, le jugement des signaux est fiable et des gains stables à long terme peuvent être obtenus grâce à la gestion des arrêts et des arrêts de perte.

Code source de la stratégie
/*backtest
start: 2023-10-23 00:00:00
end: 2023-11-22 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//VERSION =================================================================================================================
//@version=5
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// This strategy is intended to study.
// It can also be used to signal a bot to open a deal by providing the Bot ID, email token and trading pair in the strategy settings screen.
// As currently written, this strategy uses a SAR PARABOLIC to send signal, and EMA, Squeeze Momentum, Volatility Oscilator as filter.
// There are two enter point, when SAR Flips, or Breakout Point - the last SAR Value before it Flips.
// There are tree options for exit: SAR Flips, Fixed Stop Loss ande Fixed Take Profit in % and Risk Reward tha can be set, 0.5/1, 1/1, 1/2 etc.
//Autor M4TR1X_BR

//▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
//STRATEGY ================================================================================================================

strategy(title = 'BT-SAR Ema, Squeeze, Voltatility',
         shorttitle = 'SAR ESV',
         overlay = true)


//▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// INPUTS =================================================================================================================

// TIME INPUTS
usefromDate = input.bool(defval = true, title = 'Start date', inline = '0', group = "Time Filters")
initialDate = input(defval = timestamp('01 Jan 2022 00:00 UTC'), title = '', inline = "0",group = 'Time Filters',tooltip="This start date is in the time zone of the exchange ")
usetoDate = input.bool(defval = true, title = 'End date', inline = '1', group = "Time Filters")
finalDate = input(defval = timestamp('31 Dec 2029 23:59 UTC'), title = '', inline = "1",group = 'Time Filters',tooltip="This end date is in the time zone of the exchange")

// TIME LOGIC 
inTradeWindow = true


// SAR PARABOLIC INPUTS ==================================================================================================
string sargroup=  "SAR PARABOLIC ========================================="
start = input.float(defval=0.02,title='Start',inline='',group = sargroup)
increment = input.float(defval=0.02,title='Increment',inline='',group = sargroup)
maximum = input.float(defval=0.2,title='Maximo',inline='',group = sargroup)

// SAR PARABOLIC LOGIC 
out = ta.sar(start, increment, maximum)


// SAR FLIP OR BREAKOUT OPTIONS
string bkgroup ='SAR TRADE SIGNAL ====================================== '
sarTradeSignal =input.string(defval='SAR Flip',title='SAR Trade Signal', options= ['SAR Flip','SAR Breakout'],group=bkgroup, tooltip='SAR Flip: Once the parabolic SAR flips it will send a signal, SAR Breakout: Will wait the price cross last Sar Value before it flips.')
nBars = input.int(defval=4,title='Bars',group=bkgroup, tooltip ='Define the number of bars for a entry when the price cross breakout point')

float sarBreakoutPoint= ta.valuewhen((close[1] < out[1])  and (close > out),out[1],0)   //Get Sar Breakout Point
bool check = (close[1] < out[1])  and (close > out)                                     //Verify when sar flips
bool BreakoutPrice = sarTradeSignal=='SAR Breakout'? (ta.barssince(check) < nBars) and ((open < sarBreakoutPoint) and (close > sarBreakoutPoint)): (ta.barssince(check) < nBars) and (close > out)
barcolor (check? color.yellow:na,title="Signal Bar color" )


// MOVING AVERAGES INPUTS ================================================================================================
string magroup =  "Moving Average ========================================"
useEma = input.bool(defval = true, title = 'Moving Average Filter',inline='', group= magroup,tooltip='This will enable or disable Exponential Moving Average Filter on Strategy')
emaType=input.string (defval='Ema',title='Type',options=['Ema','Sma'],inline='', group= magroup)
emaSource = input.source(defval=close,title="  Source",inline="", group= magroup)
emaLength = input.int(defval=100,title="Length",minval=0,inline='', group= magroup)

// MOVING AVERAGE LOGIC
float ema = emaType=='Ema'? ta.ema(emaSource,emaLength): ta.sma(emaSource,emaLength)


// VOLATILITY OSCILLATOR =================================================================================================
string vogroup =  "VOLATILITY OSCILLATOR ================================="
useVltFilter=input.bool(defval=true,title="Volatility Oscillator Filter",inline='',group= vogroup,tooltip='This will enable or disable Volatility Oscillator filter on Strategy')
vltFilterLength = input.int(defval=100,title="Volatility Oscillator",inline='',group=vogroup)
vltFilterSpike = close - open
vltFilterX = ta.stdev(vltFilterSpike,vltFilterLength)
vltFilterY = ta.stdev(vltFilterSpike,vltFilterLength) * -1


// SQUEEZE MOMENTUM INPUTS ==============================================================================================
string sqzgroup = "SQUEEZE MOMENTUM =====================================" 
useSqzFilter=input.bool(defval=true,title="Squeeze Momentum Filter",inline='',group= sqzgroup, tooltip='This will enable or disable Squeeze Momentum filter on Strategy')
sqzFilterlength = input.int(defval=20, title='Bollinger Bands Length',inline='',group= sqzgroup)
sqzFiltermult = input.float(defval=2.0, title='Boliinger Bands Mult',inline='',group= sqzgroup)
keltnerLength = input.int(defval=20, title='Keltner Channel Length',inline='',group= sqzgroup)
keltnerMult = input.float(defval=1.5, title='Keltner Channel Mult',inline='',group= sqzgroup)
useTrueRange = input(true, title='Use TrueRange (KC)', inline='',group= sqzgroup)


// CALCULATE BOLLINGER BANDS
sqzFilterSrc = close
basis = ta.sma(sqzFilterSrc, sqzFilterlength)
dev = keltnerMult * ta.stdev(sqzFilterSrc, sqzFilterlength)
upperBB = basis + dev
lowerBB = basis - dev

// CALCULATE KELTNER CHANNEL 
sma = ta.sma(sqzFilterSrc, keltnerLength)
range_1 = useTrueRange ? ta.tr : high - low
rangema = ta.sma(range_1, keltnerLength)
upperKC = sma + rangema * keltnerMult
lowerKC = sma - rangema * keltnerMult


// CHECK IF BOLLINGER BANDS IS IN OR OUT OF KELTNER CHANNEL
sqzOn = lowerBB > lowerKC and upperBB < upperKC
sqzOff = lowerBB < lowerKC and upperBB > upperKC
noSqz = sqzOn == false and sqzOff == false

// SQUEEZE MOMENTUM LOGIC
val = ta.linreg(sqzFilterSrc - math.avg(math.avg(ta.highest(high, keltnerLength), ta.lowest(low, keltnerLength)),ta.sma(close, keltnerLength)), keltnerLength, 0)


// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// TAKE PROFIT STOP LOSS INPUTS =========================================================================================

string tkpgroup='Take Profit =================================================='
tpType = input.string(defval = 'SAR Flip', title='Take Profit and Stop Loss', options=['SAR Flip','Fixed % TP/SL', 'Risk Reward TP/SL'], group=tkpgroup )
longTakeProfitPerc = input.float(defval = 1.5, title = 'Fixed TP %', minval = 0.05, step = 0.5, group=tkpgroup, tooltip = 'The percentage increase to set the take profit price target.')/100

longLossPerc = input.float(defval=1.0, title="Fixed Long SL %", minval=0.1, step=0.5, group = tkpgroup, tooltip = 'The percentage increase to set the Long Stop Loss price target.') * 0.01
//shortLossPerc = input.float(defval=1.5, title="Fixed Short SL (%)", minval=0.1, step=0.5, group = tkpgroup, tooltip = 'The percentage increase to set the Short Stop Loss price target.') * 0.01

longTakeProfitRR = input.float(defval = 1, title = 'Risk Reward TP', minval = 0.25, step = 0.25, group=tkpgroup, tooltip = 'The Risk Reward parameter.')
var plotStopLossRR = input.bool(defval=false, title='Show RR Stop Loss', group=tkpgroup)
//enableStopLossRR = input.bool(defval = false, title = 'Enable Risk Reward TP',group=tkpgroup, tooltip = 'Enable Variable Stop Loss.')

string trpgroup='Traling Profit ==============================================='
enableTrailing = input.bool(defval = false, title = 'Enable Trailing',group=trpgroup, tooltip = 'Enable or disable the trailing for take profit.')
trailingTakeProfitDeviationPerc = input.float(defval = 0.1, title = 'Trailing Take Profit Deviation %', minval = 0.01, maxval = 100, step = 0.01, group=trpgroup, tooltip = 'The step to follow the price when the take profit limit is reached.') / 100


// BOT MESSAGES
string msgroup='Alert Message For Bot ========================================='
messageEntry = input.string("", title="Strategy Entry Message",group=msgroup)
messageExit  =input.string("",title="Strategy Exit Message",group=msgroup)
messageClose = input.string("", title="Strategy Close Message",group=msgroup)

// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// POSITIONS =============================================================================================================

//VERIFY IF THE BUY FILTERS ARE ON OR OFF 
bool emaFilterBuy = useEma? (close > ema):(close >= ema) or (close <= ema)                      
bool volatilityFilterBuy = useVltFilter? (vltFilterSpike > vltFilterX) : (vltFilterSpike >= 0) or (vltFilterSpike <= 0)                  
bool sqzFilterBuy = useSqzFilter? (val > val[1]): (val >= val[1] or val <=val[1])                                      
bool sarflip = (close > out)


//LONG / SHORT POSITIONS LOGIC
//Var 'check' will verify if the SAR flips and if the exit price occurs it will limit in bars number a new entry on the same signal.
bool limitEntryNumbers = (ta.barssince(check) < nBars) 
bool openLongPosition =   sarTradeSignal == 'SAR Flip'? (sarflip and emaFilterBuy and volatilityFilterBuy and sqzFilterBuy and limitEntryNumbers) :sarTradeSignal=='SAR Breakout'? (BreakoutPrice and emaFilterBuy and volatilityFilterBuy and sqzFilterBuy): na
bool openShortPosition = na
bool closeLongPosition= tpType=='SAR Flip'? (close < out):na
bool closeShortPosition=na


// CHEK OPEN POSITONS =====================================================================================================
// open signal when not already into a position
bool validOpenLongPosition = openLongPosition and strategy.opentrades.size(strategy.opentrades - 1) <= 0
bool longIsActive = validOpenLongPosition or strategy.opentrades.size(strategy.opentrades - 1) > 0


// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// TAKE PROFIT STOP LOSS CONFIG ==========================================================================================

// FIXED TAKE PROFIT IN %

float posSize = strategy.opentrades.entry_price(strategy.opentrades - 1) //Get the entry price

var float longTakeProfitPrice = na
longTakeProfitPrice := if (longIsActive)
    if (openLongPosition and not (strategy.opentrades.size(strategy.opentrades - 1) > 0))
        posSize * (1 + longTakeProfitPerc)
    else
        nz(longTakeProfitPrice[1], close * (1 + longTakeProfitPerc))
else
    na

longTrailingTakeProfitStepTicks = longTakeProfitPrice * trailingTakeProfitDeviationPerc / syminfo.mintick

// FIXED STOP LOSS IN %
longStopPrice  = strategy.position_avg_price * (1 - longLossPerc)
//shortStopPrice = strategy.position_avg_price * (1 + shortLossPerc)


// TAKE PROFIT BY RISK/REWARD
// Set stop loss
tta = not (strategy.opentrades.size(strategy.opentrades - 1) > 0)
float lastb = ta.valuewhen(check and tta,ta.lowest(low,5),0) - (10 * syminfo.mintick)

// TAKE PROFIT CALCULATION
float stopLossRisk = (posSize - lastb)
float takeProfitRR = posSize + (longTakeProfitRR * stopLossRisk)


// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// POSITION ORDERS =====================================================================================================

// LOGIC ===============================================================================================================
// getting into LONG position
if (openLongPosition) and (inTradeWindow)
    strategy.entry(id = 'Long Entry', direction = strategy.long, alert_message=messageEntry)

//submit exit orders for trailing take profit price 
if (longIsActive) and (inTradeWindow)
    strategy.exit(id = 'Long Take Profit', from_entry = 'Long Entry', limit = enableTrailing ? na : tpType=='Fixed % TP/SL'? longTakeProfitPrice: tpType == 'Risk Reward TP/SL'? takeProfitRR:na, trail_price = enableTrailing ? longTakeProfitPrice : na, trail_offset = enableTrailing ? longTrailingTakeProfitStepTicks : na, stop = tpType =='Fixed % TP/SL' ? longStopPrice: tpType == 'Risk Reward TP/SL'? lastb:na) //, alert_message='{  "action": "close_at_market_price",  "message_type": "bot",  "bot_id": 9330698,  "email_token": "392265bc-84eb-4a54-a99c-758383ff9449",  "delay_seconds": 0,"pair":"USDT_{{ticker}}" }')

if (closeLongPosition)
    strategy.close(id = 'Long Entry', alert_message='{  "action": "close_at_market_price",  "message_type": "bot",  "bot_id": 9330698,  "email_token": "392265bc-84eb-4a54-a99c-758383ff9449",  "delay_seconds": 0,"pair":"USDT_{{ticker}}" }')
                                                   

// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// PLOTS ===============================================================================================================

// TRADE WINDOW ========================================================================================================
bgcolor(color = inTradeWindow ? color.new(#089981,90):na, title = 'Time Window')


// SAR PARABOLIC
var sarColor = color.new(#00bcd4,0)
plot(out, "ParabolicSAR", color=sarColor, linewidth=1,style=plot.style_cross)


//BREAKOUT LINE
var plotBkPoint = input.bool(defval=false, title='Show Breakout Point', group=bkgroup)
plot(series = (sarTradeSignal=='SAR Breakout' and plotBkPoint == true)? sarBreakoutPoint:na, title = 'Breakout line', color =color.new(#ffeb3b,50) , linewidth = 1, style = plot.style_linebr, offset = 0)


// EMA/SMA 
var emafilterColor = color.new(color.white, 0)
plot(series=useEma? ema:na, title = 'EMA Filter', color = emafilterColor, linewidth = 2, style = plot.style_line)


// ENTRY PRICE
var posColor = color.new(#2962ff, 0)
plot(series = strategy.opentrades.entry_price(strategy.opentrades - 1), title = 'Position', color = posColor, linewidth = 1, style = plot.style_linebr,offset=0)


// FIXED TAKE PROFIT 
var takeProfitColor = color.new(#ba68c8, 0)
plot(series = tpType=='Fixed % TP/SL'? longTakeProfitPrice:na, title = 'Fixed TP', color = takeProfitColor, linewidth = 1, style = plot.style_linebr, offset = 0)


// FIXED STOP LOSS
var stopLossColor = color.new(#ff0000, 0)
plot(series = tpType=='Fixed % TP/SL' ? longStopPrice:na, title = 'Fixed SL', color = stopLossColor, linewidth = 1, style = plot.style_linebr, offset = 0)


// RISK REWARD TAKE PROFIT
var takeProfitRRColor = color.new(#ba68c8, 0)
plot(series=tpType == 'Risk Reward TP/SL'? takeProfitRR:na,title='Risk Reward TP',color=takeProfitRRColor,linewidth=1,style=plot.style_linebr)

// STOP LOSS RISK REWARD
plot(series = (check and plotStopLossRR)? lastb:na, title = 'Last Bottom', color =color.new(#ff0000,0), linewidth = 2, style = plot.style_linebr, offset = 0)


// ======================================================================================================================