데이터 파이프라인 구축 - 4회차

Suhyeon Lee·2025년 1월 17일
0

라이브 세션

목록 보기
37/37

개인 과제 피드백 예시

  • get_coingecko_top_coins_by_marketcap(n=30)
    • coins가 전체 JSON을 그대로 반환하지 않고 "필요한 필드만 추출해서" 리턴해야 합니다.
      • id, symbol(대문자로 표시해야 함), name, market_cap 등
  • get_one_year_daily_candles(market, end_kst_str)
    • "1년치(최대 365개 이상) 일봉"을 가져오려면 반복 요청이 필요합니다.
      • 한 번 API를 호출하면 최대 200개의 일봉만 받을 수 있기 때문입니다.
    • requests.get()을 단 한 번만 호출하고 바로 save_candles_to_csv_by_date로 넘어가게 되면 최대 200개만 얻고 종료되므로 1년치를 수집할 수 없습니다.
  • KST → UTC 변환
    • Upbit에서는 candles/days API의 to 파라미터에 "UTC 시간"을 2025-01-17T10:00:00+09:00 형태(YYYY-mm-ddTHH:MM:SSZ)로 넘겨야 한다고 명시되어 있습니다.
    • end_kst_str의 경우 "2025-01-17 10:00:00" 형태이므로 to에 넣기 위해서는 형태 변환이 필요합니다.
  • "1년 전보다 더 과거면 중단" 로직
    • 과제의 "반복으로 과거 데이터를 계속 가져오다가, 가장 오래된 캔들의 날짜가 1년 전보다 넘어가면 중단"을 구현하기 위해서는 while문이나 if문을 사용해야 합니다.
  • save_candles_to_csv_by_date(candles, market)
    • candles(pd.DataFrame)에 일봉 데이터가 여러 날짜가 들어있을 수 있습니다. 과제는 날짜마다 폴더를 생성해 그 날짜의 캔들은 매일 csv에 한 줄씩 기록(append)할 것을 요구하고 있습니다.
    • pandas의 to_csv 기본 동작은 새 파일 생성 또는 덮어쓰기(overwrite)입니다.
      • 여러 캔들이 같은 날짜라도 파일 모드(mode='a') + 헤더 중복 방지 등의 처리가 필요합니다.
  • main
    • "(오늘-1일)부터 1년치"를 연결된 데이터로 모으기 위해서는 "1년치"를 따로 모아두는(while문) 로직이 필요합니다.
      • while문으로 200개씩 받아서 1년 전보다 더 내려가면 중단 → 그 결과를 한꺼번에 csv 저장

앞으로 해야 할 일

  • DB 설치
  • Table 설계
  • Data Mart 설계

최종 목표

  • 최근 20일 고가(High) 대비 일정 %를 돌파(상승 돌파)했을 때 매수한 경우와
  • 최근 20일 저가(Low) 대비 일정 %를 하락(하단 돌파)했을 때 매수한 경우 중
  • 어떤 전략이 D+X일 후(또는 동적 로직) 수익률이 더 높은지 통계적으로 비교

핵심 지표

  • 돌파 발생 시점(이벤트), 매수가(종가 등), D+X일 후 수익률(%)
  • 승률(수익≥0%), 평균 수익률, 최대 낙폭, 최대 수익 등
  • "상승 돌파" vs. "하락 돌파" 이벤트 각각에 대해 통계를 내 비교

1. 파일 구조 정리 & 스테이징 영역 구성

  1. 폴더 구조 통일 → 여기가 과제 내용
    • 또는 일자별/코인별 폴더로 나눠 저장
  2. 스테이징 테이블(또는 DB) 만들기
  • "stg_coin_daily" 같은 DB 테이블에 이 csv 데이터를 그대로 로드
  • 아직 분석용 스키마(마트)로 들어가기 전이므로 최대한 원본에 가깝게 저장
    • 컬럼 그대로 & 타입만 SQL에 맞춤 → 스테이징 테이블이자 DW가 되는 것!
  • 이렇게 하면 DB 쿼리로도 손쉽게 중복/결측 등을 다시 한번 점검 가능

2. 차원 테이블(Dimensions)

→ 본격적인 마트 테이블 구성:

  • raw 형태에서 날짜 차원의 데이터와 코인 기반의 데이터로 두 개의 차원 생성

※ 아래 내용은 예시(최종본은 5회차에서 공유)

2.1. dim_date (날짜 차원)

만드는 이유

  • 일봉 데이터에서 “연도/월/일/요일/주말여부” 등을 자주 분석하게 되므로, 별도 차원 테이블을 두면 JOIN 한 번으로 쉽게 접근 가능
  • 예: “월별 거래량”, “요일별 변동률” 등 시계열 분석에 유리

스키마 예시

CREATE TABLE dim_date (
 date_key INT NOT NULL, -- YYYYMMDD 형태 (PK)
 date DATE NOT NULL, -- 실제 날짜 (ex: 2025-01-12)
 year INT NOT NULL,
 month INT NOT NULL,
 day INT NOT NULL,
 weekday VARCHAR(10), -- 'Monday', 'Tuesday' 등
 is_weekend CHAR(1), -- 'Y' / 'N'
 PRIMARY KEY (date_key)
);
  • SQL
    • date_key: YYYYMMDD 정수(예: 20250112) → 다른 팩트 테이블에서 날짜 FK로 사용
    • is_weekend, weekday 등은 사소하지만 분석할 때 매우 자주 쓰임

