Skip to content

[BE] SISC1-56 [FEAT] 백테스팅 실행 api 구현#102

Merged
discipline24 merged 20 commits intomainfrom
SISC1-56-BE-백테스팅-실행-API-구현
Nov 14, 2025

Hidden character warning

The head ref may contain hidden characters: "SISC1-56-BE-\ubc31\ud14c\uc2a4\ud305-\uc2e4\ud589-API-\uad6c\ud604"
Merged

[BE] SISC1-56 [FEAT] 백테스팅 실행 api 구현#102
discipline24 merged 20 commits intomainfrom
SISC1-56-BE-백테스팅-실행-API-구현

Conversation

@discipline24
Copy link
Contributor

@discipline24 discipline24 commented Nov 13, 2025

Summary by CodeRabbit

  • 새로운 기능

    • 백테스트 요청에 기본 청산 기간(defaultExitDays) 옵션 추가
    • 개별 매수/매도 거래 기록(TradeLog)과 일별 성과 기반 메트릭(일별 수익, MDD, 샤프, 평균 보유일, 거래수) 제공
    • 백테스트 응답이 실행 정보와 메트릭을 함께 반환하도록 결과 구조 개선
  • 버그 수정

    • 백테스트 조회/실행 시 소유권 검증 및 입력 유효성 검사 강화
  • 문서화

    • 템플릿 및 요청 필드에 API 설명(스웨거) 추가
  • 테스트

    • 변경된 응답 구조에 따른 테스트 수정 및 검증 업데이트

customUserDetails에 user 추가 후, 반환시 해당 객체 넣음으로써 해결
userRepository 이용하여 DB 접근으로 해결
# Conflicts:
#	.gitignore
#	backend/src/main/java/org/sejongisc/backend/backtest/repository/BacktestRunRepository.java
#	backend/src/main/java/org/sejongisc/backend/template/service/TemplateService.java
#	backend/src/main/java/org/sejongisc/backend/user/entity/User.java
@coderabbitai
Copy link

coderabbitai bot commented Nov 13, 2025

Walkthrough

백테스팅 관련 DTO, 서비스, 엔진 및 보조 유틸이 리팩토링되었습니다. 요청 DTO에 필드가 추가되고 응답 구조가 단순화되었으며 거래 로그·지표 응답 타입이 추가되고, 지표 계산·리포지토리 조회·템플릿·사용자 조회 흐름이 변경되었습니다.

Changes

