Стратегия захвата двойной скользящей средней линии

Автор:Чао Чжан, Дата: 2023-12-13 15:28:50
Тэги:

img

Обзор

Эта стратегия использует двойные скользящие средние линии для определения направления тенденции рынка в сочетании с полосами Боллинджера для выявления условий перекупки и перепродажи, чтобы достичь покупки низкого и продажи высокого для получения прибыли.

Логика стратегии

Стратегия использует двойные скользящие средние для определения общего направления рынка, опираясь на полосы Боллинджера для конкретных сигналов входа.

Правило двойной скользящей средней предусматривает вычисление краткосрочной и долгосрочной экспоненциальной скользящей средней линии, причем краткосрочная линия, пересекающая долгосрочную линию вверх, указывает на сигнал покупки; краткосрочная линия, пересекающая вниз через долгосрочную, представляет собой сигнал продажи.

Индикатор Болинджерских полос определяет, являются ли цены перекупленными или перепроданными. Средняя полоса Болинджерских полос представляет собой скользящую среднюю линию цен закрытия n-период, в то время как ширина полосы представляет стандартное отклонение скользящей средней за последние n периодов. Цены, приближающиеся к верхней полосе, указывают на состояние перекупления, а те, которые приближаются к нижней полосе, представляют собой ситуацию перепродажи.

Правила стратегии определяются следующим образом: Когда короткая средняя линия пересекает длинную среднюю линию вверх плюс цена закрытия, проникающая выше верхней полосы Боллинджера, идти длинным.

Стоп-лосс после длинной продажи устанавливается на самом низком уровне за последние n дней, в то время как получение прибыли размещается в 1,6 раза выше входной цены. Стоп-лосс после короткой продажи привязан к наивысшему максимуму за последние n дней с получением прибыли в 0,6 раза выше входной цены.

Кроме того, в стратегии учитывается индекс тренда EMA для предотвращения переворота тренда.

Анализ преимуществ

  1. Использование двойных скользящих средних для определения общего направления в сочетании с полосами Боллинджера для выявления конкретных входных точек представляет собой разумную комбинацию индикаторов;
  2. Принятие наименьшего минимума за n дней в качестве стоп-лосса для длинных и наибольшего максимума за n дней в качестве стоп-лосса для коротких помогает уменьшить вероятность проведения стопов;
  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)

Больше