
Cette stratégie est basée sur le Trend Flex Oscillator (TFO) et l’Average True Range (ATR) de Dr. John Ehlers. Il s’agit d’une stratégie de suivi des pertes de tendance. Elle s’applique aux marchés à plusieurs niveaux, ouvrant des positions à plusieurs niveaux lorsque le prix recule après l’Oversold.
Cette stratégie combine les deux indicateurs TFO et ATR, en ouvrant une position en plus si les conditions d’achat sont remplies, et en laissant une position en moins si les conditions de vente sont remplies.
Conditions d’achat: lorsque le TFO est inférieur à un seuil particulier (indiquant une surchauffe) et que le TFO de la ligne K supérieure est inférieur à la ligne K actuelle (indiquant une hausse inversée du TFO) et que l’ATR est supérieur au seuil de fluctuation fixé (indiquant une augmentation de la fluctuation du marché), la satisfaction de ces trois conditions signifie que vous pouvez ouvrir plus de positions.
Conditions de placement: Lorsque le TFO est supérieur à un certain seuil (indiquant un excès de tête) et que l’ATR est supérieur au seuil fixé, toutes les positions en cours sont liquidées. De plus, la stratégie définit un arrêt de suivi, qui élimine toutes les positions en cours lorsque le prix tombe en dessous du prix d’arrêt de suivi fixé.
Cette stratégie permet d’ouvrir jusqu’à 15 positions multiples simultanément. Ses paramètres peuvent être ajustés pour différentes périodes de temps.
Le TFO peut capturer les signaux précoces de rupture de tendance, tandis que l’ATR peut saisir le moment où les fluctuations du marché augmentent.
Les paramètres d’achat et de vente et les paramètres d’arrêt sont réglables, ce qui permet une flexibilité d’utilisation. L’utilisateur peut ajuster les paramètres en fonction du marché pour optimiser.
La fonctionnalité de stop-loss est intégrée pour réduire les pertes en cas de situation extrême. La stratégie de stop-loss est un élément très important du trading quantitatif.
Il est possible d’augmenter les profits en augmentant les positions.
La stratégie consiste à faire trop, sans faire de failles, et à ne pas profiter d’un marché en baisse. Si le marché baissier est catastrophique, cela peut entraîner des pertes énormes.
Une mauvaise configuration des paramètres peut entraîner des transactions excessives ou des soldes négatifs. Des tests répétés sont nécessaires pour trouver la meilleure combinaison de paramètres.
Dans des situations extrêmes, le stop loss peut être inefficace et ne pas empêcher la survenue de pertes massives. C’est un problème que toutes les stratégies de stop loss peuvent rencontrer.
Les résultats de l’analyse ne reflètent pas complètement les transactions en temps réel, et les résultats en temps réel peuvent être déviés.
On peut envisager d’inclure une ligne de stop mobile dans les conditions de vente pour que la stratégie arrête les pertes à temps et contrôle efficacement le risque de baisse.
On peut étendre le mécanisme de prise de position pour ouvrir une position vide lorsque le TFO est inversé et que l’ATR est suffisamment grand pour que la stratégie s’applique aux marchés à ciel ouvert.
Des conditions de filtrage supplémentaires peuvent être ajoutées, telles que les variations de volume de transaction, afin de réduire l’impact des situations anormales sur la stratégie.
Il est possible de tester les paramètres de différentes périodes de temps et les résultats de la rétro-mesure pour trouver la meilleure combinaison de périodes et de paramètres.
La stratégie intègre les avantages de l’analyse de la tendance et de la surveillance de la volatilité pour déterminer la direction du marché à travers une combinaison d’indicateurs TFO et ATR. Des mécanismes tels que l’ouverture supplémentaire, la clôture partielle et le stop-loss mobile sont configurés pour maximiser les gains et contrôler les risques, adaptés à la pratique multijoueurs. Il existe également un espace d’optimisation extensible, permettant d’améliorer encore la performance de la stratégie en ajoutant plus de filtres d’indicateurs et d’optimisations de paramètres.
/*backtest
start: 2022-11-27 00:00:00
end: 2023-12-03 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Chart0bserver
//
// Open Source attributions:
// portions © allanster (date window code)
// portions © Dr. John Ehlers (Trend Flex Oscillator)
//
// READ THIS CAREFULLY!!! ----------------//
// This code is provided for educational purposes only. The results of this strategy should not be considered investment advice.
// The user of this script acknolwedges that it can cause serious financial loss when used as a trading tool
// This strategy has a bias for HODL (Holds on to Losses) meaning that it provides NO STOP LOSS protection!
// Also note that the default behavior is designed for up to 15 open long orders, and executes one order to close them all at once.
// Opening a long position is predicated on The Trend Flex Oscillator (TFO) rising after being oversold, and ATR above a certain volatility threshold.
// Closing a long is handled either by TFO showing overbought while above a certain ATR level, or the Trailing Stop Loss. Pick one or both.
// If the strategy is allowed to sell before a Trailing Stop Loss is triggered, you can set a "must exceed %". Do not mistake this for a stop loss.
// Short positions are not supported in this version. Back-testing should NEVER be considered an accurate representation of actual trading results.
//@version=5
strategy('TFO + ATR Strategy with Trailing Stop Loss', 'TFO ATR Trailing Stop Loss', overlay=true, pyramiding=15, default_qty_type=strategy.cash, default_qty_value=10000, initial_capital=150000, currency='USD', commission_type=strategy.commission.percent, commission_value=0.5)
strategy.risk.allow_entry_in(strategy.direction.long) // There will be no short entries, only exits from long.
// -----------------------------------------------------------------------------------------------------------//
// Back-testing Date Range code ----------------------------------------------------------------------------//
// ---------------------------------------------------------------------------------------------------------//
fromMonth = input.int(defval=9, title='From Month', minval=1, maxval=12, group='Back-Testing Start Date')
fromDay = input.int(defval=1, title='From Day', minval=1, maxval=31, group='Back-Testing Start Date')
fromYear = input.int(defval=2021, title='From Year', minval=1970, group='Back-Testing Start Date')
thruMonth = 1 //input(defval = 1, title = "Thru Month", type = input.integer, minval = 1, maxval = 12, group="Back-Testing Date Range")
thruDay = 1 //input(defval = 1, title = "Thru Day", type = input.integer, minval = 1, maxval = 31, group="Back-Testing Date Range")
thruYear = 2112 //input(defval = 2112, title = "Thru Year", type = input.integer, minval = 1970, group="Back-Testing Date Range")
// === FUNCTION EXAMPLE ===
start = timestamp(fromYear, fromMonth, fromDay, 00, 00) // backtest start window
finish = timestamp(thruYear, thruMonth, thruDay, 23, 59) // backtest finish window
window() => // create function "within window of time
time >= start and time <= finish ? true : false
// Date range code -----//
// -----------------------------------------------------------------------------------------------------------//
// ATR Indicator Code --------------------------------------------------------------------------------------//
// ---------------------------------------------------------------------------------------------------------//
length = 18 //input(title="ATR Length", defval=18, minval=1)
Period = 18 //input(18,title="ATR EMA Period")
basicEMA = ta.ema(close, length)
ATR_Function = ta.ema(ta.tr(true), length)
EMA_ATR = ta.ema(ATR_Function, Period)
ATR = ta.ema(ta.tr(true), length)
ATR_diff = ATR - EMA_ATR
volatility = 100 * ATR_diff / EMA_ATR // measure of spread between ATR and EMA
volatilityAVG = math.round((volatility + volatility[1] + volatility[2]) / 3)
buyVolatility = input.int(3, 'Min Volatility for Buy', minval=-20, maxval=20, step=1, group='Average True Range')
sellVolatility = input.int(13, 'Min Volatility for Sell', minval=-10, maxval=20, step=1, group='Average True Range')
useAvgVolatility = input.bool(defval=false, title='Average the Volatility over 3 bars', group='Average True Range')
// End of ATR ------------/
// -----------------------------------------------------------------------------------------------------------//
// TFO Indicator code --------------------------------------------------------------------------------------//
// ---------------------------------------------------------------------------------------------------------//
trendflex(Series, PeriodSS, PeriodTrendFlex, PeriodEMA) =>
var SQRT2xPI = math.sqrt(8.0) * math.asin(1.0) // 4.44288293815 Constant
alpha = SQRT2xPI / PeriodSS
beta = math.exp(-alpha)
gamma = -beta * beta
delta = 2.0 * beta * math.cos(alpha)
float superSmooth = na
superSmooth := (1.0 - delta - gamma) * (Series + nz(Series[1])) * 0.5 + delta * nz(superSmooth[1]) + gamma * nz(superSmooth[2])
E = 0.0
for i = 1 to PeriodTrendFlex by 1
E += superSmooth - nz(superSmooth[i])
E
epsilon = E / PeriodTrendFlex
zeta = 2.0 / (PeriodEMA + 1.0)
float EMA = na
EMA := zeta * epsilon * epsilon + (1.0 - zeta) * nz(EMA[1])
return_1 = EMA == 0.0 ? 0.0 : epsilon / math.sqrt(EMA)
return_1
upperLevel = input.float(1.2, 'TFO Upper Level', minval=0.1, maxval=2.0, step=0.1, group='Trend Flex Ocillator')
lowerLevel = input.float(-0.9, 'TFO Lower Level', minval=-2.0, maxval=-0.1, step=0.1, group='Trend Flex Ocillator')
periodTrendFlex = input.int(14, 'TrendFlex Period', minval=2, group='Trend Flex Ocillator')
useSuperSmootherOveride = true //input( true, "Apply SuperSmoother Override Below*", input.bool, group="Trend Flex Ocillator")
periodSuperSmoother = 8.0 //input(8.0, "SuperSmoother Period*", input.float , minval=4.0, step=0.5, group="Trend Flex Ocillator")
postSmooth = 33 //input(33.0, "Post Smooth Period**", input.float , minval=1.0, step=0.5, group="Trend Flex Ocillator")
trendFlexOscillator = trendflex(close, periodSuperSmoother, periodTrendFlex, postSmooth)
// End of TFO -------------//
// -----------------------------------------------------------------------------------------------------------//
// HODL Don't sell if losing n% ---------------------------------------------------------------------------- //
// ---------------------------------------------------------------------------------------------------------//
sellOnStrategy = input.bool(defval=true, title='Allow Stategy to close positions', group='Selling Conditions')
doHoldLoss = true // input(defval = true, title = "Strategy can sell for a loss", type = input.bool, group="Selling Conditions")
holdLoss = input.int(defval=0, title='Value (%) must exceed ', minval=-25, maxval=10, step=1, group='Selling Conditions')
totalInvest = strategy.position_avg_price * strategy.position_size
openProfitPerc = strategy.openprofit / totalInvest
bool acceptableROI = openProfitPerc * 100 > holdLoss
// -----------------------//
// -----------------------------------------------------------------------------------------------------------//
// Buying and Selling conditions -------------------------------------------------------------------------- //
// ---------------------------------------------------------------------------------------------------------//
if useAvgVolatility
volatility := volatilityAVG
volatility
tfoBuy = trendFlexOscillator < lowerLevel and trendFlexOscillator[1] < trendFlexOscillator // Always make a purchase if TFO is in this lowest range
atrBuy = volatility > buyVolatility
tfoSell = ta.crossunder(trendFlexOscillator, upperLevel)
consensusBuy = tfoBuy and atrBuy
consensusSell = tfoSell and volatility > sellVolatility
if doHoldLoss
consensusSell := consensusSell and acceptableROI
consensusSell
// --------------------//
// -----------------------------------------------------------------------------------------------------------//
// Tracing & Debugging --------------------------------------------------------------------------------------//
// ---------------------------------------------------------------------------------------------------------//
plotchar(strategy.opentrades, 'Number of open trades', ' ', location.top)
plotarrow(100 * openProfitPerc, 'Profit on open longs', color.new(color.green, 75), color.new(color.red, 75))
// plotchar(strategy.position_size, "Shares on hand", " ", location.top)
// plotchar(totalInvest, "Total Invested", " ", location.top)
// plotarrow(strategy.openprofit, "Open profit dollar amount", color.new(color.green,100), color.new(color.red, 100))
// plotarrow(strategy.netprofit, "Net profit for session", color.new(color.green,100), color.new(color.red, 100))
// plotchar(acceptableROI, "Acceptable ROI", " ", location.top)
// plotarrow(volatility, "ATR volatility value", color.new(color.green,75), color.new(color.red, 75))
// plotchar(strategy.position_avg_price, "Avgerage price of holdings", " ", location.top)
// plotchar(volatilityAVG, "AVG volatility", " ", location.top)
// plotchar(fiveBarsVal, "change in 5bars", " ", location.top)
// plotchar(crossingUp, "crossingUp", "x", location.belowbar, textcolor=color.white)
// plotchar(crossingDown, "crossingDn", "x", location.abovebar, textcolor=color.white)
// plotchar(strategy.closedtrades, "closedtrades", " ", location.top)
// plotchar(strategy.wintrades, "wintrades", " ", location.top)
// plotchar(strategy.losstrades, "losstrades", " ", location.top)
// plotchar(close, "close", " ", location.top)
//--------------------//
// -----------------------------------------------------------------------------------------------------------//
// Trade Alert Execution ------------------------------------------------------------------------------------//
// ---------------------------------------------------------------------------------------------------------//
strategy.entry('long', strategy.long, when=window() and consensusBuy, comment='long')
if sellOnStrategy
strategy.close('long', when=window() and consensusSell, qty_percent=100, comment='Strat')
// -----------------------------------------------------------------------------------------------------------//
// Trailing Stop Loss logic -------------------------------------------------------------------------------- //
// ---------------------------------------------------------------------------------------------------------//
useTrailStop = input.bool(defval=true, title='Set Trailing Stop Loss on avg positon value', group='Selling Conditions')
arm = input.float(defval=15, title='Trailing Stop Arms At (%)', minval=1, maxval=30, step=1, group='Selling Conditions') * 0.01
trail = input.float(defval=2, title='Trailing Stop Loss (%)', minval=0.25, maxval=9, step=0.25, group='Selling Conditions') * 0.1
longStopPrice = 0.0
stopLossPrice = 0.0
if strategy.position_size > 0
longStopPrice := strategy.position_avg_price * (1 + arm)
stopLossPrice := strategy.position_avg_price * ((100 - math.abs(holdLoss)) / 100) // for use with 'stop' in strategy.exit
stopLossPrice
else
longStopPrice := close
longStopPrice
// If you want to hide the Trailing Stop Loss threshold (green line), comment this out
plot(longStopPrice, 'Arm Trail Stop at', color.new(color.green, 60), linewidth=2)
if strategy.position_size > 0 and useTrailStop
strategy.exit('exit', 'long', when=window(), qty_percent=100, trail_price=longStopPrice, trail_offset=trail * close / syminfo.mintick, comment='Trail')
//-----------------------------------------------------------------------------------------------------------//