전략시간봉 오류 재수정
This commit is contained in:
@@ -101,23 +101,33 @@ public class LiveStrategyEvaluator {
|
||||
ta4jStorage.getOrCreate(market, candleType).getBarCount());
|
||||
|
||||
for (GcLiveStrategySettings s : settings) {
|
||||
if (!Boolean.TRUE.equals(s.getIsLiveCheck())) continue;
|
||||
if (!"CANDLE_CLOSE".equals(s.getExecutionType())) continue;
|
||||
if (s.getStrategyId() == null) continue;
|
||||
if (!conditionTimeframes.usesTimeframe(s.getStrategyId(), candleType)) continue;
|
||||
|
||||
String result = evaluate(market, candleType, s.getStrategyId(),
|
||||
s.getPositionMode(), maturedIndex,
|
||||
s.getDeviceId(), s.getUserId());
|
||||
if (!"NONE".equals(result)) {
|
||||
log.info("[Evaluator] CANDLE_CLOSE {} {} idx={} mode={} → {}",
|
||||
market, candleType, maturedIndex, s.getPositionMode(), result);
|
||||
return result;
|
||||
}
|
||||
String result = evaluateSettingOnCandleClose(s, market, candleType, maturedIndex);
|
||||
if (!"NONE".equals(result)) return result;
|
||||
}
|
||||
return "NONE";
|
||||
}
|
||||
|
||||
/**
|
||||
* 단일 live 설정 — 봉 마감(CANDLE_CLOSE) 평가.
|
||||
*/
|
||||
public String evaluateSettingOnCandleClose(GcLiveStrategySettings s, String market,
|
||||
String candleType, int maturedIndex) {
|
||||
if (!Boolean.TRUE.equals(s.getIsLiveCheck())) return "NONE";
|
||||
if (!"CANDLE_CLOSE".equals(s.getExecutionType())) return "NONE";
|
||||
if (s.getStrategyId() == null) return "NONE";
|
||||
if (!ta4jStorage.exists(market, candleType)) return "NONE";
|
||||
if (!conditionTimeframes.usesTimeframe(s.getStrategyId(), candleType)) return "NONE";
|
||||
|
||||
String result = evaluate(market, candleType, s.getStrategyId(),
|
||||
s.getPositionMode(), maturedIndex,
|
||||
s.getDeviceId(), s.getUserId());
|
||||
if (!"NONE".equals(result)) {
|
||||
log.info("[Evaluator] CANDLE_CLOSE strategyId={} {} {} idx={} mode={} → {}",
|
||||
s.getStrategyId(), market, candleType, maturedIndex, s.getPositionMode(), result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 방식 B — 3초 스케줄러에서 호출.
|
||||
*
|
||||
@@ -141,37 +151,44 @@ public class LiveStrategyEvaluator {
|
||||
List<GcLiveStrategySettings> settings = settingsRepo.findActiveByMarket(market);
|
||||
if (settings.isEmpty()) return "NONE";
|
||||
|
||||
for (GcLiveStrategySettings s : settings) {
|
||||
String result = evaluateSettingRealtimeTick(s, market, candleType);
|
||||
if (!"NONE".equals(result)) return result;
|
||||
}
|
||||
return "NONE";
|
||||
}
|
||||
|
||||
/**
|
||||
* 단일 live 설정 — 3초 스케줄러(REALTIME_TICK) 평가.
|
||||
*/
|
||||
public String evaluateSettingRealtimeTick(GcLiveStrategySettings s, String market,
|
||||
String candleType) {
|
||||
if (!Boolean.TRUE.equals(s.getIsLiveCheck())) return "NONE";
|
||||
if (!"REALTIME_TICK".equals(s.getExecutionType())) return "NONE";
|
||||
if (s.getStrategyId() == null) return "NONE";
|
||||
if (!ta4jStorage.exists(market, candleType)) return "NONE";
|
||||
|
||||
BarSeries series = ta4jStorage.getOrCreate(market, candleType);
|
||||
if (series.isEmpty()) return "NONE";
|
||||
int currentIndex = series.getEndIndex();
|
||||
if (!conditionTimeframes.usesTimeframe(s.getStrategyId(), candleType)) return "NONE";
|
||||
|
||||
// 동일 provisional 봉에서 이미 시그널을 냈으면 중복 발화 방지
|
||||
String dedupeKey = market + ":" + candleType;
|
||||
String dedupeKey = market + ":" + candleType + ":" + s.getStrategyId();
|
||||
Integer lastSignaledIdx = realtimeSignaledIdx.get(dedupeKey);
|
||||
if (lastSignaledIdx != null && lastSignaledIdx == currentIndex) return "NONE";
|
||||
|
||||
for (GcLiveStrategySettings s : settings) {
|
||||
if (!Boolean.TRUE.equals(s.getIsLiveCheck())) continue;
|
||||
if (!"REALTIME_TICK".equals(s.getExecutionType())) continue;
|
||||
if (s.getStrategyId() == null) continue;
|
||||
if (!conditionTimeframes.usesTimeframe(s.getStrategyId(), candleType)) continue;
|
||||
String cacheKey = market + ":" + candleType + ":" + s.getStrategyId();
|
||||
triggerRulesCache.remove(cacheKey);
|
||||
|
||||
// ★ Ta4j CachedIndicator 캐시 무효화 — Rule 트리 재빌드
|
||||
String cacheKey = market + ":" + candleType + ":" + s.getStrategyId();
|
||||
triggerRulesCache.remove(cacheKey);
|
||||
|
||||
String result = evaluate(market, candleType, s.getStrategyId(),
|
||||
s.getPositionMode(), currentIndex,
|
||||
s.getDeviceId(), s.getUserId());
|
||||
if (!"NONE".equals(result)) {
|
||||
log.info("[Evaluator] REALTIME_TICK {} {} idx={} mode={} → {}",
|
||||
market, candleType, currentIndex, s.getPositionMode(), result);
|
||||
realtimeSignaledIdx.put(dedupeKey, currentIndex);
|
||||
return result;
|
||||
}
|
||||
String result = evaluate(market, candleType, s.getStrategyId(),
|
||||
s.getPositionMode(), currentIndex,
|
||||
s.getDeviceId(), s.getUserId());
|
||||
if (!"NONE".equals(result)) {
|
||||
log.info("[Evaluator] REALTIME_TICK strategyId={} {} {} idx={} mode={} → {}",
|
||||
s.getStrategyId(), market, candleType, currentIndex, s.getPositionMode(), result);
|
||||
realtimeSignaledIdx.put(dedupeKey, currentIndex);
|
||||
}
|
||||
return "NONE";
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,31 +209,39 @@ public class LiveStrategyEvaluator {
|
||||
public String evaluateRealtimeAtClose(String market, String candleType, int maturedIndex) {
|
||||
List<GcLiveStrategySettings> settings = settingsRepo.findActiveByMarket(market);
|
||||
if (settings.isEmpty()) return "NONE";
|
||||
if (!ta4jStorage.exists(market, candleType)) return "NONE";
|
||||
|
||||
for (GcLiveStrategySettings s : settings) {
|
||||
if (!Boolean.TRUE.equals(s.getIsLiveCheck())) continue;
|
||||
if (!"REALTIME_TICK".equals(s.getExecutionType())) continue;
|
||||
if (s.getStrategyId() == null) continue;
|
||||
if (!conditionTimeframes.usesTimeframe(s.getStrategyId(), candleType)) continue;
|
||||
|
||||
// CachedIndicator 캐시 무효화 — 확정봉의 최종 close 로 재계산
|
||||
String cacheKey = market + ":" + candleType + ":" + s.getStrategyId();
|
||||
triggerRulesCache.remove(cacheKey);
|
||||
|
||||
String result = evaluate(market, candleType, s.getStrategyId(),
|
||||
s.getPositionMode(), maturedIndex,
|
||||
s.getDeviceId(), s.getUserId());
|
||||
if (!"NONE".equals(result)) {
|
||||
log.info("[Evaluator] REALTIME_TICK @candle_close {} {} idx={} mode={} → {}",
|
||||
market, candleType, maturedIndex, s.getPositionMode(), result);
|
||||
realtimeSignaledIdx.put(market + ":" + candleType, maturedIndex);
|
||||
return result;
|
||||
}
|
||||
String result = evaluateSettingRealtimeAtClose(s, market, candleType, maturedIndex);
|
||||
if (!"NONE".equals(result)) return result;
|
||||
}
|
||||
return "NONE";
|
||||
}
|
||||
|
||||
/**
|
||||
* 단일 live 설정 — 봉 마감 시점 REALTIME_TICK 평가(교차 누락 방지).
|
||||
*/
|
||||
public String evaluateSettingRealtimeAtClose(GcLiveStrategySettings s, String market,
|
||||
String candleType, int maturedIndex) {
|
||||
if (!Boolean.TRUE.equals(s.getIsLiveCheck())) return "NONE";
|
||||
if (!"REALTIME_TICK".equals(s.getExecutionType())) return "NONE";
|
||||
if (s.getStrategyId() == null) return "NONE";
|
||||
if (!ta4jStorage.exists(market, candleType)) return "NONE";
|
||||
if (!conditionTimeframes.usesTimeframe(s.getStrategyId(), candleType)) return "NONE";
|
||||
|
||||
String cacheKey = market + ":" + candleType + ":" + s.getStrategyId();
|
||||
triggerRulesCache.remove(cacheKey);
|
||||
|
||||
String result = evaluate(market, candleType, s.getStrategyId(),
|
||||
s.getPositionMode(), maturedIndex,
|
||||
s.getDeviceId(), s.getUserId());
|
||||
if (!"NONE".equals(result)) {
|
||||
log.info("[Evaluator] REALTIME_TICK @candle_close strategyId={} {} {} idx={} mode={} → {}",
|
||||
s.getStrategyId(), market, candleType, maturedIndex, s.getPositionMode(), result);
|
||||
realtimeSignaledIdx.put(market + ":" + candleType + ":" + s.getStrategyId(), maturedIndex);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** 설정 변경 시 해당 마켓 캐시 무효화 */
|
||||
public void invalidateCache(String market) {
|
||||
triggerRulesCache.keySet().removeIf(k -> k.startsWith(market + ":"));
|
||||
|
||||
Reference in New Issue
Block a user