跳到正文
进阶指标2026-08-0412分钟阅读

成交量与持仓量:期货独有的第四维信息

新手学习路线 · 第 4 阶段「看懂市场」第 1 / 6 篇

目录(10 节)
  1. 写在前面
  2. 一、为什么股票没有持仓量
  3. 二、一笔成交,四种组合,三种结果
  4. 三、开始用之前,四个口径的坑
  5. 四、它没有参数,但有一个比值
  6. 五、三个用法(按价值排序)
  7. 六、失效场景(这一节请比上一节读得更用力)
  8. 七、代码
  9. 八、三个你该自己跑一遍的实验
  10. 九、三句话结论

写在前面

一句在股票市场里大致成立、搬到期货上会出人命的话:

"放量了,说明有资金在进场。"

在期货里,这句话可能完全说反。

因为一笔成交的双方未必都在进场。可能一个人进场、另一个人离场;也可能两个人都在离场。

也就是说:成交量放大,市场上的钱可能正在变多,可能正在变少,也可能一分没变、只是换了主人。 光看成交量,这三件事你一件都分不出来。

能分出来的,是另一个数——持仓量。

这是股票没有、期货独有的维度。开高低收算作价,再加成交量,持仓量就是第四个。国内几乎所有行情软件都把它摆在最显眼的位置,也几乎所有新手都在忽略它。


一、为什么股票没有持仓量

先问一个问题:一只股票,"未平仓股数"是多少?

这个问题没有意义。一家公司的股份总数是发行出来的,是固定的。你买我卖,股份从一个账户挪到另一个账户,总数一根毛都不会变。

期货不是。期货合约不是谁发行的,是两个人当场约定出来的:一个要买,一个要卖,双方都愿意承担未来的履约义务——这一刻,市场上就凭空多出一份合约。等两人都不想玩了,把仓平掉,这份合约就凭空消失。

(合约为什么能被"约定"出来、标准化解决了什么问题,《期货到底是什么》讲过。)

一句话:

股票的成交是转手,期货的成交可以是创造,也可以是销毁。

持仓量(Open Interest),就是当下还活着、还没被平掉的合约总数。

它有个很多人没意识到的性质:每一手持仓的背后,永远是一个多头和一个空头。没有例外——你要开多,必须有人愿意开空来接。

所以多头的总持仓永远等于空头的总持仓,一手不多一手不少。这也是《期货 vs 股票》里说的"你赚的每一分钱都来自另一个具体的人"在数字上的样子。

由此得到本篇的第一句结论:

持仓量不是有多少人看多,是有多少人还没和解。


二、一笔成交,四种组合,三种结果

这一节是全篇的机制内核,看懂了后面全部通顺。

任何一笔成交都有买方和卖方。而在期货里,买和卖各自还要再分一次——你这一笔是"开仓"还是"平仓"。国内下单界面上开仓和平仓是两个不同的按钮,这不是多此一举:它决定了这笔成交对市场的意义完全不同。

于是一笔成交有四种组合:

买方卖方成交量持仓量发生了什么
开仓开仓+1+1一份新合约被创造出来
开仓平仓+1不变多头换人,合约还在
平仓开仓+1不变空头换人,合约还在
平仓平仓+1−1一份合约被注销

请盯住这张表看三秒钟。它说的是:

成交量在四种情况下都增加,持仓量却有三种走向。

这就是为什么"放量"在期货里什么都说明不了——它是四件完全不同的事共用的一个数字。

而持仓量的变化,指向的东西很具体:

  • 增加 → 净新开仓,未了结的合约变多,有新钱进来对赌
  • 减少 → 净平仓,有人在了结离场,市场在缩小
  • 不变、成交量却很大 → 全是换手,钱在原地转圈,总规模没动

于是有了本篇最该记住的一句话:

成交量告诉你有多少人在换手,持仓量告诉你有多少人还没走。

(顺带一句:国内平仓还分"平今""平昨",手续费经常差出十几倍。两者对持仓量的影响完全一样,对你账单的影响不一样——那是手续费那篇的事。)


三、开始用之前,四个口径的坑

和 ATR 那篇第三节一样,这一节讲的是"同一个名字,不同的数"。这四个坑的共同点是:栽了你不知道自己栽了。

① 单边还是双边

一手持仓,多空各占一边。那这算"1 手"还是"2 手"?

国内现在统一是单边口径:六家交易所公布的成交量与持仓量,一手持仓记 1 手,不是 2 手。交易所日行情和主流行情软件上的数,默认都是这个。(以各交易所官网的数据说明为准。)

要留神的是数据源:第三方数据商、以及一些年头较久的历史数据,口径不一定和现在一致。

