本篇重点:本篇讲回测前怎么把行情下载到本地数据库,以及数据存在哪里、怎么查看和直接查询。
1 数据存在哪里
khQuant 的行情数据存放在一个「数据目录」里,格式是 DuckDB 数据库。回测时只从这个目录读数据,不连网取数,下载好之后断网也能回测。
- 数据目录的位置:V2 第一次启动时在引导页里选择(见 1.3),没有改过的话默认是
%LOCALAPPDATA%\KhQuantOS\khData。V3 没有引导页,第一次打开时状态栏显示「DuckDB: 未设置」,要到「设置 → 数据设置」里填(见 2.1)。建议放在系统盘以外、空间充足的磁盘上。 - 查看和修改:主界面底部状态栏右侧显示「DuckDB:数据目录路径」,鼠标悬停可以看到完整路径。要换目录,在「设置 → 数据设置 → DuckDB数据路径」里修改(见 1.12)。
- 数据状态指示灯:主界面工具栏右侧有一个圆点。绿色表示数据目录里已经有数据库文件(首次启动下载的沪深300 基准也算);红色表示数据目录为空、不存在或没有设置,鼠标悬停会显示具体原因。
- 目录结构和成交量单位:见本篇第 7 节的图;成交量统一按「手」存。
「数据管理」窗口顶部也有一个「数据目录」和「浏览…」按钮。在这里换目录,只会切换这个窗口正在查看和导入的目录,不会改变回测读取的目录。回测读的始终是「设置 → 数据设置 → DuckDB数据路径」。如果在这里换到别的目录下载了数据,回测时会找不到。
策略里用 khHistory 等函数取历史数据时,软件只读本地数据库,缺数据不会自动下载。所以下载时开始日期要往前多留一段。例如策略用 60 日均线,至少往前多下 3 个月。
2 两个免费数据源能下什么
V2 内置 BaoStock 和 Tushare 两个数据源。它们能提供的数据不同:
| 周期 / 品种 | BaoStock | Tushare |
|---|---|---|
| 股票日线 | 支持,免费,不用账号 | 支持,需要 Token |
| 股票 5 分钟线 | 支持 | 需要分钟数据权限 |
| 股票 1 分钟线 | 不支持 | 需要 stk_mins 权限 |
| 指数 | 日线 | 只有日线 |
| ETF、LOF 等场内基金 | 不支持(下载时自动跳过) | 日线需要 fund_daily;ETF 分钟需要 etf_mins,LOF 等其他基金仅支持日线 |
| 可转债 | 不支持(下载时自动跳过) | 使用 cb_daily 下载不复权日线;取消前/后复权选项,不支持分钟线 |
| 复权价 | 前复权、后复权 | 前复权、后复权,股票需要 adj_factor 接口(约 2000 积分),ETF 用 fund_adj 接口 |
| Tick | 不支持 | 不支持 |
Tick 数据两个数据源都不提供,需要自己导入 DuckDB。
- tx、同花顺(扶摇开放平台)、HTTP 桥接、miniQMT,并会持续集成更多数据源;部分数据源还能下载等比前复权、等比后复权价格。
- 定时自动补充数据:设好时间后自动增量下载,不用每天手动点「开始导入」。界面里的「定时补充」窗口需要 Windows + miniQMT;其他数据源用
kh data sync定时补,见 2.3。 - 命令行下载:用
kh data download一条命令批量下载,可以写进脚本定时执行。
下载好的数据同样存进本地 DuckDB。库的结构见本篇第 7 节;V3 多出的数据源和定时补数据见 2.3《数据管理模块(V3)》,命令行用法见 2.2《命令行模式与 AI 智能策略研究》。
3 打开「数据管理」
打开方式有两种:
- 点主界面工具栏上的「数据管理」。
- 第一次启动完成后,如果数据目录里还没有股票行情,软件会弹出「还没有行情数据」提示,点里面的「打开数据管理」。
打开后是「看海数据管理模块」窗口,分为几部分:
- 顶部工具栏:左边是两个下载入口「BaoStock导入」「Tushare导入」;右边是维护工具「占用诊断」「统计信息」「核验索引」「WAL修复」。维护工具的用法见 1.11。
- 数据目录:显示当前打开的数据目录。
- 左侧:已下载的股票列表。
- 右侧:查询条件和数据表格。
- 底部状态栏:左侧显示「可浏览股票数」和上一次操作的结果(例如「查询完成: 241 条记录」),右侧显示「BaoStock 今日已用 x/30000 次」。

