| | |
| | | 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.pojo.DataStockBean; |
| | | import com.nq.pojo.ReponseBase; |
| | | import com.nq.pojo.Stock; |
| | | import com.nq.pojo.UserPosition; |
| | | import com.nq.enums.EUserAssets; |
| | | import com.nq.pojo.*; |
| | | import com.nq.pojo.reponse.kResponse; |
| | | import com.nq.service.IMandatoryLiquidationService; |
| | | import com.nq.service.IStockService; |
| | | import com.nq.service.IUserPositionService; |
| | | 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.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; |
| | |
| | | @Autowired |
| | | UserPositionMapper userPositionMapper; |
| | | |
| | | private final Lock stockConstraintLock = new ReentrantLock(); |
| | | |
| | | |
| | | @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); |
| | | |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 挂单 |
| | | */ |
| | | @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 |
| | |
| | | if (lock.tryLock()) { // 尝试获取锁 |
| | | try { |
| | | gold(); |
| | | Thread.sleep(1000); |
| | | Thread.sleep(2000); |
| | | getKDate(); |
| | | } finally { |
| | | lock.unlock(); // 释放锁 |
| | |
| | | RedisShardedPoolUtils.set("k_gold_"+entry.getKey(), gold); |
| | | } |
| | | |
| | | Thread.sleep(1000); |
| | | Thread.sleep(2000); |
| | | String c = getResp(K_URL+getKQueryData(entry.getValue(),"USOIL")); |
| | | if(StringUtils.isNotEmpty(c)){ |
| | | if(entry.getKey().equals("d")) { |
| | |
| | | } |
| | | RedisShardedPoolUtils.set("k_crude_oil_"+entry.getKey(), c); |
| | | } |
| | | Thread.sleep(1000); |
| | | Thread.sleep(2000); |
| | | } |
| | | } |
| | | |
| | |
| | | kData.setVo(item.getTurnover()); |
| | | kDataList.add(kData); |
| | | } |
| | | DecimalFormat decimalFormat = new DecimalFormat("#.00"); |
| | | double oneC = Double.valueOf(kDataList.get(kDataList.size() - 1).getC()); |
| | | double twoC = Double.valueOf(kDataList.get(kDataList.size() - 2).getC()); |
| | | String h = String.valueOf(decimalFormat.format(((oneC - twoC) / oneC * 100))); |
| | | RedisShardedPoolUtils.set(key+"_H",h); |
| | | RedisShardedPoolUtils.set(key+"_H",h); |
| | | 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){ |