DEV Community

Henry Lin
Henry Lin

Posted on

第 24.2 课:Freqtrade实盘交易止损操作详解

第 24.2 课:实盘交易止损操作详解

⏱ 课时:2 小时
🎯 学习目标:掌握各种止损策略,学会在实盘中有效控制风险


课程概述

止损是实盘交易中最重要的风险控制工具。一个没有止损策略的交易系统,就像一辆没有刹车的汽车。

本课重点

止损不是失败,而是为了保护本金,让交易能够继续下去。

本课将详细介绍:

  • 各种止损类型的实现和应用
  • Freqtrade中的止损配置
  • 动态止损和追踪止损
  • 止损优化技巧

第一部分:止损类型详解

1.1 固定止损(Fixed Stop Loss)

1.1.1 基本概念

固定止损是最简单的止损方式,基于买入价格设置固定的百分比。

计算公式

止损价格 = 买入价格 × (1 - 止损百分比)
Enter fullscreen mode Exit fullscreen mode

示例

买入价: $30,000
止损: -5%
止损价: $30,000 × (1 - 0.05) = $28,500
Enter fullscreen mode Exit fullscreen mode

1.1.2 Freqtrade配置

{
  "stoploss": -0.05,
  "stoploss_type": "standard",
  "stoploss_on_exchange": true,
  "stoploss_on_exchange_interval": 60
}
Enter fullscreen mode Exit fullscreen mode

策略示例

class FixedStopLossStrategy(IStrategy):
    # 设置5%固定止损
    stoploss = -0.05

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # 买入信号逻辑
        return dataframe
Enter fullscreen mode Exit fullscreen mode

1.1.3 优缺点分析

优点

✅ 简单直观,容易理解
✅ 计算简便,系统开销小
✅ 适合新手
✅ 在正常市场中表现稳定
Enter fullscreen mode Exit fullscreen mode

缺点

❌ 不能适应市场波动性变化
❌ 可能被正常波动触发
❌ 在高波动市场中可能过于激进
❌ 不能追踪盈利
Enter fullscreen mode Exit fullscreen mode

1.2 动态止损(Dynamic Stop Loss)

1.2.1 基于ATR的止损

ATR(Average True Range):平均真实波幅,衡量市场波动性。

计算公式

ATR = 过去N天的真实波幅平均值
止损价 = 当前价格 - (ATR × N倍数)
Enter fullscreen mode Exit fullscreen mode

策略实现

import pandas as pd
import talib.abstract as ta

class ATRStopLossStrategy(IStrategy):
    # 使用动态止损
    use_custom_stoploss = True

    # 最小止损
    stoploss = -0.10

    def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
                       current_rate: float, current_profit: float, **kwargs) -> float:

        # 获取历史数据
        dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
        last_candle = dataframe.iloc[-1].squeeze()

        # 计算ATR
        atr = last_candle['atr']

        # 计算动态止损 (2倍ATR)
        atr_multiplier = 2
        stoploss_pct = (atr * atr_multiplier) / current_rate

        # 确保止损不超过-15%
        stoploss_pct = min(stoploss_pct, 0.15)

        # 确保止损不小于-2%
        stoploss_pct = max(stoploss_pct, 0.02)

        return -stoploss_pct

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # 计算ATR指标
        dataframe['atr'] = ta.ATR(dataframe, timeperiod=14)

        return dataframe
Enter fullscreen mode Exit fullscreen mode

1.2.2 基于波动率的止损

概念:根据历史波动率调整止损距离。

import numpy as np

class VolatilityStopLossStrategy(IStrategy):
    use_custom_stoploss = True
    stoploss = -0.15

    def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
                       current_rate: float, current_profit: float, **kwargs) -> float:

        dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)

        # 计算20天收益率的标准差
        returns = dataframe['close'].pct_change().dropna()
        volatility = returns.tail(20).std() * np.sqrt(252)  # 年化波动率

        # 根据波动率调整止损
        if volatility > 0.5:  # 高波动
            multiplier = 2.0
        elif volatility > 0.3:  # 中等波动
            multiplier = 1.5
        else:  # 低波动
            multiplier = 1.0

        base_stoploss = 0.03  # 基础止损3%
        stoploss_pct = base_stoploss * multiplier

        return -min(stoploss_pct, 0.15)  # 最大-15%
