Стратегия обратной торговли на основе обобщенной поддержки/сопротивления

Автор:Чао Чжан, Дата: 2023-10-30 11:23:25
Тэги:

img

Обзор

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

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

  1. Определение бычьих/медвежьих факторов на основе Генерализованной поддержки/сопротивления с объемом

    • Использование моделей свечей для определения классических уровней S/R, фильтрованных по значительному объему

    • Общие S/R имеют лучший охват, чем классические модели

    • Разрыв обобщенных сигналов поддержки длинный фактор, разрыв обобщенных сигналов сопротивления короткий фактор

  2. Реверсивная торговля

    • Возьмите обратное положение, когда фактор сигнал запускается

    • Если уже на месте, уменьшить или добавить обратное положение

  3. Установление целевых уровней прибыли

    • Установка стоп-потери на основе ATR

    • Установите несколько уровней прибыли как 1R, 2R, 3R

    • Частичное получение прибыли при достижении различных целей

Преимущества

  • Зафиксировать благоприятные среднесрочные реверсии

    Прорывы S/R представляют собой сильные сигналы реверсии с некоторой надежностью, способные улавливать среднесрочные реверсии.

  • Быстрая прибыль, небольшие вычеты

    Установление стоп-лосс и множественные цели прибыли, может достичь быстрых прибылей и ограничить выводы

  • Подходит для акций с значительным институциональным капиталом и волатильностью

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

Риски

  • Попасть в ловушку на рынке с ограниченным диапазоном

    Частые выходы и повторные выходы в противоположном направлении могут привести к ударам.

  • Неисправность поддержки/сопротивления

    Общие S / R не являются абсолютно надежными, некоторые сбои существуют

  • Односторонний риск хранения

    Чистая логика переворота может упустить большие возможности тренда

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

    • Условия фактора расслабления, не обратный при каждом прорыве

    • Добавить другие фильтры, например, расхождение между ценой и объемом

    • Оптимизировать стратегию стоп-лосса для уменьшения ловушек

Руководство по улучшению

  • Оптимизация параметров S/R

    Найти более надежные факторы путем настройки обобщенных настроек S / R

  • Оптимизировать получение прибыли

    Добавьте больше уровней прибыли или используйте нефиксированные цели

  • Оптимизация стоп-лосса

    Регулировать параметры ATR или использовать предотвращение потерь для уменьшения ненужных остановок

  • Включить тенденцию и другие факторы

    Добавьте фильтры трендов, такие как скользящая средняя, чтобы избежать больших конфликтов трендов; также добавьте другие факторы, помогающие

Резюме

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


