package com.goldenchart.service; import com.goldenchart.dto.BacktestSettingsDto; import com.goldenchart.entity.GcBacktestSettings; import com.goldenchart.repository.GcBacktestSettingsRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor public class BacktestSettingsService { private final GcBacktestSettingsRepository repo; /** device_id 기준 설정 조회 — 없으면 기본값 반환 */ @Transactional(readOnly = true) public BacktestSettingsDto get(String deviceId) { return repo.findFirstByDeviceIdOrderByUpdatedAtDesc(deviceId) .map(this::toDto) .orElseGet(BacktestSettingsDto::new); } /** upsert — 기존 설정이 있으면 덮어쓰기, 없으면 새 행 삽입 */ @Transactional public BacktestSettingsDto save(String deviceId, BacktestSettingsDto dto) { GcBacktestSettings entity = repo .findFirstByDeviceIdOrderByUpdatedAtDesc(deviceId) .orElseGet(GcBacktestSettings::new); entity.setDeviceId(deviceId); entity.setInitialCapital(dto.getInitialCapital()); entity.setCommissionType(dto.getCommissionType()); entity.setCommissionRate(dto.getCommissionRate()); entity.setSlippageRate(dto.getSlippageRate()); entity.setEntryPriceType(dto.getEntryPriceType()); entity.setExitPriceType(dto.getExitPriceType()); entity.setPositionDirection(dto.getPositionDirection()); entity.setTradeSizeType(dto.getTradeSizeType()); entity.setTradeSizeValue(dto.getTradeSizeValue()); entity.setStopLossEnabled(dto.getStopLossEnabled()); entity.setStopLossPct(dto.getStopLossPct()); entity.setTakeProfitEnabled(dto.getTakeProfitEnabled()); entity.setTakeProfitPct(dto.getTakeProfitPct()); entity.setTrailingStopEnabled(dto.getTrailingStopEnabled()); entity.setTrailingStopPct(dto.getTrailingStopPct()); entity.setReentryWaitBars(dto.getReentryWaitBars()); entity.setMaxOpenTrades(dto.getMaxOpenTrades()); entity.setPartialExitEnabled(dto.getPartialExitEnabled()); entity.setPartialExitPct(dto.getPartialExitPct()); entity.setPositionMode( "SIGNAL_ONLY".equals(dto.getPositionMode()) ? "SIGNAL_ONLY" : "LONG_ONLY"); return toDto(repo.save(entity)); } // ── 변환 헬퍼 ───────────────────────────────────────────────────────────── private BacktestSettingsDto toDto(GcBacktestSettings e) { return BacktestSettingsDto.builder() .id(e.getId()) .initialCapital(e.getInitialCapital()) .commissionType(e.getCommissionType()) .commissionRate(e.getCommissionRate()) .slippageRate(e.getSlippageRate()) .entryPriceType(e.getEntryPriceType()) .exitPriceType(e.getExitPriceType()) .positionDirection(e.getPositionDirection()) .tradeSizeType(e.getTradeSizeType()) .tradeSizeValue(e.getTradeSizeValue()) .stopLossEnabled(e.getStopLossEnabled()) .stopLossPct(e.getStopLossPct()) .takeProfitEnabled(e.getTakeProfitEnabled()) .takeProfitPct(e.getTakeProfitPct()) .trailingStopEnabled(e.getTrailingStopEnabled()) .trailingStopPct(e.getTrailingStopPct()) .reentryWaitBars(e.getReentryWaitBars()) .maxOpenTrades(e.getMaxOpenTrades()) .partialExitEnabled(e.getPartialExitEnabled()) .partialExitPct(e.getPartialExitPct()) .positionMode(e.getPositionMode() != null ? e.getPositionMode() : "LONG_ONLY") .build(); } }