코호트 / 파일(s) 요약
요청 DTO 변경
backend/src/main/java/org/sejongisc/backend/backtest/dto/BacktestRequest.java
int defaultExitDays 필드 추가(@Schema로 설명)
응답 DTO 구조 변경
backend/src/main/java/org/sejongisc/backend/backtest/dto/BacktestResponse.java
여러 스칼라/참조 필드 제거 후 backtestRunbacktestRunMetricsResponse 필드로 구조 단순화
신규 DTO / 로그 타입
backend/src/main/java/org/sejongisc/backend/backtest/dto/BacktestRunMetricsResponse.java, backend/src/main/java/org/sejongisc/backend/backtest/dto/TradeLog.java
BacktestRunMetricsResponse 신규 추가 (id, totalReturn, maxDrawdown, sharpeRatio, avgHoldDays, tradesCount, fromEntity); TradeLog 신규 추가(타입 enum, time/price/shares 필드)
DTO 내부 변경
backend/src/main/java/org/sejongisc/backend/backtest/dto/StrategyOperand.java
@AllArgsConstructor 제거, @Setter 추가로 세터 제공(기존 필드 유지)
리포지토리 확장
backend/src/main/java/org/sejongisc/backend/backtest/repository/BacktestRunRepository.java
findByIdWithMember(Long) 추가 — template LEFT JOIN FETCH 및 user JOIN FETCH, Optional 반환
백테스트 서비스 리팩토링
backend/src/main/java/org/sejongisc/backend/backtest/service/BacktestService.java
사용자 조회를 UserRepository로 전환; 응답을 backtestRun/backtestRunMetricsResponse로 조립; 완료 여부에 따라 메트릭 포함 조건 분기; findByIdWithMember 사용해 소유권 검증
백테스팅 엔진 개선
backend/src/main/java/org/sejongisc/backend/backtest/service/BacktestingEngine.java
거래 기록(TradeLog) 추가, 일별 포트폴리오값·수익률·MDD 추적, Sharpe·평균 보유일 계산 분리(calculateMetrics 등), 오류 처리 및 종료 타임스탬프 보장
TA4J 헬퍼 리팩토링
backend/src/main/java/org/sejongisc/backend/backtest/service/Ta4jHelperService.java
switch 표현식 도입, validateOperand 추가, MACD 출력 처리 재구성 등 지표/오퍼랜드 생성 흐름 정리
템플릿 관련 변경
backend/src/main/java/org/sejongisc/backend/template/controller/TemplateController.java, .../service/TemplateService.java, .../dto/TemplateRequest.java
updateTemplate에서 인증 사용자 ID 주입; EntityManager 제거 및 UserRepository 사용; TemplateRequest에 @Schema 주석 추가(문서화)
불필요 import 정리
backend/src/main/java/org/sejongisc/backend/point/service/PointHistoryService.java
사용되지 않는 OptimisticLock 관련 import 삭제
테스트 업데이트
backend/src/test/java/org/sejongisc/backend/backtest/service/BacktestServiceTest.java
어설션에서 getBacktestRunMetrics()getBacktestRunMetricsResponse()로 변경
엔티티 주석 변경
backend/src/main/java/org/sejongisc/backend/backtest/entity/BacktestRunMetrics.java
maxDrawdown 주석을 "퍼센티지로 계산됨"으로 수정 (기능 영향 없음)

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant BacktestService
    participant BacktestRunRepository
    participant BacktestingEngine
    participant BacktestRunMetricsRepo
    participant ResponseBuilder

    rect rgb(235,245,235)
    Note over Client,ResponseBuilder: 백테스트 실행 흐름 (요약)
    Client->>BacktestService: runBacktest(request with defaultExitDays)
    BacktestService->>BacktestRunRepository: save(backtestRun)
    BacktestRunRepository-->>BacktestService: backtestRun (with member/template)
    BacktestService->>BacktestingEngine: execute(backtestRun)
    BacktestingEngine-->>BacktestService: BacktestRunMetrics + TradeLogs
    BacktestService->>BacktestRunMetricsRepo: save(metrics)
    BacktestService->>ResponseBuilder: build(backtestRun, metricsResponse)
    ResponseBuilder-->>Client: backtestRun + backtestRunMetricsResponse
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60분

  • 추가로 주의할 파일/영역:
    • backend/.../BacktestingEngine.java: 일별 수익률, MDD, Sharpe 및 평균 보유일 계산 로직 검증
    • backend/.../Ta4jHelperService.java: 지표 생성 경로 변경에 따른 엣지케이스 확인
    • backend/.../BacktestService.java: 응답 구조 변경(직렬화/호환성) 및 소유권 검증(findByIdWithMember) 검토
    • DTO 변경(BacktestResponse, BacktestRunMetricsResponse): 직렬화/역직렬화 영향 점검
    • StrategyOperand 생성자→세터 변경으로 인한 호출부 영향 확인

Possibly related PRs

Suggested reviewers

  • Kosw6
  • ochanhyeok

🐰 포지션 찍고 로그 남기네,
캔들 아래 당근 한 줌, 지표가 반짝이네.
DTO는 가벼워지고 엔진은 분주해도,
토끼한테는 코드 리뷰가 축제일 뿐이네. 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 백테스팅 실행 API 구현이라는 주요 변경 사항을 명확하게 요약하며, 변경 세트의 핵심 목표와 일치합니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch SISC1-56-BE-백테스팅-실행-API-구현

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/src/main/java/org/sejongisc/backend/backtest/dto/BacktestResponse.java (1)

8-12: 불필요한 import 때문에 빌드가 깨집니다
현재 DTO는 BacktestRunBacktestRunMetricsResponse만 사용하지만 BacktestStatus, Template, LocalDate import가 그대로 남아 있어 javac가 unused import 오류를 발생시킵니다. 모두 제거해주세요.

-import org.sejongisc.backend.backtest.entity.BacktestStatus;
-import org.sejongisc.backend.template.entity.Template;
-
-import java.time.LocalDate;
🧹 Nitpick comments (3)
backend/src/main/java/org/sejongisc/backend/backtest/dto/StrategyOperand.java (2)

7-7: 사용하지 않는 import를 정리하세요.

@Setter 어노테이션이 추가되었지만, 4번 라인의 lombok.AllArgsConstructor import는 더 이상 사용되지 않습니다. 코드 품질을 위해 제거해 주세요.

다음과 같이 수정하세요:

-import lombok.AllArgsConstructor;

Also applies to: 18-18


39-39: 주석 처리된 코드는 제거를 고려하세요.

향후 적용 예정인 필드를 주석으로 남겨두는 것보다는, 실제로 필요할 때 추가하거나 별도 이슈로 관리하는 것이 코드 가독성에 더 좋습니다.

backend/src/main/java/org/sejongisc/backend/backtest/dto/BacktestRequest.java (1)

38-40: 유효성 검증 어노테이션 추가를 고려하세요.

defaultExitDays 필드에 값의 범위를 제한하는 유효성 검증이 없습니다. 비즈니스 로직에 따라 음수 값이나 과도하게 큰 값을 방지하기 위한 제약 조건을 추가하는 것이 좋습니다.

