day04-股票K线功能实现

news2025/3/12 18:52:05

股票K线功能实现

今日目标

1.理解股票T和T-1概念,实现成交量对比功能;
2.理解个股涨跌幅度统计功能;
2.1 分析业务,SQL落地;
2.2 完善不存在数据的区间默认回显功能;
3.理解个股分时线业务,并实现功能;
4.理解个股日K线业务,并实现功能;

第一章 股票成交量对比功能

1、股票成交量对比功能分析

1.1 股票成交量对比功能原型

功能描述:统计A股大盘T日和T-1日成交量对比功能(成交量为沪深两市成交量之和)

在这里插入图片描述

1.2 相关表分析

stock_market_index_info表结构相关字段:

在这里插入图片描述

1.3 成交量对比功能接口分析

功能描述:统计A股大盘T日和T-1日成交量对比功能(成交量为沪深两市成交量之和)

服务路径:/api/quot/stock/tradeAmt
服务方法:GET
前端请求频率:每分钟
请求参数:无

在这里插入图片描述

返回数据格式:

{
    "code": 1,
    "data": {
        "amtList": [{"count": 3926392,"time": "202112310930"},{"count": 3926392,"time": "202112310931"}...],//T日每分钟成交量信息
        "yesAmtList":[{"count": 3926392,"time": "202112310930"},...]//T-1日每分钟成交量信息 
	}
}

注意事项:如果当前日期不在股票交易日,则按照前一个有效股票交易日作为T日查询

R<Map<String,List>>

2、成交量对比功能SQL分析

-- 思路:通过逻辑获取T日开盘时间和当前时间日期范围,ge: 2022-01-03 09:30:00 到 2022-01-03 14:40:00
-- 那么T-1日日期范围则为:2022-01-02 09:30:00 到 2022-01-02 14:40:00
-- 我们可分别统计T日和T-1日国内A股大盘交易量,然后再讲数据组装即可
-- 1.统计T日交易量数据信息(T-1日SQL结构一致)
select
	date_format(smi.cur_time,'%Y%m%d%H%i') as time,
	sum(smi.trade_amount) as count
from
	stock_market_index_info as smi
where
	smi.cur_time between '2022-01-03 09:30:00' and '2022-01-03 14:40:00'
and
	smi.market_code in ('sh000001','sz399001')
group by time
order by smi.cur_time asc;
-- SQL语句添加order by 保证查询的数据是按照日期排序

3、成交量对比功能实现

3.1 定义web服务接口方法

    /**
     * 功能描述:统计国内A股大盘T日和T-1日成交量对比功能(成交量为沪市和深市成交量之和)
     * @return
     */
    @GetMapping("/stock/tradeAmt")
    public R<Map> stockTradeVol4InnerMarket(){
        return stockService.stockTradeVol4InnerMarket();
    }

3.2 定义服务接口方法与实现

服务接口方法:

    /**
     * 功能描述:统计国内A股大盘T日和T-1日成交量对比功能(成交量为沪市和深市成交量之和)
     * @return
     */
    R<Map> stockTradeVol4InnerMarket();

