问题描述
解决方案
在 QMT (Quantitative Trading Platform) 中,获取股票的最新流通股本并计算换手率主要有两种方式:一种是直接调用平台提供的换手率计算接口,另一种是通过获取流通股本和成交量手动计算。
以下是详细的说明和代码实现。
方法一:使用 get_turnover_rate 直接获取(推荐用于历史回测)
QMT 提供了直接获取换手率的 API ContextInfo.get_turnover_rate,该函数会自动处理历史股本变动,非常适合回测和获取历史区间的换手率数据。
方法二:手动计算(推荐用于实时监控)
如果您需要基于最新的盘口数据实时计算,或者需要特定的计算逻辑,可以通过以下步骤实现:
- 使用
ContextInfo.get_last_volume(stockcode)获取最新流通股本。 - 使用
ContextInfo.get_market_data_ex(...)获取当前成交量。 - 计算公式:
换手率 = 成交量 / 流通股本。
策略代码示例
以下代码展示了如何在 QMT 中同时使用这两种方法。
# -*- coding: gbk -*-
import pandas as pd
def init(ContextInfo):
# 设置股票池,以浦发银行为例
ContextInfo.stock = '600000.SH'
ContextInfo.set_universe([ContextInfo.stock])
# 设置账号(仅作示例,非必须)
ContextInfo.account_id = 'test_account'
def handlebar(ContextInfo):
# 获取当前主图的股票代码
stock_code = ContextInfo.stock
# -------------------------------------------------------
# 方法一:使用 get_turnover_rate 直接获取 (适用于获取历史区间)
# -------------------------------------------------------
# 获取当前K线的时间
current_time = ContextInfo.get_bar_timetag(ContextInfo.barpos)
# 将时间戳转换为字符串格式 YYYYMMDD
date_str = timetag_to_datetime(current_time, '%Y%m%d')
# 获取当天的换手率数据
# 注意:get_turnover_rate 返回的是 DataFrame
turnover_df = ContextInfo.get_turnover_rate([stock_code], date_str, date_str)
if not turnover_df.empty:
# 获取对应股票和日期的换手率
# 数据结构通常 index 为日期,columns 为股票代码
try:
api_turnover = turnover_df.at[date_str, stock_code]
print(f"[{date_str}] API获取换手率: {api_turnover:.4f}%")
except Exception as e:
print(f"API数据解析异常: {e}")
# -------------------------------------------------------
# 方法二:手动计算 (适用于实时计算或自定义逻辑)
# 公式:换手率 = 成交量 / 流通股本
# -------------------------------------------------------
# 1. 获取最新流通股本 (单位:股)
# get_last_volume 获取的是最新的流通股本数据
last_volume = ContextInfo.get_last_volume(stock_code)
# 2. 获取当前周期的成交量
# 使用 get_market_data_ex 获取最新一根Bar的数据
# 注意:period='1d' 表示日线,如果是分钟线则计算的是分钟换手率
market_data = ContextInfo.get_market_data_ex(
fields=['volume'],
stock_code=[stock_code],
period='1d',
count=1,
dividend_type='none'
)
if stock_code in market_data and not market_data[stock_code].empty:
# 获取最新一根K线的成交量 (单位:股)
current_vol = market_data[stock_code].iloc[-1]['volume']
# 3. 计算换手率
if last_volume > 0:
# 换手率通常以百分比表示
manual_turnover = (current_vol / last_volume) * 100
print(f"[{date_str}] 手动计算换手率: {manual_turnover:.4f}% (成交量: {current_vol}, 流通股本: {last_volume})")
else:
print(f"[{date_str}] 流通股本数据异常,无法计算")
print("-" * 30)
关键函数解析
-
ContextInfo.get_last_volume(stockcode)- 功能:获取指定股票的最新流通股本。
- 返回值:
number(浮点数),单位为股。 - 注意:此函数返回的是当前最新的流通股本。如果在回测非常久远的历史数据,且该股票历史上发生过较大的股本变动(如增发、回购),直接使用“最新”股本计算历史换手率可能会有偏差。对于严格的历史回测,建议使用
get_turnover_rate或通过get_financial_data获取历史财务数据中的股本结构。
-
ContextInfo.get_turnover_rate(stock_list, startTime, endTime)- 功能:获取指定时间段内的换手率。
- 参数:
stock_list: 股票代码列表。startTime: 开始时间 (格式 'YYYYMMDD')。endTime: 结束时间 (格式 'YYYYMMDD')。
- 返回值:
pandas.DataFrame。
-
ContextInfo.get_market_data_ex(...)- 功能:获取行情数据。
- 参数:
fields=['volume']用于获取成交量。 - 注意:QMT 中的成交量
volume单位通常为股(股票)或手(期货),计算时需确保分子分母单位一致。
Q&A
Q: get_last_volume 获取的是总股本还是流通股本?
A: get_last_volume 获取的是流通股本。如果需要获取总股本,可以使用 ContextInfo.get_total_share(stockcode)。
Q: 为什么手动计算的换手率和行情软件上看到的不完全一致?
A: 可能原因有二:
- 股本数据差异:行情软件可能使用的是实时更新的股本,而本地数据可能存在滞后,或者对于“流通股本”的定义(是否包含限售流通股等)略有不同。
- 成交量单位:确保成交量是“股”而不是“手”。QMT 的股票
volume字段通常是股数,但需注意确认。
Q: 如何获取历史某一天的准确流通股本?
A: 如果需要历史某时刻的精确股本(而非最新),应使用财务数据接口 ContextInfo.get_financial_data,读取 CAPITALSTRUCTURE 表中的 circulating_capital(已上市流通A股)字段,并配合 report_type 参数来匹配当时的报告期。