换手率指标详细分析 Skill(配套11)

换手率指标详细分析 Skill

一、指标概述

1.1 换手率的定义

换手率(Turnover Rate),又称周转率,是指在一定时期内某只股票的成交量(或成交金额)与其流通股本(或流通市值)的比率。其本质衡量的是市场中股票所有权转移的频率,即"股票换手的速度"。换手率是衡量股票流通性和市场活跃程度最核心的量化指标之一。

从微观层面来看,换手率反映了投资者对该股票的交易热情和参与意愿。一只换手率高的股票,意味着大量投资者在短时间内进行了买卖操作,市场分歧较大;而换手率低的股票,则表明持股者倾向于持有,市场共识度较高。

1.2 换手率反映股票流通性和市场活跃度

换手率与股票流通性呈正相关关系。流通性好的股票,投资者可以以较低的交易成本快速买入或卖出,而不会对价格产生显著影响。换手率正是这种流通性的直接度量。

在市场实践中,换手率能够揭示以下关键信息:

  • 市场情绪温度计:换手率升高通常意味着市场情绪升温,投资者交易意愿增强;换手率降低则暗示市场趋于冷淡。
  • 筹码分布变化:持续的高换手率意味着筹码在快速换手,原有持仓者可能在离场,新资金在入场。
  • 流动性风险评估:极低的换手率可能意味着流动性不足,大额交易可能面临较大的滑点风险。
  • 主力行为追踪:异常的换手率变化往往是主力资金进出市场的信号。

1.3 换手率在技术分析中的重要性

在技术分析体系中,换手率占据着不可替代的地位,其重要性体现在以下几个方面:

第一,换手率是量价分析的核心补充。单纯观察成交量存在一个固有缺陷——大盘股和小盘股的成交量天然存在数量级差异,无法直接比较。换手率通过将成交量标准化为比率,消除了股本规模的影响,使得不同股票之间的横向比较成为可能。

第二,换手率是识别趋势可靠性的关键指标。在上升趋势中,适度的换手率表明趋势有资金支撑;在下跌趋势中,缩量换手可能意味着抛压减轻。换手率与价格走势的配合关系,能够帮助投资者判断趋势的健康程度。

第三,换手率是发现主力行为的重要窗口。机构资金的建仓、拉升、洗盘、出货等操作,都会在换手率上留下 distinctive 的痕迹。通过系统性地分析换手率的变化模式,投资者可以在一定程度上"跟踪"主力的操作轨迹。

第四,换手率在选股策略中具有筛选价值。通过设定换手率阈值,可以快速筛选出市场关注度高的活跃个股,或者排除流动性不足的标的,从而提高交易效率和风险管理水平。


二、计算公式详解

2.1 A股换手率计算

A股市场中最常用的换手率计算公式如下:

换手率 = 成交量 ÷ 流通股本 × 100%

其中:

  • 成交量:指统计周期内的累计成交股数(单位:股)。
  • 流通股本:指公司总股本中可以在二级市场自由交易的股份数量(单位:股)。

注意事项

  • 流通股本应使用最新数据,因为限售股解禁会导致流通股本发生变化。
  • 部分数据平台提供的换手率可能基于自由流通股本计算(扣除大股东长期持有的股份),结果会更高。
  • 计算日换手率时,成交量使用当日成交量;计算周换手率时,使用一周内每日成交量之和。

2.2 相对换手率与绝对换手率

在实际应用中,换手率分为两种口径:

相对换手率(总股本口径)

相对换手率 = 成交量 ÷ 总股本 × 100%

相对换手率以公司总股本为分母,包含了限售股等不能在二级市场交易的股份。这一指标在A股早期较为常用,但由于大量股份处于限售状态,相对换手率往往偏低,不能真实反映市场的实际交易活跃度。

绝对换手率(实际流通盘口径)

绝对换手率 = 成交量 ÷ 实际流通股本 × 100%

绝对换手率以实际流通股本为分母,只计算可以在二级市场自由交易的股份。这一指标更准确地反映了市场真实的交易活跃程度,是目前主流数据平台和投资者普遍采用的口径。

两者差异与实战意义

对比维度 相对换手率 绝对换手率
分母 总股本 实际流通股本
数值 偏低 偏高
准确性 较低 较高
适用场景 历史数据对比 实战交易分析

实战意义:对于限售股占比较大的公司(如次新股),两者的差异尤为显著。例如,一家总股本10亿股但实际流通仅2亿股的公司,若当日成交4000万股,相对换手率为4%,而绝对换手率高达20%。后者更能反映该股当日的真实交易热度。因此,在进行换手率分析时,强烈建议使用绝对换手率。

2.3 国外换手率计算

在欧美等成熟市场,换手率的计算方式有所不同,通常以金额为基准:

换手率 = 成交金额 ÷ 流通市值 × 100%

其中:

  • 成交金额:统计周期内的累计成交金额(单位:美元或当地货币)。
  • 流通市值:流通股本乘以当前股价。

差异原因

  • 成熟市场中,股票价格差异巨大(从几美元到几千美元),单纯以股数计算的换手率无法反映真实的资金活跃程度。
  • 以金额计算的换手率能够更直观地反映资金流向和市场活跃度。
  • 对于ADR(美国存托凭证)等特殊品种,以金额计算更为准确。

2.4 多周期换手率

换手率可以根据不同的统计周期进行计算,以满足不同分析需求:

日换手率

日换手率 = 当日成交量 ÷ 流通股本 × 100%

日换手率是最常用的换手率指标,反映单日内的交易活跃程度。A股市场日换手率的正常范围通常在1%-5%之间。

周换手率

周换手率 = 本周累计成交量 ÷ 流通股本 × 100%
          = Σ(每日成交量) ÷ 流通股本 × 100%

