#공통, 전략
[설명]
볼린저 밴드 밖으로 크게 이탈한 강한 스윙 고/저점을 먼저 찾고
그 이후에 형성되는 되돌림 스윙(약한 고/저점) 을 기준으로
•
강한 고점 → 약한 저점 → 추세 재상승 롱 진입
•
강한 저점 → 약한 고점 → 추세 재하락 숏 진입
을 노리는 전략입니다.
진입 가격은 강/약 고저점 사이의 범위를 잘라서 일부 지점에 설정하고,
손절은 약한 고/저점 바로 위/아래에 두며,
수익 실현은 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
복사
