docs: known-issues 4건 추가 + devlog 2026-03-11 세션 기록

This commit is contained in:
EDF Agent
2026-03-11 23:25:55 +09:00
parent e4b2c02ab1
commit 348b5bbf27
4 changed files with 79 additions and 41 deletions

View File

@@ -5,4 +5,26 @@
---
(아직 기록된 이슈가 없습니다.)
### 2026-03-11 pykrx — get_market_ticker_list 항상 0 반환
- **증상**: `stock.get_market_ticker_list(date, market="KOSPI")`가 모든 날짜에 0 반환
- **원인**: pykrx 1.2.4 버전에서 ticker_list API가 정상 동작하지 않음 (2026년 환경)
- **해결**: DART `corp_codes`로 종목 목록 확보 + per-ticker `get_market_ohlcv`는 정상 동작
- **주의**: `get_market_ticker_list` 의존하지 말 것. DART corp_codes를 종목 마스터로 사용
### 2026-03-11 pykrx — get_market_cap 단일일자 조회 시 시총=0
- **증상**: `stock.get_market_cap(date, date, ticker)` 호출 시 시가총액이 0 반환
- **원인**: 단일일자 조회 문법 이슈 (pykrx 내부 처리 문제)
- **해결**: `stock.get_market_cap_by_date(start, end, ticker)`로 15일 범위 조회 후 마지막 값 사용
- **주의**: 단일일자 `get_market_cap` 사용 금지. 반드시 date range + `_by_date` 변형 사용
### 2026-03-11 DART — corp_codes 순서에 소형/비활성 종목 우선
- **증상**: DART `corp_codes` 순서대로 수집 시 처음 10~20개가 전부 에러 (비활성/상폐 종목)
- **원인**: corp_codes 정렬이 코드 순이라 소형/비활성사가 앞에 위치
- **해결**: KRX에서 주가 확인된 종목(volatility 테이블)만 DART 수집 대상으로 필터링
- **주의**: DART 수집 시 반드시 KRX 활성 필터 적용. `finstate(stock_code, year)` 형태로 직접 조회 가능
### 2026-03-11 PowerShell — 인라인 Python f-string 이스케이핑 불가
- **증상**: `python -c "...f'{var}'..."` 형태 인라인 코드가 PowerShell에서 파싱 오류
- **원인**: PowerShell의 `'`, `"`, `{}` 이스케이핑이 Python f-string과 충돌
- **해결**: 항상 별도 `.py` 파일로 작성하여 실행
- **주의**: PowerShell에서 복잡한 Python 코드를 `-c` 옵션으로 실행하지 말 것

View File

@@ -0,0 +1,6 @@
# Devlog — 2026-03-11
| # | 시간 | 작업 | 커밋 | 상태 |
|---|------|------|------|------|
| 001 | 19:21 | 프로젝트 초기 세팅 (.agents, 모듈, DB 스키마) | `a20a720` | ✅ |
| 002 | 20:18 | KRX 2,609종목 주가/변동성 수집 + DART 2,497종목 재무제표 수집 | `e4b2c02` | ✅ |

View File

@@ -0,0 +1,20 @@
# EDF 프로젝트 초기 세팅 + 데이터 수집
- **시간**: 2026-03-11 19:21~23:18
- **Commit**: `a20a720`, `e4b2c02`
- **Vikunja**: #312, #313, #317 → done
## 결정 사항
1. **종목 목록 소스**: pykrx `get_market_ticker_list`가 동작하지 않아 DART `corp_codes`를 종목 마스터로 사용
2. **시가총액 조회**: `get_market_cap_by_date` + 15일 범위 조회 (단일일자 조회는 0 반환)
3. **DART 필터링**: KRX에서 주가가 확인된(volatility 테이블 존재) 종목만 DART 수집 → 불필요한 API 호출 방지
4. **DB 설계**: SQLite 8 테이블 (companies, market_data, financial_data, volatility, merton_results, credit_ratings, defaults, default_rates)
5. **기준일**: 2025-03-10 (pykrx가 2026년 데이터를 제공하지 않아 2025년 최근 거래일 사용)
## 미완료
- #314 전체 종목 Merton DD/EDF 일괄 산출 → 다음 세션
- #315 Shadow Rating 모델 구현
- #316 등급별 부도율 산출 및 글로벌 블렌딩
- 금융업 종목 필터링 미적용 (현재 KB금융 등 포함)

View File

@@ -1,44 +1,34 @@
"""DART finstate test — stock code vs corp_code"""
import OpenDartReader
import time
"""DB stats and sample data"""
import sqlite3
dart = OpenDartReader("ef6deb100be436aed88051fd4914dbdb58ff2e94")
conn = sqlite3.connect("data/edf.db")
# Test: finstate with stock code directly
print("=== DART finstate with stock code directly ===")
for code, name in [("005930", "삼성전자"), ("000660", "SK하이닉스"), ("036720", "한볼트")]:
try:
fs = dart.finstate(code, 2024)
time.sleep(0.5)
n = len(fs) if fs is not None else 0
print(f" {code} {name}: {n} rows")
except Exception as e:
print(f" {code} {name}: ERROR {e}")
print("=== DB Stats ===")
for t in ["companies", "market_data", "financial_data", "volatility", "merton_results"]:
c = conn.execute(f"SELECT COUNT(*) FROM {t}").fetchone()[0]
print(f" {t}: {c:,}")
# Test: finstate_all — bulk download per corp_code
print("\n=== DART finstate_all (삼성전자 00126380) ===")
try:
fs = dart.finstate_all("00126380", 2024)
time.sleep(0.5)
n = len(fs) if fs is not None else 0
print(f" 삼성전자 finstate_all: {n} rows")
except Exception as e:
print(f" ERROR: {e}")
print("\n=== Volatility sample ===")
rows = conn.execute("SELECT ticker, sigma_E FROM volatility ORDER BY ticker LIMIT 5").fetchall()
for r in rows:
print(f" {r[0]}: sigma_E={r[1]:.4f}")
# Test: KOSPI major — find their corp_codes and try finstate
print("\n=== DART finstate loop with known-good corp_codes ===")
corp_codes = dart.corp_codes
for ticker in ["005930", "000660", "005380", "036720", "040130"]:
match = corp_codes[corp_codes["stock_code"] == ticker]
if len(match) > 0:
cc = match.iloc[0]["corp_code"]
cn = match.iloc[0]["corp_name"]
try:
fs = dart.finstate(cc, 2024)
time.sleep(0.5)
n = len(fs) if fs is not None else 0
print(f" {ticker} {cn} (corp={cc}): {n} rows")
except Exception as e:
print(f" {ticker} {cn}: ERROR {e}")
else:
print(f" {ticker}: Not found in corp_codes")
print("\n=== Financial sample ===")
rows = conn.execute("""
SELECT ticker, total_assets, default_point, leverage_ratio
FROM financial_data WHERE total_assets IS NOT NULL
ORDER BY total_assets DESC LIMIT 5
""").fetchall()
for r in rows:
dp = f"{r[2]:,.0f}" if r[2] else "N/A"
lev = f"{r[3]:.3f}" if r[3] else "N/A"
print(f" {r[0]}: TA={r[1]:,.0f} DP={dp} LEV={lev}")
# Overlap: tickers with BOTH volatility AND financial_data
both = conn.execute("""
SELECT COUNT(DISTINCT v.ticker)
FROM volatility v JOIN financial_data f ON v.ticker = f.ticker
""").fetchone()[0]
print(f"\n=== Merton 산출 가능 종목 (KRX+DART 모두 있는 종목): {both} ===")
conn.close()