如果第一次启动时的沪深300基准还没下载完,点「数据管理」会提示「首次启动的沪深300基准还在下载,完成后再打开数据管理」。等基准下载完成再打开即可。
4 用 BaoStock 下载日线
4.1 打开 BaoStock 导入窗口
在「数据管理」窗口点工具栏的「BaoStock导入」,打开「从BaoStock导入数据」窗口。窗口上方有两个页签:
- 行情数据:下载日线、5 分钟线。本节讲这一页。
- 指标下载:下载换手率、市盈率等每日指标,见 4.9。
窗口底部一排是「开始导入」「停止」「下载进程数」和「关闭」。刚打开时各项都是默认值:

4.2 选择股票池
「股票池选择」里有三种方式,用单选按钮切换:
- 预设板块:勾选一个或多个板块,可选沪深A股、上证A股、深证A股、沪深300、上证50、中证500、创业板、科创板、常用指数。
- 从文件导入:点「浏览…」选择一个股票列表 CSV 文件。文件第一列是代码(例如
600000.SH)即可;如果有表头,软件会找列名里含「代码」或「code」的那一列。 - 手动输入:选中后出现一个输入框,上方写着「输入股票代码(每行一个,支持纯数字或带市场后缀):」。可以写带市场后缀的代码(如
600000.SH),也可以只写 6 位数字,软件会自动补上市场后缀。
本篇的演示用「手动输入」,填了两只股票,每行一只。截图里的股票代码已打码,这两只股票只是举例,不代表推荐。
如果接下来要跑 1.5 的示例,先加载配置,在主界面左侧「股票池设置」自行填写研究标的。随包 .kh 的 data.stock_list 为空;这里应下载你自己填入的同一批标的。
BaoStock 不提供 ETF、LOF 等场内基金和可转债行情。股票池里有这类代码时,软件会在执行日志里列出并跳过,不消耗请求次数。ETF、LOF 请用 Tushare 下载(见第 5 节);可转债用 Tushare 下载不复权日线,取消前/后复权选项。

4.3 设置周期和日期
「数据周期设置」里有两行:
- 日线 (1d):默认勾选,开始日期默认是 10 年前的今天,结束日期是今天。
- 5分钟 (5m):默认勾选,开始日期默认是 1 年前。
两个周期的开始、结束日期分别设置。点日期框右侧的箭头可以弹出日历选择。不需要 5 分钟线时,取消勾选「5分钟 (5m)」,可以省下时间和请求次数。演示里只下日线。
这一组下方有一段橙色提示:开始日期要早于回测开始日期,给均线、MACD 等指标留出预热期(例如用 60 日均线,至少往前多下 3 个月);BaoStock 只有股票和指数的日线、5 分钟线,没有 1 分钟、Tick,也不提供 ETF、LOF 等场内基金和可转债;ETF、LOF 请用 Tushare,可转债仅支持 Tushare 不复权日线。
4.4 选择价格字段
「价格字段(原始价必存,复权价可选)」里有三个选项:
- 原始价(必存):不复权的行情,是数据库的基础字段,始终保存,不能取消。
- 前复权:默认勾选。
- 后复权:默认勾选。
回测时「复权方式」选前复权,就要求下载时勾选了「前复权」;选后复权同理(见 1.7)。每多勾一种复权价,每只股票每个周期多用一次请求。
前复权价以最新价格为基准计算,股票发生分红送转后,历史的前复权价格会整体变化。所以增量下载前复权数据时,软件可能会把这只股票本地的整段历史重新拉一遍,以保持同一个复权基准。全市场只更新日线大约需要 1.5 万次请求。
4.5 选择导入方式
「导入方式」默认是增量:软件先逐个交易日核对本地已有的数据,只请求缺失或条数不完整的区间;当天还没收盘的数据不会被当成缺失。
下面的「强制覆写已有数据(跳过增量检测,重新下载所选完整区间)」一般不用勾。只有确认本地某段历史数据有问题、需要整段重建时才勾选。
4.6 设置下载进程数
窗口底部按钮行有「下载进程数」,范围 1~8,默认 2。建议用 1~2:进程多了,BaoStock 服务器容易限流或断开连接,请求次数也消耗得更快。
4.7 开始导入
- 点「开始导入」。
- 「进度信息」里显示进度条、请求用量「软件每日BaoStock请求上限3万次;当前:x/30000」、当前状态和「预计剩余」时间。
- 「执行日志」里逐条记录每只股票、每个周期的下载情况。
- 下载完成后弹出「导入完成」对话框,列出:已是最新、成功区间、失败区间、无数据区间、处理记录数。如果还有没核实清楚的交易日(可能是停牌、未上市、数据源没返回或下载没完成),标题会是「导入完成(仍有待核验项)」,并列出数量。
- 点「确定」关闭对话框,再点「关闭」回到「数据管理」窗口。左侧列表会自动刷新,出现刚下载的股票。
演示里下载了两只股票近 10 年的日线(含前复权、后复权),用时约 25 秒,「导入完成」对话框显示成功区间 2、处理记录数 4854,请求用量从 1 变为 7:两只股票各用 3 次(原始价、前复权、后复权各 1 次),开头的 1 次是首次启动时下载沪深300 基准用掉的。
下载中途想停,点「停止」。软件会等当前写入完成后再停,已写入的数据会保留,下次增量导入会接着补。
每次用 BaoStock 导入行情,软件还会顺带检查沪深300指数(000300.SH)日线有没有缺口,有缺口就补上,保证回测时有基准数据。

