penti/COLUMN_MAPPING.md

17 KiB

컬럼명 매핑 가이드

개요

현재 프로젝트는 하이브리드 컬럼명 방식을 사용합니다:

  • PostgreSQL 테이블: 영문 컬럼명
  • DataFrame (전략 코드): 한글 컬럼명

이는 DB 표준(영문)과 make-quant-py 호환성(한글)을 동시에 만족하기 위한 설계입니다.


1. Asset (종목 정보)

PostgreSQL 테이블: assets

DB 컬럼명 (영문) 타입 설명
id UUID 고유 ID
ticker String(20) 종목코드
name String(100) 종목명
market String(20) 시장 (KOSPI/KOSDAQ)
market_cap BigInteger 시가총액
stock_type String(20) 주식 분류
sector String(100) 섹터
last_price Numeric(15,2) 최종 가격
eps Numeric(15,2) 주당순이익
bps Numeric(15,2) 주당순자산
dividend_per_share Numeric(15,2) 주당배당금
base_date Date 기준일
is_active Boolean 활성 여부

DataFrame 컬럼 (한글)

# data_helpers.get_ticker_list() 반환
{
    '종목코드': ticker,
    '종목명': name,
    '시장': market,
    '섹터': sector
}
DataFrame 컬럼 (한글) DB 컬럼 (영문)
종목코드 ticker
종목명 name
시장 market
섹터 sector

2. PriceData (가격 데이터)

PostgreSQL 테이블: price_data

DB 컬럼명 (영문) 타입 설명
ticker String(20) 종목코드
timestamp DateTime 일시
open Numeric(15,2) 시가
high Numeric(15,2) 고가
low Numeric(15,2) 저가
close Numeric(15,2) 종가
volume BigInteger 거래량

DataFrame 컬럼 (한글)

# data_helpers.get_price_data() 반환
{
    '종목코드': ticker,
    '날짜': timestamp,
    '시가': open,
    '고가': high,
    '저가': low,
    '종가': close,
    '거래량': volume
}
DataFrame 컬럼 (한글) DB 컬럼 (영문)
종목코드 ticker
날짜 timestamp
시가 open
고가 high
저가 low
종가 close
거래량 volume

3. FinancialStatement (재무제표)

PostgreSQL 테이블: financial_statements

DB 컬럼명 (영문) 타입 설명
id UUID 고유 ID
ticker String(20) 종목코드
account String(100) 계정명
base_date Date 기준일
value Numeric(20,2)
disclosure_type Char(1) 공시 유형 (Y/Q)

DataFrame 컬럼 (한글)

# data_helpers.get_financial_statements() 반환
{
    '종목코드': ticker,
    '계정': account,
    '기준일': base_date,
    '값': value
}
DataFrame 컬럼 (한글) DB 컬럼 (영문)
종목코드 ticker
계정 account
기준일 base_date
value

4. 전략에서 사용하는 파생 컬럼

전략 코드에서 계산되는 추가 컬럼들 (모두 한글):

Multi-Factor 전략

Quality 팩터:

  • ROE - 자기자본이익률
  • GPA - Gross Profit / Assets
  • CFO - 영업활동현금흐름

Value 팩터:

  • PER - 주가수익비율
  • PBR - 주가순자산비율
  • PCR - 주가현금흐름비율
  • PSR - 주가매출액비율
  • DY - 배당수익률

Momentum 팩터:

  • 12M_Return - 12개월 수익률
  • K_Ratio - K-Ratio (모멘텀 지속성)

Magic Formula 전략

  • magic_ebit - EBIT (영업이익)
  • magic_ev - Enterprise Value
  • magic_ic - Invested Capital
  • magic_ey - Earnings Yield (EBIT / EV)
  • magic_roc - Return on Capital (EBIT / IC)
  • magic_rank - 종합 순위

F-Score 전략

  • f_score - F-Score (0-9점)
  • 분류 - 시가총액 분류 (대형주/중형주/소형주)

5. 변환 로직 위치

모든 영문 → 한글 변환은 **app/utils/data_helpers.py**에서 수행됩니다.

# app/utils/data_helpers.py

