CCI는 가격이 최근 평균에서 얼마나 멀리 떨어졌는지를 표준화된 단위로 재는 오실레이터다. 도널드 램버트가 1980년에 원자재 가격의 주기적 전환점을 잡으려고 만들었고, 지금은 원자재뿐 아니라 주식에도 널리 쓰인다. 값이 +100을 넘으면 통계적으로 드문 강세, -100을 밑돌면 드문 약세로 본다. 이 경계선을 추세 시작 신호로 삼는 돌파 매매법이 있고, 반대로 극단에서 되돌아오는 순간을 저점·고점 신호로 삼는 역추세 매매법도 있다. 이번 글은 돌파 매매법을 검증한다.
램버트가 종가 대신 전형가격(고가·저가·종가 평균)을 쓴 이유는 하루 안의 변동 폭까지 반영하려는 의도였다. 종가만 보면 장중 급등락이 다음 날 평균 계산에서 사라지지만, 전형가격은 그날의 고점과 저점을 함께 끌고 간다. 0.015라는 상수는 자의적인 숫자가 아니라, 표본이 정규분포를 따른다고 가정했을 때 값의 대략 70~80%가 -100과 +100 사이에 들어오도록 역산해서 고정한 값이다. 즉 ±100 밖은 원래 통계적으로 드문 구간이어야 한다는 전제가 깔려 있다.
HD한국조선해양을 고른 이유는 이 구간의 가격 움직임이 CCI를 시험하기에 좋은 조건을 갖췄기 때문이다. 6월 말부터 9월 초까지 주가는 뚜렷한 한 방향 추세 없이 큰 폭으로 오르내렸다. 7월 말부터 8월 초 랠리로 40만원을 넘었다가, 8월 중순부터 다시 흘러내렸다. 조선업은 수주 소식 하나에 며칠씩 거래량이 튀는 업종이라, 8월 13일(41만 3,250주)이나 7월 30일(42만 6,858주)처럼 평소보다 거래량이 두 배 가까이 뛴 날이 여러 번 있었다. 방향이 두 번 바뀌고 거래량 스파이크까지 섞인 구간이면, 돌파 신호가 진짜 추세의 시작을 잡는지 아니면 되돌림 직전에 발동해 물리는지가 선명하게 갈린다.

종목 HD한국조선해양(009540)
구간 2026-06-24 ~ 2026-09-03 (50거래일)
출처 stockanalysis.com/quote/krx/009540/history
--------------------------------------------------
최고가 412,500원 (08/11)
최저가 314,000원 (07/29)
시작 종가 368,000원 (06/24)
종료 종가 344,000원 (09/03)
구간 등락률 -6.52%
고점 대비 낙폭 -18.44% (08/10 종가 → 09/02 종가)이 글은 투자 권유가 아니다. 과거 구간의 신호를 그대로 대입해 본 결과이며, 같은 신호가 다음에도 같은 결과를 낸다고 보장하지 않는다.
계산과 실측
CCI는 전형가격(고가·저가·종가의 평균)이 이동평균에서 얼마나 벗어났는지를 재는 지표다. 계산식은 다음과 같다.
전형가격 TP = (고가 + 저가 + 종가) / 3
이동평균 SMA(20) = 최근 20일 TP의 평균
평균절대편차 MAD(20) = 최근 20일 |TP - SMA(20)|의 평균
--------------------------------------------------
CCI (TP - SMA(20)) / (0.015 * MAD(20))0.015라는 상수는 램버트가 정규분포를 가정했을 때 값의 약 70~80%가 -100과 +100 사이에 들어오도록 역산해 고정한 값이다. 기간은 20일로 잡았다. 램버트는 원래 전체 주기의 3분의 1에서 2분의 1 사이를 권했는데, 지금은 트레이딩뷰를 비롯한 대부분의 플랫폼이 20일을 기본값으로 쓴다. 라이브러리 없이 numpy만으로 직접 계산했고, 위 계산식을 그대로 코드에 옮겼다.
20일 이동평균을 쓰면 첫 19거래일은 채울 표본이 부족해 값이 나오지 않는다. 50거래일 중 유효한 CCI 값은 31개뿐이다. 예열 구간이 전체의 40%에 육박한다는 뜻이라, 이 구간 앞머리의 등락은 CCI로 판단할 수 없었다.