예를 들어, 다음과 같이 검증 어노테이션을 추가할 수 있습니다:

+ import jakarta.validation.constraints.Min;
+ import jakarta.validation.constraints.Max;

  @Schema(description = "기본 청산 기간")
+ @Min(value = 1, message = "기본 청산 기간은 최소 1일 이상이어야 합니다")
+ @Max(value = 365, message = "기본 청산 기간은 최대 365일을 초과할 수 없습니다")
  private Integer defaultExitDays;

참고: 실제 최소/최대 값은 비즈니스 요구사항에 맞게 조정하세요.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2fb2310 and 3afe57f.

📒 Files selected for processing (14)
  • backend/src/main/java/org/sejongisc/backend/backtest/dto/BacktestRequest.java (1 hunks)
  • backend/src/main/java/org/sejongisc/backend/backtest/dto/BacktestResponse.java (1 hunks)
  • backend/src/main/java/org/sejongisc/backend/backtest/dto/BacktestRunMetricsResponse.java (1 hunks)
  • backend/src/main/java/org/sejongisc/backend/backtest/dto/StrategyOperand.java (3 hunks)
  • backend/src/main/java/org/sejongisc/backend/backtest/dto/TradeLog.java (1 hunks)
  • backend/src/main/java/org/sejongisc/backend/backtest/repository/BacktestRunRepository.java (2 hunks)
  • backend/src/main/java/org/sejongisc/backend/backtest/service/BacktestService.java (7 hunks)
  • backend/src/main/java/org/sejongisc/backend/backtest/service/BacktestingEngine.java (3 hunks)
  • backend/src/main/java/org/sejongisc/backend/backtest/service/Ta4jHelperService.java (7 hunks)
  • backend/src/main/java/org/sejongisc/backend/point/service/PointHistoryService.java (0 hunks)
  • backend/src/main/java/org/sejongisc/backend/template/controller/TemplateController.java (1 hunks)
  • backend/src/main/java/org/sejongisc/backend/template/dto/TemplateRequest.java (2 hunks)
  • backend/src/main/java/org/sejongisc/backend/template/service/TemplateService.java (3 hunks)
  • backend/src/test/java/org/sejongisc/backend/backtest/service/BacktestServiceTest.java (1 hunks)
💤 Files with no reviewable changes (1)
  • backend/src/main/java/org/sejongisc/backend/point/service/PointHistoryService.java
🧰 Additional context used
🧬 Code graph analysis (3)
backend/src/main/java/org/sejongisc/backend/backtest/dto/BacktestRunMetricsResponse.java (1)
backend/src/main/java/org/sejongisc/backend/backtest/dto/BacktestResponse.java (1)
  • Getter (14-21)
backend/src/main/java/org/sejongisc/backend/backtest/service/BacktestingEngine.java (1)
backend/src/main/java/org/sejongisc/backend/backtest/dto/TradeLog.java (1)
  • TradeLog (6-19)
backend/src/main/java/org/sejongisc/backend/backtest/service/Ta4jHelperService.java (1)
backend/src/main/java/org/sejongisc/backend/backtest/service/BacktestingEngine.java (1)
  • Service (33-229)
🔇 Additional comments (4)
backend/src/main/java/org/sejongisc/backend/template/dto/TemplateRequest.java (1)

3-28: Swagger 문서화가 적절하게 추가되었습니다.

API 문서화를 위한 @Schema 어노테이션이 올바르게 적용되었습니다. 특히 userIdtemplateIdhidden = true로 설정한 것은 이 필드들이 클라이언트 요청 본문이 아닌 컨트롤러에서 주입되는 값임을 명확히 하여 적절합니다.

backend/src/main/java/org/sejongisc/backend/template/controller/TemplateController.java (1)

69-69: 인증된 사용자 ID 주입이 올바르게 추가되었습니다.

createTemplate 메서드(Line 57)와 동일한 패턴으로 인증된 사용자의 ID를 요청 객체에 주입하고 있습니다. 이는 클라이언트가 요청 본문에서 userId를 조작하는 것을 방지하여 보안을 강화하고 일관성을 보장합니다.

backend/src/main/java/org/sejongisc/backend/template/service/TemplateService.java (1)

48-51: 검증 완료: 변경사항은 적절합니다.

Template.of() 메서드 구현을 확인한 결과, 완전한 User 엔티티가 필요합니다. 메서드는 User 객체를 직접 저장하므로 (user(user)), UserRepository.findById()로 변경한 것은 올바른 결정입니다.

추가로 orElseThrow()를 통한 명시적 사용자 존재 검증은:

  • 잘못된 요청 처리 개선
  • LazyInitializationException 방지
  • 데이터 일관성 보장

이러한 이점이 DB 쿼리 추가 비용을 상쇄합니다.

backend/src/main/java/org/sejongisc/backend/backtest/service/Ta4jHelperService.java (1)

