From 91bbc719126310f09031e55967c059c0a01f20b1 Mon Sep 17 00:00:00 2001
From: zyy3 <zyy3@zy.com>
Date: Wed, 05 Nov 2025 18:50:49 +0800
Subject: [PATCH] 1

---
 trading-order-admin/src/main/java/com/yami/trading/api/controller/KlineController.java       |   16 +++
 trading-order-huobi/src/main/java/com/yami/trading/huobi/data/internal/KlineService.java     |    7 +
 trading-order-huobi/src/main/java/com/yami/trading/huobi/jsws/WebsocketRunClient.java        |   19 +++-
 trading-order-huobi/src/main/java/com/yami/trading/huobi/data/internal/KlineServiceImpl.java |   52 +++++++++++++
 trading-order-service/src/main/java/com/yami/trading/service/item/ItemService.java           |   18 ++++
 trading-order-admin/src/main/java/com/yami/trading/admin/task/StockTask.java                 |   85 +++++++++++----------
 trading-order-huobi/src/main/java/com/yami/trading/huobi/jsws/WebSocketClientBeanConfig.java |   13 +++
 7 files changed, 160 insertions(+), 50 deletions(-)

diff --git a/trading-order-admin/src/main/java/com/yami/trading/admin/task/StockTask.java b/trading-order-admin/src/main/java/com/yami/trading/admin/task/StockTask.java
index b152b1d..a2959a3 100644
--- a/trading-order-admin/src/main/java/com/yami/trading/admin/task/StockTask.java
+++ b/trading-order-admin/src/main/java/com/yami/trading/admin/task/StockTask.java
@@ -79,6 +79,8 @@
         }
     }
 
+
+
     /**
      * 加载所有股票数据
      */
@@ -111,55 +113,54 @@
                     .eq("type", Item.indices));
 
             log.info("同步股票 已有数据 {} 获取数据 {}", stockList.size(), list.size());
-            System.out.println(stockList);
             List<Item> updateStockList = new ArrayList<>();
             for (StockRealTimeBean o : list) {
                 //System.out.println(o);
+                Item indices = indicesList.stream()
+                        .filter(x -> x.getSymbol().equals(o.getSymbol()))
+                        .findFirst()
+                        .orElse(null);
+                if (indices != null) {  //指数不添加
+                    continue;
+                }
+
+
                 Item item = stockList.stream()
                         .filter(x -> x.getSymbol().equals(o.getSymbol()) &&
                                 x.getStockCode().equals(o.getId()))
                         .findFirst()
                         .orElse(null);
-                if (item != null) {  //已有不添加
-                    continue;
-                }
-                item = indicesList.stream()
-                        .filter(x -> x.getSymbol().equals(o.getSymbol()))
-                        .findFirst()
-                        .orElse(null);
-                if (item != null) {  //已有不添加
-                    continue;
-                }
+                if (item == null) {
+                    item = new Item();
+                    String name = StringUtils.trim(o.getName());
+                    item.setEnName(name);
+                    item.setName(name);
+                    item.setSymbolFullName(name);
+                    item.setSymbol(o.getSymbol());
+                    item.setSymbolData(o.getSymbol());
+                    item.setPips(BigDecimal.valueOf(0.01).doubleValue());
+                    item.setPipsAmount(BigDecimal.valueOf(0.02).doubleValue());
+                    item.setAdjustmentValue(BigDecimal.ZERO.doubleValue());
+                    item.setUnitAmount(BigDecimal.valueOf(1000).doubleValue());
+                    item.setUnitFee(BigDecimal.valueOf(30).doubleValue());
+                    item.setMarket("FOREVER");
+                    item.setDecimals(2);
+                    item.setMultiple(BigDecimal.ZERO.doubleValue());
+                    item.setBorrowingRate(BigDecimal.ZERO.doubleValue());
+                    item.setDelFlag(0);
+                    item.setType(Item.US_STOCKS);
+                    item.setCategory(Item.US_STOCKS);
+                    item.setSorted("100");
+                    item.setOpenCloseType(Item.US_STOCKS);
+                    item.setFake("0");
+                    item.setShowStatus("1");
+                    item.setTradeStatus("1");
+                    item.setQuoteCurrency("USDT");
+                    item.setCrawlStatus("default_active");
+                    item.setStockCode(o.getId());
 
-                item = new Item();
-                String name = StringUtils.trim(o.getName());
-                item.setEnName(name);
-                item.setName(name);
-                item.setSymbolFullName(name);
-                item.setSymbol(o.getSymbol());
-                item.setSymbolData(o.getSymbol());
-                item.setPips(BigDecimal.valueOf(0.01).doubleValue());
-                item.setPipsAmount(BigDecimal.valueOf(0.02).doubleValue());
-                item.setAdjustmentValue(BigDecimal.ZERO.doubleValue());
-                item.setUnitAmount(BigDecimal.valueOf(1000).doubleValue());
-                item.setUnitFee(BigDecimal.valueOf(30).doubleValue());
-                item.setMarket("FOREVER");
-                item.setDecimals(2);
-                item.setMultiple(BigDecimal.ZERO.doubleValue());
-                item.setBorrowingRate(BigDecimal.ZERO.doubleValue());
-                item.setDelFlag(0);
-                item.setType(Item.US_STOCKS);
-                item.setCategory(Item.US_STOCKS);
-                item.setSorted("100");
-                item.setOpenCloseType(Item.US_STOCKS);
-                item.setFake("0");
-                item.setShowStatus("1");
-                item.setTradeStatus("1");
-                item.setQuoteCurrency("USDT");
-                item.setCrawlStatus("default_active");
-                item.setStockCode(o.getId());
-
-                updateStockList.add(item);
+                    updateStockList.add(item);
+                }
 
 
                 Realtime realtime = new Realtime();
@@ -191,6 +192,10 @@
         }
     }
 