Enter fullscreen mode Exit fullscreen mode

1.3 追踪止损(Trailing Stop Loss)

1.3.1 基本原理

追踪止损会随着价格有利变动而调整止损价格,但不会向下调整。

示例

买入价: $30,000
设置: 5%追踪止损

价格上涨到 $31,000: 止损价调整到 $29,450 ($31,000 × 0.95)
价格上涨到 $32,000: 止损价调整到 $30,400 ($32,000 × 0.95)
价格下跌到 $31,500: 止损价保持 $30,400
价格下跌到 $30,400: 触发止损
Enter fullscreen mode Exit fullscreen mode

1.3.2 Freqtrade实现

class TrailingStopLossStrategy(IStrategy):
    # 启用追踪止损
    trailing_stop = True
    trailing_stop_positive = 0.01  # 盈利后1%追踪
    trailing_stop_positive_offset = 0.03  # 盈利3%后开始追踪
    trailing_only_offset_is_reached = True  # 只有达到offset才开始追踪

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        # 买入信号
        return dataframe
Enter fullscreen mode Exit fullscreen mode

配置说明

  • trailing_stop: 启用追踪止损
  • trailing_stop_positive: 盈利后的追踪距离
  • trailing_stop_positive_offset: 开始追踪的盈利阈值
  • trailing_only_offset_is_reached: 只有达到offset才开始追踪

1.3.3 自定义追踪止损

class CustomTrailingStopLossStrategy(IStrategy):
    use_custom_stoploss = True
    stoploss = -0.10

    def __init__(self, config: dict) -> None:
        super().__init__(config)
        # 存储每个交易的最高价
        self.highest_prices = {}

    def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
                       current_rate: float, current_profit: float, **kwargs) -> float:

        # 获取交易ID
        trade_id = trade.id

        # 初始化最高价
        if trade_id not in self.highest_prices:
            self.highest_prices[trade_id] = trade.open_rate

        # 更新最高价
        if current_rate > self.highest_prices[trade_id]:
            self.highest_prices[trade_id] = current_rate

        highest_price = self.highest_prices[trade_id]

        # 如果当前盈利超过3%,使用追踪止损
        if current_profit > 0.03:
            # 2%追踪止损
            trailing_distance = 0.02
            stoploss_price = highest_price * (1 - trailing_distance)
            stoploss_pct = (current_rate - stoploss_price) / current_rate

            return -stoploss_pct
        else:
            # 否则使用5%固定止损
            return -0.05
Enter fullscreen mode Exit fullscreen mode

第二部分:高级止损策略

2.1 技术指标止损

2.1.1 移动平均线止损

class MAStopLossStrategy(IStrategy):
    use_custom_stoploss = True
    stoploss = -0.15

    def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
                       current_rate: float, current_profit: float, **kwargs) -> float:

        dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
        last_candle = dataframe.iloc[-1].squeeze()

        # 使用20日移动平均线作为止损
        ma20 = last_candle['ma20']

        if current_rate > ma20:
            # 当前价格在均线上方,使用均线止损
            stoploss_pct = (current_rate - ma20) / current_rate
            return -min(stoploss_pct, 0.15)
        else:
            # 价格跌破均线,使用固定止损
            return -0.08

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe['ma20'] = ta.SMA(dataframe, timeperiod=20)
        dataframe['ma50'] = ta.SMA(dataframe, timeperiod=50)
        return dataframe
Enter fullscreen mode Exit fullscreen mode

2.1.2 布林带止损

class BollingerStopLossStrategy(IStrategy):
    use_custom_stoploss = True
    stoploss = -0.15

    def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
                       current_rate: float, current_profit: float, **kwargs) -> float:

        dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
        last_candle = dataframe.iloc[-1].squeeze()

        # 使用布林带下轨作为止损
        lower_band = last_candle['bb_lowerband']

        # 确保止损价不低于布林带下轨
        if current_rate > lower_band:
            stoploss_pct = (current_rate - lower_band) / current_rate
            return -min(stoploss_pct, 0.20)
        else:
            return -0.10

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
        dataframe['bb_lowerband'] = bollinger['lower']
        dataframe['bb_middleband'] = bollinger['mid']
        dataframe['bb_upperband'] = bollinger['upper']
        return dataframe
Enter fullscreen mode Exit fullscreen mode

2.1.3 支撑位止损

