首页
/ freqtrade convert-db 详解:交易数据库跨系统迁移命令与源码原理

freqtrade convert-db 详解:交易数据库跨系统迁移命令与源码原理

2026-09-05 11:32:31作者:裴麒琰

本篇基于 docs/commands/convert-db.md 与仓库源码,完整讲解 freqtrade convert-db 命令的用途、全部参数含义与默认值、典型迁移操作方式,以及底层 migrate_db 实现 究竟迁移了哪些数据表、又如何在 PostgreSQL 上正确处理自增序列。读完之后,你可以把机器人运行了很久的 SQLite 交易库完整搬到 PostgreSQL(或从一个 PostgreSQL 实例迁到另一个),并理解迁移过程每一类数据的落库逻辑与序列重置原理。

命令概述

convert-db 是 freqtrade 提供的数据库迁移子命令。它的作用是把交易数据库从一个系统搬到另一个系统,例如 SQLite 迁往 PostgreSQL、PostgreSQL 迁往另一个 PostgreSQL 实例,迁移内容包括全部 trades、orders 以及 PairLock 等关联数据。

命令在 CLI 中的完整帮助信息如下(继承自 docs/commands/convert-db.md 原文):

usage: freqtrade convert-db [-h] [--db-url PATH] [--db-url-from PATH]

options:
  -h, --help          show this help message and exit
  --db-url PATH       Override trades database URL, this is useful in custom
                      deployments (default: `sqlite:///tradesv3.sqlite` for
                      Live Run mode, `sqlite:///tradesv3.dryrun.sqlite` for
                      Dry Run).
  --db-url-from PATH  Source db url to use when migrating a database.

该子命令在 命令注册代码 中定义,帮助文案为 "Migrate database to different system",执行入口绑定到 start_convert_db 函数

参数详解

convert-db 只接受两个业务参数(外加 -h),对应 arguments.py 中的 ARGS_CONVERT_DB = ["db_url", "db_url_from"],参数定义位于 cli_options.py

--db-url

目标数据库 URL,即迁移完成后机器人将要使用的数据库。它是 freqtrade 全局通用的 db_url 配置项的命令行覆盖形式。

默认值定义在 constants.py

DEFAULT_DB_PROD_URL = "sqlite:///tradesv3.sqlite"
DEFAULT_DB_DRYRUN_URL = "sqlite:///tradesv3.dryrun.sqlite"

configuration.py 的赋值逻辑看,dry-run 模式下默认使用 tradesv3.dryrun.sqlite,实盘模式下默认使用 tradesv3.sqlite,这也正是帮助文本中"default: sqlite:///tradesv3.sqlite for Live Run mode, sqlite:///tradesv3.dryrun.sqlite for Dry Run"的来源。

--db-url-from

源数据库 URL,即迁移的起点库。这个参数是 convert-db 专属的,用于指明"从哪个库读数据"。在典型的 SQLite 迁 PostgreSQL 场景中,目标库(--db-url)指定 PostgreSQL 连接串,源库(--db-url-from)指向已有的 tradesv3.sqlite 文件。

源码调用链:start_convert_db 做了什么

db_commands.py 中的入口函数逻辑非常紧凑:

def start_convert_db(args: dict[str, Any]) -> None:

    from freqtrade.configuration.config_setup import setup_utils_configuration
    from freqtrade.persistence import Trade, init_db
    from freqtrade.persistence.db_migration import migrate_db

    config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE)

    init_db(config["db_url"])
    session_target = Trade.session
    init_db(config["db_url_from"])
    logger.info("Starting db migration.")
    migrate_db(session_target)

从源码结构可以读出以下要点:

  1. 以工具模式启动配置setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE) 说明 convert-db 属于纯离线工具命令——不连接交易所、不加载策略行情,只需要解析出 db_urldb_url_from 两项配置即可运行。
  2. 先后两次 init_db 决定了源与目标的角色:先对 config["db_url"](目标库)初始化,并立刻通过 session_target = Trade.session 拿到目标库的会话对象;随后再次对 config["db_url_from"](源库)初始化。由于 init_db 会重建默认 Trade.session,后一次初始化使得默认会话指向源库。
  3. 单行迁移调用migrate_db(session_target) 负责把源库(当前默认会话所连的库)中的全部数据写入 session_target(目标库)。