def get_ticker_list(db_session: Session) -> pd.DataFrame:
    """종목 리스트 조회 (영문 → 한글 변환)"""
    assets = db_session.query(Asset).filter(Asset.is_active == True).all()

    data = [{
        '종목코드': asset.ticker,      # ticker → 종목코드
        '종목명': asset.name,          # name → 종목명
        '시장': asset.market,          # market → 시장
        '섹터': asset.sector           # sector → 섹터
    } for asset in assets]

    return pd.DataFrame(data)

def get_price_data(...) -> pd.DataFrame:
    """가격 데이터 조회 (영문 → 한글 변환)"""
    # ...
    data = [{
        '종목코드': p.ticker,          # ticker → 종목코드
        '날짜': p.timestamp,           # timestamp → 날짜
        '시가': float(p.open),         # open → 시가
        '고가': float(p.high),         # high → 고가
        '저가': float(p.low),          # low → 저가
        '종가': float(p.close),        # close → 종가
        '거래량': p.volume             # volume → 거래량
    } for p in prices]

    return pd.DataFrame(data)

def get_financial_statements(...) -> pd.DataFrame:
    """재무제표 조회 (영문 → 한글 변환)"""
    # ...
    data = [{
        '종목코드': fs.ticker,         # ticker → 종목코드
        '계정': fs.account,            # account → 계정
        '기준일': fs.base_date,        # base_date → 기준일
        '값': float(fs.value)          # value → 값
    } for fs in fs_data]

    return pd.DataFrame(data)

def get_value_indicators(...) -> pd.DataFrame:
    """밸류 지표 조회"""
    # ...
    data = [{
        '종목코드': ticker,
        '지표': indicator_name,        # PER, PBR, PCR, PSR, DY
        '값': value
    }]

    return pd.DataFrame(data)

6. 새로운 컬럼 추가 시 주의사항

Step 1: DB 모델에 영문 컬럼 추가

# app/models/asset.py
class Asset(Base):
    # ...
    new_field = Column(String(50))  # 영문 컬럼명

Step 2: Alembic 마이그레이션

alembic revision --autogenerate -m "Add new_field to assets"
alembic upgrade head

Step 3: data_helpers.py에 매핑 추가

# app/utils/data_helpers.py
def get_ticker_list(db_session):
    data = [{
        '종목코드': asset.ticker,
        '종목명': asset.name,
        # ...
        '새필드': asset.new_field  # 한글 컬럼명 추가
    } for asset in assets]

Step 4: 전략 코드에서 사용

# app/strategies/composite/my_strategy.py
ticker_list['새필드'].tolist()  # 한글 컬럼명 사용

7. 일관성 검증

테스트 코드 예시

# tests/test_column_mapping.py
def test_ticker_list_columns():
    """종목 리스트 컬럼명 검증"""
    df = get_ticker_list(db_session)

    # 한글 컬럼명 확인
    assert '종목코드' in df.columns
    assert '종목명' in df.columns
    assert '시장' in df.columns
    assert '섹터' in df.columns

def test_price_data_columns():
    """가격 데이터 컬럼명 검증"""
    df = get_price_data(db_session, ['005930'], start_date, end_date)

    # 한글 컬럼명 확인
    assert '종목코드' in df.columns
    assert '날짜' in df.columns
    assert '시가' in df.columns
    assert '고가' in df.columns
    assert '저가' in df.columns
    assert '종가' in df.columns
    assert '거래량' in df.columns

8. 대안적 접근 (참고)

옵션 A: 완전 영문화 (현재 미사용)

# DB와 DataFrame 모두 영문
ticker_list['ticker'].tolist()
data_bind[['ticker', 'name', 'sector']].copy()

장점: 일관성 단점: make-quant-py 코드 대대적 수정 필요

옵션 B: 완전 한글화 (현재 미사용)

# DB도 한글 컬럼명
class Asset(Base):
    종목코드 = Column(String(20))
    종목명 = Column(String(100))

장점: 변환 불필요 단점: DB 표준 위반, 국제화 어려움, ORM 이슈

옵션 C: 하이브리드 (현재 채택)

  • DB: 영문 (표준 준수)
  • DataFrame: 한글 (make-quant-py 호환)
  • 변환: data_helpers.py가 책임

장점: 양쪽 장점 모두 활용 단점: 변환 레이어 유지보수


