-
Notifications
You must be signed in to change notification settings - Fork 0
Description
신규 파일
1. DB/init_tables.sqlto show thinking)
PostgreSQL 데이터베이스 테이블 스키마 정의
· Topsy-turvying… (esc to interrupt · 45s · ↓ 1.8k tokens)
테이블 구조:
stocks: 티커 메타데이터 (ticker, company_name, exchange, sector, market_cap)───────────────────────────────────prices: 일일 가격 데이터 (ticker, trade_date, OHLCV)graph_segments: 정규화된 벡터 세그먼트 (ticker, ma_type, segment_start/end, vector[128], volatility)───────────
? for shortcuts
인덱스:- prices: ticker, trade_date
- graph_segments: ticker, ma_type
2. app/db_io.py
PostgreSQL 데이터베이스 연동 모듈
주요 기능:
init_pool(): 연결 풀 초기화 (SimpleConnectionPool)get_connection(): Context manager로 안전한 연결 관리fetch_all_segments(): MA20 벡터 세그먼트 일괄 조회 (128차원)fetch_latest_ma20_for_tickers(): 특정 티커들의 최신 MA20 세그먼트 조회get_segment_count(): 전체 세그먼트 수 확인close_pool(): 연결 풀 종료
반환 형식:
vectors: np.ndarray # Shape: (N, 128)
tickers: List[str] # 티커 리스트
metadata: List[dict] # {id, ticker, start_date, end_date, volatility}3. tests/test_similarity_validation.py
유사도 검증 테스트 모듈
테스트 패턴:
- uptrend: 상승 추세
- downtrend: 하락 추세
- peak: 산 모양 (올라갔다 내려옴)
- valley: 골짜기 (내려갔다 올라옴)
- sine: 사인파 (주기적 변동)
- flat: 평평함
평가 지표:
- Precision@K: 상위 K개 중 정답 비율
- Recall@K: 전체 정답 중 검색된 비율
- NDCG@K: 순위를 고려한 정규화된 누적 이득
실행 방법:
python3 tests/test_similarity_validation.py
✏️ 수정된 파일
1. DB/build_segments.py
변경 사항:
- 테이블 컬럼명 변경
- window_start → segment_start
- window_end → segment_end
- ma_window → ma_type (값: "MA20", "MA30")
- length → 제거 (항상 128)
- vec → vector
- stdev → volatility - 데이터 처리 변경
- MA20만 처리 (MA30 제거)
- DB에서 티커 자동 조회 (fetch_all_tickers())
- tickers_list.txt 의존성 제거
주요 함수:
def fetch_all_tickers(conn) -> list[str]:
"""DB의 prices 테이블에서 모든 티커 조회"""
실행 결과:
[INFO] Found {N} tickers in DB
[INFO] Processing MA20 only...
[OK] {ticker} MA20: inserted {count} segments
2. DB/ingest_prices.py
변경 사항:
- 데이터 소스 우선순위 변경
tickers_nasdaq.json > tickers_list.txt > NASDAQ API > FALLBACK - 신규 함수 추가
def read_tickers_json(limit: int = 1000) -> List[str] | None:
"""data/tickers_nasdaq.json에서 상위 limit개 티커 읽기""" - 데이터 수집 설정 변경
- 티커 수: 200개 → 1000개
- 수집 기간: 3년 → 18개월 (300 거래일)
파일 경로:
DRS/
├── data/
│ └── tickers_nasdaq.json # 1000개 티커 (Market Cap 기준 정렬)
└── DB/
└── ingest_prices.py
3. app/config.py
추가된 설정:
PostgreSQL Settings
pg_host: str = "172.17.240.1"
pg_port: int = 5433
pg_database: str = "drs_db"
pg_user: str = "postgres"
pg_password: str = ""
pg_min_conn: int = 1
pg_max_conn: int = 10
Data Source Selection
data_source: str = "parquet" # "parquet" or "postgresql"
환경 변수 지원:
- .env 파일에서 PG_HOST, PG_PORT, DATA_SOURCE 등 오버라이드 가능
4. app/main.py
변경 사항:
- startup 이벤트 확장
@app.on_event("startup")
def warmup():PostgreSQL 연결 풀 초기화 (data_source="postgresql"인 경우)
if settings.data_source == "postgresql":
db_io.init_pool(...)
seg_count = db_io.get_segment_count()
logger.info(f"{seg_count} segments available") - 신규 엔드포인트: /similar_db
- PostgreSQL의 graph_segments 테이블에서 직접 벡터 검색
- 기존 /similar와 동일한 응답 형식
- Rate limit: 20/minute
요청 예시:
curl -X POST 'http://localhost:8080/similar_db'
-H 'Content-Type: application/json'
-d '{"y": [0.1, 0.2, ..., 0.5]}'
응답:
{
"items": [
{
"ticker": "AAPL",
"score": 0.876,
"rank": 1,
"series_norm": [...], // 128차원
"sketch_norm": [...] // 128차원
}
]
}
5. app/similar.py
변경 사항: ensemble_score() 개선
AS-IS (문제점):
d_norm = -d / len(sketch) # 음수 값
score = alpha * d_norm + beta * c + gamma * s # 범위 불일치
TO-BE (개선):
DTW 거리 → 유사도 변환 (0~1)
d_normalized = d / len(sketch)
dtw_similarity = 1.0 / (1.0 + d_normalized)
Pearson, Cosine: -11 → 01 변환
c_normalized = (c + 1.0) / 2.0
s_normalized = (s + 1.0) / 2.0
앙상블 (모두 0~1 범위)
score = alpha * dtw_similarity + beta * c_normalized + gamma * s_normalized
score = max(0.0, min(1.0, score)) # 클리핑
효과:
- 모든 유사도 지표가 0~1 범위로 정규화
- DTW 거리가 유사도로 올바르게 변환
- 앙상블 스코어의 해석 가능성 향상
🔄 워크플로우 변경
기존 워크플로우 (Parquet 기반)
- DB/ingest_prices.py → PostgreSQL에 데이터 적재
- app/main.py → /ingest 엔드포인트로 Parquet 생성
- app/main.py → /similar 엔드포인트로 검색
신규 워크플로우 (PostgreSQL 직접 사용)
- DB/ingest_prices.py → PostgreSQL에 데이터 적재
- DB/build_segments.py → graph_segments 테이블에 벡터 생성
- app/main.py → /similar_db 엔드포인트로 검색 (Parquet 불필요)
장점:
- Parquet 생성 단계 생략
- 대용량 데이터 처리 효율 (1000+ 티커)
- 실시간 업데이트 가능
📊 테이블 스키마 비교
graph_segments (변경 전 → 변경 후)
| 컬럼명 (AS-IS) | 컬럼명 (TO-BE) | 타입 | 설명 |
|---|---|---|---|
| window_start | segment_start | DATE | 세그먼트 시작일 |
| window_end | segment_end | DATE | 세그먼트 종료일 |
| ma_window | ma_type | VARCHAR(10) | "MA20" / "MA30" |
| length | (제거) | - | 항상 128 |
| vec | vector | REAL[] | 128차원 벡터 |
| stdev | volatility | REAL | 변동성 |
🧪 테스트 및 검증
- 유사도 알고리즘 검증
- 테스트 패턴 6종 (uptrend, downtrend, peak, valley, sine, flat)
- 노이즈 레벨별 검증 (low, high)
- 평가 지표: Precision@K, Recall@K, NDCG@K
- 실행 방법
테스트 실행
python3 tests/test_similarity_validation.py
결과 저장 위치
tests/results/validation_results.json
📝 설정 파일 예시
.env
PostgreSQL
PG_HOST=172.17.240.1
PG_PORT=5433
PG_DATABASE=drs_db
PG_USER=postgres
PG_PASSWORD=your_password
Data Source
DATA_SOURCE=postgresql # or "parquet"
API
API_KEY=your_api_key
🚀 실행 가이드
- 데이터 수집 (1000 티커)
cd DB
python3 ingest_prices.py
- 벡터 세그먼트 생성
python3 build_segments.py
- 서버 실행
cd ..
uvicorn app.main:app --host 0.0.0.0 --port 8080 --reload
- DB 기반 검색 테스트
curl -X POST 'http://localhost:8080/similar_db'
-H 'Content-Type: application/json'
-d '{"y": [0.1, 0.2, 0.3, 0.4, 0.5]}'
🎯 주요 개선 사항 요약
- PostgreSQL 직접 통합: Parquet 중간 단계 제거
- 대용량 데이터 처리: 200 → 1000 티커 지원
- 테이블 스키마 개선: 명확한 컬럼명, 불필요한 필드 제거
- 유사도 스코어 정규화: 0~1 범위 보장, 해석 가능성 향상
- 자동 테스트 추가: 객관적 검증 프레임워크
- 설정 관리 강화: 환경 변수 기반 유연한 설정