4.8 每日请求上限
BaoStock 是免费服务,软件给它设了每天 3 万次的请求上限,按数据目录分别计数:
- 「从BaoStock导入数据」窗口和「数据管理」窗口状态栏都显示当天已用次数。
- 一只股票的一个周期,原始价、前复权、后复权各算一次请求。
- 达到上限后,下载会停止,没下完的部分保留为待补,第二天再用增量导入接着下。
4.9 下载每日指标(可选)
「指标下载」页签可以下载 BaoStock 提供的每日指标:换手率、交易状态、涨跌幅、滚动市盈率、滚动市销率、滚动市现率、市净率、是否ST。BaoStock 一次请求就返回全部指标,所以这 8 项总是一起下载。
使用前要注意:
- 指标写在日线数据的同一行里,只会补到本地已有日线的日期上。先下日线,再下指标。
- 股票池选择方式和「行情数据」页相同,另外有「日期范围」。
- 默认只补本地日线中还没有指标的日期;勾选「强制重新请求所选日期范围」会整段重新请求。
- 指标请求同样计入每天 3 万次的上限。
- 下载按钮在这一页叫「开始下载」。

5 用 Tushare 下载 1 分钟线和 ETF
5.1 填写 Tushare Token
- 在 Tushare 官网注册账号,取得 Token。股票分钟线需要
stk_mins权限,ETF 分钟线需要etf_mins权限,场内基金日线需要fund_daily权限,复权价需要复权因子接口:股票用adj_factor(约 2000 积分),ETF 用fund_adj。具体权限规则以 Tushare 官方说明为准。 - 回到 khQuant 主界面,点工具栏「设置」,切到「数据设置」页签,找到「Tushare 接口配置」。
- 在「Token」一栏粘贴 Token。输入后显示为一串圆点;点右边的「显示」可以查看输入的内容,点「测试连接」检查能否连通。
- 「API 地址」一般留空,留空时使用官方 HTTPS 接口。填写了地址就按所填的用:填 http:// 就走 http://,软件不会自动改成 https://。http:// 不加密,Token 会以明文传输,填写前请先向服务方确认是否支持 HTTPS。旧截图中的 SDK 默认地址提示以新版界面为准。
- 如果需要通过代理上网,勾选「使用网络代理访问 Tushare」,在「代理地址」里填写,例如
http://127.0.0.1:7890。 - 点右下角「保存设置」,弹出「成功」提示后设置窗口关闭。

没有填 Token 就点「Tushare导入」,软件会弹出「未配置Token」提示:

