추세에 따른 전략 Hull MA와 STC 지표에 기초

저자:차오장, 날짜: 2023-10-07 10:20:06
태그:

전반적인 설명

이 전략은 트렌드를 정확하게 추적하기 위해 Hull MA 매끄러운 이동 평균과 STC 지표를 결합합니다. Hull MA 라인이 녹색으로 변하고 STC 지표가 빨간색에서 녹색으로 변하고 25 이하일 때 길어집니다. Hull MA 라인이 빨간색으로 변하고 STC 지표가 녹색에서 빨간색으로 변하고 75 이상일 때 짧아집니다. 한편, 전략은 트렌드 신호를 더 확인하기 위해 UT Bot 지표를 통합합니다.

전략 논리

이 전략은 가격 트렌드 방향을 결정하기 위해 Hull MA 매끄러운 이동 평균선을 사용합니다. Hull MA 라인의 녹색에서 빨간색 또는 반대로 색의 변화는 트렌드 반전을 판단하는 데 사용될 수 있습니다.

STC 지표는 MACD 지표와 유사하다. 지표 선은 상승/하락 반전을 결정하는 데 사용될 수 있다. 지표 선이 밑에서 25을 넘으면 구매 신호이며, 위에서 75을 넘으면 판매 신호이다.

Hull MA와 STC 지표를 결합함으로써 두 지표가 동시에 구매/판매 신호를 생성하면 거래 진입에 대한 트렌드 전환을 나타냅니다.

또한, 전략은 또한 트렌드 신호를 추가로 확인하기 위해 ATR에 기반한 동적 스톱 로스 라인과 가격의 관계를 기반으로 상승/하락 편향을 출력하는 UT Bot 지표를 포함합니다.

구체적으로, 전략 논리는 다음과 같습니다.

  1. 헬스 MA 라인이 녹색으로 변하고 STC 표시 라인이 빨간색에서 녹색으로 변하면 25 이하로, 그것은 긴 신호입니다.

  2. 헬스 MA 라인이 빨간색으로 변하고 STC 표시 라인이 녹색에서 빨간색으로 변하면 75 이상이면 짧은 신호입니다.

  3. 위의 기준이 충족되면, 긴 포지션을 열기 위해 UT Bot가 상승세를 나타냅니다.

  4. 위의 기준이 충족되면, UT Bot가 상장 시장을 개설하기 위해 하향 시장을 보여줍니다.

이점 분석

이 전략은 세 가지 지표를 결합하여 트렌드를 결정하여 신호의 신뢰성을 향상시킬 수 있습니다.

매끄러운 Hull MA 곡선은 트렌드 방향을 정확하게 결정하고 윙사브를 피할 수 있습니다. STC 지표는 트렌드 반전 지점을 캡처하여 전략의 실시간 성능을 향상시킬 수 있습니다. UT Bot는 잘못된 신호를 추가로 필터링 할 수 있습니다.

이 3가지 지표의 조합은 안정성을 높이는 동시에 정확한 경향 추적을 가능하게 합니다. 이것이 전략의 가장 큰 강점입니다.

위험 분석

전략의 주요 위험:

  1. STC 지표는 잘못된 신호를 생성하여 불필요한 입력으로 이어집니다.

  2. 잘못된 Hull MA 매개 변수 설정도 추세를 잘못 판단할 수 있습니다.

  3. 3가지 지표의 부적절한 조합은 서로 간섭할 수 있습니다.

위험은 Hull MA 매개 변수를 최적화하고 STC 매개 변수 혼합을 조정하고 UT Bot 매개 변수를 테스트함으로써 완화 될 수 있습니다.

또한, 스톱 로스는 단일 거래 손실을 제어하는 데 사용될 수 있습니다. 더 많은 지표는 잘못된 신호 비율을 줄이기 위해 콤보 검증을 위해 도입 될 수 있습니다.

최적화 방향