周换手率用于观察一周内的资金进出情况,能够平滑单日异常波动,更好地反映中期趋势。正常范围通常在5%-25%之间。

月换手率

月换手率 = 本月累计成交量 ÷ 流通股本 × 100%
          = Σ(每日成交量) ÷ 流通股本 × 100%

月换手率反映较长时间内的筹码换手情况,常用于判断主力建仓或出货的中长期行为。正常范围通常在20%-100%之间。

年换手率

年换手率 = 本年累计成交量 ÷ 流通股本 × 100%
          = Σ(每日成交量) ÷ 流通股本 × 100%

年换手率反映全年的交易活跃程度,A股市场个股年换手率通常在200%-1000%之间,远高于成熟市场(通常在50%-200%之间),这体现了A股市场短线交易活跃的特征。

2.5 换手率移动平均

为了消除短期波动噪音,实践中常使用换手率的移动平均值:

5日平均换手率

MA5换手率 = (T日换手率 + T-1日换手率 + ... + T-4日换手率) ÷ 5

5日平均换手率反映近一周的平均交易活跃度,适合短线分析。

10日平均换手率

MA10换手率 = (T日换手率 + T-1日换手率 + ... + T-9日换手率) ÷ 10

10日平均换手率反映近两周的平均交易活跃度,适合中线分析。

20日平均换手率

MA20换手率 = (T日换手率 + T-1日换手率 + ... + T-19日换手率) ÷ 20

20日平均换手率反映近一个月的平均交易活跃度,适合中长线趋势判断。

应用技巧:当短期换手率均线(如MA5)上穿长期换手率均线(如MA20)时,表明交易活跃度正在提升,可能预示着新一轮行情的启动;反之,则可能意味着行情趋于平淡。

2.6 完整计算示例

假设某A股上市公司数据如下:

  • 流通股本:5亿股
  • 总股本:8亿股
  • 当前股价:20元/股
  • 某日成交量:3000万股
  • 某日成交金额:6亿元
  • 流通市值:100亿元

计算过程

绝对换手率 = 3000万 ÷ 50000万 × 100% = 6.00%
相对换手率 = 3000万 ÷ 80000万 × 100% = 3.75%
金额换手率 = 60000万 ÷ 1000000万 × 100% = 6.00%

若该周五个交易日的成交量分别为:2000万、2500万、3000万、3500万、4000万股:

周换手率 = (2000+2500+3000+3500+4000)万 ÷ 50000万 × 100% = 30.00%
5日平均换手率 = 30.00% ÷ 5 = 6.00%

三、参数动态调整策略

3.1 换手率阈值设定

根据A股市场的长期统计和实践经验,换手率可按以下阈值进行分级:

等级 换手率范围 市场含义 操作建议
极低换手率 <1% 成交极度低迷,流动性差 谨慎参与,注意流动性风险
低换手率 1%-2% 交易清淡,市场关注度低 可关注,等待放量信号
温和换手率 2%-3% 交易正常偏弱 中性,结合其他指标判断
正常换手率 3%-7% 交易活跃度适中 正常交易区间
高换手率 7%-15% 交易活跃,资金关注度高 关注方向,警惕风险
极高换手率 >15% 交易异常活跃 高度警惕,可能见顶
异常换手率 >20% 极端异常,可能主力对倒 规避为主,等待确认

特别说明

  • 上述阈值为一般性参考标准,实际应用中需要结合具体股票的市值、板块特征和市场环境进行调整。
  • 异常换手率(>20%)在A股中虽然罕见,但在特定场景下会出现,如:新股上市首日、重大利好/利空消息公布、主力资金对倒操作等。
  • 持续多日换手率超过15%的股票,往往意味着筹码在快速换手,需要特别关注后续方向。

3.2 不同市值股票的换手率标准

不同市值规模的股票,其换手率特征存在显著差异:

大盘股(市值>500亿元)

大盘股由于流通盘巨大,资金难以在短时间内完成大规模换手,因此换手率普遍较低。

等级 换手率范围
低迷 <0.3%
正常 0.3%-1.0%
活跃 1.0%-2.0%
高换手 >2.0%

典型代表:工商银行、中国石油、贵州茅台等。贵州茅台作为特例,由于其独特的投资属性,换手率长期维持在0.2%-0.5%的极低水平,但价格走势强劲。

中盘股(市值100-500亿元)

中盘股的换手率处于中等水平,是主力资金较为青睐的标的。

等级 换手率范围
低迷 <1%
正常 1%-3%
活跃 3%-7%
高换手 >7%

小盘股(市值<100亿元)

小盘股由于流通盘较小,少量资金即可推动较大换手率。

等级 换手率范围
低迷 <2%
正常 2%-5%
活跃 5%-10%
高换手 >10%

创业板/科创板

创业板和科创板由于涨跌幅限制为20%(主板为10%),投机性更强,换手率普遍高于主板同市值股票。

等级 换手率范围
低迷 <3%
正常 3%-8%
活跃 8%-15%
高换手 >15%

3.3 不同市场环境下的参数调整

牛市环境

在牛市中,市场整体交易活跃,换手率中枢系统性上移:

  • 所有等级的阈值可上移30%-50%
  • 正常换手率范围调整为5%-10%
  • 高换手率阈值从7%上调至10%以上
  • 牛市中换手率持续维持高位是趋势健康的表现,不必过度恐慌

熊市环境

在熊市中,市场交易清淡,换手率中枢系统性下移:

  • 所有等级的阈值可下移20%-40%
  • 正常换手率范围调整为1%-4%
  • 低换手率阈值从1%下调至0.5%
  • 熊市中的突然放量换手需要高度关注,可能是反弹信号也可能是恐慌性抛售

震荡市环境

在震荡市中,换手率波动较大,建议:

  • 使用换手率移动平均(如MA10、MA20)来平滑波动
  • 关注换手率突破均线的行为,可能预示方向选择
  • 结合价格突破方向综合判断