+
+
+
+
     public static void main(String[] args) {
         StockTask task = new StockTask();
         task.loadAllStock(EStockType.US);
diff --git a/trading-order-admin/src/main/java/com/yami/trading/api/controller/KlineController.java b/trading-order-admin/src/main/java/com/yami/trading/api/controller/KlineController.java
index e9e33e8..f1d50ee 100644
--- a/trading-order-admin/src/main/java/com/yami/trading/api/controller/KlineController.java
+++ b/trading-order-admin/src/main/java/com/yami/trading/api/controller/KlineController.java
@@ -8,6 +8,7 @@
 import com.yami.trading.common.web.ResultObject;
 import com.yami.trading.huobi.constants.KlinePeriodEnum;
 import com.yami.trading.huobi.data.TimeZoneConverterService;
+import com.yami.trading.huobi.data.internal.KlineService;
 import com.yami.trading.huobi.tradingview.service.TradingViewService;
 import com.yami.trading.service.data.DataService;
 import com.yami.trading.service.item.ItemService;
@@ -50,6 +51,9 @@
     @Autowired
     RedisTemplate redisTemplate;
 
+    @Autowired
+    KlineService klineService;
+
 
     @ApiOperation(value = "行情")
     @GetMapping("/api/hobi!getKline.action")
@@ -62,13 +66,21 @@
             // Fetch item details based on symbol
             Item bySymbol = itemService.findBySymbol(symbol);
 
+            List<Kline> data;
             // Handle non-cryptos separately
             if (!Item.cryptos.equals(bySymbol.getType())) {
-                return getKlineForNonCryptos(bySymbol, line, symbol);
+                if (bySymbol.getType().equalsIgnoreCase(Item.US_STOCKS)) {
+                    data = klineService.getKData(bySymbol, line);
+                    formatKlineTimestamps(data, line);
+                    return Result.succeed(this.build(data, line, symbol));
+                } else {
+                    return getKlineForNonCryptos(bySymbol, line, symbol);
+                }
             }
 
+            data = this.dataService.kline(symbol, line);
             // Fetch Kline data from service (for cryptos)
-            List<Kline> data = this.dataService.kline(symbol, line);
+
 
             // Return an empty response if no data is found
             if (Objects.isNull(data)) {
diff --git a/trading-order-huobi/src/main/java/com/yami/trading/huobi/data/internal/KlineService.java b/trading-order-huobi/src/main/java/com/yami/trading/huobi/data/internal/KlineService.java
index dc607f5..c6c0a37 100644
--- a/trading-order-huobi/src/main/java/com/yami/trading/huobi/data/internal/KlineService.java
+++ b/trading-order-huobi/src/main/java/com/yami/trading/huobi/data/internal/KlineService.java
@@ -2,6 +2,7 @@
 
 import com.yami.trading.bean.data.domain.Kline;
 import com.yami.trading.bean.data.domain.Realtime;
+import com.yami.trading.bean.item.domain.Item;
 
 import java.util.List;
 import java.util.Map;
@@ -115,4 +116,8 @@
 
 	public List<Kline> calculateKline(String symbol, int seq, String period, List<Kline> klineList) ;
 
-	}
+	List<Kline> getKData(Item item, String interval);
+
+}
+
+
diff --git a/trading-order-huobi/src/main/java/com/yami/trading/huobi/data/internal/KlineServiceImpl.java b/trading-order-huobi/src/main/java/com/yami/trading/huobi/data/internal/KlineServiceImpl.java
index 09ba49d..7a8e13f 100644
--- a/trading-order-huobi/src/main/java/com/yami/trading/huobi/data/internal/KlineServiceImpl.java
+++ b/trading-order-huobi/src/main/java/com/yami/trading/huobi/data/internal/KlineServiceImpl.java
@@ -1,13 +1,19 @@
 package com.yami.trading.huobi.data.internal;
 
