QMT量化交易实战:用Python脚本一键获取你的股票持仓明细(含完整代码)
·
QMT量化交易实战:用Python脚本一键解析股票持仓数据
每次打开交易软件手动翻看持仓明细,总有种被数据淹没的无力感。作为量化交易者,我们需要的是清晰、可编程的持仓数据视图。本文将手把手教你用QMT平台的Python接口,打造专属持仓分析工具——从API调用到盈亏计算,完整代码可直接套用。
1. 环境准备与基础配置
在开始编写持仓查询脚本前,需要确保QMT客户端已正确安装并登录交易账户。打开QMT后,点击右上角的"Python"按钮进入策略编辑界面。这里建议新建一个专门用于数据查询的文件夹,与交易策略文件分开管理。
QMT的Python环境已预装必要依赖库,但我们仍需导入几个关键模块:
import pandas as pd
from datetime import datetime
import matplotlib.pyplot as plt # 用于后续可视化
账户信息配置技巧 :
- 主账户通常以大写字母"A"开头
- 信用账户则以大写字母"C"开头
- 模拟账户前缀可能因券商而异,常见有"S"或"M"
注意:账户字符串必须用单引号包裹,且严格区分大小写。错误的账户格式会导致
get_trade_detail_data返回空列表。
2. 核心API函数深度解析
get_trade_detail_data 是QMT获取持仓数据的瑞士军刀,其完整参数结构如下:
datas = get_trade_detail_data(
account_id, # 交易账户
asset_type, # 资产类型:'stock'/'fund'/'bond'等
query_type, # 查询类型:'position'/'entrust'/'deal'
stock_code=None, # 可选参数,指定证券代码
start_date=None, # 可选参数,查询起始日
end_date=None # 可选参数,查询结束日
)
2.1 参数组合实战案例
场景一 :查询股票持仓全量数据
positions = get_trade_detail_data('A123456789', 'stock', 'position')
场景二 :查询指定股票持仓
tsla_position = get_trade_detail_data(
'A123456789',
'stock',
'position',
stock_code='600519.SH'
)
字段映射表 :
| API返回字段 | 业务含义 | 数据类型 | 示例值 |
|---|---|---|---|
| m_strInstrumentID | 证券代码 | str | '600519' |
| m_strExchangeID | 交易所代码 | str | 'SH' |
| m_nVolume | 当前持仓量 | int | 1000 |
| m_dOpenPrice | 开仓均价 | float | 168.50 |
| m_dPositionProfit | 浮动盈亏 | float | 32500.00 |
3. 持仓数据解析与增强
原始API返回的数据对象需要转换为更易处理的格式。以下代码将持仓列表转换为Pandas DataFrame:
def parse_position_data(positions):
position_list = []
for pos in positions:
position_list.append({
'证券代码': f"{pos.m_strInstrumentID}.{pos.m_strExchangeID}",
'证券名称': pos.m_strInstrumentName,
'持仓量': pos.m_nVolume,
'可用数量': pos.m_nCanUseVolume,
'成本价': round(pos.m_dOpenPrice, 2),
'当前价': round(pos.m_dInstrumentValue / pos.m_nVolume, 2),
'持仓市值': round(pos.m_dInstrumentValue, 2),
'持仓成本': round(pos.m_dPositionCost, 2),
'浮动盈亏': round(pos.m_dPositionProfit, 2),
'盈亏比例': round(pos.m_dPositionProfit / pos.m_dPositionCost * 100, 2)
})
return pd.DataFrame(position_list)
关键计算逻辑 :
- 当前价 = 市值 / 持仓量
- 盈亏比例 = 浮动盈亏 / 持仓成本 × 100%
提示:QMT返回的成本价可能包含手续费等杂费,与交易记录中的成交均价略有差异。
4. 高级应用与可视化
4.1 持仓分析报告生成
def generate_report(df):
total_mv = df['持仓市值'].sum()
total_pnl = df['浮动盈亏'].sum()
print(f"\n【持仓概览 {datetime.now().strftime('%Y-%m-%d')}】")
print(f"总市值: {total_mv:,.2f} 元")
print(f"总盈亏: {total_pnl:+,.2f} 元")
# 按盈亏排序
top_gainers = df.sort_values('盈亏比例', ascending=False).head(3)
print("\n【最佳表现】")
for _, row in top_gainers.iterrows():
print(f"{row['证券代码']} {row['证券名称']}: {row['盈亏比例']:+.2f}%")
4.2 持仓分布可视化
def plot_holdings(df):
plt.figure(figsize=(10, 6))
df['权重'] = df['持仓市值'] / df['持仓市值'].sum()
# 饼图展示持仓分布
plt.subplot(121)
df.plot.pie(y='权重', labels=df['证券名称'], autopct='%1.1f%%')
plt.title('持仓市值分布')
# 条形图展示盈亏
plt.subplot(122)
df.sort_values('盈亏比例').plot.barh(
x='证券名称',
y='盈亏比例',
color=df['盈亏比例'].apply(lambda x: 'green' if x >=0 else 'red')
)
plt.title('各标的盈亏比例')
plt.tight_layout()
plt.show()
5. 异常处理与性能优化
实际运行中可能遇到的典型问题及解决方案:
常见错误排查表 :
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
| 返回空列表 | 账户格式错误 | 检查账户前缀大小写 |
| 缺少字段 | 查询类型错误 | 确认第二个参数为'stock' |
| 数据延迟 | 未登录交易账户 | 先手动登录QMT客户端 |
| 连接超时 | 网络问题 | 检查客户端连接状态 |
性能优化建议 :
- 缓存机制:对不常变动的持仓数据设置本地缓存
- 批量查询:避免在循环中频繁调用API
- 异常重试:对网络请求添加retry逻辑
from tenacity import retry, stop_after_attempt
@retry(stop=stop_after_attempt(3))
def safe_get_position(account):
return get_trade_detail_data(account, 'stock', 'position')
6. 完整代码实现
将上述功能整合为可直接运行的脚本:
# qmt_position_analyzer.py
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime
from tenacity import retry, stop_after_attempt
class PositionAnalyzer:
def __init__(self, account_id):
self.account = account_id
@retry(stop=stop_after_attempt(3))
def get_positions(self):
return get_trade_detail_data(self.account, 'stock', 'position')
def analyze(self):
raw_data = self.get_positions()
df = self.parse_to_dataframe(raw_data)
self.generate_report(df)
self.plot_holdings(df)
return df
@staticmethod
def parse_to_dataframe(positions):
# ...同上文parse_position_data实现...
@staticmethod
def generate_report(df):
# ...同上文generate_report实现...
@staticmethod
def plot_holdings(df):
# ...同上文plot_holdings实现...
if __name__ == '__main__':
analyzer = PositionAnalyzer('A123456789') # 替换为你的账户
position_df = analyzer.analyze()
position_df.to_excel('持仓分析.xlsx') # 导出Excel
实际项目中,这个脚本帮我节省了大量手动统计时间。特别是组合盈亏比例的自动计算,让调仓决策变得直观很多。记得第一次运行时,发现某个持仓的盈亏比例计算异常,检查才发现是除零错误——原来那只股票刚刚买入尚未成交,成本价为零。后来增加了异常值处理,代码就健壮多了。
更多推荐

所有评论(0)