🚀 AI 一键生成 qmt 策略代码

QMT load_stk_vol_list 函数使用指南:批量导入证券代码及数量

qmt | 发布时间: 2025/12/29
以下内容由 EasyQuant 生成。

问题描述

怎样从txt或csv文件读取股票列表和数量进行批量交易?

解决方案

在QMT中,从外部文件(TXT或CSV)读取股票列表和数量并进行批量交易,通常有两种主要方式:

  1. 使用 Python 标准库或 Pandas 库(推荐):这种方式最灵活,支持标准的表格格式(如每行一个股票),易于编辑和维护。
  2. 使用 QMT 内置接口 load_stk_vol_list:这种方式需要文件符合特定的紧凑格式(代码和数量成对出现),适合特定场景。

下面我将为您提供一个基于 Pandas 读取 CSV 文件的完整策略代码,这是最通用且稳健的方法。

策略说明

  1. 文件格式:假设您的 CSV 文件名为 trade_list.csv,内容格式如下(包含表头):
    stock_code,volume
    600000.SH,100
    000001.SZ,200
    600519.SH,100
    
  2. 运行逻辑
    • 策略初始化时设置账号。
    • handlebar 中,当运行到最新一根K线(实时行情)且尚未交易过时,读取文件。
    • 遍历文件内容,调用 order_shares 下单。
    • 设置标志位防止重复下单。

策略代码

# -*- coding: gbk -*-
import pandas as pd
import os

def init(ContextInfo):
    # 1. 设置资金账号 (请替换为您真实的资金账号)
    ContextInfo.accID = '6000000000' 
    ContextInfo.set_account(ContextInfo.accID)
    
    # 2. 设置文件路径 (请修改为您的实际文件路径)
    # 注意:Windows路径请使用双斜杠 \\ 或反斜杠 /
    ContextInfo.file_path = 'D:/qmt_data/trade_list.csv'
    
    # 3. 设置全局变量,控制是否已执行,防止重复下单
    ContextInfo.has_traded = False
    
    print("策略初始化完成,等待读取文件交易...")

def handlebar(ContextInfo):
    # 只在实时行情的最后一根K线执行,且只执行一次
    if not ContextInfo.is_last_bar() or ContextInfo.has_traded:
        return

    # 检查文件是否存在
    if not os.path.exists(ContextInfo.file_path):
        print(f"错误:文件未找到 - {ContextInfo.file_path}")
        return

    try:
        # 读取CSV文件
        # encoding='gbk' 或 'utf-8' 取决于您CSV文件的保存编码
        df = pd.read_csv(ContextInfo.file_path, encoding='gbk')
        
        print(f"成功读取文件,共 {len(df)} 条指令")
        
        # 遍历每一行进行交易
        for index, row in df.iterrows():
            stock_code = row['stock_code'] # 对应CSV中的列名
            volume = int(row['volume'])    # 对应CSV中的列名
            
            # 过滤掉无效数据
            if not stock_code or volume <= 0:
                continue
                
            # 执行下单:指定股数交易
            # order_shares(代码, 数量, 报价类型, 价格, ContextInfo, 账号)
            # 'LATEST' 表示使用最新价下单,也可以改为 'FIX' 并传入指定价格
            order_shares(stock_code, volume, 'LATEST', -1, ContextInfo, ContextInfo.accID)
            
            print(f"已发送委托:{stock_code} 数量:{volume}")
            
        # 标记为已交易,避免下一笔Tick重复执行
        ContextInfo.has_traded = True
        print("批量交易执行完毕")

    except Exception as e:
        print(f"读取文件或交易过程中发生错误: {e}")

关键点说明

  1. 文件路径

    • 代码中的 D:/qmt_data/trade_list.csv 需要替换为您电脑上的实际路径。
    • 如果是 TXT 文件,只要内容是用逗号分隔的(类似 CSV),pd.read_csv 同样可以读取。
  2. 编码问题

    • 代码中使用了 # -*- coding: gbk -*-,这是 QMT Python 编辑器的标准编码。
    • pd.read_csv(..., encoding='gbk'):如果您的 CSV 文件是用 Excel 保存的,通常是 GBK 编码。如果是用现代编辑器保存的 UTF-8 格式,请将此处改为 utf-8
  3. 下单函数

    • 本例使用的是 order_shares(按股数下单)。
    • 如果您希望按金额下单,可以使用 order_value(stock_code, money, ...)
    • 如果您希望按目标仓位下单(例如调仓到指定股数),可以使用 order_target_shares(需自行封装逻辑或使用 order_target_value)。
  4. 防重复机制

    • ContextInfo.has_traded 变量非常重要。因为 handlebar 会随行情 Tick 不断触发,如果不加锁,会导致瞬间重复下无数单。

附:使用 QMT 内置 load_stk_vol_list 的方式(备选)

如果您偏好使用 QMT 原生 API 读取文件,可以使用 load_stk_vol_list。但请注意,该接口对文件内容格式要求较特殊。

文件内容格式(TXT/CSV)
必须是成对出现的 代码,数量,例如:
600000.SH,100,600004.SH,200

代码片段

def handlebar(ContextInfo):
    # ... 前置判断逻辑同上 ...
    
    # 读取文件内容
    # 参数1:文件夹路径,参数2:文件名
    content = ContextInfo.load_stk_vol_list('D:/qmt_data/', 'trade_list.txt')
    
    if content:
        # content 返回的是一个长字符串,需要自行分割处理
        items = content.split(',')
        # 步长为2进行遍历
        for i in range(0, len(items), 2):
            if i + 1 < len(items):
                code = items[i].strip()
                vol = int(items[i+1].strip())
                order_shares(code, vol, 'LATEST', -1, ContextInfo, ContextInfo.accID)

总结:建议使用第一种 Pandas 方式,因为它对文件格式的容错率更高,且代码逻辑更符合通用的量化开发习惯。


Q&A

Q: 如何实现定时读取文件进行交易(例如每天特定时间)?
A: 可以在 handlebar 中加入时间判断。例如:

import time
# 获取当前时间戳对应的HHMMSS
current_time = int(time.strftime("%H%M%S", time.localtime(time.time())))
# 比如在 10:00:00 到 10:00:05 之间触发
if 100000 <= current_time <= 100005 and not ContextInfo.has_traded:
    # 执行读取和交易逻辑
    pass

Q: 如果我想指定价格下单而不是用最新价怎么办?
A: 修改 order_shares 的参数。例如,如果 CSV 中有 price 列:

price = row['price']
# 'FIX' 表示限价单
order_shares(stock_code, volume, 'FIX', price, ContextInfo, ContextInfo.accID)

Q: 为什么读取 CSV 时报错 UnicodeDecodeError
A: 这通常是编码不匹配造成的。请检查 pd.read_csv 中的 encoding 参数。如果文件是 UTF-8 编码,请改为 encoding='utf-8';如果是 Windows 默认格式(Excel 保存),通常是 encoding='gbk'encoding='gb18030'