이 전략은 다음과 같은 측면에서 최적화 될 수 있습니다.

  1. Hull MA 매개 변수를 최적화하여 유연한 곡선이 트렌드에 더 잘 맞도록 최적의 길이를 찾습니다.

  2. STC 매개 변수 믹스를 조정해서 역전을 감지하기 위해 더 정확한 조합을 찾습니다.

  3. 트렌드 판단의 정확성을 높이기 위해 UT Bot 매개 변수를 최적화합니다.

  4. 신호 신뢰성을 더욱 향상시키기 위해 콤보 검증을 위한 다른 지표를 도입하는 시험

  5. 스톱 로스 전략을 최적화하여 수익을 유지하면서 허용 가능한 범위 내에서 단일 거래 손실을 제어합니다.

  6. 더 높은 수익/위험 비율을 위해 포지션 사이징 전략을 최적화하십시오.

결론

이 전략은 헐 MA, STC 및 UT Bot 지표를 결합하여 트렌드를 정확하게 추적합니다. 이는 잘못된 판단 위험을 줄이고 안정성을 향상시키는 지표 다양성의 장점이 있습니다. 전략은 매개 변수를 지속적으로 최적화하고 다른 지표를 도입하고 스톱 로스 전략을 완성함으로써 더욱 향상 될 수 있습니다.


/*backtest
start: 2023-09-06 00:00:00
end: 2023-10-06 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/
// © myn

//@version=5
strategy('Strategy Myth-Busting #1 - UT Bot+STC+Hull+ [MYN]', max_bars_back=5000, overlay=true, pyramiding=0, initial_capital=20000, currency='USD', default_qty_type=strategy.percent_of_equity, default_qty_value=100.0, commission_value=0.075)




/////////////////////////////////////
//* Put your strategy logic below *//
/////////////////////////////////////
//2oVDibie_bk

/// UT Bot Alerts by QuantNomad - https://www.tradingview.com/script/n8ss8BID-UT-Bot-Alerts/
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
//study(title="UT Bot Alerts", overlay = true)

// Inputs
a = input(2, title='Key Vaule. \'This changes the sensitivity\'')
c = input(6, title='ATR Period')
h = input(false, title='Signals from Heikin Ashi Candles')

xATR = ta.atr(c)
nLoss = a * xATR

src = h ? request.security(ticker.heikinashi(syminfo.tickerid), timeframe.period, close, lookahead=barmerge.lookahead_off) : close

xATRTrailingStop = 0.0
iff_1 = src > nz(xATRTrailingStop[1], 0) ? src - nLoss : src + nLoss
iff_2 = src < nz(xATRTrailingStop[1], 0) and src[1] < nz(xATRTrailingStop[1], 0) ? math.min(nz(xATRTrailingStop[1]), src + nLoss) : iff_1
xATRTrailingStop := src > nz(xATRTrailingStop[1], 0) and src[1] > nz(xATRTrailingStop[1], 0) ? math.max(nz(xATRTrailingStop[1]), src - nLoss) : iff_2

pos = 0
iff_3 = src[1] > nz(xATRTrailingStop[1], 0) and src < nz(xATRTrailingStop[1], 0) ? -1 : nz(pos[1], 0)
pos := src[1] < nz(xATRTrailingStop[1], 0) and src > nz(xATRTrailingStop[1], 0) ? 1 : iff_3

xcolor = pos == -1 ? color.red : pos == 1 ? color.green : color.blue

ema = ta.ema(src, 1)
above = ta.crossover(ema, xATRTrailingStop)
below = ta.crossover(xATRTrailingStop, ema)

buy = src > xATRTrailingStop and above
sell = src < xATRTrailingStop and below

barbuy = src > xATRTrailingStop
barsell = src < xATRTrailingStop

//plotshape(buy,  title = "Buy",  text = 'Buy',  style = shape.labelup,   location = location.belowbar, color= color.green, textcolor = color.white, transp = 0, size = size.tiny)
//plotshape(sell, title = "Sell", text = 'Sell', style = shape.labeldown, location = location.abovebar, color= color.red,   textcolor = color.white, transp = 0, size = size.tiny)

