🚀 AI 一键生成 qmt 策略代码

如何将 QMT 策略的回测绩效或历史行情数据保存到本地 CSV 文件中?

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

问题描述

怎样把获取到的股票日线历史行情数据保存成一个 CSV 文件?

解决方案

在 QMT 中将获取的股票日线历史行情数据保存为 CSV 文件,主要利用 Python 内置的 pandas 库(QMT 环境已自带)的 to_csv 方法。

核心步骤如下:

  1. 使用 ContextInfo.get_market_data_ex 获取历史行情数据。
  2. 该接口返回的是一个字典 {股票代码: DataFrame}
  3. 遍历字典,将数据合并为一个大的 DataFrame(或者分别保存)。
  4. 调用 df.to_csv() 保存到本地磁盘。

以下是完整的策略代码示例:

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

def init(ContextInfo):
    # 1. 设置要获取数据的参数
    # 示例:获取 浦发银行 和 平安银行 的数据
    stock_list = ['600000.SH', '000001.SZ']
    
    # 设置起止时间 (格式:YYYYMMDD)
    start_time = '20230101'
    end_time = '20231231'
    
    # 设置需要的字段
    fields = ['open', 'high', 'low', 'close', 'volume', 'amount']
    
    # 2. 调用 get_market_data_ex 获取数据
    # period='1d' 表示日线
    # dividend_type='front' 表示前复权 (根据需求修改: 'none'不复权, 'back'后复权)
    print("开始获取数据...")
    data_dict = ContextInfo.get_market_data_ex(
        fields, 
        stock_list, 
        period='1d', 
        start_time=start_time, 
        end_time=end_time,
        dividend_type='front'
    )
    
    # 3. 处理数据并合并
    # get_market_data_ex 返回的是 {code: dataframe} 格式
    all_data_df = pd.DataFrame()
    
    for code, df in data_dict.items():
        if df is not None and not df.empty:
            # 在 DataFrame 中增加一列显示股票代码,方便区分
            df['stock_code'] = code
            # 将索引(时间)重置为普通列,方便保存
            df.index.name = 'date'
            df = df.reset_index()
            
            # 合并到总表中
            all_data_df = pd.concat([all_data_df, df], axis=0)
    
    # 4. 保存到 CSV 文件
    if not all_data_df.empty:
        # 设置保存路径,请确保该路径存在且有写入权限
        # 注意:Windows路径建议使用双反斜杠 \\ 或正斜杠 /
        save_path = 'D:/qmt_history_data.csv' 
        
        try:
            # encoding='gbk' 是为了防止中文乱码(如Excel打开),也可以用 'utf-8-sig'
            all_data_df.to_csv(save_path, index=False, encoding='gbk')
            print(f"数据已成功保存至: {save_path}")
            print(f"共保存 {len(all_data_df)} 条数据")
        except Exception as e:
            print(f"保存文件失败: {e}")
    else:
        print("未获取到数据,请检查股票代码或时间范围,并确保已下载历史数据。")

def handlebar(ContextInfo):
    # 本策略只需在 init 中运行一次即可导出数据
    pass

代码关键点说明

  1. 接口选择
    使用了 ContextInfo.get_market_data_ex。相比旧版接口,它返回的数据结构更清晰(字典包含 DataFrame),且处理多只股票更方便。

  2. 数据合并
    API 返回的数据是字典格式 { '600000.SH': DataFrame, ... }。代码通过 for 循环遍历这个字典,给每个 DataFrame 加上 stock_code 列,然后使用 pd.concat 将它们拼接到一起。这样导出的 CSV 文件会包含所有股票的数据,且可以通过代码列区分。

  3. 文件路径与编码

    • 路径:请修改 save_path = 'D:/qmt_history_data.csv' 为您电脑上实际存在的路径。
    • 编码encoding='gbk' 是为了让生成的 CSV 文件在 Excel 中打开时不乱码。如果您主要用于其他程序读取,可以使用 utf-8
  4. 数据下载
    QMT 的 Python API 依赖本地数据。如果运行后提示“未获取到数据”或数据为空,请务必在 QMT 客户端界面上方点击 “数据管理” -> “行情数据下载”,补充对应品种和周期的历史数据。


Q&A

Q: 为什么运行代码后 CSV 文件是空的或者提示未获取到数据?
A: QMT 的 Python API 是从本地数据库读取历史行情的。请确保您已经在 QMT 客户端的【数据管理】中下载了对应股票、对应周期(如日线)和对应时间段的历史数据。

Q: 如何将每只股票保存成单独的 CSV 文件?
A: 可以在遍历字典的循环中直接保存。将 all_data_df.to_csv(...) 移到 for 循环内部,并将文件名修改为动态文件名,例如 save_path = f'D:/{code}.csv'

Q: get_market_data_ex 返回的 DataFrame 索引是什么?
A: 返回的 DataFrame 的索引(Index)通常是时间字符串(例如 20230101093000)。在上面的代码中,我们使用了 df.reset_index() 将其变成了一列名为 date 的普通数据列,以便保存到 CSV 中。

Q: 如何保存分钟级别的历史数据?
A: 只需将代码中的 period='1d' 修改为 period='1m'(1分钟)、period='5m'(5分钟)等即可。同时请确保已下载对应的分钟线历史数据。