class SupportStopLossStrategy(IStrategy):
    use_custom_stoploss = True
    stoploss = -0.15

    def find_support_levels(self, dataframe: DataFrame):
        """寻找支撑位"""
        # 简单的支撑位识别:局部最低点
        lows = dataframe['low']

        # 寻找支撑位(简化版)
        support_levels = []
        for i in range(2, len(lows) - 2):
            current_low = lows.iloc[i]
            if (current_low < lows.iloc[i-1] and
                current_low < lows.iloc[i-2] and
                current_low < lows.iloc[i+1] and
                current_low < lows.iloc[i+2]):
                support_levels.append(current_low)

        return sorted(support_levels, reverse=True)[:5]  # 返回前5个支撑位

    def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
                       current_rate: float, current_profit: float, **kwargs) -> float:

        dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
        support_levels = self.find_support_levels(dataframe)

        if support_levels:
            # 使用最近的支撑位作为止损
            nearest_support = support_levels[0]

            if current_rate > nearest_support:
                stoploss_pct = (current_rate - nearest_support) / current_rate
                # 至少2%止损,最多15%
                stoploss_pct = max(stoploss_pct, 0.02)
                stoploss_pct = min(stoploss_pct, 0.15)
                return -stoploss_pct

        return -0.08  # 默认止损
Enter fullscreen mode Exit fullscreen mode

2.2 时间止损

2.2.1 持仓时间止损

import datetime

class TimeStopLossStrategy(IStrategy):
    use_custom_stoploss = True
    stoploss = -0.15

    # 最大持仓时间(小时)
    max_hold_time = 24  # 24小时

    def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
                       current_rate: float, current_profit: float, **kwargs) -> float:

        # 计算持仓时间
        hold_time = current_time - trade.open_date

        # 如果持仓时间超过限制,降低止损
        if hold_time > datetime.timedelta(hours=self.max_hold_time):
            if current_profit > 0:
                # 持仓时间过长且有盈利,使用较小止损快速平仓
                return -0.01
            else:
                # 持仓时间过长且亏损,止损平仓
                return -0.001

        # 正常止损逻辑
        if current_profit > 0.05:
            return -0.03  # 盈利5%以上,3%止损
        else:
            return -0.08  # 默认止损
Enter fullscreen mode Exit fullscreen mode

2.2.2 分时止损

class HourlyStopLossStrategy(IStrategy):
    use_custom_stoploss = True
    stoploss = -0.15

    def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
                       current_rate: float, current_profit: float, **kwargs) -> float:

        hour = current_time.hour

        # 根据时间段调整止损
        if 0 <= hour < 6:  # 深夜时段,波动较小
            if current_profit > 0:
                return -0.02  # 较紧止损
            else:
                return -0.05

        elif 6 <= hour < 12:  # 上午时段
            return -0.08

        elif 12 <= hour < 18:  # 下午时段,波动较大
            return -0.10

        else:  # 晚上时段
            return -0.06
Enter fullscreen mode Exit fullscreen mode

2.3 组合止损策略

2.3.1 多条件止损

class CombinedStopLossStrategy(IStrategy):
    use_custom_stoploss = True
    stoploss = -0.20

    def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
                       current_rate: float, current_profit: float, **kwargs) -> float:

        dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
        last_candle = dataframe.iloc[-1].squeeze()

        # 1. ATR止损
        atr = last_candle['atr']
        atr_stoploss = (atr * 2) / current_rate

        # 2. 移动平均线止损
        ma20 = last_candle['ma20']
        if current_rate > ma20:
            ma_stoploss = (current_rate - ma20) / current_rate
        else:
            ma_stoploss = 0.15

        # 3. 时间止损
        hold_time = current_time - trade.open_date
        if hold_time > datetime.timedelta(hours=12):
            time_stoploss = 0.03 if current_profit > 0 else 0.08
        else:
            time_stoploss = 0.15

        # 4. 盈利追踪止损
        if current_profit > 0.05:
            trailing_stoploss = 0.02
        else:
            trailing_stoploss = 0.15

        # 取最严格的止损(最小值)
        final_stoploss = min(atr_stoploss, ma_stoploss, time_stoploss, trailing_stoploss)
        final_stoploss = max(final_stoploss, 0.02)  # 至少2%
        final_stoploss = min(final_stoploss, 0.20)  # 最多20%

        return -final_stoploss

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe['atr'] = ta.ATR(dataframe, timeperiod=14)
        dataframe['ma20'] = ta.SMA(dataframe, timeperiod=20)
        return dataframe
