개인 과제 피드백 예시
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. 파일 구조 정리 & 스테이징 영역 구성
- 폴더 구조 통일 → 여기가 과제 내용
- 스테이징 테이블(또는 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,
date DATE NOT NULL,
year INT NOT NULL,
month INT NOT NULL,
day INT NOT NULL,
weekday VARCHAR(10),
is_weekend CHAR(1),
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,
symbol VARCHAR(10) NOT NULL,
coin_name VARCHAR(50),
market VARCHAR(10),
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,
coin_key VARCHAR(20) NOT NULL,
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_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,
coin_key VARCHAR(20) NOT NULL,
breakout_type VARCHAR(10),
alpha_threshold DECIMAL(5,2),
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를 돌리면 됨