A estratégia multifatorial integra oscilantes, tendências e estratégias de ruptura em uma só, combinando seus pontos fortes.
A estratégia multifatorial baseia-se principalmente nos seguintes aspectos:
A parte oscilante usa o oscilador estocástico para identificar sinais de compra e venda. Especificamente, um sinal de compra é gerado quando a linha %K cruza a linha %D da zona de sobrevenda. Um sinal de venda é gerado quando a linha %K cruza abaixo da linha %D da zona de sobrecompra.
A parte que segue a tendência usa a cruz de ouro das SMAs para determinar a direção da tendência. Um sinal de compra é gerado quando a SMA rápida cruza acima da SMA lenta. Um sinal de venda é gerado quando a SMA rápida cruza abaixo da SMA lenta.
A parte de quebra monitora se o preço rompe acima do preço mais alto ou cai abaixo do preço mais baixo em um período especificado.
O indicador ADX é usado para medir a força da tendência.
As linhas de stop loss e take profit são implementadas para otimizar a rentabilidade.
Em resumo, a estratégia multifatorial segue a seguinte lógica:
Quando o ADX está acima de um limiar, a tendência é considerada forte. A estratégia que segue a tendência entra em vigor. Quando o ADX está abaixo do limiar, o mercado está variando. Apenas a estratégia oscilante entra em vigor.
Em um mercado em tendência, a cruz de ouro da SMA desencadeia uma entrada longa e a cruz de morte desencadeia posições de saída.
Em um mercado variável, os sinais de negociação do oscilador estocástico são seguidos.
A estratégia de ruptura aplica-se em ambas as condições de mercado para seguir um forte ímpeto.
As linhas de stop loss e take profit são definidas para bloquear lucros e limitar perdas.
A maior vantagem da estratégia multifatorial é que combina os pontos fortes de diferentes estratégias e alcança um bom desempenho em mercados de tendências e variáveis.
Ele acompanha bem as tendências e alcança altas taxas de ganho nos mercados de tendências.
Pode beneficiar de mercados de intervalo e evitar ficar preso em posições.
Possui altos fatores de lucro com stop loss e take profit adequadamente definidos.
Considera a força da tendência para reduzir as perdas de falsos sinais.
A combinação de múltiplos indicadores leva a fortes sinais de negociação.
Os parâmetros podem ser otimizados para um melhor desempenho.
Há também riscos associados à estratégia multifatorial:
Uma combinação inadequada de fatores pode levar a sinais de negociação conflitantes.
Os múltiplos parâmetros aumentam a dificuldade de otimização e exigem dados históricos suficientes.
Pode falhar na saída de posições a tempo de a tendência se inverter, levando a grandes perdas.
O indicador ADX tem efeitos de atraso e pode perder pontos de virada da tendência.
A negociação de breakout é propensa a ficar presa em posições perdedoras.
Os riscos podem ser mitigados através de:
Testar a estabilidade dos fatores e escolher os estáveis.
Usando algoritmos de otimização heurística para encontrar os parâmetros ideais.
Configurar o stop loss adequado para controlar o drawdown máximo.
Incorporar indicadores adicionais para detectar a inversão da tendência.
Otimizar as regras de stop loss para a negociação de breakout.
A estratégia multifatorial ainda pode ser melhorada:
Testando mais tipos de fatores como volatilidade, volume etc. para encontrar melhores combinações.
Utilizando técnicas de aprendizagem de máquina para otimizar o peso dos fatores de forma dinâmica.
Aproveitando algoritmos heurísticos para otimização rápida de parâmetros.
Teste da rentabilidade em diferentes períodos de detenção.
Explorar regras dinâmicas de stop loss, por exemplo, alargar o stop loss depois de fazer alguns lucros.
Adicionar mais filtros como picos de volume para melhorar a qualidade do sinal.
Otimização dos parâmetros ADX ou utilização de indicadores de detecção de tendências mais avançados.
A estratégia multifator combina múltiplas lógicas de negociação como tendência, reversão média e ruptura. Alcança um bom desempenho em mercados de tendência e de variação. Em comparação com as estratégias de fator único, fornece retornos mais estáveis e tem grande potencial para atualizações. No entanto, a otimização de parâmetros pode ser difícil e requer dados históricos suficientes.
/*backtest start: 2023-09-30 00:00:00 end: 2023-10-30 00:00:00 period: 1h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=4 // strategy("Strategy_1", shorttitle="Strategy1",overlay=true ,pyramiding = 12, initial_capital=25000, currency='EUR', commission_type = strategy.commission.cash_per_order, commission_value = 3, default_qty_type = strategy.percent_of_equity, default_qty_value = 20) // Revision: 1 // Author: Jonas // === INPUT === // > BACKTEST RANGE < FromMonth = input(defval=1, title="From Month", minval=1, maxval=12) FromDay = input(defval=1, title="From Day", minval=1, maxval=31) FromYear = input(defval=2017, title="From Year", minval=2010) ToMonth = input(defval=1, title="To Month", minval=1, maxval=12) ToDay = input(defval=1, title="To Day", minval=1, maxval=31) ToYear = input(defval=9999, title="To Year", minval=2010) // > STRATEGY SETTINGS < bolOS = input(defval = false, type=input.bool, title="Oscillating Strategy") bolTS = input(defval = true, type=input.bool, title="Trend Strategy") bolBO = input(defval = false, type=input.bool, title="Breakout Strategy") strStrategy = input(defval = "Long", type=input.string, title="Trade Strategy",options = ["Long", "Short","Long & Short"]) flStopLoss = input(defval = 2.0, title="Stop Loss %", type=input.float)/100 flTakeProfit = input(defval = 4.0, title="Take Profit %", type=input.float)/100 // > SMA < fastMA = input(defval=8, type=input.integer, title="FastMA length", minval=1, step=1) slowMA = input(defval=21, type=input.integer, title="SlowMA length", minval=1, step=1) // > ADX < adx_len = input(defval=10, type=input.integer, title="ADX length", minval=1, step=1) adx_trend = input(defval=30, type=input.integer, title="ADX Tr", minval=1, step=1) adx_choppy = adx_trend adx_limit = adx_trend // > TRENDSCORE < ts_fromIndex = input(title="From", type=input.integer, minval=1, defval=10) ts_toIndex = input(title="To", type=input.integer, minval=1, defval=14) ts_src = input(title="Source", type=input.source, defval=close) // > Oscillator < stoch_length = 14 stoch_OverBought = 75 stoch_OverSold = 25 stoch_smoothK = 3 stoch_smoothD = 3 // === BACK TEST RANGE FUNCTION === window_start = timestamp(FromYear, FromMonth, FromDay, 00, 00) // backtest start window window_finish = timestamp(ToYear, ToMonth, ToDay, 23, 59) // backtest finish window window() => // create function "within window of time" time >= window_start and time <= window_finish ? true : false //plot(stop_level_Long, title="TEST",color=color.red, style=plot.style_linebr, linewidth=2) //plot(take_level_Long, color=color.green, style=plot.style_linebr, linewidth=2) // === ADX === adx_up = change(high) adx_down = -change(low) adx_trur = rma(tr, adx_len) adx_plus = fixnan(100 * rma(adx_up > adx_down and adx_up > 0 ? adx_up : 0, adx_len) / adx_trur) adx_minus = fixnan(100 * rma(adx_down > adx_up and adx_down > 0 ? adx_down : 0, adx_len) / adx_trur) adx_sum = adx_plus + adx_minus ADX = 100 * rma(abs(adx_plus - adx_minus) / (adx_sum == 0 ? 1 : adx_sum), adx_len) //=== TRENDSCORE === trendscore(ts_src, ts_fromIndex, ts_toIndex) => ts_sum = 0.0 for i = ts_fromIndex to ts_toIndex ts_sum := ts_sum + (ts_src >= nz(ts_src[i]) ? 1 : -1) ts_sum intTS = trendscore(ts_src, ts_fromIndex, ts_toIndex) // Long if TrendDirection = 1, Short if TrendDirection = -1; Indifferent if TrendDirection = 0 intTrendDirection = (intTS > (ts_toIndex-ts_fromIndex)) ? 1 : (intTS < (ts_fromIndex-ts_toIndex)) ? -1 : 0 // > TREND CONDITION < adx_growing = ADX > highest(ADX[1],3) intTrend = ((ADX >= adx_limit) and (ADX[1] >= adx_limit) and adx_growing) ? intTrendDirection : 0 // === ATR === ATR = sma(tr,10) ATR_100 = ATR /abs(high - low) // === STOCHASTICS === stoch_k = sma(stoch(close, high, low, stoch_length), stoch_smoothK) stoch_d = sma(stoch_k, stoch_smoothD) // === FILTER & CONDITIONS === // > STOCHASTICS < bolFilter_OS1 = close[1] > hl2[1] bolSigOsc_long_1 = (na(stoch_k) or na(stoch_d)) ? false : (crossover(stoch_d,stoch_OverSold) and stoch_k > stoch_d) ? true:false bolSigOsc_short_1 = (na(stoch_k) or na(stoch_d)) ? false : (crossunder(stoch_d,stoch_OverBought) and stoch_k < stoch_d) ? true:false bolLongOpenOS = bolSigOsc_long_1 and bolFilter_OS1 bolLongCloseOS = bolSigOsc_short_1 bolShortOpenOS = bolSigOsc_short_1 and bolFilter_OS1 bolShortCloseOS = bolSigOsc_long_1 // > TREND < bolFilter_TS1 = close[1] > hl2[1] and open[1] < hl2[1] bolFilter_TS2 = sma(close,50)>sma(close,50)[10] bolFilter_TS3 = close[1] < hl2[1] and open[1] > hl2[1] bolSigTrendLO1 = sma(close, fastMA) > sma(close, slowMA) bolSigTrendLO2 = close > sma(close,fastMA) bolSigTrendLO3 = bolSigTrendLO1 and bolSigTrendLO2 bolSigTrendLC1 = sma(close, fastMA) < sma(close, slowMA) bolSigTrendLC2 = close < sma(close, fastMA) bolSigTrendLC3 = bolSigTrendLC1 and bolSigTrendLC2 bolSigTrendSO1 = bolSigTrendLC3 bolSigTrendSC1 = bolSigTrendLO1 bolLongOpenTS = bolSigTrendLO3 and bolFilter_TS1 bolLongCloseTS = bolSigTrendLC3 and bolFilter_TS3 bolShortOpenTS = bolSigTrendSO1 and bolFilter_TS3 bolShortCloseTS = bolLongOpenTS and bolFilter_TS1 plot(sma(close, fastMA), title='FastMA', color=color.green, linewidth=2, style=plot.style_line) // plot FastMA plot(sma(close, slowMA), title='SlowMA', color=color.red, linewidth=2, style=plot.style_line) // plot SlowMA // > BREAKOUT < flFilter_BS1 = 0.5 * stdev(close,slowMA)[1] bolFilter_BS2 = volume > sma(volume,slowMA)*1.25 bolSigBreakoutLO1 = close > (highestbars(high,slowMA)[1] + flFilter_BS1) bolSigBreakoutLC1 = barssince(bolSigBreakoutLO1)==5 bolSigBreakoutSO1 = close < lowestbars(low,slowMA)[1] - flFilter_BS1 bolSigBreakoutSC1 = barssince(bolSigBreakoutSO1)==5 bolLongOpenBO = bolSigBreakoutLO1 and bolFilter_BS2 bolLongCloseBO = bolSigBreakoutLC1 bolShortOpenBO = bolSigBreakoutSO1 and bolFilter_BS2 bolShortCloseBO = bolSigBreakoutSC1 //=== STRATEGIES ENTRIES & EXITS === // > STOPS & LIMITS < stop_level_Long = strategy.position_avg_price * (1 - flStopLoss) take_level_Long = strategy.position_avg_price * (1 + flTakeProfit) stop_level_Short = strategy.position_avg_price * (1 + flStopLoss) take_level_Short = strategy.position_avg_price * (1 - flTakeProfit) // > ENTRIES / CLOSES / EXITS < if window() //only in backtest-window if (bolOS == true) if (intTrend == 0) if(strStrategy == "Long" or strStrategy == "Long & Short") strategy.entry("Lng Osc", strategy.long, when=bolLongOpenOS) // buy long when "within window of time" AND crossover if(strStrategy == "Short" or strStrategy == "Long & Short") strategy.entry("Short Osc", strategy.short, when=bolShortOpenOS) strategy.close("Lng Osc", when=(bolLongCloseOS)) //strategy.exit("Exit L OS/STD", "Lng Osc", stop = strategy.position_avg_price - 2*stdev(close,10)) strategy.exit("Exit L OS/%", "Lng Osc", stop=stop_level_Long) strategy.close("Short Osc", when=(bolShortCloseOS)) //strategy.exit("Exit S OS/STD", "Short Osc", stop = strategy.position_avg_price + 2*stdev(strategy.position_avg_price,10)) strategy.exit("Exit S OS/%", "Short Osc", stop=stop_level_Short) if (bolTS == true) if (not(intTrend == 0)) if((strStrategy == "Long") or (strStrategy == "Long & Short")) strategy.entry("Lng TD", strategy.long, when=bolLongOpenTS) // buy long when "within window of time" AND crossover if((strStrategy == "Short") or (strStrategy == "Long & Short")) strategy.entry("Short TD", strategy.short, when=(bolShortOpenTS and bolTS)) // buy long when "within window of time" AND crossover strategy.exit("Exit L TD", "Lng TD", stop=stop_level_Long) strategy.close("Lng TD", when=bolLongCloseTS) strategy.exit("Exit S TD", "Short TD", stop=stop_level_Short) strategy.close("Short TD", when=bolShortCloseTS) if (bolBO == true) if((strStrategy == "Long") or (strStrategy == "Long & Short")) strategy.entry("Lng BO", strategy.long, when=bolLongOpenBO) // buy long when "within window of time" AND crossover strategy.close("Lng BO", when=bolLongCloseBO) //strategy.exit("Exit L BO/STD", "Lng BO", stop = strategy.position_avg_price - 2*stdev(strategy.position_avg_price,10)) strategy.exit("Exit L BO/2.5%", "Lng BO", stop=stop_level_Long) if((strStrategy == "Short") or (strStrategy == "Long & Short")) strategy.entry("Short BO", strategy.short, when=bolShortOpenBO) // buy long when "within window of time" AND crossover strategy.close("Short BO", when=bolShortCloseBO) //strategy.exit("Exit S BO/STD", "Short BO", stop = strategy.position_avg_price - 2*stdev(strategy.position_avg_price,10)) strategy.exit("Exit S BO/%", "Short BO", stop=stop_level_Short)