Enter fullscreen mode Exit fullscreen mode

第三部分:止损执行机制

3.1 本地止损 vs 交易所止损

3.1.1 本地止损

特点

✅ 灵活性高,可以实现复杂逻辑
✅ 不占用交易所API限额
✅ 可以实时监控和调整
❌ 依赖系统稳定性
❌ 网络问题可能导致延迟
❌ 需要系统持续运行
Enter fullscreen mode Exit fullscreen mode

配置

{
  "stoploss_on_exchange": false,
  "stoploss": -0.05
}
Enter fullscreen mode Exit fullscreen mode

3.1.2 交易所止损

特点

✅ 执行可靠,不受本地系统影响
✅ 响应速度快
✅ 不占用本地资源
❌ 功能有限,只支持基本止损
❌ 占用API限额
❌ 调整不够灵活
Enter fullscreen mode Exit fullscreen mode

配置

{
  "stoploss_on_exchange": true,
  "stoploss_on_exchange_interval": 60,
  "stoploss": -0.05
}
Enter fullscreen mode Exit fullscreen mode

3.2 止损订单类型

3.2.1 止损市价单

# 在交易所设置止损市价单
def create_stop_market_order(exchange, symbol, amount, stop_price):
    """
    创建止损市价单
    """
    try:
        order = exchange.create_order(
            symbol=symbol,
            type='stop_market',
            side='sell',
            amount=amount,
            params={'stopPrice': stop_price}
        )

        print(f"止损市价单已创建: {order['id']}")
        print(f"触发价格: ${stop_price}")

        return order

    except Exception as e:
        print(f"创建止损单失败: {e}")
        return None
Enter fullscreen mode Exit fullscreen mode

3.2.2 止损限价单

def create_stop_limit_order(exchange, symbol, amount, stop_price, limit_price):
    """
    创建止损限价单
    """
    try:
        order = exchange.create_order(
            symbol=symbol,
            type='stop_limit',
            side='sell',
            amount=amount,
            price=limit_price,
            params={'stopPrice': stop_price}
        )

        print(f"止损限价单已创建: {order['id']}")
        print(f"触发价格: ${stop_price}")
        print(f"限价: ${limit_price}")

        return order

    except Exception as e:
        print(f"创建止损单失败: {e}")
        return None
Enter fullscreen mode Exit fullscreen mode

3.3 止损监控和调整

3.3.1 止损状态监控

class StopLossMonitor:
    def __init__(self):
        self.active_stop_orders = {}
        self.stop_history = []

    def add_stop_order(self, trade_id, stop_price, order_type='market'):
        """添加止损订单"""
        self.active_stop_orders[trade_id] = {
            'stop_price': stop_price,
            'order_type': order_type,
            'created_time': datetime.now(),
            'adjusted_times': 0
        }

    def update_stop_price(self, trade_id, new_stop_price):
        """更新止损价格"""
        if trade_id in self.active_stop_orders:
            old_price = self.active_stop_orders[trade_id]['stop_price']
            self.active_stop_orders[trade_id]['stop_price'] = new_stop_price
            self.active_stop_orders[trade_id]['adjusted_times'] += 1

            print(f"止损价格更新: {old_price}{new_stop_price}")

    def check_stop_trigger(self, current_price, trade_id):
        """检查止损是否触发"""
        if trade_id not in self.active_stop_orders:
            return False

        stop_price = self.active_stop_orders[trade_id]['stop_price']

        if current_price <= stop_price:
            # 记录止损历史
            self.stop_history.append({
                'trade_id': trade_id,
                'stop_price': stop_price,
                'trigger_price': current_price,
                'trigger_time': datetime.now(),
                'order_type': self.active_stop_orders[trade_id]['order_type']
            })

            # 移除活跃止损
            del self.active_stop_orders[trade_id]
            return True

        return False

    def get_stop_statistics(self):
        """获取止损统计"""
        if not self.stop_history:
            return None

        total_stops = len(self.stop_history)
        market_stops = len([s for s in self.stop_history if s['order_type'] == 'market'])

        return {
            'total_stops': total_stops,
            'market_stops': market_stops,
            'limit_stops': total_stops - market_stops,
            'stop_efficiency': self.calculate_stop_efficiency()
        }

    def calculate_stop_efficiency(self):
        """计算止损效率"""
        # 简化计算:实际止损价格与设定止损价格的差异
        if not self.stop_history:
            return 0

        total_slippage = 0
        for stop in self.stop_history:
            slippage = abs(stop['trigger_price'] - stop['stop_price']) / stop['stop_price']
            total_slippage += slippage

        avg_slippage = total_slippage / len(self.stop_history)
        efficiency = max(0, 1 - avg_slippage)  # 效率 = 1 - 平均滑点

        return efficiency
