# 股票动量系统分析文档 ## 1. 系统概述 ### 1.1 系统定位 本动量系统是基于 RuoYi-Vue 框架开发的股票分析模块,用于识别市场中的强势板块和个股,通过量化计算生成动量排名,辅助投资决策。 ### 1.2 核心功能 - **动量个股筛选**:基于多周期涨跌幅筛选强势个股 - **板块动量计算**:计算各行业板块的动量值并排名 - **趋势跟踪**:跟踪板块动量值和排名的变化 - **多周期分析**:支持 1/3/5/10/15/20/30/60 日不同周期的动量分析 --- ## 2. 核心数据表结构 ### 2.1 股票交易数据表 (stocks) | 字段 | 类型 | 说明 | |------|------|------| | id | bigint | 主键 | | code | varchar(45) | 股票代码 | | trade_day | date | 交易日期 | | open | decimal | 开盘价 | | close | decimal | 收盘价 | | high | decimal | 最高价 | | low | decimal | 最低价 | | differrange | decimal | 当日涨跌幅(%) | | differrange3/5/10/15/20/30/60 | decimal | 多周期涨跌幅 | | islimit | varchar | 是否涨停 | | isdrop | varchar | 是否跌停 | ### 2.2 动量个股表 (stocks_in_trend) | 字段 | 类型 | 说明 | |------|------|------| | id | bigint | 主键 | | code | varchar(45) | 股票代码 | | trade_day | date | 交易日期 | | sort | int | 排名 | | type | varchar(45) | 动量数据类型(10日/20日等) | ### 2.3 板块动量结果表 (trends) | 字段 | 类型 | 说明 | |------|------|------| | id | bigint | 主键 | | trade_day | date | 交易日期 | | blemind2 | varchar(50) | 所属东财行业指数2级 | | stocks_count | decimal | 动量个股数量 | | trend_value | decimal | 动量值 | | trend_value_change | decimal | 动量值变化 | | sort | int | 板块排名 | | sort_change | int | 板块排名变化 | | type | varchar(45) | 动量数据类型 | ### 2.4 辅助数据表 (stocks_tmp) | 字段 | 类型 | 说明 | |------|------|------| | id | bigint | 主键 | | code | varchar(45) | 股票代码 | | trade_day | date | 交易日期 | | differrange3/5/15/30 | decimal | 3/5/15/30日区间涨跌幅 | --- ## 3. 动量计算规则详解 ### 3.1 系统处理流程 ``` ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 导入日线数据 │ -> │ 计算多周期 │ -> │ 筛选动量个股 │ -> │ 计算板块动量 │ │ (stocks) │ │ 涨跌幅 │ │(stocks_in_trend)│ │ (trends) │ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ ``` ### 3.2 动量个股筛选规则 #### 3.2.1 入选条件 **代码位置**: `StocksController.java` (约第 1369 行) ```java if(stock.getTradeDays() >= 120 && stock.getAgenciesHold().compareTo(new BigDecimal(2)) == 1) { // 入选动量个股 } ``` | 条件 | 阈值 | 说明 | |------|------|------| | 上市天数 | ≥ 120 天 | 排除新股,确保有足够历史数据 | | 机构持股比例 | > 2% | 筛选机构关注的优质股票 | | 排名范围 | 前 600 名 | 只保留各周期涨跌幅排名靠前的股票 | #### 3.2.2 筛选逻辑 1. 按指定周期涨跌幅降序排列所有股票 2. 遍历排名列表,检查每只股票的上市天数和机构持股比例 3. 满足条件的股票插入 `stocks_in_trend` 表 4. 最多取前 600 只符合条件的股票 ### 3.3 板块动量值计算公式 #### 3.3.1 核心公式 **代码位置**: `StocksController.java` (约第 1403 行) ```java BigDecimal c = new BigDecimal(stock.getBlemindCount()); // 板块内动量个股数量 BigDecimal allStocks = new BigDecimal(blemindCoundMap.get(stock.getBlemind2())); // 板块总个股数 BigDecimal result = c.multiply(c).divide(allStocks, 2, BigDecimal.ROUND_HALF_UP); ``` **数学表达式**: $$ \text{板块动量值} = \frac{( ext{板块内动量个股数})^2}{ ext{板块总个股数}} $$ #### 3.3.2 公式解读 | 要素 | 说明 | |------|------| | **平方加权** | 动量个股数量越多,动量值呈指数级增长,突出强势板块 | | **归一化处理** | 除以板块总个股数,消除不同规模板块之间的差异 | | **精度控制** | 结果保留 2 位小数,使用四舍五入 | #### 3.3.3 计算示例 假设某日数据: | 板块 | 动量个股数 | 板块总股数 | 动量值计算 | 动量值 | |------|-----------|-----------|-----------|--------| | 非银行金融 | 29 | 75 | $29^2 / 75 = 841 / 75$ | 11.21 | | 食品 | 23 | 75 | $23^2 / 75 = 529 / 75$ | 7.05 | | 房地产开发 | 27 | 116 | $27^2 / 116 = 729 / 116$ | 6.28 | | 计算机软件 | 32 | 185 | $32^2 / 185 = 1024 / 185$ | 5.54 | --- ## 4. 多周期动量类型 ### 4.1 支持的周期类型 | 类型 | 排序字段 | 适用场景 | |------|----------|----------| | 1日 | `differrange` | 当日强势股,捕捉日内热点 | | 3日 | `differrange3` | 超短期动量,快速轮动策略 | | 5日 | `differrange5` | 短期动量,一周趋势跟踪 | | 10日 | `differrange10` | 中期动量,两周趋势跟踪 | | 15日 | `differrange15` | 中期动量,半月趋势判断 | | 20日 | `differrange20` | 中长期动量,月度趋势(默认) | | 30日 | `differrange30` | 长期动量,月度以上趋势 | | 60日 | `differrange60` | 超长期动量,季度趋势 | ### 4.2 多周期涨跌幅计算 **代码位置**: `StocksController.java` (约第 969-1038 行) 涨跌幅计算公式: $$ \text{N日涨跌幅} = \frac{\text{当日收盘价} - \text{N日前收盘价}}{\text{N日前收盘价}} \times 100\% $$ 计算逻辑: 1. 获取当日股票收盘价 2. 查询 N 个交易日前的收盘价(基于 `trade_dates` 表) 3. 计算涨跌幅并存储到 `stocks_tmp` 表 --- ## 5. 排名与变化计算 ### 5.1 板块排名规则 **代码位置**: `StocksController.java` (约第 1410-1421 行) 按动量值降序排列,动量值越大排名越靠前: ```java Collections.sort(trendsList, new Comparator() { @Override public int compare(Trends s1, Trends s2) { if(s1.getTrendValue().compareTo(s2.getTrendValue()) == 1) return -1; // 动量值大的排前面 else if(s1.getTrendValue().compareTo(s2.getTrendValue()) == -1) return 1; else return 0; } }); ``` ### 5.2 排名变化计算 **代码位置**: `StocksController.java` (约第 1434-1450 行) ```java if(lastTrendsMap.containsKey(trend.getBlemind2())) { trend.setSort(sort); trend.setSortChange(lastTrendsMap.get(trend.getBlemind2()).getSort() - sort); trend.setTrendValueChange(lastTrendsMap.get(trend.getBlemind2()).getTrendValue().subtract(trend.getTrendValue())); } else { trend.setSort(sort); trend.setSortChange(blemindCoundMap.size() - sort); trend.setTrendValueChange(trend.getTrendValue()); } ``` | 指标 | 计算方式 | 说明 | |------|----------|------| | 排名变化 | 昨日排名 - 今日排名 | 正数表示排名上升,负数表示下降 | | 动量值变化 | 今日动量值 - 昨日动量值 | 正数表示动量增强,负数表示减弱 | ### 5.3 新上榜板块处理 对于昨日未上榜的板块: - 排名变化 = 板块总数 - 当前排名 - 动量值变化 = 当前动量值(视为从无到有) --- ## 6. 最大回撤计算 ### 6.1 计算逻辑 **代码位置**: `TrendsController.java` (约第 161-188 行) 计算动量个股相对于近期高点的回撤幅度: ```java BigDecimal current = stocksInTrend1.getClose(); // 当前收盘价 BigDecimal high = stocks1.getClose(); // N日最高收盘价 BigDecimal diff = current.subtract(high); BigDecimal hresult = diff.divide(high, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100")); ``` ### 6.2 回撤公式 $$ \text{回撤} = \frac{\text{当前收盘价} - \text{N日最高收盘价}}{\text{N日最高收盘价}} \times 100\% $$ ### 6.3 用途 - 评估动量个股的获利回吐压力 - 识别可能的 trend reversal 信号 - 辅助判断买入/卖出时机 --- ## 7. 实际数据示例 ### 7.1 动量个股表示例 (stocks_in_trend) | id | code | trade_day | sort | type | |----|------|-----------|------|------| | 1 | 600340.SH | 2021-01-04 | 1 | 20 | | 2 | 002607.SZ | 2021-01-04 | 2 | 20 | | 3 | 600260.SH | 2021-01-04 | 3 | 20 | | ... | ... | ... | ... | ... | | 100 | 601375.SH | 2021-01-04 | 100 | 20 | ### 7.2 板块动量结果示例 (trends) | trade_day | blemind2 | stocks_count | trend_value | sort | sort_change | type | |-----------|----------|--------------|-------------|------|-------------|------| | 2021-01-04 | 非银行金融 | 29 | 11.2133 | 1 | 0 | 20 | | 2021-01-04 | 食品 | 23 | 7.0533 | 2 | 0 | 20 | | 2021-01-04 | 房地产开发 | 27 | 6.2845 | 3 | 0 | 20 | | 2021-01-04 | 计算机软件 | 32 | 5.5351 | 4 | 0 | 20 | | 2021-01-05 | 非银行金融 | 28 | 10.4533 | 2 | -1 | 20 | | 2021-01-05 | 食品 | 30 | 12.0000 | 1 | 1 | 20 | --- ## 8. API 接口说明 ### 8.1 动量个股查询 ``` GET /stocksystem/trendStocks/list 参数: - tradeDay: 交易日期 - type: 动量类型 (1/3/5/10/15/20/30/60) - blemind2: 行业板块(可选) ``` ### 8.2 板块动量查询 ``` GET /stocksystem/trends/list 参数: - tradeDay: 交易日期 - type: 动量类型 ``` ### 8.3 行业趋势数据 ``` GET /stocksystem/trends/listSection 参数: - tradeDay: 交易日期 - type: 动量类型 ``` ### 8.4 数据分析触发 ``` POST /stocksystem/stocks/analysis 参数: - tradeDay: 交易日期 说明: 触发指定日期的动量计算流程 ``` --- ## 9. 系统特点与注意事项 ### 9.1 系统特点 1. **多周期支持**: 支持 8 种不同时间周期的动量分析 2. **机构视角**: 通过机构持股比例过滤,聚焦机构关注的股票 3. **归一化计算**: 动量值公式考虑了板块规模差异 4. **变化跟踪**: 自动计算排名和动量值的变化趋势 5. **缓存机制**: 使用 Redis 缓存热点数据,提高查询性能 ### 9.2 使用注意事项 1. **数据依赖**: 系统依赖完整的交易日历数据 (`trade_dates`) 2. **基础数据**: 需要完整的股票基础信息 (`stock_basis`) 3. **计算时机**: 建议在每日收盘后 18:00 后执行分析 4. **首次运行**: 首次导入历史数据时需要批量计算多周期涨跌幅 --- ## 10. 核心代码文件清单 | 文件路径 | 说明 | |----------|------| | `stock-system/src/main/java/com/ruoyi/stocksystem/controller/StocksController.java` | 股票数据控制器,包含动量计算核心逻辑 | | `stock-system/src/main/java/com/ruoyi/stocksystem/controller/TrendsController.java` | 动量结果控制器,包含回撤计算 | | `stock-system/src/main/resources/mapper/stocksystem/StocksInTrendMapper.xml` | 动量个股数据访问层 | | `stock-system/src/main/resources/mapper/stocksystem/TrendsMapper.xml` | 板块动量数据访问层 | | `sql/nstocks/stocks_in_trend.sql` | 动量个股表结构 | | `sql/nstocks/trends.sql` | 板块动量表结构 | | `sql/nstocks/stocks_tmp.sql` | 辅助表结构 | --- *文档生成时间: 2026-03-14* *基于代码版本: RuoYi-Vue Stock-System*