第 2 章 · 01 交易主循环与状态机


文档摘要

第 2 章 · 01 交易主循环与状态机 本节摘要:本节把 freqtrade 的「心跳」拆给你看。机器人的所有动作——拉行情、问策略、下单、风控——都由一个由两层组成的循环驱动:外层 用 throttle(节流)机制每隔几秒唤醒一次,并对齐到 K 线边界;内层 在每次唤醒时执行完整的「数据→策略→订单→持仓」闭环。整个机器人在任意时刻处于四种状态之一(RUNNING/PAUSED/STOPPED/RELOADCONFIG),由这个状态机决定该不该交易、要不要重载配置。读完本节,你能用一张图画清 freqtrade 进程从启动到退出的全部控制流,并在出问题时知道去看哪个环节。 内容来源:原项目源码 、 、 ,文档 ,汉化并套用体系化模板。

第 2 章 · 01 交易主循环与状态机

本节摘要:本节把 freqtrade 的「心跳」拆给你看。机器人的所有动作——拉行情、问策略、下单、风控——都由一个由两层组成的循环驱动:外层 Worker 用 throttle(节流)机制每隔几秒唤醒一次,并对齐到 K 线边界;内层 FreqtradeBot.process() 在每次唤醒时执行完整的「数据→策略→订单→持仓」闭环。整个机器人在任意时刻处于四种状态之一(RUNNING/PAUSED/STOPPED/RELOAD_CONFIG),由这个状态机决定该不该交易、要不要重载配置。读完本节,你能用一张图画清 freqtrade 进程从启动到退出的全部控制流,并在出问题时知道去看哪个环节。

内容来源:原项目源码 freqtrade/worker.pyfreqtrade/freqtradebot.pyfreqtrade/enums/state.py,文档 docs/bot-basics.md,汉化并套用体系化模板。

⚠️ 风险提示:理解主循环是排查实盘异常的前提——「为什么我的信号没触发」「为什么止损没生效」往往都能从循环执行时序里找到答案。实盘前务必先在 Dry-Run 下观察循环行为。

学习目标

阅读完本节,你应当能够:

  1. 画出 Worker 与 FreqtradeBot 的两层循环结构。
  2. 说清 throttle 节流如何把迭代对齐到 K 线收盘。
  3. 列举 State 的四个取值及它们之间的转换条件。
  4. 描述 FreqtradeBot.process() 一次迭代内的 8 个核心步骤
  5. 区分 STOPPED 与 PAUSED 的差异。
  6. 在排查异常时知道问题对应循环中的哪一步

一、两层结构:Worker 是外壳,FreqtradeBot 是引擎

freqtrade 进程启动后,控制权先交给 Worker,它再创建一个 FreqtradeBot 实例。两者职责分明:

  • Worker:负责「什么时候跑」——循环调度、节流、状态机切换、捕获异常、与 systemd watchdog 通信。
  • FreqtradeBot:负责「跑什么」——拉数据、问策略、下单、风控、记账,是真正的交易引擎。

💡 核心心法:把「调度」和「业务」分到两个类,是 freqtrade 能稳定长跑的关键——业务代码抛异常不会让循环崩掉,调度层会捕获并按状态机决定下一步。

二、Worker 的 throttle 节流

Worker.run() 是一个无限循环,但每次迭代之间必须休眠——既是为了省 CPU,更是为了对齐到 K 线收盘时刻,避免在 K 线未成形时算指标。

节流的核心逻辑(_throttle() 方法):

  1. 记录本次迭代开始时间。
  2. 调用业务函数(如 process())。
  3. 计算「已耗时」,得 sleep_duration = throttle_secs - 已耗时
  4. 如果传入了 timeframe,进一步把 sleep_duration 夹取到「下一根 K 线收盘 + 1 秒」——确保唤醒时新 K 线已就绪。
  5. 休眠后再进入下一轮。

两个关键参数(在配置文件的 internals 段):

参数 默认 作用
process_throttle_secs 5 业务迭代的最小间隔秒数
heartbeat_interval 60 心跳日志间隔(0 关闭)

⚠️ 不要把 process_throttle_secs 调到 1 以下:迭代内会做大量网络请求与 DataFrame 计算,过快的循环既无意义(指标在 K 线收盘前不会变)又会触发交易所限流。

三、State 状态机:四种状态与转换

State 是一个 Python 枚举(源码 freqtrade/enums/state.py),定义了机器人的四种状态:

状态 数值 含义
RUNNING 1 正常运行,会执行 process() 全流程
PAUSED 2 暂停——不开新仓,但已有持仓仍被监控、可被止损/ROI 平仓
STOPPED 3 停止——不再交易,等待用户手动清仓后退出
RELOAD_CONFIG 4 重载配置——清理当前实例,重新读 JSON,重建 FreqtradeBot

状态切换由用户通过 Telegram(/start/stop/pause/reload_config)或 WebUI 触发,引擎内部修改 freqtrade.state 后,下一轮 _worker() 调用就会读到新状态。

💡 PAUSED 与 STOPPED 的关键差异:PAUSED 只是不开新仓,旧仓照常管理(可以止损出场);STOPPED 几乎完全停摆,只检查是否还有未平仓。临时观望用 pause,要下线维护用 stop

四、FreqtradeBot.process():一次迭代做了什么

当状态是 RUNNINGPAUSED 时,每次唤醒都会调用 FreqtradeBot.process()。这是引擎的真正心脏,完成一个完整的「拉数据 → 问策略 → 管持仓 → 开新仓」闭环(顺序按源码与文档):

  1. 加载未平仓:从 SQLite 取出所有 open trades。
  2. 刷新白名单:计算当前可交易对列表(详见第 03 节)。
  3. 下载 OHLCV:为白名单及 informative pair 拉行情,每根 K 线只拉一次以省流量。
  4. bot_loop_start 回调:策略的每轮起始钩子(第 4 章详讲)。
  5. 逐对分析策略:依次调用 populate_indicatorspopulate_entry_trendpopulate_exit_trend,把信号挂回 DataFrame。
  6. 更新持仓订单状态:查交易所订单是否成交,触发 order_filled 回调;检查超时订单,触发 adjust_order_price
  7. 管理已有持仓:综合考虑 stoploss、minimal_roi、出场信号、custom_exitcustom_stoploss 决定是否平仓;平仓前调用 confirm_trade_exit
  8. 开新仓(仅 RUNNING):检查 max_open_trades 是否还有空位,扫描入场信号,通过 entry_pricingcustom_entry_price 定价,经 confirm_trade_entry 最后确认后下单。

五、异常处理:循环为什么不会崩

_process_running() 用两层异常捕获保护循环:

  • TemporaryError:临时错误(网络抖动等),记日志后 RETRY_TIMEOUT 秒重试,状态不变。
  • OperationalException:严重错误(策略代码崩溃、配置非法等),记完整 traceback,推送 Telegram 通知,并把状态自动切到 STOPPED——防止异常状态下继续乱下单。

⚠️ 看到 Telegram 收到 OperationalException 通知一定要重视:引擎已经自保进入 STOPPED,需要你 /start 才会恢复;在没排查清楚前别盲目重启,否则可能反复崩在同一个错。

六、RELOAD_CONFIG:热重载配置

收到 /reload_config 后,Worker 进入 _reconfigure() 流程:

  1. 通知 systemd「正在重载」。
  2. 调用 freqtrade.cleanup(),取消所有未成交订单(已成交持仓保留)。
  3. 重新读取 JSON 配置,创建全新的 FreqtradeBot 实例。
  4. 通知 systemd「重载完成」,状态回到 RUNNING。

这是不重启进程就能改参数(如调整 max_open_trades、更换策略)的官方途径。注意:策略文件本身的修改不一定能通过 reload 生效——策略类是在实例化时加载的,通常需要重启进程。

本节要点回顾

  1. 两层结构:Worker 负责调度与状态机,FreqtradeBot 负责业务闭环;分离让循环对业务异常免疫。
  2. throttle 节流:process_throttle_secs(默认 5 秒)控制最小间隔,且自动对齐 K 线收盘 +1 秒,避免在半根 K 线上算指标。
  3. 四个状态:RUNNING(全跑)、PAUSED(不开新仓但管旧仓)、STOPPED(几乎停摆,等清仓)、RELOAD_CONFIG(热重载)。
  4. process 八步:取未平仓 → 刷新白名单 → 下载行情 → bot_loop_start → 跑策略 → 更新订单 → 管持仓 → 开新仓。
  5. 异常自保:TemporaryError 重试,OperationalException 自动 STOPPED 并通知,避免异常态乱下单。
  6. 热重载:/reload_config 不重启进程换参数,但策略文件改动通常需要重启进程。

下一节,我们看主循环赖以驱动的「大脑」——配置文件 JSON 的完整结构,以及交易所、风控、并发等关键参数如何设置。


发布者: 作者: 灏天文库 转发
评论区 (0)
U