后果:口径差一倍,你所有基于绝对量的横向比较、以及第四节那个换手速度比值,全都要打对折或翻倍——而且这种错不会报错,只会让你算出一个看起来很合理的数。换数据源之前先确认口径,查一次管很久。

② 单个合约的持仓量 ≠ 这个品种的持仓量

这是本节最实用的一条。

软件默认显示的是当前这份合约的持仓量,而"这个品种一共有多少未平仓合约"要把所有月份加起来。

平时两者同涨同跌,看哪个都行。但在移仓换月那几天,它们会朝相反的方向跑:新合约的持仓量在暴涨,旧合约的在暴跌,而品种总持仓量可能几乎没动——因为根本没有新钱,只是同一批人从一份合约挪到了另一份。移仓换月那篇讲了那几天在发生什么,这里补上它在数据上长什么样。

做法:判断"有没有新钱进这个品种"看全合约加总,判断"这份合约还能不能玩"才看单合约。只盯主力那一个数,你会在移仓期看到一场根本不存在的资金大戏。

③ 盘中看到的持仓量,不是最终的数

成交量实时累加,收盘就定了。持仓量不一样——要等交易所结算之后才是准数,盘中跳动的那个值是滚动估算。还有个更容易忽略的:夜盘的成交归属下一个交易日,夜盘里持仓量的变化会记在明天的账上(《量化研究的标准工作流》第二节讲数据时点时说过)。

做法:做研究用收盘后的结算数据,别用盘中快照。

④ 主连的量和持仓量,同样是拼出来的

主连上的成交量、持仓量序列和价格序列一样,是把历次主力各截一段接起来的。接缝那天持仓量会断崖式跳跃——上一次讲主连的时候说过,这个跳不是市场跳的。

用主连算"持仓量变化率"这类指标,接缝那几天的值全是废的,而且它不会报错。


四、它没有参数,但有一个比值

成交量和持仓量都是原始数据,没有像 ATR 的 n 那样的参数可调。但它们的比值很好用:

换手速度=成交量持仓量\text{换手速度} = \frac{\text{成交量}}{\text{持仓量}}

它回答的是:这个市场里的钱,平均待多久。

  • 比值高 → 大量单子当天进当天出,日内短线资金主导
  • 比值低 → 大家开了仓就放着,持仓型资金主导

它无量纲,所以能跨品种、跨时间比——这点很关键,因为成交量和持仓量的绝对值跨品种毫无可比性(一个品种一天一百万手,另一个一天几千手,比大小没有意义)。

⚠️ 别把它叫成"换手率"。 股票的换手率有个固定分母——流通股本。期货没这个东西,持仓量本身每天都在变。所以这个比值只能做相对比较,不能解读成"百分之多少的筹码换了手"。


五、三个用法(按价值排序)

5.1 用法一:选合约时,两个量各看一半

讲主力合约那篇给过一条规矩:只做成交量排在前列的合约。这里补一句为什么光看成交量不够。

两个量回答的是两个不同的问题:

它回答的问题
成交量我现在下单,能不能成交?多久能成交?
持仓量这份合约还有多少人扛着?明天还有没有人陪我玩?

差别在合约临近到期时露出来。那几天旧合约的成交量可能还很大——因为一堆人在集中平仓,而平仓也是成交。但它的持仓量已经在崩塌,愿意扛着这份合约过夜的人正在飞速消失。

只看成交量,你会以为它还热闹,然后进去、过夜、第二天发现盘口薄得吓人。

成交量决定你能不能进出,持仓量决定你敢不敢过夜。

5.2 用法二:判断移仓时点——一个和直觉相反的实测结果

移仓那篇里我说过:盯着新旧两份合约的量,看到交叉就动手。当时留了个尾巴——到底看哪个量的交叉?

流传最广的说法是"看成交量交叉"。我不太信,所以拉了数据实测。

做法:取一批品种历史上相邻的两任主力合约各构成一对,分别找出新合约的成交量、持仓量持续反超旧合约的那一天,看谁先到。注意"持续"两个字:某天反超一下不算数,那多半是噪音;要的是"从这天起再没被反超回去"的起点(代码见第七节的 stable_cross)。

样本:六大交易所的 36 对主力切换(公开日线数据,2026 年 8 月 4 日拉取,二手源,仅作观察用)。

结果:持仓量先交叉 31 对,同一天 2 对,成交量先交叉 3 对。持仓量领先的中位数是 2 个交易日,最长 8 个;三个反例里成交量最多领先 4 个。

