Skip to content

AI 자동매매 매매 결정 엔드포인트 구현 - #8

Merged
cfcromn merged 6 commits into
developfrom
feature/trading-decision-endpoint
Aug 12, 2026
Merged

AI 자동매매 매매 결정 엔드포인트 구현#8
cfcromn merged 6 commits into
developfrom
feature/trading-decision-endpoint

Conversation

@cfcromn

@cfcromn cfcromn commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

✨ 작업 내용

이번 PR에서 어떤 작업을 했는지 간단히 요약해주세요.

Spring Boot가 호출할 첫 AI 엔드포인트 POST /internal/ai/trading-decisions 를 요청 수신부터 결정 로그 기록까지 한 번에 관통시켰습니다.

  • 내부 API 키 인증X-Internal-Api-Key 검증 (app/shared/http.py)
  • 공통 에러 응답 포맷 + 전역 예외 처리{"error": {"code", "message"}}
  • 요청/응답 Pydantic 스키마 — camelCase 변환 베이스를 두어 나머지 두 엔드포인트도 재사용
  • lifespan 모델 로딩 — LightGBM Booster 로드 (현재는 스텁)
  • 시장별 매매 임계값 — 시장 × 전략 조합별 BUY/SELL/HOLD 경계
  • 결정 로그 기록 유틸 — 추천 엔드포인트에서도 그대로 사용할 함수
  • 마이그레이션 0002decision_logsparticipant_id, ai_strategy 컬럼 + 인덱스 추가

🔍 리뷰 시 참고사항

  • 리뷰어가 알면 좋은 변경 이유, 배경, 고려했던 점 등을 적어주세요.

왜 배관과 엔드포인트를 한 PR에 묶었는지
인증/에러 포맷만 먼저 올리면 검증할 대상이 없어 반쪽짜리가 됩니다. 이 PR이 만든 인증·로깅 유틸 위에 추천/피드백 엔드포인트는 라우터와 스키마만 얹으면 됩니다.

미들웨어 대신 Depends
BaseHTTPMiddleware 로 하면 /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.pyload_model() 만 채우면 됩니다. SHAP 계산과 shap_values 기록도 그때 함께 붙입니다.

컬럼 추가 vs JSONB
participantId / aiStrategyfeature_snapshot JSONB 에 넣지 않고 컬럼으로 뽑았습니다. 참가자별·전략별 성능 비교가 관측 대시보드의 축이라 집계와 인덱싱이 필요합니다. 기존 0001 이 Enum 을 native 대신 String + CHECK 로 구현했으므로 같은 패턴을 유지했습니다.

features 계산 주체
명세대로 Spring 이 계산해서 보내는 구조로 구현했습니다. CLAUDE.md 의 "피처 엔지니어링은 이 서비스에서 계산" 문구와 어긋나므로 별도로 문서를 고쳐야 합니다.

동작 확인 결과

요청 응답
정상 (US/STABLE) 200 {"decisionId":1,"action":"HOLD","probability":0.5,"modelVersion":"stub-0"}
키 없음 / 틀린 키 401 {"error":{"code":"UNAUTHORIZED",...}}
body 필드 누락 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 에 띄워서 했습니다.

✅ 체크리스트

  • 문서(README, .env.example 등) 변경이 필요한 경우 작성 또는 수정했나요?
  • 작업한 코드가 정상적으로 동작하는 것을 직접 확인했나요?
  • 필요한 경우 테스트 코드를 작성하거나 수정했나요?
  • Merge 대상 브랜치를 올바르게 설정했나요?
  • PR에 관련 없는 작업이 포함되지 않았나요?
  • 적절한 라벨과 리뷰어를 설정했나요? (라벨만 설정, 리뷰어 미지정)

📎 관련 이슈(선택)

  • 없음

@cfcromn cfcromn added ✅ Test Test관련사항 ✨ Feature 신규 기능 labels Aug 10, 2026
@cfcromn
cfcromn merged commit 570a320 into develop Aug 12, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 신규 기능 ✅ Test Test관련사항

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant