AI 자동매매 매매 결정 엔드포인트 구현 - #8
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
✨ 작업 내용
Spring Boot가 호출할 첫 AI 엔드포인트
POST /internal/ai/trading-decisions를 요청 수신부터 결정 로그 기록까지 한 번에 관통시켰습니다.X-Internal-Api-Key검증 (app/shared/http.py){"error": {"code", "message"}}decision_logs에participant_id,ai_strategy컬럼 + 인덱스 추가🔍 리뷰 시 참고사항
왜 배관과 엔드포인트를 한 PR에 묶었는지
인증/에러 포맷만 먼저 올리면 검증할 대상이 없어 반쪽짜리가 됩니다. 이 PR이 만든 인증·로깅 유틸 위에 추천/피드백 엔드포인트는 라우터와 스키마만 얹으면 됩니다.
미들웨어 대신
DependsBaseHTTPMiddleware로 하면/health까지 막혀서 예외 경로를 또 만들어야 합니다. 라우터에dependencies=[Depends(verify_internal_api_key)]로 붙였고/health는 라우터 밖에 두었습니다.성공 응답을 감싸지 않은 이유
명세의 응답이 bare object (
{decisionId, action, probability, modelVersion}) 라 Spring 쪽에서 바로 역직렬화되도록 두었습니다. 에러 응답만 포맷을 통일했습니다.모델은 스텁입니다
모델 파일이 없으면 고정 확률
0.5+modelVersion: "stub-0"을 반환합니다. 학습된 LightGBM 이 나오면app/trading_ai/predictor.py의load_model()만 채우면 됩니다. SHAP 계산과shap_values기록도 그때 함께 붙입니다.컬럼 추가 vs JSONB
participantId/aiStrategy를feature_snapshotJSONB 에 넣지 않고 컬럼으로 뽑았습니다. 참가자별·전략별 성능 비교가 관측 대시보드의 축이라 집계와 인덱싱이 필요합니다. 기존 0001 이 Enum 을 native 대신 String + CHECK 로 구현했으므로 같은 패턴을 유지했습니다.features계산 주체명세대로 Spring 이 계산해서 보내는 구조로 구현했습니다.
CLAUDE.md의 "피처 엔지니어링은 이 서비스에서 계산" 문구와 어긋나므로 별도로 문서를 고쳐야 합니다.동작 확인 결과
200 {"decisionId":1,"action":"HOLD","probability":0.5,"modelVersion":"stub-0"}401 {"error":{"code":"UNAUTHORIZED",...}}422+ 누락 필드 목록/health(키 없이)200 {"status":"ok"}decision_logs에 행이 남고participant_id,ai_strategy,feature_snapshot이 모두 채워지는 것까지 확인했습니다. 마이그레이션은upgrade → downgrade -1 → upgrade왕복을 확인했습니다.참고: 로컬 환경 이슈 2건 (이 PR 범위 밖)
requirements.txt에 있는psycopg가 로컬.venv에 설치되어 있지 않아 alembic 이 실패했습니다. 리포 파일은 건드리지 않았습니다.compose.yml의 postgres 가 5432 를 쓰는데 다른 프로젝트 컨테이너가 이미 점유 중일 수 있습니다. 검증은 임시 컨테이너를 5433 에 띄워서 했습니다.✅ 체크리스트
.env.example등) 변경이 필요한 경우 작성 또는 수정했나요?📎 관련 이슈(선택)