方向想通之后觉得理所当然:搬家的人,是先把行李搬过去的。 持仓量交叉说明扛货过夜的钱已经把重心挪到了新合约;而旧合约上迟迟不散的成交量,很大一部分是日内进出的短线单——当天开当天平,制造大量成交,却不留下任何持仓。

钱搬完的时候,热闹还留在原地。

但这个结论要打三个折

我很想把这一节写成"实测证明该看持仓量"。数据不支持我这么写:

① 有 3 个反例。 这是个倾向,不是规律——你具体的这一次,可能就是那三个之一。

② 领先幅度比想象中小。 中位数只有 2 个交易日,意味着大多数时候看哪个量差别不大。真正差得多的是少数几对,而你没法提前知道自己是哪一种。

③ 样本很小。 36 对、一次取数、一个二手数据源,只够说明"方向大致成立"。

那它还有什么用? 它让"该看成交量交叉"这个流传最广的说法失去了数据支持;而且它和移仓宁早勿晚同向——既然两个信号差距不大,选早的那个几乎不花你什么成本。

结论一句话:两个都看,以先到的那个为准。你要的是"别拖",不是精确择时。第七节的代码能让你在自己的品种上重跑一遍,那比记住我的 31 比 3 有用得多。

5.3 用法三:看这个市场在变大还是变小

把品种的全合约持仓量拉成一条曲线,看到的是这个市场的规模变化:持续上升说明新的对赌在不断产生,持续萎缩说明大家在陆续了结。

注意这里说的全是"规模",不是"方向"。 至于持仓量的变化配合价格涨跌怎么读——那是一张有名的四象限表,是《米粒指标》后面专门的一篇,本篇刻意不碰。原因下一节第一条就会说清楚。


六、失效场景(这一节请比上一节读得更用力)

① 头号误用:持仓量没有方向

再说一遍第一节那句话:每一手持仓的背后,永远是一个多头和一个空头。

所以当你看到"增仓 5 万手"的时候,真实发生的事情是:

有 5 万手的人认为它会涨,同时有 5 万手的人认为它会跌。

"增仓"这两个字天然带着一股看涨的暗示,但它描述的是双方。 拿持仓量增加当买入理由,是这个数字被误用得最多、也最贵的方式。

持仓量测的是分歧的规模,不是分歧的胜负。

② 它不告诉你"是谁"

产业客户的套保盘、CTA 的趋势仓、散户的隔夜单,在这个总数里长得一模一样。而这三种钱的逻辑完全不同——套保盘不在乎浮亏,趋势仓有止损纪律,散户会扛。同样是"增仓 5 万手",谁增的意义天差地别。

想知道是谁,得看席位和大户持仓数据,那是另一套东西,值得单开一篇。别逼持仓量回答它答不了的问题。

③ 持仓量的下降,不一定是自愿的

有几种情况持仓量在掉,却和"市场情绪"毫无关系:临近交割月制度在赶人(保证金一层层加、持仓限额一档档收紧,《保证金制度》那篇第三节讲过这套四层加码,意图就是把不打算交割的人挤出去)、极端行情下的强制平仓(那不是了结,是被清出去的)、交易所的临时风控措施。

把制度造成的减仓读成"资金撤退",你读到的是规则,不是市场。

④ 它是结果,不是原因,而且滞后

持仓量是结算之后才有的数。它的价值在于确认已经发生了什么,不是预测将要发生什么——这一点上它和 ATR 同类:描述过去,不预告未来。

⑤ 移仓期的数据全脏

第三节 ② 和 ④ 在移仓那几天会同时发作:单合约的持仓量剧烈失真,主连上的序列还有接缝。这是全年最不该拿这两个量下判断的几天,偏偏也是最多人盯着看的几天。

⑥ 冷清合约上,两个量都是噪音

一天成交几十手的合约,百分比变化可以大得离谱——分母太小,一个大户挪个仓就能让数字翻倍。所有基于变化率的判断,在流动性差的合约上一律失效。


七、代码

老规矩,计算逻辑写成纯函数,不绑定任何数据源。你只要有一张带 date / volume / hold 三列、按时间升序的表就能用。

import pandas as pd

def oi_change(df: pd.DataFrame) -> pd.DataFrame:
    """持仓量的日变化与变化率。df 需含 volume(成交量)、hold(持仓量)。"""
    out = df.copy()
    out["oi_chg"] = out["hold"].diff()
    out["oi_pct"] = out["hold"].pct_change() * 100
    return out

def turnover_speed(df: pd.DataFrame) -> pd.Series:
    """换手速度 = 成交量 / 持仓量。无量纲,可跨品种比较。
    注意:这不是股票意义上的换手率,分母每天都在变。"""
    return df["volume"] / df["hold"].replace(0, pd.NA)