+import cn.hutool.http.HttpUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.google.common.collect.Lists;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
 import com.yami.trading.bean.data.domain.Kline;
 import com.yami.trading.bean.data.domain.Realtime;
 import com.yami.trading.bean.item.domain.Item;
 import com.yami.trading.common.config.RequestDataHelper;
 import com.yami.trading.common.constants.Constants;
+import com.yami.trading.common.domain.Result;
+import com.yami.trading.common.exception.YamiShopBindException;
 import com.yami.trading.common.util.DateUtils;
+import com.yami.trading.huobi.websocket.constant.enums.EStockType;
 import com.yami.trading.service.MarketOpenChecker;
 import com.yami.trading.common.util.ThreadUtils;
 import com.yami.trading.common.util.UTCDateUtils;
@@ -16,6 +22,7 @@
 import com.yami.trading.service.data.RealtimeService;
 import com.yami.trading.service.item.ItemService;
 import com.yami.trading.service.syspara.SysparaService;
+import lombok.Data;
 import org.jetbrains.annotations.Nullable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -952,4 +959,49 @@
         }
         return result;
     }
+
+    @Data
+    class kData {
+        long t;
+        String c;
+        String o;
+        String h;
+        String l;
+        String v;
+        String vo;
+    }
+
+    @Override
+    public List<Kline> getKData(Item item, String interval) {
+        try {
+            EStockType eStockType = EStockType.US;
+            Object object = HttpUtil.get(eStockType.stockUrl + "kline?pid=" + item.getStockCode() + "&interval=" + interval + "&key=" + eStockType.stockKey);
+            Gson gson = new Gson();
+            List<kData> dataList = gson.fromJson(object.toString(), new TypeToken<List<kData>>(){}.getType());
+            logger.info("{}获取{}条K线" , item.getSymbol() ,dataList.size());
+            Realtime realtime = DataCache.getRealtime(item.getSymbol());
+            // 修改 List 中的最后一条数据
+            kData lastData = dataList.get(dataList.size() - 1);
+            lastData.setC(String.valueOf(realtime.getClose()));
+            lastData.setO(String.valueOf(realtime.getOpen()));
+            lastData.setH(String.valueOf(realtime.getHigh()));
+            lastData.setL(String.valueOf(realtime.getLow()));
+
+            List<Kline> list = new ArrayList<>();
+            for (int i = 0; i < dataList.size(); i++) {
+                kData kData = dataList.get(i);
+                Kline kline = new Kline();
+                kline.setTs(Long.valueOf(kData.getT() + "000"));
+                kline.setClose(Double.valueOf(kData.getC()));
+                kline.setOpen(Double.valueOf(kData.getO()));
+                kline.setHigh(Double.valueOf(kData.getH()));
+                kline.setLow(Double.valueOf(kData.getL()));
+                list.add(kline);
+            }
+            return list;
+        } catch (Exception e) {
+            logger.error("getKData error", e);
+        }
+        return null;
+    }
 }
diff --git a/trading-order-huobi/src/main/java/com/yami/trading/huobi/jsws/WebSocketClientBeanConfig.java b/trading-order-huobi/src/main/java/com/yami/trading/huobi/jsws/WebSocketClientBeanConfig.java
index c105d73..4319b2a 100644
--- a/trading-order-huobi/src/main/java/com/yami/trading/huobi/jsws/WebSocketClientBeanConfig.java
+++ b/trading-order-huobi/src/main/java/com/yami/trading/huobi/jsws/WebSocketClientBeanConfig.java
@@ -4,6 +4,8 @@
 import com.yami.trading.huobi.websocket.constant.enums.EStockType;
 import lombok.extern.slf4j.Slf4j;
 import org.java_websocket.client.WebSocketClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.Bean;
 import org.springframework.stereotype.Component;
 
