Адаптивная стратегия получения прибыли и остановки убытков на основе двойных временных рамок и индикаторов импульса

Автор:Чао Чжан, Дата: 2023-11-23 17:57:52
Тэги:

img

Обзор

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

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

  1. Основной временной рамок использует индикатор линейной регрессии Squeeze Momentum (SQM) для определения тренда. Вторичный временной рамок использует комбинацию EMA на индикаторе SQM для фильтрации ложных сигналов.

  2. Когда основной график SQM выходит вверх, а вторичный график SQM также поднимается, принимается длинная позиция.

  3. После выхода на рынок начальные уровни получения прибыли и остановки потери устанавливаются на основе входных параметров. Когда цена достигает уровня получения прибыли, обновляются уровни получения прибыли и остановки потери. В частности, уровень получения прибыли постепенно увеличивается, а уровень остановки потери ужесточается, достигая постепенного получения прибыли.

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

  1. Двойные временные рамки фильтруют ложные сигналы и обеспечивают точность.

  2. Индикатор SQM определяет направление тренда, избегая шума рынка.

  3. Адаптивный механизм получения прибыли и остановки убытков максимально блокирует прибыль и эффективно контролирует риск.

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

  1. Неправильные настройки параметров SQM могут пропустить поворотные моменты тренда, что приведет к потерям.

  2. Неправильные вторичные временные рамки могут не эффективно фильтровать шум, вызывая ошибочные сделки.

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

Возможности для расширения

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

  2. Чтобы найти наилучший эффект фильтрации шума, следует испытать различные вторичные периоды времени.

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

Резюме

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


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

//@version=4
strategy("SQZ Multiframe Strategy", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=10)
fast_ema_len = input(11, minval=5, title="Fast EMA")
slow_ema_len = input(34, minval=20, title="Slow EMA")
sqm_lengthKC = input(20, title="SQM KC Length")
kauf_period = input(20, title="Kauf Period")
kauf_mult = input(2,title="Kauf Mult factor")
min_profit_sl = input(5.0, minval=1, maxval=100, title="Min profit to start moving SL [%]")
longest_sl = input(10, minval=1, maxval=100, title="Maximum possible of SL [%]")
sl_step = input(0.5, minval=0.0, maxval=1.0, title="Take profit factor")
// ADMF
CMF_length = input(11, minval=1, title="CMF length") // EMA27 = SMMA/RMA14 ~ lunar month
show_plots = input(true, title="Show plots")

lower_resolution = timeframe.period=='1'?'5':timeframe.period=='5'?'15':timeframe.period=='15'?'30':timeframe.period=='30'?'60':timeframe.period=='60'?'240':timeframe.period=='240'?'D':timeframe.period=='D'?'W':'M'
higher_resolution = timeframe.period=='5'?'1':timeframe.period=='15'?'5':timeframe.period=='30'?'15':timeframe.period=='60'?'30':timeframe.period=='240'?'60':timeframe.period=='D'?'240':timeframe.period=='W'?'D':'W'

// Calculate Squeeze Momentum
sqm_val = linreg(close - avg(avg(highest(high, sqm_lengthKC), lowest(low, sqm_lengthKC)),sma(close,sqm_lengthKC)), sqm_lengthKC,0)
sqm_val_high = security(syminfo.tickerid, higher_resolution, linreg(close - avg(avg(highest(high, sqm_lengthKC), lowest(low, sqm_lengthKC)),sma(close,sqm_lengthKC)), sqm_lengthKC,0), lookahead=barmerge.lookahead_on)
sqm_val_low = security(syminfo.tickerid, lower_resolution, linreg(close - avg(avg(highest(high, sqm_lengthKC), lowest(low, sqm_lengthKC)),sma(close,sqm_lengthKC)), sqm_lengthKC,0), gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_on)

