본문 바로가기
기술지표

시장폭 지표(Market Breadth)로 코스피/나스닥 진짜 체력 확인하기 [지표 백과 018]

by 흔한트리이더 2026. 2. 26.
반응형
반응형

1. 탄생 배경: 지수라는 화려한 겉옷을 벗기다

지수가 오르는데 내 주식은 떨어지는 이유, 바로 코스피 같은 지수가 '시가총액 가중 방식'이기 때문입니다. 삼성전자 하나만 5% 올라도 지수는 상승하지만, 나머지 999개의 종목이 하락한다면 그 시장은 속으로 심각하게 병들어 있는 것입니다.

그렇다면 진짜 시장의 체력은 어떻게 측정해야 할까요? 시장폭 지표는 지수라는 화려한 겉옷을 벗기고, 그 숲을 이루는 나무(개별 종목)들이 얼마나 건강한지 진찰하기 위해 탄생했습니다. 우리는 복잡하게 수천 개의 종목을 다루는 대신, 초보자도 파이썬으로 쉽게 따라 할 수 있는 '나만의 관심 우량주 10선'이라는 작은 시장(Micro Market)을 만들어 이 원리를 아주 쉽게 훔쳐보겠습니다.

2. 수리적 원리와 계산 구조

가격이 얼마나 올랐는지가 아니라, '오늘 몇 개의 종목이 올랐는가'에 집중하는 발상의 전환입니다. 수학을 몰라도 초등학생도 따라 할 수 있는 3단계 카운팅 로직을 소개합니다.

Step 1. 상승과 하락 카운팅

우리가 선정한 10개의 관심 종목 중, 오늘 전일 대비 상승한 종목 수(Advances)와 하락한 종목 수(Declines)를 하나씩 셉니다. 보합은 제외합니다.

Step 2. AD 스프레드(Net Advances) 산출

상승 종목 수에서 하락 종목 수를 빼서, 오늘의 순수 매수 에너지를 구합니다.

AD 스프레드 공식

만약 10개 중 7개가 오르고 3개가 내렸다면, 오늘의 스프레드는 `+4`가 됩니다.

Step 3. 등락주선(ADL, Advance-Decline Line) 누적

매일매일 계산된 AD 스프레드를 저금통에 동전 넣듯 계속 누적해서 더해 나갑니다.

ADL 누적 공식

이 누적된 선(ADL)이 위로 향하고 있다면 숲이 전체적으로 건강하게 자라고 있다는 뜻이고, 선이 아래로 꺾인다면 시장의 밑단 체력이 고갈되었다는 명백한 증거입니다.

 

3. 차트로 보는 지표의 특성

코스피 대표 10종목으로 만든 마이크로 마켓 차트를 통해 시장의 체력을 진단해 보겠습니다.

# 코스피 대형주 10선 "A005930": "삼성전자", "A000660": "SK하이닉스", "A005380": "현대차", "A373220": "LG에너지솔루션", "A207940": "삼성바이오로직스", "A000270": "기아", "A068270": "셀트리온", "A005490": "POSCO홀딩스", "A035420": "NAVER", "A006400": "삼성SDI"

 

  • 진짜 상승(수렴 현상): 차트 상단의 붉은 선(지수)이 급등하는 동안, 하단의 푸른 선(ADL) 역시 가파르게 우상향하고 있습니다. 이는 삼성전자 하나만 억지로 오른 것이 아니라 10개 종목 다수가 골고루 상승에 참여한 '매우 튼튼하고 건강한 상승장'임을 수리적으로 증명합니다.
  • 다이버전스 경고 (참고사항): 만약 붉은 선(지수)은 오르는데 푸른 선(ADL)이 뚝뚝 떨어진다면? 대형주 하나만 오르고 내 종목은 다 떨어지는 '가짜 상승'입니다. 곧 폭락이 올 수 있으니 현금 비중을 늘려야 합니다.

4. 장점 및 한계

  • 장점: 세력이 대형주 몇 개로 시장을 억지로 끌어올릴 때, 그 화려한 지수 이면에 숨겨진 '가짜 상승'을 엑스레이처럼 완벽하게 걸러냅니다.
  • 한계: ADL은 매일 누적하는 지표이기 때문에 시작일을 언제로 잡느냐에 따라 Y축 숫자가 달라집니다. 따라서 절대적인 숫자 자체보다는, 지수와 ADL 선이 '같은 방향을 보고 있는지'를 비교하는 용도로만 사용해야 합니다.

5. 파이썬 구현

이전 포스팅에서 사용했던 우리만의 표준 데이터 로딩 함수(load_data)를 그대로 재사용합니다. 어려운 데이터 병합(Merge) 없이, 여러분이 이미 아시는 기초적인 for 반복문만으로 10개 종목의 상승/하락을 세어보겠습니다.

import sqlite3
import pandas as pd

# 1. 표준 데이터 로딩 함수
def load_data(code):
    conn = sqlite3.connect("stock.db")
    query = f"SELECT * FROM stock_{code} ORDER BY date"
    df = pd.read_sql(query, conn)
    df['date'] = pd.to_datetime(df['date'])
    df.set_index('date', inplace=True)
    return df

# 2. 마이크로 마켓(10종목) 데이터 불러오기
def get_micro_market_data():
    # 코스피 대형주 10선 리스트
    codes = ["005930", "000660", "005380", "373220", "207940", 
             "000270", "068270", "005490", "035420", "006400"]
    
    stock_df_list = []
    for code in codes:
        df = load_data(code) # 우리가 만든 표준 함수로 10번 불러옵니다.
        stock_df_list.append(df)
        
    return stock_df_list

# 3. 왕초보용 직관적 카운터 로직
def calculate_adl_for_beginners(stock_df_list):
    days = len(stock_df_list[0]) # 분석할 날짜 수
    adl_line = [0] # 첫째 날은 비교할 과거가 없으므로 0으로 시작
    current_adl = 0 # 저금통
    
    # 둘째 날부터 마지막 날까지 하루씩 이동하며 검사합니다.
    for i in range(1, days):
        advances = 0 # 오늘 오른 종목 수
        declines = 0 # 오늘 내린 종목 수
        
        # 10개의 종목을 하나씩 꺼내서 어제보다 올랐는지 내렸는지 셉니다.
        for df in stock_df_list:
            today_price = df['close'].iloc[i]
            yesterday_price = df['close'].iloc[i-1]
            
            if today_price > yesterday_price:
                advances += 1
            elif today_price < yesterday_price:
                declines += 1
                
        # 오늘의 순수 에너지(스프레드) 계산 후 저금통에 누적
        daily_spread = advances - declines
        current_adl = current_adl + daily_spread
        adl_line.append(current_adl)
        
    return adl_line

# 실행 예시
# market_data = get_micro_market_data()
# adl_result = calculate_adl_for_beginners(market_data)

6. 실전 Tip 및 요약

지수라는 '가짜 거울'에 속지 마세요. 내 관심 종목 10선으로 만든 ADL 지표가 꺾인다면, 아무리 뉴스가 좋아도 시장의 진짜 체력은 방전된 것입니다. 숲의 화려함에 취하지 말고, 숲을 이루는 나무들이 병들고 있는지 하루에 한 번씩 카운트하는 습관이 여러분의 계좌를 지켜줄 것입니다.


*본 포스팅은 기술적 지표의 수리적 이해를 돕기 위한 참고 자료이며, 투자 결과에 대한 책임은 투자자 본인에게 있습니다.*
반응형