migrate_db 内部实现:哪些数据被迁移

真正的数据搬运逻辑在 db_migration.py。该函数按以下五类实体逐类迁移,且每类独立 commit 一次:

数据类别 ORM 模型 迁移方式
交易(含其下的订单) Trade / Order 遍历 Trade.get_trades(),对每个 trade 及其 trade.orders 逐个 make_transient 后 add 到目标会话
交易对锁 PairLock 遍历 PairLock.get_all_locks() 逐条写入
键值存储 _KeyValueStoreModel 全表 select 后逐条写入
自定义交易数据 _CustomData 全表 select 后逐条写入
钱包历史 WalletHistory 全表 select 后逐条写入

其中 make_transient(obj) 是关键手法:把从源会话读取的对象"脱钩",使其可以被 add 进目标会话而不会带着旧的身份信息与目标库产生冲突。Trade 迁移时特意连同其 orders 关系一起搬运,因此 orders 表也随交易一并完成迁移。

所有数据写入完成后,函数会查询五张表各自的 max(id),并调用 set_sequence_ids

max_trade_id = session_target.scalar(select(func.max(Trade.id)))
max_order_id = session_target.scalar(select(func.max(Order.id)))
# ... 同理查询 pairlock / kv / custom_data / wallet_history
set_sequence_ids(
    session_target.get_bind(),
    trade_id=(max_trade_id or 0) + 1,
    order_id=(max_order_id or 0) + 1,
    # ... 各表 max(id) + 1
)

这段处理只在目标库是 PostgreSQL 时生效——set_sequence_ids 内部以 engine.name == "postgresql" 为条件,对各序列执行 ALTER SEQUENCE ... RESTART WITH <max_id + 1>(涉及 trades_id_seqorders_id_seqpairlocks_id_seqKeyValueStore_id_seqtrade_custom_data_id_seqwallet_history_id_seq 六个序列)。从源码结构看,这正是跨库迁移最容易踩的坑:PostgreSQL 的自增序列不会因导入数据而自动推进,若不重置,新插入的行会与源库已有的主键冲突;而 SQLite 的自增由 rowid/sqlite_sequence 维护,则不需要此步骤。

整个迁移结束后,日志会输出形如 Migrated {n} Trades, {n} Pairlocks, {n} Key-Value pairs, {n} Custom Data entries, and {n} Wallet History entries. 的汇总信息,可据此核对迁移条数与源库是否一致。

使用示例

典型的"SQLite 迁往 PostgreSQL"操作方式是:

freqtrade convert-db \
    --db-url "postgresql://user:pass@host:5432/freqtrade" \
    --db-url-from "sqlite:///tradesv3.sqlite"

反向迁移(PostgreSQL 迁回 SQLite 或迁往另一个 PostgreSQL)同样适用,只需交换两个 URL 的角色。命令运行后会以 INFO 级别输出 Starting db migration. 与最终的迁移条数汇总。

注意事项与适用边界

  • 目标库必须是空库:官方在 utils.md 中明确警告——请确保只在空的目标数据库上使用此命令,因为 freqtrade 执行的是常规迁移,若目标库中已存在数据可能会失败。
  • 不依赖交易所凭据:从 RunMode.UTIL_NO_EXCHANGE 的启动方式看,该命令属于离线工具,不需要交易所 API key,可在无网络环境下对数据库文件直接操作。
  • 迁移范围:与 utils.md 的表述(trades、orders 与 PairLocks)一致,源码实际还覆盖 KeyValueStore、CustomData 与 WalletHistory 三类表,因此这是一次覆盖持久层全部业务表的完整迁移,而不仅是交易记录。
  • 适用前提:两个数据库的表结构需兼容(同一版本 freqtrade 建表)。数据库版本升级场景的表结构变更走的是启动时自动 schema 迁移机制,而非本命令;跨系统迁移时建议保持迁移前后 freqtrade 版本一致。
登录后查看全文
热门项目推荐
相关项目推荐