7월 22일 처음 값이 나온 CCI는 32.33이었다. 다음 날인 7월 23일, 종가 381,000원에서 CCI가 141.96까지 튀며 +100을 뚫었다. 이후 8월 11일까지 CCI는 +100 위아래를 세 번 오갔고, 8월 21일부터는 반대쪽 -100 아래로 세 번 떨어졌다. 이번 구간에서 나온 ±100 돌파는 총 여섯 번, 그중 하나(9월 2일 하향 돌파)는 데이터가 끝난 9월 3일까지도 반대쪽으로 돌아오지 않아 미청산 상태로 남았다.
돌파 매매 규칙은 단순하다. CCI가 +100을 상향 돌파하면 그날 종가로 매수하고, 다시 +100 아래로 내려오면 그날 종가로 청산한다. -100 하향 돌파는 반대로 매도(공매도) 진입, -100 위로 올라오면 청산으로 잡았다. 아래는 이 규칙을 이번 구간 전체에 그대로 적용한 결과다.
구분 진입일 → 청산일 진입가 → 청산가 손익
--------------------------------------------------
매수1 07/23 → 07/28 381,000 → 354,000 -7.09%
매수2 07/31 → 08/03 384,500 → 368,500 -4.16%
매수3 08/05 → 08/12 396,000 → 380,500 -3.91%
매도1 08/21 → 08/25 348,500 → 362,500 -4.02%
매도2 08/31 → 09/01 348,500 → 353,500 -1.43%
매도3 09/02 → 미청산 329,500 → 344,000(09/03) -4.40%
여섯 번의 신호를 하나씩 짚으면 이렇다. 매수1은 7월 23일 급등 다음 날 진입했는데, 정작 그 급등은 이미 끝난 뒤였다. 종가 381,000원에서 CCI가 32.33에서 141.96으로 하루 만에 튀어 오른 시점이 이미 단기 고점에 가까웠고, 진입 이후 5거래일 만에 CCI가 꺾이며 -7.09% 손실로 청산됐다. 매수2는 7월 31일 384,500원에 진입했다. 이때는 CCI가 42.93에서 131.01로 다시 급등했는데, 이틀 뒤인 8월 3일 곧바로 90.90까지 주저앉으며 368,500원에서 청산돼 -4.16%를 남겼다. 매수3은 8월 5일 396,000원, CCI 151.60에서 진입해 8월 12일 380,500원, CCI 51.53에서 -3.91% 손실로 끝났다. 세 매수 모두 +100을 뚫는 시점이 그날그날의 단기 고점 근처였고, 청산 신호가 나올 때는 이미 반락이 상당히 진행된 뒤였다.
매도 쪽도 다르지 않았다. 매도1은 8월 21일 -131.76까지 떨어진 CCI를 보고 348,500원에 매도 진입했는데, 바로 다음 거래일부터 반등이 시작돼 나흘 만인 8월 25일 -71.84로 -100 위에 복귀, 362,500원에 청산됐다. 공매도인데 주가가 오르니 손실이다. 매도2는 8월 31일 348,500원에 진입해 하루 만인 9월 1일 353,500원에 청산됐다. 진입과 청산 사이가 단 하루였고 손실 폭(-1.43%)은 작았지만 방향은 역시 틀렸다. 매도3은 9월 2일 CCI -135.92, 종가 329,500원에 진입한 뒤 데이터가 끝난 9월 3일까지 청산 신호가 나오지 않았다. 9월 3일 CCI는 -104.43으로 여전히 -100 아래였고, 그날 종가 344,000원으로 계산한 평가손실은 -4.40%다.
완결된 다섯 거래의 평균 손익은 -4.12%, 승률은 0%다. 맞은 신호가 하나도 없었다. 방향을 가리지 않고 극단을 뚫는 순간이 매번 추세의 끝자락과 겹쳤다는 뜻이다. 이 구간의 HD한국조선해양은 뚜렷한 한 방향 추세가 아니라 넓은 박스 안에서 왕복했고, 그런 장에서는 돌파 신호가 추세의 시작이 아니라 되돌림 직전의 극점을 가리키기 쉽다.
기간을 바꾸면 결론이 어떻게 달라지는지도 확인했다. CCI(10)은 유효값이 41개로 늘지만 값이 훨씬 거칠다. 9월 2일 하루만 봐도 CCI(20)은 -135.92인데 CCI(10)은 -200.68까지 튄다. 진입·청산 신호도 2·2·5·4번으로 늘어 잡음이 심해진다. 반대로 CCI(30)은 유효값이 21개까지 줄고, 같은 날 값도 -154.05로 상대적으로 완만하다. 8월 초 랠리 구간에서는 CCI(30)이 187~198까지 올라가 +100을 진작에 넘겼지만, 정작 그 뒤로는 신호가 거의 나오지 않아 완결된 왕복 자체를 찾기 어려웠다. 20일은 이번 구간에서 신호를 낼 만큼 민감하면서도 완결된 왕복을 잡아낼 만큼 느린, 둘 사이의 절충점이었다. 다만 절충점이라고 해서 신호의 방향까지 맞은 건 아니었다. CCI(14)로 계산해도 돌파 시점과 손익 부호는 CCI(20)과 거의 같았다. 이번 구간에서는 기간을 14로 줄이든 20으로 두든 결론이 바뀌지 않았다는 뜻이다.