四、核心交易信号

4.1 低位放量换手

底部区域突然换手率放大

当股票经过较长时间(通常3-6个月或更长)的下跌后,在底部区域出现换手率突然放大的现象,这是一个重要的关注信号。

识别特征

  • 股价处于长期下跌趋势的末端,累计跌幅通常超过30%-50%
  • 前期换手率持续低迷(通常低于2%)
  • 突然出现换手率放大至前期均值的2-3倍以上
  • 放量当日或随后几日,股价不再创新低,甚至出现小幅上涨
  • 成交量柱状图明显高出前期平均水平

主力吸筹信号

低位放量换手是主力吸筹的典型特征。主力资金在底部区域通过大量买入来收集筹码,由于买入量大,必然导致换手率显著上升。

确认方法

  • 观察换手率放大后是否持续(持续3-5日以上更为可靠)
  • 检查大宗交易数据是否有机构专用席位买入
  • 观察龙虎榜数据是否有知名游资或机构席位
  • 结合股东人数变化(股东人数减少通常意味着筹码集中)

4.2 高位放量换手

顶部区域换手率急剧放大

当股票经过较大幅度的上涨后,在高位区域出现换手率急剧放大的现象,这是一个危险的预警信号。

识别特征

  • 股价处于长期上涨趋势的高位,累计涨幅通常超过50%-100%
  • 前期换手率已经处于较高水平
  • 突然出现换手率急剧放大至异常水平(如>15%甚至>20%)
  • 股价虽然可能还在创新高,但涨幅明显收窄或出现长上影线
  • 当日成交量创出近期甚至历史新高

主力出货信号

高位放量换手是主力出货的典型特征。主力资金在高位区域通过大量卖出来实现获利了结,大量筹码从主力手中转移到了散户手中。

确认方法

  • 换手率放大后股价未能继续上涨,反而开始回落
  • 龙虎榜显示机构席位大量卖出
  • 股东人数急剧增加
  • 后续交易日换手率维持高位但股价持续走低

4.3 换手率与价格关系

换手率与价格走势的组合关系,是判断市场状态的重要工具:

低换手率 + 价格上涨(筹码锁定,看涨)

这是最健康的上涨模式。低换手率意味着持股者惜售,筹码锁定良好,少量买盘即可推动价格上涨。这种情况通常出现在:

  • 主力高度控盘的股票
  • 具有长期投资价值的优质白马股
  • 上涨趋势的中段,市场共识度高

操作建议:持股待涨,趋势未破不轻易离场。

高换手率 + 价格上涨(资金积极,但需警惕)

高换手伴随上涨,说明资金积极入场做多,短期动能强劲。但需要警惕的是,过高的换手率可能意味着多空分歧加大,筹码在快速换手。

操作建议

  • 换手率在5%-10%之间:可适当参与,跟随趋势
  • 换手率超过15%:需要高度警惕,考虑逐步减仓
  • 连续多日高换手上涨:可能进入冲刺阶段,随时可能见顶

低换手率 + 价格下跌(无量阴跌,看跌)

无量阴跌是最令人担忧的走势之一。低换手率意味着没有主力资金接盘,持股者因绝望而不断以低价卖出,但买盘稀少。这种情况通常出现在:

  • 下跌趋势的中后段
  • 基本面恶化的股票
  • 市场关注度极低的冷门股

操作建议:不宜抄底,等待放量止跌信号。

高换手率 + 价格下跌(恐慌抛售,可能见底)

高换手伴随下跌,说明市场出现恐慌性抛售,大量筹码在低价被抛出。虽然短期看似危险,但这往往是见底的信号之一——恐慌盘涌出意味着最后的卖压被释放。

操作建议

  • 首次出现恐慌性放量下跌:不宜立即抄底,等待企稳确认
  • 连续放量下跌后出现缩量企稳:可考虑轻仓试探
  • 放量下跌后出现放量上涨(底部反转):可考虑逐步建仓

4.4 换手率拐点

换手率从低位开始上升

当换手率从长期低迷状态开始上升,意味着市场关注度正在提升,资金开始流入。这是行情启动的前兆信号。

识别方法

  • 换手率从1%以下上升至3%以上
  • 换手率MA5上穿MA20
  • 伴随成交量温和放大
  • 股价开始摆脱底部整理区域

操作建议:可作为早期介入信号,结合其他技术指标确认后建仓。

换手率从高位开始下降

当换手率从高位开始下降,意味着市场热情正在消退,资金活跃度降低。

场景一:高位回落(看跌)

  • 股价在高位,换手率从15%以上降至5%以下
  • 意味着主力出货接近尾声,跟风盘减少
  • 后续可能进入阴跌阶段

场景二:中位回落(整理)

  • 股价在上涨中途回调,换手率从高位回落至正常水平
  • 可能是主力洗盘行为
  • 若回调幅度不大且换手率维持在3%以上,后续可能继续上涨

4.5 换手率背离

价格创新高但换手率下降(顶背离)

这是经典的看跌背离信号。价格虽然创出新高,但换手率反而下降,说明推动价格上涨的资金量在减少,上涨动能衰竭。

形成机制

  • 前期大量买入的资金已经获利,开始减少买入
  • 新入场资金不足以维持之前的上涨力度
  • 价格创新高更多是由于惯性而非新增资金推动

操作建议:考虑逐步减仓,设置止盈位。

价格创新低但换手率上升(底背离)

这是潜在的看涨背离信号。价格虽然创出新低,但换手率反而上升,说明有资金在低位积极承接。

形成机制

  • 恐慌性抛售导致价格创新低
  • 但同时有主力资金或价值投资者在低位大量买入
  • 抛压正在被新增买盘逐步消化

