package com.yami.trading.huobi.data;
|
|
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson2.JSON;
|
import com.yami.trading.bean.data.domain.Realtime;
|
import com.yami.trading.bean.item.domain.Item;
|
import com.yami.trading.common.util.Arith;
|
import com.yami.trading.huobi.data.internal.DataDBService;
|
import com.yami.trading.huobi.data.job.AdjustmentTaskScheduler;
|
import com.yami.trading.huobi.data.model.AdjustmentValue;
|
import com.yami.trading.huobi.hobi.HobiDataService;
|
import com.yami.trading.huobi.websocket.model.market.MarketTicker;
|
import com.yami.trading.service.item.ItemService;
|
import com.yami.trading.service.syspara.SysparaService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Component;
|
|
import java.math.BigDecimal;
|
import java.math.RoundingMode;
|
import java.util.List;
|
|
/**
|
* @Author: TG:哪吒出海
|
* @Date: 2025-04-27-3:49
|
* @Description: 处理所有行情 加载进缓存 and 数据库
|
*/
|
@Slf4j
|
@Component
|
public class NezhaHandleRealTime {
|
|
public static volatile boolean first = true;
|
/**
|
* 数据接口调用间隔时长(毫秒)
|
*/
|
protected int interval = 1000;
|
@Autowired
|
protected DataDBService dataDBService;
|
@Autowired
|
protected ItemService itemService;
|
@Autowired
|
private AdjustmentTaskScheduler adjustmentTaskScheduler;
|
private String name;
|
|
public NezhaHandleRealTime builder(String name){
|
this.name = name;
|
return this;
|
}
|
|
public void handleRealTimeList(List<Realtime> realtimeList) {
|
for (Realtime realtime : realtimeList) {
|
try {
|
String symbol = realtime.getSymbol();
|
symbol = itemService.getSymbolByRemarks(symbol);
|
Integer decimal = itemService.getDecimal(symbol);
|
Item item = this.itemService.findBySymbol(symbol);
|
//更新行情中的symbol [要不然后续取不到缓存]
|
realtime.setSymbol(item.getSymbol());
|
|
Double currentValue = AdjustmentValueCache.getCurrentValue().get(symbol);
|
AdjustmentValue delayValue = AdjustmentValueCache.getDelayValue().get(symbol);
|
if (delayValue != null) {
|
log.info("-----------------:"+AdjustmentValueCache.getDelayValue().toString());
|
// 延时几次
|
int frequency = (int) Arith.div(Arith.mul(delayValue.getSecond(), 1000.0D), this.interval);
|
|
if (frequency <= 1) {
|
if (currentValue == null) {
|
AdjustmentValueCache.getCurrentValue().put(symbol, delayValue.getValue());
|
} else {
|
AdjustmentValueCache.getCurrentValue().put(symbol, delayValue.getValue() + currentValue);
|
}
|
|
if (item.getAdjustmentValue() != AdjustmentValueCache.getCurrentValue().get(symbol)) {
|
item.setAdjustmentValue(AdjustmentValueCache.getCurrentValue().get(symbol));
|
itemService.saveOrUpdate(item);
|
}
|
AdjustmentValueCache.getDelayValue().remove(symbol);
|
} else {
|
// 本次调整值
|
//logger.info("---> AbstractGetDataJob.handleRealTimeList debug 位置2, current symbol:{} value:{}", symbol, AdjustmentValueCache.getCurrentValue().get(symbol));
|
double currentValueFrequency = BigDecimal.valueOf(delayValue.getValue() / frequency).setScale(decimal, RoundingMode.HALF_UP).doubleValue();
|
// delayValue.getValue().divide(new BigDecimal(frequency), decimal, RoundingMode.HALF_UP);
|
if (currentValue == null) {
|
AdjustmentValueCache.getCurrentValue().put(symbol, currentValueFrequency);
|
} else {
|
AdjustmentValueCache.getCurrentValue().put(symbol, currentValue + currentValueFrequency);
|
}
|
|
delayValue.setValue(delayValue.getValue() - currentValueFrequency);
|
delayValue.setSecond(Arith.sub(delayValue.getSecond(), Arith.div(this.interval, 1000.0D)));
|
AdjustmentValueCache.getDelayValue().put(symbol, delayValue);
|
|
if (item.getAdjustmentValue() != AdjustmentValueCache.getCurrentValue().get(symbol)) {
|
item.setAdjustmentValue(AdjustmentValueCache.getCurrentValue().get(symbol));
|
itemService.saveOrUpdate(item);
|
}
|
}
|
}
|
|
currentValue = AdjustmentValueCache.getCurrentValue().get(realtime.getSymbol());
|
//logger.info("---> AbstractGetDataJob.handleRealTimeList debug 位置3, currentValue:{}", currentValue);
|
if (currentValue != null && currentValue != 0) {
|
realtime.setClose(BigDecimal.valueOf(realtime.getClose() + currentValue).setScale(decimal, RoundingMode.HALF_UP).doubleValue());
|
realtime.setAsk(BigDecimal.valueOf(realtime.getAsk() + currentValue).setScale(decimal, RoundingMode.HALF_UP).doubleValue());
|
realtime.setBid(BigDecimal.valueOf(realtime.getBid() + currentValue).setScale(decimal, RoundingMode.HALF_UP).doubleValue());
|
}
|
//获取24h开盘价
|
MarketTicker marketTicker = DataCache.getMarketTicker(symbol+"usdt");
|
BigDecimal open = marketTicker.getOpen();
|
BigDecimal close = BigDecimal.valueOf(realtime.getClose());
|
//计算涨跌幅
|
BigDecimal changeRatio = close.subtract(open).divide(open, 10, RoundingMode.HALF_UP)
|
.multiply(new BigDecimal(100)).setScale(2, RoundingMode.DOWN);
|
BigDecimal netChange = close.multiply(changeRatio).divide(new BigDecimal(100), 10, RoundingMode.HALF_UP);
|
netChange = netChange.setScale(4, RoundingMode.DOWN);
|
realtime.setNetChange(netChange.doubleValue());
|
realtime.setChangeRatio(changeRatio.doubleValue());
|
try {
|
// 缓存中最新一条Realtime数据
|
Realtime realtimeLast = DataCache.getRealtime(symbol);
|
// 临时处理:正常10秒超过25%也不合理,丢弃.只有虚拟货币才这样执行
|
boolean checkRate = Item.cryptos.equals(this.name);
|
double rate = 0;
|
if (!checkRate) {
|
saveData(realtime, symbol, item);
|
} else {
|
if (realtimeLast != null) {
|
rate = Math.abs(Arith.sub(realtime.getClose(), realtimeLast.getClose()));
|
}
|
if (null == realtimeLast) {
|
log.error("缓存里面没有realtimeLast数据, 注意观察");
|
saveData(realtime, symbol, item);
|
return;
|
}
|
if (realtimeLast.getClose() == 0) {
|
saveData(realtime, symbol, item);
|
}
|
|
//System.out.println("收到数字货币消息:" + JSON.toJSONString(realtime));
|
|
saveData(realtime, symbol, item);
|
//else if (Arith.div(rate, realtimeLast.getClose()) < 0.25D) {
|
// saveData(realtime, symbol, item);
|
//} else {
|
// log.error("当前{}价格{},上一次价格为{}过25%也不合理,丢弃Realtime,不入库", realtime.getSymbol(), realtime.getClose(), realtimeLast.getClose());
|
//}
|
}
|
} catch (Exception e) {
|
log.error("---> AbstractGetDataJob.handleRealTimeList debug 位置4, realtime -> symbol:{}, error: ", realtime.getSymbol(), e);
|
throw e;
|
}
|
} catch (Exception e) {
|
log.error("数据采集失败 {}:[]", realtime.getSymbol(), JSONObject.toJSON(realtime), e);
|
}
|
}
|
}
|
|
public void handleRealTimeList(Realtime realtime) {
|
try {
|
String symbol = realtime.getSymbol();
|
// 如果是纯数字且长度小于5,补充前导零 兼容 港股
|
if (symbol.matches("\\d+")) {
|
symbol = String.format("%05d", Integer.parseInt(symbol));
|
}
|
symbol = itemService.getSymbolByRemarks(symbol);
|
Integer decimal = itemService.getDecimal(symbol);
|
Item item = this.itemService.findBySymbol(symbol);
|
if (item == null) {
|
return;
|
}
|
//更新行情中的symbol [要不然后续取不到缓存]
|
realtime.setSymbol(item.getSymbol());
|
|
Double currentValue = AdjustmentValueCache.getCurrentValue().get(symbol);
|
AdjustmentValue delayValue = AdjustmentValueCache.getDelayValue().get(symbol);
|
//logger.info("---> AbstractGetDataJob.handleRealTimeList debug 位置1, item:{}", item);
|
if (delayValue != null) {
|
// 延时几次
|
int frequency = (int) Arith.div(Arith.mul(delayValue.getSecond(), 1000.0D), this.interval);
|
|
if (frequency <= 1) {
|
if (currentValue == null) {
|
AdjustmentValueCache.getCurrentValue().put(symbol, delayValue.getValue());
|
} else {
|
AdjustmentValueCache.getCurrentValue().put(symbol, delayValue.getValue() + currentValue);
|
}
|
|
if (item.getAdjustmentValue() != AdjustmentValueCache.getCurrentValue().get(symbol)) {
|
item.setAdjustmentValue(AdjustmentValueCache.getCurrentValue().get(symbol));
|
itemService.saveOrUpdate(item);
|
}
|
AdjustmentValueCache.getDelayValue().remove(symbol);
|
} else {
|
// 本次调整值
|
//logger.info("---> AbstractGetDataJob.handleRealTimeList debug 位置2, current symbol:{} value:{}", symbol, AdjustmentValueCache.getCurrentValue().get(symbol));
|
double currentValueFrequency = BigDecimal.valueOf(delayValue.getValue() / frequency).setScale(decimal, RoundingMode.HALF_UP).doubleValue();
|
// delayValue.getValue().divide(new BigDecimal(frequency), decimal, RoundingMode.HALF_UP);
|
if (currentValue == null) {
|
AdjustmentValueCache.getCurrentValue().put(symbol, currentValueFrequency);
|
} else {
|
AdjustmentValueCache.getCurrentValue().put(symbol, currentValue + currentValueFrequency);
|
}
|
|
delayValue.setValue(delayValue.getValue() - currentValueFrequency);
|
delayValue.setSecond(Arith.sub(delayValue.getSecond(), Arith.div(this.interval, 1000.0D)));
|
AdjustmentValueCache.getDelayValue().put(symbol, delayValue);
|
|
if (item.getAdjustmentValue() != AdjustmentValueCache.getCurrentValue().get(symbol)) {
|
item.setAdjustmentValue(AdjustmentValueCache.getCurrentValue().get(symbol));
|
itemService.saveOrUpdate(item);
|
}
|
}
|
}
|
|
currentValue = AdjustmentValueCache.getCurrentValue().get(realtime.getSymbol());
|
//logger.info("---> AbstractGetDataJob.handleRealTimeList debug 位置3, currentValue:{}", currentValue);
|
if (currentValue != null && currentValue != 0) {
|
realtime.setClose(BigDecimal.valueOf(realtime.getClose() + currentValue).setScale(decimal, RoundingMode.HALF_UP).doubleValue());
|
realtime.setAsk(BigDecimal.valueOf(realtime.getAsk() + currentValue).setScale(decimal, RoundingMode.HALF_UP).doubleValue());
|
realtime.setBid(BigDecimal.valueOf(realtime.getBid() + currentValue).setScale(decimal, RoundingMode.HALF_UP).doubleValue());
|
}
|
|
try {
|
// 缓存中最新一条Realtime数据
|
Realtime realtimeLast = DataCache.getRealtime(symbol);
|
// 临时处理:正常10秒超过25%也不合理,丢弃.只有虚拟货币才这样执行
|
boolean checkRate = Item.cryptos.equals(this.name);
|
double rate = 0;
|
if (!checkRate) {
|
saveData(realtime, symbol, item);
|
} else {
|
if (realtimeLast != null) {
|
rate = Math.abs(Arith.sub(realtime.getClose(), realtimeLast.getClose()));
|
}
|
if (null == realtimeLast) {
|
log.error("缓存里面没有realtimeLast数据, 注意观察");
|
saveData(realtime, symbol, item);
|
return;
|
}
|
if (realtimeLast.getClose() == 0) {
|
saveData(realtime, symbol, item);
|
}
|
|
//System.out.println("收到数字货币消息:" + JSON.toJSONString(realtime));
|
|
saveData(realtime, symbol, item);
|
//else if (Arith.div(rate, realtimeLast.getClose()) < 0.25D) {
|
// saveData(realtime, symbol, item);
|
//} else {
|
// log.error("当前{}价格{},上一次价格为{}过25%也不合理,丢弃Realtime,不入库", realtime.getSymbol(), realtime.getClose(), realtimeLast.getClose());
|
//}
|
}
|
} catch (Exception e) {
|
log.error("---> AbstractGetDataJob.handleRealTimeList debug 位置4, realtime -> symbol:{}, error: ", realtime.getSymbol(), e);
|
throw e;
|
}
|
} catch (Exception e) {
|
log.error("数据采集失败 {}:[]",realtime.getSymbol(), JSONObject.toJSON(realtime), e);
|
}
|
}
|
|
private void saveData(Realtime realtime, String symbol, Item item) {
|
Double high = DataCache.getRealtimeHigh(symbol);
|
Double low = DataCache.getRealtimeLow(symbol);
|
if (realtime.getTs().toString().length() <= 10) {
|
realtime.setTs(Long.valueOf(realtime.getTs() + "000"));
|
}
|
realtime.setName(item.getName());
|
if (high == null || realtime.getHigh() > high) {
|
// 刷新内存中的 high
|
DataCache.putRealtimeHigh(symbol, realtime.getHigh());
|
}
|
if ((low == null || realtime.getLow() < low) && realtime.getLow() > 0) {
|
// 刷新内存中的 low,并且只使用值大于 0 的 low
|
DataCache.putRealtimeLow(symbol, realtime.getLow());
|
}
|
this.dataDBService.saveAsyn(realtime);
|
}
|
|
}
|