请问如何获取某个股票在某一天内的涨停特征?
最近在做涨停相关研究,日内首次涨停时间/末次涨停时间/开板次数这几个是比较重要的特征,请问在聚宽有办法获取这些信息吗?
问题描述
解决方案
在聚宽(JoinQuant)平台上,要精确获取股票日内的首次涨停时间、末次涨停时间以及开板次数,最准确的方法是结合日线数据(获取当天的涨停价)和 Tick 数据(获取微观的盘口价格变化)来进行统计。
由于分钟线(1m)可能会掩盖一分钟内发生的瞬间开板和回封,因此强烈建议使用 get_ticks 接口来提取这些特征。
实现思路
- 获取涨停价:使用
get_price获取目标股票在目标日期的high_limit(涨停价)。 - 获取高频数据:使用
get_ticks获取目标股票在目标日期的所有 Tick 数据。 - 状态机统计:遍历 Tick 数据,维护一个
is_limit_up(是否处于涨停状态)的布尔变量。- 当价格首次达到涨停价时,记录首次涨停时间,并将状态设为
True。 - 只要价格等于涨停价,就不断更新末次涨停时间。
- 当状态为
True且最新价格跌破涨停价时,说明发生了开板,开板次数加 1,并将状态设为False。
- 当价格首次达到涨停价时,记录首次涨停时间,并将状态设为
Python 代码实现
您可以将以下代码直接复制到聚宽的**研究环境(Jupyter Notebook)**中运行和测试:
from jqdata import *
import pandas as pd
def get_limit_up_features(security, date):
"""
获取指定股票在指定日期的涨停特征
:param security: 股票代码,如 '000001.XSHE'
:param date: 日期字符串,如 '2021-01-05'
:return: dict 包含涨停特征,如果没有触及涨停则返回 None
"""
# 1. 获取当天的涨停价
df_day = get_price(security, start_date=date, end_date=date, frequency='daily', fields=['high_limit'], panel=False)
if df_day.empty:
return None
high_limit = df_day['high_limit'].iloc[0]
# 2. 获取当天的 Tick 数据
start_dt = f"{date} 09:15:00"
end_dt = f"{date} 15:00:00"
# skip=False 保留所有盘口变化的 tick,确保不漏掉瞬间开板
ticks = get_ticks(security, start_dt=start_dt, end_dt=end_dt, fields=['time', 'current'], skip=False, df=True)
if ticks.empty:
return None
# 初始化特征变量
first_limit_up_time = None
last_limit_up_time = None
open_board_count = 0
is_limit_up = False
# 3. 遍历 Tick 数据进行统计
for index, row in ticks.iterrows():
current_price = row['current']
current_time = row['time']
# 考虑到浮点数精度问题,使用 round 比较
if round(current_price, 2) >= round(high_limit, 2):
if not is_limit_up:
is_limit_up = True
if first_limit_up_time is None:
first_limit_up_time = current_time
# 只要在涨停价,就更新末次涨停时间
last_limit_up_time = current_time
else:
# 如果当前处于涨停状态,但价格掉下来了,说明开板
if is_limit_up:
is_limit_up = False
open_board_count += 1
# 如果全天未触及涨停,返回 None
if first_limit_up_time is None:
return {
'security': security,
'date': date,
'is_limit_up_touched': False
}
# 格式化 Tick 的时间戳 (聚宽的 tick time 格式为 float: YYYYMMDDHHMMSS.0)
def format_tick_time(t):
if pd.isna(t) or t is None:
return None
return pd.to_datetime(str(int(t)), format='%Y%m%d%H%M%S')
return {
'security': security,
'date': date,
'high_limit': high_limit,
'is_limit_up_touched': True,
'first_limit_up_time': format_tick_time(first_limit_up_time),
'last_limit_up_time': format_tick_time(last_limit_up_time),
'open_board_count': open_board_count
}
# ================= 测试用例 =================
# 假设我们要查询某只股票在某天的涨停情况
# 请替换为您已知当天涨停的股票代码和日期进行测试
features = get_limit_up_features('000001.XSHE', '2015-04-13')
print(features)
注意事项与优化建议
- Tick 数据的获取限制:
get_ticks接口每次获取的数据量较大。如果您需要大批量计算全市场所有股票的历史涨停特征,直接循环调用get_ticks可能会非常耗时。建议先通过日线数据(high == high_limit)筛选出当天触及过涨停的股票池,然后再针对这些股票请求 Tick 数据。 - 浮点数精度:在比较价格时,由于 Python 浮点数的特性,建议使用
round(price, 2)来与high_limit进行比较,避免因为9.9999999和10.00的微小差异导致判断失败。 - 集合竞价:
get_ticks包含了 09:15~09:25 的集合竞价数据。如果您只关心连续竞价期间(09:30 之后)的涨停和开板,可以在遍历前将ticks数据过滤,例如ticks = ticks[ticks['time'] >= float(date.replace('-', '') + '093000')]。 - 分钟线替代方案:如果您的研究对精度要求没有那么苛刻(允许忽略 1 分钟内的瞬间开板),可以使用
get_price(..., frequency='1m')替代get_ticks,这会大幅提升数据获取和计算的速度。