이 결과를 봇 게이트에 넣을지는 부정적이다. 여섯 번의 신호 중 다섯 번이 확정 손실이고 나머지 하나도 평가손실이라면, 단순 돌파 규칙을 그대로 자동매매에 걸 근거가 없다. 다만 이 실패 자체는 정보다. 이번 구간처럼 큰 폭의 박스권에서는 CCI 돌파가 역신호에 가깝게 작동했다는 사실은, 추세장과 박스장을 먼저 구분하는 필터 없이 CCI 돌파만 단독으로 쓰면 안 된다는 근거가 된다.
남기는 것
이번 구간에서 남길 것은 두 가지다. 첫째, CCI의 ±100은 통계적으로 드문 값일 뿐 추세 전환의 확정 신호가 아니다. 둘째, 파라미터를 20으로 고정해도 신호의 승패까지 바로잡히지는 않았다. 파라미터 튜닝이 방향성 문제 자체를 해결해 주지 않는다는 걸 이번 데이터로 다시 확인했다.
CCI는 애초에 가격이 통계적 정상 범위를 벗어났는지를 재는 도구로 설계됐고, 그 자체가 매매 타이밍을 보장하는 신호는 아니다. 이번 구간의 결과는 그 구분을 그대로 보여준다. 정상 범위를 벗어난 건 맞았지만, 그게 매수·매도 타이밍이 되지는 못했다.
이 글은 투자 조언이 아니며, 다룬 신호는 과거 데이터에 대한 사후 검증일 뿐이다. 다음 구간에서 CCI(20) 돌파가 다르게 작동할지는 아직 확인하지 못한 숙제로 남긴다.
약어 풀이
- 이 글에 나온 영어 약어를 풀어 둔다.
- CCI (Commodity Channel Index): 가격이 최근 평균에서 표준적으로 얼마나 벗어났는지를 재는 오실레이터.
- SMA (Simple Moving Average): 최근 n일 값을 단순 평균한 이동평균.
- MAD (Mean Absolute Deviation): 평균에서 각 값이 벗어난 정도의 절댓값을 다시 평균한 값.