操作建议:密切关注,等待价格企稳和换手率持续放大后考虑介入。


五、换手率与成交量结合分析

5.1 换手率标准化的意义

成交量是技术分析中最基础最重要的指标之一,但原始成交量存在一个根本性缺陷:不同股票之间的成交量不具有可比性。一家流通盘100亿股的大盘股,日成交5亿股可能只是0.5%的换手率;而一家流通盘1亿股的小盘股,日成交500万股就是5%的换手率。两者的绝对成交量相差100倍,但后者的交易活跃度实际上是前者的10倍。

换手率通过将成交量除以流通股本,实现了标准化处理,使得不同市值、不同板块的股票之间可以进行横向比较。这种标准化对于以下场景尤为重要:

  • 选股筛选:在全市场范围内筛选交易活跃的个股
  • 行业比较:比较不同行业板块的交易活跃度差异
  • 历史对比:比较同一股票在不同时期(流通股本可能发生变化)的交易活跃度

5.2 量比与换手率的关系

量比(Volume Ratio)是另一个常用的成交量指标,其计算公式为:

量比 = 当日即时成交量 ÷ 过去5日同时段平均成交量

量比和换手率的区别与联系:

对比维度 量比 换手率
含义 当日与历史同期成交量的比较 成交量与流通股本的比率
参照系 自身历史数据 流通股本
时间维度 盘中实时指标 日/周/月等固定周期
横向可比性 较差 较好
主要用途 发现当日异动 评估整体活跃度

结合使用方法

  • 量比>2 且 换手率>5%:当日放量且整体活跃,可能是行情启动信号
  • 量比<0.5 且 换手率<1%:当日缩量且整体低迷,市场关注度极低
  • 量比>3 但 换手率<2%:可能是盘中短暂脉冲,持续性存疑

5.3 换手率选股策略

基于换手率的选股策略主要包括以下几种:

策略一:低位放量突破选股

  • 筛选条件:股价在60日低点附近(±10%),换手率突然放大至近20日平均的2倍以上
  • 逻辑:底部放量可能是主力吸筹信号
  • 风险:可能是假突破,需要结合其他指标确认

策略二:温和放量上涨选股

  • 筛选条件:股价处于上升趋势,换手率维持在3%-8%之间,MA5换手率>MA20换手率
  • 逻辑:适度活跃的换手率支撑价格上涨
  • 风险:趋势可能随时反转

策略三:异常换手率监控

  • 筛选条件:换手率突然超过15%,且股价未涨停
  • 逻辑:发现潜在的主力异动
  • 风险:可能是主力对倒出货

六、Python代码实现

6.1 换手率计算函数(支持动态参数和多口径)

import pandas as pd
import numpy as np

def calculate_turnover_rate(volume, float_shares, total_shares=None,
                            method='absolute'):
    """
    计算换手率,支持多种口径

    参数:
        volume (pd.Series or np.array): 成交量(股)
        float_shares (float): 流通股本(股)
        total_shares (float): 总股本(股),method='relative'时需要
        method (str): 计算口径,'absolute'(绝对换手率)或 'relative'(相对换手率)

    返回:
        pd.Series: 换手率(百分比)
    """
    if method == 'absolute':
        denominator = float_shares
    elif method == 'relative':
        if total_shares is None:
            raise ValueError("计算相对换手率需要提供 total_shares 参数")
        denominator = total_shares
    else:
        raise ValueError(f"不支持的 method: {method},请使用 'absolute' 或 'relative'")

    turnover_rate = volume / denominator * 100
    return turnover_rate


def calculate_turnover_rate_by_amount(trade_amount, float_market_cap):
    """
    以金额口径计算换手率(适用于海外市场)

    参数:
        trade_amount (pd.Series or np.array): 成交金额
        float_market_cap (float): 流通市值

    返回:
        pd.Series: 换手率(百分比)
    """
    turnover_rate = trade_amount / float_market_cap * 100
    return turnover_rate

6.2 多周期换手率计算

def calculate_multi_period_turnover(df, float_shares, periods=None):
    """
    计算多周期换手率

    参数:
        df (pd.DataFrame): 包含 'volume' 列的DataFrame,需有DatetimeIndex
        float_shares (float or pd.Series): 流通股本
        periods (list): 需要计算的周期列表,默认为 ['1D', '1W', '1M']

    返回:
        pd.DataFrame: 包含各周期换手率的DataFrame
    """
    if periods is None:
        periods = ['1D', '1W', '1M']

    result = pd.DataFrame(index=df.index)

    # 日换手率
    if isinstance(float_shares, pd.Series):
        result['daily_turnover'] = df['volume'] / float_shares * 100
    else:
        result['daily_turnover'] = df['volume'] / float_shares * 100

    # 周换手率(滚动5个交易日)
    if '1W' in periods:
        result['weekly_turnover'] = result['daily_turnover'].rolling(
            window=5, min_periods=1).sum()

    # 月换手率(滚动22个交易日)
    if '1M' in periods:
        result['monthly_turnover'] = result['daily_turnover'].rolling(
            window=22, min_periods=1).sum()

    # 年换手率(滚动250个交易日)
    if '1Y' in periods:
        result['yearly_turnover'] = result['daily_turnover'].rolling(
            window=250, min_periods=1).sum()

    return result


def calculate_turnover_ma(daily_turnover, windows=None):
    """
    计算换手率移动平均

    参数:
        daily_turnover (pd.Series): 日换手率序列
        windows (list): 移动平均窗口列表

    返回:
        pd.DataFrame: 包含各窗口移动平均的DataFrame
    """
    if windows is None:
        windows = [5, 10, 20]

    result = pd.DataFrame(index=daily_turnover.index)
    result['daily_turnover'] = daily_turnover

    for w in windows:
        result[f'ma{w}_turnover'] = daily_turnover.rolling(
            window=w, min_periods=1).mean()

    return result