Enter fullscreen mode Exit fullscreen mode

3.3.2 动态止损调整

def dynamic_stop_adjustment(trade, current_price, current_profit, indicators):
    """
    根据市场情况动态调整止损
    """
    original_stop = trade.stop_loss

    # 基于盈利调整
    if current_profit > 0.10:
        # 盈利超过10%,收紧止损
        new_stop = current_price * 0.97  # 3%止损
    elif current_profit > 0.05:
        # 盈利5-10%,适度收紧
        new_stop = current_price * 0.95  # 5%止损
    else:
        # 盈利较少,保持原止损
        new_stop = original_stop

    # 基于波动率调整
    volatility = indicators.get('volatility', 0.02)
    if volatility > 0.05:  # 高波动
        new_stop = min(new_stop, original_stop * 1.2)  # 放宽止损
    elif volatility < 0.01:  # 低波动
        new_stop = max(new_stop, original_stop * 0.8)  # 收紧止损

    # 基于技术指标调整
    if indicators.get('trend') == 'strong_bullish':
        new_stop = max(new_stop, current_price * 0.95)  # 趋势向上,放宽止损

    return new_stop
Enter fullscreen mode Exit fullscreen mode

第四部分:止损优化策略

4.1 止损回测分析

4.1.1 止损效果分析

def analyze_stoploss_effectiveness(trades_dataframe):
    """
    分析止损策略的有效性
    """
    total_trades = len(trades_dataframe)
    stopped_trades = trades_dataframe[trades_dataframe['stoploss_reason'].notna()]

    # 止损触发统计
    stop_count = len(stopped_trades)
    stop_rate = stop_count / total_trades if total_trades > 0 else 0

    # 止损避免的损失
    avg_stop_loss = stopped_trades['profit_ratio'].mean()
    max_potential_loss = stopped_trades['max_drawdown'].mean()
    loss_saved = max_potential_loss - avg_stop_loss

    # 止损类型分布
    stop_types = stopped_trades['stoploss_reason'].value_counts()

    analysis = {
        'total_trades': total_trades,
        'stop_count': stop_count,
        'stop_rate': stop_rate,
        'avg_stop_loss': avg_stop_loss,
        'loss_saved_per_trade': loss_saved,
        'total_loss_saved': loss_saved * stop_count,
        'stop_type_distribution': stop_types.to_dict()
    }

    return analysis

# 使用示例
import pandas as pd
# 假设有一个交易记录DataFrame
trades_df = pd.read_csv('backtest_results.csv')
analysis = analyze_stoploss_effectiveness(trades_df)

print(f"总交易数: {analysis['total_trades']}")
print(f"止损触发数: {analysis['stop_count']}")
print(f"止损触发率: {analysis['stop_rate']:.2%}")
print(f"止损避免的平均损失: {analysis['loss_saved_per_trade']:.2%}")
print(f"止损避免的总损失: {analysis['total_loss_saved']:.2%}")
Enter fullscreen mode Exit fullscreen mode

4.1.2 不同止损策略对比

def compare_stoploss_strategies(backtest_results):
    """
    对比不同止损策略的表现
    """
    comparison = {}

    for strategy_name, results in backtest_results.items():
        trades = results['trades']

        # 计算关键指标
        total_profit = trades['profit_abs'].sum()
        win_rate = len(trades[trades['profit_abs'] > 0]) / len(trades)
        max_drawdown = results['max_drawdown']
        sharpe_ratio = results['sharpe']

        # 止损相关指标
        stopped_trades = trades[trades['stoploss_reason'].notna()]
        stop_rate = len(stopped_trades) / len(trades)
        avg_stop_loss = stopped_trades['profit_ratio'].mean() if len(stopped_trades) > 0 else 0

        comparison[strategy_name] = {
            'total_profit': total_profit,
            'win_rate': win_rate,
            'max_drawdown': max_drawdown,
            'sharpe_ratio': sharpe_ratio,
            'stop_rate': stop_rate,
            'avg_stop_loss': avg_stop_loss
        }

    return comparison

