Stratégie d'investissement fixe à coût moyen dynamique et intérêt composé


Date de création: 2024-01-04 16:34:10 Dernière modification: 2024-01-04 16:34:10
Copier: 0 Nombre de clics: 806
1
Suivre
1621
Abonnés

Stratégie d’investissement fixe à coût moyen dynamique et intérêt composé

Aperçu

La stratégie d’investissement à coût moyen dynamique consiste à ajuster dynamiquement le nombre d’ouvertures de position, en ouvrant une petite quantité de positions au début de la tendance, puis en augmentant progressivement la position avec l’augmentation de la profondeur de liquidation. La stratégie utilise une fonction d’indicateur pour calculer le prix d’arrêt de chaque couche et déclencher la répartition de la réouverture de nouvelles positions, ce qui permet de maintenir la ligne de coût de détention de la position à la baisse de l’indice.

Principe de stratégie

La stratégie consiste à choisir le moment de l’ouverture d’une position en choisissant la ligne de choix de la paire de signaux RSI simple. Un signal d’ouverture de position unique est généré lorsque le RSI est inférieur à la ligne de survente et que le prix de clôture est inférieur à la ligne moyenne. Après l’ouverture de la première position, un signal de DCA est généré en fonction de la fonction d’indice calculée en fonction de la limite inférieure de la chute des prix. Le coût de détention diminue à mesure que le nombre de DCA augmente, ce qui signifie qu’il suffit d’un petit rebond pour réaliser un profit. Après plusieurs sorties consécutives, un stop loss est tracé au-dessus de la moyenne. Si le prix rebondit à la hausse, dépassant la moyenne de la position et la ligne de stop loss, le stop loss est mis en jeu.

Le plus grand avantage de la stratégie est qu’avec la baisse constante des coûts de détention, même en liquidation, les coûts peuvent être réduits progressivement. Lorsque la tendance est inversée, les coûts de détention sont déjà largement inférieurs au prix du marché, ce qui permet de réaliser des bénéfices plus importants.

Risques et défauts

Le risque le plus important de cette stratégie réside dans le fait que la position initiale est limitée. Si la tendance baissière se poursuit, il y a un risque de perte. Il est donc nécessaire de définir le seuil de perte que vous pouvez supporter.

En outre, il existe également deux extrêmes dans la définition de la marge d’arrêt. Une unité d’arrêt trop grande ne produit pas de rebond suffisamment profond. Une marge d’arrêt trop petite entraîne une probabilité plus élevée de reprise de la reprise de la reprise de la reprise de la reprise de la reprise au cours de l’ajustement à moyen terme. Il est donc essentiel de choisir la marge d’arrêt appropriée en fonction des différents marchés et de vos propres préférences en matière de risque.

Après un cycle de DCA plus long et formé à plusieurs niveaux, si le prix augmente considérablement, le coût de la position est trop élevé et le risque de perte est irréversible. Cela nécessite également de définir raisonnablement le niveau de DCA en fonction du volume total de la position et du coût de la position la plus élevée que l’on peut supporter.

Conseils d’optimisation

  1. Optimiser le signal de sélection. Différents paramètres peuvent être testés ainsi que différentes combinaisons d’indicateurs, dans l’espoir de sélectionner un signal avec un taux de réussite plus élevé.

  2. Optimisation des mécanismes de stop. Les stops de type Λ ou les stops en forme d’arc peuvent être testés en lieu et place des stops mobiles simples, ce qui peut permettre d’obtenir de meilleurs résultats de stop. Il est également possible d’ajouter des stratégies d’ajustement de la marge de stop au moment des positions.

  3. Optimiser la méthode d’arrêt. Vous pouvez tester différents types d’arrêt mobiles pour trouver des occasions d’arrêt plus favorables, ce qui améliore le taux de rendement global.

  4. Ajout d’un mécanisme de protection contre les rebonds. Après l’arrêt des pertes, il peut arriver que le signal DCA soit à nouveau déclenché pour réouvrir la position. Il est alors possible d’envisager d’ajouter une certaine amplitude de zone de protection contre les rebonds, afin d’éviter une réactivation immédiate de la position après l’arrêt des pertes.

Résumer

Cette stratégie utilise le RSI pour déterminer le moment de l’achat, ainsi qu’une stratégie de DCA de stop-loss dynamique calculée en fonction de la fonction d’indice, permettant d’ajuster dynamiquement le nombre de positions et le coût de la position pour obtenir un avantage de prix sur le marché des bandes. Le programme d’optimisation se concentre principalement sur les signaux d’entrée et de sortie, les arrêts et les arrêts.