6.3 换手率信号检测函数

def detect_turnover_signals(df, turnover_col='daily_turnover',
                            low_threshold=1.0, high_threshold=15.0,
                            abnormal_threshold=20.0):
    """
    检测换手率交易信号

    参数:
        df (pd.DataFrame): 包含换手率和价格数据的DataFrame
        turnover_col (str): 换手率列名
        low_threshold (float): 低换手率阈值
        high_threshold (float): 高换手率阈值
        abnormal_threshold (float): 异常换手率阈值

    返回:
        pd.DataFrame: 包含信号标记的DataFrame
    """
    result = df.copy()
    turnover = result[turnover_col]
    close = result['close']

    # 信号1:低位放量换手(底部吸筹信号)
    # 条件:换手率突然放大至20日均值的2倍以上,且股价处于60日低点附近
    ma20_turnover = turnover.rolling(window=20, min_periods=1).mean()
    price_60d_low = close.rolling(window=60, min_periods=1).min()
    result['signal_bottom_volume'] = (
        (turnover > ma20_turnover * 2) &
        (close < price_60d_low * 1.10)
    ).astype(int)

    # 信号2:高位放量换手(顶部出货信号)
    price_60d_high = close.rolling(window=60, min_periods=1).max()
    result['signal_top_volume'] = (
        (turnover > high_threshold) &
        (close > price_60d_high * 0.90)
    ).astype(int)

    # 信号3:异常换手率
    result['signal_abnormal'] = (turnover > abnormal_threshold).astype(int)

    # 信号4:换手率顶背离(价格创新高,换手率下降)
    price_20d_high = close.rolling(window=20, min_periods=1).max()
    turnover_20d_high = turnover.rolling(window=20, min_periods=1).max()
    result['signal_bearish_divergence'] = (
        (close == price_20d_high) &
        (turnover < turnover_20d_high * 0.7)
    ).astype(int)

    # 信号5:换手率底背离(价格创新低,换手率上升)
    price_20d_low = close.rolling(window=20, min_periods=1).min()
    ma5_turnover = turnover.rolling(window=5, min_periods=1).mean()
    result['signal_bullish_divergence'] = (
        (close == price_20d_low) &
        (ma5_turnover > ma20_turnover * 1.3)
    ).astype(int)

    # 信号6:换手率拐点向上
    result['signal_turnover_up'] = (
        (ma5_turnover > ma20_turnover) &
        (ma5_turnover.shift(1) <= ma20_turnover.shift(1))
    ).astype(int)

    # 信号7:换手率拐点向下
    result['signal_turnover_down'] = (
        (ma5_turnover < ma20_turnover) &
        (ma5_turnover.shift(1) >= ma20_turnover.shift(1))
    ).astype(int)

    return result


def classify_turnover_level(turnover_value, market_cap=None, board=None):
    """
    根据换手率数值和市场特征进行分级

    参数:
        turnover_value (float): 换手率值(百分比)
        market_cap (float): 市值(亿元),可选
        board (str): 板块,'main'/'gem'/'star',可选

    返回:
        str: 换手率等级
    """
    # 根据市值和板块调整阈值
    if board == 'gem' or board == 'star':
        thresholds = {
            '极低': 3, '低': 5, '温和': 8,
            '正常': (8, 15), '高': (15, 25), '极高': 25
        }
    elif market_cap and market_cap > 500:
        thresholds = {
            '极低': 0.3, '低': 0.5, '温和': 1.0,
            '正常': (1.0, 2.0), '高': (2.0, 3.0), '极高': 3.0
        }
    elif market_cap and market_cap < 100:
        thresholds = {
            '极低': 2, '低': 3, '温和': 5,
            '正常': (5, 10), '高': (10, 20), '极高': 20
        }
    else:
        thresholds = {
            '极低': 1, '低': 2, '温和': 3,
            '正常': (3, 7), '高': (7, 15), '极高': 15
        }

    if turnover_value < thresholds['极低']:
        return '极低换手率'
    elif turnover_value < thresholds['低']:
        return '低换手率'
    elif turnover_value < thresholds['温和']:
        return '温和换手率'
    elif turnover_value < thresholds['正常'][1]:
        return '正常换手率'
    elif turnover_value < thresholds['高'][1]:
        return '高换手率'
    else:
        return '极高换手率'

6.4 换手率选股函数

def turnover_stock_selection(stock_pool, turnover_data, min_turnover=3.0,
                             max_turnover=15.0, price_change_min=None,
                             price_change_max=None, volume_ratio_min=None):
    """
    基于换手率的选股函数

    参数:
        stock_pool (list): 股票代码列表
        turnover_data (dict): {stock_code: DataFrame} 各股票数据
        min_turnover (float): 最低换手率阈值
        max_turnover (float): 最高换手率阈值
        price_change_min (float): 最低涨跌幅限制
        price_change_max (float): 最高涨跌幅限制
        volume_ratio_min (float): 最低量比限制

    返回:
        list: 符合条件的股票代码列表
    """
    selected = []

    for code in stock_pool:
        if code not in turnover_data:
            continue

        df = turnover_data[code]
        if df.empty:
            continue

        latest = df.iloc[-1]

        # 换手率筛选
        turnover = latest.get('daily_turnover', 0)
        if turnover < min_turnover or turnover > max_turnover:
            continue

        # 涨跌幅筛选
        if price_change_min is not None or price_change_max is not None:
            pct_change = latest.get('pct_change', 0)
            if price_change_min is not None and pct_change < price_change_min:
                continue
            if price_change_max is not None and pct_change > price_change_max:
                continue

        # 量比筛选
        if volume_ratio_min is not None:
            volume_ratio = latest.get('volume_ratio', 0)
            if volume_ratio < volume_ratio_min:
                continue

        selected.append({
            'code': code,
            'turnover': turnover,
            'close': latest.get('close', 0),
            'pct_change': latest.get('pct_change', 0),
            'volume_ratio': latest.get('volume_ratio', 0)
        })

    # 按换手率降序排列
    selected.sort(key=lambda x: x['turnover'], reverse=True)
    return selected