# 可视化对比
def plot_stoploss_comparison(comparison):
    """
    绘制止损策略对比图
    """
    import matplotlib.pyplot as plt

    strategies = list(comparison.keys())
    metrics = ['total_profit', 'win_rate', 'max_drawdown', 'sharpe_ratio']

    fig, axes = plt.subplots(2, 2, figsize=(15, 10))
    axes = axes.ravel()

    for i, metric in enumerate(metrics):
        values = [comparison[s][metric] for s in strategies]
        axes[i].bar(strategies, values)
        axes[i].set_title(f'{metric.replace("_", " ").title()}')
        axes[i].tick_params(axis='x', rotation=45)

    plt.tight_layout()
    plt.show()
Enter fullscreen mode Exit fullscreen mode

4.2 止损参数优化

4.2.1 止损百分比优化

def optimize_stoploss_percentage(strategy_class, timeframe, pair_list,
                               stoploss_range=[-0.02, -0.03, -0.04, -0.05, -0.06, -0.08, -0.10]):
    """
    优化止损百分比
    """
    results = {}

    for stoploss in stoploss_range:
        print(f"测试止损: {stoploss:.1%}")

        # 创建策略实例
        strategy = strategy_class({
            'strategy': strategy_class.__name__,
            'stoploss': stoploss
        })

        # 运行回测
        backtest_result = run_backtest(strategy, timeframe, pair_list)

        results[str(stoploss)] = {
            'total_profit': backtest_result['total_profit'],
            'profit_mean': backtest_result['profit_mean'],
            'win_rate': backtest_result['wins'] / backtest_result['total_trades'],
            'max_drawdown': backtest_result['max_drawdown_abs'],
            'sharpe': backtest_result['sharpe']
        }

    # 找到最优止损
    best_stoploss = max(results.keys(),
                       key=lambda x: results[x]['sharpe'])

    return {
        'results': results,
        'best_stoploss': best_stoploss,
        'best_performance': results[best_stoploss]
    }
Enter fullscreen mode Exit fullscreen mode

4.2.2 追踪止损参数优化

def optimize_trailing_stop(strategy_class, timeframe, pair_list,
                          trailing_offsets=[0.01, 0.02, 0.03, 0.04, 0.05],
                          trailing_stops=[0.005, 0.01, 0.015, 0.02]):
    """
    优化追踪止损参数
    """
    results = {}

    for offset in trailing_offsets:
        for stop in trailing_stops:
            print(f"测试追踪参数: offset={offset:.1%}, stop={stop:.1%}")

            # 创建策略实例
            strategy = strategy_class({
                'strategy': strategy_class.__name__,
                'trailing_stop': True,
                'trailing_stop_positive_offset': offset,
                'trailing_stop_positive': stop
            })

            # 运行回测
            backtest_result = run_backtest(strategy, timeframe, pair_list)

            key = f"offset_{offset:.1%}_stop_{stop:.1%}"
            results[key] = {
                'offset': offset,
                'stop': stop,
                'total_profit': backtest_result['total_profit'],
                'win_rate': backtest_result['wins'] / backtest_result['total_trades'],
                'max_drawdown': backtest_result['max_drawdown_abs'],
                'sharpe': backtest_result['sharpe']
            }

    # 找到最优参数
    best_params = max(results.keys(),
                     key=lambda x: results[x]['sharpe'])

    return {
        'results': results,
        'best_parameters': best_params,
        'best_performance': results[best_params]
    }
Enter fullscreen mode Exit fullscreen mode

第五部分:实战配置示例

5.1 保守型止损配置

适合:新手、低风险偏好

{
  "stoploss": -0.06,
  "trailing_stop": false,
  "stoploss_on_exchange": true,
  "stoploss_on_exchange_interval": 60,
  "order_types": {
    "stoploss": "market",
    "stoploss_on_exchange": true,
    "stoploss_on_exchange_interval": 60
  }
}
Enter fullscreen mode Exit fullscreen mode