服务接口方法实现:

    /**
     * 功能描述:统计国内A股大盘T日和T-1日成交量对比功能(成交量为沪市和深市成交量之和)
     *   map结构示例:
     *      {
     *         "volList": [{"count": 3926392,"time": "202112310930"},......],
     *       "yesVolList":[{"count": 3926392,"time": "202112310930"},......]
     *      }
     * @return
     */
    @Override
    public R<Map> stockTradeVol4InnerMarket() {
        //1.获取T日和T-1日的开始时间和结束时间
        //1.1 获取最近股票有效交易时间点--T日时间范围
        DateTime lastDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        DateTime openDateTime = DateTimeUtil.getOpenDate(lastDateTime);
        //转化成java中Date,这样jdbc默认识别
        Date startTime4T = openDateTime.toDate();
        Date endTime4T=lastDateTime.toDate();
        //TODO  mock数据
        startTime4T=DateTime.parse("2022-01-03 09:30:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        endTime4T=DateTime.parse("2022-01-03 14:40:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();

        //1.2 获取T-1日的区间范围
        //获取lastDateTime的上一个股票有效交易日
        DateTime preLastDateTime = DateTimeUtil.getPreviousTradingDay(lastDateTime);
        DateTime preOpenDateTime = DateTimeUtil.getOpenDate(preLastDateTime);
        //转化成java中Date,这样jdbc默认识别
        Date startTime4PreT = preOpenDateTime.toDate();
        Date endTime4PreT=preLastDateTime.toDate();
        //TODO  mock数据
        startTime4PreT=DateTime.parse("2022-01-02 09:30:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        endTime4PreT=DateTime.parse("2022-01-02 14:40:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();

        //2.获取上证和深证的配置的大盘id
        //2.1 获取大盘的id集合
        List<String> markedIds = stockInfoConfig.getInner();
        //3.分别查询T日和T-1日的交易量数据,得到两个集合
        //3.1 查询T日大盘交易统计数据
        List<Map> data4T=stockMarketIndexInfoMapper.getStockTradeVol(markedIds,startTime4T,endTime4T);
        if (CollectionUtils.isEmpty(data4T)) {
            data4T=new ArrayList<>();
        }
        //3.2 查询T-1日大盘交易统计数据
        List<Map> data4PreT=stockMarketIndexInfoMapper.getStockTradeVol(markedIds,startTime4PreT,endTime4PreT);
        if (CollectionUtils.isEmpty(data4PreT)) {
            data4PreT=new ArrayList<>();
        }
        //4.组装响应数据
        HashMap<String, List> info = new HashMap<>();
        info.put("amtList",data4T);
        info.put("yesAmtList",data4PreT);
        //5.返回数据
        return R.ok(info);
    }

注意:当前无法获取实时的数据,选择已存在的合适的时间范围查询即可;

3.3 定义mapper接口和xml

定义mapper接口方法:

    /**
     * 根据时间范围和指定的大盘id统计每分钟的交易量
     * @param markedIds 大盘id集合
     * @param startTime 交易开始时间
     * @param endTime 结束时间
     * @return
     */
    List<Map> getStockTradeVol(@Param("markedIds") List<String> markedIds,
                               @Param("startTime") Date startTime,
                               @Param("endTime") Date endTime);

XML方法绑定:

    <select id="getStockTradeVol" resultType="map">
        select
            date_format(smi.cur_time,'%Y%m%d%H%i') as time,
            sum(smi.trade_amount)  as count
        from stock_market_index_info as smi
        where smi.market_code in
        <foreach collection="markedIds" item="marketId" open="("  separator="," close=")">
            #{marketId}
        </foreach>
        and smi.cur_time between #{startTime} and #{endTime}
        group by smi.cur_time
        order by time asc;
    </select>

3.4 web接口测试

  • postman:http://localhost:8091/api/quot/stock/tradeAmt

在这里插入图片描述

  • 页面效果如下

在这里插入图片描述

第二章 个股分时涨跌幅度统计功能

1、个股分时涨跌幅度统计功能分析

1.1 个股涨跌幅度功能原型

功能说明:统计当前时间下(精确到分钟),A股在各个涨跌区间股票的数量;

在这里插入图片描述

股票涨跌幅区间定义: “<-7%” 、 “-7~-5%”、 “-5~-3%” 、 “-3~0%” 、“0~3%” 、 “3~5%” 、 “5~7%” 、 “>7%”

1.2 个股分时涨跌幅度统计功能接口说明

功能描述:统计当前时间下(精确到分钟),A股在各个涨跌区间股票的数量;
服务路径:/api/quot/stock/updown
服务方法:GET
前端请求频率:每分钟
请求参数:无

注意事项:如果当前不在股票有效时间内,则以最近最新的一个有效股票交易日作为查询时间点展示;

响应数据格式:

{
    "code": 1,
    "data": {
        "time": "2021-12-31 14:58:00",
        "infos": [
            {
                "count": 17,
                "title": "-3~0%"
            },
            {
                "count": 2,
                "title": "-5~-3%"
            },
			//省略......
        ]
    }
}

1.3 个股涨跌幅度区间统计功能SQL分析

在这里插入图片描述

2、涨跌幅度统计SQL实现

-- 整体思路:先统计当前时间点下每支股票的涨幅和时间集合,然后再将结果子查询将涨幅值转换成涨幅区间名称,
-- 最后再根据涨幅区间分组统计每一组对应的数量即可
-- 步骤1:统计当前时间下,每只股票的涨幅值
select
	( sri.cur_price - sri.pre_close_price )/ sri.pre_close_price as rate 
from
	stock_rt_info as sri 
where
	sri.cur_time = '2022-01-06 09:55:00'
-- 步骤2:将步骤1的查询结果中数据转换为区间范围集合
select
		CASE
			WHEN tmp.rate > 0.07 THEN  '>7%'
			WHEN tmp.rate > 0.05  AND tmp.rate <= 0.07 THEN '5~7%'
			WHEN tmp.rate > 0.03  AND tmp.rate <= 0.05 THEN '3~5%'
			WHEN tmp.rate > 0     AND tmp.rate <= 0.03 THEN '0~3%'
			WHEN tmp.rate > -0.03 AND tmp.rate <= 0 THEN '-3~0%'
			WHEN tmp.rate > -0.05 AND tmp.rate <= -0.03 THEN '-5~-3%'
			WHEN tmp.rate > -0.07 AND tmp.rate <= -0.05 THEN '-7~-5%'
			ELSE '<-7%'
		END 'title'
from
	(
		select
			(sri.cur_price-sri.pre_close_price)/sri.pre_close_price as rate
		from stock_rt_info as sri
		where sri.cur_time='2022-01-06 09:55:00'
	)as tmp
-- 根据区间分组,统计各个区间数据量
select
	tmp2.title,
	count(*) as count
from
(select
	CASE
		WHEN tmp.rate > 0.07 THEN  '>7%'
		WHEN tmp.rate > 0.05 AND tmp.rate <= 0.07 THEN '5~7%'
		WHEN tmp.rate > 0.03 AND tmp.rate <= 0.05 THEN '3~5%'
		WHEN tmp.rate > 0 AND tmp.rate <= 0.03 THEN '0~3%'
		WHEN tmp.rate > -0.03 AND tmp.rate <= 0 THEN '-3~0%'
		WHEN tmp.rate > -0.05 AND tmp.rate <= -0.03 THEN '-5~-3%'
		WHEN tmp.rate > -0.07 AND tmp.rate <= -0.05 THEN '-7~-5%'
		ELSE '<-7%'
	END 'title'
from
(select
(sri.cur_price-sri.pre_close_price)/sri.pre_close_price as rate
from stock_rt_info as sri
where sri.cur_time='2022-01-06 09:55:00')
as tmp)
as tmp2 group by tmp2.title;

3、个股涨跌幅度区间统计功能实现

3.1 定义web访问接口

    /**
     * 查询当前时间下股票的涨跌幅度区间统计功能
     * 如果当前日期不在有效时间内,则以最近的一个股票交易时间作为查询点
     * @return
     */
    @GetMapping("/stock/updown")
    public R<Map> getStockUpDown(){
        return stockService.stockUpDownScopeCount();
    }

3.2 定义服务接口和实现

定义服务接口:

    /**
     * 查询当前时间下股票的涨跌幅度区间统计功能
     * 如果当前日期不在有效时间内,则以最近的一个股票交易时间作为查询点
     * @return
     */
     R<Map> stockUpDownScopeCount();

定义实现:

    /**
     * 功能描述:统计在当前时间下(精确到分钟),股票在各个涨跌区间的数量
     *  如果当前不在股票有效时间内,则以最近的一个有效股票交易时间作为查询时间点;
     * @return
     *  响应数据格式:
     *  {
     *     "code": 1,
     *     "data": {
     *         "time": "2021-12-31 14:58:00",
     *         "infos": [
     *             {
     *                 "count": 17,
     *                 "title": "-3~0%"
     *             },
     *             //...
     *             ]
     *     }
     */
    @Override
    public R<Map> stockUpDownScopeCount() {
        //1.获取股票最新一次交易的时间点
        Date curDate = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
        //mock data
        curDate=DateTime.parse("2022-01-06 09:55:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //2.查询股票信息
        List<Map> maps=stockRtInfoMapper.getStockUpDownSectionByTime(curDate);
        //3.组装数据
        HashMap<String, Object> mapInfo = new HashMap<>();
        //获取指定日期格式的字符串
        String curDateStr = new DateTime(curDate).toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"));
        mapInfo.put("time",curDateStr);
        mapInfo.put("infos",maps);
        //4.返回数据
        return R.ok(mapInfo);
    }

3.3 定义mapper接口方法与xml

mapper接口方法定义

    /**
     * 统计指定时间点下,各个涨跌区间内股票的个数
     * @param avlDate
     * @return
     */
    List<Map> stockUpDownScopeCount(@Param("avlDate") Date avlDate);

xml定义:

<select id="stockUpDownScopeCount" resultType="java.util.Map">
        select
            tmp2.title,
            count(*) as count
        from
            (select
                CASE
                WHEN tmp.rate > 0.07 THEN  '>7%'
                WHEN tmp.rate > 0.05 AND tmp.rate &lt;= 0.07 THEN '5~7%'
                WHEN tmp.rate > 0.03 AND tmp.rate &lt;= 0.05 THEN '3~5%'
                WHEN tmp.rate > 0 AND tmp.rate &lt;= 0.03 THEN '0~3%'
                WHEN tmp.rate > -0.03 AND tmp.rate &lt;= 0 THEN '-3~0%'
                WHEN tmp.rate > -0.05 AND tmp.rate &lt;= -0.03 THEN '-5~-3%'
                WHEN tmp.rate > -0.07 AND tmp.rate &lt;= -0.05 THEN '-7~-5%'
                ELSE '&lt;-7%'
                END 'title'
            from
              (select
              (sri.cur_price-sri.pre_close_price)/sri.pre_close_price as rate
              from stock_rt_info as sri
              where sri.cur_time=#{avlDate})
              as tmp)
            as tmp2 
      group by tmp2.title
</select>

大量的转义符书写非常麻烦?

如果在XML中SQL语句遇到大量特殊字符需要转义,比如:< 等,建议使用**<![CDATA[ sql 语句 ]]>**标记,这样特殊字符就不会被解析器解析,所以最终xml方式:

<select id="stockUpDownScopeCount" resultType="java.util.Map">
    <![CDATA[
        select
            tmp2.title,
            count(*) as count
        from
            (select
            CASE
            WHEN tmp.rate > 0.07 THEN  '>7%'
            WHEN tmp.rate > 0.05 AND tmp.rate <= 0.07 THEN '5~7%'
            WHEN tmp.rate > 0.03 AND tmp.rate <= 0.05 THEN '3~5%'
            WHEN tmp.rate > 0 AND tmp.rate <= 0.03 THEN '0~3%'
            WHEN tmp.rate > -0.03 AND tmp.rate <= 0 THEN '-3~0%'
            WHEN tmp.rate > -0.05 AND tmp.rate <= -0.03 THEN '-5~-3%'
            WHEN tmp.rate > -0.07 AND tmp.rate <= -0.05 THEN '-7~-5%'
            ELSE '<-7%'
            END 'title'
            from
            (select
            (sri.cur_price-sri.pre_close_price)/sri.pre_close_price as rate
            from stock_rt_info as sri
            where sri.cur_time=#{avlDate})
            as tmp)
            as tmp2 group by tmp2.title
    ]]>
</select>

3.4 功能测试

  • postman测试:http://localhost:8091/api/quot/stock/updown

在这里插入图片描述

  • 页面展示效果:

在这里插入图片描述

4、股涨幅幅度排序优化

4.1 分析问题

  • 前端查询的数据是无序展示的,涨幅区间应该从小到大顺序展示;
  • 当前涨幅区间下如果没有对应的股票,则区间标题不会被展示,我们需要对无数据的区间默认为0给前端显示;
  • 最终效果

在这里插入图片描述

4.2 实现思路分析

在这里插入图片描述

说明:

1.先顺序定义一个包含区间范围标题的有序集合;

2.遍历有序集合,然后从实际查询结果中找出各自的区间值,如果没有则以0补齐;

3.遍历过程形成新的集合,包可以顺序性保证数据有序且完整;

4.3 顺序定义股票涨幅范围集合

在application-stock.yml中顺序添加股票涨幅区间信息:

# 配置股票相关的参数
stock:
  upDownRange:
    - "<-7%"
    - "-7~-5%"
    - "-5~-3%"
    - "-3~0%"
    - "0~3%"
    - "3~5%"
    - "5~7%"
    - ">7%"

说明:yml中顺序定义区间范围值,这样加载到内存时也可保证其顺序性;

4.4 完善实体类

在stock_common工程下为StockInfoConfig类补齐配置:

@Data
@ConfigurationProperties(prefix = "stock")
public class StockInfoConfig {
    //a股大盘ID集合
    private List<String> inner;
    //外盘ID集合
    private List<String> outer;
    //股票区间
    private List<String> upDownRange;
}

4.5 完善过滤实现

    /**
     * 查询当前时间下股票的涨跌幅度区间统计功能
     * 如果当前日期不在有效时间内,则以最近的一个股票交易时间作为查询点
     * @return
     */
    @Override
    public R<Map> stockUpDownScopeCount() {
        //1.获取股票最新一次交易的时间点
        Date curDate = DateTimeUtil.getLastDate4Stock(DateTime.now()).toDate();
        //mock data
        curDate=DateTime.parse("2022-01-06 09:55:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //2.查询股票信息
        List<Map> maps=stockRtInfoMapper.getStockUpDownSectionByTime(curDate);
        //2.1 获取有序的标题集合
        List<String> orderSections = stockInfoConfig.getUpDownRange();
        //思路:利用List集合的属性,然后顺序编译,找出每个标题对应的map,然后维护到一个新的List集合下即可
//        List<Map> orderMaps =new ArrayList<>();
//        for (String title : orderSections) {
//            Map map=null;
//            for (Map m : maps) {
//                if (m.containsValue(title)) {
//                    map=m;
//                    break;
//                }
//            }
//            if (map==null) {
//                map=new HashMap();
//                map.put("count",0);
//                map.put("title",title);
//            }
//            orderMaps.add(map);
//        }
        //方式2:使用lambda表达式指定
        List<Map> orderMaps  =  orderSections.stream().map(title->{
            Map mp=null;
            Optional<Map> op = maps.stream().filter(m -> m.containsValue(title)).findFirst();
            //判断是否存在符合过滤条件的元素
            if (op.isPresent()) {
                mp=op.get();
            }else{
                mp=new HashMap();
                mp.put("count",0);
                mp.put("title",title);
            }
            return mp;
        }).collect(Collectors.toList());
        //3.组装数据
        HashMap<String, Object> mapInfo = new HashMap<>();
        //获取指定日期格式的字符串
        String curDateStr = new DateTime(curDate).toString(DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss"));
        mapInfo.put("time",curDateStr);
        mapInfo.put("infos",orderMaps);
        //4.返回数据
        return R.ok(mapInfo);
    }

第三章 股票K线图功能

1、个股分时图行情功能

1.1 个股分时K线行情功能分析

1.1.1 个股分时线行情原型效果

在这里插入图片描述

在这里插入图片描述

1.1.2 个股分时K线行情接口说明

功能描述:查询个股的分时行情数据,也就是统计指定股票T日每分钟的交易数据;
服务路径:/api/quot/stock/screen/time-sharing
服务方法:GET
前端请求频率:每分钟请求

请求参数:code

参数说明参数名称是否必须数据类型备注
股票编码codetruestring股票编码

返回数据格式:

{
    "code": 1,
    "data": [
        {
            "date": "2021-12-31 09:25",//当前时间,精确到分钟
            "tradeAmt": 63263,//当前交易量
            "code": "000021",//股票编码
            "lowPrice": 15.85,//最低价格
            "preClosePrice": 15.85,//前收盘价格
            "name": "深科技",//股票名称
            "highPrice": 15.85,//最高价格
            "openPrice": 15.85,//开盘价
            "tradeVol": 1002718.55,//交易金额
            "tradePrice": 15.85//当前价格(最新价格)
        },
		//......
          ]
}
1.1.3 查询封装

在stock_common工程下添加实体类:

/**
 * @author by itheima
 * @Date 2022/2/28
 * @Description 个股分时数据封装
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Stock4MinuteDomain {
    /**
     * 日期,eg:202201280809
     */
   @JsonFormat(pattern = "yyyy-MM-dd HH:mm",timezone = "Asia/Shanghai")
   private Date date;
    /**
     * 交易量
     */
   private Long tradeAmt;
    /**
     * 股票编码
     */
   private String code;
    /**
     * 最低价
     */
   private BigDecimal lowPrice;
    /**
     * 前收盘价
     */
   private BigDecimal preClosePrice;
    /**
     * 股票名称
     */
   private String name;
    /**
     * 最高价
     */
   private BigDecimal highPrice;
    /**
     * 开盘价
     */
   private BigDecimal openPrice;

    /**
     * 当前交易总金额
     */
   private BigDecimal tradeVol;
    /**
     * 当前价格
     */
   private BigDecimal tradePrice;
}

1.2 个股分时K线行情功能SQL分析

-- 分析:查询个股分时K线图,说白了就是查询指定股票在当前交易日产生的流水数据报表展示
-- 综合条件:1.股票ID 2.股票开盘时间 3.当前时间点
select
	sri.cur_time     as date,
	sri.trade_amount as tradeAmt,
	sri.stock_code as code,
	sri.min_price lowPrice,
	sri.pre_close_price as preClosePrice,
	sri.stock_name as name,
	sri.max_price as highPrice,
	sri.open_price as openPrice,
	sri.trade_volume as tradeVol,
	sri.cur_price as tradePrice
from stock_rt_info as sri
where	sri.stock_code='600021'
and sri.cur_time between '2021-12-30 09:30:00' and '2021-12-30 14:30:00';

1.3 个股分时K线行情功能实现

1.3.1 定义web服务接口
    /**
     * 功能描述:查询单个个股的分时行情数据,也就是统计指定股票T日每分钟的交易数据;
     *         如果当前日期不在有效时间内,则以最近的一个股票交易时间作为查询时间点
     * @param code 股票编码
     * @return
     */
    @GetMapping("/stock/screen/time-sharing")
    public R<List<Stock4MinuteDomain>> stockScreenTimeSharing(String code){
        return stockService.stockScreenTimeSharing(code);
    }
1.3.2 定义服务接口方法与实现

服务接口方法:

    /**
     * 功能描述:查询单个个股的分时行情数据,也就是统计指定股票T日每分钟的交易数据;
     *         如果当前日期不在有效时间内,则以最近的一个股票交易时间作为查询时间点
     * @param code 股票编码
     * @return
     */
    R<List<Stock4MinuteDomain>> stockScreenTimeSharing(String code);

接口实现:

    /**
     * 功能描述:查询单个个股的分时行情数据,也就是统计指定股票T日每分钟的交易数据;
     *         如果当前日期不在有效时间内,则以最近的一个股票交易时间作为查询时间点
     * @param code 股票编码
     * @return
     */
    @Override
    public R<List<Stock4MinuteDomain>> stockScreenTimeSharing(String code) {
        //1.获取最近最新的交易时间点和对应的开盘日期
        //1.1 获取最近有效时间点
        DateTime lastDate4Stock = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date endTime = lastDate4Stock.toDate();
        //TODO mockdata
        endTime=DateTime.parse("2021-12-30 14:47:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();

        //1.2 获取最近有效时间点对应的开盘日期
        DateTime openDateTime = DateTimeUtil.getOpenDate(lastDate4Stock);
        Date startTime = openDateTime.toDate();
        //TODO MOCK DATA
        startTime=DateTime.parse("2021-12-30 09:30:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //2.根据股票code和日期范围查询
        List<Stock4MinuteDomain> list=stockRtInfoMapper.getStockInfoByCodeAndDate(code,startTime,endTime);
        //判断非空处理
        if (CollectionUtils.isEmpty(list)) {
            list=new ArrayList<>();
        }
        //3.返回响应数据
        return R.ok(list);
    }
1.3.3 定义mapper接口和xml

mapper接口方法:

    /**
     * 根据时间范围查询指定股票的交易流水
     * @param stockCode 股票code
     * @param startTime 起始时间
     * @param endTime 终止时间
     * @return
     */
    List<Stock4MinuteDomain> getStockInfoByCodeAndDate(@Param("stockCode") String stockCode,
                                                       @Param("startTime") Date startTime,
                                                       @Param("endTime") Date endTime);

xml sql绑定:

    <select id="getStockInfoByCodeAndDate" resultType="com.itheima.stock.pojo.domain.Stock4MinuteDomain">
        select
            sri.cur_time    as date,
            sri.trade_amount as tradeAmt,
            sri.stock_code as code,
            sri.min_price as lowPrice,
            sri.pre_close_price as preClosePrice,
            sri.stock_name as name,
            sri.max_price as highPrice,
            sri.open_price as openPrice,
            sri.trade_volume as tradeVol,
            sri.cur_price as tradePrice
        from stock_rt_info as sri
        where sri.stock_code=#{stockCode}
          and sri.cur_time between #{startTime} and #{endTime}
    </select>
1.3.4 web接口测试
  • postman测试:http://localhost:8091/api/quot/stock/screen/time-sharing?code=600019

在这里插入图片描述

  • 页面效果

在这里插入图片描述

在这里插入图片描述

2、个股日K线详情功能

2.1 个股日K线详情功能分析

2.1.1 个股日K线详情功能原型

在这里插入图片描述

说明:

1.日K线就是将股票交易流水按天分组,然后统计出每天的交易数据,内容包含:日期、股票编码、名称、最高价、最低价、开盘价、收盘价、前收盘价、交易量;

2.需要注意的是这里的收盘价就是指每天最大交易时间点下对应的价格;

2.1.2 个股日K线详情功能接口说明

功能描述:查询指定股票每天产生的数据,组装成日K线数据;

​ 如果当大盘尚未收盘,则以最新的交易价格作为当天的收盘价格;

服务路径:/api/quot/stock/screen/dkline
服务方法:GET
前端请求频率:每分钟

请求参数:code

参数说明参数名称是否必须数据类型备注
股票编码codetruestring股票编码

响应数据结构:

{
    "code": 1,
    "data": [
        {
            "date": "2021-12-20 10:20",//日期
            "tradeAmt": 28284252,//交易量(指收盘时的交易量,如果当天未收盘,则显示最新数据)
            "code": "000021",//股票编码
            "lowPrice": 16,//最低价格(指收盘时记录的最低价,如果当天未收盘,则显示最新数据)
            "name": "深科技",//名称
            "highPrice": 16.83,//最高价(指收盘时记录的最高价,如果当天未收盘,则显示最新数据)
            "openPrice": 16.8,//开盘价
            "tradeVol": 459088567.58,//交易金额(指收盘时记录交易量,如果当天未收盘,则显示最新数据)
            "closePrice": 16.81//当前收盘价(指收盘时的价格,如果当天未收盘,则显示最新cur_price)
            "preClosePrice": 16.81//前收盘价
        },
        //......
    ]
}
2.1.3 封装查询数据

在stock_common工程添加实体类:


/**
 * @author by itheima
 * @Date 2022/2/28
 * @Description 个股日K数据封装
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Stock4EvrDayDomain {
    /**
     * 日期,eg:202201280809
     */
   @JsonFormat(pattern = "yyyy-MM-dd HH:mm",timezone = "Asia/Shanghai")
   private Date date;
    /**
     * 交易量
     */
   private Long tradeAmt;
    /**
     * 股票编码
     */
   private String code;
    /**
     * 最低价
     */
   private BigDecimal lowPrice;
    /**
     * 股票名称
     */
    private String name;
    /**
     * 最高价
     */
    private BigDecimal highPrice;
    /**
     * 开盘价
     */
    private BigDecimal openPrice;
    /**
     * 当前交易总金额
     */
    private BigDecimal tradeVol;
    /**
     * 当前收盘价格指收盘时的价格,如果当天未收盘,则显示最新cur_price)
     */
    private BigDecimal closePrice;
    /**
     * 前收盘价
     */
   private BigDecimal preClosePrice;
}

2.2 个股日K线详情功能SQL分析

2.2.1 核心思路
  • SQL查询要划定一个默认的日期范围,这样可避免大数据量下全表查询而导致慢查询的问题;
  • 在指定的日期范围内以天分组统计出每天日期的最大值(收盘时间);
  • 根据获取的最大日期组,使用in进行条件查询,进而获取日K线相关的数据;

总之,股票每天最后一条数据就包含了当天最高价、最低价等相关信息了。

2.2.2 SQL实现
-- 说明:因为在股票流水中,开盘价、最高价、最低价、当前价等信息在每条记录中都会记录,所以我们更加关注的是每天的收盘价格,业务要求如果当前没有收盘,则以最新价格作为收盘价,所以该业务就可以转化成查询每天最大交易时间对应的信息;
-- 步骤1:查询指定股票在指定日期范围内每天的最大时间,说白了就是以天分组,求每天最大时间
select
	max( sri.cur_time ) as closeDate 
from
	stock_rt_info as sri 
where
	sri.stock_code ='600021' 
	and sri.cur_time between '2022-01-01 09:30:00' and '2022-01-06 14:25:00' 
group by
	date_format( sri.cur_time, '%Y%m%d' )
-- 步骤2:以步骤1查询结果作为条件,同统计指定时间点下,股票的数据信息
select
	sri2.cur_time as date,
	sri2.trade_amount as tradeAmt,
	sri2.stock_code as code,
	sri2.min_price as lowPrice,
	sri2.stock_name as name,
	sri2.max_price as highPrice,
	sri2.open_price as openPrice,
	sri2.trade_volume as tradeVol,
	sri2.cur_price as closePrice,
	sri2.pre_close_price as preClosePrice
from
	stock_rt_info as sri2
where sri2.stock_code='600021'  and sri2.cur_time in (
  select
	max( sri.cur_time ) as closeDate 
  from
	stock_rt_info as sri 
  where
	sri.stock_code ='600021' 
	and sri.cur_time between '2022-01-01 09:30:00' and '2022-01-06 14:25:00' 
  group by
	date_format( sri.cur_time, '%Y%m%d' )
  )	
  order by sri2.cur_time;

2.3 个股日K线详情功能实现

2.3.1 定义web接口方法

    /**
     * 单个个股日K 数据查询 ,可以根据时间区间查询数日的K线数据
     * @param stockCode 股票编码
     */
    @RequestMapping("/stock/screen/dkline")
    public R<List<Map>> getDayKLinData(@RequestParam("code") String stockCode){
        return stockService.stockCreenDkLine(stockCode);
    }
2.3.2 定义服务方法和实现

服务接口方法:

    /**
     * 单个个股日K 数据查询 ,可以根据时间区间查询数日的K线数据
     * @param stockCode 股票编码
     */
    R<List<Stock4EvrDayDomain>> stockCreenDkLine(String code);

服务接口实现方法:

    /**
     * 功能描述:单个个股日K数据查询 ,可以根据时间区间查询数日的K线数据
     * 		默认查询历史20天的数据;
     * @param code 股票编码
     * @return
     */
    @Override
    public R<List<Stock4EvrDayDomain>> stockCreenDkLine(String code) {
        //1.获取查询的日期范围
        //1.1 获取截止时间
        DateTime endDateTime = DateTimeUtil.getLastDate4Stock(DateTime.now());
        Date endTime = endDateTime.toDate();
        //TODO MOCKDATA
        endTime=DateTime.parse("2022-01-07 15:00:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //1.2 获取开始时间
        DateTime startDateTime = endDateTime.minusDays(10);
        Date startTime = startDateTime.toDate();
        //TODO MOCKDATA
        startTime=DateTime.parse("2022-01-01 09:30:00", DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")).toDate();
        //2.调用mapper接口获取查询的集合信息-方案1
        List<Stock4EvrDayDomain> data= stockRtInfoMapper.getStockInfo4EvrDay(code,startTime,endTime);
        //3.组装数据,响应
        return R.ok(data);
    }
2.3.3 定义mapper接口方法与xml

在StockRtInfoMapper定义接口方法:

    /**
     * 查询指定日期范围内指定股票每天的交易数据
     * @param stockCode 股票code
     * @param startTime 起始时间
     * @param endTime 终止时间
     * @return
     */
    List<Stock4EvrDayDomain> getStockInfo4EvrDay(@Param("stockCode") String stockCode,
                                                 @Param("startTime") Date startTime,
                                                 @Param("endTime") Date endTime);

在StockRtInfoMapper.xml定义sql:

    <select id="getStockInfo4EvrDay" resultType="com.itheima.stock.pojo.domain.Stock4EvrDayDomain">
        select
             date_format(sri2.cur_time,'%Y%m%d') as date,
             sri2.trade_amount as tradeAmt,
             sri2.stock_code as code,
             sri2.min_price as lowPrice,
             sri2.stock_name as name,
             sri2.max_price as highPrice,
             sri2.open_price as openPrice,
             sri2.trade_volume as tradeVol,
             sri2.cur_price as closePrice,
             sri2.pre_close_price as preClosePrice
        from stock_rt_info as sri2
        where sri2.cur_time in (select
            max(sri.cur_time) as max_time
            from stock_rt_info as sri
            where sri.stock_code=#{stockCode}
          and sri.cur_time between  #{startTime}   and	#{endTime}
            group by date_format(sri.cur_time,'%Y%m%d'))
          and sri2.stock_code=#{stockCode}
        order by sri2.cur_time
    </select>
2.3.4 web接口测试
  • postman测试:http://localhost:8091/api/quot/stock/screen/dkline?code=600019

在这里插入图片描述

  • 页面效果

在这里插入图片描述

在这里插入图片描述

3、日K线功能拆分实现[作业]

3.1 拆分目标

​ 练习复杂sql拆分的实现思路;

3.2 日K线功能拆分

  • 第一步:查询指定股票在指定日期范围内的每天的最大时间;
  • 第二步:将第一步的结果作为条件查询对应的数据;
    • 定义2个Mapper方法。落后逻辑层逐次调用方法,最终获取日K线的数据;

price as lowPrice,
sri2.stock_name as name,
sri2.max_price as highPrice,
sri2.open_price as openPrice,
sri2.trade_volume as tradeVol,
sri2.cur_price as closePrice,
sri2.pre_close_price as preClosePrice
from stock_rt_info as sri2
where sri2.cur_time in (select
max(sri.cur_time) as max_time
from stock_rt_info as sri
where sri.stock_code=#{stockCode}
and sri.cur_time between #{startTime} and #{endTime}
group by date_format(sri.cur_time,‘%Y%m%d’))
and sri2.stock_code=#{stockCode}
order by sri2.cur_time


#### 2.3.4 web接口测试

- postman测试:http://localhost:8091/api/quot/stock/screen/dkline?code=600019

[外链图片转存中...(img-JhgWKPYb-1708244780206)]

- 页面效果

[外链图片转存中...(img-2XkQlb4D-1708244780208)]

[外链图片转存中...(img-Fn9jKgw2-1708244780211)]

## 3、日K线功能拆分实现[作业]

### 3.1 拆分目标

​	练习复杂sql拆分的实现思路;

### 3.2 日K线功能拆分

- 第一步:查询指定股票在指定日期范围内的每天的最大时间;
- 第二步:将第一步的结果作为条件查询对应的数据;
  - 定义2个Mapper方法。落后逻辑层逐次调用方法,最终获取日K线的数据;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1455621.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2.18作业

作业要求&#xff1a;使用fgets统计给定文件的行数 程序代码&#xff1a; #include<stdlib.h> #include<string.h> #include<stdio.h>int main(int argc, const char *argv[]) {if(argc!2){printf("input file error\n");printf("usage:./a…

爬虫之正则表达式

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 概念&#xff1a; 正则表达式(regular expression)描述了一种字符串匹配的模式&#xff08;pattern&#xff09;&#xff0c;正则匹配是一个模糊的匹配(不是精确匹配) 如下四个方法经常使用&#xff1a; match()search()f…

数据分析师SQL面试准备(part1)

1. SQL 万能框架 2. SQL的书写顺序&#xff0c;跟程序真的执行顺序不同 3. 4. 5. 6. 7. case when utilization 8. 9. 10. 11.

【RL】Monte Carlo Learning(蒙特卡洛学习)

Lecture 5: Monte Carlo Learning The simplest MC-based RL algorithm: MC Basic 理解MC basic算法的关键是理解如何将policy iteration算法迁移到model-free的条件下。 Policy iteration算法在每次迭代过程中有两步&#xff1a; { Policy evaluation: v π k r π k γ…

【HarmonyOS】鸿蒙开发之Button组件——第3.4章

按钮类型 Capsule&#xff08;默认值&#xff09;&#xff1a;胶囊类型 Button("默认样式").height(40)//高度.width(90)//宽度.backgroundColor(#aabbcc)//背景颜色运行结果: Normal&#xff1a;矩形按钮&#xff0c;无圆角 Button({type:ButtonType.Normal}){Te…

防御保护---防火墙综合实验

拓扑图 实验要求 办公区的设备可以通过电信链路和移动链路上网分公司设备可以通过总公司的移动链路和电信链路访问到DMZ区域的HTTP服务器分公司内部的客户端可以通过公网地址访问到内部的服务器FW1和FW2组成主备模式双击热备办公区上网用户限制流量不超过60M&#xff0c;其中销…

人工智能技术应用笔记(二):OpenAI SORA文生视频模型技术报告全文中英对照 (GPT4翻译+人工润色)

目录 Video generation models as world simulators&#xff08;视频生成模型作为世界模拟器&#xff09; Turning visual data into patches &#xff08;将视觉数据转换为图像块&#xff09; Video compression network &#xff08;视频压缩网络&#xff09; Spacetim…

Linux系统中 uboot、内核与文件系统之间的关系

前言&#xff1a; 最近正在学习Linux&#xff0c;总结了一下Linux系统中 uboot、内核与文件系统之间的关系 Linux初学者首先要搞清楚的三个文件: 引导程序(bootoader):uboot.bin/uboot.imx Linux内核镜像: zlmage 文件系统镜像:system.img/rootfs.tar.ba2 初期很多工作都是围…

Eclipse - Format Comment

Eclipse - Format & Comment 1. Correct Indentation2. Format3. Toggle Comment4. Add Block Comment5. Remove Block CommentReferences 1. Correct Indentation Ctrl A: 选择全部代码 Ctrl I: 校正缩进 or right-click -> Source -> Correct Indentation 2. F…

OLMo论文里的模型结构的小白解析

模型参数量 以7B为例&#xff0c;隐藏层为4086&#xff0c;attention heads为32 训练的token量为2.46T 训练策略 超参数 在我们的硬件上优化训练吞吐量&#xff0c;同时最小化损失峰值和缓慢发散的风险来选择超参数 损失峰值&#xff1a;在机器学习中&#xff0c;"损失峰…

RabbitMQ保证消息的可靠性

1. 问题引入 消息从发送&#xff0c;到消费者接收&#xff0c;会经理多个过程&#xff1a; 其中的每一步都可能导致消息丢失&#xff0c;常见的丢失原因包括&#xff1a; 发送时丢失&#xff1a; 生产者发送的消息未送达exchange消息到达exchange后未到达queue MQ宕机&…

【MATLAB GUI】 1. 普通按钮、静态文本和可编辑文本

看B站up主freexyn的freexyn编程实例视频教程系列36Matlab GUI的学习笔记 文章目录 初步认识普通按钮静态文本和可编辑文本设计一个简易计算机 初步认识普通按钮 任务要求&#xff1a;点击一次“100”按钮&#xff0c;按钮上的文字值就递增1&#xff1b;点击“close”按钮&…

边坡位移监测设备:守护工程安全的前沿科技

随着现代工程建设的飞速发展&#xff0c;边坡位移监测作为预防山体滑坡、泥石流等自然灾害的重要手段&#xff0c;日益受到人们的关注。边坡位移监测设备作为这一领域的关键技术&#xff0c;以其高精度、实时监测的特点&#xff0c;成为守护工程安全的重要武器。 一、边坡位移…

20-k8s中pod的调度-nodeSelector节点选择器

一、概念 我们先创建一个普通的deploy资源&#xff0c;设置为10个副本 [rootk8s231 dns]# cat deploy.yaml apiVersion: apps/v1 kind: Deployment metadata: name: dm01 spec: replicas: 10 selector: matchLabels: k8s: k8s template: metadata: …

零基础搭建 Kubernetes 集群

零基础搭建 Kubernetes 集群 1、简介 在数字化时代&#xff0c;容器技术已经变成了软件开发和部署的标准&#xff0c;而在众多容器管理工具中&#xff0c;Kubernetes&#xff08;简称为 K8s&#xff09;凭借其高效的资源管理、弹性伸缩和自我修复的能力&#xff0c;成为了行业…

第一个 Angular 项目 - 动态页面

第一个 Angular 项目 - 动态页面 使用的所有技巧都在下面的笔记里&#xff1a; [Angular 基础] - 数据绑定(databinding) [Angular 基础] - 指令(directives) 以上为静态页面&#xff0c;即不涉及到跨组件交流的内容 以下涉及到组件内的沟通&#xff0c;从这开始数据就“活”…

双向bfs P1032 字串变换

传送门https://www.luogu.com.cn/problem/P1032 找一个最短方案&#xff0c;考虑用bfs&#xff08;没试过单向&#xff0c;但是系数很大&#xff09; 更详细的解答 下面是代码理解&#xff08;注释版&#xff09; // Problem: // P1032 [NOIP2002 提高组] 字串变换 // …

分布式学习笔记

1. CAP理论 Consistency&#xff08;一致性&#xff09;&#xff1a;用户访问分布式系统中的任意节点&#xff0c;得到的数据必须一致。 Availability&#xff08;可用性&#xff09;&#xff1a;用户访问集群中的任意健康节点&#xff0c;必须得到相应&#xff0c;而不是超时…

OpenAI划时代大模型——文本生成视频模型Sora作品欣赏(一)

Sora介绍 Sora是一个能以文本描述生成视频的人工智能模型&#xff0c;由美国人工智能研究机构OpenAI开发。 Sora这一名称源于日文“空”&#xff08;そら sora&#xff09;&#xff0c;即天空之意&#xff0c;以示其无限的创造潜力。其背后的技术是在OpenAI的文本到图像生成模…

svg图片构造QGraphicsSvgItem对象耗时很长的问题解决

目录 1. 问题的提出 2. 问题解决 1. 问题的提出 今天通过一张像素为141 * 214&#xff0c;大小为426KB的svg格式的图片构造QGraphicsSvgItem对象&#xff0c;再通过Qt的Graphics View Framework框架&#xff0c;将QGraphicsSvgItem对象显示到场景视图上&#xff0c;代码如下&…