전략평가 시 부하문제 개선
This commit is contained in:
@@ -56,6 +56,17 @@ public class BarBuilder {
|
||||
/** 진행 중인 1분봉 상태 (market → PartialBar) */
|
||||
private final ConcurrentHashMap<String, PartialBar> partialBars = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Bar 생성용 공유 팩토리 BarSeries.
|
||||
* barBuilder()는 Series 상태를 읽지 않고 BarBuilderFactory·NumFactory 만 참조하므로
|
||||
* 싱글턴으로 재사용해도 안전하다. 매번 BaseBarSeriesBuilder를 생성하는 낭비를 제거.
|
||||
*/
|
||||
private static final org.ta4j.core.BarSeries BAR_FACTORY_SERIES =
|
||||
new org.ta4j.core.BaseBarSeriesBuilder()
|
||||
.withBarBuilderFactory(new TimeBarBuilderFactory())
|
||||
.withNumFactory(DoubleNumFactory.getInstance())
|
||||
.build();
|
||||
|
||||
// ── 공개 API ──────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
@@ -175,14 +186,15 @@ public class BarBuilder {
|
||||
= java.util.Collections.unmodifiableList(closedUppers);
|
||||
barCloseEvalExecutor.execute(() -> {
|
||||
try {
|
||||
if (barCloseEvaluation.shouldEvaluateOnClose(market, "1m")) {
|
||||
BarSeries series1m = ta4jStorage.getOrCreate(market, "1m");
|
||||
barCloseEvaluation.onMaturedBarClose(market, "1m", series1m.getEndIndex(), confirmedBar);
|
||||
}
|
||||
// shouldEvaluateOnClose → onMaturedBarClose 를 분리 호출하면 findActiveByMarket DB 쿼리가
|
||||
// 타임프레임 수(최대 9+1=10)만큼 중복 실행된다.
|
||||
// onMaturedBarClose 내부가 이미 activeSettings 조회 + 빈 경우 early-return 처리하므로
|
||||
// shouldEvaluateOnClose 선행 체크를 제거하여 DB 쿼리를 타임프레임당 1회로 절감한다.
|
||||
BarSeries series1m = ta4jStorage.getOrCreate(market, "1m");
|
||||
barCloseEvaluation.onMaturedBarClose(market, "1m", series1m.getEndIndex(), confirmedBar);
|
||||
|
||||
for (UpperCloseInfo info : closedUppersSnap) {
|
||||
if (barCloseEvaluation.shouldEvaluateOnClose(market, info.type())) {
|
||||
barCloseEvaluation.onMaturedBarClose(market, info.type(), info.maturedIdx(), info.bar());
|
||||
}
|
||||
barCloseEvaluation.onMaturedBarClose(market, info.type(), info.maturedIdx(), info.bar());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[BarBuilder] Phase 2 전략 평가 오류 market={}: {}", market, e.getMessage(), e);
|
||||
@@ -232,15 +244,11 @@ public class BarBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
/** PartialBar → Ta4j Bar 변환 */
|
||||
/** PartialBar → Ta4j Bar 변환 — BAR_FACTORY_SERIES를 재사용하여 임시 BarSeries 생성 제거 */
|
||||
private Bar buildTa4jBar(PartialBar partial, Duration duration, ZonedDateTime endZdt) {
|
||||
BarSeries tmp = new org.ta4j.core.BaseBarSeriesBuilder()
|
||||
.withBarBuilderFactory(new TimeBarBuilderFactory())
|
||||
.withNumFactory(DoubleNumFactory.getInstance()) // Ta4j 0.22
|
||||
.build();
|
||||
// Ta4j 0.22: barBuilder().endTime() 은 Instant 파라미터
|
||||
Instant endInstant = endZdt.toInstant();
|
||||
return tmp.barBuilder()
|
||||
return BAR_FACTORY_SERIES.barBuilder()
|
||||
.timePeriod(duration)
|
||||
.endTime(endInstant)
|
||||
.openPrice(partial.open)
|
||||
|
||||
@@ -117,6 +117,16 @@ public class UpbitWebSocketClient {
|
||||
return wsClient != null && wsClient.isOpen();
|
||||
}
|
||||
|
||||
/** 마지막 연결 성공 시각 (ms) — staleness monitor 유예 기간 계산용 */
|
||||
public long getConnectedAtMs() {
|
||||
return connectedAtMs;
|
||||
}
|
||||
|
||||
/** 마지막 메시지 수신 시각 (ms) — WS 전체 건강 상태 확인용 */
|
||||
public long getLastMessageAtMs() {
|
||||
return lastMessageAtMs;
|
||||
}
|
||||
|
||||
public Map<String, Object> monitorSnapshot() {
|
||||
Map<String, Object> m = new LinkedHashMap<>();
|
||||
m.put("connected", isConnected());
|
||||
@@ -199,6 +209,8 @@ public class UpbitWebSocketClient {
|
||||
log.info("[UpbitWebSocketClient] 연결 성공");
|
||||
reconnectDelaySec = 2; // 재연결 딜레이 리셋
|
||||
connectedAtMs = System.currentTimeMillis();
|
||||
// 이전 연결의 오래된 타임스탬프를 초기화하여 재연결 직후 즉시 stale 판단 → 재연결 루프 방지
|
||||
activityTracker.resetAll();
|
||||
sendSubscribePacket();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user