이중 이동 평균 선 포착 전략

저자:차오장, 날짜: 2023-12-13 15:28:50
태그:

img

전반적인 설명

이 전략은 이중 이동 평균 라인을 사용하여 시장 트렌드 방향을 결정하고 볼링거 밴드를 사용하여 과잉 구매 및 과잉 판매 조건을 식별하여 수익을 얻기 위해 낮은 구매와 높은 판매를 달성합니다.

전략 논리

이 전략은 시장의 전반적인 방향을 확인하기 위해 이중 이동 평균을 사용하며 특정 입시 신호를 위해 볼링거 밴드 (Bollinger Band) 에 의존합니다.

이중 이동 평균 규칙은 단기 및 장기 지수 이동 평균 라인을 계산하도록 규정하고 있으며, 단기 라인이 장기 라인을 상향으로 가로 지르면 구매 신호를 나타냅니다. 단기 라인이 장기 라인을 상향으로 가로 지르면 판매 신호를 구성합니다.

볼링거 밴드 지표는 가격이 과잉 구매 또는 과잉 판매되는지를 결정합니다. 볼링거 밴드의 중간 밴드는 n 기간 종료 가격의 이동 평균 라인이며, 밴드 폭은 지난 n 기간 동안 이동 평균의 표준 편차를 나타냅니다. 상단 지대에 접근하는 가격은 과잉 구매 상태를 나타냅니다. 하단 지대에 접근하는 것은 과잉 판매 상황을 구성합니다.

전략 규칙은 다음과 같이 정의됩니다. 짧은 평균선이 긴 평균선을 상향으로 가로질러 닫기 가격과 볼링거 상단선을 넘을 때, 길게 가십시오. 짧은 라인이 긴 라인을 가로질러 하향으로 가로질러 닫기 가격과 볼링거 하단선을 넘을 때, 짧게 가십시오.

장기간 거래 후의 스톱 로스는 지난 n 일 동안 가장 낮은 수준으로 설정되며, 영업이익은 입시 가격의 1.6 배로 설정됩니다. 단편 판매 후의 스톱 로스는 지난 n 일 동안 가장 높은 수준에 고정되며, 영업이익은 입시 가격의 0.6 배로 설정됩니다.

또한 전략은 EMA 트렌드 인덱스를 고려하여 트렌드 반전을 피합니다.

이점 분석

  1. 전체 방향을 결정하기 위해 이중 이동평균을 사용하는 것은 특정 입구점을 강조하기 위해 볼링거 밴드와 결합하여 합리적인 지표 믹스를 나타냅니다.
  2. 최저 하락값을 롱 (long) 로, 최저 하락값을 셔트 (short) 로 채택하면 스톱 손실의 가능성을 줄일 수 있습니다.
  3. 입시 가격의 1.6배로 수익 목표를 설정하면 적절한 수익을 얻는 것이 용이해집니다.
  4. EMA 트렌드 인덱스를 고려하면 주요 트렌드에 대한 거래를 피하고 시스템 손실을 줄일 수 있습니다.

위험 분석

  1. 볼링거 밴드 매개 변수의 부적절한 최적화는 과도하게 빈번한 거래 또는 불충분한 신호로 이어질 수 있습니다.
  2. 너무 느슨한 스톱 로스 포인트는 더 큰 손실을 유도합니다.
  3. 너무 엄격한 수익 제한은 더 큰 이익을 잃게 합니다.

위의 위험을 해결하기 위해 볼링거 매개 변수 조합을 최적화하고 최적의 설정을 선택하기 위해 다른 스톱 로스/프로프트 캡처 임계 수준을 테스트하십시오.

최적화 방향

  1. 이상적인 조합을 찾아내기 위해 볼링거 밴드 입력 매개 변수를 최적화합니다.
  2. 스톱 로스 인크리먼트 매개 변수를 조사하여 스톱을 실행할 확률을 줄이십시오.
  3. 테스트는 가능한 더 큰 이득을 얻기 위해 수익 곱셈 값을 취합니다.

결론

이 전략은 이중 이동 평균을 사용하여 전반적인 트렌드를 확인하고 특정 입시 신호에 볼링거 밴드를 의존함으로써 백테스트에서 신뢰성있게 수행되었습니다. 지속적인 매개 변수 최적화 및 규칙 수정으로 추가 성능 개선이 예상 될 수 있습니다. 스톱 손실 / 이익 취득 메커니즘은 또한 적응을 위해 다른 시스템에 이전 할 수 있습니다.


