NT8 UltTripleSyncPro_v2 → 한선씨 이식 설계
2026-08-01. NinjaTrader 8용으로 실사용 중인 3TF 동조 전략의 신호 생성 로직을 맥 네이티브(한선씨/TOAU)로 이식하기 위한 설계·매핑·정직도 표기.>
구현 산출물:/Users/ef/CrownyDoc/projects/kps-trading-tool/전략트리플싱크.한선(컴파일CROWNY_STRICT=1경고 0 / 자체시험 21건 전건 PASS / 주문·실행 호출 0)
0. 원본 파일과 확보 범위
| 원본 | 경로 | 소스 확보 |
|---|---|---|
| 전략 | crowny-trading/ninjatrader/Strategies/UltTripleSyncPro_v2.cs (992줄) | ✅ 전문 |
| SMC 오더블록 인디케이터 | UltSMCOrderBlocks_260503.zip → Indicators/UltSMCOrderBlocks.cs (332줄) | ✅ 전문 |
| 칼만 인디케이터 | UltKalmanV2_260430.zip → UltKalmanV2_260430.cs + .dll | ⚠️ .cs는 NinjaScript 생성 래퍼뿐, 실제 알고리즘은 DLL 안(비공개) |
| NT8 Add-On | ninjatrader/CrownyAddon/CrownyAddon.cs (578줄) | ✅ 전문 — 신호 로직 없음(감시·리스크게이트·텔레그램·UI 전용) |
1. 전략 골자 — 수식 수준
1.1 3 타임프레임 구성
| TF | NT8 데이터시리즈 | 역할 |
|---|---|---|
| TF1 | 주 차트(BarsArray[0], 틱) | 트리거 — 칼만 상태전환 / 신규 OB |
| TF2 | AddDataSeries(Tick, 512) | 필터(스티키) — 칼만·OB 상태가 같은 방향이어야 통과 |
| TF3 | AddDataSeries(Minute, 1) | 필터(스티키) |
OnBarUpdate 분기에서 상태만 갱신하고 즉시 return → 값이 다음 TF1 봉까지 유지(스티키)된다.1.2 칼만 상태 전이 (원본 UpdateKalmanState, 992줄본 580–599)
입력: shortK0 = Values[1][0](단기 칼만 현재), shortK2 = Values[1][2](단기 2봉 전), longK0 = Values[0][0](장기 칼만 현재), isPPUp = Values[2][0] ≠ 0/NaN, isPPDown = Values[3][0] ≠ 0/NaN.
가드: CurrentBar < 5 → 상태 갱신 안 함(직전 상태 유지)
가드: shortK0/longK0 가 NaN 또는 0 → 갱신 안 함
trendUp := shortK0 > longK0
trendUp ∧ (shortK0 > shortK2) → 상태 = +1 (롱)
¬ trendUp ∧ (shortK0 < shortK2) → 상태 = -1 (숏)
그 외: isPPUp → +1
isPPDown → -1
아니면 → 0 (중립)
주의: 두 주분기 어느 쪽도 아닐 때만 PP가 개입하는 폴백 구조다(PP가 주신호가 아님).
1.3 OB(오더블록) 상태 (원본 UpdateSMCState, 601–624) — TF2/TF3용
currBull := i=0..3 중 NearestBullOB_Bottom[i] > 0 인 최초값 (없으면 0)
currBear := i=0..3 중 NearestBearOB_Top[i] > 0 인 최초값 (없으면 0)
상태 == 0 이면: currBull>0 → +1, 아니면 currBear>0 → -1
newBull := currBull>0 ∧ currBull ≠ lastBull → 참이면 상태 = +1
newBear := currBear>0 ∧ currBear ≠ lastBear → 참이면 상태 = -1
currBull>0 → lastBull = currBull ; currBear>0 → lastBear = currBear
즉 OB 상태는 한 번 켜지면 반대 신규 OB가 나올 때까지 유지되는 래치다(중립으로 되돌아가지 않음).
1.4 TF1 신규 OB 판정 (원본 795–808) — TF2/TF3와 규칙이 다름
scanBull := i=0..3 중 첫 양수 NearestBullOB_Bottom[i]
isNewBullOB := (lastBullOB_TF1 ≠ 0) ∧ (scanBull > 0) ∧ (scanBull ≠ lastBullOB_TF1)
(숏 대칭: scanBear / NearestBearOB_Top)
★ lastBullOB_TF1 ≠ 0 조건 때문에 세션 최초 OB는 트리거가 되지 않는다(직전 기준값이 있어야 "갱신"으로 인정). 이식본도 그대로 재현했다.
1.5 진입 결합식 (원본 783–836) — 이식의 핵심
tf2_Long := ¬use_tf2 ∨ ((¬TF2_UseKalman ∨ kState_TF2 == +1) ∧ (¬TF2_UseSMC ∨ obState_TF2 == +1))
tf3_Long := (동형)
kalmanTurnedLong := (kState_TF1 == +1) ∧ (prev_kState_TF1 ≠ +1) // 봉 시작 시점 스냅샷과 비교
triggerLong := (TF1_UseKalman ∧ kalmanTurnedLong) ∨ (TF1_UseSMC ∧ isNewBullOB)
진입롱 ⟸ tf2_Long ∧ tf3_Long ∧ triggerLong
진입숏 ⟸ tf2_Short ∧ tf3_Short ∧ triggerShort (롱이 우선 — else-if)
사유 문자열도 3분기 그대로: [TF1 칼만 + 롱 OB 갱신] / [TF1 칼만 롱 전환] / [TF1 롱 OB 갱신].
1.6 진입 전 통과해야 하는 게이트 (원본 739–781, 순서대로)
수동청산요청 없음 → IsStrategyEnabled → ¬일일한도도달 → ¬하드킬존 → 거래시간 내 →
(현재봉시각 − 마지막청산시각) > EntryResumeSeconds(3초) → 포지션 플랫 → ¬복구중(재연결 후 20봉).
이 게이트들은 운영 상태기계이지 신호가 아니다 → 이식 1단계 범위에서 제외(§3 매핑표 참조).
1.7 SMC 오더블록 산출 (UltSMCOrderBlocks.cs — 확인됨, 1:1 이식)
프랙탈(3봉 모드, 기본값)
isFractalHigh := High[1] > High[0] ∧ (High[2] < High[1] ∨ (High[2]==High[1] ∧ High[3]<High[2]))
isFractalLow := Low[1] < Low[0] ∧ (Low[2] > Low[1] ∨ (Low[2]==Low[1] ∧ Low[3] >Low[2]))
저장값 = High[1] / Low[1] (off=1), 최대 10개 FIFO
돌파 → OB 생성 (기준 BreakType=Close)
불(Bullish) OB는 프랙탈 고점을 종가가 상향 돌파할 때 만들어진다:
Close[0] > 프랙탈고값 이면:
k = 0..99 (그리고 Time[k] ≥ 프랙탈시각):
bullishGap := (Close[k+1] > High[k+2]) ∧ (Low[k] > High[k+2]) → gIdx = k+2 (마지막=가장 과거 갭이 남음)
if Close[k] < Open[k] ∧ Low[k] < min → idx = k, min = Low[k] (구간 내 최저저가 음봉)
FVG 필터(기본 ON): gIdx > 0 ∧ 0 ≤ idx-gIdx ≤ FvgDistance(3)
OB: Top = Open[idx] (Body 모드) , Bottom = Low[idx] , IsBullish = true
베어 OB는 프랙탈 저점 하향 돌파 시 대칭(단 if(bearishGap && High[k]>max) gIdx=k+2 — 원본 베어 분기에만 High[k]>max 조건이 함께 붙어 있다. 이식본은 이 비대칭을 그대로 두지 않고 불 분기와 동일한 형태로 정규화했다 → §4-C 차이표 참조).미티게이션 / 최근 OB
불 OB: Low[0] ≤ Top ∧ Low[0] ≤ Bottom → mitigated
베어 OB: High[0] ≥ Bottom ∧ High[0] ≥ Top → mitigated
보유 상한 MaxOBs=30 초과 시 가장 오래된 것부터 제거
NearestBullOB_Bottom = 미티 안 된 불 OB 중 |Close[0] − Bottom| 최소인 것의 Bottom
NearestBearOB_Top = 미티 안 된 베어 OB 중 |Close[0] − Top| 최소인 것의 Top
2. 한선씨 구현 구조
파일: kps-trading-tool/전략트리플싱크.한선 (11,852 큐브)
| 함수 | 역할 |
|---|---|
칼만1차채움(관측, 개수, Q, R, 출력) | 1차원 칼만 — 정수 스케일. 재호출 안전(호출자 버퍼) |
칼만1차(관측, Q, R) | 스펙 시그니처 래퍼. 공유 버퍼 칼만출력 반환 |
ATR채움 / PP채움 | ATR(10) 정수 SMA + 피벗포인트 밴드 → 버퍼PP ∈ {+1,0,-1} |
칼만상태판정(봉배열) | §1.2 전이식 그대로 → [현재상태, 직전봉상태] |
오더블록탐지(봉배열) | §1.7 전체 + §1.3/§1.4 → [OB상태, 신규불, 신규베어, 최근불바텀, 최근베어탑, 활성OB수] |
TF필터(봉배열, 기간) | 기간>1이면 OHLC 리샘플 후 → [칼만상태, OB상태] |
트리플결합(k1,k1직전,신규불,신규베어,k2,ob2,k3,ob3) | §1.5 결합식 (순수 함수) |
트리플싱크판정(TF1봉,TF2봉,TF3봉) | 위를 엮은 최종 판정 → [행동, 방향, 사유, 발화] |
칼만Q단=40 · 칼만Q장=6 · 칼만R=1000 · PP피벗기간=2 · PPATR기간=10 · PPATR팩터백=300 · OB룩백=100 · OB최대유지=30 · FVG필터=1 · FVG거리=3 · OB스캔깊이=3 · TF1/2/3기간 · 쿨다운초=3정수 전용(float 금지) 설계
- 가격은 정수 틱. 칼만 내부 상태는 ×1000 밀리스케일 정수.
- 칼만 이득
K는 ×1000 고정소수점:K = Pp*1000/(Pp+R),x += K*(z−x)/1000,P = (1000−K)*Pp/1000. - crownyc 나눗셈은 자연반올림(floor 아님)이므로 전 구간을 자체
나누기(a,b)절단 나눗셈 헬퍼로 통과시킨다(부호 분리 후 보정 루프). - 중간곱 최대치는 5e8 수준 → 3^24 오버플로 및 2.147e9 문자열핸들 충돌지대 모두 회피.
회피한 VM 함정 (실제로 물렸거나 예방한 것)
- 함수 반환 배열/지역 배열 재사용 함정 → 결과는 전부 최상위 사전할당 전역 버퍼 +
설정()으로 처리. 그리고안에서 사용자 함수 2회 이상 인라인 호출 → 봉 접근값을 전부 변수 선캡처 후 비교.- 배열 1023칸 상한 → 봉배열 평탄 4필드 구성으로 최대 200봉(=800칸)으로 명시 제한.
- 루프 카운터는 bare 증가(
i = i + 1), 비교식 변수 대입 금지, 주석은 파일 헤더에만. - 자체시험은
env SELFTEST=1게이트 —가져오기시 오염되지 않음.
3. NT8 의존 요소 → 한선씨 대체 1:1 매핑
| # | NT8 요소 | 정체 | 한선씨 대체 | 상태 |
|---|---|---|---|---|
| 1 | UltKalmanV2 Values[0]/[1] | 장기/단기 칼만 라인 | 칼만1차채움(…, 칼만Q장/칼만Q단, 칼만R, …) | ⚠️ 근사 |
| 2 | UltKalmanV2 Values[2]/[3] | PP 상승/하락 라인 | PP채움() — 피벗(2) + ATR(10)×3.0 밴드 | ⚠️ 근사 |
| 3 | UltSMCOrderBlocks.NearestBullOB_Bottom/BearOB_Top | 최근접 미티 안 된 OB | 오더블록탐지() 전체 이식 | ✅ 확인 |
| 4 | AddDataSeries(Tick,512) / (Minute,1) | 상위 TF 시리즈 | TF필터(봉배열, 기간) + 봉묶기() OHLC 리샘플 | ✅ 등가(단 §4-D) |
| 5 | ATR 내장 | 인디케이터 | ATR채움() — TR max 3식 + 정수 SMA | ✅ 확인(단 NT8 ATR 기본은 Wilder EMA → §4-B) |
| 6 | CurrentBar / Time[i] / High[i] 역인덱스 | 바 접근 | 정인덱스 평탄배열 + 봉고/봉저/봉시/봉종 | ✅ 등가 |
| 7 | EnterLong/EnterShort/SetStopLoss/SetProfitTarget | 주문 | 이식 안 함(판정만) — 상위 실행기 책임 | 의도적 제외 |
| 8 | Position/Account/GetRealizedPnL/일일한도 | 계좌·리스크 | 기존 자산 kps_상태기계.한선·kps_사이징.한선·kps_라이브락_엣지.한선 | 재사용 예정 |
| 9 | Watchdog·연결복구·Heartbeat·텔레그램·WPF UI | 운영 안전장치 | kps_허브.한선·세션감시.한선·폰푸시채널.한선 계열 | 범위 밖 |
| 10 | 세션시간/하드킬/일일리셋(시·분 정수 비교) | 스케줄 게이트 | kps_상태기계.한선 가드 슬롯으로 흡수 | 범위 밖 |
4. 미확인 / 근사 구현 목록 (정직 표기)
A. 칼만 재귀식 — 미확인, 근사 구현
- 아는 것: 호출 시그니처
UltKalmanV2(bars, shortLen=50, longLen=120, candleColor=true, pivotPeriod=2, atrFactor=3.0, atrPeriod=10, showKalmanLines, showPPLines). DLL 문자열에서 확인한 플롯/속성 라벨:1. Short Length,2. Long Length,1. PP Pivot Period,2. PP ATR Factor,3. PP ATR Period, 플롯 4개(0=장기,1=단기,2/3=PP), 내부cacheATR사용. - 모르는 것: 프로세스잡음 Q·측정잡음 R을
shortLen/longLen에서 어떻게 유도하는지, 상수속도(위치+속도 2상태) 모델인지 상수위치(1상태)인지, 관측이 Close인지 HL2/Typical인지. - 근사 방식: 관측 = 종가, 모델 = 1상태 상수위치 칼만,
R고정(1000)에Q만 단기/장기로 나눠 반응속도를 벌린다(Q단=40,Q장=6). 정상상태 이득은K ≈ (√(Q²+4QR) − Q)/(2R)꼴로 수렴 — 길이 파라미터 대신 Q/R 비가 평활 강도를 정한다. - 한계: 두 라인의 교차 시점·기울기 반응이 원본과 봉 단위로 어긋날 수 있다. 즉
kalmanTurnedLong발생 봉이 원본과 다를 수 있고, 이는 진입 시점 차이로 직결된다. Q단/Q장은 백테스트로 원본 상태열에 맞춰 캘리브레이션해야 하는 값이지 검증된 값이 아니다. - 해소 방법(권장 순): ① NT8에서 두 칼만 라인을 CSV로 export → 같은 봉 입력으로 이식본과 상태열 일치율 측정 → Q 그리드 탐색 ② 그래도 안 맞으면 DLL IL 디컴파일 검토 ③ 원저자 소스 확보.
B. PP(피벗포인트) 라인 — 미확인, 근사 구현
- 아는 것: 파라미터가
PivotPeriod=2,AtrFactor=3.0,AtrPeriod=10이고 상승/하락 두 플롯으로 나온다는 것. → 통칭 Pivot Point SuperTrend 계열로 보이나 확정 불가. - 근사 방식:
피벗고/피벗저(좌우 2봉 엄격 극값) 발생 시 중심선center = (center*2 + pivot)/3, 밴드center ± ATR(10)*3.0, 종가가 상단 초과=상승/하단 미만=하락, 그 외 직전 방향 유지. - 한계: 중심선 갱신 규칙(2:1 가중)과 방향 플립 조건은 관례를 채택한 것이며 원본과 같다는 근거가 없다. 다만 §1.2대로 PP는 폴백 경로에서만 쓰이므로 영향 범위는 칼만 라인보다 작다.
C. SMC 베어 분기 비대칭 — 원본과 의도적으로 다르게 한 1곳
원본 C#의 불 분기는if (bullishGap) gIdx = k+2;인데 베어 분기만 if (bearishGap && High[k] > max) gIdx = k+2;로 High[k] > max가 덧붙어 있다(불 분기엔 대응 조건 없음). 원저자 오타로 보이나 확증 불가 → 이식본은 양 방향을 대칭으로 정규화했다. 원본 거동을 100% 재현해야 한다면 이 한 줄을 되살려야 한다.D. 타임프레임 리샘플 — 구조적 근사
원본 TF2는 512틱 봉, TF3는 1분봉으로 NT8이 직접 만든다. 이식본TF필터(봉,기간)는 기본 시리즈를 N개씩 묶는 고정배수 리샘플이라, 틱봉↔시간봉 경계가 원본과 정확히 일치하지 않는다. 실전 정합을 원하면 TF2/TF3 봉을 데이터 소스에서 각각 별도로 공급(트리플싱크판정에 이미 3개 봉배열을 따로 받도록 설계)하는 쪽이 정답이고, TF필터(…, 기간)는 단일 소스만 있을 때의 보조 경로다.E. 미이식(의도적) — 신호가 아닌 것
주문 실행, SL/TP 300틱, 일일 손실 $900/목표 $1200, 세션·하드킬 시간창, 3초 쿨다운(파라미터만 보유), Watchdog/Heartbeat/연결복구, 텔레그램, WPF UI, 프랍 일일 리셋.5. 자체시험 (21/21 PASS)
bashcd /Users/ef/CrownyOS/crownyc
CROWNY_STRICT=1 ./hanseonc_high /Users/ef/CrownyDoc/projects/kps-trading-tool/전략트리플싱크.한선 > /tmp/tsync.toau
env SELFTEST=1 ./crownyc run /tmp/tsync.toau
| 군 | 케이스 |
|---|---|
| 칼만 수렴 | 상승 시계열 40봉 → 상태 +1 / 하락 40봉 → −1 / 평탄 40봉 → 0 / 칼만1차 재호출 안전성 |
| OB 탐지 | 합성 불 OB(프랙탈고 돌파+FVG) → 바텀 90·상태 +1·활성 1 / 가격 미러링한 베어 케이스 → 탑 210·상태 −1 / OB 없는 평탄 → 0 |
| TF 필터 | 기간1(상승)=+1 / 기간4 리샘플(하락)=−1 / 기간2(평탄) OB=0 |
| 트리플 결합 | 롱 진입·숏 진입·TF3 차단·칼만 전환 없음 차단·신규불OB 단독 트리거·전중립 대기 |
| 통합 | 트리플싱크판정 실봉 3종 입력 정상 판정 |
idx ≥ gIdx가 성립해야 한다). 테스트를 코드에 맞춘 게 아니라 원본 조건을 만족하도록 봉을 다시 설계해서 통과시켰다.6. 재사용한 기존 한선씨 자산
| 자산 | 재사용 형태 |
|---|---|
crowny-trader/한선씨/kps/kps_상태기계.한선 | 일일한도·트레일링DD·쿨다운·연승 트리거 = 원본의 운영 게이트(§1.6) 대체처. 신규 구현 안 함 |
kps_사이징.한선 | 계약수 캡(원본 TradeQuantity 고정 1 대체) |
kps_라이브락_엣지.한선 | 실자본 진입 차단 — 이 이식본이 판정만 하고 주문을 안 하는 이유와 정확히 같은 원칙 |
kps_장세분류.한선 | TF2/TF3 필터의 상위 개념(장세) 태깅 — 백테스트 시 조건부 승률 분해에 사용 |
kps_nt8매핑.한선 | NT8 CSV/이벤트 → 저널행. 백테스트 데이터 공급 경로로 그대로 활용 가능 |
| 코딩 관례 | 위 모듈들의 "코드=산술 / 셀코어=선언적 게이트" 분업, 절단 나눗셈 클램프 관례 답습 |
7. 다음 단계 — 필요한 것
- 백테스트 데이터 요건 (최우선)
시각,시가,고가,저가,종가 (가격은 정수 틱 환산 — 소수 금지). 3개 파일(TF1 틱봉 / TF2 512틱봉 / TF3 1분봉)을 각각 받는 것이 정합상 최선(§4-D).
- 기간: 최소 3개월, 세션시간(07:05–18:55) 포함. 심볼은 실거래 대상(ES/NQ 등) 1종부터.
- 한선씨 측 제약: 배열 1023칸 → 1회 판정 입력 200봉. 긴 구간은 슬라이딩 윈도우로 공급하는 러너가 별도로 필요하다.
- 칼만 캘리브레이션 데이터 — NT8에서
UltKalmanV24개 플롯값을 봉별로 CSV export. 이게 있어야 §4-A의 "근사"를 "정합 측정된 근사"로 승격할 수 있다. 없으면 Q단/Q장은 계속 추정치다. - 슬라이딩 윈도우 백테스트 러너(.한선) — 봉 스트림 → 200봉 윈도우 →
트리플싱크판정→ 신호 로그 PSV. 여기에 §1.6 운영 게이트(kps_상태기계)를 결선. - 원본 대조 리포트 — 같은 구간에서 NT8 전략 로그의 진입 시각 목록 vs 이식본 발화 시각 목록의 일치율. 이 수치가 나오기 전에는 "이식 완료"가 아니라 "이식 초안"이다.
- 결정 사항 확인 필요(사장님) — §4-C 베어 분기 비대칭을 원본 그대로 둘지, 정규화된 현재 이식본을 정본으로 할지.
8. 안전 선언
- 이 파일과 산출물에는 주문·체결·계좌·네트워크 호출이 하나도 없다(순수 판정).
- 포트 9847 · 9848 · 9853 · 9857 · 9869 무접촉. 기존 라이브 파일 수정 0건(신규 2파일만 생성).
- 실자본 적용은
kps_라이브락_엣지.한선의 3조건(엣지 실증·사이징 평탄화·약관 확인)이 여전히 선행 조건이다.