barcolor(barbuy ? color.green : na)
barcolor(barsell ? color.red : na)

alertcondition(buy, 'UT Long', 'UT Long')
alertcondition(sell, 'UT Short', 'UT Short')

///////////////////////////////////////////////
//======[ Position Check (long/short) ]======//
///////////////////////////////////////////////

last_longCondition = float(na)
last_shortCondition = float(na)
last_longCondition := buy ? time : nz(last_longCondition[1])
last_shortCondition := sell ? time : nz(last_shortCondition[1])

in_longCondition = last_longCondition > last_shortCondition
in_shortCondition = last_shortCondition > last_longCondition


UTBotBuyZone = in_longCondition
UTBotSellZone = in_shortCondition



/// STC Indicator - A Better MACD [SHK] By shayankm - https://www.tradingview.com/script/WhRRThMI-STC-Indicator-A-Better-MACD-SHK/

// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
//[SHK] STC colored indicator
//https://www.tradingview.com/u/shayankm/

//indicator(title='[SHK] Schaff Trend Cycle (STC)', shorttitle='STC', overlay=false)
STCDivider = input(false, '░░░░░░░░░░░░░░░░░░░░░░░░░')
EEEEEE = input(80, 'Length')
BBBB = input(27, 'FastLength')
BBBBB = input(50, 'SlowLength')

AAAA(BBB, BBBB, BBBBB) =>
    fastMA = ta.ema(BBB, BBBB)
    slowMA = ta.ema(BBB, BBBBB)
    AAAA = fastMA - slowMA
    AAAA

AAAAA(EEEEEE, BBBB, BBBBB) =>
    AAA = input(0.5)
    var CCCCC = 0.0
    var DDD = 0.0
    var DDDDDD = 0.0
    var EEEEE = 0.0
    BBBBBB = AAAA(close, BBBB, BBBBB)
    CCC = ta.lowest(BBBBBB, EEEEEE)
    CCCC = ta.highest(BBBBBB, EEEEEE) - CCC
    CCCCC := CCCC > 0 ? (BBBBBB - CCC) / CCCC * 100 : nz(CCCCC[1])
    DDD := na(DDD[1]) ? CCCCC : DDD[1] + AAA * (CCCCC - DDD[1])
    DDDD = ta.lowest(DDD, EEEEEE)
    DDDDD = ta.highest(DDD, EEEEEE) - DDDD
    DDDDDD := DDDDD > 0 ? (DDD - DDDD) / DDDDD * 100 : nz(DDDDDD[1])
    EEEEE := na(EEEEE[1]) ? DDDDDD : EEEEE[1] + AAA * (DDDDDD - EEEEE[1])
    EEEEE

mAAAAA = AAAAA(EEEEEE, BBBB, BBBBB)
mColor = mAAAAA > mAAAAA[1] ? color.new(color.green, 20) : color.new(color.red, 20)



if mAAAAA[3] <= mAAAAA[2] and mAAAAA[2] > mAAAAA[1] and mAAAAA > 75
    alert('Red', alert.freq_once_per_bar)
if mAAAAA[3] >= mAAAAA[2] and mAAAAA[2] < mAAAAA[1] and mAAAAA < 25
    alert('Green', alert.freq_once_per_bar)


//plot(mAAAAA, color=mColor, title='STC', linewidth=2)

//ul = plot(25, color=color.new(color.white, 0 ))
//ll = plot(75, color=color.new(color.purple, 0))
//fill(ul, ll, color=color.new(color.gray, 96))

STCGreenAndBelow25AndRising = mAAAAA > mAAAAA[1] and mAAAAA < 25
STCRedAndAndAbove75AndFalling = mAAAAA < mAAAAA[1] and mAAAAA > 75

