EMA 평균 회전 거래 전략은 가격과 EMA의 비율 차이를 기준으로 포지션을 열고 닫습니다. 포지션을 관리하기 위해 엔트리 신호와 트레일링 스톱 로스로 사용됩니다.
이 전략은 EMA를 벤치마크로 사용하고 현재 가격과 EMA 사이의 비율 차이를 계산합니다. 가격이 EMA에서 충분히 멀리 떨어져있을 때 (기본 9%), 가격이 EMA (기본 1%) 에 충분히 가까워질 때 포지션을 닫습니다. 포지션을 열면 증가함에 따라 수익을 잠금하기 위해 후속 스톱 손실을 사용합니다.
특히 전략은 다음과 같은 구성 요소를 포함합니다.
EMA를 계산합니다. 기간 (예정 200), 소스 (폐기 가격) 및 방법 (EMA, SMA, RMA, WMA) 은 구성 가능합니다.
현재 가격과 EMA의 비율 차이를 계산해 보라.
열리는 포지션은 차이 임계값에 기초합니다. 기본 롱 엔트리는 9%이고 쇼트 엔트리는 9%입니다.
지원 사다리 입구. 계단 수와 계단 당 단계의 비율을 구성 할 수 있습니다.
입력 후 후속 스톱 손실을 사용 합니다. 후속 시작 임계 (1% 기본 이익) 및 후속 비율 (1% 기본) 는 구성 됩니다.
차이 임계 기준에 따라 포지션을 닫습니다. 기본 출구는 장기 및 단위 모두에서 1%입니다.
가격이 EMA로 돌아간다면 채우지 않은 주문을 취소하세요.
설정 가능한 스톱 로스 비율
백테스팅과 라이브 트레이딩을 지원합니다
이 전략의 장점:
EMA 오차를 기반으로 트레이드 트렌드에 평균 회귀 개념을 활용합니다. 트렌드 트레이딩 이론과 일치합니다.
엔트리, 스톱 로스, 엑시트 매개 변수는 다른 시장 조건에 적응할 수 있습니다.
계단으로 들어가면 점진적으로 위치가 쌓이고 비용을 줄일 수 있습니다.
후속 스톱은 수익을 확보하고 위험을 관리합니다.
EMA 매개 변수 또는 입출동 문턱을 조정하여 매우 최적화 할 수 있습니다.
파인 스크립트는 트레이딩뷰에서 쉽게 사용할 수 있습니다.
관측과 분석을 위한 직관적인 차트
이 전략의 위험은:
백테스트 오버피팅 위험. 매개 변수 최적화는 백테스트 데이터에 오버피팅을 할 수 있으며 라이브 트레이딩에서 성과가 떨어질 수 있습니다.
EMA 실패 위험. 가격은 EMA에서 장기간 벗어날 수 있습니다.
스톱 러스가 위험보다 더 커질 때
높은 거래 빈도는 높은 수수료 비용을 초래합니다.
더 긴 회상 기간이 필요하고 갑작스러운 사건에 더 취약합니다.
위험 관리
최적화와 멀티 시장 검증을 통해 강력한 매개 변수 선택
합리적인 EMA 기간, 너무 짧거나 너무 길지 않습니다.
더 넓은 스톱 로스 버퍼로 조기 중단되는 것을 방지합니다.
덜 공격적인 진입 규칙은 무역의 빈도를 줄입니다.
부피, 볼링거 밴드, RSI와 같은 추가 지표를 포함하여 이벤트에 적응하십시오.
이 전략은 다음과 같은 측면에서 개선될 수 있습니다.
부피, 볼링거 밴드, RSI 같은 필터를 추가하여 잘못된 신호를 줄입니다.
더 높은 확률 트렌드 거래를 위해 이중 EMA를 추가합니다.
적응식 스톱, 캔들리어 출구로 스톱 로스를 강화해 위험을 더 제한합니다.
더 나은 매개 변수 집합을 찾기 위해 자동 매개 변수 최적화를 추가합니다.
EMA 오차의 확률에 대해 기계 학습을 포함합니다.
격차를 활용하기 위해 내일 또는 오버나이트 포지션을 고려하십시오.
더 큰 용량을 위해 주식 우주 선택을 통합합니다.
EMA는 이동평균 주위의 가격의 평균 역행위에 기반한 트레이드이다. 트렌드 변화를 식별하기 위해 EMA의 통계적 특성을 합리적으로 활용하고 위험을 제어하기 위해 스톱 로스를 사용합니다. 전통적인 이동평균 전략과 비교하면 엄격한 입출 규칙보다는 동적 트레일링 스톱에 더 초점을 맞추고 있습니다. 전략은 트렌드 다음 전략을 보완 할 수 있지만 곡선 부착과 거래 빈도를 제어하는 데 주의가 필요합니다. 스톱 로스와 엔트리 품질의 추가 개선은 더 나은 라이브 성과로 이어질 수 있습니다.
/*backtest start: 2022-10-19 00:00:00 end: 2023-10-25 00:00:00 period: 1d basePeriod: 1h 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/ // © jordanfray //@version=5 strategy(title="EMA Mean Reversion Strategy", overlay=true, max_bars_back=5000, default_qty_type=strategy.percent_of_equity, default_qty_value=100,initial_capital=100000, commission_type=strategy.commission.percent, commission_value=0.05, backtest_fill_limits_assumption=2) // Indenting Classs indent_1 = " " indent_2 = " " indent_3 = " " indent_4 = " " // Tooltips longEntryToolTip = "When the percentage that the price is away from the selected EMA reaches this point, a long postion will open." shortEntryToolTip = "When the percentage that the price is away from the selected EMA reaches this point, a short postion will open." closeEntryToolTip = "When the percentage that the price is away from the selected EMA reaches this point, open postion will close." ladderInToolTip = "Enable this to use the laddering settings below." cancelEntryToolTip = "When the percentage that the price is away from the selected EMA reaches this point, any unfilled entries will be canceled." // Group Titles group_one_title = "EMA Settings" group_two_title = "Entry Settings" // Colors blue = color.new(#00A5FF,0) lightBlue = color.new(#00A5FF,90) green = color.new(#2DBD85,0) gray_80 = color.new(#7F7F7F,80) gray_60 = color.new(#7F7F7F,60) gray_40 = color.new(#7F7F7F,40) white = color.new(#ffffff,0) red = color.new(#E02A4A,0) transparent = color.new(#000000,100) // Strategy Settings EMAtimeframe = input.timeframe(defval="", title="Timeframe", group=group_one_title) EMAlength = input.int(defval=200, minval=1, title="Length", group=group_one_title) EMAtype = input.string(defval="EMA", options = ["EMA", "SMA", "RMA", "WMA"], title="Type", group=group_one_title) EMAsource = input.source(defval=close, title="Source", group=group_one_title) openLongEntryAbove = input.float(defval=9, title="Long Position Entry Trigger", tooltip=longEntryToolTip, group=group_two_title) openEntryEntryAbove = input.float(defval=9, title="Short Position Entry Trigger", tooltip=shortEntryToolTip, group=group_two_title) closeEntryBelow = input.float(defval=1.0, title="Close Position Trigger", tooltip=closeEntryToolTip, group=group_two_title) cancelEntryBelow = input.float(defval=4, title="Cancel Unfilled Entries Trigger", tooltip=cancelEntryToolTip, group=group_two_title) enableLaddering = input.bool(defval=true, title="Ladder Into Positions", tooltip=ladderInToolTip, group=group_two_title) ladderRungs = input.int(defval=4, minval=2, maxval=4, step=1, title=indent_4+"Ladder Rungs", group=group_two_title) ladderStep = input.float(defval=.5, title=indent_4+"Ladder Step (%)", step=.1, group=group_two_title)/100 stop_loss_val = input.float(defval=4.0, title="Stop Loss (%)", step=0.1, group=group_two_title)/100 start_trailing_after = input.float(defval=1, title="Start Trailing After (%)", step=0.1, group=group_two_title)/100 trail_behind = input.float(defval=1, title="Trail Behind (%)", step=0.1, group=group_two_title)/100 // Calculate trailing stop values long_start_trailing_val = strategy.position_avg_price + (strategy.position_avg_price * start_trailing_after) long_trail_behind_val = close - (strategy.position_avg_price * trail_behind) long_stop_loss = strategy.position_avg_price * (1.0 - stop_loss_val) short_start_trailing_val = strategy.position_avg_price - (strategy.position_avg_price * start_trailing_after) short_trail_behind_val = close + (strategy.position_avg_price * trail_behind) short_stop_loss = strategy.position_avg_price * (1 + stop_loss_val) // Calulate EMA EMA = switch EMAtype "EMA" => ta.ema(EMAsource, EMAlength) "SMA" => ta.sma(EMAsource, EMAlength) "RMA" => ta.rma(EMAsource, EMAlength) "WMA" => ta.wma(EMAsource, EMAlength) => na EMA_ = EMAtimeframe == timeframe.period ? EMA : request.security(syminfo.ticker, EMAtimeframe, EMA[1], lookahead = barmerge.lookahead_on) plot(EMA_, title="EMA", linewidth=2, color=blue, editable=true) EMA_cloud_upper_band_val = EMA_ + (EMA_ * openLongEntryAbove/100) EMA_cloud_lower_band_val = EMA_ - (EMA_ * openLongEntryAbove/100) EMA_cloud_upper_band = plot(EMA_cloud_upper_band_val, title="EMA Cloud Upper Band", color=blue) EMA_cloud_lower_band = plot(EMA_cloud_lower_band_val, title="EMA Cloud Upper Band", color=blue) fill(EMA_cloud_upper_band, EMA_cloud_lower_band, editable=false, color=lightBlue) distance_from_EMA = ((close - EMA_)/close)*100 if distance_from_EMA < 0 distance_from_EMA := distance_from_EMA * -1 // Calulate Ladder Entries long_ladder_1_limit_price = close - (close * 1 * ladderStep) long_ladder_2_limit_price = close - (close * 2 * ladderStep) long_ladder_3_limit_price = close - (close * 3 * ladderStep) long_ladder_4_limit_price = close - (close * 4 * ladderStep) short_ladder_1_limit_price = close + (close * 1 * ladderStep) short_ladder_2_limit_price = close + (close * 2 * ladderStep) short_ladder_3_limit_price = close + (close * 3 * ladderStep) short_ladder_4_limit_price = close + (close * 4 * ladderStep) var position_qty = strategy.equity/close if enableLaddering position_qty := (strategy.equity/close) / ladderRungs else position_qty := strategy.equity/close plot(position_qty, color=white) //plot(strategy.equity, color=green) // Entry Conditions currently_in_a_postion = strategy.position_size != 0 currently_in_a_long_postion = strategy.position_size > 0 currently_in_a_short_postion = strategy.position_size < 0 average_price = strategy.position_avg_price bars_since_entry = currently_in_a_postion ? bar_index - strategy.opentrades.entry_bar_index(strategy.opentrades - 1) + 1 : 5 long_run_up = ta.highest(high, bar_index == 0 ? 5000: bars_since_entry) long_run_up_line = plot(long_run_up, style=plot.style_stepline, editable=false, color=currently_in_a_long_postion ? green : transparent) start_trailing_long_entry = currently_in_a_long_postion and long_run_up > long_start_trailing_val long_trailing_stop = start_trailing_long_entry ? long_run_up - (long_run_up * trail_behind) : long_stop_loss long_trailing_stop_line = plot(long_trailing_stop, style=plot.style_stepline, editable=false, color=currently_in_a_long_postion ? long_trailing_stop > strategy.position_avg_price ? green : red : transparent) short_run_up = ta.lowest(low, bar_index == 0 ? 5000: bars_since_entry) short_run_up_line = plot(short_run_up, style=plot.style_stepline, editable=false, color=currently_in_a_short_postion ? green : transparent) start_trailing_short_entry = currently_in_a_short_postion and short_run_up < short_start_trailing_val short_trailing_stop = start_trailing_short_entry ? short_run_up + (short_run_up * trail_behind) : short_stop_loss short_trailing_stop_line = plot(short_trailing_stop, style=plot.style_stepline, editable=false, color=currently_in_a_short_postion ? short_trailing_stop < strategy.position_avg_price ? green : red : transparent) long_conditions_met = distance_from_EMA > openLongEntryAbove and close < EMA_ and not currently_in_a_postion short_conditions_met = distance_from_EMA > openEntryEntryAbove and close > EMA_ and not currently_in_a_postion close_long_entries = distance_from_EMA <= closeEntryBelow or close <= long_trailing_stop close_short_entries = distance_from_EMA <= closeEntryBelow or close >= short_trailing_stop cancel_entries = distance_from_EMA <= cancelEntryBelow plotshape(long_conditions_met ? close : na, style=shape.diamond, title="Long Conditions Met" ) plotshape(short_conditions_met ? close : na, style=shape.diamond, title="Short Conditions Met" ) plot(average_price,style=plot.style_stepline, editable=false, color=currently_in_a_postion ? blue : transparent) // Long Entry if enableLaddering if ladderRungs == 2 strategy.entry(id="Long Ladder 1", direction=strategy.long, qty=position_qty, limit=long_ladder_1_limit_price, when=long_conditions_met) strategy.entry(id="Long Ladder 2", direction=strategy.long, qty=position_qty, limit=long_ladder_2_limit_price, when=long_conditions_met) else if ladderRungs == 3 strategy.entry(id="Long Ladder 1", direction=strategy.long, qty=position_qty, limit=long_ladder_1_limit_price, when=long_conditions_met) strategy.entry(id="Long Ladder 2", direction=strategy.long, qty=position_qty, limit=long_ladder_2_limit_price, when=long_conditions_met) strategy.entry(id="Long Ladder 3", direction=strategy.long, qty=position_qty, limit=long_ladder_3_limit_price, when=long_conditions_met) else if ladderRungs == 4 strategy.entry(id="Long Ladder 1", direction=strategy.long, qty=position_qty, limit=long_ladder_1_limit_price, when=long_conditions_met) strategy.entry(id="Long Ladder 2", direction=strategy.long, qty=position_qty, limit=long_ladder_2_limit_price, when=long_conditions_met) strategy.entry(id="Long Ladder 3", direction=strategy.long, qty=position_qty, limit=long_ladder_3_limit_price, when=long_conditions_met) strategy.entry(id="Long Ladder 4", direction=strategy.long, qty=position_qty, limit=long_ladder_4_limit_price, when=long_conditions_met) strategy.exit(id="Close Long Ladder 1", from_entry="Long Ladder 1", stop=long_trailing_stop, limit=long_trailing_stop, when=close_long_entries) strategy.exit(id="Close Long Ladder 2", from_entry="Long Ladder 2", stop=long_trailing_stop, limit=long_trailing_stop, when=close_long_entries) strategy.exit(id="Close Long Ladder 3", from_entry="Long Ladder 3", stop=long_trailing_stop, limit=long_trailing_stop, when=close_long_entries) strategy.exit(id="Close Long Ladder 4", from_entry="Long Ladder 4", stop=long_trailing_stop, limit=long_trailing_stop, when=close_long_entries) strategy.cancel(id="Long Ladder 1", when=cancel_entries) strategy.cancel(id="Long Ladder 2", when=cancel_entries) strategy.cancel(id="Long Ladder 3", when=cancel_entries) strategy.cancel(id="Long Ladder 4", when=cancel_entries) else strategy.entry(id="Long", direction=strategy.long, qty=100, when=long_conditions_met) strategy.exit(id="Close Long", from_entry="Long", stop=long_stop_loss, limit=EMA_, when=close_long_entries) strategy.cancel(id="Long", when=cancel_entries) // Short Entry if enableLaddering if ladderRungs == 2 strategy.entry(id="Short Ladder 1", direction=strategy.short, qty=position_qty, limit=short_ladder_1_limit_price, when=short_conditions_met) strategy.entry(id="Short Ladder 2", direction=strategy.short, qty=position_qty, limit=short_ladder_2_limit_price, when=short_conditions_met) else if ladderRungs == 3 strategy.entry(id="Short Ladder 1", direction=strategy.short, qty=position_qty, limit=short_ladder_1_limit_price, when=short_conditions_met) strategy.entry(id="Short Ladder 2", direction=strategy.short, qty=position_qty, limit=short_ladder_2_limit_price, when=short_conditions_met) strategy.entry(id="Short Ladder 3", direction=strategy.short, qty=position_qty, limit=short_ladder_3_limit_price, when=short_conditions_met) else if ladderRungs == 4 strategy.entry(id="Short Ladder 1", direction=strategy.short, qty=position_qty, limit=short_ladder_1_limit_price, when=short_conditions_met) strategy.entry(id="Short Ladder 2", direction=strategy.short, qty=position_qty, limit=short_ladder_2_limit_price, when=short_conditions_met) strategy.entry(id="Short Ladder 3", direction=strategy.short, qty=position_qty, limit=short_ladder_3_limit_price, when=short_conditions_met) strategy.entry(id="Short Ladder 4", direction=strategy.short, qty=position_qty, limit=short_ladder_4_limit_price, when=short_conditions_met) strategy.exit(id="Close Short Ladder 1", from_entry="Short Ladder 1", stop=short_trailing_stop, limit=EMA_, when=close_short_entries) strategy.exit(id="Close Short Ladder 2", from_entry="Short Ladder 2", stop=short_trailing_stop, limit=EMA_, when=close_short_entries) strategy.exit(id="Close Short Ladder 3", from_entry="Short Ladder 3", stop=short_trailing_stop, limit=EMA_, when=close_short_entries) strategy.exit(id="Close Short Ladder 4", from_entry="Short Ladder 4", stop=short_trailing_stop, limit=EMA_, when=close_short_entries) strategy.cancel(id="Short Ladder 1", when=cancel_entries) strategy.cancel(id="Short Ladder 2", when=cancel_entries) strategy.cancel(id="Short Ladder 3", when=cancel_entries) strategy.cancel(id="Short Ladder 4", when=cancel_entries) else strategy.entry(id="Short", direction=strategy.short, when=short_conditions_met) strategy.exit(id="Close Short", from_entry="Short", limit=EMA_, when=close_short_entries) strategy.cancel(id="Short", when=cancel_entries)