trading-order-admin/src/main/java/com/yami/trading/admin/task/InitHandle.java
@@ -112,6 +112,7 @@ // todo 先注释观察报错 // futuresRecomConsumeServer.start(); log.info("开始Data初始化........"); stockGetDataJob.start(); List<Item> items = itemService.list(); for (Item item : items) { AdjustmentValueCache.getCurrentValue().put(item.getSymbol(), item.getAdjustmentValue()); @@ -135,9 +136,9 @@ klineInitService.klineInit(symbols); // 高低修正 highLowHandleJob.start(); stockGetMarketJob.start(); // stockGetMarketJob.start(); // // 获取realtime实时数据 stockGetDataJob.start(); // forexGetDataJob.start(); 外汇 cryptosGetDataJob.start(); fakeSymbolGetDataJob.start(); trading-order-admin/src/main/java/com/yami/trading/api/controller/ApiCapitaltWalletWalletController.java
@@ -92,8 +92,8 @@ // 获取合约账户(contract) Wallet wallet = walletService.saveWalletByPartyId(partyId); // 获取资金账户(capital) CapitaltWallet capitaltWallet = capitaltWalletService.getOne(new LambdaQueryWrapper<>(CapitaltWallet.class) .eq(CapitaltWallet::getUserId, partyId).last(" limit 1 ")); // CapitaltWallet capitaltWallet = capitaltWalletService.getOne(new LambdaQueryWrapper<>(CapitaltWallet.class) // .eq(CapitaltWallet::getUserId, partyId).last(" limit 1 ")); List<WalletExtend> walletExtends = walletExtendService.findByUserId(partyId); AtomicReference<BigDecimal> walletExtendMoneyRef = new AtomicReference<>(BigDecimal.ZERO); walletExtends.forEach(f -> { @@ -107,8 +107,8 @@ Map<String, BigDecimal> assets = new HashMap<>(); assets.put("contract",wallet.getMoney().setScale(2,RoundingMode.DOWN)); assets.put("capital",capitaltWallet.getMoney().add(walletExtendMoney).setScale(2,RoundingMode.DOWN)); assets.put("capitalUSDT",capitaltWallet.getMoney());//划转专用 // assets.put("capital",capitaltWallet.getMoney().add(walletExtendMoney).setScale(2,RoundingMode.DOWN)); // assets.put("capitalUSDT",capitaltWallet.getMoney());//划转专用 return Result.succeed(assets); } } trading-order-admin/src/main/java/com/yami/trading/api/controller/ApiWalletController.java
@@ -215,13 +215,13 @@ df2.setRoundingMode(RoundingMode.FLOOR); // String partyId ="dcc0dd35a49c383dadabc4dc030afe70"; String partyId = SecurityUtils.getCurrentUserId(); CapitaltWallet usdt = null; Wallet usdt = null; if (StringUtils.isNotEmpty(partyId)) { // usdt = this.walletService.saveWalletByPartyId(partyId); usdt = capitaltWalletService.getUserIdWallet(partyId); usdt = this.walletService.saveWalletByPartyId(partyId); // usdt = capitaltWalletService.getUserIdWallet(partyId); } if (null == usdt) { usdt = new CapitaltWallet(); usdt = new Wallet(); usdt.setMoney(new BigDecimal(0)); usdt.setLockMoney(new BigDecimal(0)); usdt.setFreezeMoney(new BigDecimal(0)); trading-order-admin/src/main/java/com/yami/trading/api/controller/ApiWithdrawController.java
@@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.yami.trading.bean.model.CapitaltWallet; import com.yami.trading.bean.model.User; import com.yami.trading.bean.model.Wallet; import com.yami.trading.bean.model.Withdraw; import com.yami.trading.common.constants.Constants; import com.yami.trading.common.domain.Result; @@ -13,6 +14,7 @@ import com.yami.trading.security.common.util.SecurityUtils; import com.yami.trading.service.CapitaltWalletService; import com.yami.trading.service.SessionTokenService; import com.yami.trading.service.WalletService; import com.yami.trading.service.WithdrawService; import com.yami.trading.service.syspara.SysparaService; import com.yami.trading.service.user.UserService; @@ -50,6 +52,8 @@ protected WalletLogService walletLogService; @Autowired CapitaltWalletService capitaltWalletService; @Autowired WalletService walletService; /** * 首次进入页面,传递session_token @@ -111,9 +115,14 @@ // 获取资金账户(capital) if(channel.contains("USDT")){ CapitaltWallet capitaltWallet = capitaltWalletService.getOne(new LambdaQueryWrapper<>(CapitaltWallet.class) .eq(CapitaltWallet::getUserId, partyId).last(" limit 1 ")); if(capitaltWallet.getMoney().compareTo(new BigDecimal(amount)) < 0){ // CapitaltWallet capitaltWallet = capitaltWalletService.getOne(new LambdaQueryWrapper<>(CapitaltWallet.class) // .eq(CapitaltWallet::getUserId, partyId).last(" limit 1 ")); // if(capitaltWallet.getMoney().compareTo(new BigDecimal(amount)) < 0){ // throw new YamiShopBindException("Insufficient available balance for withdrawal!"); // } Wallet wallet = walletService.getOne(new LambdaQueryWrapper<>(Wallet.class) .eq(Wallet::getUserId, partyId).last(" limit 1 ")); if(wallet.getMoney().compareTo(new BigDecimal(amount)) < 0){ throw new YamiShopBindException("Insufficient available balance for withdrawal!"); } } trading-order-admin/src/main/java/com/yami/trading/api/controller/exchange/ApiExchangeApplyOrderController.java
@@ -109,13 +109,14 @@ Map<String, Object> parities = parities(symbol, symbol_to, volume_temp); Object getVolume = parities.get("get_volume"); if(symbol.equals("usdt")){ CapitaltWallet userIdWallet = capitaltWalletService.getUserIdWallet(partyId); Wallet userIdWallet = walletService.saveWalletByPartyId(partyId); // CapitaltWallet userIdWallet = capitaltWalletService.getUserIdWallet(partyId); if(userIdWallet.getMoney().compareTo(new BigDecimal(volume_temp)) < 0){ throw new YamiShopBindException("not sufficient funds"); } Double value = Double.valueOf(volume_temp); capitaltWalletService.update(userIdWallet, -value); // capitaltWalletService.update(userIdWallet, -value); walletService.update(userIdWallet.getUserId(), -value); WalletExtend walletExtend = walletExtendService.getOne(new LambdaQueryWrapper<>(WalletExtend.class) .eq(WalletExtend::getWallettype, symbol_to) .eq(WalletExtend::getPartyId,partyId) @@ -147,8 +148,10 @@ walletExtendService.update(walletExtend,new LambdaUpdateWrapper<WalletExtend>().eq(UUIDEntity::getUuid,walletExtend.getUuid())); CapitaltWallet userIdWallet = capitaltWalletService.getUserIdWallet(partyId); capitaltWalletService.update(userIdWallet,Double.valueOf(getVolume.toString())); // CapitaltWallet userIdWallet = capitaltWalletService.getUserIdWallet(partyId); // capitaltWalletService.update(userIdWallet,Double.valueOf(getVolume.toString())); Wallet userIdWallet = walletService.saveWalletByPartyId(partyId); walletService.update(userIdWallet.getUserId(),Double.valueOf(getVolume.toString())); }else{ WalletExtend walletExtend = walletExtendService.getOne(new LambdaQueryWrapper<>(WalletExtend.class) .eq(WalletExtend::getWallettype, symbol) @@ -374,12 +377,12 @@ public Result openview() { Map<String, Object> data = new HashMap<String, Object>(); String partyId = SecurityUtils.getUser().getUserId(); // Wallet wallet = walletService.saveWalletByPartyId(partyId); CapitaltWallet userIdWallet = capitaltWalletService.getUserIdWallet(partyId); Wallet wallet = walletService.saveWalletByPartyId(partyId); // CapitaltWallet userIdWallet = capitaltWalletService.getUserIdWallet(partyId); // 账户剩余资金 DecimalFormat df = new DecimalFormat("#.##"); df.setRoundingMode(RoundingMode.FLOOR);// 向下取整 data.put("volume", df.format(userIdWallet.getMoney())); data.put("volume", df.format(wallet.getMoney())); String session_token = sessionTokenService.savePut(partyId); data.put("session_token", session_token); data.put("fee", sysparaService.find("exchange_apply_order_buy_fee").getSvalue()); trading-order-admin/src/main/resources/application-prod.yml
@@ -49,4 +49,4 @@ maxIdle: 20 maxTotal: 50 host: 127.0.0.1 port: 6379 port: 6380 trading-order-admin/src/main/resources/redisson/redisson-dev.yml
@@ -1,6 +1,6 @@ # 单节点设置 singleServerConfig: address: redis://127.0.0.1:6379 address: redis://127.0.0.1:6380 database: 0 password: idleConnectionTimeout: 10000 trading-order-bean/src/main/java/com/yami/trading/bean/item/domain/Item.java
@@ -30,7 +30,7 @@ */ public final static String forex = "forex"; /** * 指数 * etf */ public final static String indices = "indices"; trading-order-huobi/src/main/java/com.yami.trading.huobi/data/job/ETFDataSynchronizationJob.java
New file @@ -0,0 +1,272 @@ package com.yami.trading.huobi.data.job; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.yami.trading.bean.item.domain.Item; import com.yami.trading.huobi.data.model.ETFData; import com.yami.trading.huobi.data.model.ETFResponse; import com.yami.trading.huobi.data.model.RealTimeData; import com.yami.trading.huobi.data.model.RealTimeResponse; import com.yami.trading.service.item.ItemService; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.checkerframework.checker.units.qual.A; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; /** * @program: trading-order-master * @description: * @create: 2025-09-28 11:20 **/ @Slf4j @Component public class ETFDataSynchronizationJob { @Autowired private ItemService itemService; @Autowired private RestTemplate restTemplate; private static final String LIST_API_URL = "https://www.tsanghi.com/api/fin/etf/XNAS/list?token=9668db3503214cd19a831a9f866923b9"; private static final String REALTIME_API_URL = "https://www.tsanghi.com/api/fin/etf/XNAS/realtime?token=9668db3503214cd19a831a9f866923b9&ticker="; /** * 同步ETF数据定时任务 */ // @Scheduled(cron = "0 * * * * ?") public void syncETFData() { try { log.info("开始同步ETF数据..."); // 获取ETF列表 List<ETFData> etfList = getETFList(); if (etfList == null || etfList.isEmpty()) { log.warn("未获取到ETF列表数据"); return; } log.info("共获取到{}个ETF数据", etfList.size()); int successCount = 0; int errorCount = 0; // 处理每个ETF for (ETFData etf : etfList) { try { if (processETFItem(etf)) { successCount++; } else { errorCount++; } } catch (Exception e) { log.error("处理ETF {} 时发生错误: {}", etf.getTicker(), e.getMessage()); errorCount++; } } log.info("ETF数据同步完成: 成功 {}, 失败 {}", successCount, errorCount); } catch (Exception e) { log.error("同步ETF数据时发生错误: {}", e.getMessage(), e); } } /** * 获取ETF列表 */ private List<ETFData> getETFList() { try { ResponseEntity<ETFResponse> response = restTemplate.exchange( LIST_API_URL, HttpMethod.GET, null, ETFResponse.class ); if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) { ETFResponse apiResponse = response.getBody(); if (apiResponse.getCode() == 200) { return apiResponse.getData(); } else { log.error("API返回错误: {} - {}", apiResponse.getCode(), apiResponse.getMsg()); } } } catch (Exception e) { log.error("获取ETF列表失败: {}", e.getMessage(), e); } return null; } /** * 处理单个ETF项目 */ private boolean processETFItem(ETFData etf) { // 只处理活跃的ETF if (etf.getIsActive() == null || etf.getIsActive() != 1) { log.info("跳过非活跃ETF: {}", etf.getTicker()); return false; } // 检查是否已存在 Item existingItem = itemService.getOne(new LambdaQueryWrapper<Item>() .eq(Item::getSymbol,etf.getTicker()) ); if (existingItem != null) { log.info("ETF {} 已存在,跳过", etf.getTicker()); return true; } // 获取实时数据计算小数位 RealTimeData realtimeData = getRealtimeData(etf.getTicker()); if (realtimeData == null) { log.warn("无法获取ETF {} 的实时数据", etf.getTicker()); return false; } // 创建Item对象 Item item = createItemFromETFData(etf, realtimeData); // 保存到数据库 return itemService.save(item); } /** * 获取实时数据 */ private RealTimeData getRealtimeData(String ticker) { try { String url = REALTIME_API_URL + ticker; ResponseEntity<RealTimeResponse> response = restTemplate.exchange( url, HttpMethod.GET, null, RealTimeResponse.class ); if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) { RealTimeResponse apiResponse = response.getBody(); if (apiResponse.getCode() == 200) { return apiResponse.getData().get(0); } } } catch (Exception e) { log.error("获取ETF {} 实时数据失败: {}", ticker, e.getMessage()); } return null; } /** * 根据收盘价计算小数位数和PIPS */ private ETFDecimalInfo calculateDecimalInfo(BigDecimal closePrice) { ETFDecimalInfo info = new ETFDecimalInfo(); if (closePrice == null) { // 默认值 info.setDecimals(2); info.setPips(new BigDecimal("0.01")); info.setPipsAmount(new BigDecimal("0.01")); return info; } try { String priceStr = closePrice.stripTrailingZeros().toPlainString(); int decimalPlaces = 0; // 查找小数点位置 int dotIndex = priceStr.indexOf('.'); if (dotIndex != -1) { // 计算实际的小数位数(去除末尾的0) decimalPlaces = priceStr.length() - dotIndex - 1; } // 设置小数位数,至少为2位 int decimals = Math.max(decimalPlaces, 2); info.setDecimals(decimals); // 计算PIPS(最小价格单位) BigDecimal pips = BigDecimal.ONE.divide( BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_UP ); info.setPips(pips); info.setPipsAmount(pips); } catch (Exception e) { log.error("计算小数位信息失败,使用默认值", e); info.setDecimals(2); info.setPips(new BigDecimal("0.01")); info.setPipsAmount(new BigDecimal("0.01")); } return info; } /** * 创建Item对象 */ private Item createItemFromETFData(ETFData etf, RealTimeData realtimeData) { Item item = new Item(); // 生成UUID String uuid = UUID.randomUUID().toString().replace("-", ""); item.setUuid(uuid); // 基础信息 item.setName(etf.getName()); item.setEnName(etf.getName()); item.setSymbol(etf.getTicker()); item.setSymbolData(etf.getTicker()); item.setSymbolFullName(etf.getName()); // 计算小数位信息 item.setDecimals(2); item.setPips(new BigDecimal("0.01")); item.setPipsAmount(new BigDecimal("0.01")); // 固定值设置 item.setAdjustmentValue(BigDecimal.ZERO); item.setUnitAmount(new BigDecimal("1000")); item.setUnitFee(new BigDecimal("30")); item.setMarket("indices"); item.setMultiple(BigDecimal.ZERO); item.setBorrowingRate(BigDecimal.ZERO); item.setType("indices"); item.setCategory("Miscellaneous"); item.setSorted("100"); item.setOpenCloseType("indices"); item.setFake("0"); item.setShowStatus("1"); item.setTradeStatus("1"); item.setQuoteCurrency("USDT"); item.setFaceValue(0.01); // 创建时间和更新时间 item.setCreateTime(new Date()); item.setUpdateTime(new Date()); return item; } /** * 小数位信息辅助类 */ @Data private static class ETFDecimalInfo { private Integer decimals; private BigDecimal pips; private BigDecimal pipsAmount; } } trading-order-huobi/src/main/java/com.yami.trading.huobi/data/job/StockGetDataJob.java
@@ -2,9 +2,11 @@ import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.yami.trading.bean.data.domain.Realtime; import com.yami.trading.bean.data.domain.StockMarket; import com.yami.trading.bean.item.domain.Item; import com.yami.trading.common.domain.BaseEntity; import com.yami.trading.common.util.*; import com.yami.trading.huobi.data.AdjustmentValueCache; import com.yami.trading.huobi.data.DataCache; @@ -64,23 +66,24 @@ } while (true) { try { List<Item> list = itemService.list().stream().filter(i->"0".equalsIgnoreCase(i.getFake())).collect(Collectors.toList()); List<Item> list = itemService.list(new LambdaQueryWrapper<>(Item.class).eq(BaseEntity::getDelFlag,0)).stream().filter(i->"0".equalsIgnoreCase(i.getFake())).collect(Collectors.toList()); // etf 和A股开盘时间是一样的 String aStocSymbols = list.stream().filter(item ->item.getOpenCloseType() != null && item.getOpenCloseType().equalsIgnoreCase(Item.A_STOCKS)) .map(Item::getSymbol).collect(Collectors.joining(",")); String hkStocSymbols = list.stream().filter(item -> item.getOpenCloseType() != null &&item.getOpenCloseType().equalsIgnoreCase(Item.HK_STOCKS)).map(Item::getSymbol).collect(Collectors.joining(",")); // String aStocSymbols = list.stream().filter(item ->item.getOpenCloseType() != null && item.getOpenCloseType().equalsIgnoreCase(Item.A_STOCKS)) // .map(Item::getSymbol).collect(Collectors.joining(",")); // String hkStocSymbols = list.stream().filter(item -> item.getOpenCloseType() != null &&item.getOpenCloseType().equalsIgnoreCase(Item.HK_STOCKS)).map(Item::getSymbol).collect(Collectors.joining(",")); String usStocSymbols = list.stream().filter(item -> item.getOpenCloseType() != null &&item.getOpenCloseType().equalsIgnoreCase(Item.US_STOCKS)).map(Item::getSymbol).collect(Collectors.joining(",")); String indicesymbols = list.stream().filter(item -> item.getOpenCloseType() != null &&item.getOpenCloseType().equalsIgnoreCase(Item.indices)).map(Item::getSymbol).collect(Collectors.joining(",")); if(stockFirstFetch){ this.realtimeHandle(aStocSymbols); this.realtimeHandle(hkStocSymbols); // this.realtimeHandle(aStocSymbols); this.realtimeHandle(indicesymbols); this.realtimeHandle(usStocSymbols); stockFirstFetch = false; } if(MarketOpenChecker.isMarketOpen(Item.A_STOCKS)){ this.realtimeHandle(aStocSymbols); } if(MarketOpenChecker.isMarketOpen(Item.HK_STOCKS)){ this.realtimeHandle(hkStocSymbols); // if(MarketOpenChecker.isMarketOpen(Item.A_STOCKS)){ // this.realtimeHandle(aStocSymbols); // } if(MarketOpenChecker.isMarketOpen(Item.indices)){ this.realtimeHandle(indicesymbols); } if(MarketOpenChecker.isMarketOpen(Item.US_STOCKS)){ this.realtimeHandle(usStocSymbols); trading-order-huobi/src/main/java/com.yami.trading.huobi/data/job/StockGetMarketJob.java
@@ -58,10 +58,10 @@ try { List<Item> list = itemService.list().stream().filter(i -> "0".equalsIgnoreCase(i.getFake())).collect(Collectors.toList()); // etf 和A股开盘时间是一样的 String aStocSymbols = list.stream().filter(item -> item.getOpenCloseType() != null && item.getOpenCloseType().equalsIgnoreCase(Item.A_STOCKS)).map(Item::getSymbol).collect(Collectors.joining(",")); String hkStocSymbols = list.stream().filter(item -> item.getOpenCloseType() != null && item.getOpenCloseType().equalsIgnoreCase(Item.HK_STOCKS)).map(Item::getSymbol).collect(Collectors.joining(",")); // String aStocSymbols = list.stream().filter(item -> item.getOpenCloseType() != null && item.getOpenCloseType().equalsIgnoreCase(Item.A_STOCKS)).map(Item::getSymbol).collect(Collectors.joining(",")); // String hkStocSymbols = list.stream().filter(item -> item.getOpenCloseType() != null && item.getOpenCloseType().equalsIgnoreCase(Item.HK_STOCKS)).map(Item::getSymbol).collect(Collectors.joining(",")); String usStocSymbols = list.stream().filter(item -> item.getOpenCloseType() != null && item.getOpenCloseType().equalsIgnoreCase(Item.US_STOCKS)).map(Item::getSymbol).collect(Collectors.joining(",")); String symbols = aStocSymbols + "," + hkStocSymbols + "," + usStocSymbols; String symbols = usStocSymbols; List<StockMarket> markets = xueQiuDataService.getMarkets(symbols); markets.forEach(m -> DataCache.putMarket(m.getSymbol(), m)); trading-order-huobi/src/main/java/com.yami.trading.huobi/data/model/ETFData.java
New file @@ -0,0 +1,30 @@ package com.yami.trading.huobi.data.model; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; /** * @program: trading-order-master * @description: * @create: 2025-09-28 14:16 **/ @Data public class ETFData { @JsonProperty("ticker") private String ticker; @JsonProperty("name") private String name; @JsonProperty("is_active") private Integer isActive; @JsonProperty("exchange_code") private String exchangeCode; @JsonProperty("country_code") private String countryCode; @JsonProperty("currency_code") private String currencyCode; } trading-order-huobi/src/main/java/com.yami.trading.huobi/data/model/ETFResponse.java
New file @@ -0,0 +1,19 @@ package com.yami.trading.huobi.data.model; import lombok.Data; import java.util.List; /** * @program: trading-order-master * @description: * @create: 2025-09-28 14:18 **/ @Data public class ETFResponse { private String msg; private Integer code; private List<ETFData> data; } trading-order-huobi/src/main/java/com.yami.trading.huobi/data/model/RealTimeData.java
New file @@ -0,0 +1,35 @@ package com.yami.trading.huobi.data.model; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; /** * @program: trading-order-master * @description: * @create: 2025-09-28 14:18 **/ @Data public class RealTimeData { @JsonProperty("ticker") private String ticker; @JsonProperty("close") private Double close; @JsonProperty("date") private String date; @JsonProperty("open") private Double open; @JsonProperty("high") private Double high; @JsonProperty("low") private Double low; @JsonProperty("volume") private Double volume; } trading-order-huobi/src/main/java/com.yami.trading.huobi/data/model/RealTimeResponse.java
New file @@ -0,0 +1,19 @@ package com.yami.trading.huobi.data.model; import lombok.Data; import java.util.List; /** * @program: trading-order-master * @description: * @create: 2025-09-28 14:19 **/ @Data public class RealTimeResponse { private String msg; private Integer code; private List<RealTimeData> data; } trading-order-huobi/src/main/java/com.yami.trading.huobi/hobi/internal/XinLangDataServiceImpl.java
@@ -65,17 +65,7 @@ private ItemService itemService; public static void main(String[] args) { XinLangDataServiceImpl service = new XinLangDataServiceImpl(); List<Realtime> usdsgd = service.realtimeSingle("USDSGD"); for (Realtime re : usdsgd) { System.out.println(JSONObject.toJSONString(re)); } // List<Kline> sz300750 = service.buildOneYearPeriod("AAPL"); // System.out.println(sz300750.size()); // List<Kline> eurusd = service.getTimeseriesByPeriodOneDay("EURUSD"); // System.out.println(JSONObject.toJSONString(eurusd)); } /** @@ -142,10 +132,10 @@ return list; } public List<Realtime> realtime(String symbols) { List<Realtime> realtimeList = realtimeSingle(symbols); return realtimeList; } // public List<Realtime> realtime(String symbols) { // List<Realtime> realtimeList = realtimeSingle(symbols); // return realtimeList; // } /** * 1day 历史数据 : 周期 1年 trading-order-huobi/src/main/java/com.yami.trading.huobi/hobi/internal/XueQiuDataServiceImpl.java
@@ -7,6 +7,7 @@ import com.google.common.collect.Lists; import com.yami.trading.bean.cms.Infomation; import com.yami.trading.bean.data.domain.*; import com.yami.trading.bean.item.domain.Item; import com.yami.trading.common.util.RedisUtil; import com.yami.trading.huobi.data.DataCache; import com.yami.trading.huobi.data.internal.DepthTimeObject; @@ -16,6 +17,7 @@ import com.yami.trading.huobi.hobi.http.HttpMethodType; import com.yami.trading.service.cms.InfomationService; import com.yami.trading.service.item.ItemService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; @@ -27,6 +29,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -36,6 +39,7 @@ * 完成需求k线图采集 */ @Component @Slf4j public class XueQiuDataServiceImpl { // https://stock.xueqiu.com/v5/stock/chart/kline.json?symbol=TSLA&begin=1682695800000&period=120m&type=before&count=-500&indicator=kline"; public final static String klineUrl = "https://stock.xueqiu.com/v5/stock/chart/kline.json?symbol={}&begin={}&period={}&type=before&count=-500&indicator=kline"; @@ -45,7 +49,7 @@ /** * live */ public final static String live = "https://stock.xueqiu.com/v5/stock/quote.json"; public final static String live = "https://www.tsanghi.com/api/fin/"; public final static String markets = "https://stock.xueqiu.com/v5/stock/quote.json"; public final static String pankou = "https://stock.xueqiu.com/v5/stock/realtime/pankou.json"; @@ -322,55 +326,164 @@ } public List<Realtime> realtimeSingle(String symbols) { List<Realtime> list = new ArrayList<Realtime>(); List<Realtime> list = new ArrayList<>(); try { List<String> strings = Arrays.asList(symbols.split(",")); String cookie = HttpHelper.getCookie("https://xueqiu.com/"); for (String symbol: strings) { String result = HttpHelper.sendGetHttp(live, "symbol=" + symbol, cookie); JSONObject resultJson = JSON.parseObject(result); String code = resultJson.getString("error_code"); if ("0".equals(code)) { JSONObject jsonObject = resultJson.getJSONObject("data").getJSONObject("quote"); Realtime realtime = new Realtime(); String currency; currency = symbol; int decimal = itemService.getDecimal(currency); realtime.setSymbol(currency); realtime.setName(currency); Long timestamp = jsonObject.getLong("timestamp"); if (timestamp.toString().length() > 13) { timestamp = timestamp / 1000; List<String> symbolList = Arrays.asList(symbols.split(",")); for (String symbol : symbolList) { try { Item item = itemService.findBySymbol(symbol); if (item == null) { log.warn("未找到对应的item: {}", symbol); continue; } realtime.setTs(timestamp); realtime.setOpen(jsonObject.getBigDecimal("open").setScale(decimal, RoundingMode.HALF_UP)); realtime.setClose(jsonObject.getBigDecimal("current").setScale(decimal, RoundingMode.HALF_UP)); realtime.setHigh(jsonObject.getBigDecimal("high").setScale(decimal, RoundingMode.HALF_UP)); realtime.setLow(jsonObject.getBigDecimal("low").setScale(decimal, RoundingMode.HALF_UP)); realtime.setMarketCapital(jsonObject.getLong("market_capital")); realtime.setFloatMarketCapital(jsonObject.getLong("float_market_capital")); realtime.setPeForecast(jsonObject.getBigDecimal("pe_forecast")); realtime.setVolumeRatio(jsonObject.getBigDecimal("volume_ratio")); realtime.setTurnoverRate(jsonObject.getBigDecimal("turnover_rate")); BigDecimal amount = jsonObject.getBigDecimal("amount"); if (amount == null) { amount = BigDecimal.ZERO; String type = ""; String exchange = ""; // 根据类型确定API路径和交易所 if ("US-stocks".equals(item.getType())) { type = "stock"; exchange = "XNAS"; // 美股纳斯达克 } else if ("indices".equals(item.getType()) || "ETF".equals(item.getType())) { type = "etf"; exchange = "XNAS"; // ETF也在纳斯达克 } else { // 其他类型,默认为股票和上交所 type = "stock"; exchange = "XSHG"; } realtime.setAmount(amount.setScale(decimal, RoundingMode.HALF_UP)); BigDecimal volume = jsonObject.getBigDecimal("volume"); if (volume == null) { volume = BigDecimal.ZERO; // 构建API URL String url = String.format("https://www.tsanghi.com/api/fin/%s/%s/realtime?token=9668db3503214cd19a831a9f866923b9&ticker=%s", type, exchange, symbol); String result = HttpHelper.sendGetHttp(url, null, null); JSONObject resultJson = JSON.parseObject(result); String code = resultJson.getString("code"); if ("200".equals(code)) { JSONArray dataArray = resultJson.getJSONArray("data"); // 检查数据是否为空 if (dataArray == null || dataArray.isEmpty()) { log.warn("股票 {} 的实时数据为空", symbol); continue; } // 取第一个数据对象 JSONObject dataObject = dataArray.getJSONObject(0); Realtime realtime = new Realtime(); int decimal = itemService.getDecimal(symbol); realtime.setSymbol(symbol); realtime.setName(item.getName() != null ? item.getName() : symbol); // 处理时间戳 String dateStr = dataObject.getString("date"); long timestamp = parseDateTimeToTimestamp(dateStr); if (Long.toString(timestamp).length() > 13) { timestamp = timestamp / 1000; } realtime.setTs(timestamp); // 设置价格数据 realtime.setOpen(getBigDecimalValue(dataObject, "open", decimal)); realtime.setClose(getBigDecimalValue(dataObject, "close", decimal)); realtime.setHigh(getBigDecimalValue(dataObject, "high", decimal)); realtime.setLow(getBigDecimalValue(dataObject, "low", decimal)); // 设置成交量和成交额 realtime.setVolume(getBigDecimalValue(dataObject, "volume", decimal)); realtime.setAmount(getBigDecimalValue(dataObject, "amount", decimal)); // 设置昨收价 BigDecimal preClose = getBigDecimalValue(dataObject, "pre_close", decimal); if (preClose != null) { // 如果Realtime类有preClose字段,取消注释 // realtime.setPreClose(preClose); } // 处理盘口数据(如果存在) JSONArray buyPriceArray = dataObject.getJSONArray("buy_price"); JSONArray sellPriceArray = dataObject.getJSONArray("sell_price"); JSONArray buyVolumeArray = dataObject.getJSONArray("buy_volume"); JSONArray sellVolumeArray = dataObject.getJSONArray("sell_volume"); if (buyPriceArray != null && !buyPriceArray.isEmpty()) { realtime.setBid(getBigDecimalFromArray(buyPriceArray, 0, decimal)); } if (sellPriceArray != null && !sellPriceArray.isEmpty()) { realtime.setAsk(getBigDecimalFromArray(sellPriceArray, 0, decimal)); } list.add(realtime); } else { log.warn("API返回错误代码: {}, 股票: {}", code, symbol); } realtime.setVolume(volume.setScale(decimal, RoundingMode.HALF_UP)); // realtime.setAsk(realtimeJson.getBigDecimal("ask").setScale(decimal, RoundingMode.HALF_UP)); // realtime.setBid(realtimeJson.getBigDecimal("pb").setScale(decimal, RoundingMode.HALF_UP)); list.add(realtime); } catch (Exception e) { log.error("处理股票 {} 时发生错误", symbol, e); } } } catch (Exception e) { logger.error("error", e); log.error("获取实时数据失败", e); } return list; } /** * 将日期时间字符串转换为时间戳 * 格式: "yyyy-mm-dd hh:mm:ss" */ private long parseDateTimeToTimestamp(String dateTimeStr) { try { if (dateTimeStr == null || dateTimeStr.isEmpty()) { return System.currentTimeMillis(); } SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = sdf.parse(dateTimeStr); return date.getTime(); } catch (Exception e) { log.error("日期时间解析失败: {}", dateTimeStr, e); return System.currentTimeMillis(); } } /** * 安全获取BigDecimal值 */ private BigDecimal getBigDecimalValue(JSONObject jsonObject, String key, int decimal) { try { BigDecimal value = jsonObject.getBigDecimal(key); if (value == null) { return BigDecimal.ZERO; } return value.setScale(decimal, RoundingMode.HALF_UP); } catch (Exception e) { log.warn("获取字段 {} 失败", key, e); return BigDecimal.ZERO; } } /** * 从JSONArray中获取BigDecimal值 */ private BigDecimal getBigDecimalFromArray(JSONArray jsonArray, int index, int decimal) { try { if (jsonArray == null || jsonArray.size() <= index) { return BigDecimal.ZERO; } BigDecimal value = jsonArray.getBigDecimal(index); if (value == null) { return BigDecimal.ZERO; } return value.setScale(decimal, RoundingMode.HALF_UP); } catch (Exception e) { log.warn("从数组获取数据失败", e); return BigDecimal.ZERO; } } public List<Realtime> realtime(String symbols) { @@ -389,25 +502,25 @@ map.put(Kline.PERIOD_1MON, buildOneMonthPeriod(symbol)); map.put(Kline.PERIOD_1DAY, buildOneDayPeriod(symbol)); map.put(Kline.PERIOD_5DAY, buildFiveDayPeriod(symbol)); map.put(Kline.PERIOD_QUARTER, buildOneQuarterPeriod(symbol)); // map.put(Kline.PERIOD_QUARTER, buildOneQuarterPeriod(symbol)); map.put(Kline.PERIOD_YEAR, buildOneYearPeriod(symbol)); return map; } public List<Kline> buildOneDayPeriod(String currency) { return getTimeseriesByPeriod(currency, "day", Kline.PERIOD_1DAY, 365); return getTimeseriesByPeriod(currency, "daily", Kline.PERIOD_1DAY, 365); } public List<Kline> buildOneWeekPeriod(String currency) { return getTimeseriesByPeriod(currency, "week", Kline.PERIOD_1WEEK, 365 * 5); return getTimeseriesByPeriod(currency, "weekly", Kline.PERIOD_1WEEK, 365 * 5); } public List<Kline> buildOneMonthPeriod(String currency) { return getTimeseriesByPeriod(currency, "month", Kline.PERIOD_1MON, 365 * 5); return getTimeseriesByPeriod(currency, "monthly", Kline.PERIOD_1MON, 365 * 5); } public List<Kline> buildOneQuarterPeriod(String currency) { @@ -415,7 +528,7 @@ } public List<Kline> buildOneYearPeriod(String currency) { return getTimeseriesByPeriod(currency, "year", Kline.PERIOD_YEAR, 365 * 100); return getTimeseriesByPeriod(currency, "yearly", Kline.PERIOD_YEAR, 365 * 100); } /** @@ -588,64 +701,144 @@ public List<Kline> getTimeseriesByPeriod(String currency, String periodXieQiu, String sysPeriod, long limitDays) { List<Kline> resList = new ArrayList<>(); long nowTs = System.currentTimeMillis(); long startTs = System.currentTimeMillis() - limitDays * 24 * 60 * 60 * 1000; long begin = nowTs; String cookie = HttpHelper.getCookie("https://xueqiu.com/"); Set<Long> tsSet = new HashSet<>(); while (begin > startTs) { String url = StrUtil.format(klineUrl, currency, begin, periodXieQiu); String json = HttpHelper.sendGetHttp(url, null, cookie); try { // 获取商品信息判断类型 Item itemData = itemService.findBySymbol(currency); String type = "stock"; // 默认股票 String exchange = "XNAS"; // 默认纳斯达克 if (itemData != null) { if ("ETF".equals(itemData.getType()) || "etf".equals(itemData.getType()) || "indices".equals(itemData.getType()) || currency.startsWith("51") || currency.startsWith("15") || currency.startsWith("16")) { type = "etf"; // ETF可能在不同的交易所,根据实际情况调整 exchange = "XNAS"; // 或者可能是XSHG等其他交易所 } else if ("US-stocks".equals(itemData.getType())) { type = "stock"; exchange = "XNAS"; } else { // 其他类型默认为A股股票 type = "stock"; exchange = "XSHG"; } } else { // 如果没有找到item信息,根据symbol特征猜测类型 if (currency.startsWith("51") || currency.startsWith("15") || currency.startsWith("16")) { type = "etf"; exchange = "XSHG"; // A股ETF } else if (currency.matches("[A-Z]+")) { type = "stock"; exchange = "XNAS"; // 美股 } else { type = "stock"; exchange = "XSHG"; // 默认A股 } } log.debug("获取K线数据,symbol: {}, 类型: {}, 交易所: {}, 周期: {}", currency, type, exchange, periodXieQiu); // 构建API URL String url = StrUtil.format("https://www.tsanghi.com/api/fin/{}/{}/{}?token=9668db3503214cd19a831a9f866923b9&ticker={}&order=2", type, exchange, periodXieQiu, currency); // 发送HTTP请求 String json = HttpHelper.sendGetHttp(url, null, null); JSONObject resultJson = JSON.parseObject(json); JSONArray dataArray = resultJson.getJSONObject("data").getJSONArray("item"); List<List> lists = dataArray.toJavaList(List.class); long minTS = begin; for (List result : lists) { // 检查API响应是否成功 if (resultJson == null || !resultJson.containsKey("data")) { log.error("API响应数据格式异常: {}", json); return resList; } JSONArray dataArray = resultJson.getJSONArray("data"); if (dataArray == null || dataArray.isEmpty()) { log.warn("未获取到K线数据"); return resList; } // 计算时间范围 long endTime = System.currentTimeMillis(); long startTime = endTime - limitDays * 24 * 60 * 60 * 1000L; Set<String> dateSet = new HashSet<>(); // 解析数据 for (int i = 0; i < dataArray.size(); i++) { JSONObject item = dataArray.getJSONObject(i); // 解析日期 String dateStr = item.getString("date"); if (dateSet.contains(dateStr)) { continue; } dateSet.add(dateStr); // 将日期转换为时间戳 long ts = parseDateToTimestamp(dateStr); // 检查时间范围 if (ts < startTime) { continue; } Kline kline = new Kline(); kline.setSymbol(currency); kline.setPeriod(sysPeriod); // 毫秒 long ts = Long.parseLong(result.get(0).toString()); if (Long.toString(ts).length() > 13) { ts = ts / 1000; } if (tsSet.contains(ts)) { continue; } else { tsSet.add(ts); } kline.setTs(ts); kline.setOpen(new BigDecimal(result.get(2).toString())); kline.setClose(new BigDecimal(result.get(5).toString())); kline.setHigh(new BigDecimal(result.get(3).toString())); kline.setLow(new BigDecimal(result.get(4).toString())); kline.setVolume(new BigDecimal(result.get(1).toString())); kline.setAmount(new BigDecimal(result.get(9).toString())); kline.setOpen(item.getBigDecimal("open")); kline.setClose(item.getBigDecimal("close")); kline.setHigh(item.getBigDecimal("high")); kline.setLow(item.getBigDecimal("low")); kline.setVolume(item.getBigDecimal("volume")); // 如果有amount字段就设置,没有就设为0 if (item.containsKey("amount")) { kline.setAmount(item.getBigDecimal("amount")); } else { kline.setAmount(BigDecimal.ZERO); } // 修复K线数据(如果有修复逻辑) if (klineService != null) { klineService.repairKline(kline); } resList.add(kline); if (ts < minTS) { minTS = ts; } } // 按时间戳升序排序 Collections.sort(resList); // 如果需要设置开盘价为前一根的收盘价 int len = resList.size(); for (int i = 1; i < len; i++) { resList.get(i).setOpen(resList.get(i - 1).getClose()); } if (minTS == begin) { break; } begin = minTS; if (begin < startTs) { break; } } catch (Exception e) { log.error("获取K线数据失败: {}", currency, e); } Collections.sort(resList); int len = resList.size(); for (int i = 1; i < len; i++) { resList.get(i).setOpen(resList.get(i - 1).getClose()); } return resList; } /** * 将日期字符串转换为时间戳 * 格式: "yyyy-mm-dd" */ private long parseDateToTimestamp(String dateStr) { try { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date date = sdf.parse(dateStr); return date.getTime(); } catch (Exception e) { log.error("日期解析失败: {}", dateStr, e); return System.currentTimeMillis(); } } public List<Kline> getTimeseriesByMinute(String currency, int minute, long limitDays) { trading-order-service/src/main/java/com/yami/trading/service/exchange/impl/ExchangeApplyOrderServiceImpl.java
@@ -111,11 +111,11 @@ double amount = Arith.mul(sub, realtime.getClose().doubleValue()); order.setCloseTime(new Date()); order.setClosePrice(realtime.getClose().doubleValue()); // Wallet wallet = this.walletService.saveWalletByPartyId(order.getPartyId()); CapitaltWallet capitaltWallet = capitaltWalletService.getUserIdWallet(order.getPartyId()); double amount_before = capitaltWallet.getMoney().doubleValue(); // this.walletService.update(userIdWallet.getUserId().toString(), amount); this.capitaltWalletService.update(capitaltWallet, amount); Wallet wallet = this.walletService.saveWalletByPartyId(order.getPartyId()); // CapitaltWallet capitaltWallet = capitaltWalletService.getUserIdWallet(order.getPartyId()); double amount_before = wallet.getMoney().doubleValue(); this.walletService.update(wallet.getUserId().toString(), amount); // this.capitaltWalletService.update(capitaltWallet, amount); /* * 保存资金日志 @@ -124,7 +124,7 @@ moneylog_deposit.setCategory(Constants.MONEYLOG_CATEGORY_EXCHANGE); moneylog_deposit.setAmountBefore(new BigDecimal(amount_before)); moneylog_deposit.setAmount(new BigDecimal(amount)); moneylog_deposit.setAmountAfter(capitaltWallet.getMoney()); moneylog_deposit.setAmountAfter(wallet.getMoney()); moneylog_deposit.setLog("委托单,订单号[" + order.getOrderNo() + "]"); moneylog_deposit.setUserId(order.getPartyId()); moneylog_deposit.setWalletType(Constants.WALLET); @@ -615,8 +615,8 @@ // 可以买的数量 double amount = Arith.div(sub, order.getClosePrice(), 8); order.setSymbolValue(amount); // Wallet wallet = this.walletService.saveWalletByPartyId(order.getPartyId()); CapitaltWallet userIdWallet = capitaltWalletService.getUserIdWallet(order.getPartyId()); Wallet userIdWallet = this.walletService.saveWalletByPartyId(order.getPartyId()); // CapitaltWallet userIdWallet = capitaltWalletService.getUserIdWallet(order.getPartyId()); double amount_before = userIdWallet.getMoney().doubleValue(); // 如果是计划委托,则先不扣钱 if (order.isTriggerOrder()) { @@ -643,8 +643,8 @@ if (userIdWallet.getMoney().doubleValue() < order.getVolume().doubleValue()) { throw new YamiShopBindException("余额不足"); } // this.walletService.update(userIdWallet.getUserId().toString(), Arith.sub(0, order.getVolume())); capitaltWalletService.update(userIdWallet, Arith.sub(0, order.getVolume())); this.walletService.update(userIdWallet.getUserId().toString(), Arith.sub(0, order.getVolume())); // capitaltWalletService.update(userIdWallet, Arith.sub(0, order.getVolume())); /* * 保存资金日志 */ trading-order-service/src/main/java/com/yami/trading/service/impl/RechargeBlockchainOrderServiceImpl.java
@@ -135,10 +135,15 @@ // // walletService.update(wallet.getUserId(), amount1); CapitaltWallet capitaltWallet = capitaltWalletService.getOne(new LambdaQueryWrapper<>(CapitaltWallet.class) .eq(CapitaltWallet::getUserId, recharge.getPartyId()).last(" limit 1 ")); double amount_before = capitaltWallet.getMoney().doubleValue(); capitaltWalletService.update(capitaltWallet,amount1); // CapitaltWallet capitaltWallet = capitaltWalletService.getOne(new LambdaQueryWrapper<>(CapitaltWallet.class) // .eq(CapitaltWallet::getUserId, recharge.getPartyId()).last(" limit 1 ")); // double amount_before = capitaltWallet.getMoney().doubleValue(); // capitaltWalletService.update(capitaltWallet,amount1); Wallet wallet = walletService.getOne(new LambdaQueryWrapper<>(Wallet.class) .eq(Wallet::getUserId, recharge.getPartyId()).last(" limit 1 ")); double amount_before = wallet.getMoney().doubleValue(); walletService.update(wallet.getUserId(),amount1); // 保存资金日志 MoneyLog moneyLog = new MoneyLog(); trading-order-service/src/main/java/com/yami/trading/service/impl/WithdrawServiceImpl.java
@@ -151,14 +151,24 @@ // walletService.update(wallet.getUserId().toString(), // Arith.add(withdraw.getAmount(), withdraw.getAmountFee())); CapitaltWallet capitaltWallet = capitaltWalletService.getOne(new LambdaQueryWrapper<>(CapitaltWallet.class) .eq(CapitaltWallet::getUserId, wallet.getUserId().toString()).last(" limit 1 ")); if(ObjectUtil.isEmpty(capitaltWallet)){ // CapitaltWallet capitaltWallet = capitaltWalletService.getOne(new LambdaQueryWrapper<>(CapitaltWallet.class) // .eq(CapitaltWallet::getUserId, wallet.getUserId().toString()).last(" limit 1 ")); // if(ObjectUtil.isEmpty(capitaltWallet)){ // throw new YamiShopBindException("用户资金账户不存在!"); // } // capitaltWalletService.update(new LambdaUpdateWrapper<CapitaltWallet>() // .set(CapitaltWallet::getMoney,new BigDecimal(Arith.add(capitaltWallet.getMoney(), withdraw.getVolume()))) // .eq(CapitaltWallet::getUserId,wallet.getUserId())); Wallet wallet1 = walletService.getOne(new LambdaQueryWrapper<>(Wallet.class) .eq(Wallet::getUserId, wallet.getUserId().toString()).last(" limit 1 ")); if(ObjectUtil.isEmpty(wallet1)){ throw new YamiShopBindException("用户资金账户不存在!"); } capitaltWalletService.update(new LambdaUpdateWrapper<CapitaltWallet>() .set(CapitaltWallet::getMoney,new BigDecimal(Arith.add(capitaltWallet.getMoney(), withdraw.getVolume()))) .eq(CapitaltWallet::getUserId,wallet.getUserId())); walletService.update(new LambdaUpdateWrapper<Wallet>() .set(Wallet::getMoney,new BigDecimal(Arith.add(wallet1.getMoney(), withdraw.getVolume()))) .eq(Wallet::getUserId,wallet.getUserId())); /* @@ -482,11 +492,11 @@ throw new YamiShopBindException("Your account has been frozen"); } // Wallet wallet = walletService.saveWalletByPartyId(withdraw.getUserId()); Wallet wallet = walletService.saveWalletByPartyId(withdraw.getUserId()); CapitaltWallet capitaltWallet = capitaltWalletService.getOne(new LambdaQueryWrapper<>(CapitaltWallet.class) .eq(CapitaltWallet::getUserId, withdraw.getUserId()).last(" limit 1 ")); if (capitaltWallet.getMoney().doubleValue() < withdraw.getVolume().doubleValue()) { // CapitaltWallet capitaltWallet = capitaltWalletService.getOne(new LambdaQueryWrapper<>(CapitaltWallet.class) // .eq(CapitaltWallet::getUserId, withdraw.getUserId()).last(" limit 1 ")); if (wallet.getMoney().doubleValue() < withdraw.getVolume().doubleValue()) { throw new YamiShopBindException("not sufficient funds"); } // 手续费(USDT) @@ -671,17 +681,17 @@ */ String withdraw_qr = qRGenerateService.generateWithdraw(withdraw.getOrderNo(), withdraw.getAddress()); withdraw.setQdcode(withdraw_qr); double amount_before = capitaltWallet.getMoney().doubleValue(); double amount_before = wallet.getMoney().doubleValue(); // walletService.update(wallet.getUserId().toString(), Arith.sub(0, withdraw.getVolume().doubleValue())); if(ObjectUtil.isEmpty(capitaltWallet)){ if(ObjectUtil.isEmpty(wallet)){ throw new YamiShopBindException("The user's funds account does not exist!"); } capitaltWalletService.update(capitaltWallet,-withdraw.getVolume().doubleValue()); walletService.update(wallet.getUserId(),-withdraw.getVolume().doubleValue()); save(withdraw); @@ -692,7 +702,7 @@ moneyLog.setCategory(Constants.MONEYLOG_CATEGORY_COIN); moneyLog.setAmountBefore(new BigDecimal(amount_before)); moneyLog.setAmount(new BigDecimal(Arith.sub(0, withdraw.getVolume().doubleValue()))); moneyLog.setAmountAfter(capitaltWallet.getMoney()); moneyLog.setAmountAfter(wallet.getMoney()); moneyLog.setLog("提现订单[" + withdraw.getOrderNo() + "]"); // moneyLog.setExtra(withdraw.getOrder_no()); moneyLog.setUserId(withdraw.getUserId()); trading-order-service/src/main/java/com/yami/trading/service/item/ItemService.java
@@ -162,7 +162,7 @@ @Cached(name = ITEM_CACHE, key = "'all'", expire = 3600) @Override public List<Item> list() { List<Item> list = super.list(new LambdaQueryWrapper<>(Item.class).eq(Item::getType,Item.cryptos)); List<Item> list = super.list(new LambdaQueryWrapper<>(Item.class).eq(Item::getDelFlag,0)); symbolDecimal = list.stream() .collect(Collectors.toMap(Item::getSymbol, Item::getDecimals, (s1, s2) -> s2)); return list; trading-order-service/src/main/java/com/yami/trading/service/user/impl/UserStatisticsServiceImpl.java
@@ -118,8 +118,10 @@ result.add(0,data); Map<String,Object> capitaldata = new HashMap<String,Object>(); CapitaltWallet capitaltWallet = capitaltWalletService.getOne(new LambdaQueryWrapper<>(CapitaltWallet.class) .eq(CapitaltWallet::getUserId, targetPartyId).last(" limit 1 ")); // CapitaltWallet capitaltWallet = capitaltWalletService.getOne(new LambdaQueryWrapper<>(CapitaltWallet.class) // .eq(CapitaltWallet::getUserId, targetPartyId).last(" limit 1 ")); Wallet capitaltWallet = walletService.getOne(new LambdaQueryWrapper<>(Wallet.class) .eq(Wallet::getUserId, targetPartyId).last(" limit 1 ")); capitaldata.put("wallettype", "capitalusdt"); capitaldata.put("amount",null==capitaltWallet?0:new BigDecimal(capitaltWallet.getMoney().doubleValue()).setScale(8, RoundingMode.FLOOR).toPlainString() ); capitaldata.put("lock_amount",null==capitaltWallet?0:capitaltWallet.getLockMoney().setScale(8, RoundingMode.FLOOR).toPlainString() );