Эта стратегия торгует ценовым прорывом полос Боллинджера. Она направлена на захват трендовых возможностей от прорывов канала.
Логика стратегии:
Вычислять полосы Боллинджера с скользящей средней за n периодов как полосы средней линии и волатильности выше и ниже.
Включите короткий, когда цена падает ниже нижней полосы. Включите длинный, когда выходит выше верхней полосы.
Установите остановки за пределами противоположной полосы для контроля риска.
Регулируйте ширину полосы на основе максимального снижения для оптимизации параметров.
Добавьте фильтр громкости, чтобы избежать ложных прорывов.
Преимущества:
Разрыв полосы эффективно определяет повороты тренда.
Оптимизация параметров Боллинджера проста и практична.
Фильтр объема улучшает качество, избегая фальсификаций.
Риски:
Отстающие группы могут пропустить лучшее время входа.
Пост-прорыв отмены являются общими, требуя разумные остановки.
Поиск низкочастотных сделок в оптимизации может упустить возможности.
В общем, это типичная стратегия выхода из канала, торгуя перерывами Боллинджера.
/*backtest start: 2023-08-12 00:00:00 end: 2023-09-11 00:00:00 period: 2h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=2 // strategy("ChannelBreakOutStrategyV2.1", commission_type = "percent", commission_value = 0.1, calc_on_order_fills = true, overlay=true) length = input(title="Length", minval=1, maxval=1000, defval=40) maxR = input(title = "R", minval = 1.0, maxval = 10, defval = 3, step = 0.1) adoptR = input(title = "Auto Adjust R", defval = false) stepR = input(title = "Step in R", minval = 0.01, maxval = 0.1, step = 0.01, defval = 0.02) baseYear = input(title = "Base Year", minval = 2000, maxval = 2016, defval = 2000) volumeTh = input(title = "Volume Threadhold", minval = 100.0, maxval = 200, defval = 120, step = 5) hasLong = input(title = "Include Long", defval = true) hasShort = input(title = "Include Short", defval = true) usePositionSizing = input(title = "Enable Position Sizing", defval = true) getTrailStop(val, current) => s = val > 1.6 ? 0.8 : val >= 1.4 ? 0.85 : val >= 1.3 ? 0.9 : 0.93 s * current upBound = highest(high, length) downBound = lowest(low, length) hasVol = (volume / sma(volume, length) * 100 >= volumeTh) ? 1 : 0 hasPos = strategy.position_size != 0 ? 1 : 0 trailstop = atr(length) * 3 ptvalue = syminfo.pointvalue equity = strategy.openprofit > 0 ? strategy.equity - strategy.openprofit : strategy.equity curR = adoptR == false ? maxR : n == 0 ? maxR : hasPos == 1 ? curR[1] : (rising(equity,1) > 0? curR[1] + stepR : falling(equity, 1) > 0 ? curR[1] <= 2.0 ? 2.0 : curR[1] - stepR : curR[1]) contracts = usePositionSizing == false ? 20 : floor(equity / 100 * curR / (trailstop * ptvalue)) realbuystop = close - trailstop realsellstop = close + trailstop isPFst = (hasPos[1] == 0 and hasPos == 1) ? 1 : 0 isPOn = (hasPos[1] + hasPos == 2) ? 1 : 0 largestR = hasPos == 0 or isPFst == 1 ? -1 : nz(largestR[1]) < close ? close : largestR[1] pctRise = largestR / strategy.position_avg_price rbs = strategy.position_size <= 0 ? realbuystop : isPFst ? strategy.position_avg_price - trailstop : pctRise >= 1.3 ? getTrailStop(pctRise, largestR) : (isPOn and realbuystop > rbs[1] and close > close[1]) ? realbuystop : rbs[1] rss = strategy.position_size >= 0 ? realsellstop : isPFst ? strategy.position_avg_price + trailstop : (isPOn and realsellstop < rss[1] and close < close[1]) ? realsellstop : rss[1] isStart = na(rbs) or na(rss) ? 0 : 1 buyARun = close - open > 0 ? 0 : open - close sellARun = open - close > 0 ? 0 : close - open if (strategy.position_size > 0 and buyARun >= trailstop / 3 * 2 and pctRise < 1.3) strategy.close("buy") strategy.cancel("exit") if (strategy.position_size < 0 and sellARun >= trailstop / 3 * 2) strategy.close("sell") strategy.cancel("exit") strategy.cancel("buy") strategy.cancel("sell") conLong = hasLong == true and hasPos == 0 and year > baseYear and (isStart + hasVol) == 2 strategy.order("buy", strategy.long, qty = contracts, stop=upBound + syminfo.mintick * 5, comment="BUY", when = conLong) if (rbs > high) strategy.close("buy") strategy.exit("exit", "buy", stop = rbs, when = hasPos == 1 and isStart == 1) conShort = hasShort == true and hasPos == 0 and year > baseYear and (isStart + hasVol) == 2 strategy.order("sell", strategy.short, qty = contracts, stop=downBound - syminfo.mintick * 5, comment="SELL", when = conShort) if (rss < low) strategy.close("sell") strategy.exit("exit", "sell", stop = rss, when = hasPos == 1 and isStart == 1) plot(series = rbs, color=blue) plot(series = realbuystop, color=green) plot(series = rss, color=red) plot(series = realsellstop, color=yellow)