package com.nq.utils.task.stock;
|
|
import cn.hutool.core.collection.CollectionUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.json.JSONArray;
|
import com.alibaba.fastjson2.JSONObject;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.google.gson.Gson;
|
import com.nq.common.ServerResponse;
|
import com.nq.dao.StockMapper;
|
import com.nq.dao.UserMapper;
|
import com.nq.dao.UserPendingorderMapper;
|
import com.nq.dao.UserPositionMapper;
|
import com.nq.enums.EConfigKey;
|
import com.nq.enums.EStockType;
|
import com.nq.enums.EUserAssets;
|
import com.nq.pojo.*;
|
import com.nq.pojo.reponse.kResponse;
|
import com.nq.service.*;
|
import com.nq.service.impl.StockServiceImpl;
|
import com.nq.service.impl.UserServiceImpl;
|
import com.nq.utils.ConverterUtil;
|
import com.nq.utils.KeyUtils;
|
import com.nq.utils.UserPointUtil;
|
import com.nq.utils.http.HttpClientRequest;
|
import com.nq.utils.redis.RedisKeyConstant;
|
import com.nq.utils.redis.RedisKeyUtil;
|
import com.nq.utils.redis.RedisShardedPoolUtils;
|
import com.nq.utils.stock.GeneratePosition;
|
import com.nq.vo.position.PositionProfitVO;
|
import org.apache.commons.lang3.StringUtils;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.stereotype.Component;
|
import org.springframework.web.client.RestTemplate;
|
|
import javax.servlet.http.HttpServletRequest;
|
import java.io.BufferedReader;
|
import java.io.InputStreamReader;
|
import java.io.UnsupportedEncodingException;
|
import java.math.BigDecimal;
|
import java.math.RoundingMode;
|
import java.net.HttpURLConnection;
|
import java.net.URL;
|
import java.net.URLEncoder;
|
import java.text.DecimalFormat;
|
import java.util.*;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.ReentrantLock;
|
|
|
@Component
|
public class StockTask {
|
@Autowired
|
IStockService stockService;
|
@Autowired
|
StockMapper stockMapper;
|
|
@Autowired
|
IUserPositionService userPositionService;
|
|
@Autowired
|
UserPositionMapper userPositionMapper;
|
|
@Autowired
|
private UserPendingorderService userPendingorderService;
|
@Autowired
|
IMandatoryLiquidationService mandatoryLiquidationService;
|
@Autowired
|
IUserAssetsServices iUserAssetsServices;
|
@Autowired
|
IStockConfigServices iStockConfigServices;
|
|
@Autowired
|
IPriceServices priceServices;
|
@Autowired
|
UserMapper userMapper;
|
|
private static final Logger log = LoggerFactory.getLogger(StockTask.class);
|
|
|
|
private final AtomicBoolean syncINStockData = new AtomicBoolean(false);
|
|
private final Lock syncINStockDataLock = new ReentrantLock();
|
|
/**
|
* 同步系统所需要的股票
|
*/
|
@Scheduled(cron = "0 0/1 * * * ?")
|
public void syncINStockData() {
|
if (syncINStockData.get()) { // 判断任务是否在处理中
|
return;
|
}
|
if (syncINStockDataLock.tryLock()) {
|
try {
|
syncINStockData.set(true); // 设置处理中标识为true
|
loadAllStock(EStockType.ST);
|
} finally {
|
syncINStockDataLock.unlock();
|
syncINStockData.set(false); // 设置处理中标识为false
|
}
|
}
|
}
|
|
|
/**
|
* 挂单
|
*/
|
@Scheduled(cron = "0/10 * * * * ?")
|
public void pendingOrder() {
|
ReentrantLock lock = new ReentrantLock();
|
if (lock.tryLock()) { // 尝试获取锁
|
try {
|
pending();
|
}catch (Exception e){
|
e.printStackTrace();
|
log.error("买入挂单定时任务报错:",e.getMessage());
|
}
|
finally {
|
lock.unlock(); // 释放锁
|
}
|
} else {
|
// 如果锁不可用,可以选择不执行或打印日志等
|
System.out.println("买入挂单定时任务 任务正在执行,跳过本次执行。");
|
}
|
}
|
|
/**
|
* 挂单平仓
|
*/
|
@Scheduled(cron = "0/10 * * * * ?")
|
public void closeOrder() {
|
ReentrantLock lock = new ReentrantLock();
|
if (lock.tryLock()) { // 尝试获取锁
|
try {
|
closeOutOrder();
|
}catch (Exception e){
|
e.printStackTrace();
|
log.error("平仓挂单定时任务报错:",e.getMessage());
|
}
|
finally {
|
lock.unlock(); // 释放锁
|
}
|
} else {
|
// 如果锁不可用,可以选择不执行或打印日志等
|
System.out.println("平仓挂单定时任务 任务正在执行,跳过本次执行。");
|
}
|
}
|
|
public void closeOutOrder() {
|
List<UserPendingorder> list = userPendingorderService.list(new LambdaQueryWrapper<>(UserPendingorder.class)
|
.eq(UserPendingorder::getPositionType, 1)
|
.eq(UserPendingorder::getHangingOrderType,2));
|
if(CollectionUtil.isNotEmpty(list)){
|
list.forEach(f->{
|
//获取当前价格
|
//股票类型 现价 数据源的处理
|
BigDecimal nowPrice = BigDecimal.ZERO;
|
if(f.getStockType().equals("ST")){
|
nowPrice = priceServices.getNowPrice(f.getStockCode());
|
}else{
|
nowPrice = new BigDecimal(RedisShardedPoolUtils.get(RedisKeyConstant.getRedisKey(f.getStockName())));
|
}
|
if((f.getOrderDirection().equals("买涨") && nowPrice.compareTo(f.getSellOrderPrice()) >= 0) || (f.getOrderDirection().equals("买跌") && nowPrice.compareTo(f.getSellOrderPrice()) <= 0)){
|
closeStockTransferPositions(f);
|
}
|
});
|
}
|
}
|
|
private void closeStockTransferPositions(UserPendingorder f) {
|
UserPosition userPosition = userPositionMapper.selectOne(new LambdaQueryWrapper<>(UserPosition.class)
|
.eq(UserPosition::getPositionSn, f.getPositionSn())
|
.eq(UserPosition::getUserId, f.getUserId())
|
|
);
|
|
BigDecimal siitteBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.SELL_HANDLING_CHARGE.getCode()).getCValue());
|
//部分平仓
|
if(f.getOrderNum() < userPosition.getOrderNum()){
|
//拆分订单
|
UserPosition position = ConverterUtil.convert(userPosition,UserPosition.class);
|
position.setId(null);
|
position.setPositionSn(KeyUtils.getUniqueKey());
|
//得到均价
|
double buyOrderPrice = position.getOrderTotalPrice().doubleValue() / position.getOrderNum().doubleValue() * position.getOrderLever();
|
position.setOrderNum(userPosition.getOrderNum()-f.getOrderNum());
|
BigDecimal positionBuyAmt = new BigDecimal(buyOrderPrice).multiply(new BigDecimal(position.getOrderNum())).divide(new BigDecimal(position.getOrderLever()));
|
position.setOrderTotalPrice(positionBuyAmt);
|
position.setBuyOrderPrice(new BigDecimal(buyOrderPrice));
|
position.setBuyOrderId(GeneratePosition.getPositionId());
|
//修改拆分订单手续费
|
BigDecimal BuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.BUY_HANDLING_CHARGE.getCode()).getCValue());
|
BigDecimal buyPrice = position.getBuyOrderPrice().multiply(new BigDecimal(position.getOrderNum()));
|
BigDecimal xsPrice = buyPrice.multiply(BuyFee);
|
position.setOrderFee(xsPrice);
|
userPositionMapper.insert(position);
|
//得到均价
|
double orderPrice = userPosition.getOrderTotalPrice().doubleValue() / userPosition.getOrderNum().doubleValue() * position.getOrderLever();
|
//修改原订单
|
userPosition.setOrderNum(f.getOrderNum());
|
BigDecimal buyAmt = new BigDecimal(orderPrice).multiply(new BigDecimal(userPosition.getOrderNum())).divide(new BigDecimal(userPosition.getOrderLever()));
|
userPosition.setOrderTotalPrice(buyAmt);
|
userPosition.setOrderFee(userPosition.getOrderFee().subtract(position.getOrderFee()));
|
userPositionMapper.updateById(userPosition);
|
}
|
getObjectServerResponse(userPosition, f.getSellOrderPrice(), siitteBuyFee, f.getStockType());
|
f.setPositionType(2);
|
userPendingorderService.updateById(f);
|
}
|
|
public void getObjectServerResponse( UserPosition userPosition, BigDecimal nowPrice, BigDecimal siitteBuyFee, String stockType) {
|
userPosition.setSellOrderId(GeneratePosition.getPositionId());
|
userPosition.setSellOrderPrice(nowPrice);
|
userPosition.setSellOrderTime(new Date());
|
|
BigDecimal sellOrderTotel = nowPrice.multiply(new BigDecimal(userPosition.getOrderNum()));
|
BigDecimal xsPrice = sellOrderTotel.multiply(siitteBuyFee);
|
userPosition.setOrderFee(userPosition.getOrderFee().add(xsPrice));
|
userPositionMapper.updateById(userPosition);
|
|
iUserAssetsServices.availablebalanceChange(stockType,
|
userPosition.getUserId(),
|
EUserAssets.CLOSE_POSITION_RETURN_SECURITY_DEPOSIT,
|
userPosition.getOrderTotalPrice(), "", "");
|
iUserAssetsServices.availablebalanceChange(stockType,
|
userPosition.getUserId(), EUserAssets.HANDLING_CHARGE,
|
xsPrice, "", "");
|
|
PositionProfitVO profitVO = UserPointUtil.getPositionProfitVO(userPosition,
|
priceServices.getNowPrice(userPosition.getStockCode()));
|
|
iUserAssetsServices.availablebalanceChange(stockType,
|
userPosition.getUserId(), EUserAssets.CLOSE_POSITION,
|
profitVO.getAllProfitAndLose(), "", "");
|
}
|
|
public void pending(){
|
List<UserPendingorder> list = userPendingorderService.list(new LambdaQueryWrapper<>(UserPendingorder.class)
|
.eq(UserPendingorder::getPositionType, 1)
|
.eq(UserPendingorder::getHangingOrderType,1));
|
if(CollectionUtil.isNotEmpty(list)){
|
list.forEach(f->{
|
if(f.getStockGid().equals("ST")){
|
//获取当前价格
|
//股票类型 现价 数据源的处理
|
BigDecimal nowPrice = priceServices.getNowPrice(f.getStockCode());
|
if((f.getOrderDirection().equals("买涨") && f.getBuyOrderPrice().compareTo(nowPrice) >= 0) || (f.getOrderDirection().equals("买跌") && f.getBuyOrderPrice().compareTo(nowPrice) <= 0)){
|
stockTransferPositions(f);
|
}
|
}else{
|
String price = RedisShardedPoolUtils.get(RedisKeyConstant.getRedisKey(f.getStockName()));
|
if((f.getOrderDirection().equals("买涨") && f.getBuyOrderPrice().compareTo(new BigDecimal(price)) >= 0) || (f.getOrderDirection().equals("买跌") && f.getBuyOrderPrice().compareTo(new BigDecimal(price)) <= 0)){
|
hjTransferPositions(f);
|
}
|
}
|
});
|
}
|
}
|
public void hjTransferPositions(UserPendingorder userPendingorder){
|
UserPosition position = userPositionMapper.selectOne(new LambdaQueryWrapper<>(UserPosition.class)
|
.eq(UserPosition::getUserId, userPendingorder.getUserId())
|
.eq(UserPosition::getStockCode, userPendingorder.getStockCode())
|
.isNull(UserPosition::getSellOrderId)
|
);
|
User user = userMapper.selectById(userPendingorder.getUserId());
|
BigDecimal siteSettingBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.BUY_HANDLING_CHARGE.getCode()).getCValue()) ;
|
BigDecimal orderFree = siteSettingBuyFee.multiply(userPendingorder.getOrderTotalPrice());
|
UserPosition userPosition = ConverterUtil.convert(userPendingorder, UserPosition.class);
|
if(ObjectUtil.isEmpty(position)){
|
userPosition.setPositionType(user.getAccountType());
|
userPosition.setId(null);
|
userPendingorder.setPositionType(0);
|
userPendingorderService.updateById(userPendingorder);
|
userPositionMapper.insert(userPosition);
|
iUserAssetsServices.availablebalanceChange("USD", user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
|
}else{
|
position.setOrderNum(position.getOrderNum()+userPosition.getOrderNum());
|
position.setOrderTotalPrice(position.getOrderTotalPrice().add(userPosition.getOrderTotalPrice()));
|
position.setOrderFee(position.getOrderFee().add(orderFree));
|
position.setBuyOrderPrice(position.getBuyOrderPrice());
|
position.setAllProfitAndLose(position.getAllProfitAndLose().add(orderFree));
|
userPositionMapper.updateById(position);
|
userPendingorder.setPositionType(0);
|
userPendingorderService.updateById(userPendingorder);
|
iUserAssetsServices.availablebalanceChange("USD", user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
|
}
|
}
|
|
public void stockTransferPositions(UserPendingorder userPendingorder){
|
UserPosition position = userPositionMapper.selectOne(new LambdaQueryWrapper<>(UserPosition.class)
|
.eq(UserPosition::getUserId, userPendingorder.getUserId())
|
.eq(UserPosition::getStockCode, userPendingorder.getStockCode())
|
.isNull(UserPosition::getSellOrderId)
|
);
|
// 手续费率
|
BigDecimal siteSettingBuyFee = new BigDecimal(iStockConfigServices.queryByKey(EConfigKey.BUY_HANDLING_CHARGE.getCode()).getCValue()) ;
|
BigDecimal orderFree = siteSettingBuyFee.multiply(userPendingorder.getOrderTotalPrice());
|
User user = userMapper.selectById(userPendingorder.getUserId());
|
UserPosition userPosition = ConverterUtil.convert(userPendingorder, UserPosition.class);
|
if(ObjectUtil.isEmpty(position)){
|
userPosition.setPositionType(user.getAccountType());
|
userPosition.setId(null);
|
userPendingorder.setPositionType(0);
|
userPendingorderService.updateById(userPendingorder);
|
userPositionMapper.insert(userPosition);
|
//挂单成功扣除手续费
|
iUserAssetsServices.availablebalanceChange("ST", user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
|
}else{
|
position.setOrderNum(position.getOrderNum()+userPosition.getOrderNum());
|
position.setOrderTotalPrice(position.getOrderTotalPrice().add(userPosition.getOrderTotalPrice()));
|
position.setOrderFee(position.getOrderFee().add(orderFree));
|
double divide = position.getOrderTotalPrice().doubleValue() / position.getOrderNum();
|
position.setBuyOrderPrice(new BigDecimal(divide*position.getOrderLever()));
|
position.setAllProfitAndLose(position.getAllProfitAndLose().add(orderFree));
|
userPositionMapper.updateById(position);
|
userPendingorder.setPositionType(0);
|
userPendingorderService.updateById(userPendingorder);
|
//挂单成功扣除手续费
|
iUserAssetsServices.availablebalanceChange("ST", user.getId(), EUserAssets.HANDLING_CHARGE, orderFree, "", "");
|
}
|
}
|
|
//最新价格url
|
private static final String PRICE_URL = "https://quote.alltick.io/quote-b-api/trade-tick?token=794ea65dc03c5af582cddec476fbb0d7-c-app&query=";
|
//k线url
|
private static final String K_URL = "https://quote.alltick.io/quote-b-api/kline?token=794ea65dc03c5af582cddec476fbb0d7-c-app&query=";
|
|
|
public String getPriceData() {
|
// 创建查询数据
|
JSONObject data = new JSONObject();
|
|
// 用于存储符号的列表
|
JSONArray symbolList = new JSONArray();
|
|
// 需要查询的符号列表(按你的要求,这里符号从 ["857.HK", "UNH.US"] 开始)
|
String[] symbols = {"GOLD", "USOIL"};
|
|
// 遍历符号列表,构建 JSON 对象
|
for (String symbol : symbols) {
|
JSONObject symbolObject = new JSONObject();
|
symbolObject.put("code", symbol);
|
symbolList.put(symbolObject);
|
}
|
|
// 将 symbol_list 放入 data 对象中
|
data.put("symbol_list", symbolList);
|
|
// 创建查询请求对象
|
JSONObject query = new JSONObject();
|
query.put("trace", generateTraceCode()); // 假设 generateTraceCode() 是生成唯一追踪代码的方法
|
query.put("data", data);
|
// 返回构建的查询对象
|
return buildUrlWithQuery(query);
|
}
|
|
// 生成唯一追踪码
|
public static String generateTraceCode() {
|
// 获取当前时间戳
|
long timestamp = System.currentTimeMillis();
|
|
// 生成唯一的 UUID
|
String uuid = UUID.randomUUID().toString();
|
|
// 组合时间戳和 UUID,保证唯一性
|
return uuid + "-" + timestamp;
|
}
|
|
@Scheduled(cron = "0/2 * * * * ?") // 每6秒执行一次
|
public void sync() throws InterruptedException {
|
ReentrantLock lock = new ReentrantLock();
|
if (lock.tryLock()) { // 尝试获取锁
|
try {
|
gold();
|
Thread.sleep(2000);
|
getKDate();
|
} finally {
|
lock.unlock(); // 释放锁
|
}
|
} else {
|
// 如果锁不可用,可以选择不执行或打印日志等
|
System.out.println("任务正在执行,跳过本次执行。");
|
}
|
}
|
|
public void gold() {
|
try {
|
String url = PRICE_URL+getPriceData();
|
URL obj = new URL(url);
|
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
|
con.setRequestMethod("GET");
|
int responseCode = con.getResponseCode();
|
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
|
String inputLine;
|
StringBuffer response = new StringBuffer();
|
while ((inputLine = in.readLine()) != null) {
|
response.append(inputLine);
|
}
|
in.close();
|
if(responseCode == 200){
|
// 创建 ObjectMapper 对象
|
ObjectMapper objectMapper = new ObjectMapper();
|
|
// 解析 JSON 字符串
|
JsonNode rootNode = objectMapper.readTree(response.toString());
|
|
// 获取 "data" 节点下的 "tick_list" 数组
|
JsonNode tickList = rootNode.path("data").path("tick_list");
|
|
// 遍历 tick_list 数组并提取 code 和 price
|
for (JsonNode tick : tickList) {
|
String code = tick.path("code").asText().equals("GOLD") ? "XAUUSD" : tick.path("code").asText();
|
String price = tick.path("price").asText();
|
RedisShardedPoolUtils.set(RedisKeyConstant.getRedisKey(code), price);
|
}
|
}else{
|
log.info("黄金原油获实时价格定时任务------没有接收到数据:"+response);
|
}
|
} catch (Exception e) {
|
e.printStackTrace();
|
}
|
}
|
|
public static String buildUrlWithQuery(JSONObject jsonObject) {
|
try {
|
// 将 JSON 对象转换为字符串
|
String jsonString = jsonObject.toString();
|
// 使用 URLEncoder 编码 JSON 字符串
|
String encodedJson = URLEncoder.encode(jsonString, "UTF-8");
|
return encodedJson;
|
} catch (UnsupportedEncodingException e) {
|
e.printStackTrace();
|
return null;
|
}
|
}
|
|
|
public void getKDate() throws InterruptedException {
|
// 创建Map对象
|
Map<String, Integer> map = new HashMap<>();
|
|
// 写死键值对
|
map.put("d", 8);
|
map.put("w", 9);
|
map.put("m", 10);
|
map.put("1", 1);
|
map.put("5", 2);
|
map.put("30", 4);
|
|
for (Map.Entry<String, Integer> entry : map.entrySet()) {
|
String gold = getResp(K_URL + getKQueryData(entry.getValue(), "XAUUSD"));
|
if(StringUtils.isNotEmpty(gold)){
|
if(entry.getKey().equals("d")){
|
priceLimit(gold,"XAUUSD");
|
}
|
RedisShardedPoolUtils.set("k_gold_"+entry.getKey(), gold);
|
}
|
|
Thread.sleep(2000);
|
String c = getResp(K_URL+getKQueryData(entry.getValue(),"USOIL"));
|
if(StringUtils.isNotEmpty(c)){
|
if(entry.getKey().equals("d")) {
|
priceLimit(c, "USOIL");
|
}
|
RedisShardedPoolUtils.set("k_crude_oil_"+entry.getKey(), c);
|
}
|
Thread.sleep(2000);
|
}
|
}
|
|
@lombok.Data
|
class kData {
|
long t;
|
String c;
|
String o;
|
String h;
|
String l;
|
String v;
|
String vo;
|
}
|
public void priceLimit(String data,String key){
|
List<kData> kDataList = new ArrayList<>();
|
// 使用 Gson 解析 JSON 字符串
|
Gson gson = new Gson();
|
kResponse kResponse = gson.fromJson(data, kResponse.class);
|
|
// 打印 kline_list 的内容
|
for (kResponse.KlineData item : kResponse.getData().getKlineList()) {
|
kData kData = new kData();
|
kData.setT(item.getTimestamp());
|
kData.setC(item.getClose_price());
|
kData.setO(item.getOpen_price());
|
kData.setH(item.getHigh_price());
|
kData.setL(item.getLow_price());
|
kData.setV(item.getVolume());
|
kData.setVo(item.getTurnover());
|
kDataList.add(kData);
|
}
|
double oneC = Double.valueOf(kDataList.get(kDataList.size() - 1).getC());
|
double twoC = Double.valueOf(kDataList.get(kDataList.size() - 2).getC());
|
String h = String.valueOf(((oneC - twoC) / oneC * 100));
|
BigDecimal bd = new BigDecimal(h);
|
bd = bd.setScale(2, RoundingMode.DOWN); // RoundingMode.DOWN 表示截断而非四舍五入
|
RedisShardedPoolUtils.set(key+"_H",bd.toString());
|
RedisShardedPoolUtils.set(key+"_H",bd.toString());
|
}
|
|
public String getResp(String url){
|
try {
|
URL obj = new URL(url);
|
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
|
con.setRequestMethod("GET");
|
int responseCode = con.getResponseCode();
|
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
|
String inputLine;
|
StringBuffer response = new StringBuffer();
|
while ((inputLine = in.readLine()) != null) {
|
response.append(inputLine);
|
}
|
in.close();
|
if(responseCode == 200){
|
return response.toString();
|
}
|
}catch (Exception e){
|
e.printStackTrace();
|
log.error("k线请求错误!", e.getMessage());
|
}
|
return null;
|
}
|
|
//k线请求组装数据
|
public String getKQueryData(Integer k_data,String code){
|
JSONObject queryData = new JSONObject();
|
queryData.put("trace", generateTraceCode());
|
JSONObject data = new JSONObject();
|
data.put("code", code);//产品code
|
/**
|
* k线类型
|
* 1、1是1分钟K,2是5分钟K,3是15分钟K,4是30分钟K,5是小时K,6是2小时K(股票不支持2小时),7是4小时K(股票不支持4小时),8是日K,9是周K,10是月K (注:股票不支持2小时K、4小时K)
|
* 2、最短的k线只支持1分钟
|
* 3、查询昨日收盘价,kline_type 传8
|
*/
|
data.put("kline_type", k_data);
|
/**
|
* 从指定时间往前查询K线
|
* 1、传0表示从当前最新的交易日往前查k线
|
* 2、指定时间请传时间戳,传时间戳表示从该时间戳往前查k线
|
* 3、只有外汇贵金属加密货币支持传时间戳,股票类的code不支持
|
*/
|
data.put("kline_timestamp_end", 0);
|
/**
|
* 1、表示查询多少根K线,每次最大请求1000根,可根据时间戳循环往前请求
|
* 2、通过该字段可查询昨日收盘价,kline_type 传8,query_kline_num传2,返回2根k线数据中,时间戳较小的数据是昨日收盘价
|
*/
|
data.put("query_kline_num", 200);
|
/*
|
复权类型,对于股票类的code才有效,例如:0:除权,1:前复权,目前仅支持0
|
*/
|
data.put("adjust_type", 0);
|
queryData.put("data", data);
|
return buildUrlWithQuery(queryData);
|
}
|
|
|
/**
|
* 加载所有股票数据
|
*/
|
public void loadAllStock(EStockType eStockType) {
|
log.info("同步股票 数据 {}", eStockType.getCode());
|
List<DataStockBean> list = new ArrayList<>();
|
int totleStock = 1;
|
int page = 0;
|
try {
|
while (totleStock > list.size()) {
|
try {
|
String result = HttpClientRequest.doGet(eStockType.stockUrl + "list?country_id=" + eStockType.getContryId() + "&size=1000&page=" + page + "&key=" + eStockType.stockKey);
|
ReponseBase reponseBase = new Gson().fromJson(result, ReponseBase.class);
|
list.addAll(reponseBase.getData());
|
page++;
|
totleStock = reponseBase.getTotal();
|
} catch (Exception e) {
|
e.printStackTrace();
|
break;
|
}
|
}
|
for (DataStockBean o : list) {
|
Stock stock = stockMapper.findStockByCode(o.getId());
|
if (stock == null) {
|
stock = new Stock();
|
stock.setStockCode(o.getId());
|
stock.setStockName(o.getName());
|
stock.setStockType(eStockType.getCode());
|
if (o.getType() == null) {
|
stock.setStockGid(eStockType.getCode());
|
} else {
|
stock.setStockGid(o.getType());
|
}
|
stock.setStockSpell(o.getSymbol());
|
stock.setIsLock(0);
|
stock.setIsShow(0);
|
stock.setDataBase(0);
|
stock.setAddTime(new Date());
|
stockMapper.insert1(stock);
|
} else {
|
stock.setStockCode(o.getId());
|
stock.setStockName(o.getName());
|
stock.setStockType(eStockType.getCode());
|
if (o.getType() == null) {
|
stock.setStockGid(eStockType.getCode());
|
} else {
|
stock.setStockGid(o.getType());
|
}
|
stock.setStockSpell(o.getSymbol());
|
stock.setIsLock(0);
|
stock.setIsShow(0);
|
stock.setDataBase(0);
|
stock.setAddTime(new Date());
|
stockMapper.updateById(stock);
|
}
|
RedisKeyUtil.setCaCheKeyBaseStock(eStockType, o);
|
}
|
log.info("同步股票 数据 成功 {} 总共同步数据 {}", eStockType.getCode(), list.size());
|
} catch (
|
Exception e) {
|
log.error("同步出错", e);
|
}
|
}
|
|
private final AtomicBoolean stockConstraint = new AtomicBoolean(false);
|
|
/**
|
* 强制平仓
|
*/
|
// @Scheduled(cron = "0/1 * * * * ?")
|
// public void stockConstraint() {
|
// if (stockConstraint.get()) { // 判断任务是否在处理中
|
// return;
|
// }
|
// if (stockConstraintLock.tryLock()) {
|
// try {
|
// stockConstraint.set(true); // 设置处理中标识为true
|
// List<UserPosition> userPositions = userPositionMapper.selectList(new LambdaQueryWrapper<UserPosition>().isNull(UserPosition::getSellOrderId));
|
// if (CollectionUtils.isNotEmpty(userPositions)) {
|
// userPositionService.stockConstraint(userPositions);
|
// }
|
// } catch (Exception e) {
|
// e.printStackTrace();
|
// log.error("强制平仓任务错误:" + e.getMessage());
|
// } finally {
|
// stockConstraintLock.unlock();
|
// stockConstraint.set(false); // 设置处理中标识为false
|
// }
|
// } else {
|
// log.info("强制平仓任务--------->上次任务还未执行完成,本次任务忽略");
|
// }
|
// }
|
}
|