다중 요인 전략

저자:차오장, 날짜: 2023-10-31 15:45:39
태그:

img

전반적인 설명

다중 요인 전략은 오시일레이션, 트렌드 추적 및 브레이크아웃 전략을 하나로 통합하여 강점을 결합합니다. 이것은 다른 시장 조건에서 더 나은 성능을 얻을 수 있습니다.

전략 논리

다중 요소 전략은 주로 다음 측면에 기초하여 모델링됩니다:

  • 오시일레이션 부분은 스토카스틱 오시일레이터를 사용하여 구매 및 판매 신호를 식별합니다. 구체적으로, %K 라인이 과소매 구역에서 %D 라인을 넘을 때 구매 신호가 생성됩니다. %K 라인이 과소매 구역에서 %D 라인을 넘을 때 판매 신호가 생성됩니다.

  • 트렌드를 따르는 부분은 트렌드 방향을 결정하기 위해 SMA의 황금 십자가를 사용합니다. 빠른 SMA가 느린 SMA 위에 넘어가면 구매 신호가 생성됩니다. 빠른 SMA가 느린 SMA 아래에 넘어가면 판매 신호가 생성됩니다.

  • 브레이크아웃 부분은 가격이 특정 기간 동안 가장 높은 가격 이상으로 돌파하거나 가장 낮은 가격 아래로 떨어지는지 모니터링합니다. 가격이 가장 높은 가격 이상으로 돌파하면 구매를 유발하고 가격이 가장 낮은 가격 아래로 떨어지면 판매를 유발합니다.

  • ADX 지표는 트렌드 강도를 측정하는 데 사용됩니다. 트렌드 거래 신호는 트렌드가 충분히 강할 때만 생성됩니다.

  • 수익성을 최적화하기 위해 스톱 손실 및 수익 라인을 구현합니다.

요약하자면, 다중 요소 전략은 아래의 논리를 따르고 있습니다.

  1. ADX가 한 임계 이상의 경우 트렌드가 강하다고 간주됩니다. 트렌드를 따르는 전략이 유효합니다. ADX가 임계 이하일 때 시장이 다양합니다. 오스실레이션 전략만 유효합니다.

  2. 트렌딩 시장에서, SMA 황금 십자선은 긴 진입을 촉발하고 죽음의 십자선은 진출을 촉발합니다.

  3. 범위에 있는 시장에서는 스토카스틱 오시일레이터로부터의 거래 신호를 따릅니다.

  4. 파업 전략은 두 가지 시장 조건에 적용됩니다.

  5. 스톱 로즈와 취익 라인은 수익을 차단하고 손실을 제한하도록 설정됩니다.

이점 분석

멀티 팩터 전략의 가장 큰 장점은 다른 전략의 강점을 결합하고 트렌딩 및 범위 시장에서 좋은 성과를 달성한다는 것입니다. 주요 장점은 다음과 같습니다.

  1. 트렌드를 잘 따라가며 트렌드 시장에서 높은 수익률을 달성합니다.

  2. 범주형 시장에서 이익을 얻을 수 있고 포지션에 갇히지 않도록 합니다.

  3. 높은 수익률을 가지고 있고 제대로 설정된 스톱 로스로 수익을 취합니다.

  4. 잘못된 신호로 인한 손실을 줄이기 위해 트렌드 강도를 고려합니다.

  5. 여러 가지 지표의 조합은 강력한 거래 신호로 이어집니다.

  6. 더 나은 성능을 위해 매개 변수를 최적화 할 수 있습니다.

위험 분석

또한 다중 요인 전략과 관련된 위험도 있습니다.

  1. 부적절 한 요인 조합 은 상반 된 거래 신호 를 초래 할 수 있다. 최적의 조합 을 찾기 위해 광범위한 테스트 가 필요 하다.

  2. 여러 매개 변수가 최적화의 어려움을 증가시키고 충분한 역사적 데이터를 필요로합니다.

  3. 트렌드가 역전될 때 지점을 제때 종료하지 못하고 큰 손실을 초래할 수도 있습니다.

  4. ADX 지표는 지연 효과를 가지고 있으며 트렌드 전환점을 놓칠 수 있습니다.

  5. 브레이크오웃 거래는 손실 포지션에 갇히기 쉽기 때문에 합리적인 스톱 로스가 필요합니다.

위험은 다음을 통해 완화 될 수 있습니다.

  1. 요인 안정성 검사를 거쳐 안정적인 요인을 선택합니다.

  2. 최적의 매개 변수를 찾기 위해 유러스틱 최적화 알고리즘을 이용합니다.

  3. 최대 마감량을 조절하기 위해 적절한 스톱 로스를 설정합니다.

  4. 트렌드 반전을 감지하기 위한 추가 지표를 포함합니다.

  5. 브레이크오웃 거래에 필요한 스톱 로스 규칙을 최적화합니다.

개선 방향

이 다중 요소 전략은 여전히 개선 할 여지가 있습니다.

  1. 더 나은 조합을 찾기 위해 변동성, 부피 등과 같은 더 많은 요인 유형을 테스트합니다.

  2. 기계 학습 기술을 사용하여 동적으로 요인 가중을 최적화합니다.

  3. 빠른 매개 변수 최적화를 위한 유리스틱 알고리즘을 활용합니다.

  4. 다른 보유 기간에 수익성을 테스트합니다.

  5. 동적 스톱 로스 규칙을 탐구합니다. 예를 들어, 수익을 얻은 후 스톱 로스를 확장하는 것입니다.

  6. 신호 품질을 향상시키기 위해 볼륨 스파이크와 같은 더 많은 필터를 추가합니다.

  7. ADX 매개 변수를 최적화하거나 더 발전된 트렌드 감지 지표를 사용합니다.

결론

다중 요인 전략은 트렌드, 평균 역전 및 브레이크아웃과 같은 여러 거래 논리를 결합합니다. 트렌딩 및 범위 시장 모두에서 좋은 성능을 달성합니다. 단일 요인 전략에 비해 더 안정적인 수익을 제공하고 업그레이드 할 수있는 큰 잠재력을 가지고 있습니다. 그러나 매개 변수 최적화는 어려울 수 있으며 충분한 역사적 데이터가 필요합니다. 전반적으로 다중 요인 전략은 추가 연구 및 최적화에 가치가있는 매우 효과적인 알고리즘 거래 기술입니다.


/*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)




더 많은