第 9 章 · 03 做空交易 本节摘要:做空就是「先卖后买」,从价格下跌中获利。freqtrade 通过 / 列产生做空信号,要求策略类声明 ,且必须在合约( )模式下。本节讲清三件事:做空信号在策略里的写法约定、现货做空(只能靠 BTCDOWN 这类杠杆代币)与合约做空的差异、做空特有的风控要点——做空的亏损理论上是无限的(价格可以涨到任意高),所以止损纪律比做多更严格。读完你能在策略里正确实现并管理做空逻辑。 内容来源:原项目文档 、 ,汉化并套用体系化模板。 ⚠️ 风险提示:做空的亏损理论上是无限的(资产价格没有上限),而做多最多亏 100%。做空务必设严格止损,且优先用 isolated 保证金模式隔离风险。
本节摘要:做空就是「先卖后买」,从价格下跌中获利。freqtrade 通过
enter_short/exit_short列产生做空信号,要求策略类声明can_short = True,且必须在合约(futures)模式下。本节讲清三件事:做空信号在策略里的写法约定、现货做空(只能靠 BTCDOWN 这类杠杆代币)与合约做空的差异、做空特有的风控要点——做空的亏损理论上是无限的(价格可以涨到任意高),所以止损纪律比做多更严格。读完你能在策略里正确实现并管理做空逻辑。
内容来源:原项目文档
docs/leverage.md、docs/strategy-callbacks.md,汉化并套用体系化模板。
⚠️ 风险提示:做空的亏损理论上是无限的(资产价格没有上限),而做多最多亏 100%。做空务必设严格止损,且优先用 isolated 保证金模式隔离风险。
阅读完本节,你应当能够:
exit_reason 正确区分多空平仓。freqtrade 用两套平行的信号列管理多空:
| 方向 | 入场列 | 出场列 | 含义 |
|---|---|---|---|
| 做多 | enter_long |
exit_long |
价格看涨,先买后卖 |
| 做空 | enter_short |
exit_short |
价格看跌,先卖后买 |
| 共用 | enter_tag |
— | 入场标签(多空共用,区分来源) |
做空在 populate_entry_trend / populate_exit_trend 里的写法与做多完全对称:
def populate_entry_trend(self, df, metadata): # 做多:预测值为正且模型有信心 enter_long_conditions = [df["do_predict"] == 1, df["&-s_close"] > 0.01] df.loc[ reduce(lambda x, y: x & y, enter_long_conditions), ["enter_long", "enter_tag"] ] = (1, "long") # 做空:预测值为负且模型有信心 enter_short_conditions = [df["do_predict"] == 1, df["&-s_close"] < -0.01] df.loc[ reduce(lambda x, y: x & y, enter_short_conditions), ["enter_short", "enter_tag"] ] = (1, "short") return df def populate_exit_trend(self, df, metadata): # 平多:预测值转负 df.loc[(df["do_predict"]==1) & (df["&-s_close"] < 0), "exit_long"] = 1 # 平空:预测值转正 df.loc[(df["do_predict"]==1) & (df["&-s_close"] > 0), "exit_short"] = 1 return df
💡 信号语义:设
enter_short=1表示「产生做空入场信号」。freqtrade 看到后会在交易所执行做空操作(合约模式下)。exit_short=1表示「平掉空头仓位」。
策略类必须显式声明能做空:
class MyShortStrategy(IStrategy): can_short = True # 必须显式设 True # ...
can_short 的前提条件:
trading_mode 必须是 futures(或 margin,目前未开放)。现货模式(spot)下,即使 can_short = True 也无法做空。"trading_mode": "futures" 和 "margin_mode": "isolated"(或 cross)。⚠️ 如果策略里写了
enter_short信号但can_short = False(或现货模式),这些信号会被静默忽略——不会报错,但也不会做空。排查「为什么不做空」时先查这两项。
现货市场不能真正做空。现货只有「买了再卖」,没有「借币先卖」。但在现货市场上有两种「伪做空」方式:
BTCDOWN/USDT、ETHBEAR/USD,这些代币的设计是标的资产跌它就涨。freqtrade 可以交易它们,但本质是「做多一个看跌代币」,不是真做空。trading_mode: "margin" 的模式,交易所借币给你卖,但目前 freqtrade 未开放。合约做空才是真正的做空。在永续合约市场,你可以直接「卖出」一个你并不拥有的合约仓位,价格跌了再买回来平仓。这才是 freqtrade 里 enter_short 的标准用法:
"trading_mode": "futures", "margin_mode": "isolated"
| 维度 | 现货(杠杆代币) | 合约(真做空) |
|---|---|---|
| 机制 | 做多看跌代币 | 直接卖空合约 |
| 配置 | trading_mode: spot |
trading_mode: futures |
| 信号 | enter_long(把代币当普通币做多) |
enter_short |
| 杠杆 | 通常无(代币本身带杠杆) | 可配 |
| 强平 | 无 | 有 |
| 资金费率 | 无 | 有 |
💡 多数情况下「做空」指合约做空。如果你在现货模式交易 BTCDOWN,那只是做多一个特殊代币,策略逻辑和真做空不同(代币有损耗、再平衡机制)。
做空的风险特征与做多有本质不同,必须区别对待:
1. 亏损理论无限
做多最多亏 100%(价格归零)。做空的理论亏损没有上限——资产价格可以涨到任意高。比如 10 美元做空,价格涨到 100 美元,你亏 900%;涨到 1000 美元,亏 9900%。虽然强平机制会在保证金耗尽时止损,但这意味着做空的止损纪律必须比做多更严格,绝不能裸空(不设止损)。
2. 强平更近
做空时,价格上涨触发强平。配合杠杆,价格上涨一点点就可能强平。比如 10 倍杠杆做空,价格上涨约 10% 就可能强平(具体取决于保证金模式和维持保证金率)。
3. 借币成本
合约做空涉及借币,可能有利息或资金费率成本。资金费率为正时空头收钱、多头付钱;费率为负则相反。长期持仓的成本会侵蚀利润。
4. 「轧空」风险
某些小币种流动性差,一旦上涨可能引发空头被迫平仓(买回),推高价格,形成「轧空」螺旋,导致亏损远超预期。做空要避开流动性差的标的。
合约模式下,多空的保证金计算方向相反:
所有费用(包括资金费率)都计入 current_profit 计算。
平仓后,exit_reason 会区分多空来源。常见的 exit_reason(注意 v3 命名):
| exit_reason | 含义 |
|---|---|
exit_signal |
策略出场信号触发 |
stop_loss / stoploss_on_exchange / trailing_stop_loss |
止损触发 |
roi |
到达 ROI 目标 |
custom_exit |
自定义出场回调 |
force_exit |
手动强制平仓(Telegram/API) |
emergency_exit |
紧急平仓 |
策略里如果用 exit_reason 做逻辑判断,注意用 v3 的新名字(老的 sell_signal 等已废弃)。
💡 Telegram 里有
/profit_long和/profit_short分别看多头和空头的盈亏,方便单独评估做空表现。
freqtrade 的多空逻辑是对称的——enter_long/exit_long 与 enter_short/exit_short 成对出现,回调(如 custom_exit、custom_stoploss)都会收到 trade.is_short 让你按方向分支处理。但实战中做多和做空并不完全等价,需注意:
趋势市与震荡市的差异:加密货币长期有「上涨 bias」(尤其 BTC),牛市里做空胜率天然偏低;熊市里做多同理。策略应结合大周期趋势过滤方向,避免逆势死扛。可用 informative_pair 取大周期均线判断趋势,只在顺势方向开仓。
仓位隔离:同一交易对,freqtrade 不会同时开多和开空(一个币对一个仓位)。先平掉旧仓位才能开反向。adjust_trade_position 回调可用来加减仓,但不能反向。
资金费率方向:资金费率为正时,多头付钱给空头——这对做空是个额外优势(收资金费)。反之费率为负时空头要付钱。长期做空要把资金费率成本算进预期收益。
# 趋势过滤示例:只在 1h 趋势向上时做多,向下时做空 def populate_entry_trend(self, df, metadata): df_trend = self.dp.get_pair_dataframe(pair, '1h') ema_200 = ta.EMA(df_trend, 200) uptrend = ema_200.iloc[-1] > ema_200.iloc[-2] if uptrend: df.loc[(df['rsi'] < 30), ['enter_long','enter_tag']] = (1, 'long_uptrend') else: df.loc[(df['rsi'] > 70), ['enter_short','enter_tag']] = (1, 'short_downtrend') return df
⚠️ 不要为了「对冲」同时开多空。freqtrade 一个币对一个仓位的设计不支持对冲,且对冲在永续合约里通常因资金费率和手续费反而亏更多。真要分散风险,用不同币种、降低单币杠杆更有效。
enter_short / exit_short 与 enter_long / exit_long 对称;enter_tag 多空共用。can_short = True,且 trading_mode 必须是 futures;现货模式下信号被静默忽略。current_profit;exit_reason 用 v3 命名(/profit_short 单看空头)。下一节,我们看生产者-消费者集群——一个 bot 出信号、多个 bot 跟单的协同模式。