262-288: 입력 검증 강화 👍

validateOperand 덕분에 DTO 필드 누락이 조기에 감지되어 런타임 예외가 줄어들었습니다. 잘 반영되었습니다.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3afe57f and 6bb3d3b.

📒 Files selected for processing (2)
  • backend/src/main/java/org/sejongisc/backend/backtest/entity/BacktestRunMetrics.java (1 hunks)
  • backend/src/main/java/org/sejongisc/backend/backtest/service/BacktestService.java (7 hunks)
✅ Files skipped from review due to trivial changes (1)
  • backend/src/main/java/org/sejongisc/backend/backtest/entity/BacktestRunMetrics.java

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
backend/src/main/java/org/sejongisc/backend/backtest/service/BacktestService.java (1)

41-43: 응답 빌딩 로직의 중복을 제거하는 것을 고려해보세요.

backtestRun만 포함하는 BacktestResponse 빌딩 로직이 3곳에서 반복됩니다. 헬퍼 메서드로 추출하면 유지보수성이 향상됩니다.

다음과 같이 헬퍼 메서드를 추가할 수 있습니다:

+  private BacktestResponse createRunOnlyResponse(BacktestRun backtestRun) {
+    return BacktestResponse.builder()
+        .backtestRun(backtestRun)
+        .build();
+  }
+
   public BacktestResponse getBacktestStatus(Long backtestRunId, UUID userId) {
     log.info("백테스팅 실행 상태 조회를 시작합니다.");
     BacktestRun backtestRun = findBacktestRunByIdAndVerifyUser(backtestRunId, userId);
-    return BacktestResponse.builder()
-        .backtestRun(backtestRun)
-        .build();
+    return createRunOnlyResponse(backtestRun);
   }

Also applies to: 50-52, 111-113

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6bb3d3b and 5211c44.

📒 Files selected for processing (1)
  • backend/src/main/java/org/sejongisc/backend/backtest/service/BacktestService.java (7 hunks)
🔇 Additional comments (5)
backend/src/main/java/org/sejongisc/backend/backtest/service/BacktestService.java (5)

9-9: 새로운 의존성이 올바르게 추가되었습니다.

BacktestRunMetricsResponseUserRepository 임포트 및 필드 추가가 리팩토링된 응답 구조와 리포지토리 기반 사용자 조회를 지원하기 위해 적절하게 이루어졌습니다.

Also applies to: 19-19, 36-36


49-61: 이전 리뷰 이슈가 올바르게 해결되었습니다.

status != BacktestStatus.COMPLETED 조건 추가로 PENDING, RUNNING 등 미완료 상태에서의 404 예외 문제가 해결되었습니다. COMPLETED 상태일 때만 metrics를 조회하고, 그 외 상태에서는 backtestRun만 반환하는 로직이 정확합니다.


79-83: EntityManager에서 UserRepository로의 전환이 적절합니다.

사용자 조회를 EntityManager가 아닌 UserRepository를 통해 수행하도록 리팩토링한 것은 좋은 개선입니다. 코드가 더 명확해지고 repository 계층의 책임이 잘 분리되었습니다.


150-158: findByIdWithMember 사용으로 최적화되었습니다.

findById에서 findByIdWithMember로 변경하여 user 연관관계를 함께 페치하는 것은 N+1 문제를 방지하는 좋은 최적화입니다. Line 154에서 user.getUserId()를 접근하므로 fetch join이 필요한 변경입니다.


38-44: 원본 리뷰 의견의 주요 우려사항이 타당하지 않습니다.

코드를 검증한 결과, findByIdWithMember() 메서드가 다음과 같이 구현되어 있습니다:

@Query("SELECT br FROM BacktestRun br " +
       "LEFT JOIN FETCH br.template t " +
       "JOIN FETCH br.user u " +
       "WHERE br.id = :backtestRunId ")

문제점 분석:

  • templateuser 모두 JOIN FETCH로 조회되어 즉시 로딩(eager loading) 됩니다
  • BacktestRun 엔티티가 서비스에서 반환될 때 이미 완전히 초기화된 상태입니다
  • 따라서 응답 직렬화 시 LazyInitializationException 발생 가능성이 없습니다
  • @Transactional 부재는 문제가 되지 않습니다

남아있는 개선 제안:

  • Line 39의 log.info()는 단순 상태 조회 작업에는 과도할 수 있으므로 log.debug()로 변경 권장

Likely an incorrect or invalid review comment.

@discipline24 discipline24 merged commit a64f6bf into main Nov 14, 2025
1 check passed
@discipline24 discipline24 deleted the SISC1-56-BE-백테스팅-실행-API-구현 branch November 14, 2025 08:49
@discipline24 discipline24 restored the SISC1-56-BE-백테스팅-실행-API-구현 branch November 15, 2025 23:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant