股票关联的概念是老标签还是新叙事:get_stock_concept_heat 首末提及时间的 10 个问答
摘要
熔岩(Lava)概念板块热度有两个方向:「概念 → 个股」由 get_concept_stock_heat(/concepts/stocks)负责,「个股 → 概念」由 get_stock_concept_heat(GET /concepts/by-stock)负责。后者对一只股票返回它在回看期内关联的各个概念,以及每个概念被提到几次、第一次和最近一次被提到的时间、有多少机构/大V 提到。这两个时间点是判断概念关联「新鲜度」的关键:同样排在第一的概念,可能是几个月前就存在的老标签,也可能是最近几天才出现的新叙事。本文用 10 个问答讲清参数、时间字段的读法、新鲜度分档方法以及与其他熔岩数据板块的配合。文中数字均为示例,分档结果是描述性标签。
一、接口速查
| 项目 | 内容 |
|---|---|
| HTTP 路径 | /concepts/by-stock |
| MCP 工具 | get_stock_concept_heat |
| 股票标识 | ts_code(如 300750.SZ)或 stock_name,二选一 |
days |
回看天数,默认 90,范围 1~365 |
limit |
返回条数,默认 30,最大 200 |
| 每行内容 | 概念名、被提到次数、第一次被提到时间、最近一次被提到时间、机构/大V 数 |
| 计费 | 每次 0.005 元,非 2xx 不计费 |
每行字段的具体列名以 OpenAPI 为准;下文为了表述方便,把两个时间记作「首提时间」与「最近时间」,把计数记作 mentions 与 agencies。
二、参数类问答
Q:days 默认 90,和概念成分排行的默认 30 为什么不同?
A:两个接口回答的问题不同。/concepts/stocks 关注某概念「最近谁被提得多」,默认 30 天;/concepts/by-stock 关注一只股票「挂了哪些概念」,需要更长的回看才能看到完整的概念画像,默认 90 天。两者 days 都可以显式指定,引用结果时写上取值即可。
Q:limit 默认 30 够用吗?
A:对大多数股票够用;被广泛讨论的股票可能关联上百个概念。如果目的是做新鲜度分档,建议 limit=200,否则排在 30 名以后的新概念可能被截掉——新概念初期提及数少,恰恰最容易排在后面。
Q:用 stock_name 还是 ts_code?
A:优先 ts_code。简称可能变更或重名,代码可以直接与自有行情、行业数据关联。
三、时间字段类问答
Q:「首提时间」是这个概念第一次和该股关联的时间吗?
A:应理解为回看期内第一次被提到的时间。若 days=90,一个一年前就存在的老概念,首提时间也会落在 90 天窗口的起点附近。要区分「真正的新概念」和「回看期起点的老概念」,用较大的 days(例如 365)再取一次:两次首提时间都很近的,才是近期新出现的关联。
Q:「最近时间」能说明什么?
A:说明这个关联最近是否仍在被讨论。首提时间早、最近时间也近,是持续活跃的老标签;首提时间早、最近时间很久以前,是已经沉寂的标签。最近时间与调用时刻的差,可以用响应里的 meta.server_time(带 +08:00)计算。
Q:两个时间的时区是什么?
A:熔岩消息面记录的时间为北京时间。入库时统一标注为 Asia/Shanghai,计算时间差前先确认两个时间戳都已带时区,避免与 UTC 时间混算。
Q:首提时间与 /hot/first-mentions 的「首次被提到」是同一回事吗?
A:不是。首提流 /hot/first-mentions(get_first_mention_stocks)的口径是股票在此前 7 天一次都没被提过、在最近 hours 小时内(默认 24,最多 72)首次被提到,返回 first_time、首提主体的 agency_id 与分数;而 /concepts/by-stock 的首提时间是股票与某个概念的关联在回看期内第一次出现。前者描述股票本身是否「新冒头」,后者描述概念标签是否「新贴上」。日频面板 /panel/daily 的 is_first_mention_day 又是按自然日标记的股票级口径,三者不要混用。
四、新鲜度分档示例
把首提时间与最近时间换算成「距调用时刻的天数」,可以给每个概念打一个描述性标签。以下为示例阈值与示例读数:
| 概念(示例) | mentions |
agencies |
首提距今(天) | 最近距今(天) | 标签 |
|---|---|---|---|---|---|
| 概念甲 | 412 | 96 | 88 | 0 | 持续活跃 |
| 概念乙 | 37 | 14 | 4 | 0 | 新近出现 |
| 概念丙 | 65 | 22 | 85 | 41 | 已沉寂 |
| 概念丁 | 9 | 3 | 2 | 1 | 新近出现,样本小 |
分档规则(示例阈值,可按研究需要调整):
新近出现:首提距今 <= 7 天(且用 days=365 复核后仍 <= 7 天)
持续活跃:首提距今 > 30 天,最近距今 <= 3 天
已沉寂: 最近距今 > 30 天
其他: 记为「中间状态」,不强行归类
样本小: agencies < 5 时附加此标记
# freshness.py —— 示例,地址与令牌为占位
import os, requests, pandas as pd
BASE = os.environ.get("LAVA_BASE", "<YOUR_LAVA_BASE>/subscribe/v1")
H = {"Authorization": "Bearer " + os.environ.get("LAVA_API_KEY", "<YOUR_TOKEN>")}
def by_stock(code, days):
r = requests.get(BASE + "/concepts/by-stock",
params={"ts_code": code, "days": days, "limit": 200},
headers=H, timeout=60).json()
assert r["ok"], r["code"]
rows = r["data"] if isinstance(r["data"], list) else r["data"].get("list", [])
return pd.DataFrame(rows), pd.Timestamp(r["meta"]["server_time"])
d90, now = by_stock("<CODE>", 90)
d365, _ = by_stock("<CODE>", 365)
# 概念名与两个时间的列名以 OpenAPI 为准,这里假设为 concept / first_time / last_time
m = d90.merge(d365[["concept", "first_time"]], on="concept", suffixes=("", "_365"))
for c in ("first_time", "last_time", "first_time_365"):
m[c + "_age"] = (now - pd.to_datetime(m[c]).dt.tz_localize("Asia/Shanghai")).dt.days
两次调用计费两次。若时间字符串已带时区,把 tz_localize 换成 tz_convert。
五、与其他板块配合的问答
Q:一个「新近出现」的概念,下一步查什么?
A:先用 get_market_hot_concepts(/hot/concepts)看该概念在全市场是否也在热榜上;再用 get_concept_stock_heat(/concepts/stocks,concept 精确匹配、≤30 字符)看该概念下还有哪些股票被提到。如果只有这一只股票在讨论该概念,标签更可能是个股层面的叙事。
Q:能用这个接口做历史回测吗?
A:它返回的是从调用时刻往回的统计,不带 as_of_date 参数,无法还原历史某一天的概念画像。需要日频历史时,用 /panel/daily 的 type=concept(names 传概念名)取概念层面的自然日序列,并注明口径不同。
Q:概念名可以直接传给其他接口吗?
A:可以,而且推荐这样做。/concepts/by-stock 返回的概念名就是标准名,直接作为 /concepts/stocks 的 concept 或 /panel/daily 的 names 传入,可以避免手写别名导致的精确匹配失败。
熔岩站点的个股概念查询工具页提供了同一方向(个股 → 概念)的只读展示,适合人工查看一只股票的概念画像;需要做新鲜度分档、批量或落库时,再用上面的接口复现。
六、常见误读对照表
| 误读 | 实际口径 | 规范写法(示例) |
|---|---|---|
| 「概念乙首提距今 4 天,所以是这只股票的新概念」 | 首提时间只在回看期内成立 | 「days=90 与 days=365 两次取数,首提均在 4 天内」 |
| 「概念甲提及最多,所以它是这只股票的主题」 | 提及多可能来自长期累积 | 「90 天回看内概念甲 mentions=412,最近距今 0 天」 |
| 「概念丙最近距今 41 天,说明关联已经失效」 | 只说明回看期内最近一次被提到在 41 天前 | 「概念丙近 41 天无新提及」 |
| 「两只股票都挂了概念甲,所以它们会同步变化」 | 概念关联只描述讨论中的共现 | 「两只股票在回看期内都与概念甲共现」 |
「limit=30 没返回的概念就不存在」 |
只是排在前 30 名之外 | 「limit=200 下复核」 |
误读的共同来源是省略了 days、limit 和时间基准。只要写清这三项,读者就能判断标签的适用范围。
七、落库字段与复核节奏
为了让新鲜度标签可以追溯,建议每次保存:
- 请求参数:
ts_code、days、limit; - 响应元数据:
meta.server_time、meta.request_id,以及计费字段meta.billing.charged_yuan; - 每行:概念名、
mentions、agencies、首提时间、最近时间; - 本地计算列:首提距今天数、最近距今天数、
days=365复核结果、标签与是否样本小。
复核节奏可以按研究用途决定:对固定观察列表做周度快照即可看到标签迁移,例如某概念从「新近出现」变为「持续活跃」或「已沉寂」;盘中不需要高频调用,因为概念画像是长回看统计,短时间内变化很小。把相邻两次快照按概念名对齐,统计新增、消失和标签变化的数量,就是一张简单的概念画像变更表。
需要注意,概念画像变更表记录的是讨论中的共现关系变化,不代表公司业务或分类的变化;涉及行业归属的问题,仍以自有的行业分类数据为准。
八、用消息面记录抽样核对
分档只基于计数与时间。想看「新近出现」的概念具体是在什么语境下与股票共现,可以用个股消息面 get_stock_news_heat(/opinions)取同一只股票最近几天的记录。每条记录带 topic_time、agency_id、agency_score、stocks、concepts、summary(≤120 字)和 detail(≤600 字),在本地筛出 concepts 中包含该概念名的记录,按 topic_time 排序抽样阅读 summary 即可。
r = requests.get(BASE + "/opinions",
params={"ts_code": "<CODE>", "days": 7, "limit": 200},
headers=H, timeout=60).json()
assert r["ok"], r["code"]
data = r["data"]
recs = data.get("list", []) if isinstance(data, dict) else data
hit = [x for x in recs if "<概念标准名>" in (x.get("concepts") or [])]
print(len(hit), [x["topic_time"] for x in hit[:5]])
抽样核对有两个用途:确认新概念的共现不是少数主体的重复表达(可按匿名 agency_id 计数),以及确认首提时间附近确实存在相关记录。/opinions 的 days 最大 90,记录受 limit 截断,条数等于 200 时应缩短区间。核对结果仍然只记录事实,不把摘要内容改写为结论。
结论
get_stock_concept_heat 的价值不只在于「哪个概念提及最多」,更在于每个概念的首提时间与最近时间。用较长的 days 复核首提时间、用 meta.server_time 计算距今天数、给小样本附加标记,就能把一只股票的概念关联区分为持续活跃、新近出现和已沉寂三类,并与概念热榜、概念成分排行和日频面板衔接成完整的只读研究流程。
数据来自熔岩消息面热度监测,仅供研究参考,不构成投资建议。
Comments
Join the discussionNo comments yet. Be the first to comment.