| | |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import com.google.common.reflect.TypeToken; |
| | | import com.google.gson.Gson; |
| | | import lombok.Data; |
| | | import org.apache.commons.lang.StringUtils; |
| | | import org.example.dao.CurrencyMapper; |
| | | import org.example.pojo.Currency; |
| | | import org.example.pojo.Market; |
| | | import org.example.pojo.bo.AsksBo; |
| | | import org.example.pojo.bo.BidsBo; |
| | | import org.example.pojo.bo.MarketBo; |
| | | import org.example.server.CurrencySerivce; |
| | | import org.example.util.RedisUtil; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import org.yaml.snakeyaml.error.Mark; |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.util.*; |
| | | import java.util.ArrayList; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * @program: demo |
| | |
| | | |
| | | private HashMap hashMap = new HashMap(); |
| | | private static final Gson gson = new Gson(); |
| | | private Set<String> keys; |
| | | private ArrayList<String> keys; |
| | | |
| | | List<MarketBo> mexcList = new ArrayList<>(); |
| | | List<MarketBo> gateList = new ArrayList<>(); |
| | | List<MarketBo> bitgetList = new ArrayList<>(); |
| | | List<MarketBo> kucoinList = new ArrayList<>(); |
| | | |
| | | @Override |
| | | public void start() throws JsonProcessingException { |
| | | Set<String> mexcSet = RedisUtil.keys("mexc"); |
| | |
| | | Set<String> bitgetSet = RedisUtil.keys("bitget"); |
| | | Set<String> kucoinSet = RedisUtil.keys("kucoin"); |
| | | |
| | | //这里做一个定时器,每10秒更新一次 |
| | | keys = RedisUtil.keys("*"); |
| | | |
| | | HashMap<String,Map<String, Object>> mexcMap = new HashMap<>(); |
| | | //这里做一个定时器,每10分钟更新一次 |
| | | Set<String> setKeys = RedisUtil.keys("*"); |
| | | keys = new ArrayList<>(setKeys); |
| | | for (String key : mexcSet) { |
| | | MarketBo marketBo = new MarketBo(); |
| | | |
| | | String v = RedisUtil.get(key); |
| | | Map<String, Object> redisValueMap = gson.fromJson(v, new TypeToken<Map<String, Object>>() {}.getType()); |
| | | mexcMap.put(key.replaceAll("mexc",""),redisValueMap); |
| | | String asks = redisValueMap.get("asks").toString(); |
| | | String bids = redisValueMap.get("bids").toString(); |
| | | |
| | | if(!asks.equals("[]") && !StringUtils.isEmpty(asks)){ |
| | | Gson gson = new Gson(); |
| | | AsksBo asksBo = new AsksBo(); |
| | | Market[] asksDataArray = gson.fromJson(asks, Market[].class); |
| | | Market asksElement = asksDataArray[0]; |
| | | asksBo.setP(asksElement.getP()); |
| | | asksBo.setV(asksElement.getV()); |
| | | marketBo.setAsks(asksBo); |
| | | } |
| | | |
| | | HashMap<String,List<HashMap<String,String>>> asksHashMapList = new HashMap<>(); |
| | | HashMap<String,Map<String, Object>> gateMap = new HashMap<>(); |
| | | if(!bids.equals("[]") && !StringUtils.isEmpty(bids)){ |
| | | BidsBo bidsBo = new BidsBo(); |
| | | Market[] bidsDataArray = gson.fromJson(bids, Market[].class); |
| | | Market bidsElement = bidsDataArray[bidsDataArray.length-1]; |
| | | bidsBo.setP(bidsElement.getP()); |
| | | bidsBo.setV(bidsElement.getV()); |
| | | marketBo.setBids(bidsBo); |
| | | } |
| | | marketBo.setKey(key.replaceAll("mexc","")); |
| | | marketBo.setExchange("mexc"); |
| | | mexcList.add(marketBo); |
| | | } |
| | | |
| | | |
| | | for (String key : gateSet) { |
| | | String v = RedisUtil.get(key); |
| | | Map<String, Object> redisValueMap = gson.fromJson(v, new TypeToken<Map<String, Object>>() {}.getType()); |
| | | String asks = redisValueMap.get("asks").toString(); |
| | | String bids = redisValueMap.get("bids").toString(); |
| | | |
| | | // 使用 Jackson 解析 JSON |
| | | ObjectMapper objectMapper = new ObjectMapper(); |
| | | JsonNode asksNode = objectMapper.readTree(asks); |
| | | JsonNode bidsNode = objectMapper.readTree(bids); |
| | | |
| | | // 将 "asks" 数组转换为 List<List<String>> |
| | | List<HashMap<String,String>> asksList = new ArrayList<>(); |
| | | for (JsonNode arrayNode : asksNode) { |
| | | HashMap<String,String> asksMap = new HashMap<>(); |
| | | asksMap.put("p",arrayNode.get(0).toString()); |
| | | asksMap.put("v",arrayNode.get(1).toString()); |
| | | asksList.add(asksMap); |
| | | } |
| | | for (JsonNode arrayNode : bidsNode) { |
| | | HashMap<String,String> asksMap = new HashMap<>(); |
| | | asksMap.put("p",arrayNode.get(0).toString()); |
| | | asksMap.put("v",arrayNode.get(1).toString()); |
| | | asksList.add(asksMap); |
| | | } |
| | | gateMap.put(key.replaceAll("gate",""),redisValueMap); |
| | | MarketBo marketBo = new MarketBo(); |
| | | if(!asks.equals("[]") && !StringUtils.isEmpty(asks)){ |
| | | String[][] dataArray = gson.fromJson(asks, String[][].class); |
| | | String[] asksData = dataArray[0]; |
| | | AsksBo asksBo = new AsksBo(); |
| | | asksBo.setP(new BigDecimal(asksData[0])); |
| | | asksBo.setV(new BigDecimal(asksData[1])); |
| | | marketBo.setAsks(asksBo); |
| | | } |
| | | |
| | | // HashMap<String,Map<String, Object>> bitgetMap = new HashMap<>(); |
| | | // for (String key : mexcSet) { |
| | | // String v = RedisUtil.get(key); |
| | | // Map<String, Object> redisValueMap = gson.fromJson(v, new TypeToken<Map<String, Object>>() {}.getType()); |
| | | // mexcMap.put(key.replaceAll("bitget",""),redisValueMap); |
| | | // } |
| | | // |
| | | // HashMap<String,Map<String, Object>> kucoinMap = new HashMap<>(); |
| | | // for (String key : mexcSet) { |
| | | // String v = RedisUtil.get(key); |
| | | // Map<String, Object> redisValueMap = gson.fromJson(v, new TypeToken<Map<String, Object>>() {}.getType()); |
| | | // mexcMap.put(key.replaceAll("kucoin",""),redisValueMap); |
| | | // } |
| | | |
| | | if(!bids.equals("[]") && !StringUtils.isEmpty(bids)){ |
| | | String[][] dataArray = gson.fromJson(bids, String[][].class); |
| | | String[] bidsData = dataArray[dataArray.length-1]; |
| | | BidsBo bidsBo = new BidsBo(); |
| | | bidsBo.setP(new BigDecimal(bidsData[0])); |
| | | bidsBo.setV(new BigDecimal(bidsData[1])); |
| | | marketBo.setBids(bidsBo); |
| | | } |
| | | marketBo.setKey(key.replaceAll("gate","")); |
| | | marketBo.setExchange("gate"); |
| | | gateList.add(marketBo); |
| | | } |
| | | |
| | | |
| | | for (String key : bitgetSet) { |
| | | String v = RedisUtil.get(key); |
| | | Map<String, Object> redisValueMap = gson.fromJson(v, new TypeToken<Map<String, Object>>() {}.getType()); |
| | | String asks = redisValueMap.get("asks").toString(); |
| | | String bids = redisValueMap.get("bids").toString(); |
| | | |
| | | MarketBo marketBo = new MarketBo(); |
| | | if(!asks.equals("[]") && !StringUtils.isEmpty(asks)){ |
| | | String[][] dataArray = gson.fromJson(asks, String[][].class); |
| | | String[] asksData = dataArray[0]; |
| | | AsksBo asksBo = new AsksBo(); |
| | | asksBo.setP(new BigDecimal(asksData[0])); |
| | | asksBo.setV(new BigDecimal(asksData[1])); |
| | | marketBo.setAsks(asksBo); |
| | | } |
| | | |
| | | if(!bids.equals("[]") && !StringUtils.isEmpty(bids)){ |
| | | String[][] dataArray = gson.fromJson(bids, String[][].class); |
| | | String[] bidsData = dataArray[dataArray.length-1]; |
| | | BidsBo bidsBo = new BidsBo(); |
| | | bidsBo.setP(new BigDecimal(bidsData[0])); |
| | | bidsBo.setV(new BigDecimal(bidsData[1])); |
| | | marketBo.setBids(bidsBo); |
| | | } |
| | | marketBo.setKey(key.replaceAll("bitget","")); |
| | | marketBo.setExchange("bitget"); |
| | | bitgetList.add(marketBo); |
| | | } |
| | | |
| | | |
| | | for (String key : kucoinSet) { |
| | | String v = RedisUtil.get(key); |
| | | Map<String, Object> redisValueMap = gson.fromJson(v, new TypeToken<Map<String, Object>>() {}.getType()); |
| | | String asks = redisValueMap.get("asks").toString(); |
| | | String bids = redisValueMap.get("bids").toString(); |
| | | |
| | | MarketBo marketBo = new MarketBo(); |
| | | if(!asks.equals("[]") && !StringUtils.isEmpty(asks)){ |
| | | String[][] dataArray = gson.fromJson(asks, String[][].class); |
| | | String[] asksData = dataArray[0]; |
| | | AsksBo asksBo = new AsksBo(); |
| | | asksBo.setP(new BigDecimal(asksData[0])); |
| | | asksBo.setV(new BigDecimal(asksData[1])); |
| | | marketBo.setAsks(asksBo); |
| | | } |
| | | |
| | | if(!bids.equals("[]") && !StringUtils.isEmpty(bids)){ |
| | | String[][] dataArray = gson.fromJson(bids, String[][].class); |
| | | String[] bidsData = dataArray[dataArray.length-1]; |
| | | BidsBo bidsBo = new BidsBo(); |
| | | bidsBo.setP(new BigDecimal(bidsData[0])); |
| | | bidsBo.setV(new BigDecimal(bidsData[1])); |
| | | marketBo.setBids(bidsBo); |
| | | } |
| | | marketBo.setKey(key.replaceAll("kucoin","")); |
| | | marketBo.setExchange("kucoin"); |
| | | kucoinList.add(marketBo); |
| | | } |
| | | testDemo(); |
| | | } |
| | | |
| | | // 计算利润百分比 |
| | | private static BigDecimal calculateProfitPercentage(BigDecimal buyPrice, BigDecimal sellPrice) { |
| | | BigDecimal profit = sellPrice.subtract(buyPrice); |
| | | if (buyPrice.compareTo(BigDecimal.ZERO) == 0) { |
| | | return BigDecimal.ZERO; // 防止除以零 |
| | | } |
| | | BigDecimal profitPercentage = profit.divide(buyPrice, 12, RoundingMode.DOWN).multiply(new BigDecimal(100)); |
| | | return profitPercentage; |
| | | } |
| | | |
| | | private static List<String> findProfitablePairs(List<MarketBo>... exchangeLists) { |
| | | List<String> result = new ArrayList<>(); |
| | | Map<String, Map<String, MarketBo>> marketMap = new HashMap<>(); |
| | | |
| | | // 按币种名称和交易所分组市场数据 |
| | | for (List<MarketBo> exchangeList : exchangeLists) { |
| | | for (MarketBo market : exchangeList) { |
| | | String coinName = market.getKey(); |
| | | String exchangeName = market.getExchange(); // 假设有获取交易所名称的方法 getExchange() |
| | | |
| | | // 如果该币种在该交易所不存在,则创建新的列表 |
| | | if (!marketMap.containsKey(coinName)) { |
| | | marketMap.put(coinName, new HashMap<>()); |
| | | } |
| | | if (!marketMap.get(coinName).containsKey(exchangeName)) { |
| | | marketMap.get(coinName).put(exchangeName, new MarketBo()); |
| | | } |
| | | |
| | | // 将市场数据添加到对应的交易所列表中 |
| | | marketMap.get(coinName).put(exchangeName,market); |
| | | } |
| | | } |
| | | marketMap = marketMap.entrySet().stream() |
| | | .filter(entry -> entry.getValue().size() != 1) |
| | | .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); |
| | | // 遍历每个币种 |
| | | for (String coinName : marketMap.keySet()) { |
| | | Map<String, MarketBo> exchangeMap = marketMap.get(coinName); |
| | | // 遍历每个交易所 |
| | | for (String exchangeName : exchangeMap.keySet()) { |
| | | MarketBo markets1 = exchangeMap.get(exchangeName); |
| | | // 在同一交易所中寻找有差价的交易对 |
| | | for (String exchangeName2 : exchangeMap.keySet()) { |
| | | MarketBo markets2 = exchangeMap.get(exchangeName2); |
| | | if(markets1.getExchange().equals(markets2.getExchange())){ |
| | | continue; |
| | | } |
| | | |
| | | if(null != markets1.getBids() && null != markets2.getAsks()){ |
| | | BigDecimal buyPrice = markets1.getBids().getP(); |
| | | BigDecimal sellPrice = markets2.getAsks().getP(); |
| | | // 计算利润百分比 |
| | | BigDecimal profitPercentage = calculateProfitPercentage(buyPrice, sellPrice); |
| | | |
| | | // 如果利润大于零,则添加到结果列表 |
| | | if (profitPercentage.compareTo(BigDecimal.ZERO) > 0) { |
| | | // 准备输出字符串 |
| | | String pair = String.format("%s: 在 %s 以 %s 买入,在 %s 以 %s 卖出,利润为 %.4f%%", |
| | | coinName, markets1.getExchange(), buyPrice, markets2.getExchange(), sellPrice, profitPercentage); |
| | | result.add(pair); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | |
| | | |
| | | public void testDemo(){ |
| | | List<String> profitablePairs = findProfitablePairs(mexcList, gateList, bitgetList, kucoinList); |
| | | |
| | | // 输出结果 |
| | | for (String pair : profitablePairs) { |
| | | System.out.println(pair); |
| | | } |
| | | } |
| | | |
| | | |
| | | } |