/// Hull Suite by InSilico
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
//Basic Hull Ma Pack tinkered by InSilico - https://www.tradingview.com/script/hg92pFwS-Hull-Suite/
//study("Hull Suite by InSilico", overlay=true)

HullDivider = input(false, '░░░░░░░░░░░░░░░░░░░░░░░░░')
//INPUT
srcHull = input(close, title='Source')
modeSwitch = input.string('Hma', title='Hull Variation', options=['Hma', 'Thma', 'Ehma'])
length = input(55, title='Length(180-200 for floating S/R , 55 for swing entry)')
lengthMult = input(1.0, title='Length multiplier (Used to view higher timeframes with straight band)')

useHtf = input(false, title='Show Hull MA from X timeframe? (good for scalping)')
htf = input.timeframe('240', title='Higher timeframe')

switchColor = input(true, 'Color Hull according to trend?')
candleCol = input(false, title='Color candles based on Hull\'s Trend?')
visualSwitch = input(true, title='Show as a Band?')
thicknesSwitch = input(1, title='Line Thickness')
transpSwitch = input.int(40, title='Band Transparency', step=5)

//FUNCTIONS
//HMA
HMA(_src, _length) =>
    ta.wma(2 * ta.wma(_src, _length / 2) - ta.wma(_src, _length), math.round(math.sqrt(_length)))
//EHMA    
EHMA(_src, _length) =>
    ta.ema(2 * ta.ema(_src, _length / 2) - ta.ema(_src, _length), math.round(math.sqrt(_length)))
//THMA    
THMA(_src, _length) =>
    ta.wma(ta.wma(_src, _length / 3) * 3 - ta.wma(_src, _length / 2) - ta.wma(_src, _length), _length)

//SWITCH
Mode(modeSwitch, src, len) =>
    modeSwitch == 'Hma' ? HMA(src, len) : modeSwitch == 'Ehma' ? EHMA(src, len) : modeSwitch == 'Thma' ? THMA(src, len / 2) : na

//OUT
_hull = Mode(modeSwitch, srcHull, int(length * lengthMult))
HULL = useHtf ? request.security(syminfo.ticker, htf, _hull) : _hull
MHULL = HULL[0]
SHULL = HULL[2]

//COLOR
hullColor = switchColor ? HULL > HULL[2] ? #00ff00 : #ff0000 : #ff9800

//PLOT
///< Frame
Fi1 = plot(MHULL, title='MHULL', color=hullColor, linewidth=thicknesSwitch, transp=50)
Fi2 = plot(visualSwitch ? SHULL : na, title='SHULL', color=hullColor, linewidth=thicknesSwitch, transp=50)
alertcondition(ta.crossover(MHULL, SHULL), title='Hull trending up.', message='Hull trending up.')
alertcondition(ta.crossover(SHULL, MHULL), title='Hull trending down.', message='Hull trending down.')
///< Ending Filler
fill(Fi1, Fi2, title='Band Filler', color=hullColor, transp=transpSwitch)
///BARCOLOR
barcolor(color=candleCol ? switchColor ? hullColor : na : na)

HullGreen = hullColor == #00ff00
HullRed = hullColor == #ff0000

//////////////////////////////////////
//* Put your strategy rules below *//
/////////////////////////////////////



longCondition = STCGreenAndBelow25AndRising and HullGreen and UTBotBuyZone
shortCondition = STCRedAndAndAbove75AndFalling and HullRed and UTBotSellZone

//define as 0 if do not want to use
closeLongCondition = 0
closeShortCondition = 0


//░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
useStartPeriodTime = input.bool(true, 'Start', group='Date Range', inline='Start Period')
startPeriodTime = input(timestamp('1 Jan 2019'), '', group='Date Range', inline='Start Period')
useEndPeriodTime = input.bool(true, 'End', group='Date Range', inline='End Period')
endPeriodTime = input(timestamp('31 Dec 2030'), '', group='Date Range', inline='End Period')