2.2. dim_coin (코인 차원)

만드는 이유

  • 코인 정보(심볼, 이름, 마켓, 추가 설명 등)를 코인별로 단 1회만 저장하고 , 팩트 테이블에서는 coin_key(FK)로 참조
  • “BTC, ETH, DOGE, SOL” 등 5개 코인 중 어느 것인지 구분 + 필요 시 확장(시총, 로고URL 등)

스키마 예시

CREATE TABLE dim_coin (
 coin_key VARCHAR(20) NOT NULL, -- 예: "KRW-BTC" (PK)
 symbol VARCHAR(10) NOT NULL, -- "BTC"
 coin_name VARCHAR(50), -- "Bitcoin"
 market VARCHAR(10), -- "KRW"
 PRIMARY KEY (coin_key)
);
  • SQL
    • coin_key: “KRW-BTC”, “KRW-ETH” 등 고유 식별자
    • symbol: “BTC”, “ETH” 등 짧은 심볼
    • 이후 다른 코인(“KRW-ADA”, “KRW-XRP”)이 추가될 때도 이 테이블에 1행만 넣으면 됨

3. 팩트 테이블(Facts)

3.1. fact_coin_daily (일봉 시세)

만드는 이유

  • CSV에 들어있는 일봉(OHLC, 거래량 등)을 날짜 × 코인으로 정규화해 저장
  • 추후 “최근 20일 고가”, “월별 평균 종가”, “년별 거래량 합계” 등을 SQL로 쉽게 집계

스키마 예시

CREATE TABLE fact_coin_daily (
 date_key INT NOT NULL, -- FK → dim_date(date_key)
 coin_key VARCHAR(20) NOT NULL, -- FK → dim_coin(coin_key)
 open_price DECIMAL(20,8),
 high_price DECIMAL(20,8),
 low_price DECIMAL(20,8),
 close_price DECIMAL(20,8),
 volume DECIMAL(28,8), -- 거래량 (candle_acc_trade_volume)
 candle_acc_trade_price DECIMAL(28,8), 
 prev_closing_price DECIMAL(20,8),
 change_price DECIMAL(20,8),
 change_rate DECIMAL(10,8),
 PRIMARY KEY (date_key, coin_key),
 FOREIGN KEY (date_key) REFERENCES dim_date(date_key),
 FOREIGN KEY (coin_key) REFERENCES dim_coin(coin_key)
);
  • SQL
    • date_key, coin_key가 복합 PK
    • CSV의 candle_date_time_kst를 YYYY-MM-DD로 변환해 date_key(ex: 20250112) 생성
    • volume: CSV의 candle_acc_trade_volume 해당
    • 다른 컬럼(prev_closing_price, change_rate)도 추가

4. 이벤트 테이블 (브레이크아웃 등 돌파 전략 분석)

4.1. fact_breakout_event (상승/하락 돌파 이벤트)

만드는 이유

  • 백테스트나 실시간 모니터링 시, “어제(또는 오늘) 돌파 이벤트 발생!”한 날짜/가격/수익률을 체계적으로 기록
  • 이후 “상승 돌파 vs 하락 돌파 승률” 등 통계를 낼 때, 매번 계산할 필요 없이 이 테이블을 조회하면 됨

스키마 예시

CREATE TABLE fact_breakout_event (
 event_id BIGINT AUTO_INCREMENT,
 date_key INT NOT NULL, -- 돌파 발생 날짜 (FK → dim_date)
 coin_key VARCHAR(20) NOT NULL, -- 어떤 코인인지 (FK → dim_coin)
 breakout_type VARCHAR(10), -- 'UP' or 'DOWN'
 alpha_threshold DECIMAL(5,2), -- 돌파 임계치 (%) ex: 1.0, 3.0
 
 entry_price DECIMAL(20,8), -- 돌파 시점 종가(가정 매수 가격)
 return_d1, return_d3, etc
 exit_day, exit_price, exit_return
 PRIMARY KEY (event_id),
 FOREIGN KEY (date_key) REFERENCES dim_date(date_key),
 FOREIGN KEY (coin_key) REFERENCES dim_coin(coin_key)
);
  • SQL
    • breakout_type: “UP”(상단 돌파), “DOWN”(하단 돌파)
    • alpha_threshold: “20일 고가 × (1 + alpha)”를 돌파했는지, “20일 저가 × (1 - alpha)”를 돌파했는지 구분
    • entry_price: 그날 종가(매수 가정)
    • 추가 컬럼(return_d1, return_d3 등)은 “D+1일 종가 대비 수익률”, “D+3일 종가 대비 수익률”을 기록
    • 동적 로직(목표수익, 손절 등)을 구현할 경우 exit_day, exit_return, exit_reason(‘목표5%도달’, ‘7일만료’ 등)을 추가

ERD

code

  • upit_raw_collector_1y.py
  • upit_raw_collector_daily.py

→ 1년치 데이터를 수집하고 배치로 하루씩 날짜 지날 때마다 추가되어야 해서 upit_raw_collector_daily.py가 추가되었습니다.

  • 1년치 데이터 수집은 한 번만 돌리면 되고 하루씩 지날 때마다 daily를 돌리면 됨
profile
2 B R 0 2 B

0개의 댓글

관련 채용 정보