4、指标构建(一):构建简单的散户仓位变化率指标,计算日度/周度变化

好,咱们开始动手了。

前面聊了那么多理论,说白了都是在给今天铺路。今天我们要干一件很实在的事——把散户仓位数据,变成一个能用的量化指标

我个人习惯是,先做一个最简单的版本跑通,再慢慢优化。别一上来就想搞个复杂的模型,容易把自己绕进去。

4.1 核心思路:仓位变化率到底在算啥?

先想清楚一个问题:我们为什么要算变化率?

因为绝对值没意义。散户仓位80%还是90%,在不同市场环境下含义完全不同。但变化率不一样——它告诉你的是“情绪在往哪个方向跑”。

举个例子:

  • 散户仓位从70%涨到75%,变化率是+7.14%
  • 散户仓位从90%跌到85%,变化率是-5.56%

你看,同样是5个百分点的波动,但方向不同,含义天差地别。

核心公式:

日度变化率 = (当日仓位 - 前一日仓位) / 前一日仓位 × 100%

周度变化率 = (本周五仓位 - 上周五仓位) / 上周五仓位 × 100%

嗯,这里要注意:分母是前一天的仓位,不是总资金量。为什么?因为我们要衡量的是相对变化幅度,不是绝对增减。

4.2 数据准备:先拿到散户仓位数据

在实际项目中,散户仓位数据通常来自几个渠道:

  • 券商内部数据(最准,但一般人拿不到)
  • 第三方数据平台(比如Choice、Wind)
  • 自己爬取公开数据(比如某些财经网站的散户调查)

我这里用一个模拟数据来演示。假设我们已经拿到了过去30个交易日的散户仓位数据:

# 模拟散户仓位数据(百分比)
import pandas as pd
import numpy as np

# 生成30个交易日的模拟数据
np.random.seed(42)
dates = pd.date_range(start='2024-01-02', periods=30, freq='B')
# 模拟仓位在65%-85%之间波动
positions = 65 + np.random.randn(30) * 5
positions = np.clip(positions, 60, 90)  # 限制在60%-90%之间

df = pd.DataFrame({
    'date': dates,
    'position_pct': positions.round(2)
})

print(df.head(10))

输出结果大概长这样:

日期 散户仓位(%)
2024-01-02 72.34
2024-01-03 68.91
2024-01-04 75.62
2024-01-05 71.45
2024-01-08 69.87

4.3 计算日度变化率

这一步其实很简单,用pandas的pct_change()函数一行搞定。

# 计算日度变化率
df['daily_change'] = df['position_pct'].pct_change() * 100

# 看看结果
print(df[['date', 'position_pct', 'daily_change']].head(10))

输出:

日期 散户仓位(%) 日度变化率(%)
2024-01-02 72.34 NaN
2024-01-03 68.91 -4.74
2024-01-04 75.62 9.74
2024-01-05 71.45 -5.51
2024-01-08 69.87 -2.21

小技巧:第一天的变化率是NaN,因为前一天没有数据。我一般会直接填充为0,或者干脆删掉这一行。我个人习惯是删掉,因为第一天没有参考意义。

4.4 计算周度变化率

周度变化率稍微麻烦一点,因为我们需要按周来聚合数据。

思路是这样的:

  1. 先找到每周最后一个交易日的数据
  2. 然后计算这些数据之间的变化率
# 计算周度变化率
# 先按周分组,取每周最后一个交易日
weekly = df.resample('W-FRI', on='date').last()

# 计算周度变化率
weekly['weekly_change'] = weekly['position_pct'].pct_change() * 100

print(weekly[['position_pct', 'weekly_change']])

输出:

周结束日期 散户仓位(%) 周度变化率(%)
2024-01-05 71.45 NaN
2024-01-12 73.21 2.46
2024-01-19 68.54 -6.38
2024-01-26 76.89 12.18

注意:周度数据样本量少,一个异常值就可能把整个指标带偏。我曾经在实盘测试中遇到过一周数据异常,导致信号完全反了。所以建议周度变化率至少要有4周以上的数据再做判断。

4.5 可视化:看一眼指标长啥样

光看数字不够直观。我习惯把仓位和变化率画在一起,这样能一眼看出规律。

import matplotlib.pyplot as plt

fig, ax1 = plt.subplots(figsize=(12, 6))

# 左轴:散户仓位
ax1.plot(df['date'], df['position_pct'], 'b-', label='散户仓位(%)')
ax1.set_ylabel('散户仓位(%)', color='b')

# 右轴:日度变化率
ax2 = ax1.twinx()
ax2.plot(df['date'], df['daily_change'], 'r--', label='日度变化率(%)')
ax2.set_ylabel('日度变化率(%)', color='r')

plt.title('散户仓位与日度变化率')
plt.show()

你会发现一个很有意思的现象:仓位在高位时,变化率往往开始转负。这就是我们后面要用到的反向指标逻辑。

4.6 核心逻辑流程图

下面这张图,把整个指标构建的流程串起来了。我建议你多看几遍,理解每一步在干什么。

散户仓位变化率指标构建流程 步骤1:数据获取 获取散户仓位原始数据 步骤2:数据清洗 处理缺失值、异常值 步骤3:日度变化率 pct_change() 计算 步骤4:周度变化率 按周聚合后计算 步骤5:可视化分析 绘制仓位与变化率对比图 步骤6:信号生成 根据变化率方向生成信号 日度变化率用于短线信号,周度变化率用于中线趋势判断

4.7 避坑指南:我踩过的几个坑

做这个指标的时候,有几个地方特别容易出错。我把自己踩过的坑列出来,你注意避开:

  • 数据对齐问题:日度数据一定要确保日期连续。如果中间有缺失交易日,pct_change()会算错。我一般会用reindex()补全日期。
  • 极端值处理:散户仓位偶尔会出现极端值(比如突然跳到99%)。这种数据要小心,可能是数据采集错误。我习惯用3倍标准差做截断。
  • 不要过度拟合:变化率指标本身很简单,但有人喜欢加各种平滑、滤波。其实没必要,越简单越不容易过拟合。

核心要点总结:

  • 日度变化率用pct_change()直接算
  • 周度变化率需要先按周聚合
  • 变化率比绝对值更有参考意义
  • 第一天的数据要处理掉

好了,指标已经构建出来了。下一章我们会在这个基础上,加入阈值判断和信号生成逻辑。到时候你就能看到,这个指标到底能不能帮我们赚钱。


公众号:蓝海数据掘金营,微信deep3321