def stable_cross(cond: pd.Series):
    """找出条件"从此以后一直成立"的第一天。

    用于移仓交叉判定:只有一天反超不算数(可能是噪音),
    要的是"此后再没被反超回去"的那个起点。
    cond 是布尔序列,索引为日期。
    """
    once_true_forever = cond[::-1].cummin()[::-1]      # 从后往前取最小值
    hits = once_true_forever[once_true_forever].index
    return hits.min() if len(hits) else None

def roll_cross(old: pd.DataFrame, new: pd.DataFrame):
    """比较新旧两份合约,返回成交量与持仓量各自的持续反超日。

    old / new: 以 date 为索引,含 volume、hold 两列。
    """
    j = old.join(new, lsuffix="_old", rsuffix="_new", how="inner").dropna()
    j = j[(j["volume_old"] > 0) & (j["volume_new"] > 0)]
    return {
        "vol_cross": stable_cross(j["volume_new"] > j["volume_old"]),
        "oi_cross":  stable_cross(j["hold_new"]   > j["hold_old"]),
    }

取数据(AKShare 的单合约日线,接口名与列名可能随版本变化,以官方文档为准):

import akshare as ak

def load(symbol: str) -> pd.DataFrame:
    d = ak.futures_zh_daily_sina(symbol=symbol)      # 返回列含 volume、hold
    d["date"] = pd.to_datetime(d["date"])
    return d.set_index("date")[["volume", "hold", "close"]]

print(roll_cross(load("rb2605"), load("rb2610")))

⚠️ 注意这里取的是"具体合约",不是主连。 第三节 ④ 说过原因:主连的量和持仓量序列在接缝处是断的,拿它做这个计算,结果没有意义。

另外,AKShare 拿到的是数据商整理过的公开数据,属于二手源。做严肃研究请以交易所官网公布的日行情为准,两边的口径(尤其单边/双边)先对一次。


八、三个你该自己跑一遍的实验

代码就在上面,跑一遍你会记一辈子。

实验一:在你做的品种上重跑移仓交叉

取你在做的品种历史上相邻的两任主力合约,跑一次 roll_cross。

你要看的:持仓量交叉是不是也在前面,以及在你这个品种上差几天。这个数字对你的价值远大于我给的中位数——你要移的是你的仓。

实验二:单合约持仓量 vs 品种总持仓量

把主力合约的持仓量、和该品种全部合约持仓量之和画在同一张图上,重点看移仓那几天。

你会看到:单合约那条线剧烈起伏,总量那条线相对平缓。

结论:你以为的"资金大举进场/撤退",很大一部分是合约之间的搬家,不是钱进出这个市场。

实验三:换手速度的跨品种排序

挑十来个品种各算一条 turnover_speed,取近一年均值排序。

你会看到:这个比值在品种之间差距很大,而且相当稳定。

结论:不同品种住着不同的钱。 比值高的地方是日内资金的地盘,你拿一套隔夜策略进去,对手盘和你想象的不是一批人。


九、三句话结论

1. 成交量测热闹,持仓量测规模。 一笔成交可能是创造合约、注销合约或纯换手,成交量把这三件事记成同一个数——只有持仓量能把它们分开。

2. 持仓量没有方向。 每多一手持仓,就多一个赌涨的和一个赌跌的。它测的是分歧有多大,不是谁会赢。

3. 移仓时两个量都看,以先到的那个为准。 实测里持仓量领先的居多,但幅度不大、还有反例——所以别去赌哪个更准,取早的那个,反正你要的只是"别拖"。


一粒米想知道潮水往哪儿去,光听浪声不够,得看沙滩上还剩多少脚印。

下一篇:回到《米粒识期》,讲每日无负债结算——为什么你昨天还赚着,今天就爆了。这是前面好几篇都欠着的一笔账。


⚠️ 风险提示 本文仅为期货知识分享与研究交流,不构成任何投资建议。文中的统计结果基于有限样本的历史数据, 历史统计不代表未来表现,也不构成对任何一次移仓时点的建议。期货交易具有高杠杆特性, 可能导致本金全部损失甚至产生穿仓负债。文中涉及的持仓量统计口径、结算时点、保证金与持仓限额 等规则以各期货交易所官方最新公告为准,数据口径以各数据源的说明为准。请通过正规期货公司开户, 理性参与、独立决策、风险自担。

本文首发于微信公众号「米粒论期」 · 阅读原文

免责声明:本文仅供学习参考,不构成任何投资建议。期货交易存在风险,入市需谨慎。

本文涉及

文中提到的概念、品种和书目,都能在站内查到。

沪ICP备2026050790号-1