
ADR 평행선 교차 전략은 TradingView 플랫폼을 기반으로 한 수량 거래 전략으로, 트렌드를 판단하고, 신호를 필터링하고, 스톱로드를 설정하기 위해 여러 기술적 지표를 결합한다. 이 전략은 두 개의 다른 주기의 지수 이동 평균 (EMA) 을 사용하여 주요 트렌드를 식별하고, 평균 실제 파도 (ATR) 를 변동률 필터로 사용하고, 위험-수익 비교에 따라 역동적으로 스톱로드를 설정한다. 또한, 이 전략은 거래 시간 창, 손해 균형, 최대 일일 손해와 같은 위험 관리를 도입하여, 트렌드 기회를 파악하는 동시에, 하향 위험을 엄격히 통제한다.
양평선 교차: 전략은 두 개의 다른 주기의 EMA 선을 사용하여 추세를 판단한다. 단기 EMA 위에 장기 EMA를 밟을 때, 추세가 상향으로 간주되어, 다중 신호를 생성한다. 반대로, 단기 EMA 아래에 장기 EMA를 밟을 때, 추세가 하향으로 간주되어, 공백 신호를 생성한다.
ADR 변동율 필터: 낮은 변동율 환경에서 거래 신호를 발생하지 않도록, ADR 지표가 변동율 필터로 도입되었습니다. ADR 값이 기본 최소 값보다 높을 때만 입장을 열 수 있습니다.
거래 시간 창: 이 전략은 사용자가 매일 거래의 시작 시간을 설정할 수 있도록 합니다. 거래는 지정된 시간 창 내에서만 실행됩니다. 이것은 유동성이 낮은 또는 변동성이 높은 시기를 피하는 데 도움이됩니다.
동적 스톱스톱: 전략은 최근 N근 K선의 평균 최고 가격과 최저 가격에 따라, 그리고 기본 리스크 수익률과 결합하여, 동적으로 스톱스톱 가격과 스톱스톱 가격을 계산한다. 이것은 각 거래의 리스크 수익률이 제어될 수 있도록 한다.
손해균형: 지분을 보유한 후에 특정 수익률을 달성하면 (사용자가 리스크 수익률을 설정할 수 있습니다) 전략은 스톱로스를 포지션 개시 가격, 즉 손해균형 수준으로 이동합니다. 이것은 이미 얻은 이익을 보호하는 데 도움이됩니다.
하루 최대 손실 제한: 하루 최대 손실을 제어하기 위해, 전략은 매일의 손실 제한을 설정합니다. 하루의 손실이 그 제한을 달성하면, 전략은 다음 날 상장할 때까지 거래를 중지합니다.
청산: 보유 지점이 스톱이나 스톱로스 라인을 만졌는지 여부에 관계없이, 전략은 매 거래 날의 고정 시간 (예: 16:00) 에 모든 지점을 청산하여 하룻밤의 위험을 피한다.
트렌드 추적 능력: 쌍평선 교차로로 트렌드를 판단하여 시장의 주요 트렌드를 효과적으로 포착하여 전략의 승률과 수익 잠재력을 향상시킬 수 있습니다.
변동률 적응성: ADR 지표를 변동률 필터로 도입하여 낮은 변동률 환경에서 자주 거래하는 것을 피할 수 있으며, 무효 신호와 가짜 돌파구로 인한 손실을 줄일 수 있습니다.
위험 통제 엄격: 이 전략은 다 차원에서 위험 통제 조치를 설정합니다. 다이내믹 스톱 스톱 로드, 손해 균형, 최대 일일 손실 제한 등이 포함됩니다. 전략의 하향 위험을 효과적으로 제어하고, 위험 조정 후 수익을 향상시킵니다.
매개 변수 유연성: 전략의 매개 변수들, 예를 들어 평균선 주기, ADR의 길, 리스크 수익률, 거래 시간 창 등은 사용자의 선호도와 시장 특성에 따라 유연하게 설정되어 전략의 성능을 최적화할 수 있다.
자동화 수준: 이 전략은 TradingView 플랫폼을 기반으로하고 거래 논리는 프로그램으로 완전히 자동으로 수행되며, 인간의 감정과 주관적 판단의 간섭을 줄여서 전략의 장기적인 안정적인 운영에 도움이 됩니다.
매개 변수 최적화 위험: 이 전략의 매개 변수는 유연하게 조정될 수 있지만, 과잉 최적화하면 과잉 적합으로 이어져 표본 외부에서 좋지 않은 성능을 나타낼 수 있다. 따라서 매개 변수 설정 시 충분한 피드백과 분석이 필요하여 전략의 건전성을 보장한다.
급격한 사건 위험: 이 전략은 주로 기술 지표 거래에 기반하고 있으며, 정책 변화, 경제 데이터의 큰 변동과 같은 일부 급격한 주요 기본 사건에 대한 반응이 부족하여 큰 회수로 이어질 수 있습니다.
트렌드 리버팅 위험: 트렌드 리버팅의 중요한 시점에 쌍평선 교차 신호가 지연되어 전략이 최적의 포지션 시기를 놓치게 하거나 트렌드 리버팅의 초기에 손실을 입을 수 있다.
유동성 위험: 전략이 거래 시간 창을 설정했음에도 불구하고 거래 지표의 유동성이 떨어지면 슬라이드 포인트, 거래 지연 등의 위험에 직면하여 전략의 성과에 영향을 줄 수 있습니다.
기술 지표 실패 위험: 이 전략은 기술 지표에 크게 의존하고 있으며, 시장 환경이 크게 변하면 지표가 원래의 지시 의미를 잃게되면 전략의 유효성이 떨어질 수 있습니다.
더 많은 차원의 지표를 도입: 기존의 이중 평균선과 ADR의 기반에서 MACD, RSI 등과 같은 더 많은 효과적인 기술 지표를 도입하여 신호의 신뢰성과 안정성을 향상시킬 수 있습니다.
동적 최적화 매개 변수: 매개 변수 최적화 메커니즘을 구축할 수 있으며, 시장의 변화에 따라 전략의 핵심 매개 변수를 동적으로 조정할 수 있습니다.
기본 요소를 포함하십시오. 경제 데이터, 정책 동향 등과 같은 중요한 기본 지표를 적절하게 고려하면 시장 추세를 더 잘 파악하고 체계적인 위험을 조기에 피할 수 있습니다.
스톱스톱 메커니즘의 개선: 기존의 동적 스톱스톱을 기반으로 스톱스톱의 논리를 더욱 최적화할 수 있습니다. 예를 들어, 추적 스톱, 부분 스톱 등의 방법을 도입하여 수익을 더 잘 보호하고 위험을 제어할 수 있습니다.
다중 표적, 다중 시간 주기: 이 전략을 다중 거래 표적 및 다중 시간 주기까지 확장하여 투자 분산과 시간 주기 최적화를 통해 전략의 적응성과 안정성을 향상시킵니다.
ADR 평행선 교차 전략은 기술 분석을 기반으로 한 정량 거래 전략으로, 쌍평행선 교차를 통해 트렌드를 판단하고 ADR 지표를 사용하여 변동률 필터링한다. 이 전략은 또한 역동적인 중지 손실, 손해 균형, 최대 일일 손실 제한 등과 같은 엄격한 위험 관리를 설정하여 하향 위험을 제어한다. 전략의 장점은 트렌드 추적 능력이 강하고, 변동율 적응성이 좋으며, 위험 통제가 엄격하며, 매개 변수가 유연하게 조정 가능하며, 자동화 수준이 높다. 그러나 또한 파라미터 최적화 위험, 갑작스러운 사건 위험, 트렌드 전환 위험, 유동성 위험 및 기술 지표 실효 위험과 같은 위험이 있습니다.
/*backtest
start: 2024-02-26 00:00:00
end: 2024-03-27 00:00:00
period: 2h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Sameh_Hussein
//@version=5
strategy('EMA Cross ADR Strategy with Stats', overlay=true)
// Adjustable Parameters
shortEmaLength = input(10, title='Short EMA Length')
longEmaLength = input(50, title='Long EMA Length')
adrLength = input(14, title='ADR Length')
riskRewardRatio = input(2.0, title='Risk/Reward Ratio')
lookbackCandles = input(10, title='Lookback Candles for Stop Loss')
startTime = input(0900, title='Start Time')
endTime = input(1600, title='End Time')
minAdrValue = input(10, title='Minimum ADR Value for Entry')
breakEvenProfit = input.float(1.0, title='Break-Even Profit', minval=0.0)
breakEvenRR = input.float(1.0, title='Break-Even Risk-Reward Ratio', minval=0.0)
dailyLossLimit = input(-2000.0, title='Daily Loss Limit')
// Exponential Moving Averages
shortEma = ta.ema(close, shortEmaLength)
longEma = ta.ema(close, longEmaLength)
// Average Daily Range
adr = ta.sma(ta.tr, adrLength)
// Time Filter Function
timeFilter() => true
// Entry Conditions with ADR filter
longCondition = ta.crossover(shortEma, longEma) and timeFilter() and adr > minAdrValue
shortCondition = ta.crossunder(shortEma, longEma) and timeFilter() and adr > minAdrValue
// Calculate the average low and average high of the previous 'lookbackCandles' candles
averageLow = ta.sma(low, lookbackCandles)
averageHigh = ta.sma(high, lookbackCandles)
// Risk and Reward Calculation
stopLossLong = averageLow
takeProfitLong = close + (close - averageLow) * riskRewardRatio
stopLossShort = averageHigh
takeProfitShort = close - (averageHigh - close) * riskRewardRatio
// Entry Control Variables
var longEntryAllowed = true
var shortEntryAllowed = true
// Update entry price on trade execution
var float entryPriceLong = na
var float entryPriceShort = na
if (strategy.position_size > 0)
if (strategy.position_size[1] <= 0)
entryPriceLong := strategy.opentrades.entry_price(strategy.opentrades - 1)
else
entryPriceLong := entryPriceLong
else
entryPriceLong := na
if (strategy.position_size < 0)
if (strategy.position_size[1] >= 0)
entryPriceShort := strategy.opentrades.entry_price(strategy.opentrades - 1)
else
entryPriceShort := entryPriceShort
else
entryPriceShort := na
// Adjust stop loss to break-even plus the defined profit when the specified risk-reward ratio is reached
breakEvenTriggerLong = entryPriceLong + (entryPriceLong - stopLossLong) * breakEvenRR
breakEvenTriggerShort = entryPriceShort - (stopLossShort - entryPriceShort) * breakEvenRR
if (longEntryAllowed and close >= breakEvenTriggerLong)
stopLossLong := entryPriceLong + breakEvenProfit
if (shortEntryAllowed and close <= breakEvenTriggerShort)
stopLossShort := entryPriceShort - breakEvenProfit
// Close all trades at 1600
if (hour == 15 and minute == 59)
strategy.close_all(comment='Close at 1600')
// Define the daily loss variable and last trade day
var float[] dailyLossArray = array.new_float(1, 0.0)
var int[] lastTradeDayArray = array.new_int(1, na)
// Function to update the daily loss
updateDailyLoss() =>
_dailyLoss = array.get(dailyLossArray, 0)
_lastTradeDay = array.get(lastTradeDayArray, 0)
if na(_lastTradeDay) or dayofmonth != _lastTradeDay
_dailyLoss := 0.0
array.set(lastTradeDayArray, 0, dayofmonth)
if not na(strategy.closedtrades.entry_bar_index(strategy.closedtrades - 1))
_dailyLoss += strategy.closedtrades.profit(strategy.closedtrades - 1)
array.set(dailyLossArray, 0, _dailyLoss)
// Call the function to update the daily loss
updateDailyLoss()
// Execute Strategy
if longCondition and longEntryAllowed
strategy.entry('Long', strategy.long)
strategy.exit('Take Profit/Stop Loss', 'Long', stop=stopLossLong, limit=takeProfitLong)
longEntryAllowed := false
if shortCondition and shortEntryAllowed
strategy.entry('Short', strategy.short)
strategy.exit('Take Profit/Stop Loss', 'Short', stop=stopLossShort, limit=takeProfitShort)
shortEntryAllowed := false
// Reset entry control variables on position close
if strategy.position_size == 0
longEntryAllowed := true
shortEntryAllowed := true
// // Statistics
// winRate = strategy.wintrades / strategy.closedtrades * 100
// totalTrades = strategy.closedtrades
// averageProfit = strategy.grossprofit / strategy.wintrades
// averageLoss = strategy.grossloss / strategy.losstrades
// // Plotting
// plot(shortEma, color=color.new(color.red, 0), title='Short EMA')
// plot(longEma, color=color.new(color.blue, 0), title='Long EMA')
// // Display Table
// table statsTable = table.new(position=position.top_right, columns=2, rows=4, bgcolor=color.gray, border_width=1)
// table.cell(statsTable, column=0, row=0, text='Win Rate (%)', bgcolor=color.blue)
// table.cell(statsTable, column=1, row=0, text=str.tostring(winRate), bgcolor=color.blue)
// table.cell(statsTable, column=0, row=1, text='Total Trades', bgcolor=color.blue)
// table.cell(statsTable, column=1, row=1, text=str.tostring(totalTrades), bgcolor=color.blue)
// table.cell(statsTable, column=0, row=2, text='Average Profit', bgcolor=color.blue)
// table.cell(statsTable, column=1, row=2, text=str.tostring(averageProfit), bgcolor=color.blue)
// table.cell(statsTable, column=0, row=3, text='Average Loss', bgcolor=color.blue)
// table.cell(statsTable, column=1, row=3, text=str.tostring(averageLoss), bgcolor=color.blue)