5.2 下载数据
在「数据管理」窗口点「Tushare导入」,打开「从Tushare导入数据」窗口。操作和 BaoStock 类似,区别如下:
- 预设板块:比 BaoStock 多了沪深ETF、沪深场内基金(含ETF/LOF)、沪深转债、T0型ETF。
- 数据周期:有日线 (1d)、1分钟 (1m)、5分钟 (5m) 三行。默认只勾选日线(10 年);1 分钟和 5 分钟默认不勾选,开始日期默认 1 年前。
- 价格字段:原始价必存,前复权、后复权默认勾选。复权价需要复权因子接口权限(股票
adj_factor、ETFfund_adj)。 - 强制覆写:窗口下方的「强制覆写已有数据」默认不勾选,用法同 BaoStock。
- 提示文字:股票分钟线用
stk_mins,ETF 分钟线用etf_mins,基金日线用fund_daily;指数和 LOF 等其他基金仅支持日线,可转债仅支持不复权日线。 - 点「开始下载」开始,「停止」中止,「关闭」关闭窗口。没有「下载进程数」设置。
策略要交易 ETF 时,回测前必须先用 Tushare 把对应 ETF 的数据下好。BaoStock 下载时会直接跳过 ETF 代码。

6 查看下载好的数据
下载完成后,回到「数据管理」窗口查看。
6.1 左侧股票列表
- 列表按市场分组,例如「SZ (2只)」,展开后每行是「代码 名称」。
- 上方有搜索框(可以搜代码或名称)、「市场」和「周期」两个筛选框,右边的「⟳」按钮用来刷新列表。
- 点一只股票,这一行的「记录数」一栏会显示各周期的条数,例如「1d:2427 1m:0 5m:0 tick:0」;还没点过的股票显示「点击查看」。
- 在股票上点右键,有「查看数据」「导出CSV」「删除数据」三项。「删除数据」会删除本地这只股票的数据,操作前请确认。
6.2 右侧查询与数据表格
点左侧的股票后,右侧会自动选好这只股票有数据的周期,并按当前日期范围查询一次:
- 查询条件:股票代码、周期、限制(最多显示的条数,默认 10000)、开始日期、结束日期。开始日期默认是一年前,想看更早的数据,把开始日期往前改,再点「查询」。
- 数据表格:一个交易日一行。列名是英文字段名加中文说明,例如 time(时间)、open(开盘价)、high(最高价)、low(最低价)、close(收盘价)、volume(成交量)、amount(成交额);往右拖还有 open_front(前复权开盘)、close_back(后复权收盘) 等复权列,以及 turn(换手率)、peTTM(滚动市盈率)、isST(是否ST) 等指标列。没有数据的格子显示
nan或<NA>。表格下方显示本次查询的条数和时间范围。 - 日线的时间显示为当天
09:30:00,例如2025-09-30 09:30:00,表示这一天的日 K 线。这个 09:30 只是日期标记,不代表 9 点半那一刻的行情:这一行里的开盘、最高、最低、收盘都是全天的数据。 - 「数据完整性检查」和「导出CSV」按钮的用法见 1.11。