6.5 回测框架示例

import pandas as pd
import numpy as np
from datetime import datetime, timedelta

class TurnoverBacktest:
    """基于换手率信号的简单回测框架"""

    def __init__(self, initial_capital=1000000, commission_rate=0.0003):
        self.initial_capital = initial_capital
        self.commission_rate = commission_rate
        self.trades = []
        self.equity_curve = []

    def generate_signals(self, df, signal_col='signal_bottom_volume'):
        """
        生成交易信号

        买入条件:出现底部放量信号
        卖出条件:持仓N日后或出现高位放量信号
        """
        signals = pd.DataFrame(index=df.index)
        signals['signal'] = 0
        signals.loc[df[signal_col] == 1, 'signal'] = 1  # 买入信号

        # 卖出信号:买入后持有5日自动卖出,或出现高位放量
        hold_period = 5
        buy_dates = df[df[signal_col] == 1].index
        for buy_date in buy_dates:
            sell_candidates = []
            for i in range(1, hold_period + 1):
                try:
                    next_date = df.index[df.index.get_loc(buy_date) + i]
                    sell_candidates.append(next_date)
                except (IndexError, KeyError):
                    break

            for sell_date in sell_candidates:
                if df.loc[sell_date, 'signal_top_volume'] == 1:
                    signals.loc[sell_date, 'signal'] = -1
                    break
            else:
                if sell_candidates:
                    signals.loc[sell_candidates[-1], 'signal'] = -1

        return signals

    def run_backtest(self, df, signals):
        """
        执行回测

        参数:
            df (pd.DataFrame): 价格数据
            signals (pd.DataFrame): 交易信号

        返回:
            dict: 回测结果
        """
        capital = self.initial_capital
        position = 0
        entry_price = 0
        equity_list = []

        for date in df.index:
            if date not in signals.index:
                equity_list.append({'date': date, 'equity': capital})
                continue

            price = df.loc[date, 'close']
            signal = signals.loc[date, 'signal']

            if signal == 1 and position == 0:  # 买入
                shares = int(capital * 0.95 / price / 100) * 100  # 整手买入
                if shares > 0:
                    cost = shares * price * (1 + self.commission_rate)
                    capital -= cost
                    position = shares
                    entry_price = price
                    self.trades.append({
                        'date': date, 'action': 'BUY',
                        'price': price, 'shares': shares
                    })

            elif signal == -1 and position > 0:  # 卖出
                revenue = position * price * (1 - self.commission_rate)
                capital += revenue
                self.trades.append({
                    'date': date, 'action': 'SELL',
                    'price': price, 'shares': position,
                    'pnl': (price - entry_price) / entry_price * 100
                })
                position = 0

            total_equity = capital + position * price
            equity_list.append({'date': date, 'equity': total_equity})

        equity_df = pd.DataFrame(equity_list)
        equity_df.set_index('date', inplace=True)

        # 计算回测指标
        total_return = (capital - self.initial_capital) / self.initial_capital * 100
        winning_trades = [t for t in self.trades if t['action'] == 'SELL' and t['pnl'] > 0]
        losing_trades = [t for t in self.trades if t['action'] == 'SELL' and t['pnl'] <= 0]
        win_rate = len(winning_trades) / max(len(winning_trades) + len(losing_trades), 1) * 100

        return {
            'total_return': total_return,
            'total_trades': len([t for t in self.trades if t['action'] == 'SELL']),
            'win_rate': win_rate,
            'equity_curve': equity_df,
            'trades': self.trades
        }

6.6 可视化代码

import matplotlib.pyplot as plt
import matplotlib.dates as mdates

def plot_turnover_analysis(df, turnover_col='daily_turnover',
                          ma_windows=[5, 10, 20], figsize=(14, 10)):
    """
    换手率分析可视化

    参数:
        df (pd.DataFrame): 包含价格和换手率数据的DataFrame
        turnover_col (str): 换手率列名
        ma_windows (list): 移动平均窗口列表
        figsize (tuple): 图表大小
    """
    fig, axes = plt.subplots(3, 1, figsize=figsize, height_ratios=[2, 1, 1],
                             sharex=True)

    # 子图1:价格走势
    axes[0].plot(df.index, df['close'], color='#1E88E5', linewidth=1.2,
                 label='收盘价')
    axes[0].fill_between(df.index, df['close'], alpha=0.1, color='#1E88E5')
    axes[0].set_ylabel('价格(元)', fontsize=12)
    axes[0].set_title('换手率综合分析', fontsize=14, fontweight='bold')
    axes[0].legend(loc='upper left')
    axes[0].grid(True, alpha=0.3)

    # 子图2:换手率及均线
    axes[1].bar(df.index, df[turnover_col], alpha=0.5, color='#90CAF9',
                label='日换手率')
    colors = ['#FF5722', '#FFC107', '#4CAF50']
    for i, w in enumerate(ma_windows):
        ma_col = f'ma{w}_turnover'
        if ma_col in df.columns:
            axes[1].plot(df.index, df[ma_col], color=colors[i],
                         linewidth=1.2, label=f'MA{w}换手率')

    # 添加阈值线
    axes[1].axhline(y=1, color='gray', linestyle='--', alpha=0.5, linewidth=0.8)
    axes[1].axhline(y=7, color='orange', linestyle='--', alpha=0.5, linewidth=0.8)
    axes[1].axhline(y=15, color='red', linestyle='--', alpha=0.5, linewidth=0.8)
    axes[1].set_ylabel('换手率(%)', fontsize=12)
    axes[1].legend(loc='upper left')
    axes[1].grid(True, alpha=0.3)

    # 子图3:成交量
    axes[2].bar(df.index, df['volume'] / 10000, alpha=0.6,
                color='#26A69A', label='成交量(万手)')
    axes[2].set_ylabel('成交量(万手)', fontsize=12)
    axes[2].set_xlabel('日期', fontsize=12)
    axes[2].legend(loc='upper left')
    axes[2].grid(True, alpha=0.3)
    axes[2].xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
    axes[2].xaxis.set_major_locator(mdates.MonthLocator(interval=1))

    plt.tight_layout()
    plt.savefig('turnover_analysis.png', dpi=150, bbox_inches='tight')
    plt.show()


