Стратегия торговли EMA с возвратом к среднему значению


Дата создания: 2023-10-26 15:33:50 Последнее изменение: 2023-10-26 15:33:50
Копировать: 2 Количество просмотров: 1006
1
Подписаться
1617
Подписчики

Стратегия торговли EMA с возвратом к среднему значению

Обзор

Торговая стратегия, основанная на степени отклонения цены от средней линии для открытия позиций и проведения позиционных операций. Она использует процентную разницу в расстоянии от средней линии EMA от текущей цены в качестве сигнала для открытия позиции и использует отслеживание стоп-лосса для управления позициями.

Стратегический принцип

Эта стратегия использует EMA в качестве среднелинейного показателя и рассчитывает процентную разницу между текущей ценой и EMA. Когда цена достаточно далеко от EMA (по умолчанию 9%), открывается большая позиция; когда цена достаточно близко к EMA (по умолчанию 1%), закрывается. После открытия позиции, она использует операционный стоп-лосс для блокирования прибыли, постепенно повышая стоп-лосс по мере увеличения прибыли.

В частности, стратегия включает в себя следующие компоненты:

  1. Вычислить среднюю линию EMA. Можно настроить цикл (по умолчанию 200), источник данных (закрывающая цена), способ расчета (EMA, SMA, RMA, WMA).

  2. Расчет процентной разницы между текущей ценой и EMA. Обратите внимание на обработку положительных и отрицательных значений.

  3. Открытие позиции в зависимости от пропорции разрыва. Предельный предел открытия позиции составляет 9% (конфигурируемо), а предел открытия позиции по умолчанию составляет 9% (конфигурируемо).

  4. Поддерживает гравитационное открытие. Можно настроить количество и степень лестницы для гравитации.

  5. Следить за остановкой после открытия позиции. Конфигурируемый порог для запуска остановки (прибыль 1%) и траекторная величина (прибыль 1%)

  6. Прямые позиции в зависимости от разрыва. Прямые позиции с большим количеством позиций имеют порог в 1% (конфигурируемый), пустые позиции - то же самое.

  7. Отмена невыполненного заказа. Отмена невыполненного заказа, когда цена снова приближается к EMA.

  8. Конфигурируемый процент остановки убытков.

  9. Поддержка обратной связи и транзакций в реальном времени.

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

Эта стратегия имеет следующие преимущества:

  1. Используя концепцию регрессии средней линии, открывайте позиции, когда цена отходит от средней линии, а при возвращении сглаживайте позиции, в соответствии с теорией трендовых торгов.

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

  3. В результате строительства складов можно строить их по частям, что позволяет снизить затраты на строительство.

  4. Операционный стоп-лосс может блокировать прибыль, управлять рисками.

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

  6. Поддержка основного языка программирования Pine Script, который можно использовать непосредственно в TradingView.

  7. Интуитивное отображение графиков для удобства анализа.

Анализ рисков

Также существуют следующие риски:

  1. Риск совпадения данных обратной связи. Оптимизация параметров может быть чрезмерно совпадает с данными обратной связи, эффективность реального диска сомнительна.

  2. Риск срыва средней линии. Цены могут сильно отклониться от средней линии в течение длительного времени и не вернуться назад.

  3. Стоп-падеж может быть превышен.

  4. Сделки бывают частыми, а расходы - тяжелыми.

  5. Некоторые из них, как правило, имеют более длительный цикл наблюдений.

Управление рисками:

  1. Многократная корректировка параметров, чтобы обеспечить стабильность параметров.

  2. Рационально распределенный равнолинейный цикл, который не может быть слишком коротким или слишком длинным

  3. Примерная разрывная остановка для предотвращения зацепления.

  4. Соответствующее смягчение условий открытия позиций, снижение частоты торгов.

  5. Вместе с другими показателями повышается адаптация к чрезвычайным ситуациям.

Направление оптимизации

Эта стратегия может быть оптимизирована в следующих аспектах:

  1. Добавить фильтрующие условия, такие как объем торгов, BRI, RSI и другие, чтобы уменьшить ложные сигналы.

  2. Добавление комбинированных средних линий, таких как двойная система EMA, повышает вероятность торговли в сторону.

  3. Оптимизация стратегий остановки убытков, таких как адаптивная остановка убытков, выход из канделяра и т. д., для дальнейшего ограничения риска.

  4. Добавлена функция автоматической оптимизации параметров для автоматического поиска наилучших комбинаций параметров.

  5. Повышение вероятности отклонения цены от средней линии с помощью машинного обучения.

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

  7. Интеграция фондовых пулов, автоматический выбор акций и торгов, расширение потенциала стратегии.

Подвести итог