/*backtest
start: 2023-12-05 00:00:00
end: 2023-12-06 22:00:00
period: 15m
basePeriod: 5m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This close code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © AugustoErni

//@version=5
strategy('Bollinger Bands Modified (Stormer)', overlay=true)

bbL                   = input.int(20, title='BB Length/Comprimento da Banda de Bollinger', minval=1, step=1, tooltip='Calculate the length of bollinger bands./Calcula o comprimento das bandas de bollinger.')
mult                  = input.float(0.38, title='BB Standard Deviation/Desvio Padrão da Banda de Bollinger', minval=0.01, step=0.01, tooltip='Calculate the standard deviation of bollinger bands./Calcula o desvio padrão das bandas de bollinger.')
emaL                  = input.int(80, title='EMA Length/Comprimento da Média Móvel Exponencial', minval=1, step=1, tooltip='Calculate the length of EMA./Calcula o comprimento da EMA.')
highestHighL          = input.int(7, title='Highest High Length/Comprimento da Alta Maior', minval=1, step=1, tooltip='Fetches the highest high candle from length input. Use to set stop loss for short position./Obtém a vela de maior alta com base na medida fornecida. Usa para definir o stop loss para uma posição curta.')
lowestLowL            = input.int(7, title='Lowest Low Length/Comprimento da Baixa Menor', minval=1, step=1, tooltip='Fetches the lowest low candle from length input. Use to set stop loss for long position./Obter a vela de menor baixa com base na medida fornecida. Usa para definir o stop loss para uma posição longa.')
targetFactor          = input.float(1.6, title='Target Take Profit/Objetivo de Lucro Alvo', minval=0.1, step=0.1, tooltip='Calculate the take profit factor when entry position./Calcula o fator do alvo lucro ao entrar na posição.')
emaTrend              = input.bool(true, title='Check Trend EMA/Verificar Tendência da Média Móvel Exponencial', tooltip='Use EMA as trend verify for opening position./Usa a EMA como verificação de tendência para abrir posição.')
crossoverCheck        = input.bool(false, title='Add Another Crossover Check/Adicionar Mais uma Verificação de Cruzamento Superior', tooltip='This option is to add one more veryfication attempt to check if price is crossover upper bollinger band./Esta opção é para adicionar uma verificação adicional para avaliar se o preço cruza a banda superior da banda de bollinger.')
crossunderCheck       = input.bool(false, title='Add Another Crossunder Check/Adicionar Mais uma Verificação de Cruzamento Inferior', tooltip='This option is to add one more veryfication attempt to check if price is crossunder lower bollinger band./Esta opção é para adicionar uma verificação adicional para avaliar se o preço cruza a banda inferior da banda de bollinger.')
insideBarPatternCheck = input.bool(true, title='Show Inside Bar Pattern/Mostrar Padrão de Inside Bar', tooltip='This option is to show possible inside bar pattern./Esta opção é para mostrar um possível padrão de inside bar.')

[middle, upper, lower] = ta.bb(close, bbL, mult)
ema                    = ta.ema(close, emaL)
highestHigh            = ta.highest(high, highestHighL)
lowestLow              = ta.lowest(low, lowestLowL)
isCrossover            = ta.crossover(close, upper) ? 1 : 0
isCrossunder           = ta.crossunder(close, lower) ? 1 : 0

isPrevBarHighGreaterCurBarHigh = high[1] > high ? 1 : 0
isPrevBarLowLesserCurBarLow    = low[1] < low ? 1 : 0
isInsideBar                    = isPrevBarHighGreaterCurBarHigh and isPrevBarLowLesserCurBarLow ? 1 : 0

isBarLong  = ((close - open) > 0) ? 1 : 0
isBarShort = ((close - open) < 0) ? 1 : 0

isLongCross  = crossoverCheck ? ((isBarLong and not isBarShort) and (open < upper and close > upper)) ? 1 : 0 : isCrossover ? 1 : 0
isShortCross = crossunderCheck ? ((isBarShort and not isBarLong) and (close < lower and open > lower)) ? 1 : 0 : isCrossunder ? 1 : 0

isCandleAboveEma = close > ema ? 1 : 0
isCandleBelowEma = close < ema ? 1 : 0

isLongCondition  = emaTrend ? isLongCross and isCandleAboveEma ? 1 : 0 : isLongCross
isShortCondition = emaTrend ? isShortCross and isCandleBelowEma ? 1 : 0 : isShortCross

isPositionNone  = strategy.position_size == 0 ? 1 : 0
isPositionLong  = strategy.position_size > 0 ? 1 : 0
isPositionShort = strategy.position_size < 0 ? 1 : 0

var float enterLong     = 0.0
var float stopLossLong  = 0.0
var float targetLong    = 0.0
var float enterShort    = 0.0
var float stopLossShort = 0.0
var float targetShort   = 0.0
var bool isLongEntry    = false
var bool isShortEntry   = false

if (isPositionNone)
    isLongEntry   := false
    isShortEntry  := false
    enterLong     := 0.0
    stopLossLong  := 0.0
    targetLong    := 0.0
    enterShort    := 0.0
    stopLossShort := 0.0
    targetShort   := 0.0
if (isPositionShort or isPositionNone)
    isLongEntry  := false
    enterLong    := 0.0
    stopLossLong := 0.0
    targetLong   := 0.0
if (isPositionLong or isPositionNone)
    isShortEntry  := false
    enterShort    := 0.0
    stopLossShort := 0.0
    targetShort   := 0.0
if (isPositionLong and isLongEntry)
    isLongEntry   := true
    isShortEntry  := false
    enterShort    := 0.0
    stopLossShort := 0.0
    targetShort   := 0.0
if (isPositionShort and isShortEntry)
    isShortEntry := true
    isLongEntry  := false
    enterLong    := 0.0
    stopLossLong := 0.0
    targetLong   := 0.0

if (isLongCondition and not isLongEntry)
    isLongEntry  := true
    enterLong    := close
    stopLossLong := lowestLow
    targetLong   := (enterLong + (math.abs(enterLong - stopLossLong) * targetFactor))
    alertMessage = '{ "side/lado": "buy", "entry/entrada": ' + str.tostring(enterLong) + ', "stop": ' + str.tostring(stopLossLong) + ', "target/alvo": ' + str.tostring(targetLong) + ' }'
    alert(alertMessage)
    strategy.entry('Long', strategy.long)
    strategy.exit('Exit Long', 'Long', stop=stopLossLong, limit=targetLong)

if (isShortCondition and not isShortEntry)
    isShortEntry  := true
    enterShort    := close
    stopLossShort := highestHigh
    targetShort   := (enterShort - (math.abs(enterShort - stopLossShort) * targetFactor))
    alertMessage = '{ "side/lado": "sell", "entry/entrada": ' + str.tostring(enterShort) + ', "stop": ' + str.tostring(stopLossShort) + ', "target/alvo": ' + str.tostring(targetShort) + ' }'
    alert(alertMessage)
    strategy.entry('Short', strategy.short)
    strategy.exit('Exit Short', 'Short', stop=stopLossShort, limit=targetShort)

plot(upper, title='Upper Band', color=color.blue)
plot(middle, title='Middle Band', color=color.gray)
plot(lower, title='Lower Band', color=color.blue)
plot(ema, title='EMA', color=color.white)

barcolor(insideBarPatternCheck and isInsideBar and isBarLong ? color.lime : insideBarPatternCheck and isInsideBar and isBarShort ? color.maroon : na, title='Inside Bar Color in Long Bar Long and in Short Bar Short/Cor do Inside Bar em Barra Longa Longa e em Barra Curta Curta')

tablePosition    = position.bottom_right
tableColumns     = 2
tableRows        = 5
tableFrameWidth  = 1
tableBorderColor = color.gray
tableBorderWidth = 1

tableInfoTrade = table.new(position=tablePosition, columns=tableColumns, rows=tableRows, frame_width=tableFrameWidth, border_color=tableBorderColor, border_width=tableBorderWidth)

table.cell(table_id=tableInfoTrade, column=0, row=0)
table.cell(table_id=tableInfoTrade, column=1, row=0)

table.cell(table_id=tableInfoTrade, column=0, row=1, text='Entry Side/Lado da Entrada', text_color=color.white)
table.cell(table_id=tableInfoTrade, column=0, row=2, text=isLongEntry ? 'LONG' : isShortEntry ? 'SHORT' : 'NONE/NENHUM', text_color=color.yellow)

table.cell(table_id=tableInfoTrade, column=1, row=1, text='Entry Price/Preço da Entrada', text_color=color.white)
table.cell(table_id=tableInfoTrade, column=1, row=2, text=isLongEntry ? str.tostring(enterLong) : isShortEntry ? str.tostring(enterShort) : 'NONE/NENHUM', text_color=color.blue)

table.cell(table_id=tableInfoTrade, column=0, row=3, text='Take Profit Price/Preço Alvo Lucro', text_color=color.white)
table.cell(table_id=tableInfoTrade, column=0, row=4, text=isLongEntry ? str.tostring(targetLong) : isShortEntry ? str.tostring(targetShort) : 'NONE/NENHUM', text_color=color.green)

table.cell(table_id=tableInfoTrade, column=1, row=3, text='Stop Loss Price/Preço Stop Loss', text_color=color.white)
table.cell(table_id=tableInfoTrade, column=1, row=4, text=isLongEntry ? str.tostring(stopLossLong) : isShortEntry ? str.tostring(stopLossShort) : 'NONE/NENHUM', text_color=color.red)

더 많은