第 4 章 · 03 Trade 对象


文档摘要

第 4 章 · 03 Trade 对象 本节摘要:回调函数(上一节)里反复出现的 参数,就是 对象——每一笔未平仓持仓在代码里的抽象。它由引擎创建并持久化到 SQLite,在回调中传给你只读使用(不能直接改属性)。本节讲透 Trade 的核心字段:基础信息( / / )、价格与仓位( / / )、盈亏( 是回调参数, / 是字段)、止损( / )、合约特有( / / ),以及几个最常用的类方法( / / )。读完本节,你能在任意回调里安全地读 trade 的状态,做出基于持仓信息的决策。 内容来源:原项目文档 、源码 ,汉化并套用体系化模板。 学习目标 阅读完本节,你应当能够: 说清 在引擎与策略之间的传递方向(只读)。 列举基础信息字段: / / / / / 。

第 4 章 · 03 Trade 对象

本节摘要:回调函数(上一节)里反复出现的 trade 参数,就是 Trade 对象——每一笔未平仓持仓在代码里的抽象。它由引擎创建并持久化到 SQLite,在回调中传给你只读使用(不能直接改属性)。本节讲透 Trade 的核心字段:基础信息(pair/is_short/open_date_utc)、价格与仓位(open_rate/amount/stake_amount)、盈亏(current_profit 是回调参数,realized_profit/close_profit 是字段)、止损(stop_loss/stop_loss_pct)、合约特有(leverage/liquidation_price/funding_fees),以及几个最常用的类方法(get_trades_proxy/get_open_trade_count/get_total_closed_profit)。读完本节,你能在任意回调里安全地读 trade 的状态,做出基于持仓信息的决策。

内容来源:原项目文档 docs/trade-object.md、源码 freqtrade/persistence/trade_model.py,汉化并套用体系化模板。

学习目标

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

  1. 说清 Trade 在引擎与策略之间的传递方向(只读)。
  2. 列举基础信息字段:pair/is_open/is_short/open_date_utc/enter_tag/exit_reason
  3. 列举价格与仓位字段:open_rate/amount/stake_amount/max_stake_amount
  4. 区分盈亏字段:current_profit(回调参数)、realized_profitclose_profit
  5. 列举止损字段:stop_loss/stop_loss_pct/initial_stop_loss/stoploss_or_liquidation
  6. 列举合约特有字段:leverage/liquidation_price/funding_fees/interest_rate
  7. 在回调用 Trade.get_trades_proxy() 查历史,避开 backtesting 不支持的类方法

一、Trade 是什么:持久化的持仓

引擎开仓时,创建一个 Trade 对象并存入 SQLite;每次迭代从库里取出所有 is_open=True 的 trade,逐个判断要不要平仓、要不要补仓;平仓后 is_open=False 但记录保留。

💡 只读原则:文档明确「The object passed to the strategy cannot be modified directly」——回调里不要trade.open_rate = xxx,这不会生效或导致状态不一致。要改 trade,通过回调的返回值(custom_stoploss 返回止损比例、adjust_trade_position 返回加减仓量等),让引擎代为执行。

二、基础信息字段

字段 类型 说明
pair str 交易对,如 "ETH/USDT"
is_open bool 是否仍持仓
is_short bool 是否做空
trade_direction str "long"/"short"(文字)
entry_side/exit_side str 入/出场方向("buy"/"sell")
exchange str 交易所名
strategy str 所属策略名
open_date_utc datetime 开仓时间(UTC,优先用它而非 open_date)
close_date_utc datetime 平仓时间(仅 is_open=False)
enter_tag str 入场标签(来自 DataFrame 的 enter_tag 列)
exit_reason str 出场理由("stop_loss"/"roi"/"exit_signal"/custom_exit 返回的字符串)

enter_tagexit_reason 是策略可观测性的关键——你可以给不同入场条件打不同 tag,事后统计哪类信号表现好。

三、价格与仓位字段

字段 类型 说明
open_rate float 实际开仓均价(DCA 加仓后会重算)
open_rate_requested float 请求的开仓价(可能与成交价不同)
close_rate float 平仓价(仅 is_open=False)
amount float 持有的 base 币数量(初始订单成交前为 0)
amount_requested float 请求的数量
stake_amount float 当前投入的 quote 币金额
max_stake_amount float 历史最大 stake(DCA 后增加)
open_trade_value float 含费用的开仓总值
leverage float 杠杆倍数(现货为 1.0)

注意 open_rate 是「均价」——DCA 加仓后,引擎会按新的总量与总投入重新算均价。这也是为什么 current_profit 相对 open_rate 计算时,DCA 后会「摊低」浮亏。

四、盈亏:三个层次

盈亏在 freqtrade 里分三个层次,容易混淆:

名称 何时存在 含义
current_profit 仅 open 时,回调参数(不是字段) 当前未实现浮盈比例(0.01=1%)
realized_profit open 与 closed 都有,字段 部分平仓已锁定的绝对盈亏(stake 币计)
close_profit 仅 closed,字段 最终平仓的相对盈亏比例
close_profit_abs 仅 closed,字段 最终平仓的绝对盈亏(stake 币计)