Стратегия EMA является стратегией для отслеживания тенденции, основанной на характеристиках ценовой средней обратной линии. Она разумно использует статистические характеристики средней линии для определения обратного тренда и управления риском с помощью остановочных потерь. По сравнению с традиционной стратегией для торговли средней линией, она уделяет больше внимания динамическому отслеживанию стоп-убытков, а не открытию позиций на фиксированном уровне.

Исходный код стратегии
/*backtest
start: 2022-10-19 00:00:00
end: 2023-10-25 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

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

//@version=5
strategy(title="EMA Mean Reversion Strategy", overlay=true, max_bars_back=5000, default_qty_type=strategy.percent_of_equity, default_qty_value=100,initial_capital=100000, commission_type=strategy.commission.percent, commission_value=0.05, backtest_fill_limits_assumption=2)


// Indenting Classs
indent_1 = " "
indent_2 = "  "
indent_3 = "   "
indent_4 = "    "


// Tooltips
longEntryToolTip = "When the percentage that the price is away from the selected EMA reaches this point, a long postion will open."
shortEntryToolTip = "When the percentage that the price is away from the selected EMA reaches this point, a short postion will open."
closeEntryToolTip = "When the percentage that the price is away from the selected EMA reaches this point, open postion will close."
ladderInToolTip = "Enable this to use the laddering settings below."
cancelEntryToolTip = "When the percentage that the price is away from the selected EMA reaches this point, any unfilled entries will be canceled."

// Group Titles
group_one_title = "EMA Settings"
group_two_title = "Entry Settings"


// Colors
blue = color.new(#00A5FF,0)
lightBlue = color.new(#00A5FF,90)
green = color.new(#2DBD85,0)
gray_80 =  color.new(#7F7F7F,80)
gray_60 =  color.new(#7F7F7F,60)
gray_40 =  color.new(#7F7F7F,40)
white = color.new(#ffffff,0)
red = color.new(#E02A4A,0)
transparent = color.new(#000000,100)


// Strategy Settings
EMAtimeframe = input.timeframe(defval="", title="Timeframe", group=group_one_title)
EMAlength = input.int(defval=200, minval=1, title="Length", group=group_one_title)
EMAtype = input.string(defval="EMA", options = ["EMA", "SMA", "RMA", "WMA"], title="Type", group=group_one_title)
EMAsource = input.source(defval=close, title="Source", group=group_one_title)

openLongEntryAbove = input.float(defval=9, title="Long Position Entry Trigger", tooltip=longEntryToolTip, group=group_two_title)
openEntryEntryAbove = input.float(defval=9, title="Short Position Entry Trigger", tooltip=shortEntryToolTip, group=group_two_title)
closeEntryBelow = input.float(defval=1.0, title="Close Position Trigger", tooltip=closeEntryToolTip, group=group_two_title)
cancelEntryBelow = input.float(defval=4, title="Cancel Unfilled Entries Trigger", tooltip=cancelEntryToolTip, group=group_two_title)

enableLaddering = input.bool(defval=true, title="Ladder Into Positions", tooltip=ladderInToolTip, group=group_two_title)
ladderRungs = input.int(defval=4, minval=2, maxval=4, step=1, title=indent_4+"Ladder Rungs", group=group_two_title)
ladderStep = input.float(defval=.5, title=indent_4+"Ladder Step (%)", step=.1, group=group_two_title)/100
stop_loss_val = input.float(defval=4.0, title="Stop Loss (%)", step=0.1, group=group_two_title)/100
start_trailing_after = input.float(defval=1, title="Start Trailing After (%)", step=0.1, group=group_two_title)/100
trail_behind = input.float(defval=1, title="Trail Behind (%)", step=0.1, group=group_two_title)/100

// Calculate trailing stop values
long_start_trailing_val = strategy.position_avg_price + (strategy.position_avg_price * start_trailing_after)
long_trail_behind_val = close - (strategy.position_avg_price * trail_behind)
long_stop_loss = strategy.position_avg_price * (1.0 - stop_loss_val)
short_start_trailing_val = strategy.position_avg_price - (strategy.position_avg_price * start_trailing_after)
short_trail_behind_val = close + (strategy.position_avg_price * trail_behind)
short_stop_loss = strategy.position_avg_price * (1 + stop_loss_val)


// Calulate EMA
EMA = switch EMAtype
    "EMA" => ta.ema(EMAsource, EMAlength)
    "SMA" => ta.sma(EMAsource, EMAlength)
    "RMA" => ta.rma(EMAsource, EMAlength)
    "WMA" => ta.wma(EMAsource, EMAlength)
    => na
EMA_ = EMAtimeframe == timeframe.period ? EMA : request.security(syminfo.ticker, EMAtimeframe, EMA[1], lookahead = barmerge.lookahead_on)
plot(EMA_, title="EMA", linewidth=2, color=blue, editable=true)

EMA_cloud_upper_band_val = EMA_ + (EMA_ * openLongEntryAbove/100)
EMA_cloud_lower_band_val = EMA_ - (EMA_ * openLongEntryAbove/100)
EMA_cloud_upper_band = plot(EMA_cloud_upper_band_val, title="EMA Cloud Upper Band", color=blue)
EMA_cloud_lower_band = plot(EMA_cloud_lower_band_val, title="EMA Cloud Upper Band", color=blue)
fill(EMA_cloud_upper_band, EMA_cloud_lower_band, editable=false, color=lightBlue)

distance_from_EMA = ((close - EMA_)/close)*100
if distance_from_EMA < 0
    distance_from_EMA := distance_from_EMA * -1

// Calulate Ladder Entries
long_ladder_1_limit_price = close - (close * 1 * ladderStep)
long_ladder_2_limit_price = close - (close * 2 * ladderStep)
long_ladder_3_limit_price = close - (close * 3 * ladderStep)
long_ladder_4_limit_price = close - (close * 4 * ladderStep)

short_ladder_1_limit_price = close + (close * 1 * ladderStep)
short_ladder_2_limit_price = close + (close * 2 * ladderStep)
short_ladder_3_limit_price = close + (close * 3 * ladderStep)
short_ladder_4_limit_price = close + (close * 4 * ladderStep)

var position_qty = strategy.equity/close
if enableLaddering
    position_qty := (strategy.equity/close) / ladderRungs
else
    position_qty := strategy.equity/close
    
plot(position_qty, color=white)
//plot(strategy.equity, color=green)

// Entry Conditions
currently_in_a_postion = strategy.position_size != 0
currently_in_a_long_postion = strategy.position_size > 0
currently_in_a_short_postion = strategy.position_size < 0
average_price = strategy.position_avg_price

bars_since_entry = currently_in_a_postion ? bar_index - strategy.opentrades.entry_bar_index(strategy.opentrades - 1) + 1 : 5
long_run_up = ta.highest(high, bar_index == 0 ? 5000: bars_since_entry)
long_run_up_line = plot(long_run_up, style=plot.style_stepline, editable=false, color=currently_in_a_long_postion ? green : transparent)
start_trailing_long_entry = currently_in_a_long_postion and long_run_up > long_start_trailing_val
long_trailing_stop = start_trailing_long_entry ? long_run_up - (long_run_up * trail_behind) : long_stop_loss
long_trailing_stop_line = plot(long_trailing_stop, style=plot.style_stepline, editable=false, color=currently_in_a_long_postion ? long_trailing_stop > strategy.position_avg_price ? green : red : transparent)

short_run_up = ta.lowest(low, bar_index == 0 ? 5000: bars_since_entry)
short_run_up_line = plot(short_run_up, style=plot.style_stepline, editable=false, color=currently_in_a_short_postion ? green : transparent)
start_trailing_short_entry = currently_in_a_short_postion and short_run_up < short_start_trailing_val
short_trailing_stop = start_trailing_short_entry ? short_run_up + (short_run_up * trail_behind) : short_stop_loss
short_trailing_stop_line = plot(short_trailing_stop, style=plot.style_stepline, editable=false, color=currently_in_a_short_postion ? short_trailing_stop < strategy.position_avg_price ? green : red : transparent)

long_conditions_met = distance_from_EMA > openLongEntryAbove and close < EMA_ and not currently_in_a_postion
short_conditions_met = distance_from_EMA > openEntryEntryAbove and close > EMA_ and not currently_in_a_postion
close_long_entries = distance_from_EMA <= closeEntryBelow or close <= long_trailing_stop
close_short_entries = distance_from_EMA <= closeEntryBelow or close >= short_trailing_stop
cancel_entries = distance_from_EMA <= cancelEntryBelow

plotshape(long_conditions_met ? close : na, style=shape.diamond, title="Long Conditions Met" )
plotshape(short_conditions_met ? close : na, style=shape.diamond, title="Short Conditions Met" )
plot(average_price,style=plot.style_stepline, editable=false, color=currently_in_a_postion ? blue : transparent)

// Long Entry
if enableLaddering
    if ladderRungs == 2
        strategy.entry(id="Long Ladder 1", direction=strategy.long, qty=position_qty, limit=long_ladder_1_limit_price, when=long_conditions_met)
        strategy.entry(id="Long Ladder 2", direction=strategy.long, qty=position_qty, limit=long_ladder_2_limit_price, when=long_conditions_met)
    else if ladderRungs == 3
        strategy.entry(id="Long Ladder 1", direction=strategy.long, qty=position_qty, limit=long_ladder_1_limit_price, when=long_conditions_met)
        strategy.entry(id="Long Ladder 2", direction=strategy.long, qty=position_qty, limit=long_ladder_2_limit_price, when=long_conditions_met)
        strategy.entry(id="Long Ladder 3", direction=strategy.long, qty=position_qty, limit=long_ladder_3_limit_price, when=long_conditions_met)
    else if ladderRungs == 4
        strategy.entry(id="Long Ladder 1", direction=strategy.long, qty=position_qty, limit=long_ladder_1_limit_price, when=long_conditions_met)
        strategy.entry(id="Long Ladder 2", direction=strategy.long, qty=position_qty, limit=long_ladder_2_limit_price, when=long_conditions_met)
        strategy.entry(id="Long Ladder 3", direction=strategy.long, qty=position_qty, limit=long_ladder_3_limit_price, when=long_conditions_met)
        strategy.entry(id="Long Ladder 4", direction=strategy.long, qty=position_qty, limit=long_ladder_4_limit_price, when=long_conditions_met)
    
    strategy.exit(id="Close Long Ladder 1", from_entry="Long Ladder 1", stop=long_trailing_stop, limit=long_trailing_stop, when=close_long_entries)
    strategy.exit(id="Close Long Ladder 2", from_entry="Long Ladder 2", stop=long_trailing_stop, limit=long_trailing_stop, when=close_long_entries)
    strategy.exit(id="Close Long Ladder 3", from_entry="Long Ladder 3", stop=long_trailing_stop, limit=long_trailing_stop, when=close_long_entries)
    strategy.exit(id="Close Long Ladder 4", from_entry="Long Ladder 4", stop=long_trailing_stop, limit=long_trailing_stop, when=close_long_entries)
    
    strategy.cancel(id="Long Ladder 1", when=cancel_entries)
    strategy.cancel(id="Long Ladder 2", when=cancel_entries)
    strategy.cancel(id="Long Ladder 3", when=cancel_entries)
    strategy.cancel(id="Long Ladder 4", when=cancel_entries)
else
    strategy.entry(id="Long", direction=strategy.long, qty=100, when=long_conditions_met)
    strategy.exit(id="Close Long", from_entry="Long", stop=long_stop_loss, limit=EMA_, when=close_long_entries)
    strategy.cancel(id="Long", when=cancel_entries)

// Short Entry
if enableLaddering
    if ladderRungs == 2
        strategy.entry(id="Short Ladder 1", direction=strategy.short, qty=position_qty, limit=short_ladder_1_limit_price, when=short_conditions_met)
        strategy.entry(id="Short Ladder 2", direction=strategy.short, qty=position_qty, limit=short_ladder_2_limit_price, when=short_conditions_met)
    else if ladderRungs == 3
        strategy.entry(id="Short Ladder 1", direction=strategy.short, qty=position_qty, limit=short_ladder_1_limit_price, when=short_conditions_met)
        strategy.entry(id="Short Ladder 2", direction=strategy.short, qty=position_qty, limit=short_ladder_2_limit_price, when=short_conditions_met)
        strategy.entry(id="Short Ladder 3", direction=strategy.short, qty=position_qty, limit=short_ladder_3_limit_price, when=short_conditions_met)
    else if ladderRungs == 4
        strategy.entry(id="Short Ladder 1", direction=strategy.short, qty=position_qty, limit=short_ladder_1_limit_price, when=short_conditions_met)
        strategy.entry(id="Short Ladder 2", direction=strategy.short, qty=position_qty, limit=short_ladder_2_limit_price, when=short_conditions_met)
        strategy.entry(id="Short Ladder 3", direction=strategy.short, qty=position_qty, limit=short_ladder_3_limit_price, when=short_conditions_met)
        strategy.entry(id="Short Ladder 4", direction=strategy.short, qty=position_qty, limit=short_ladder_4_limit_price, when=short_conditions_met)
    
    strategy.exit(id="Close Short Ladder 1", from_entry="Short Ladder 1", stop=short_trailing_stop, limit=EMA_, when=close_short_entries)
    strategy.exit(id="Close Short Ladder 2", from_entry="Short Ladder 2", stop=short_trailing_stop, limit=EMA_, when=close_short_entries)
    strategy.exit(id="Close Short Ladder 3", from_entry="Short Ladder 3", stop=short_trailing_stop, limit=EMA_, when=close_short_entries)
    strategy.exit(id="Close Short Ladder 4", from_entry="Short Ladder 4", stop=short_trailing_stop, limit=EMA_, when=close_short_entries)
    
    strategy.cancel(id="Short Ladder 1", when=cancel_entries)
    strategy.cancel(id="Short Ladder 2", when=cancel_entries)
    strategy.cancel(id="Short Ladder 3", when=cancel_entries)
    strategy.cancel(id="Short Ladder 4", when=cancel_entries)
else
    strategy.entry(id="Short", direction=strategy.short, when=short_conditions_met)
    strategy.exit(id="Close Short", from_entry="Short", limit=EMA_, when=close_short_entries)
    strategy.cancel(id="Short", when=cancel_entries)