start = useStartPeriodTime ? startPeriodTime >= time : false
end = useEndPeriodTime ? endPeriodTime <= time : false
calcPeriod = not start and not end

// Trade Direction 
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
tradeDirection = input.string('Long and Short', title='Trade Direction', options=['Long and Short', 'Long Only', 'Short Only'], group='Trade Direction')

// Percent as Points
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
per(pcnt) =>
    strategy.position_size != 0 ? math.round(pcnt / 100 * strategy.position_avg_price / syminfo.mintick) : float(na)

// Take profit 1
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
tp1 = input.float(title='Take Profit 1 - Target %', defval=100, minval=0.0, step=0.5, group='Take Profit', inline='Take Profit 1')
q1 = input.int(title='% Of Position', defval=100, minval=0, group='Take Profit', inline='Take Profit 1')

// Take profit 2
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
tp2 = input.float(title='Take Profit 2 - Target %', defval=100, minval=0.0, step=0.5, group='Take Profit', inline='Take Profit 2')
q2 = input.int(title='% Of Position', defval=100, minval=0, group='Take Profit', inline='Take Profit 2')

// Take profit 3
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
tp3 = input.float(title='Take Profit 3 - Target %', defval=100, minval=0.0, step=0.5, group='Take Profit', inline='Take Profit 3')
q3 = input.int(title='% Of Position', defval=100, minval=0, group='Take Profit', inline='Take Profit 3')

// Take profit 4
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
tp4 = input.float(title='Take Profit 4 - Target %', defval=100, minval=0.0, step=0.5, group='Take Profit')

/// Stop Loss
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
stoplossPercent = input.float(title='Stop Loss (%)', defval=15, minval=0.01, group='Stop Loss') * 0.01
slLongClose = close < strategy.position_avg_price * (1 - stoplossPercent)
slShortClose = close > strategy.position_avg_price * (1 + stoplossPercent)

/// Leverage
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
leverage = input.float(1, 'Leverage', step=.5, group='Leverage')
contracts = math.min(math.max(.000001, strategy.equity / close * leverage), 1000000000)


/// Trade State Management
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

isInLongPosition = strategy.position_size > 0
isInShortPosition = strategy.position_size < 0

/// ProfitView Alert Syntax String Generation
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

alertSyntaxPrefix = input.string(defval='PV-AccountNameHere_Strategy-Name-Here', title='Alert Syntax Prefix', group='ProfitView Alert Syntax')
alertSyntaxBase = alertSyntaxPrefix + '\n#' + str.tostring(open) + ',' + str.tostring(high) + ',' + str.tostring(low) + ',' + str.tostring(close) + ',' + str.tostring(volume) + ','


/// Trade Execution
// ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

if calcPeriod
    if longCondition and tradeDirection != 'Short Only' and isInLongPosition == false
        strategy.entry('Long', strategy.long, qty=contracts)

        alert(message=alertSyntaxBase + 'side:long', freq=alert.freq_once_per_bar_close)

    if shortCondition and tradeDirection != 'Long Only' and isInShortPosition == false
        strategy.entry('Short', strategy.short, qty=contracts)

        alert(message=alertSyntaxBase + 'side:short', freq=alert.freq_once_per_bar_close)
    //Inspired by Multiple %% profit exits example By adolgo https://www.tradingview.com/script/kHhCik9f-Multiple-profit-exits-example/
    strategy.exit('TP1', qty_percent=q1, profit=per(tp1))
    strategy.exit('TP2', qty_percent=q2, profit=per(tp2))
    strategy.exit('TP3', qty_percent=q3, profit=per(tp3))
    strategy.exit('TP4', profit=per(tp4))

    strategy.close('Long', qty_percent=100, comment='SL Long', when=slLongClose)
    strategy.close('Short', qty_percent=100, comment='SL Short', when=slShortClose)

    strategy.close_all(when=closeLongCondition or closeShortCondition, comment='Close Postion')



더 많은