9. make-quant-py MySQL vs 현재 PostgreSQL

make-quant-py (MySQL)

-- kor_ticker 테이블
CREATE TABLE kor_ticker (
    종목코드 VARCHAR(20),    -- 한글 컬럼명
    종목명 VARCHAR(100),
    시가총액 BIGINT,
    분류 VARCHAR(20),
    섹터 VARCHAR(100),
    종가 INT,
    EPS DECIMAL,
    BPS DECIMAL,
    주당배당금 DECIMAL,
    종목구분 VARCHAR(20),
    기준일 DATE
);

-- kor_price 테이블
CREATE TABLE kor_price (
    날짜 DATE,              -- 한글 컬럼명
    시가 INT,
    고가 INT,
    저가 INT,
    종가 INT,
    거래량 BIGINT,
    종목코드 VARCHAR(20)
);

-- kor_fs 테이블
CREATE TABLE kor_fs (
    종목코드 VARCHAR(20),
    계정 VARCHAR(100),
    기준일 DATE,
     DECIMAL,
    공시구분 CHAR(1)
);

현재 프로젝트 (PostgreSQL)

-- assets 테이블
CREATE TABLE assets (
    id UUID,
    ticker VARCHAR(20),      -- 영문 컬럼명
    name VARCHAR(100),
    market_cap BIGINT,
    stock_type VARCHAR(20),
    sector VARCHAR(100),
    last_price NUMERIC(15,2),
    eps NUMERIC(15,2),
    bps NUMERIC(15,2),
    dividend_per_share NUMERIC(15,2),
    market VARCHAR(20),
    base_date DATE,
    is_active BOOLEAN
);

-- price_data 테이블
CREATE TABLE price_data (
    timestamp TIMESTAMP,     -- 영문 컬럼명
    open NUMERIC(15,2),
    high NUMERIC(15,2),
    low NUMERIC(15,2),
    close NUMERIC(15,2),
    volume BIGINT,
    ticker VARCHAR(20)
);

-- financial_statements 테이블
CREATE TABLE financial_statements (
    id UUID,
    ticker VARCHAR(20),
    account VARCHAR(100),
    base_date DATE,
    value NUMERIC(20,2),
    disclosure_type CHAR(1)
);

마이그레이션 매핑 (scripts/migrate_mysql_to_postgres.py)

kor_ticker → assets:

asset = Asset(
    ticker=row['종목코드'],              # 한글 → ticker
    name=row['종목명'],                  # 한글 → name
    market=row['시장구분'],              # 한글 → market
    last_price=row['종가'],              # 한글 → last_price
    market_cap=row['시가총액'],          # 한글 → market_cap
    eps=row['EPS'],                     # 영문 → eps
    bps=row['BPS'],                     # 영문 → bps
    dividend_per_share=row['주당배당금'], # 한글 → dividend_per_share
    stock_type=row['종목구분'],          # 한글 → stock_type
    base_date=row['기준일'],             # 한글 → base_date
    is_active=True
)

kor_price → price_data:

price = PriceData(
    ticker=row['종목코드'],        # 한글 → ticker
    timestamp=row['날짜'],         # 한글 → timestamp
    open=row['시가'],              # 한글 → open
    high=row['고가'],              # 한글 → high
    low=row['저가'],               # 한글 → low
    close=row['종가'],             # 한글 → close
    volume=row['거래량']           # 한글 → volume
)

kor_fs → financial_statements:

fs = FinancialStatement(
    ticker=row['종목코드'],           # 한글 → ticker
    account=row['계정'],             # 한글 → account
    base_date=row['기준일'],         # 한글 → base_date
    value=row['값'],                 # 한글 → value
    disclosure_type=row['공시구분']  # 한글 → disclosure_type
)

마이그레이션 매핑 테이블