/*backtest
start: 2023-09-29 00:00:00
end: 2023-10-29 00:00:00
period: 1h
basePeriod: 15m
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/
// © DojiEmoji

//@version=5
strategy("Fractal Strat [KL] ", overlay=true, pyramiding=1, initial_capital=1000000000)
var string ENUM_LONG = "Long"
var string GROUP_ENTRY = "Entry"
var string GROUP_TSL = "Stop loss"
var string GROUP_TREND = "Trend prediction"
var string GROUP_ORDER = "Order size and Profit taking"

// backtest_timeframe_start = input.time(defval=timestamp("01 Apr 2000 13:30 +0000"), title="Backtest Start Time")
within_timeframe = true

// TSL: calculate the stop loss price. {
_multiple       = input(2.0, title="ATR Multiplier for trailing stop loss", group=GROUP_TSL)
ATR_TSL         = ta.atr(input(14, title="Length of ATR for trailing stop loss", group=GROUP_TSL, tooltip="Initial risk amount = atr(this length) x multiplier")) * _multiple
TSL_source      = low
TSL_line_color  = color.green
TSL_transp      = 100
var stop_loss_price = float(0)

var float initial_entry_p    = float(0)
var float risk_amt           = float(0)
var float initial_order_size = float(0)

if strategy.position_size == 0 or not within_timeframe
    TSL_line_color := color.black
    stop_loss_price := TSL_source - ATR_TSL
else if strategy.position_size > 0
    stop_loss_price := math.max(stop_loss_price, TSL_source - ATR_TSL)
    TSL_transp := 0

plot(stop_loss_price, color=color.new(TSL_line_color, TSL_transp))
// } end of "TSL" block


// Order size and profit taking {
pcnt_alloc = input.int(5, title="Allocation (%) of portfolio into this security", tooltip="Size of positions is based on this % of undrawn capital. This is fixed throughout the backtest period.", minval=0, maxval=100, group=GROUP_ORDER) / 100

// Taking profits at user defined target levels relative to risked amount (i.e 1R, 2R, 3R)
var bool  tp_mode = input(true, title="Take profit and different levels", group=GROUP_ORDER)
var float FIRST_LVL_PROFIT = input.float(1, title="First level profit", tooltip="Relative to risk. Example: entry at $10 and inital stop loss at $9. Taking first level profit at 1R means taking profits at $11", group=GROUP_ORDER)
var float SECOND_LVL_PROFIT = input.float(2, title="Second level profit", tooltip="Relative to risk. Example: entry at $10 and inital stop loss at $9. Taking second level profit at 2R means taking profits at $12", group=GROUP_ORDER)
var float THIRD_LVL_PROFIT = input.float(3, title="Third level profit", tooltip="Relative to risk. Example: entry at $10 and inital stop loss at $9. Taking third level profit at 3R means taking profits at $13", group=GROUP_ORDER)

// }

// Fractals {
// Modified from synapticEx's implementation: https://www.tradingview.com/script/cDCNneRP-Fractal-Support-Resistance-Fixed-Volume-2/

rel_vol_len = 6 // Relative volume is used; the middle candle has to have volume above the average (say sma over prior 6 bars)
rel_vol = ta.sma(volume, rel_vol_len)
_up = high[3]>high[4] and high[4]>high[5] and high[2]<high[3] and high[1]<high[2] and volume[3]>rel_vol[3]
_down = low[3]<low[4] and low[4]<low[5] and low[2]>low[3] and low[1]>low[2] and volume[3]>rel_vol[3]

fractal_resistance = high[3], fractal_support = low[3]   // initialize

fractal_resistance :=  _up ? high[3] : fractal_resistance[1]
fractal_support := _down ? low[3] : fractal_support[1]

plot(fractal_resistance, "fractal_resistance", color=color.new(color.red,50), linewidth=2, style=plot.style_cross, offset =-3, join=false)
plot(fractal_support, "fractal_support", color=color.new(color.lime,50), linewidth=2, style=plot.style_cross, offset=-3, join=false)
// }

// ATR diversion test {
// Hypothesis testing (2-tailed):
//
// Null hypothesis (H0) and Alternative hypothesis (Ha):
//     H0 : atr_fast equals atr_slow
//     Ha : atr_fast not equals to atr_slow; implies atr_fast is either too low or too high
len_fast    = input(5,title="Length of ATR (fast) for diversion test", group=GROUP_ENTRY)
atr_fast    = ta.atr(len_fast)
atr_slow    = ta.atr(input(50,title="Length of ATR (slow) for diversion test", group=GROUP_ENTRY, tooltip="This needs to be larger than Fast"))

// Calculate test statistic (test_stat)
std_error   = ta.stdev(ta.tr, len_fast) / math.pow(len_fast, 0.5)
test_stat = (atr_fast - atr_slow) / std_error

// Compare test_stat against critical value defined by user in settings
//critical_value = input.float(1.645,title="Critical value", tooltip="Strategy uses 2-tailed test to compare atr_fast vs atr_slow. Null hypothesis (H0) is that both should equal. Based on the computed test statistic value, if absolute value of it is +/- this critical value, then H0 will be rejected.", group=GROUP_ENTRY)
conf_interval = input.string(title="Confidence Interval", defval="95%", options=["90%","95%","99%"], tooltip="Critical values of 1.645, 1.96, 2.58, for CI=90%/95%/99%, respectively; Under 2-tailed test to compare atr_fast vs atr_slow. Null hypothesis (H0) is that both should equal. Based on the computed test statistic value, if absolute value of it is +/- critical value, then H0 will be rejected.")
critical_value = conf_interval == "90%" ? 1.645 : conf_interval == "95%" ? 1.96 : 2.58
reject_H0_lefttail = test_stat < -critical_value
reject_H0_righttail = test_stat > critical_value

// } end of "ATR diversion test" block

// Entry Signals
entry_signal_long = close >= fractal_support and reject_H0_lefttail

// MAIN {
// Update the stop limit if strategy holds a position.
if strategy.position_size > 0
    strategy.exit(ENUM_LONG, comment="SL", stop=stop_loss_price)

// Entry
if within_timeframe and entry_signal_long and strategy.position_size == 0
    initial_entry_p := close
    risk_amt := ATR_TSL
    initial_order_size := math.floor(pcnt_alloc * strategy.equity / close)
    strategy.entry(ENUM_LONG, strategy.long, qty=initial_order_size)

var int TP_taken_count = 0
if tp_mode and close > strategy.position_avg_price
    if close >= initial_entry_p + THIRD_LVL_PROFIT * risk_amt and TP_taken_count == 2
        strategy.close(ENUM_LONG, comment="TP Lvl3", qty=math.floor(initial_order_size / 3))
        TP_taken_count := TP_taken_count + 1
    else if close >= initial_entry_p + SECOND_LVL_PROFIT * risk_amt and TP_taken_count == 1
        strategy.close(ENUM_LONG, comment="TP Lvl2", qty=math.floor(initial_order_size / 3))
        TP_taken_count := TP_taken_count + 1
    else if close >= initial_entry_p + FIRST_LVL_PROFIT * risk_amt and TP_taken_count == 0
        strategy.close(ENUM_LONG, comment="TP Lvl1", qty=math.floor(initial_order_size / 3))
        TP_taken_count := TP_taken_count + 1
    
// Alerts
_atr = ta.atr(14)
alert_helper(msg) =>
    prefix = "[" + syminfo.root + "] "
    suffix = "(P=" + str.tostring(close, "#.##") + "; atr=" + str.tostring(_atr, "#.##") + ")"
    alert(str.tostring(prefix) + str.tostring(msg) + str.tostring(suffix), alert.freq_once_per_bar)

if strategy.position_size > 0 and ta.change(strategy.position_size)
    if strategy.position_size > strategy.position_size[1]
        alert_helper("BUY")
    else if strategy.position_size < strategy.position_size[1]
        alert_helper("SELL")

// Clean up - set the variables back to default values once no longer in use
if ta.change(strategy.position_size) and strategy.position_size == 0
    TP_taken_count := 0
    initial_entry_p := float(0)
    risk_amt := float(0)
    initial_order_size := float(0)
    stop_loss_price := float(0)
// } end of MAIN block


Больше