
이것은 볼링거 띠와 그래프 형태 분석에 기초한 트렌드 추적 전략이다. 전략은 주로 가격이 볼링거 띠를 접촉할 때 그래프 형태 특성을 관찰하여 상하 유도선과 실체의 비율 관계와 결합하여 시장의 가능한 역전점을 판단한다. 동시에, 전략은 고정 위험 모델을 사용하여 각 거래의 위험 도로를 제어하고, 여러 시간 주기의 분석을 통해 거래의 정확성을 향상시킨다.
전략의 핵심 논리는 다음과 같은 몇 가지 핵심 요소에 기반합니다: 첫째, 20 주기의 볼링을 계산하여 가격 변동의 범위를 결정합니다. 둘째, 가격이 볼링대를 만질 때, 그래프의 위아래 가이드와 실체의 비율을 분석합니다. 비율이 설정된 임계치를 초과하면 잠재적인 역전 신호로 간주합니다. 셋째, 핵심 지원 지점과 저항 지점을 계산하여 중지 지점을 설정합니다. 마지막으로, 계좌 총액의 고정 비율 ((1%) 에 따라 거래 당 포지션을 계산하여 위험을 역동적으로 관리합니다.
이 전략은 고전적인 기술적 분석 도구와 현대적인 위험 관리 방법을 결합하여 비교적 완벽한 거래 시스템을 구축한다. 전략의 핵심 장점은 엄격한 위험 제어와 유연한 입시 메커니즘이지만 실제 응용에서 시장 환경의 변화와 신호의 신뢰성을 검증하는 데 주의를 기울여야 한다. 제안된 최적화 방향에 따라 전략은 더욱 향상될 여지가 있으며, 특히 신호 필터링과 위험 관리의 측면에 있다.
/*backtest
start: 2024-01-01 00:00:00
end: 2024-11-26 00:00:00
period: 12h
basePeriod: 12h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=5
strategy("Trade Entry Detector, based on Wick to Body Ratio when price tests Bollinger Bands", overlay=true, default_qty_type=strategy.fixed)
// Input for primary analysis time frame
timeFrame = "D" // Daily time frame
// Bollinger Band settings
length = input.int(20, title="Bollinger Band Length", minval=1)
mult = input.float(2.0, title="Standard Deviation Multiplier", minval=0.1)
source = input(close, title="Source")
// Entry ratio settings
wickToBodyRatio = input.float(1.0, title="Minimum Wick-to-Body Ratio", minval=0)
// Order Fill Timing Option
fillOption = input.string("Daily Close", title="Order Fill Timing", options=["Daily Close", "Daily Open", "HOD", "LOD"])
// Account and risk settings
accountBalance = 100000 // Account balance in dollars
riskPercentage = 1.0 // Risk percentage per trade
riskAmount = (riskPercentage / 100) * accountBalance // Fixed 1% risk amount
// Request daily data for calculations
dailyHigh = request.security(syminfo.tickerid, timeFrame, high)
dailyLow = request.security(syminfo.tickerid, timeFrame, low)
dailyClose = request.security(syminfo.tickerid, timeFrame, close)
dailyOpen = request.security(syminfo.tickerid, timeFrame, open)
// Calculate Bollinger Bands on the daily time frame
dailyBasis = request.security(syminfo.tickerid, timeFrame, ta.sma(source, length))
dailyDev = mult * request.security(syminfo.tickerid, timeFrame, ta.stdev(source, length))
dailyUpperBand = dailyBasis + dailyDev
dailyLowerBand = dailyBasis - dailyDev
// Calculate the body and wick sizes on the daily time frame
dailyBodySize = math.abs(dailyOpen - dailyClose)
dailyUpperWickSize = dailyHigh - math.max(dailyOpen, dailyClose)
dailyLowerWickSize = math.min(dailyOpen, dailyClose) - dailyLow
// Conditions for a candle with an upper wick or lower wick that touches the Bollinger Bands
upperWickCondition = (dailyUpperWickSize / dailyBodySize >= wickToBodyRatio) and (dailyHigh > dailyUpperBand)
lowerWickCondition = (dailyLowerWickSize / dailyBodySize >= wickToBodyRatio) and (dailyLow < dailyLowerBand)
// Define the swing high and swing low for stop loss placement
var float swingLow = na
var float swingHigh = na
if (ta.pivothigh(dailyHigh, 5, 5))
swingHigh := dailyHigh[5]
if (ta.pivotlow(dailyLow, 5, 5))
swingLow := dailyLow[5]
// Determine entry price based on chosen fill option
var float longEntryPrice = na
var float shortEntryPrice = na
if lowerWickCondition
longEntryPrice := fillOption == "Daily Close" ? dailyClose :
fillOption == "Daily Open" ? dailyOpen :
fillOption == "HOD" ? dailyHigh : dailyLow
if upperWickCondition
shortEntryPrice := fillOption == "Daily Close" ? dailyClose :
fillOption == "Daily Open" ? dailyOpen :
fillOption == "HOD" ? dailyHigh : dailyLow
// Execute the long and short entries with expiration
var int longOrderExpiry = na
var int shortOrderExpiry = na
if not na(longEntryPrice)
longOrderExpiry := bar_index + 2 // Order expires after 2 days
if not na(shortEntryPrice)
shortOrderExpiry := bar_index + 2 // Order expires after 2 days
// Check expiration and execute orders
if (longEntryPrice and bar_index <= longOrderExpiry and high >= longEntryPrice)
longStopDistance = close - nz(swingLow, close)
longPositionSize = longStopDistance > 0 ? riskAmount / longStopDistance : na
if (not na(longPositionSize))
strategy.entry("Long", strategy.long, qty=longPositionSize)
longEntryPrice := na // Reset after entry
if (shortEntryPrice and bar_index <= shortOrderExpiry and low <= shortEntryPrice)
shortStopDistance = nz(swingHigh, close) - close
shortPositionSize = shortStopDistance > 0 ? riskAmount / shortStopDistance : na
if (not na(shortPositionSize))
strategy.entry("Short", strategy.short, qty=shortPositionSize)
shortEntryPrice := na // Reset after entry
// Exit logic: hit the opposing Bollinger Band
if (strategy.position_size > 0) // Long position
strategy.exit("Exit Long", "Long", limit=dailyUpperBand)
else if (strategy.position_size < 0) // Short position
strategy.exit("Exit Short", "Short", limit=dailyLowerBand)
if (strategy.position_size > 0) // Long position
strategy.exit("Stop Loss Long", "Long", stop=swingLow)
else if (strategy.position_size < 0) // Short position
strategy.exit("Stop Loss Short", "Short", stop=swingHigh)
// Plot daily Bollinger Bands and levels on the chosen time frame
plot(dailyUpperBand, color=color.blue, linewidth=1, title="Daily Upper Bollinger Band")
plot(dailyLowerBand, color=color.blue, linewidth=1, title="Daily Lower Bollinger Band")
plot(dailyBasis, color=color.gray, linewidth=1, title="Daily Middle Bollinger Band")