테이블 MySQL 컬럼 (한글) PostgreSQL 컬럼 (영문) 타입 변경
kor_ticker → assets
종목코드 ticker VARCHAR(20)
종목명 name VARCHAR(100)
시장구분 market VARCHAR(20)
시가총액 market_cap BIGINT
종가 last_price INT → NUMERIC(15,2)
EPS eps DECIMAL → NUMERIC(15,2)
BPS bps DECIMAL → NUMERIC(15,2)
주당배당금 dividend_per_share DECIMAL → NUMERIC(15,2)
종목구분 stock_type VARCHAR(20)
기준일 base_date DATE
kor_price → price_data
종목코드 ticker VARCHAR(20)
날짜 timestamp DATE → TIMESTAMP
시가 open INT → NUMERIC(15,2)
고가 high INT → NUMERIC(15,2)
저가 low INT → NUMERIC(15,2)
종가 close INT → NUMERIC(15,2)
거래량 volume BIGINT
kor_fs → financial_statements
종목코드 ticker VARCHAR(20)
계정 account VARCHAR(100)
기준일 base_date DATE
value DECIMAL → NUMERIC(20,2)
공시구분 disclosure_type CHAR(1)

10. 전체 데이터 흐름

┌─────────────────────────────────────────────────────┐
│          MySQL (make-quant-py)                      │
│  kor_ticker: 종목코드, 종목명, 시장구분, 시가총액    │
│  kor_price: 날짜, 시가, 고가, 저가, 종가, 거래량     │
│  kor_fs: 종목코드, 계정, 기준일, 값, 공시구분        │
│  👆 한글 컬럼명                                      │
└─────────────────────────────────────────────────────┘
                         │
                         │ scripts/migrate_mysql_to_postgres.py
                         │ (한글 → 영문 매핑)
                         │ row['종목코드'] → Asset.ticker
                         │ row['시가'] → PriceData.open
                         ▼
┌─────────────────────────────────────────────────────┐
│          PostgreSQL (현재 프로젝트)                  │
│  assets: ticker, name, market, market_cap           │
│  price_data: timestamp, open, high, low, close      │
│  financial_statements: ticker, account, base_date   │
│  👆 영문 컬럼명                                      │
└─────────────────────────────────────────────────────┘
                         │
                         │ app/utils/data_helpers.py
                         │ (영문 → 한글 매핑)
                         │ asset.ticker → '종목코드'
                         │ price.open → '시가'
                         ▼
┌─────────────────────────────────────────────────────┐
│          DataFrame (전략 코드)                       │
│  종목코드, 종목명, 시장, 섹터                        │
│  날짜, 시가, 고가, 저가, 종가, 거래량                │
│  종목코드, 계정, 기준일, 값                          │
│  👆 한글 컬럼명 (make-quant-py 호환)                │
└─────────────────────────────────────────────────────┘

일관성 보장

모든 레이어에서 동일한 매핑 규칙 사용:

  1. MySQL → PostgreSQL (마이그레이션):

    • row['종목코드']Asset.ticker
    • row['시가']PriceData.open
  2. PostgreSQL → DataFrame (data_helpers):

    • asset.ticker'종목코드'
    • price.open'시가'
  3. 결과: make-quant-py 전략 코드가 수정 없이 작동!

    # 전략 코드에서 그대로 사용 가능
    ticker_list['종목코드'].tolist()
    price_df['시가'].mean()
    

11. 결론

현재 프로젝트는 하이브리드 컬럼명 방식을 채택하여:

  1. DB 표준 준수: PostgreSQL 영문 컬럼명
  2. make-quant-py 호환: DataFrame 한글 컬럼명
  3. 마이그레이션 일관성: MySQL → PostgreSQL 자동 매핑
  4. 명확한 책임 분리:
    • scripts/migrate_mysql_to_postgres.py - 마이그레이션 변환
    • app/utils/data_helpers.py - 쿼리 결과 변환

개발자 가이드

  • DB 스키마 작업 → 영문 컬럼명 사용
  • 전략 코드 작성 → 한글 컬럼명 사용
  • 새 컬럼 추가 → 세 곳 모두 업데이트:
    1. PostgreSQL 모델 (영문)
    2. data_helpers.py 매핑 (영문→한글)
    3. 마이그레이션 스크립트 (한글→영문) - 필요 시

마이그레이션 실행

python scripts/migrate_mysql_to_postgres.py \
  --mysql-host localhost \
  --mysql-user root \
  --mysql-password password \
  --mysql-database quant_db

문서 버전: v1.1.0 최종 업데이트: 2024년 1월 (마이그레이션 매핑 추가)