6.3 用 SQL 查询
右侧第二个页签是「SQL查询」,可以对当前选中股票的数据库写 SQL 语句,点「执行SQL」查看结果。输入框里有示例写法,例如按收盘价筛选日线、计算平均收盘价。日线表名是 kline_1d。
▶ 本节视频:1.4 进阶 · 本地数据库的结构
7 本地数据库的结构(进阶)
这一节写给想直接分析数据、写外部脚本的读者,只用软件回测的话不必细读。V2 和 V3 用的是同一种 DuckDB 库,目录和表的结构相同;V3 多出的数据源(tx、同花顺、HTTP 桥接、miniQMT)也写进同一个库,见 2.3《数据管理模块(V3)》。
7.1 数据目录里有什么
数据目录就是「设置 → 数据设置 → DuckDB数据路径」里填的文件夹(见本篇第 1 节、1.12),第一次写入数据时自动建好:
修复时还可能出现 _wal_recovered、metadata.db.backup-… 这类备份(见 1.11),V3 用 miniQMT 导入时会有 *_progress.json。这些都由程序生成,不要手动改。
7.2 单只证券的库
7.2.1 有哪些表
7.2.2 K 线表的字段
日线表共 37 列,分钟线表少了日线专有的 8 列,共 29 列。分组见上图,逐列说明可以展开下表。
完整字段表(展开)
| 列 | 类型 | 说明 |
|---|---|---|
time |
TIMESTAMP(主键) | 日线为当天 09:30:00;分钟线为这根 K 线的结束时刻 |
open high low close |
DOUBLE | 不复权价 |
volume |
DOUBLE | 成交量,单位手 |
amount |
DOUBLE | 成交额,单位元;部分数据源的分钟线为空 |
settelementPrice、openInterest |
DOUBLE、BIGINT | 结算价、持仓量(期货用,股票为空) |
preClose、suspendFlag |
DOUBLE、INTEGER | 前收盘、停牌标记,部分数据源为空 |
open_front … close_front |
DOUBLE | 前复权价(4 列) |
open_back … close_back |
DOUBLE | 后复权价(4 列) |
open_front_ratio … close_front_ratio |
DOUBLE | 等比前复权价(4 列) |
open_back_ratio … close_back_ratio |
DOUBLE | 等比后复权价(4 列) |
turn tradestatus pctChg peTTM psTTM pcfNcfTTM pbMRQ isST |
DOUBLE | 仅日线:换手率、交易状态、涨跌幅、市盈率等指标,主要来自 BaoStock「指标下载」页(见 4.9);V3 用其他数据源导入时也可以勾「同时补充日线指标」 |
dividend_type |
VARCHAR | 内部标记,不用管 |
update_time |
TIMESTAMP | 这一行最后写入的时间 |

- 早期建的库可能列的顺序不同,读取时请按列名取,不要按位置。
7.2.3 Tick 表
共 34 列:time(主键)、lastPrice、open high low lastClose、amount volume pvolume、stockStatus openInt lastSettlementPrice、五档买卖价 askPrice1~5 bidPrice1~5 和挂单量 askVol1~5 bidVol1~5、transactionNum、update_time。Tick 数据按数据源原样保存,不做单位换算,也没有复权列。
7.2.4 stock_info 与单位标记
SELECT key, value FROM stock_info;
stock_code 000300.SH
kline_1d.volume_unit lots
kline_1d.amount_unit CNY
每个周期的成交量、成交额单位都记在这里(lots 即手,CNY 即元)。写入新数据前软件会核对:数据自己声明的成交量不是「手」、或成交额不是「元」时,拒绝写入。旧库的单位标记缺失或不一致时,V2、V3 的处理相同:照常续写,同时在 stock_info 里写一条 <表名>.legacy_units_unverified = 1(比如 kline_1d.legacy_units_unverified),表示这张表的历史单位未核验,不能视为已经统一:表里可能混有旧版本按其他单位写入的历史数据,新写入的部分按「手」和「元」存储。
成交量按「手」存,比行情软件里以「股」显示的数字小 100 倍,这是正常的。
7.3 metadata.db:索引库
stock_list:每只证券一行,字段有stock_code(带后缀)、stock_name、market、has_1d has_1m has_5m has_tick(各周期有没有数据)、last_sync、update_time。sync_log:每次真正写入了新数据,就记一行(代码、周期、写入条数、状态、时间)。
数据管理窗口左边的股票列表(以及 V3 的 kh data list、kh data sync)要处理哪些证券,都以 stock_list 为准。有下载好的库没出现在列表里时,用数据管理的「核验索引」补登记(见 1.11;V3 也可以用 kh data reindex --fix)。
7.4 怎么查数据
7.4.1 数据管理的「SQL查询」
在数据管理窗口左侧选中一只证券,右侧切到「SQL查询」页签,输入 SQL,点「执行SQL」。SQL 作用在当前选中的这只证券的库上,表名直接写 kline_1d、tick 等。