def plot_turnover_price_scatter(df, turnover_col='daily_turnover',
                                pct_change_col='pct_change', figsize=(10, 8)):
    """
    换手率与涨跌幅散点图

    参数:
        df (pd.DataFrame): 包含换手率和涨跌幅数据的DataFrame
        turnover_col (str): 换手率列名
        pct_change_col (str): 涨跌幅列名
        figsize (tuple): 图表大小
    """
    fig, ax = plt.subplots(figsize=figsize)

    # 根据涨跌着色
    colors = np.where(df[pct_change_col] >= 0, '#EF5350', '#26A69A')
    sizes = np.abs(df[pct_change_col]) * 5 + 10

    scatter = ax.scatter(df[turnover_col], df[pct_change_col],
                         c=colors, s=sizes, alpha=0.6, edgecolors='white',
                         linewidth=0.5)

    ax.axhline(y=0, color='gray', linestyle='-', alpha=0.3)
    ax.axvline(x=7, color='orange', linestyle='--', alpha=0.5, label='高换手率阈值(7%)')
    ax.axvline(x=15, color='red', linestyle='--', alpha=0.5, label='极高换手率阈值(15%)')

    ax.set_xlabel('换手率(%)', fontsize=12)
    ax.set_ylabel('涨跌幅(%)', fontsize=12)
    ax.set_title('换手率与涨跌幅关系散点图', fontsize=14, fontweight='bold')
    ax.legend(loc='upper right')
    ax.grid(True, alpha=0.3)

    plt.tight_layout()
    plt.savefig('turnover_price_scatter.png', dpi=150, bbox_inches='tight')
    plt.show()

七、实战案例

7.1 A股低位高换手选股案例

案例背景:2024年某A股上市公司(以下简称"A公司"),市值约80亿元,属于小盘股。该股在经历长达8个月的下跌后,累计跌幅达45%,股价从22元跌至12元左右。

换手率变化过程

阶段 时间段 日均换手率 股价区间 市场特征
阴跌期 1月-6月 0.8%-1.5% 22→13元 持续阴跌,成交低迷
筑底期 7月-8月 1.0%-2.0% 12-13元 跌速放缓,开始横盘
放量期 9月初 5%-8% 12-14元 换手率突然放大3-5倍
突破期 9月中旬 6%-10% 14-16元 放量突破,确认趋势
上涨期 10月-12月 4%-7% 16-20元 温和放量上涨

分析要点

  1. 在阴跌期,换手率长期低于1.5%,表明市场对该股完全失去兴趣。
  2. 筑底期换手率略有回升,但仍在2%以下,属于地量水平。
  3. 9月初换手率突然从1.5%飙升至5%以上,放大超过3倍,且股价不再创新低,这是典型的底部放量吸筹信号。
  4. 9月中旬换手率维持在6%-10%的高位,股价突破前期整理平台,确认上升趋势。
  5. 上涨期换手率回落至4%-7%的健康水平,说明筹码锁定良好,上涨趋势可持续。

操作策略:在9月初换手率首次放大且股价不创新低时轻仓试探(买入1/3仓位),在放量突破平台时加仓(买入1/3仓位),在上涨趋势确认后持有(保留1/3现金作为后备)。止损位设在放量前的低点下方5%。

7.2 次新股换手率分析案例

案例背景:某创业板新股上市,发行价25元,上市首日涨幅达44%(达到涨停限制),随后进入无涨跌幅限制的5个交易日。

换手率变化过程

交易日 收盘价 换手率 成交量(万股) 分析
上市首日 36.00 68.5% 6850 首日换手极高,筹码大量换手
第2日 42.00 45.2% 4520 换手率仍高,多空分歧大
第3日 38.50 32.8% 3280 冲高回落,换手率开始下降
第4日 35.00 18.5% 1850 继续调整,换手率快速下降
第5日 33.00 12.3% 1230 趋于稳定,换手率接近正常
第10日 30.50 5.2% 520 筹码逐步沉淀
第20日 28.00 3.1% 310 换手率回归正常
第60日 32.00 4.5% 450 新一轮行情启动

分析要点

  1. 次新股上市初期换手率极高是正常现象,因为中签者倾向于上市首日卖出获利了结。
  2. 首日68.5%的换手率意味着超过2/3的流通筹码换了主人,这是新股特有的现象。
  3. 随着交易日增加,换手率逐步下降,筹码从短线投机者向中线投资者转移。
  4. 第60日换手率从低位再次上升至4.5%,且股价企稳回升,可能预示新一轮行情的启动。

操作策略:次新股上市初期(前5个交易日)换手率极高,波动剧烈,不建议普通投资者参与。待换手率稳定在5%以下且股价企稳后,可结合基本面分析考虑介入。当换手率从低位再次上升时,可能是较好的介入时机。

7.3 主力吸筹/出货换手率特征案例

案例背景:某主板上市公司(以下简称"B公司"),市值约200亿元。该股在2024年上半年完成了一轮完整的"主力吸筹-拉升-出货"周期。