特点

  • 6%固定止损,相对保守
  • 使用交易所止损,可靠性高
  • 不使用追踪止损,简单直接

5.2 积极型止损配置

适合:高频交易、高风险偏好

{
  "stoploss": -0.08,
  "trailing_stop": true,
  "trailing_stop_positive": 0.01,
  "trailing_stop_positive_offset": 0.02,
  "trailing_only_offset_is_reached": true,
  "stoploss_on_exchange": false,
  "order_types": {
    "stoploss": "limit",
    "stoploss_on_exchange": false
  }
}
Enter fullscreen mode Exit fullscreen mode

特点

  • 盈利2%后开始1%追踪止损
  • 使用本地止损,可以实现复杂逻辑
  • 止损限价单,控制成交价格

5.3 智能型止损配置

适合:有经验的交易者

class IntelligentStopLossStrategy(IStrategy):
    use_custom_stoploss = True
    stoploss = -0.15

    # 配置参数
    atr_multiplier = 2.0
    trailing_start_profit = 0.03
    trailing_distance = 0.02
    max_stoploss = -0.20
    min_stoploss = -0.02

    def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
                       current_rate: float, current_profit: float, **kwargs) -> float:

        dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
        last_candle = dataframe.iloc[-1].squeeze()

        # 1. ATR动态止损
        atr = last_candle.get('atr', current_rate * 0.02)  # 默认2%
        atr_stoploss = (atr * self.atr_multiplier) / current_rate

        # 2. 追踪止损
        if current_profit > self.trailing_start_profit:
            trailing_stoploss = self.trailing_distance
        else:
            trailing_stoploss = self.stoploss * -1

        # 3. 时间止损
        hold_time = current_time - trade.open_date
        if hold_time > datetime.timedelta(hours=48):
            time_stoploss = 0.05 if current_profit > 0 else 0.15
        else:
            time_stoploss = self.stoploss * -1

        # 选择最优止损
        final_stoploss = min(atr_stoploss, trailing_stoploss, time_stoploss)

        # 限制止损范围
        final_stoploss = max(final_stoploss, self.min_stoploss)
        final_stoploss = min(final_stoploss, abs(self.max_stoploss))

        return -final_stoploss
Enter fullscreen mode Exit fullscreen mode

📝 实践任务

任务 1:止损策略测试

  1. 在回测中测试不同的止损百分比(2%, 3%, 5%, 8%, 10%)
  2. 记录每种止损的胜率、收益率、最大回撤
  3. 选择最适合你策略的止损设置

任务 2:追踪止损优化

  1. 测试不同的追踪参数组合
  2. 分析追踪止损对收益率的影响
  3. 找到最优的追踪距离和启动条件

任务 3:实盘止损验证

  1. 在小资金实盘中测试止损配置
  2. 观察止损触发的及时性和准确性
  3. 记录实际滑点情况
  4. 根据实盘表现调整参数

📌 核心要点

止损设置原则

1. 保护本金第一
   ✅ 止损是保护本金的工具
   ✅ 任何止损都比没有止损好
   ✅ 不要因为怕止损而设置过大

2. 适应策略特点
   ✅ 趋势策略需要较宽松止损
   ✅ 震荡策略需要较紧止损
   ✅ 高频策略需要快速止损

3. 考虑市场环境
   ✅ 高波动市场放宽止损
   ✅ 低波动市场收紧止损
   ✅ 重大事件前调整止损
Enter fullscreen mode Exit fullscreen mode

常见止损错误

错误 后果 正确做法
止损设置过大 损失过大 根据策略合理设置
止损设置过小 频繁止损 考虑正常波动范围
盈利后移动止损 可能过早离场 使用追踪止损
忽视止损执行 实际损失超预期 确保止损可靠执行

止损优化清单

□ 回测验证止损效果
□ 测试不同市场条件下的表现
□ 优化止损参数
□ 确保止损执行机制可靠
□ 实盘验证止损表现
□ 定期回顾和调整止损策略
Enter fullscreen mode Exit fullscreen mode

🎯 下节预告

第 24.3 课:合约交易操作详解

在下一课中,我们将学习:

  • 币安合约交易的API使用
  • 杠杆和保证金的管理
  • 合约订单类型和操作
  • 资金管理和风险控制

掌握了现货交易的止损技巧后,我们将进入更高风险的合约交易领域。

Top comments (0)