SELECT * FROM kline_1d ORDER BY time DESC LIMIT 10
SELECT AVG(close) AS avg_price, MAX(high) AS max_high FROM kline_1d WHERE time >= '2025-01-01'
- 只用来查询,不要写修改数据的语句。
- SQL 写错(语法错误、表不存在)时不会报错,只显示「查询结果: 0 行, 0 列」。看到 0 行时先检查语句和表名,比如这只证券有没有下载过分钟线。
- 查询结果可以在「数据表格」页或右键菜单用「导出CSV」保存;批量导出用下面的方法。
7.4.2 命令行(仅 V3)
kh data list # 列出库里所有证券
kh data info 000300.SH # 各周期的条数和起止日期
kh data stats # 各市场的证券数和磁盘占用
kh data export 000300.SH --period 1d --start 20260901 --output hs300.csv
export 导出指定周期的全部行情列(不含 dividend_type、update_time 两个内部列),编码 UTF-8(带 BOM,Excel 可直接打开)。代码要带后缀;CSV 的第一列是没有表头的行号。
7.4.3 用 Python 读
import duckdb
con = duckdb.connect(r"D:\khData\SH\000300.db", read_only=True)
df = con.execute("""
SELECT CAST(time AS DATE) AS trade_date, open, high, low, close, volume, amount
FROM kline_1d WHERE time >= '2026-09-24' ORDER BY time
""").fetchdf()
con.close()
print(df)
- 路径换成你自己的数据目录。
- duckdb 版本建议 1.0 以上,最好和软件一致(Windows 安装版用的是 1.4.3)。
- 一定加
read_only=True,用完立刻close()。 - 要读多只证券,就逐个打开对应的
.db文件;可以先读metadata.db的stock_list拿到清单。
在策略里读数据请用 khHistory 等函数(见第 3 部分),读写自定义指标见 3.5 第 6 节,函数说明见 3.2。
7.5 同时打开的规则
- 数据管理窗口平时以只读方式浏览,导入、删除时才临时切换成写入。
- 提示数据库被占用时,用数据管理工具栏的「占用诊断」查是谁占着(见 1.11)。
- (仅 V3)命令行下载开始时,索引库被占用会等最多 10 分钟;单只证券的库被占用时只重试几次,这只就记为失败,跑完后再补。
常见问题
问:下载完了,左侧列表里没看到新股票?
答:点左侧筛选栏右边的「⟳」刷新列表。如果还是没有,看窗口顶部「数据目录」是不是你在设置里配置的那个目录。
问:BaoStock 下载很慢,或者经常断开?
答:把「下载进程数」调成 1 再试。BaoStock 是免费服务,高峰期响应会变慢;增量导入可以随时停止、下次接着下。
问:提示已达到 BaoStock 当日请求上限?
答:当天的 3 万次用完了,第二天再用增量导入继续下载,已下好的数据不受影响。只需要日线时,取消勾选 5 分钟线;不用后复权时,取消勾选「后复权」,都能减少请求次数。
问:为什么用 BaoStock 下不了 ETF 和 1 分钟线?
答:BaoStock 本身不提供这两类数据。ETF 和 1 分钟线请用 Tushare 下载,需要相应的接口权限。
问:以前用 miniQMT 下载的数据还能用吗?
答:V2 只读本地 DuckDB 数据库,不读取 miniQMT 的数据文件,需要按本篇重新下载。
问:数据下好了,回测时还是提示数据不完整?
答:常见原因有三个:回测区间超出了下载的日期范围;主界面「周期类型」选的周期没有下载;「复权方式」选的复权价没有下载(例如选了前复权,下载时没勾「前复权」)。详见 1.7。
问:查 kline_1m 返回 0 行?
答:这只证券还没下载过 1 分钟线,表不存在。先下载分钟数据。
问:成交量比行情软件小 100 倍?
答:库里按「手」存,行情软件按「股」显示,乘以 100 就对上了。
问:Python 打开库报「File is already open」?
答:软件正在写这个库(下载、定时补充或数据管理里的导入)。等它结束,或者关掉数据管理窗口后再试。
问:能把数据目录拷到另一台电脑用吗?
答:可以,整个文件夹拷过去,在那台电脑的设置里把数据路径指向它。Windows、macOS、Linux 之间也通用。
- tx、同花顺(扶摇开放平台)、HTTP 桥接、miniQMT,并会持续集成更多数据源
- 定时自动补充数据,不用每天手动点下载
- CLI 一条 kh data download 命令批量下载
本篇基于开源 V2 和 V3.4.1.10 编写。