Code source de la stratégie
/*backtest
start: 2023-12-04 00:00:00
end: 2024-01-03 00:00:00
period: 1h
basePeriod: 15m
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///
// © A3Sh
//@version=5

// Study of a Simple RSI based, PA (priceaveraging) and DCA strategy that opens a new position everytime it hits a specified price level below the first entry.
// The first entry is opened when the specified rsi and moving average conditions are met. 
// The following DCA levels are calculated exponentially and set, starting with a specified % of price drop. 
// The disctance between the dca levels can be changed with the exponential scale.
// Each position closes individually when it reaches a specified take profit.
// The position can re-open again when it hits the price level again.
// Each time a position is closed and reopened, the average price drops a little.
// The position stays open until the first entry closes or when the price reaches the Stop level.
// When the price reaches the Stop level, all positions will close at once.

// The RSI and MA code for opening the entry is adapted from the Optimized RSI Buy the Dips strategy, by Coinrule.
// This code is used for study purposes, but any other low/ dip finding indicator can be used.
// https://www.tradingview.com/script/Pm1WAtyI-Optimized-RSI-Strategy-Buy-The-Dips-by-Coinrule/

// Dynamic DCA layers are inspired by the Backtesting 3commas DCA Bot v2, by rouxam
// This logic gives more flexibility because you can dyanically change the amount of dca entries.
// https://www.tradingview.com/script/8d6Auyst-Backtesting-3commas-DCA-Bot-v2/

// The use of for loops to (re)open and close different entries separately is based on the Simple_Pyramiding strategy.
// https://www.tradingview.com/script/t6cNLqDN-Simple-Pyramiding/


strategy('Simple_RSI+PA+DCA', overlay=true, pyramiding=20, initial_capital=500, calc_on_order_fills=true, default_qty_type=strategy.percent_of_equity, commission_type=strategy.commission.percent, commission_value=0.075, close_entries_rule='FIFO')

// Backtest Window //
start_time   = input(defval=timestamp("01 April 2021 20:00"), group = "Backtest Window", title="Start Time")
end_time     = input(defval=timestamp("01 Aug 2030 20:00"),   group = "Backtest Window", title="End Time")
window() => true

// Inputs //
takeProfit      = input.float  (3,           group = 'Risk',           title = 'Take Profit %', step=0.1)
takeProfitAll   = input.float  (6,           group = "Risk",           title = 'Close All %',   step=0.1)
posCount        = input.int    (8,           group = 'DCA Settings',   title = 'Max Amount of Entries')
increment       = input.float  (2,           group = 'DCA Settings',   title = 'Price Drop % to open First DCA Order', step=0.5)/100 
exponent_scale  = input.float  (1.4,         group = 'DCA Settings',   title = 'Exponential Scale DCA levels', step=0.1, minval=1.1) 
bar_lookback    = input.int    (4999,        group = 'DCA Settings',   title = 'Lines Bar Lookback', maxval = 4999)
plotMA          = input.bool   (false,       group = 'Moving Average', title = 'Plot Moving Average')
moving_average  = input.int    (100,         group = 'Moving Average', title = 'MA Length' )
rsiLengthInput  = input.int    (14,          group = 'RSI Settings',   title = "RSI Length", minval=1)
rsiSourceInput  = input.source (close,       group = 'RSI Settings',   title = 'Source')
overSold        = input.int    (29,          group = 'RSI Settings',   title = 'Oversold, Trigger to Enter First Position')

// variables //
var open_position    = true   // true when there are open positions
var entry_price      = 0.0    // the entry price of the first entry
var dca_price        = 0.0    // the price of the different dca layers
var int count        = 0      // bar counter since first open position
var int max_bar      = 0      // max bar buffer variable for DCA lines, stop lines, average price
var line dca_line    = na     // lines variable for creating dca lines

// arrays //
linesArray = array.new_float(posCount,na)  // array to store different dca price levels for creating the dca lines

// Create max bar buffer for DCA lines, Stop and average price lines //
max_bar := count >= bar_lookback ? bar_lookback : count

// Order size based on first entry and amount of DCA layers
q = (strategy.equity  / posCount + 1) / open


// Calculate Moving Averages
movingaverage_signal = ta.sma(close ,moving_average)
plot (plotMA ? movingaverage_signal : na, color = color.new(#f5ff35, 0))


// RSI calculations //
up   = ta.rma(math.max(ta.change(rsiSourceInput), 0), rsiLengthInput)
down = ta.rma(-math.min(ta.change(rsiSourceInput), 0), rsiLengthInput)
rsi  = down == 0 ? 100 : up == 0 ? 0 : 100 - (100 / (1 + up / down))


// Buy Signal (co)
co = ta.crossover(rsi, overSold) and close < movingaverage_signal


// Create a white line for average price, since the last opened position //
// average_price = line.new(x1 = bar_index - max_bar, y1 = strategy.position_avg_price, x2 = bar_index, y2 = strategy.position_avg_price, color = color.white)
    

// Stop //
// Create a red Stop level line based on a specified % above the average price //
stop_level = strategy.position_avg_price + (strategy.position_avg_price / 100 * takeProfitAll)
// stop_line  = line.new(x1 = bar_index - max_bar, y1 = stop_level, x2 = bar_index, y2 = stop_level, color = color.red)
    

// Take profit definition per open position //
take_profit_price = close * takeProfit / 100 / syminfo.mintick


// Make sure the Stop level and average price level don't excied the bar buffer to avoid errors //
// if count <= bar_lookback
//     line.set_x1(stop_line,     strategy.opentrades.entry_bar_index(strategy.opentrades - 1))
//     line.set_x1(average_price, strategy.opentrades.entry_bar_index(strategy.opentrades - 1))


// Exponential DCA Layer Calculation fucntion --> First try, needs more experimentation //
dca_price_level(index,entry_price) =>   
    entry_price * (1 - (increment * math.pow(exponent_scale, index)))


// Set  Entries //
// Open the first entry and set the entry price //
if co and strategy.position_size == 0 and window() 
    open_position := true
    entry_price   := close
    strategy.entry(id = 'FE1', direction = strategy.long, qty = q)  
    
// first_entry_line = line.new(x1 = bar_index - max_bar, y1 = entry_price, x2 = bar_index, y2 = entry_price, color = color.blue)


// Start bar counting since the position is open //
if open_position == true
    count := count + 1


// Set the DCA entries //
// Prices below 1 are not set to avoid negative prices //
if strategy.position_size > 0 and window()
    for i = 0 to strategy.opentrades
        if strategy.opentrades == i and i < posCount
            dca_price := dca_price_level(i,entry_price) > 1 ? dca_price_level(i,entry_price) : na
            entry_id = 'DCA' + str.tostring(i + 1) 
            strategy.entry(id = entry_id, direction = strategy.long, limit = dca_price, qty = q)  


// Store the values of the different dca price levels in an array and create the dca lines // 
// Prices below 1 are not stored//
if open_position==true and window() 
    for i = 1 to posCount -1
        array.push(linesArray, dca_price_level(i,entry_price) > 1 ? dca_price_level(i,entry_price) : na) 
    
    // for i = 1 to array.size(linesArray) - 1
    //     dca_line := line.new(x1 = bar_index - max_bar, y1 = array.get(linesArray, i), x2 = bar_index, y2 = array.get(linesArray, i),color = color.blue)


// Create thick line to show the last Entry price //
// last_entry_price = line.new(x1 = bar_index[5], y1 = strategy.opentrades.entry_price(strategy.opentrades - 1), x2 = bar_index, y2 = strategy.opentrades.entry_price(strategy.opentrades - 1),color = color.rgb(255, 0, 204), width = 5)


// Exit the first entry when the take profit triggered //   
if strategy.opentrades > 0 and window() 
    strategy.exit(id = 'Exit FE', from_entry = 'FE1', profit = take_profit_price)


// Exit DCA entries when take profit is triggered //
if strategy.opentrades > 0 and window() 
    for i = 0 to strategy.opentrades 
        exit_from = 'DCA' + str.tostring(i + 1)
        exit_id = 'Exit_' + str.tostring(i + 1)
        strategy.exit(id = exit_id, from_entry = exit_from, profit = take_profit_price)


// Close all positions at once when Stop is crossed //
if strategy.opentrades > 0 and ta.crossover(close,stop_level) and window() 
    strategy.close_all()


// Make sure nothing is open after alle positions are closed and set the condiftion back to be open for new entries //
if strategy.position_size[1] > 0 and strategy.position_size == 0
    strategy.cancel_all()
    strategy.close_all()
    // line.delete(average_price)
    // line.delete(stop_line)
    // line.delete(dca_line)
    open_position := false   // All position are closed, so back to false
    count := 0               // Reset bar counter