EMA 크로스 ADR 전략은 트레이딩뷰 플랫폼을 기반으로 한 양적 거래 전략이다. 트렌드를 결정하고 필터 신호를 표시하며 스톱 로스 및 영업 한도를 설정하기 위해 여러 기술적 지표를 결합합니다. 이 전략은 주요 트렌드를 식별하기 위해 서로 다른 기간을 가진 두 개의 기하급수적인 이동 평균 (EMA) 을 사용하고, 평균 일일 범위 (ADR) 를 변동성 필터로 사용하고, 위험-상금 비율을 기반으로 스톱 로스 및 영업 한도를 동적으로 설정합니다. 또한 전략에는 거래 시간 창, 브레이크 이븐 스톱 및 최대 일일 손실 한도와 같은 위험 관리 조치가 포함되어 있으며, 추세 기회를 포착하는 동시에 하락 위험을 엄격히 제어하는 것을 목표로합니다.
듀얼 EMA 크로스오버 (Dual EMA Crossover): 이 전략은 트렌드를 결정하기 위해 서로 다른 기간을 가진 두 개의 EMA를 사용합니다. 단기 EMA가 장기 EMA를 넘으면 상승 추세로 간주되어 긴 신호를 생성합니다. 반대로 단기 EMA가 장기 EMA를 넘으면 하향 추세로 간주되어 짧은 신호를 생성합니다.
ADR 변동성 필터: 낮은 변동성 환경에서 거래 신호를 생성하는 것을 피하기 위해 전략은 변동성 필터로 ADR 지표를 도입합니다. ADR 값이 미리 설정된 최소 문턱을 초과 할 때만 포지션을 열 수 있습니다.
거래 시간 창: 전략은 사용자가 매일 거래의 시작 및 종료 시간을 설정할 수 있습니다. 거래는 지정된 시간 창 내에서만 실행되며, 유동성 또는 매우 변동적인 기간을 피하는 데 도움이됩니다.
동적 스톱 로스 및 트레이프: 전략은 가장 최근의 N 촛불의 평균 최고 및 최저 가격을 기반으로 동적으로 스톱 로스 및 트레이프 가격을 계산하며, 미리 설정된 리스크 리워드 비율과 결합하여 각 거래의 리스크 리워드를 제어 할 수 있도록합니다.
브레이크 이븐 스톱: 포지션이 특정 수익 수준 (사용자 정의 위험 보상 비율) 에 도달하면 전략은 스톱 로스를 브레이크 이븐 포인트 (입시 가격) 로 이동시킵니다. 이것은 이미 얻은 이익을 보호하는 데 도움이됩니다.
최대 일일 손실 제한: 하루 최대 손실을 제어하기 위해 전략은 일일 손실 제한을 설정합니다. 일일 손실이 이 제한에 도달하면 전략은 다음 날 열리기 전까지 거래를 중단합니다.
모든 포지션을 하루 끝으로 닫습니다. 포지션이 수익을 취하거나 손해를 막는 수준에 도달했는지 여부에 관계없이 전략은 하루 하루 위험을 피하기 위해 모든 포지션을 매 거래일에 일정한 시간에 닫습니다. (예: 16:00)
강한 트렌드 추적 능력: 트렌드를 결정하기 위해 이중 EMA 크로스오버를 사용하여 전략은 주요 시장 트렌드를 효과적으로 파악하여 승률과 수익 잠재력을 향상시킬 수 있습니다.
변동성에 대한 좋은 적응력: 변동성 필터로서의 ADR 지표의 도입은 낮은 변동성 환경에서 빈번한 거래를 피할 수 있으며, 유효하지 않은 신호 및 잘못된 파업으로 인한 손실을 줄일 수 있습니다.
엄격한 위험 통제: 전략은 다중 차원에서 위험 통제 조치를 설정합니다. 동적 인 스톱 로스 및 영업 취득, 브레이크 이븐 스톱 및 최대 일일 손실 제한을 포함하여 하향 위험을 효과적으로 제어하고 위험 조정 수익을 향상시킵니다.
유연한 매개 변수 설정: EMA 기간, ADR 길이, 리스크/어워드 비율, 거래 시간 창 등 전략의 다양한 매개 변수들은 전략 성과를 최적화하기 위해 사용자 선호도와 시장 특성에 따라 유연하게 설정될 수 있습니다.
높은 자동화 수준: 전략은 트레이딩뷰 플랫폼을 기반으로 하며, 거래 논리는 전적으로 프로그램에서 실행되며, 인간의 감정과 주관적 판단의 간섭을 줄여 전략의 장기적인 안정적인 작동을 촉진합니다.
매개 변수 최적화 위험: 전략의 매개 변수를 유연하게 조정할 수 있지만, 과도한 최적화는 과도한 적합성과 샘플 외의 낮은 성능을 초래할 수 있습니다. 따라서 매개 변수를 설정할 때 전략의 견고성을 보장하기 위해 충분한 백테스팅과 분석이 필요합니다.
갑작스러운 이벤트 위험: 전략은 주로 기술 지표에 기반하여 거래되며 정책 변화 또는 중요한 경제 데이터 변동과 같은 갑작스러운 주요 근본 이벤트에 충분히 반응하지 않을 수 있습니다.
트렌드 역전 위험: 트렌드 역전의 중요한 기간 동안 이중 EMA 크로스오버 신호는 지연될 수 있으며, 트렌드 역전 초기에는 전략이 가장 좋은 시기를 놓치거나 손실을 입을 수 있습니다.
유동성 위험: 전략은 거래 시간 창을 설정하지만 거래되는 도구의 유동성이 좋지 않으면 여전히 슬리프 및 거래 지연과 같은 위험에 직면 할 수 있으며 전략 성과에 영향을 줄 수 있습니다.
기술 지표 실패 위험: 전략은 기술 지표에 크게 의존합니다. 시장 조건이 크게 변화하여 지표가 원래의 의미를 잃게되면 전략의 효과는 감소 할 수 있습니다.
더 많은 차원 지표를 도입: 기존의 이중 EMA와 ADR를 기반으로 신호의 신뢰성과 견고성을 향상시키기 위해 MACD 및 RSI와 같은 더 효과적인 기술적 지표를 도입하는 것을 고려하십시오.
동적 매개 변수 최적화: 시장 변화에 적응하기 위해 다른 시장 상태 (트렌드 또는 오스실레이션과 같은) 를 기반으로 주요 전략 매개 변수를 동적으로 조정하는 매개 변수 최적화 메커니즘을 구축합니다.
기본 요소를 포함합니다. 경제 데이터와 정책 방향과 같은 몇 가지 중요한 기본 지표를 적절히 고려하여 전략이 시장 동향을 더 잘 파악하고 제때 시스템 위험을 피하도록 도울 수 있습니다.
스톱 로스 및 영업 취득 메커니즘을 개선: 기존의 동적 스톱 로스 및 영업 취득 기반의 스톱 로스 및 영업 취득의 논리를 더 최적화하여 수익을 더 잘 보호하고 위험을 통제하기 위해 후속 스톱 로스 및 부분 영업 취득을 도입합니다.
여러 도구와 시간 프레임: 여러 거래 도구와 시간 프레임에 전략을 확장하고 다양한 투자 및 시간 프레임 최적화를 통해 전략의 적응력과 안정성을 향상시킵니다.
EMA 크로스 ADR 전략은 기술 분석을 기반으로 한 양적 거래 전략이다. 이중 EMA 크로스오버를 통해 트렌드를 결정하고 변동성 필터링을 위해 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)