Search
Duplicate
📝

볼린저-스윙 리트레이스 전략

#공통, 전략
[설명]
볼린저 밴드 밖으로 크게 이탈한 강한 스윙 고/저점을 먼저 찾고 그 이후에 형성되는 되돌림 스윙(약한 고/저점) 을 기준으로
강한 고점 → 약한 저점 → 추세 재상승 롱 진입
강한 저점 → 약한 고점 → 추세 재하락 숏 진입
을 노리는 전략입니다.
진입 가격은 강/약 고저점 사이의 범위를 잘라서 일부 지점에 설정하고, 손절은 약한 고/저점 바로 위/아래에 두며, 수익 실현은 1차/2차 목표가 + 트레일링 스탑 구조로 이루어져 있습니다.
BarsToEnter로 패턴 발생 후 일정 시간(봉 수) 안에서만 진입하도록 제한해, 패턴발생 후 일정시간 이상이 경과하면 배제하게 됩니다.
Inputs: PatternLength(25), // 패턴을 인식할 최대 길이(봉 수). 강/약 고저점 관계를 찾는 기간 Strength(7), // SwingHigh/SwingLow 함수에 들어가는 스윙 강도(좌우 몇 봉 비교할지) BarsToEnter(10), // 패턴 포착 후 실제 진입 가능 기간(최대 몇 봉 안에서 진입할지) Length(11), // 볼린저 밴드 계산 기간 Deviations(2), // 볼린저 밴드 표준편차 수 Trading(2), // 기본 진입 계약 수(포지션 사이즈) EntryPriceDivisor(4), // 진입 가격을 계산할 때 사용하는 분모 (가격 범위 / EntryPriceDivisor) Target1Divisor(2), // 1차 목표가 계산 시 사용하는 분모 TrailingStopDivisor(4); // 트레일링 스탑 폭 계산 시 사용하는 분모 Variables: StrongLow(0), StrongHigh(0), // 강한 저점/고점 가격 (볼밴 바깥에서 발생한 swing low/high) WeakLow(0), WeakHigh(0), // 그 이후 형성된 약한 저점/고점 가격 (패턴의 기준점) StrongLowBar(0), StrongHighBar(0), // 강한 저점/고점이 형성된 후 경과한 봉 수(카운터 역할) WeakLowBar(99999), WeakHighBar(99999), // 약한 저점/고점의 봉 카운터(초기 큰값) LongEntryPrice(99999), LongExitPrice(0), LongTarget1(0), LongTarget2(0), // 롱 진입/청산/목표가 ShortEntryPrice(0), ShortExitPrice(0), ShortTarget1(0), ShortTarget2(0), // 숏 진입/청산/목표가 RecentLow(0), RecentHigh(0), // 최근에 발견된 스윙 저점/고점의 인덱스 FoundAWeakLow(False), FoundAWeakHigh(False), // 약한 저점/고점을 찾았는지 여부 플래그 Offset(Strength), // 스윙 인덱스 오프셋(여기선 Strength와 동일) TrailStopDrop(0), TrailStopRise(0), // 롱/숏 트레일링 스탑 폭 LongTrailingTrigger(0), ShortTrailingTrigger(0), // 트레일링 스탑이 활성화될 트리거 가격 HighClose(0), LowClose(99999), // 진입 후 최고 종가(롱) / 최저 종가(숏) BuyCounter(0), SellCounter(0), // 패턴 발생 후 몇 봉 지났는지 카운터 (진입 가능 기간 관리) MakeLongTrade(False), MakeShortTrade(False), // 현재 봉에서 롱/숏 진입 시도 여부 LongTrailStop(False), ShortTrailStop(False), // 롱/숏 트레일링 스탑 활성화 여부 UpperBand(0), LowerBand(0); // 볼린저 상단/하단 밴드 // 볼린저 밴드 계산 UpperBand = BollBandUp(Length, Deviations); // 상단 밴드 LowerBand = BollBandDown(Length, Deviations); // 하단 밴드 // 강한 고점/저점 바 카운터 증가 (패턴 유효 기간 안에서만 카운트 증가) StrongHighBar = IFF(StrongHighBar <= PatternLength + Strength, StrongHighBar + 1, StrongHighBar); StrongLowBar = IFF(StrongLowBar <= PatternLength + Strength, StrongLowBar + 1, StrongLowBar); // ────────────────────────────────────────────────────────────── // 1) 강한 고점(StrongHigh)을 찾고, 그 이후 최근 약한 저점(WeakLow)을 탐색 // ────────────────────────────────────────────────────────────── If SwingHigh(1, High, Strength, Strength, Strength*2 + 1) <> -1 // 스윙 고점이 존재하고 AND High[Strength] > UpperBand[Strength] Then // 그 스윙 고점이 볼린저 상단 위에 있을 때 { StrongHigh = SwingHigh(1, High, Strength, Strength, Strength*2 + 1); // 강한 고점 가격 StrongHighBar = Strength; // 강한 고점 발생 후 경과봉 수를 Strength로 설정(기준점) // 강한 고점 이후에 형성된 최근 스윙 저점을 찾음 (MRO: Most Recent Occurrence) RecentLow = MRO( SwingLow(1, Low, Strength, Strength, Strength*2 + 1) <> -1, StrongLowBar - StrongHighBar, 1 ); If RecentLow <> -1 Then { FoundAWeakLow = True; // 약한 저점 패턴 발견 WeakLow = SwingLow(1, Low, Strength, Strength, Strength*2 + 1)[RecentLow]; // 그 최근 스윙 저점 가격 WeakLowBar = RecentLow + Strength; // 약한 저점이 발생한 봉까지의 카운트 } } // ────────────────────────────────────────────────────────────── // 2) 강한 저점(StrongLow)을 찾고, 그 이후 최근 약한 고점(WeakHigh)을 탐색 // ────────────────────────────────────────────────────────────── If SwingLow(1, Low, Strength, Strength, Strength*2 + 1) <> -1 // 스윙 저점이 존재하고 AND Low[Strength] < LowerBand[Strength] Then // 그 스윙 저점이 볼린저 하단 아래에 있을 때 { StrongLow = SwingLow(1, Low, Strength, Strength, Strength*2 + 1); // 강한 저점 가격 StrongLowBar = Strength; // 강한 저점 발생 후 경과봉 수 초기화 // 강한 저점 이후에 형성된 최근 스윙 고점을 찾음 RecentHigh = MRO( SwingHigh(1, High, Strength, Strength, Strength*2 + 1) <> -1, StrongHighBar - StrongLowBar, 1 ); If RecentHigh <> -1 Then { FoundAWeakHigh = True; // 약한 고점 패턴 발견 WeakHigh = SwingHigh(1, High, Strength, Strength, Strength*2 + 1)[RecentHigh]; // 그 최근 스윙 고점 가격 WeakHighBar = RecentHigh + Strength; } } // ────────────────────────────────────────────────────────────── // 강한 저점/고점이 패턴 유효기간(PatternLength + Strength) 안에 있는지 조건 // ────────────────────────────────────────────────────────────── Condition1 = StrongLowBar < PatternLength + Strength; // 롱 패턴 유효 조건 Condition2 = StrongHighBar < PatternLength + Strength; // 숏 패턴 유효 조건 // ────────────────────────────────────────────────────────────── // 3) 롱 패턴이 완성되었을 때(강한 고점 이후 약한 저점 발생) 진입/청산 가격 설정 // ────────────────────────────────────────────────────────────── If FoundAWeakLow AND Condition1 Then { // 롱 진입 가격: 강한 고점 - 강한 저점 범위를 EntryPriceDivisor로 나눈 값을 WeakLow 위에 더한 위치 If EntryPriceDivisor <> 0 Then LongEntryPrice = ((StrongHigh - StrongLow) / EntryPriceDivisor) + WeakLow; // 손절(or 강제 청산) 가격: WeakLow 바로 아래 (WeakLow - 1) LongExitPrice = WeakLow - 1; // 2차 목표가: WeakLow + (StrongHigh - StrongLow) → 강한 고점까지의 폭만큼 위 LongTarget2 = WeakLow + (StrongHigh - StrongLow); // 1차 목표가는 WeakLow와 LongTarget2의 중간값 (Target1Divisor로 나눔, 기본 2 → 평균) If Target1Divisor <> 0 Then LongTarget1 = (WeakLow + LongTarget2) / Target1Divisor; // 롱 트레일링 스탑이 시작되는 트리거(기준 고점) LongTrailingTrigger = StrongHigh; // 트레일링 스탑 폭: (StrongHigh - WeakLow) / TrailingStopDivisor If TrailingStopDivisor <> 0 Then TrailStopDrop = (StrongHigh - WeakLow) / TrailingStopDivisor; // 이후 BarsToEnter 안에서만 진입 허용하기 위해 카운터 초기화 BuyCounter = 0; MakeLongTrade = True; // 롱 진입 시도 플래그 ON MakeShortTrade = False; // 숏 진입은 동시에 하지 않도록 OFF } // ────────────────────────────────────────────────────────────── // 4) 숏 패턴이 완성되었을 때(강한 저점 이후 약한 고점 발생) 진입/청산 가격 설정 // ────────────────────────────────────────────────────────────── If FoundAWeakHigh AND Condition2 Then { // 숏 진입 가격: WeakHigh 위에서 (StrongHigh - StrongLow)/EntryPriceDivisor 만큼 아래 If EntryPriceDivisor <> 0 Then ShortEntryPrice = WeakHigh - ((StrongHigh - StrongLow) / EntryPriceDivisor); // 손절(or 강제 청산) 가격: WeakHigh 바로 위 ShortExitPrice = WeakHigh + 1; // 2차 목표가: WeakHigh - (StrongHigh - StrongLow) → 강한 저점 방향으로 동일 폭 ShortTarget2 = WeakHigh - (StrongHigh - StrongLow); // 1차 목표가는 WeakHigh와 ShortTarget2의 중간값 If Target1Divisor <> 0 Then ShortTarget1 = (WeakHigh + ShortTarget2) / Target1Divisor; // 숏 트레일링 스탑 트리거: StrongLow ShortTrailingTrigger = StrongLow; // 트레일링 스탑 폭: (WeakHigh - StrongLow) / TrailingStopDivisor If TrailingStopDivisor <> 0 Then TrailStopRise = (WeakHigh - StrongLow) / TrailingStopDivisor; // BarsToEnter 관리용 카운터 초기화 SellCounter = 0; MakeShortTrade = True; // 숏 진입 시도 플래그 ON MakeLongTrade = False; // 롱 진입은 동시에 하지 않도록 OFF } // 약한 고/저점 탐색 플래그는 한 번 사용 후 다시 초기화 (다음 봉에서 새로 탐색하도록) FoundAWeakLow = False; FoundAWeakHigh = False; // ────────────────────────────────────────────────────────────── // 5) 포지션이 없을 때(평단 상태) 진입 조건 관리 및 실제 진입 주문 // ────────────────────────────────────────────────────────────── If MarketPosition() == 0 Then { // 패턴 완성 후 BarsToEnter 봉 동안만 롱 진입 허용 If BuyCounter < BarsToEnter Then BuyCounter = BuyCounter + 1; Else MakeLongTrade = False; // 패턴 완성 후 BarsToEnter 봉 동안만 숏 진입 허용 If SellCounter < BarsToEnter Then SellCounter = SellCounter + 1; Else MakeShortTrade = False; // 롱 진입 플래그가 살아있으면 지정된 진입가격에 스탑 주문 If MakeLongTrade Then Buy("Buy2", AtStop, LongEntryPrice, Trading); // 숏 진입 플래그가 살아있으면 지정된 진입가격에 스탑 주문 If MakeShortTrade Then Sell("Sell2", AtStop, ShortEntryPrice, Trading); } // ────────────────────────────────────────────────────────────── // 6) 롱 포지션 관리(부분 청산 + 트레일링 스탑 등) // ────────────────────────────────────────────────────────────── If MarketPosition() == 1 Then { MakeLongTrade = False; // 이미 롱 보유 중이므로 추가 진입은 하지 않음 // 진입 직후: 아직 전체 계약(Trading) 수량을 보유 중인 상태 If CurrentContracts == Trading Then { LongTrailStop = False; // 트레일링 스탑 비활성화 상태로 시작 HighClose = 0; // 최고 종가 초기화 // 기본 손절 주문 (WeakLow 아래 LongExitPrice에 스탑) ExitLong("LDump1", AtStop, LongExitPrice); // 1차 목표가 도달 시 절반 청산 (Trading/2) ExitLong("LTarget1", AtLimit, LongTarget1, "", Trading/2, 1); } Else { // 부분 청산(1차 목표가 청산) 이후 남은 물량 관리 // 진입 이후의 최고 종가 갱신 If Close > HighClose Then HighClose = Close; // 본전 보호: 남은 물량에 대해 진입가로 스탑 설정 ExitLong("LProtect2", AtStop, EntryPrice()); // 가격이 트레일링 트리거(StrongHigh) 위로 올라가면 트레일링 스탑 활성화 If HighClose > LongTrailingTrigger Then LongTrailStop = True; // 트레일링 스탑이 활성화되면 HighClose - TrailStopDrop까지 스탑을 끌어올림 If LongTrailStop Then ExitLong("LTrail", AtStop, HighClose - TrailStopDrop); // 2차 목표가 도달 시 나머지 물량 청산 ExitLong("LTarget2", AtLimit, LongTarget2); } } // ────────────────────────────────────────────────────────────── // 7) 숏 포지션 관리(부분 청산 + 트레일링 스탑 등) // ────────────────────────────────────────────────────────────── If MarketPosition() == -1 Then { MakeShortTrade = False; // 이미 숏 보유 중이므로 추가 숏 진입은 하지 않음 // 진입 직후: 전체 계약 수량 보유 상태 If CurrentContracts == Trading Then { ShortTrailStop = False; // 트레일링 스탑 비활성화 LowClose = 99999; // 최저 종가 초기화(큰 값으로 시작) // 기본 손절 주문 (WeakHigh 위 ShortExitPrice에 스탑) ExitShort("SDump1", AtStop, ShortExitPrice); // 1차 목표가 도달 시 절반 청산 ExitShort("STarget1", AtLimit, ShortTarget1, "", (Trading / 2), 1); } Else { // 부분 청산 후 남은 물량 관리 // 최저 종가 갱신 If Close < LowClose Then LowClose = Close; // 본전 보호: 남은 물량에 대해 진입가로 스탑 설정 ExitShort("SProtect 2", AtStop, EntryPrice); // 가격이 트레일링 트리거(StrongLow) 아래로 내려가면 트레일링 스탑 활성화 If LowClose < ShortTrailingTrigger Then ShortTrailStop = True; // 트레일링 스탑이 활성화되면 LowClose + TrailStopRise까지 스탑을 내려줌 If ShortTrailStop Then ExitShort("STrail", AtStop, LowClose + TrailStopRise); // 2차 목표가 도달 시 나머지 물량 청산 ExitShort("STarget2", AtLimit, ShortTarget2); } }
JavaScript
복사