Freqtrade new-config 命令详解:交互式生成交易所配置文件的完整原理与实践
本篇围绕 Freqtrade 的 freqtrade new-config 命令展开,讲解如何通过一组交互式问答生成一份可运行的 config.json,并结合仓库源码剖析其命令注册、问答收集、Jinja2 模板渲染与文件写入的完整调用链。读完本文,你将掌握该命令的参数、每一项交互问题的作用与默认值、生成配置的结构组成,以及覆盖已存在文件等边界行为,从而独立完成从“零配置”到“可启动机器人”的第一步。
命令概览与 CLI 参数
new-config 是 Freqtrade 提供的配置生成子命令,官方文档页 docs/commands/new-config.md 给出了其命令行帮助输出:
usage: freqtrade new-config [-h] [-c PATH]
options:
-h, --help show this help message and exit
-c, --config PATH Specify configuration file (default:
`userdir/config.json` or `config.json` whichever exists).
Multiple --config options may be used. Can be set to `-`
to read config from stdin.
从源码可以确认该命令支持的参数非常精简。在 freqtrade/commands/arguments.py 中,子命令构建逻辑位于约 442 行处:
# add new-config subcommand
build_config_cmd = subparsers.add_parser(
"new-config",
help="Create new config",
)
build_config_cmd.set_defaults(func=start_new_config)
self._build_args(optionlist=ARGS_BUILD_CONFIG, parser=build_config_cmd)
其中 ARGS_BUILD_CONFIG = ["config"](同文件第 140 行),即该子命令仅挂载了 -c/--config 一个选项,用于指定要写入的新配置文件路径。若未指定,则按 Freqtrade 通用规则回退到 userdir/config.json 或 config.json(取已存在者)。
执行流程:start_new_config 做了什么
子命令的处理函数是 freqtrade/commands/build_config_commands.py 中的 start_new_config:
def start_new_config(args: dict[str, Any]) -> None:
"""
Create a new strategy from a template
Asking the user questions to fill out the template accordingly.
"""
from freqtrade.configuration.deploy_config import (
ask_user_config,
ask_user_overwrite,
deploy_new_config,
)
from freqtrade.configuration.directory_operations import chown_user_directory
config_path = Path(args["config"][0])
chown_user_directory(config_path.parent)
if config_path.exists():
overwrite = ask_user_overwrite(config_path)
if overwrite:
config_path.unlink()
else:
raise OperationalException(
f"Configuration file `{config_path}` already exists. "
"Please delete it or use a different configuration file name."
)
selections = ask_user_config()
deploy_new_config(config_path, selections)
整体流程可归纳为四步:
- 确定目标路径:取
--config的第一个值作为输出文件路径,并调用chown_user_directory调整所在目录属主(该函数在 freqtrade/configuration/directory_operations.py 中,主要用于 Docker 等容器场景下保证当前用户可写)。 - 覆盖确认:若目标文件已存在,则调用
ask_user_overwrite弹出确认框;用户拒绝时抛出OperationalException,提示删除该文件或改用其他文件名;用户同意则先删除旧文件再重建。 - 交互式问答:
ask_user_config()收集全部配置选项,返回一个键值字典。 - 模板渲染与落盘:
deploy_new_config(config_path, selections)将选项填入 Jinja2 模板并写入磁盘。
交互式问答:ask_user_config 的问题清单
问答逻辑集中在 freqtrade/configuration/deploy_config.py 的 ask_user_config(),底层使用 questionary 库(支持 confirm/text/select/password/autocomplete 等题型)。问题按顺序如下,各项均有内置默认值:
| 问题字段 | 题型 | 含义与默认值 |
|---|---|---|
dry_run |
confirm | 是否启用 Dry-run 模拟交易,默认 True |
stake_currency |
text | 计价货币,默认 USDT |
stake_amount |
text | 单笔投入金额(数字或 unlimited),默认 unlimited,并做浮点数校验 |
max_open_trades |
text | 最大同时持仓数(整数,-1 表示不限制),默认 3 |
timeframe_in_config |
select | 选择“由策略定义时间框架”还是“在配置中覆盖” |
timeframe |
text | 仅当上一项选择“在配置中覆盖”时出现,默认 5m |
fiat_display_currency |
text | 报表用的法币显示货币(留空可禁用法币换算),默认 USD |
exchange_name |
select | 从 binance、binanceus、bingx、gate、htx、kraken、kucoin、okx 中选择,或选 other 后输入 ccxt 支持的任意交易所(autocomplete 题型给出 available_exchanges() 提示) |
trading_mode |
confirm | 是否交易永续合约(perpetual futures),默认 False;仅当交易所为 binance、gate、okx、bybit 时才提问,答案会被过滤为 futures/spot |
exchange_api_key / exchange_secret |
password | 仅在关闭 dry_run 时提问 |
exchange_api_key_password |
password | 仅当非 dry-run 且交易所为 kucoin、okx 时提问 |
telegram / telegram_token / telegram_chat_id |
confirm + password | 是否启用 Telegram 通知及凭据 |
api_server |
confirm | 是否启用 REST API(含 FreqUI),默认 False |
api_server_listen_addr |
text | API 监听地址,Docker 内默认 0.0.0.0,否则默认 127.0.0.1(该默认值由 running_in_docker() 检测决定) |
api_server_username / api_server_password |
text/password | API 用户名默认 freqtrader,密码必填 |
问答结束后还有几个关键的后置处理(deploy_config.py):
answers = prompt(questions)
if not answers:
# Interrupted questionary sessions return an empty dict.
raise OperationalException("User interrupted interactive questions.")
# Ensure default is set for non-futures exchanges
answers["trading_mode"] = answers.get("trading_mode", "spot")
answers["margin_mode"] = "isolated" if answers.get("trading_mode") == "futures" else ""
# Force JWT token to be a random string
answers["api_server_jwt_key"] = secrets.token_hex()
answers["api_server_ws_token"] = secrets.token_urlsafe(25)
- 用户在交互中直接退出(Ctrl-C 等)会返回空字典,此时命令以
OperationalException("User interrupted interactive questions.")终止; - 非期货交易所统一补默认值
trading_mode = "spot"、margin_mode = "";期货则默认margin_mode = "isolated"(逐仓); - 自动生成随机密钥:无论是否启用 API,
api_server_jwt_key(secrets.token_hex())与api_server_ws_token(secrets.token_urlsafe(25))都会被随机填充,保证每次生成的配置都有不可预测的鉴权凭据。
模板渲染:从选项到 JSON 文件
deploy_new_config() 是真正产出配置文件的函数(deploy_config.py):
def deploy_new_config(config_path: Path, selections: dict[str, Any]) -> None:
from jinja2.exceptions import TemplateNotFound
from freqtrade.exchange import MAP_EXCHANGE_CHILDCLASS
from freqtrade.util import render_template
try:
exchange_template = MAP_EXCHANGE_CHILDCLASS.get(
selections["exchange_name"], selections["exchange_name"]
)
selections["exchange"] = render_template(
templatefile=f"subtemplates/exchange_{exchange_template}.j2", arguments=selections
)
except TemplateNotFound:
selections["exchange"] = render_template(
templatefile="subtemplates/exchange_generic.j2", arguments=selections
)
config_text = render_template(templatefile="base_config.json.j2", arguments=selections)
logger.info(f"Writing config to `{config_path}`.")
...
config_path.write_text(config_text)
其工作分两层:
-
交易所子模板:优先查找 freqtrade/templates/subtemplates/ 目录下与所选交易所对应的子模板(如
exchange_binance.j2、exchange_kucoin.j2等);若该交易所在 Freqtrade 中没有专属子类(MAP_EXCHANGE_CHILDCLASS查不到或模板不存在),则回退到通用模板 exchange_generic.j2。以 exchange_binance.j2 为例,Binance 专属模板会额外预置pair_blacklist: ["BNB/.*"],而通用模板的黑白名单为空数组:"exchange": { "name": "binance", "api_key": "...", "secret": "...", "ccxt_config": {}, "ccxt_async_config": {}, "pair_whitelist": [ ], "pair_blacklist": [ "BNB/.*" ] } -
主模板:用问答结果渲染 freqtrade/templates/base_config.json.j2,生成最终 JSON。
生成配置的结构组成
以主模板为据,生成出的 config.json 至少包含以下段落({{ }} 为按问答填充的变量):
- 顶层策略参数:
max_open_trades、stake_currency、stake_amount、tradable_balance_ratio(固定0.99)、dry_run、dry_run_wallet(固定1000)、trading_mode、margin_mode;仅当选择“在配置中覆盖时间框架”时才会写入timeframe字段;fiat_display_currency为空时整行省略; - 订单与定价:
unfilledtimeout(entry/exit 均 10 分钟,单位 minutes)、entry_pricing与exit_pricing(price_side: same、use_order_book: true、order_book_top: 1等); - exchange 段:即上面子模板渲染结果;
- pairlists:默认写入一个
VolumePairList(number_assets: 20、sort_key: quoteVolume、refresh_period: 1800),即按交易量挑选前 20 个资产; - telegram:
enabled与 token/chat_id; - api_server:监听地址、
listen_port固定8080、随机生成的jwt_secret_key与ws_token、用户名密码; - 其余:
bot_name: freqtrade、initial_state: running、force_entry_enable: false、internals.process_throttle_secs: 5; - 文件首行引用了
$schema(https://schema.freqtrade.io/schema.json),便于编辑器对配置做校验与补全。
测试用例验证的边界行为
单元测试 tests/commands/test_build_config.py 对上述实现做了逐项验证,可作为行为依据:
test_start_new_config:分别以bybit、binance、kraken三个交易所为参数,模拟“文件已存在并确认覆盖”的场景,断言日志中出现Writing config to ...、write_text只调用一次、旧文件被unlink一次,且渲染结果中exchange.name、api_key、timeframe与输入一致;test_start_new_config_exists:文件已存在但用户拒绝覆盖时,抛出匹配Configuration .* already exists\.的OperationalException;test_validate_is_int/test_validate_is_float:确认max_open_trades的整型校验("2.0"、"-ee"均不通过)与stake_amount的浮点校验("2.0"、"-0.5"通过,"-0.5e"不通过);test_ask_user_config:当 questionary 返回空字典(用户中断)时抛出User interrupted interactive questions.。
小结与后续步骤
new-config 的价值在于把一份易错的手工配置变成了“问答 + 模板”的确定性流程:交互式问答(ask_user_config)→ 交易所子模板选择(专属模板优先、通用模板兜底)→ 主模板渲染 → 写入目标路径,同时自动随机化 JWT 与 WebSocket 令牌、对中断和覆盖场景给出明确异常。生成配置后,日志会提示“Please make sure to check the configuration contents and adjust settings to your needs”,建议结合 配置参考文档 核对各字段,并可通过 freqtrade show-config 命令查看最终合并后的有效配置。完整字段语义可进一步对照 freqtrade/config_schema/ 中的配置校验逻辑阅读。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00