阶段一:主力吸筹期(1月-3月)

特征 具体表现
股价表现 在15-17元区间窄幅震荡,波幅不超过10%
换手率特征 日均换手率2%-4%,间歇性出现5%-8%的脉冲
成交量特征 整体缩量,但间歇性出现温和放量
筹码变化 股东人数从8万降至6.5万,筹码趋于集中
K线形态 多为小阳小阴线,偶有中阳线

分析:吸筹期换手率不高但稳定,主力通过小单持续买入,避免引起市场关注。间歇性的换手率脉冲是主力集中吸筹的表现。

阶段二:拉升期(4月-6月)

特征 具体表现
股价表现 从17元稳步上涨至28元,涨幅约65%
换手率特征 日均换手率4%-7%,呈现"涨时放量、跌时缩量"特征
成交量特征 上涨日成交量明显放大,回调日成交量萎缩
筹码变化 股东人数稳定在6万左右
K线形态 阳线多阴线少,阳线实体较大

分析:拉升期换手率适中且呈现规律性波动,表明主力控盘良好,上涨趋势健康。"涨放量跌缩量"是典型的健康上涨特征。

阶段三:出货期(7月-8月)

特征 具体表现
股价表现 在26-30元区间震荡,多次冲高回落
换手率特征 日均换手率急剧上升至8%-15%,多次超过15%
成交量特征 成交量持续维持在高位,甚至创出天量
筹码变化 股东人数从6万急剧增至9万,筹码快速分散
K线形态 频繁出现长上影线、十字星等见顶信号

分析:出货期换手率急剧放大是核心识别特征。主力在高位通过大量对倒交易吸引跟风盘,同时暗中出货。换手率超过15%的交易日往往是主力集中出货的日子。股东人数急剧增加是筹码从主力向散户转移的直接证据。

操作策略:在吸筹期尾声(换手率开始温和放大且股价突破平台)时介入,在拉升期持股不动,在出货期初期(换手率突然急剧放大且出现长上影线)时果断离场。


八、优缺点总结

优点

  1. 标准化程度高:换手率通过将成交量除以流通股本,消除了股本规模的影响,实现了不同股票之间的横向可比性,这是原始成交量无法做到的。

  2. 反映市场真实活跃度:换手率直接衡量了市场中股票所有权转移的频率,能够真实反映市场的交易活跃程度和投资者参与意愿。

  3. 揭示主力行为:异常的换手率变化往往是主力资金进出市场的信号。低位放量吸筹、高位放量出货等经典主力行为模式,都可以通过换手率变化来识别。

  4. 多维度分析价值:换手率可以与价格、成交量、均线等多个维度结合分析,形成丰富的交易信号体系,适用于不同风格和周期的投资者。

  5. 计算简单直观:换手率的计算公式简单明了,数据获取方便,不需要复杂的数学模型,适合各类投资者使用。

  6. 适用范围广泛:换手率不仅适用于个股分析,还可以用于行业板块比较、市场整体活跃度评估、ETF流动性分析等多个层面。

缺点

  1. 流通股本数据滞后:流通股本会随着限售股解禁、增发、回购等事件发生变化,但数据更新可能存在滞后,导致换手率计算出现偏差。特别是对于频繁发生股本变动的公司,这一问题更为突出。

  2. 无法区分交易方向:换手率只反映交易活跃程度,无法区分买入和卖出的力量对比。同样10%的换手率,可能是主力在买入,也可能是主力在卖出,需要结合价格走势和其他指标综合判断。

  3. 对异常交易敏感:大宗交易、大宗减持、转融通出借等非正常交易行为都会影响换手率,可能导致换手率失真。特别是在计算日换手率时,单笔大额交易可能使换手率出现异常跳升。

  4. 不同口径差异大:绝对换手率、相对换手率、自由流通换手率等不同口径的计算结果差异显著,不同数据平台可能采用不同的计算口径,导致横向比较时需要注意口径一致性。

  5. 阈值标准不统一:换手率的"高"与"低"因市值、板块、市场环境等因素而异,不存在放之四海而皆准的标准阈值。投资者需要根据具体情况动态调整参数,这增加了使用难度。

  6. 滞后性:换手率是事后计算的指标,当投资者观察到换手率变化时,市场行情可能已经走了一段。虽然换手率移动平均可以部分缓解这一问题,但无法完全消除滞后性。

  7. 次新股和特殊品种适用性差:对于刚上市的次新股,由于中签者集中卖出,换手率会异常偏高,传统的换手率分析框架可能失效。对于交易不活跃的冷门股,换手率可能长期处于极低水平,分析价值有限。

适用场景建议

场景 适用性 说明
个股趋势分析 换手率与价格走势结合,判断趋势健康度
主力行为追踪 中高 异常换手率可辅助识别主力进出
选股筛选 通过换手率阈值快速筛选活跃个股
板块比较 需注意板块内市值差异
市场整体评估 可用全市场平均换手率衡量市场情绪
次新股分析 换手率失真,需特殊处理
量化策略 换手率信号易于量化,适合系统化交易

本文档详细介绍了换手率指标的定义、计算方法、参数调整策略、核心交易信号、与其他指标的配合使用方法,以及完整的Python代码实现和实战案例分析。换手率作为技术分析中的基础但核心的指标,其价值在于将成交量标准化,为投资者提供了一个简洁而有效的市场活跃度度量工具。在实际应用中,建议将换手率与价格走势、成交量、均线等多个指标结合使用,以提高分析的准确性和可靠性。
上述内容经供学习参考,股市有风险投资需谨慎

这是一套完整的合集,上方的可以单独使用可以组合使用,使用方法,复制此行上方的完整信息,让trae帮你在本地生成一套完整的Skill,为了防止模型迷路我将完整的链接贴在下方。

2 个赞