🚀 AI 一键生成 qmt 策略代码

QMT API 教程:如何从文件导入股票代码和交易数量?

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

问题描述

如何读取本地 CSV 文件中的股票代码和数量并下单?

解决方案

在 QMT 中读取本地 CSV 文件并进行批量下单,通常推荐使用 Python 内置的 pandas 库来处理 CSV 数据,结合 QMT 的交易函数(如 order_shares)来实现。

以下是具体的实现步骤和代码示例。

1. 准备工作

首先,你需要准备一个 CSV 文件(例如命名为 orders.csv),文件内容应包含股票代码和数量。

CSV 文件格式示例(orders.csv):

code,volume
600000.SH,100
000001.SZ,200
600519.SH,100

注意:股票代码需要包含后缀(.SH 或 .SZ),数量为股数。

2. 策略代码实现

该策略会在 init 中初始化账户,并在 handlebar 中读取指定路径的 CSV 文件,遍历每一行数据进行下单。为了防止重复下单,代码中增加了一个标志位 ContextInfo.has_ordered

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

def init(ContextInfo):
    # 1. 设置资金账号 (请替换为您真实的资金账号)
    ContextInfo.account_id = '6000000000' 
    ContextInfo.set_account(ContextInfo.account_id)
    
    # 2. 设置 CSV 文件路径 (建议使用绝对路径,防止路径错误)
    # 注意:Windows路径请使用双斜杠 \\ 或反斜杠 /
    ContextInfo.csv_path = 'D:/qmt_data/orders.csv' 
    
    # 3. 设置一个标志位,防止在每一根K线上重复下单
    ContextInfo.has_ordered = False
    
    print("策略初始化完成,准备读取文件下单...")

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

    if ContextInfo.has_ordered:
        return

    # 检查文件是否存在
    if not os.path.exists(ContextInfo.csv_path):
        print(f"错误:找不到文件 {ContextInfo.csv_path}")
        ContextInfo.has_ordered = True # 标记为已执行,避免报错刷屏
        return

    try:
        # 1. 读取 CSV 文件
        # encoding='gbk' 或 'utf-8' 取决于你的 CSV 保存格式
        df = pd.read_csv(ContextInfo.csv_path, encoding='gbk')
        
        print(f"成功读取文件,共 {len(df)} 条指令")

        # 2. 遍历数据并下单
        for index, row in df.iterrows():
            stock_code = row['code']  # 获取代码列
            volume = int(row['volume'])    # 获取数量列
            
            # 过滤掉无效数据
            if volume <= 0:
                continue
                
            # 执行下单:按最新价买入指定股数
            # order_shares(代码, 数量, 报价类型, 价格, ContextInfo, 账号)
            # 'LATEST' 表示最新价,价格填 0 即可
            order_shares(stock_code, volume, 'LATEST', 0, ContextInfo, ContextInfo.account_id)
            
            print(f"已发送下单指令:代码 {stock_code}, 数量 {volume}")

        # 3. 修改标志位,确保只运行一次
        ContextInfo.has_ordered = True
        print("所有文件内指令已处理完毕。")

    except Exception as e:
        print(f"读取文件或下单过程中发生错误: {e}")
        ContextInfo.has_ordered = True

3. 代码关键点解析

  1. # -*- coding: gbk -*-:
    • QMT 的 Python 编辑器默认编码通常为 GBK,加上这行可以防止中文注释乱码。
  2. pd.read_csv:
    • 使用 pandas 读取数据非常方便。如果你的 CSV 文件包含中文字符(如列名),请注意 encoding 参数。Excel 保存的 CSV 通常是 gbk 编码。
  3. ContextInfo.has_ordered:
    • 非常重要handlebar 函数会随着行情推送不断被调用。如果不加这个锁,策略会不断地重复读取文件并重复下单,导致资金耗尽或违规交易。
  4. order_shares:
    • 这是最常用的下单函数之一,用于指定股数交易。
    • 参数说明:order_shares(stockcode, shares, style, price, ContextInfo, accId)
    • 示例中使用 'LATEST' 以最新价下单。如果需要限价,可以将 'LATEST' 改为 'FIX',并将后面的 0 改为具体的 price
  5. 路径问题:
    • 建议使用绝对路径(如 D:/data/orders.csv),因为 QMT 运行时的相对路径可能不是你想象的当前文件夹。

4. 替代方案(QMT 原生 API)

QMT API 文档中也提供了一个专门用于读取“一篮子证券及数量”的接口,如果你不想使用 pandas,也可以使用 ContextInfo.load_stk_vol_list

  • 用法ContextInfo.load_stk_vol_list(filePath, fileName)
  • 文件格式要求代码,数量,代码,数量(成对出现)。
  • 缺点:该接口对文件格式要求较死板(通常用于系统生成的篮子文件),且不如 pandas 处理数据灵活(例如 pandas 可以方便地过滤掉数量为 0 的行)。因此,推荐使用上面的 pandas 方法

Q&A

Q: 如果我的 CSV 文件里只有数字代码(如 600000)没有后缀(.SH)怎么办?
A: 你可以在代码中进行字符串拼接处理。

# 在遍历循环中修改
stock_code = str(row['code']).zfill(6) # 补全6位
if stock_code.startswith('6'):
    stock_code += '.SH'
else:
    stock_code += '.SZ'

Q: 如何实现卖出?
A: 在 order_shares 函数中,数量传入负数即为卖出。你可以在 CSV 中将卖出的数量写为负数(如 -100),或者在代码逻辑中乘以 -1。

Q: 这个策略可以直接回测吗?
A: 可以。在回测模式下,order_shares 会根据历史行情撮合交易。但要注意回测时 ContextInfo.account_id 是虚拟账号,且需要确保 CSV 中的股票在回测时间段内是上市交易的。