💡 realized_profit 何时非零:只有用了 adjust_trade_position部分平仓(返回负数),才会有部分仓位被锁定盈亏。没做部分平仓,realized_profit 一直是 0,直到完全平仓。

回调里要算「总盈亏」,需要把 current_profit(浮盈)与已实现盈亏合并。最稳妥的做法是用 trade.realized_profit + current_profit * trade.stake_amount(近似,严格公式见文档)。

五、止损相关字段

字段 说明
stop_loss 当前止损价(绝对值,会随 custom_stoploss/trailing 更新)
stop_loss_pct 当前止损比例(相对开仓价)
initial_stop_loss 初始止损价(开仓时的,不更新)
initial_stop_loss_pct 初始止损比例
stoploss_or_liquidation 「止损价」与「强平价」中更激进的那个——实际的强制出场价
stoploss_last_update_utc 止损最后更新时间

initial_stop_loss_* 让你能比较「当前止损 vs 初始止损」——常用于判断「是否已经把止损上移到保本位」。

六、合约特有字段

字段 说明
liquidation_price 强平价(杠杆持仓才会被强平)
funding_fees 资金费累计(永续合约)
interest_rate 利率(保证金交易)

合约里 stoploss_or_liquidation 取「止损」与「强平」更紧的那个——如果你的止损比强平价还远,实际会在强平时被爆,这是合约交易要小心的。

七、其他常用字段

  • max_rate / min_rate:持仓期间到达过的最高/最低价(用于追踪止损判断,不是 100% 精确,回测里按 K 线极值)。
  • nr_of_successful_entries / nr_of_successful_exits:已成交的入/出场订单数(DCA 判断「加过仓没」的关键)。
  • has_open_position:是否有实际持仓(初始订单未成交前为 False)。
  • has_open_orders / open_orders:是否有挂单 / 挂单列表。
  • orders:订单列表(含已成交与已取消),每个 Order 又有自己的字段(见下一节)。

八、类方法:从策略主动查 Trade

Trade 还有类方法(用 Trade.xxx() 调),用于跨笔查询:

from freqtrade.persistence import Trade # 当前 open trades 数 n = Trade.get_open_trade_count() # 查最近 2 天的已平仓 trade from datetime import timedelta history = Trade.get_trades_proxy(is_open=False, open_date=current_time - timedelta(days=2)) # 累计已实现盈亏 total = Trade.get_total_closed_profit() # 当前所有 open trades 占用的总 stake total_stake = Trade.total_open_trades_stakes()

get_trades_proxy 参数

  • pair:按交易对过滤。
  • is_open:True 仅 open,False 仅 closed,不传=全部。
  • open_date / close_date:按开/平仓时间过滤。

⚠️ backtesting 限制:大多数类方法在 backtesting 里只在回调中可用,在 populate_* 方法里不支持(会得到错误结果)。get_overall_performanceget_trading_volume 在 backtesting 里完全不支持,需要先判断 self.config['runmode']

九、在回调里安全使用 Trade

完整例子——「持仓期间最大回撤超过 8% 就出场」:

from datetime import datetime from freqtrade.persistence import Trade def custom_exit(self, pair, trade, current_time, current_rate, current_profit, **kwargs): # 最大回撤 = (max_rate - current_rate) / max_rate if trade.max_rate > 0: drawdown = (trade.max_rate - current_rate) / trade.max_rate if drawdown > 0.08: return "max_drawdown_exit" # 持仓超过 1 天且微亏,止损走人 if (current_time - trade.open_date_utc).days >= 1 and current_profit < -0.02: return "timeout" return None

注意:

  • trade 字段,不写。
  • trade.max_ratetrade.open_date_utc 这些字段做判断。
  • 返回字符串作为 exit_reason,事后可统计。

本节要点回顾

  1. 本质:Trade 是持久化的持仓抽象,引擎创建并传给回调,只读使用,修改通过回调返回值。
  2. 基础字段:pair/is_short/trade_direction/open_date_utc/enter_tag/exit_reason,优先用 _utc 后缀的时间字段。
  3. 价格仓位:open_rate(DCA 后是均价)/amount/stake_amount/max_stake_amount
  4. 盈亏三层次:current_profit(浮盈,回调参数)/realized_profit(部分平仓锁定)/close_profit(最终);总盈亏需合并。
  5. 止损字段:stop_loss(会更新)/initial_stop_loss(原始)/stoploss_or_liquidation(止损与强平更紧者)。
  6. 合约特有:leverage/liquidation_price/funding_fees/interest_rate
  7. 类方法:Trade.get_trades_proxy() 查历史、get_open_trade_count 查数量、get_total_closed_profit 查累计盈亏;backtesting 中只在回调里可用,populate_* 里不可用。

下一节,我们用 Trade 字段实打实地做「追踪止损」——trailing_stop 配置与 custom_stoploss 实战。


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