추세검색 설정 추가
This commit is contained in:
@@ -64,10 +64,11 @@ public class TrendSearchService {
|
||||
int wantBars = wantBarsForScan(r);
|
||||
int minBars = requiredMinBars(r);
|
||||
|
||||
List<String> markets = fetchKrwMarketsByVolume(scanLimit);
|
||||
KrwMarketSlice slice = fetchKrwMarketsByVolumeSlice(scanLimit);
|
||||
List<String> markets = slice.markets();
|
||||
if (markets.isEmpty()) return List.of();
|
||||
|
||||
Map<String, TickerSnap> tickers = fetchTickers(markets);
|
||||
Map<String, TickerSnap> tickers = fetchTickers(markets, slice.koreanNames());
|
||||
int minMatchRate = Math.min(100, Math.max(0, r.getMinMatchRate()));
|
||||
int enabledFilters = countEnabledFilters(r);
|
||||
boolean useBullishScore = r.isBullishTrendEnabled();
|
||||
@@ -84,7 +85,8 @@ public class TrendSearchService {
|
||||
BarSeries series = toSeries(candles, tf);
|
||||
if (series.getBarCount() < minBars) continue;
|
||||
|
||||
TickerSnap tick = tickers.getOrDefault(market, TickerSnap.empty(market));
|
||||
TickerSnap tick = tickers.getOrDefault(market,
|
||||
TickerSnap.empty(market, slice.koreanNames().get(market)));
|
||||
MetricValues m = computeMetrics(series, candles, tick, r);
|
||||
if (useBullishScore) {
|
||||
m.bullishTrendScore = computeBullishTrendScore(m, r);
|
||||
@@ -133,8 +135,9 @@ public class TrendSearchService {
|
||||
.market(market).matchRate(0).conditions(List.of()).build();
|
||||
}
|
||||
|
||||
Map<String, TickerSnap> tickers = fetchTickers(List.of(market));
|
||||
TickerSnap tick = tickers.getOrDefault(market, TickerSnap.empty(market));
|
||||
Map<String, String> koreanNames = fetchKoreanNamesForMarkets(List.of(market));
|
||||
Map<String, TickerSnap> tickers = fetchTickers(List.of(market), koreanNames);
|
||||
TickerSnap tick = tickers.getOrDefault(market, TickerSnap.empty(market, koreanNames.get(market)));
|
||||
BarSeries series = toSeries(candles, tf);
|
||||
MetricValues m = computeMetrics(series, candles, tick, r);
|
||||
if (r.isBullishTrendEnabled()) {
|
||||
@@ -675,7 +678,37 @@ public class TrendSearchService {
|
||||
|
||||
// ── Upbit helpers ───────────────────────────────────────────────────────
|
||||
|
||||
private List<String> fetchKrwMarketsByVolume(int limit) {
|
||||
private record KrwMarketSlice(List<String> markets, Map<String, String> koreanNames) {}
|
||||
|
||||
/** 거래대금 상위 KRW 마켓 + 한글명 (market/all 기준) */
|
||||
private KrwMarketSlice fetchKrwMarketsByVolumeSlice(int limit) {
|
||||
try {
|
||||
Map<String, String> allNames = fetchKoreanNamesFromMarketAll();
|
||||
if (allNames.isEmpty()) return new KrwMarketSlice(List.of(), Map.of());
|
||||
|
||||
List<String> krw = new ArrayList<>(allNames.keySet());
|
||||
Map<String, TickerSnap> tickers = fetchTickers(krw, allNames);
|
||||
List<String> sorted = krw.stream()
|
||||
.sorted(Comparator.comparingDouble((String m) ->
|
||||
tickers.getOrDefault(m, TickerSnap.empty(m, allNames.get(m))).accTradePrice24h).reversed())
|
||||
.limit(limit)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Map<String, String> names = new HashMap<>();
|
||||
for (String m : sorted) {
|
||||
names.put(m, allNames.getOrDefault(m, m.replace("KRW-", "")));
|
||||
}
|
||||
return new KrwMarketSlice(sorted, names);
|
||||
} catch (Exception e) {
|
||||
log.warn("[TrendSearch] market fetch fail: {}", e.getMessage());
|
||||
List<String> fallback = List.of("KRW-BTC", "KRW-ETH", "KRW-XRP", "KRW-SOL", "KRW-ADA");
|
||||
Map<String, String> names = new HashMap<>();
|
||||
for (String m : fallback) names.put(m, m.replace("KRW-", ""));
|
||||
return new KrwMarketSlice(fallback, names);
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> fetchKoreanNamesFromMarketAll() {
|
||||
try {
|
||||
WebClient client = webClientBuilder.baseUrl(upbitBaseUrl).build();
|
||||
String marketsJson = client.get()
|
||||
@@ -683,29 +716,36 @@ public class TrendSearchService {
|
||||
.retrieve()
|
||||
.bodyToMono(String.class)
|
||||
.block();
|
||||
if (marketsJson == null) return List.of();
|
||||
if (marketsJson == null) return Map.of();
|
||||
|
||||
List<Map<String, Object>> all = objectMapper.readValue(marketsJson, new TypeReference<>() {});
|
||||
List<String> krw = all.stream()
|
||||
.map(m -> (String) m.get("market"))
|
||||
.filter(m -> m != null && m.startsWith("KRW-"))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (krw.isEmpty()) return List.of();
|
||||
|
||||
Map<String, TickerSnap> tickers = fetchTickers(krw);
|
||||
return krw.stream()
|
||||
.sorted(Comparator.comparingDouble((String m) ->
|
||||
tickers.getOrDefault(m, TickerSnap.empty(m)).accTradePrice24h).reversed())
|
||||
.limit(limit)
|
||||
.collect(Collectors.toList());
|
||||
Map<String, String> names = new HashMap<>();
|
||||
for (Map<String, Object> m : all) {
|
||||
String market = (String) m.get("market");
|
||||
if (market == null || !market.startsWith("KRW-")) continue;
|
||||
Object kn = m.get("korean_name");
|
||||
if (kn != null && !kn.toString().isBlank()) {
|
||||
names.put(market, kn.toString());
|
||||
}
|
||||
}
|
||||
return names;
|
||||
} catch (Exception e) {
|
||||
log.warn("[TrendSearch] market fetch fail: {}", e.getMessage());
|
||||
return List.of("KRW-BTC", "KRW-ETH", "KRW-XRP", "KRW-SOL", "KRW-ADA");
|
||||
log.warn("[TrendSearch] korean names fetch fail: {}", e.getMessage());
|
||||
return Map.of();
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, TickerSnap> fetchTickers(List<String> markets) {
|
||||
private Map<String, String> fetchKoreanNamesForMarkets(List<String> markets) {
|
||||
if (markets.isEmpty()) return Map.of();
|
||||
Map<String, String> all = fetchKoreanNamesFromMarketAll();
|
||||
Map<String, String> out = new HashMap<>();
|
||||
for (String m : markets) {
|
||||
out.put(m, all.getOrDefault(m, m.replace("KRW-", "")));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private Map<String, TickerSnap> fetchTickers(List<String> markets, Map<String, String> koreanNames) {
|
||||
if (markets.isEmpty()) return Map.of();
|
||||
try {
|
||||
WebClient client = webClientBuilder.baseUrl(upbitBaseUrl).build();
|
||||
@@ -722,9 +762,12 @@ public class TrendSearchService {
|
||||
JsonNode arr = objectMapper.readTree(json);
|
||||
for (JsonNode n : arr) {
|
||||
String market = n.path("market").asText();
|
||||
String ko = koreanNames != null
|
||||
? koreanNames.getOrDefault(market, market.replace("KRW-", ""))
|
||||
: market.replace("KRW-", "");
|
||||
map.put(market, new TickerSnap(
|
||||
market,
|
||||
n.path("korean_name").asText(market),
|
||||
ko,
|
||||
n.path("trade_price").asDouble(0),
|
||||
n.path("signed_change_rate").asDouble(0) * 100,
|
||||
n.path("acc_trade_price_24h").asDouble(0)
|
||||
@@ -777,8 +820,11 @@ public class TrendSearchService {
|
||||
|
||||
private record TickerSnap(String market, String koreanName, double tradePrice,
|
||||
double changeRate, double accTradePrice24h) {
|
||||
static TickerSnap empty(String market) {
|
||||
return new TickerSnap(market, market.replace("KRW-", ""), 0, 0, 0);
|
||||
static TickerSnap empty(String market, String koreanName) {
|
||||
String ko = koreanName != null && !koreanName.isBlank()
|
||||
? koreanName
|
||||
: market.replace("KRW-", "");
|
||||
return new TickerSnap(market, ko, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user