I. 전략 개요
이 전략은
II. 전략 원칙
지그자그 라인을 얻기 위해 볼링거 밴드를 사용하여 가격의 극한점을 식별합니다.
지그자그 선의 완전한 ABCD 패턴을 인식합니다. A, B, C 및 D 지점은 특정 비례 관계를 충족해야합니다. 적당한 ABCD 패턴을 식별 한 후 길거나 짧게 이동하십시오.
리스크를 제어하기 위해 포지션을 열고 후속 스톱 로스를 설정합니다. 먼저 고정 스톱 로스를 사용 하 여 특정 수익 수준에 도달 한 후 일부 이익을 잠금 하 고 후속 스톱 로스로 전환 합니다.
마찬가지로 후속 영업이익은 또한 충분한 수익을 확보하고 손실을 피하기 위해 설정됩니다. 후속 영업이익은 또한 두 단계로 작동합니다. 먼저 고정 영업이익, 그 다음 후속 영업이익.
가격이 마이너스 스톱 로스를 달성했을 때 포지션을 닫거나 거래 사이클을 끝내는 수익을 취합니다.
III. 이점 분석
지그자그 라인을 식별하기 위해 볼링거 밴드를 사용하면 전통적인 지그자그의 문제를 재칠하는 것을 피하고 거래 신호를 더 신뢰할 수 있습니다.
ABCD 패턴 거래 모델은 충분한 거래 기회와 함께 성숙하고 안정적입니다. 또한 위치 방향을 결정하는 것이 쉽습니다.
두 단계의 후속 스톱 로스 및 수익 취득 설정은 위험을 더 잘 제어하고 수익을 확보 할 수 있습니다. 후속 기능은 유연성을 제공합니다.
합리적인 매개 변수 설계로 스톱 로스, 영업이익 및 후속 활성화 비율은 모두 유연성을 위해 사용자 정의 할 수 있습니다.
이 전략은 외환, 암호화폐, 주식 지수 등 모든 거래 수단에 사용할 수 있습니다.
IV. 위험 분석
ABCD 패턴의 거래 기회는 다른 전략에 비해 여전히 제한되어 있으며 충분한 빈도를 보장하지 않습니다.
범위 시장에서 스톱 로스 및 영업이익은 자주 발생 할 수 있습니다. 스톱 로스 / 영업 범위의 확대와 같은 매개 변수는 조정되어야합니다.
거래 도구의 유동성은 주의가 필요합니다. 유동성 없는 제품에서는 미끄러짐이 고려되어야합니다.
이 전략은 거래 비용에 민감합니다. 낮은 수수료율의 중개사와 계좌가 선호됩니다.
일부 매개 변수들은 더 이상 최적화 될 수 있습니다. 예를 들어 후속 스톱 손실 및 수익을 취하기 위한 활성화 레벨과 같이. 최적의 값을 찾기 위해 더 많은 값을 테스트 할 수 있습니다.
V. 최적화 방향
더 많은 필터를 추가하기 위해 다른 지표와 결합하면 일부 잘못된 신호를 피하고 비효율적인 거래를 줄입니다.
세 부분의 시장 구조에 대한 판단을 추가하십시오. 세 번째 섹션에서 거래를만하십시오. 이것은 승률을 향상시킬 수 있습니다.
초기 자본을 테스트하고 최적화하여 최적의 수준을 찾습니다. 너무 크고 너무 작은 크기는 수익률을 손상시킵니다.
샘플 외의 데이터로 진행 분석을 수행하여 장기적으로 매개 변수의 안정성을 조사합니다.
활성화 조건과 슬라이프 크기를 최적화 하 고 효율성을 높이기 위해 수익을 취하십시오. 설정의 최적화는 결코 끝나지 않습니다.
VI. 전략 요약
이 전략은 주로 시장 타이밍 및 엔트리를 위해 ABCD 패턴에 의존합니다. 두 단계의 후속 스톱 손실 및 수익 설정은 위험과 이익을 관리하는 데 사용됩니다. 전략은 상대적으로 성숙하고 안정적이지만 거래 빈도는 낮을 수 있습니다. 필터와 조건을 추가함으로써 더 효율적인 거래 기회를 얻을 수 있습니다. 또한 추가 매개 변수 조정 및 자본 크기는 수익 안정성을 향상시킬 수 있습니다. 전반적으로 이것은 명확한 논리와 이해하기 쉬운 전략이며 실제 양적 거래에서 심층 연구와 응용을 가치가 있습니다.
/*backtest start: 2024-02-11 00:00:00 end: 2024-02-18 00:00:00 period: 1h basePeriod: 15m exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ // @version=4 // @author=Daveatt - BEST // ABCD Pattern Strat StrategyName = "BEST ABCD Pattern Strategy (Trailing SL + TP)" ShortStrategyName = "BEST ABCD Strategy (Trailing)" strategy(title=StrategyName, shorttitle=ShortStrategyName, overlay=true ) filterBW = input(false, title="filter Bill Williams Fractals?") /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// UTILITIES /////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // ||-----------------------------------------------------------------------------------------------------|| // ||--- Fractal Recognition Functions: ---------------------------------------------------------------|| isRegularFractal(mode, _high, _low) => ret = mode == 1 ? _high[4] < _high[3] and _high[3] < _high[2] and _high[2] > _high[1] and _high[1] > _high[0] : mode == -1 ? _low[4] > _low[3] and _low[3] > _low[2] and _low[2] < _low[1] and _low[1] < _low[0] : false isBWFractal(mode, _high, _low) => ret = mode == 1 ? _high[4] < _high[2] and _high[3] <= _high[2] and _high[2] >= _high[1] and _high[2] > _high[0] : mode == -1 ? _low[4] > _low[2] and _low[3] >= _low[2] and _low[2] <= _low[1] and _low[2] < _low[0] : false /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// ////////////////////////////// ABCD PATTERN /////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// f_abcd()=> _r = timeframe.period _g = barmerge.gaps_off _l = barmerge.lookahead_on _high = high _low = low filteredtopf = filterBW ? isRegularFractal(1, _high, _low) : isBWFractal(1, _high, _low) filteredbotf = filterBW ? isRegularFractal(-1, _high, _low) : isBWFractal(-1, _high, _low) // ||--- ZigZag: istop = filteredtopf isbot = filteredbotf topcount = barssince(istop) botcount = barssince(isbot) zigzag = (istop and topcount[1] > botcount[1] ? _high[2] : isbot and topcount[1] < botcount[1] ? _low[2] : na) x = valuewhen(zigzag, zigzag, 4) a = valuewhen(zigzag, zigzag, 3) b = valuewhen(zigzag, zigzag, 2) c = valuewhen(zigzag, zigzag, 1) d = valuewhen(zigzag, zigzag, 0) xab = (abs(b-a)/abs(x-a)) xad = (abs(a-d)/abs(x-a)) abc = (abs(b-c)/abs(a-b)) bcd = (abs(c-d)/abs(b-c)) // ABCD Part _abc = abc >= 0.382 and abc <= 0.886 _bcd = bcd >= 1.13 and bcd <= 2.618 _bull_abcd = _abc and _bcd and d < c _bear_abcd = _abc and _bcd and d > c _bull = _bull_abcd and not _bull_abcd[1] _bear = _bear_abcd and not _bear_abcd[1] [_bull, _bear, zigzag] lapos_x = timenow + round(change(time)*12) [isLong, isShort, zigzag] = f_abcd() plot(zigzag, title= 'ZigZag', color=color.black, offset=-2) plotshape(isLong, style=shape.labelup, location=location.belowbar, color=color.new(color.green, 0), size=size.normal, text="ABCD", textcolor=color.white) plotshape(isShort, style=shape.labeldown, location=location.abovebar, color=color.new(color.maroon, 0), size=size.normal, text="ABCD", textcolor=color.white) long_entry_price = valuewhen(isLong, close, 0) short_entry_price = valuewhen(isShort, close, 0) sinceNUP = barssince(isLong) sinceNDN = barssince(isShort) buy_trend = sinceNDN > sinceNUP sell_trend = sinceNDN < sinceNUP change_trend = (buy_trend and sell_trend[1]) or (sell_trend and buy_trend[1]) entry_price = buy_trend ? long_entry_price : short_entry_price /////////////////////////////// //======[ Trailing STOP ]======// /////////////////////////////// // use SL? useSL = input(true, "Use stop Loss") // Configure trail stop level with input StopTrailPerc = input(title="Trail Loss (%)", type=input.float, minval=0.0, step=0.1, defval=3) * 0.01 // Will trigger the take profit trailing once reached use_SL_Trigger = input(true, "Use stop Loss Trigger") StopTrailTrigger = input(2.0, "SL Trigger (%)",minval=0,step=0.5,type=input.float) * 0.01 StopLossPriceTrigger = 0.0 StopLossPriceTrigger := if (use_SL_Trigger) if buy_trend entry_price * (1 + StopTrailTrigger) else entry_price * (1 - StopTrailTrigger) else -1 var SL_Trigger_Long_HIT = false SL_Trigger_Long_HIT := useSL and use_SL_Trigger and buy_trend and high >= StopLossPriceTrigger ? true : SL_Trigger_Long_HIT[1] var SL_Trigger_Short_HIT = false SL_Trigger_Short_HIT := useSL and use_SL_Trigger and sell_trend and low <= StopLossPriceTrigger ? true : SL_Trigger_Short_HIT[1] display_long_SL_trigger = useSL and buy_trend and use_SL_Trigger and SL_Trigger_Long_HIT == false and StopLossPriceTrigger != -1 display_short_SL_trigger = useSL and sell_trend and use_SL_Trigger and SL_Trigger_Short_HIT == false and StopLossPriceTrigger != -1 display_SL_trigger = display_long_SL_trigger or display_short_SL_trigger plot(display_SL_trigger ? StopLossPriceTrigger : na, title='SLPriceTrigger', transp=0, color=color.maroon, style=plot.style_circles, linewidth=3) // Determine trail stop loss prices longStopPrice = 0.0, shortStopPrice = 0.0 longStopPrice := if useSL and buy_trend stopValue = low * (1 - StopTrailPerc) max(stopValue, longStopPrice[1]) else 0 shortStopPrice := if useSL and sell_trend stopValue = high * (1 + StopTrailPerc) min(stopValue, shortStopPrice[1]) else 999999 ////////////////////////////////////////////////////////////////////////////////////////// //*** STOP LOSS HIT CONDITIONS ***// ////////////////////////////////////////////////////////////////////////////////////////// cond_long_stop_loss_hit = useSL and buy_trend and crossunder(low, longStopPrice[1]) and (SL_Trigger_Long_HIT or use_SL_Trigger == false) cond_short_stop_loss_hit = useSL and sell_trend and crossover(high, shortStopPrice[1]) and (SL_Trigger_Short_HIT or use_SL_Trigger == false) // Plot stop loss values for confirmation plot(series=useSL and buy_trend and low >= longStopPrice and (SL_Trigger_Long_HIT or use_SL_Trigger == false) ? longStopPrice : na, color=color.fuchsia, style=plot.style_cross, linewidth=2, title="Long Trail Stop") plot(series=useSL and sell_trend and high <= shortStopPrice and (SL_Trigger_Short_HIT or use_SL_Trigger == false) ? shortStopPrice : na, color=color.fuchsia, style=plot.style_cross, linewidth=2, title="Short Trail Stop") /////////////////////////////// //======[ Take Profit ]======// /////////////////////////////// // Use TP? useTP = input(true, "Use take profit") // TP trailing ProfitTrailPerc = input(1.0, "Trailing Profit (%)",minval=0,step=0.5,type=input.float) * 0.01 use_TP_Trigger = input(true, "Use Take Profit Trigger") // Will trigger the take profit trailing once reached takeProfitTrigger = input(3.0, "Take Profit Trigger (%)",minval=0,step=0.5,type=input.float) * 0.01 // ttp := ttp>tp ? tp : ttp takeprofitPriceTrigger = 0.0 takeprofitPriceTrigger := if (use_TP_Trigger) if (buy_trend) entry_price * (1 + takeProfitTrigger) else entry_price * (1 - takeProfitTrigger) else -1 //plot(entry_price, title='entry_price', transp=100) var TP_Trigger_Long_HIT = false TP_Trigger_Long_HIT := useTP and use_TP_Trigger and buy_trend and high >= takeprofitPriceTrigger ? true : TP_Trigger_Long_HIT[1] var TP_Trigger_Short_HIT = false TP_Trigger_Short_HIT := useTP and use_TP_Trigger and sell_trend and low <= takeprofitPriceTrigger ? true : TP_Trigger_Short_HIT[1] display_long_TP_trigger = useTP and buy_trend and TP_Trigger_Long_HIT == false and takeprofitPriceTrigger != -1 display_short_TP_trigger = useTP and sell_trend and TP_Trigger_Short_HIT == false and takeprofitPriceTrigger != -1 display_TP_trigger = display_long_TP_trigger or display_short_TP_trigger //🔷🔷🔷 // @hugo: Will display the TP trigger as long as not hit // once the TP trigger is hit, the TP trailing will activate plot(display_TP_trigger ? takeprofitPriceTrigger : na, title='takeprofitPriceTrigger', transp=0, color=color.orange, style=plot.style_cross, linewidth=3) longTrailTP= 0.0, shortTrailTP = 0.0 // Trailing Profit // Start trailing once trigger is reached longTrailTP := if useTP and buy_trend tpValue = high * (1 + ProfitTrailPerc) max(tpValue, longTrailTP[1]) else 0 shortTrailTP := if useTP and sell_trend tpValue = low * (1 - ProfitTrailPerc) min(tpValue, shortTrailTP[1]) else 999999 //plot(longTrailTP, title='debug longTrailTP', transp=100) //plot(shortTrailTP, title='debug shortTrailTP', transp=100) ////////////////////////////////////////////////////////////////////////////////////////// //*** TRAILING TAKE PROFIT HIT CONDITIONS TO BE USED IN ALERTS ***// ////////////////////////////////////////////////////////////////////////////////////////// //🔷🔷🔷 // @hugo: I use crossover/crossunder for the alerts to trigger the events only once cond_long_trail_tp_hit = useTP and buy_trend and crossover(high, longTrailTP[1]) and (TP_Trigger_Long_HIT or use_TP_Trigger == false) cond_short_trail_tp_hit = useTP and sell_trend and crossunder(low, shortTrailTP[1]) and (TP_Trigger_Short_HIT or use_TP_Trigger == false) // 🔷🔷🔷 // Plot take profits values for confirmation // Display the trailing TP until not hit plot(series= useTP and buy_trend and high <= longTrailTP and (TP_Trigger_Long_HIT or use_TP_Trigger == false) ? longTrailTP : na, color=color.aqua, style=plot.style_circles, linewidth=2, title="Long Trail TP") plot(series= useTP and sell_trend and low >= shortTrailTP and (TP_Trigger_Short_HIT or use_TP_Trigger == false) ? shortTrailTP : na, color=color.aqua, style=plot.style_circles, linewidth=2, title="Short Trail TP") close_long = cond_long_trail_tp_hit or cond_long_stop_loss_hit close_short = cond_short_trail_tp_hit or cond_short_stop_loss_hit strategy.entry("Long", 1, when=isLong) strategy.close("Long", when=close_long) strategy.entry("Short", 0, when=isShort) strategy.close("Short", when=close_short) if change_trend SL_Trigger_Long_HIT := false SL_Trigger_Short_HIT := false TP_Trigger_Long_HIT := false TP_Trigger_Short_HIT := false