@@ -15,13 +17,22 @@
 @Component
 public class WebSocketClientBeanConfig {
 
+    // 注入Spring上下文,用于获取原型Bean
+    @Autowired
+    private ApplicationContext applicationContext;
 
     @Bean
     public Map<String, WebSocketClient> websocketRunClientMap() {
 
         Map<String, WebSocketClient> retMap = new HashMap<>(1);
         try {
-            WebsocketRunClient websocketRunClient = new WebsocketRunClient(new URI(EStockType.US.getWsUrl()), EStockType.US);
+            // 关键:通过Spring上下文获取WebsocketRunClient实例(而非直接new)
+            // 传入参数创建实例(需配合原型作用域)
+            WebsocketRunClient websocketRunClient = applicationContext.getBean(
+                    WebsocketRunClient.class,
+                    new URI(EStockType.US.getWsUrl()),  // 第一个参数:serverUri
+                    EStockType.US                       // 第二个参数:eStockType
+            );
             websocketRunClient.connect();
             websocketRunClient.setConnectionLostTimeout(0);
             startHeartbeatThread(websocketRunClient);
diff --git a/trading-order-huobi/src/main/java/com/yami/trading/huobi/jsws/WebsocketRunClient.java b/trading-order-huobi/src/main/java/com/yami/trading/huobi/jsws/WebsocketRunClient.java
index 86fc437..e120d1f 100644
--- a/trading-order-huobi/src/main/java/com/yami/trading/huobi/jsws/WebsocketRunClient.java
+++ b/trading-order-huobi/src/main/java/com/yami/trading/huobi/jsws/WebsocketRunClient.java
@@ -12,6 +12,8 @@
 import org.java_websocket.client.WebSocketClient;
 import org.java_websocket.handshake.ServerHandshake;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
 
 import java.lang.reflect.Type;
 import java.math.BigDecimal;
@@ -20,6 +22,8 @@
 import java.util.*;
 
 @Slf4j
+@Component
+@Scope("prototype")
 public class WebsocketRunClient extends WebSocketClient {
 
     private EStockType eStockType;
@@ -27,16 +31,20 @@
     @Autowired
     ItemService itemService;
 
+    public WebsocketRunClient() {
+        super(URI.create("wss://ws.jinmanxuan.com/websocket-server"));
+    }
+
     public WebsocketRunClient(URI serverUri, EStockType eStockType) {
         // 修改为新的WebSocket服务器地址
-        super(URI.create("wss://usws.yanshiz.com/websocket-server"));
+        super(URI.create("wss://ws.jinmanxuan.com/websocket-server"));
         this.eStockType = eStockType;
     }
 
 
     @Override
     public void onOpen(ServerHandshake serverHandshake) {
-        log.info("WebSocket连接已建立,连接到: wss://usws.yanshiz.com/websocket-server");
+        log.info("WebSocket连接已建立,连接到: wss://ws.jinmanxuan.com/websocket-server");
         // 发送身份验证消息
         send(("key:"+ eStockType.getStockKey()+":"+eStockType.getContryId()).getBytes());
         Timer heartbeatTimer;
@@ -58,10 +66,9 @@
         if(!s.equals("pong") && !s.equals("身份验证成功")){
             try {
                 Map<String, String> stringObjectMap = jsonToMap(s);
-
-                String symbol = stringObjectMap.get("symbol");
-                Item item = itemService.findBySymbol(symbol);
-                if (!item.getType().equalsIgnoreCase(Item.US_STOCKS)) {
+                String symbol = stringObjectMap.get("symbol").trim();
+                Item item = itemService.findCaCheBySymbol(symbol);
+                if (item == null || !item.getType().equalsIgnoreCase(Item.US_STOCKS)) {
                     return;
                 }
                 Realtime realtime = new Realtime();
diff --git a/trading-order-service/src/main/java/com/yami/trading/service/item/ItemService.java b/trading-order-service/src/main/java/com/yami/trading/service/item/ItemService.java
index c94634b..dbf2ee8 100644
--- a/trading-order-service/src/main/java/com/yami/trading/service/item/ItemService.java
+++ b/trading-order-service/src/main/java/com/yami/trading/service/item/ItemService.java
@@ -165,6 +165,24 @@
     }
 
     /**
+     * 通过 symbol 找去缓存对象
+     *
+     * @param symbol
+     * @return
+     */
+    @Transactional(propagation = Propagation.NOT_SUPPORTED)
+    public Item findCaCheBySymbol(String symbol) {
+        Item item;
+        if (CollectionUtil.isNotEmpty(symbolItem)) {
+            item = symbolItem.get(symbol);
+            if (item != null) {
+                return item;
+            }
+        }
+        return null;
+    }
+
+    /**
      * 基于 remarks 字段去缓存提取 item 对象,特性是基于 remarks 映射 symbol,从缓存中提取 item;
      * 如果缓存中没有数据,则直接去数据库查询返回。
      *

--
Gitblit v1.9.3