// Emas
high_close = security(syminfo.tickerid, higher_resolution, close, lookahead=barmerge.lookahead_on)
high_fast_ema = security(syminfo.tickerid, higher_resolution, ema(close, fast_ema_len), lookahead=barmerge.lookahead_on)
high_slow_ema = security(syminfo.tickerid, higher_resolution, ema(close, slow_ema_len), lookahead=barmerge.lookahead_on)
//low_fast_ema = security(syminfo.tickerid, lower_resolution, ema(close, fast_ema_len), lookahead=barmerge.lookahead_on)
//low_slow_ema = security(syminfo.tickerid, lower_resolution, ema(close, slow_ema_len), lookahead=barmerge.lookahead_on)

// CMF 
ad = close==high and close==low or high==low ? 0 : ((2*close-low-high)/(high-low))*volume
money_flow = sum(ad, CMF_length) / sum(volume, CMF_length)


// Entry conditions
low_condition_long  = (sqm_val_low > sqm_val_low[1])
low_condition_short = (sqm_val_low < sqm_val_low[1])
money_flow_min = (money_flow[4] > money_flow[3]) and (money_flow[3] > money_flow[2]) and (money_flow[2] < money_flow[1])  and (money_flow[1] < money_flow)
money_flow_max = (money_flow[4] < money_flow[3]) and (money_flow[3] < money_flow[2]) and (money_flow[2] > money_flow[1])  and (money_flow[1] > money_flow)
condition_long = ((sqm_val > sqm_val[1]))  and (money_flow_min or money_flow_min[1] or money_flow_min[2] or money_flow_min[3]) and lowest(sqm_val, 5) < 0
condition_short = ((sqm_val < sqm_val[1])) and (money_flow_max or money_flow_max[1] or money_flow_max[2] or money_flow_max[3]) and highest(sqm_val, 5) > 0
high_condition_long =  true//high_close > high_fast_ema and high_close > high_slow_ema //(high_fast_ema > high_slow_ema) //and (sqm_val_low > sqm_val_low[1])
high_condition_short = true//high_close < high_fast_ema and high_close < high_slow_ema//(high_fast_ema < high_slow_ema) //and (sqm_val_low < sqm_val_low[1])
enter_long = low_condition_long and condition_long and high_condition_long
enter_short = low_condition_short and condition_short and high_condition_short

// Stop conditions
var current_target_price = 0.0
var current_sl_price = 0.0 // Price limit to take profit
var current_target_per = 0.0
var current_profit_per = 0.0

set_targets(isLong, min_profit, current_target_per, current_profit_per) =>
    target = 0.0
    sl = 0.0
    if isLong
        target := close * (1.0 + current_target_per)
        sl := close * (1.0 - (longest_sl/100.0)) // Longest SL
    else
        target := close * (1.0 - current_target_per)
        sl := close * (1.0 + (longest_sl/100.0)) // Longest SL
    [target, sl]

target_reached(isLong, min_profit, current_target_per, current_profit_per) =>
    target = 0.0
    sl = 0.0
    profit_per = 0.0
    target_per = 0.0
    if current_profit_per == 0
        profit_per := (min_profit*sl_step) / 100.0
    else
        profit_per := current_profit_per +  ((min_profit*sl_step) / 100.0)
    target_per := current_target_per + (min_profit / 100.0) 
    if isLong
        target := strategy.position_avg_price * (1.0 + target_per)
        sl := strategy.position_avg_price * (1.0 + profit_per)
    else
        target := strategy.position_avg_price * (1.0 - target_per)
        sl := strategy.position_avg_price * (1.0 - profit_per)
    [target, sl, profit_per, target_per]

hl_diff = sma(high - low, kauf_period)
stop_condition_long = 0.0
new_stop_condition_long = low - (hl_diff * kauf_mult)
if (strategy.position_size > 0) 
    if (close > current_target_price)
        [target, sl, profit_per, target_per] = target_reached(true, min_profit_sl, current_target_per, current_profit_per)
        current_target_price := target
        current_sl_price := sl
        current_profit_per := profit_per
        current_target_per := target_per
        
        
    stop_condition_long := max(stop_condition_long[1], current_sl_price)
