이 전략은 주식 및 암호화폐와 같은 기본 자산을 동적으로 거래하기 위해 여러 기술적 지표의 조합 신호를 활용합니다. 전략은 자동으로 시장 추세를 식별하고 추적 할 수 있습니다. 또한 위험을 제어하기 위해 스톱 로스 메커니즘이 통합됩니다.
이 전략은 주로 이동 평균, 상대 강도 지수 (RSI), 평균 진정한 범위 (ATR) 및 방향 움직임 지수 (ADX) 를 활용하여 거래 신호를 생성합니다.
특히, 먼저 신호를 형성하기 위해 이중 이동 평균 크로스오버를 채택합니다. 빠른 라인은 10 일, 느린 라인은 50 일 길이 있습니다. 골든 크로스오버 (하위에서 느린 라인의 위를 깨는 빠른 라인) 는 구매 신호를 생성하고 죽은 크로스오버는 판매 신호를 생성합니다. 이 시스템은 장기 트렌드의 반전을 효과적으로 식별 할 수 있습니다.
이중 MAs의 위에, RSI는 트렌드 신호를 확인하고 거짓 브레이크오웃을 피하기 위해 도입된다. RSI는 빠른 라인과 느린 라인의 차이에 의해 시장 강도를 판단한다. RSI가 30을 넘으면 구매 신호가 생성된다. 70을 넘으면 판매 신호가 생성된다.
또한, ATR은 자동으로 스톱 로스 수준을 조정하는 데 사용됩니다. ATR은 시장의 변동성을 효과적으로 반영 할 수 있습니다. 변동성이 증가하면 더 넓은 스톱 로스가 설정되어 중단 될 확률을 줄일 수 있습니다.
마지막으로 ADX는 트렌드의 강도를 측정합니다. ADX는 긍정적 인 지표 DI + 및 부정적인 지표 DI- 사이의 분리를 사용하여 트렌드 강도를 측정합니다. ADX가 20을 넘을 때만 트렌드가 확립되어 실제 거래 신호가 생성됩니다.
여러 지표의 신호를 결합함으로써 전략은 거래 신호를 보내는 데 더 신중할 수 있으며 잘못된 신호의 간섭을 피하고 따라서 더 높은 승률을 달성 할 수 있습니다.
이 전략의 장점은 다음과 같습니다.
MA, RSI, ATR, ADX 등을 조합하면 정확도를 높이고 단일 지표로 인한 잘못된 판단을 피할 수 있습니다.
시장의 변동성에 따라 스톱 로스를 조정하면 스톱 아웃의 확률을 줄이고 위험을 효과적으로 관리할 수 있습니다.
실제 거래 전에 ADX로 트렌드 강도를 판단함으로써 트렌드 상거래로 인한 손실을 줄일 수 있습니다.
MA 길이, RSI 길이, ATR 기간 및 ADX 기간과 같은 매개 변수는 모두 다른 시장에 맞게 조정되고 최적화 될 수 있습니다. 따라서 전략은 강력한 적응력을 가지고 있습니다.
빠른 및 느린 MA 시스템을 사용하여 장기 트렌드를 식별하고 RSI와 같은 지표로 단기 소음을 줄이면 더 높은 이익을 위해 장기적인 트렌드를 보유 할 수 있습니다.
이 전략에는 몇 가지 위험이 있습니다.
더 많은 매개 변수는 최적화에 더 큰 어려움을 의미합니다. 부적절한 매개 변수 세트는 전략 성능을 악화시킬 수 있습니다. 더 적절한 백테스팅과 매개 변수 조정은이 위험을 완화 할 수 있습니다.
모든 기술 지표는 적용 가능한 시장 상태가 있습니다. 시장이 특이한 상태에 들어갈 때 사용 된 지표는 동시에 실패 할 수 있습니다. 이러한 BLACK SWAN 이벤트로 인한 위험은 주의가 필요합니다.
이 전략은 쇼트 트레이딩을 허용합니다. 쇼트 포지션은 본질적으로 무제한 손실의 위험을 가지고 있습니다. 적절한 스톱 로스를 설정함으로써 이것을 줄일 수 있습니다.
지표는 반동에 즉각적으로 반응할 수 없습니다. 잘못된 방향 위치는 반동 중에 종종 손실을 초래합니다. 일부 지표의 매개 변수를 단축하면 민감도가 향상 될 수 있습니다.
더 많은 최적화를 할 수 있습니다.
시장 상태와 지표 사이의 상관관계를 분석하고 의사결정을 개선하기 위해 변화하는 시장 조건에 따라 지표 가중을 동적으로 조정하는 설계 메커니즘.
딥러닝 모델을 사용하여 가격 움직임 방향을 예측하고 규칙 기반 시스템을 확장하여 정확도를 향상시킵니다.
전략이 더 잘 적응 할 수 있도록 슬라이딩 윈도우 역사 데이터를 기반으로 표시 매개 변수를 위한 적응 조정 모듈을 설계합니다.
중장기 동향을 판단하고 수익성을 향상시키기 위해 엘리엇 파동 이론과 같은 변수 기간 분석을 통합하십시오.
요약하자면,이 전략은 MA, RSI, ATR, ADX 등을 비교적 포괄적인 시스템으로 통합하여 MA 시스템을 통해 장기 트렌드를 식별하고 RSI와 같은 단기 지표와의 노이즈 간섭을 줄일 수 있습니다. 또한 성능 향상을 위해 큰 최적화 공간이 있습니다. 전략은 지표를 결합하여 결정을 개선하고 위험을 제어합니다. 추가 연구와 응용이 필요합니다.
/*backtest start: 2023-01-28 00:00:00 end: 2024-02-03 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ // This source code to my testing // © sgb //@version=5 strategy(title='Soren test 2', overlay=true, initial_capital=100, pyramiding=1, calc_on_order_fills=true, calc_on_every_tick=true, default_qty_type=strategy.percent_of_equity, default_qty_value=50, commission_value=0.04) //SOURCE ============================================================================================================================================================================================================================================================================================================= src = input(open) // INPUTS ============================================================================================================================================================================================================================================================================================================ //ADX -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ADX_options = input.string('MASANAKAMURA', title='Adx Type', options=['CLASSIC', 'MASANAKAMURA'], group='ADX') ADX_len = input.int(38, title='Adx lenght', minval=1, group='ADX') th = input.float(23, title='Adx Treshold', minval=0, step=0.5, group='ADX') // Volume ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ volume_f = input.float(1.2, title='Volume mult.', minval=0, step=0.1, group='Volume') sma_length = input.int(35, title='Volume lenght', minval=1, group='Volume') //RSI---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- len_3 = input.int(25, title='RSI lenght', group='Relative Strenght Indeks') src_3 = input.source(low, title='RSI Source', group='Relative Strenght Indeks') RSI_VWAP_length = input(25, title='Rsi vwap lenght') // Range Filter --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- per_ = input.int(26, title='SAMPLING PERIOD', minval=1, group='Range Filter') mult = input.float(2.3, title='RANGE MULTIPLIER', minval=0.1, step=0.1, group='Range Filter') // Cloud -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- len = input.int(1, title='Cloud Length', group='Cloud') //RMI ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- RMI_len = input.int(26, title='Rmi Lenght', minval=1, group='Relative Momentum Index') mom = input.int(17, title='Rmi Momentum', minval=1, group='Relative Momentum Index') RMI_os = input.int(33, title='Rmi oversold', minval=0, group='Relative Momentum Index') RMI_ob = input.int(68, title='Rmi overbought', minval=0, group='Relative Momentum Index') // Indicators Calculations ======================================================================================================================================================================================================================================================================================================== // Range Filter ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- var bool L_RF = na var bool S_RF = na Range_filter(_src, _per_, _mult) => var float _upward = 0.0 var float _downward = 0.0 wper = _per_ * 2 - 1 avrng = ta.ema(math.abs(_src - _src[1]), _per_) _smoothrng = ta.ema(avrng, wper) * _mult _filt = _src _filt := _src > nz(_filt[1]) ? _src - _smoothrng < nz(_filt[1]) ? nz(_filt[1]) : _src - _smoothrng : _src + _smoothrng > nz(_filt[1]) ? nz(_filt[1]) : _src + _smoothrng _upward := _filt > _filt[1] ? nz(_upward[1]) + 1 : _filt < _filt[1] ? 0 : nz(_upward[1]) _downward := _filt < _filt[1] ? nz(_downward[1]) + 1 : _filt > _filt[1] ? 0 : nz(_downward[1]) [_smoothrng, _filt, _upward, _downward] [smoothrng, filt, upward, downward] = Range_filter(src, per_, mult) hband = filt + smoothrng lband = filt - smoothrng L_RF := high > hband and upward > 0 S_RF := low < lband and downward > 0 //ADX------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- calcADX(_len) => up = ta.change(high) down = -ta.change(low) plusDM = na(up) ? na : up > down and up > 0 ? up : 0 minusDM = na(down) ? na : down > up and down > 0 ? down : 0 truerange = ta.rma(ta.tr, _len) _plus = fixnan(100 * ta.rma(plusDM, _len) / truerange) _minus = fixnan(100 * ta.rma(minusDM, _len) / truerange) sum = _plus + _minus _adx = 100 * ta.rma(math.abs(_plus - _minus) / (sum == 0 ? 1 : sum), _len) [_plus, _minus, _adx] calcADX_Masanakamura(_len) => SmoothedTrueRange = 0.0 SmoothedDirectionalMovementPlus = 0.0 SmoothedDirectionalMovementMinus = 0.0 TrueRange = math.max(math.max(high - low, math.abs(high - nz(close[1]))), math.abs(low - nz(close[1]))) DirectionalMovementPlus = high - nz(high[1]) > nz(low[1]) - low ? math.max(high - nz(high[1]), 0) : 0 DirectionalMovementMinus = nz(low[1]) - low > high - nz(high[1]) ? math.max(nz(low[1]) - low, 0) : 0 SmoothedTrueRange := nz(SmoothedTrueRange[1]) - nz(SmoothedTrueRange[1]) / _len + TrueRange SmoothedDirectionalMovementPlus := nz(SmoothedDirectionalMovementPlus[1]) - nz(SmoothedDirectionalMovementPlus[1]) / _len + DirectionalMovementPlus SmoothedDirectionalMovementMinus := nz(SmoothedDirectionalMovementMinus[1]) - nz(SmoothedDirectionalMovementMinus[1]) / _len + DirectionalMovementMinus DIP = SmoothedDirectionalMovementPlus / SmoothedTrueRange * 100 DIM = SmoothedDirectionalMovementMinus / SmoothedTrueRange * 100 DX = math.abs(DIP - DIM) / (DIP + DIM) * 100 adx = ta.sma(DX, _len) [DIP, DIM, adx] [DIPlusC, DIMinusC, ADXC] = calcADX(ADX_len) [DIPlusM, DIMinusM, ADXM] = calcADX_Masanakamura(ADX_len) DIPlus = ADX_options == 'CLASSIC' ? DIPlusC : DIPlusM DIMinus = ADX_options == 'CLASSIC' ? DIMinusC : DIMinusM ADX = ADX_options == 'CLASSIC' ? ADXC : ADXM L_adx = DIPlus > DIMinus and ADX > th S_adx = DIPlus < DIMinus and ADX > th // Volume ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Volume_condt = volume > ta.sma(volume, sma_length) * volume_f //RSI------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ up_3 = ta.rma(math.max(ta.change(src_3), 0), len_3) down_3 = ta.rma(-math.min(ta.change(src_3), 0), len_3) rsi_3 = down_3 == 0 ? 100 : up_3 == 0 ? 0 : 100 - 100 / (1 + up_3 / down_3) L_rsi = rsi_3 < 70 S_rsi = rsi_3 > 30 RSI_VWAP = ta.rsi(ta.vwap(close), RSI_VWAP_length) RSI_VWAP_overSold = 13 RSI_VWAP_overBought = 68 L_VAP = ta.crossover(RSI_VWAP, RSI_VWAP_overSold) S_VAP = ta.crossunder(RSI_VWAP, RSI_VWAP_overBought) //Cloud -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- PI = 2 * math.asin(1) hilbertTransform(src) => 0.0962 * src + 0.5769 * nz(src[2]) - 0.5769 * nz(src[4]) - 0.0962 * nz(src[6]) computeComponent(src, mesaPeriodMult) => hilbertTransform(src) * mesaPeriodMult computeAlpha(src, fastLimit, slowLimit) => mesaPeriod = 0.0 mesaPeriodMult = 0.075 * nz(mesaPeriod[1]) + 0.54 smooth = 0.0 smooth := (4 * src + 3 * nz(src[1]) + 2 * nz(src[2]) + nz(src[3])) / 10 detrender = 0.0 detrender := computeComponent(smooth, mesaPeriodMult) I1 = nz(detrender[3]) Q1 = computeComponent(detrender, mesaPeriodMult) jI = computeComponent(I1, mesaPeriodMult) jQ = computeComponent(Q1, mesaPeriodMult) I2 = 0.0 Q2 = 0.0 I2 := I1 - jQ Q2 := Q1 + jI I2 := 0.2 * I2 + 0.8 * nz(I2[1]) Q2 := 0.2 * Q2 + 0.8 * nz(Q2[1]) Re = I2 * nz(I2[1]) + Q2 * nz(Q2[1]) Im = I2 * nz(Q2[1]) - Q2 * nz(I2[1]) Re := 0.2 * Re + 0.8 * nz(Re[1]) Im := 0.2 * Im + 0.8 * nz(Im[1]) if Re != 0 and Im != 0 mesaPeriod := 2 * PI / math.atan(Im / Re) mesaPeriod if mesaPeriod > 1.5 * nz(mesaPeriod[1]) mesaPeriod := 1.5 * nz(mesaPeriod[1]) mesaPeriod if mesaPeriod < 0.67 * nz(mesaPeriod[1]) mesaPeriod := 0.67 * nz(mesaPeriod[1]) mesaPeriod if mesaPeriod < 6 mesaPeriod := 6 mesaPeriod if mesaPeriod > 50 mesaPeriod := 50 mesaPeriod mesaPeriod := 0.2 * mesaPeriod + 0.8 * nz(mesaPeriod[1]) phase = 0.0 if I1 != 0 phase := 180 / PI * math.atan(Q1 / I1) phase deltaPhase = nz(phase[1]) - phase if deltaPhase < 1 deltaPhase := 1 deltaPhase alpha = fastLimit / deltaPhase if alpha < slowLimit alpha := slowLimit alpha [alpha, alpha / 2.0] er = math.abs(ta.change(src, len)) / math.sum(math.abs(ta.change(src)), len) [a, b] = computeAlpha(src, er, er * 0.1) mama = 0.0 mama := a * src + (1 - a) * nz(mama[1]) fama = 0.0 fama := b * mama + (1 - b) * nz(fama[1]) alpha = math.pow(er * (b - a) + a, 2) kama = 0.0 kama := alpha * src + (1 - alpha) * nz(kama[1]) L_cloud = kama > kama[1] S_cloud = kama < kama[1] // RMI ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- RMI(len, m) => up = ta.ema(math.max(close - close[m], 0), len) dn = ta.ema(math.max(close[m] - close, 0), len) RMI = dn == 0 ? 0 : 100 - 100 / (1 + up / dn) RMI L_rmi = ta.crossover(RMI(RMI_len, mom), RMI_os) S_rmi = ta.crossunder(RMI(RMI_len, mom), RMI_ob) //STRATEGY ========================================================================================================================================================================================================================================================================================================== L_1 = L_VAP and L_RF and not S_adx S_1 = S_VAP and S_RF and not L_adx L_2 = L_adx and Volume_condt and L_rsi and L_cloud S_2 = S_adx and Volume_condt and S_rsi and S_cloud L_3 = L_rmi and L_RF and not S_adx S_3 = S_rmi and S_RF and not L_adx L_basic_condt = L_1 or L_2 or L_3 S_basic_condt = S_1 or S_2 or S_3 var bool longCondition = na var bool shortCondition = na var float last_open_longCondition = na var float last_open_shortCondition = na var int last_longCondition = 0 var int last_shortCondition = 0 longCondition := L_basic_condt shortCondition := S_basic_condt last_open_longCondition := longCondition ? close : nz(last_open_longCondition[1]) last_open_shortCondition := shortCondition ? close : nz(last_open_shortCondition[1]) last_longCondition := longCondition ? time : nz(last_longCondition[1]) last_shortCondition := shortCondition ? time : nz(last_shortCondition[1]) in_longCondition = last_longCondition > last_shortCondition in_shortCondition = last_shortCondition > last_longCondition // SWAP-SL --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- var int last_long_sl = na var int last_short_sl = na sl = input.float(2, 'Swap % period', minval=0, step=0.1, group='strategy settings') long_sl = ta.crossunder(low, (1 - sl / 100) * last_open_longCondition) and in_longCondition and not longCondition short_sl = ta.crossover(high, (1 + sl / 100) * last_open_shortCondition) and in_shortCondition and not shortCondition last_long_sl := long_sl ? time : nz(last_long_sl[1]) last_short_sl := short_sl ? time : nz(last_short_sl[1]) var bool CondIni_long_sl = 0 CondIni_long_sl := long_sl ? 1 : longCondition ? -1 : nz(CondIni_long_sl[1]) var bool CondIni_short_sl = 0 CondIni_short_sl := short_sl ? 1 : shortCondition ? -1 : nz(CondIni_short_sl[1]) Final_Long_sl = long_sl and nz(CondIni_long_sl[1]) == -1 and in_longCondition and not longCondition Final_Short_sl = short_sl and nz(CondIni_short_sl[1]) == -1 and in_shortCondition and not shortCondition var int sectionLongs = 0 sectionLongs := nz(sectionLongs[1]) var int sectionShorts = 0 sectionShorts := nz(sectionShorts[1]) // RE-ENTRY --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- if longCondition or Final_Long_sl sectionLongs += 1 sectionShorts := 0 sectionShorts if shortCondition or Final_Short_sl sectionLongs := 0 sectionShorts += 1 sectionShorts var float sum_long = 0.0 var float sum_short = 0.0 if longCondition sum_long := nz(last_open_longCondition) + nz(sum_long[1]) sum_short := 0.0 sum_short if Final_Long_sl sum_long := (1 - sl / 100) * last_open_longCondition + nz(sum_long[1]) sum_short := 0.0 sum_short if shortCondition sum_short := nz(last_open_shortCondition) + nz(sum_short[1]) sum_long := 0.0 sum_long if Final_Short_sl sum_long := 0.0 sum_short := (1 + sl / 100) * last_open_shortCondition + nz(sum_short[1]) sum_short var float Position_Price = 0.0 Position_Price := nz(Position_Price[1]) Position_Price := longCondition or Final_Long_sl ? sum_long / sectionLongs : shortCondition or Final_Short_sl ? sum_short / sectionShorts : na //TP_1 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- tp = input.float(1.2, 'Tp-1 ', minval=0, step=0.1, group='strategy settings') long_tp = ta.crossover(high, (1 + tp / 100) * fixnan(Position_Price)) and in_longCondition and not longCondition short_tp = ta.crossunder(low, (1 - tp / 100) * fixnan(Position_Price)) and in_shortCondition and not shortCondition var int last_long_tp = na var int last_short_tp = na last_long_tp := long_tp ? time : nz(last_long_tp[1]) last_short_tp := short_tp ? time : nz(last_short_tp[1]) Final_Long_tp = long_tp and last_longCondition > nz(last_long_tp[1]) Final_Short_tp = short_tp and last_shortCondition > nz(last_short_tp[1]) fixnan_1 = fixnan(Position_Price) ltp = Final_Long_tp ? fixnan_1 * (1 + tp / 100) : na fixnan_2 = fixnan(Position_Price) stp = Final_Short_tp ? fixnan_2 * (1 - tp / 100) : na if Final_Short_tp or Final_Long_tp sum_long := 0.0 sum_short := 0.0 sectionLongs := 0 sectionShorts := 0 sectionShorts if Final_Long_tp CondIni_long_sl == 1 if Final_Short_tp CondIni_short_sl == 1 // COLORS & PLOTS -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ADX_COLOR = L_adx ? color.lime : S_adx ? color.red : color.orange barcolor(color=ADX_COLOR) hbandplot = plot(hband, title='RF HT', color=ADX_COLOR, transp=50) lbandplot = plot(lband, title='RF LT', color=ADX_COLOR, transp=50) fill(hbandplot, lbandplot, title='RF TR', color=ADX_COLOR, transp=90) plotshape(longCondition, title='Long', style=shape.triangleup, location=location.belowbar, color=color.new(color.blue, 0), size=size.tiny) plotshape(shortCondition, title='Short', style=shape.triangledown, location=location.abovebar, color=color.new(color.red, 0), size=size.tiny) plot(ltp, style=plot.style_circles, linewidth=5, color=color.new(color.fuchsia, 0), editable=false) plot(stp, style=plot.style_circles, linewidth=5, color=color.new(color.fuchsia, 0), editable=false) //BACKTESTING-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Q = 50 SL = input.float(0.4, 'StopLoss ', minval=0, step=0.1) strategy.entry('long', strategy.long, when=longCondition) strategy.entry('short', strategy.short, when=shortCondition) strategy.exit('TP', 'long', qty_percent=Q, limit=fixnan(Position_Price) * (1 + tp / 100)) strategy.exit('TP', 'short', qty_percent=Q, limit=fixnan(Position_Price) * (1 - tp / 100)) strategy.exit('SL', 'long', stop=fixnan(Position_Price) * (1 - SL / 100)) strategy.exit('SL', 'short', stop=fixnan(Position_Price) * (1 + SL / 100)) // // // // // // // By SGB