package com.yami.trading.huobi.tradingview;
|
|
import com.yami.trading.bean.item.domain.Item;
|
import org.apache.commons.lang3.StringUtils;
|
|
import java.util.ArrayList;
|
import java.util.LinkedHashSet;
|
import java.util.List;
|
import java.util.Locale;
|
import java.util.Set;
|
|
/**
|
* 将品种配置解析为 TradingView 可识别的 symbol(含交易所前缀)。
|
*/
|
public final class TradingViewSymbolResolver {
|
|
private static final String[] US_EXCHANGES = {"NYSE", "NASDAQ", "AMEX", "OTC", "CBOE"};
|
|
private TradingViewSymbolResolver() {
|
}
|
|
public static List<String> resolveCandidates(Item item) {
|
Set<String> candidates = new LinkedHashSet<>();
|
if (item == null) {
|
return new ArrayList<>();
|
}
|
|
String symbolData = StringUtils.trimToEmpty(item.getSymbolData());
|
String symbol = StringUtils.trimToEmpty(item.getSymbol());
|
String code = StringUtils.isNotBlank(symbolData) ? symbolData : symbol;
|
if (StringUtils.isBlank(code)) {
|
return new ArrayList<>();
|
}
|
|
if (code.contains(":")) {
|
candidates.add(code);
|
return new ArrayList<>(candidates);
|
}
|
|
String type = StringUtils.defaultString(item.getType());
|
String openCloseType = StringUtils.defaultString(item.getOpenCloseType());
|
|
if (Item.HK_STOCKS.equalsIgnoreCase(openCloseType) || Item.HK_STOCKS.equalsIgnoreCase(type)) {
|
String numeric = code.replaceAll("\\D", "");
|
if (StringUtils.isNotBlank(numeric)) {
|
candidates.add("HKEX:" + numeric);
|
}
|
candidates.add("HKEX:" + code);
|
return new ArrayList<>(candidates);
|
}
|
|
if (Item.forex.equalsIgnoreCase(type)) {
|
candidates.add("FX_IDC:" + code);
|
candidates.add("OANDA:" + code);
|
candidates.add("FX:" + code);
|
return new ArrayList<>(candidates);
|
}
|
|
if (isUsLike(item, type, openCloseType)) {
|
addUsExchangeCandidates(candidates, code, item.getMarket());
|
}
|
|
if (Item.TW_STOCKS.equalsIgnoreCase(type)) {
|
candidates.add("TWSE:" + code);
|
}
|
|
candidates.add(code);
|
return new ArrayList<>(candidates);
|
}
|
|
private static boolean isUsLike(Item item, String type, String openCloseType) {
|
if (Item.US_STOCKS.equalsIgnoreCase(type) || Item.US_ETF.equalsIgnoreCase(type)
|
|| Item.US_STOCKS.equalsIgnoreCase(openCloseType) || Item.US_ETF.equalsIgnoreCase(item.getMarket())) {
|
return true;
|
}
|
return type.contains("stock") || type.contains("ETF")
|
|| Item.indices.equalsIgnoreCase(type);
|
}
|
|
private static void addUsExchangeCandidates(Set<String> candidates, String code, String market) {
|
if (StringUtils.isNotBlank(market) && market.contains(":")) {
|
candidates.add(market.toUpperCase(Locale.ROOT));
|
return;
|
}
|
if (StringUtils.isNotBlank(market)) {
|
String upperMarket = market.toUpperCase(Locale.ROOT);
|
for (String exchange : US_EXCHANGES) {
|
if (upperMarket.contains(exchange)) {
|
candidates.add(exchange + ":" + code);
|
return;
|
}
|
}
|
}
|
for (String exchange : US_EXCHANGES) {
|
candidates.add(exchange + ":" + code);
|
}
|
}
|
}
|