else
    stop_condition_long := new_stop_condition_long
stop_condition_short = 99999999.9
new_stop_condition_short = high + (hl_diff * kauf_mult)
if (strategy.position_size < 0) 
    if (close < current_target_price)
        [target, sl, profit_per, target_per] = target_reached(false, min_profit_sl, current_target_per, current_profit_per)
        current_target_price := target
        current_sl_price := sl
        current_profit_per := profit_per
        current_target_per := target_per
    stop_condition_short := min(stop_condition_short[1], current_sl_price)
else
    stop_condition_short := new_stop_condition_short
    

// Submit entry orders
if (enter_long and (strategy.position_size <= 0))
    if (strategy.position_size < 0)
        strategy.close(id="SHORT")
    current_target_per := (min_profit_sl / 100.0)
    current_profit_per := 0.0
    [target, sl] = set_targets(true, min_profit_sl, current_target_per, current_profit_per)
    current_target_price := target
    current_sl_price := sl
    strategy.entry(id="LONG", long=true)
    // if show_plots
    //     label.new(bar_index, high, text=tostring("LONG\nSL: ") + tostring(stop_condition_long), style=label.style_labeldown, color=color.green)

if (enter_short and (strategy.position_size >= 0))
    if (strategy.position_size > 0)
        strategy.close(id="LONG")
    current_target_per := (min_profit_sl / 100.0)
    current_profit_per := 0.0
    [target, sl] = set_targets(false, min_profit_sl, current_target_per, current_profit_per)
    current_target_price := target
    current_sl_price := sl
    strategy.entry(id="SHORT", long=false)
    // if show_plots
        // label.new(bar_index, high, text=tostring("SHORT\nSL: ") + tostring(stop_condition_short), style=label.style_labeldown, color=color.red)
    
if (strategy.position_size > 0)
    strategy.exit(id="EXIT LONG", stop=stop_condition_long)
    
if (strategy.position_size < 0)
    strategy.exit(id="EXIT SHORT", stop=stop_condition_short)
    
// Plot anchor trend
plotshape(low_condition_long, style=shape.triangleup,
                 location=location.abovebar, color=color.green)
plotshape(low_condition_short, style=shape.triangledown,
                 location=location.abovebar, color=color.red)
                 
plotshape(condition_long, style=shape.triangleup,
                 location=location.belowbar, color=color.green)
plotshape(condition_short, style=shape.triangledown,
                 location=location.belowbar, color=color.red)
 
//plotshape((close < profit_target_short) ? profit_target_short : na, style=shape.triangledown,
//                 location=location.belowbar, color=color.yellow)                
plotshape(enter_long, style=shape.triangleup,
                 location=location.bottom, color=color.green)
plotshape(enter_short, style=shape.triangledown,
                 location=location.bottom, color=color.red)
                 
// Plot emas
plot(ema(close, 20), color=color.blue, title="20 EMA")
plot(ema(close, 50), color=color.orange, title="50 EMA")
plot(sma(close, 200), color=color.red, title="MA 200")

// Plot stop loss values for confirmation
plot(series=(strategy.position_size > 0) and show_plots ? stop_condition_long : na,
     color=color.green, style=plot.style_linebr,
     title="Long Stop")
plot(series=(strategy.position_size < 0) and show_plots ? stop_condition_short : na,
     color=color.green, style=plot.style_linebr,
     title="Short Stop")
plot(series=(strategy.position_size < 0) and show_plots ? current_target_price : na,
     color=color.yellow, style=plot.style_linebr,
     title="Short TP")
plot(series=(strategy.position_size > 0) and show_plots ? current_target_price : na,
     color=color.yellow, style=plot.style_linebr,
     title="Long TP")
//plot(series=(strategy.position_size < 0) ? profit_sl_short : na,
//     color=color.gray, style=plot.style_linebr,
//     title="Short Stop")



Больше