趋势突破策略V2 - 优化版
Timeframe
15m
Direction
Long Only
Stoploss
-5.0%
Trailing Stop
No
ROI
0m: 1000.0%
Interface Version
3
Startup Candles
N/A
Indicators
7
freqtrade/freqtrade-strategies
Strategy 003 author@: Gerald Lonlas github@: https://github.com/freqtrade/freqtrade-strategies
# pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement
# flake8: noqa: F401
# isort: skip_file
# --- Do not remove these imports ---
import numpy as np
import pandas as pd
import math
from datetime import datetime, timedelta, timezone
from pandas import DataFrame
from typing import Optional, Union
from collections import deque
from freqtrade.strategy import (
IStrategy,
Trade,
Order,
PairLocks,
informative,
BooleanParameter,
CategoricalParameter,
DecimalParameter,
IntParameter,
RealParameter,
timeframe_to_minutes,
timeframe_to_next_date,
timeframe_to_prev_date,
merge_informative_pair,
stoploss_from_absolute,
stoploss_from_open,
)
import talib.abstract as ta
from technical import qtpylib
class TrendBreakoutStrategyV2(IStrategy):
"""
趋势突破策略V2 - 优化版
主要改进:
1. 使用Supertrend代替EMA系统,减少假信号
2. 加入VWAP作为趋势确认
3. 实施三重确认系统(趋势+动量+结构)
4. 优化入场评分系统,提高门槛
5. 动态止损和分批建仓
目标:
- 胜率提升至35-45%
- 盈亏比1.5-2.0
- 最大回撤控制在10%以内
"""
INTERFACE_VERSION = 3
can_short: bool = False
# 基础参数设置
minimal_roi = {"0": 10}
stoploss = -0.05 # 5%兜底止损(提高容错)
trailing_stop = False
timeframe = '15m'
use_custom_stoploss = True
use_exit_signal = True
exit_profit_only = False
ignore_roi_if_entry_signal = False
# === 核心策略参数(简化版)===
# Supertrend参数(主要趋势信号)
st_atr_period = IntParameter(12, 18, default=14, space="buy", optimize=True)
st_multiplier = DecimalParameter(2.0, 3.0, default=2.5, space="buy", optimize=True)
# MACD参数(动量确认)
macd_fast = IntParameter(10, 14, default=12, space="buy", optimize=True)
macd_slow = IntParameter(24, 28, default=26, space="buy", optimize=True)
macd_signal = IntParameter(8, 10, default=9, space="buy", optimize=True)
# RSI参数(超买超卖)
rsi_period = IntParameter(12, 16, default=14, space="buy", optimize=True)
rsi_overbought = IntParameter(68, 75, default=70, space="buy", optimize=True)
# ADX参数(趋势强度 - 市场过滤器)
adx_period = IntParameter(12, 16, default=14, space="buy", optimize=True)
adx_threshold = IntParameter(25, 35, default=28, space="buy", optimize=True)
# 成交量确认(简化)
volume_multiplier = DecimalParameter(1.3, 2.0, default=1.5, space="buy", optimize=True)
# === 风险管理参数(简化版)===
# 简化止损系统 - 基于ATR
atr_stop_multiplier = DecimalParameter(2.0, 3.5, default=2.5, space="sell", optimize=True)
# 三级止盈系统(来自成功策略)
profit_threshold_1 = DecimalParameter(0.02, 0.04, default=0.03, space="sell", optimize=True) # 3%
profit_threshold_2 = DecimalParameter(0.06, 0.10, default=0.08, space="sell", optimize=True) # 8%
profit_threshold_3 = DecimalParameter(0.15, 0.25, default=0.20, space="sell", optimize=True) # 20%
startup_candle_count: int = 200
def __init__(self, config: dict):
super().__init__(config)
self.custom_info = {} # 简化的交易信息存储
def calculate_supertrend(self, dataframe: DataFrame, period: int = 14, multiplier: float = 2.5) -> tuple:
"""计算Supertrend指标"""
high = dataframe['high']
low = dataframe['low']
close = dataframe['close']
# 计算ATR
atr = ta.ATR(dataframe, timeperiod=period)
# 计算基础线
hl_avg = (high + low) / 2
# 计算上下轨
upper_band = hl_avg + (multiplier * atr)
lower_band = hl_avg - (multiplier * atr)
# 初始化
supertrend = pd.Series(index=dataframe.index, dtype=float)
direction = pd.Series(index=dataframe.index, dtype=float)
for i in range(period, len(dataframe)):
# 上轨调整
if upper_band.iloc[i] < upper_band.iloc[i-1] or close.iloc[i-1] > upper_band.iloc[i-1]:
upper_band.iloc[i] = upper_band.iloc[i]
else:
upper_band.iloc[i] = upper_band.iloc[i-1]
# 下轨调整
if lower_band.iloc[i] > lower_band.iloc[i-1] or close.iloc[i-1] < lower_band.iloc[i-1]:
lower_band.iloc[i] = lower_band.iloc[i]
else:
lower_band.iloc[i] = lower_band.iloc[i-1]
# 确定趋势方向
if i == period:
if close.iloc[i] <= upper_band.iloc[i]:
direction.iloc[i] = -1
else:
direction.iloc[i] = 1
else:
if direction.iloc[i-1] == -1:
if close.iloc[i] <= upper_band.iloc[i]:
direction.iloc[i] = -1
else:
direction.iloc[i] = 1
else:
if close.iloc[i] >= lower_band.iloc[i]:
direction.iloc[i] = 1
else:
direction.iloc[i] = -1
# 设置Supertrend值
if direction.iloc[i] == 1:
supertrend.iloc[i] = lower_band.iloc[i]
else:
supertrend.iloc[i] = upper_band.iloc[i]
return supertrend, direction
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""计算所需的技术指标"""
# === Supertrend指标 ===
dataframe['supertrend'], dataframe['st_direction'] = self.calculate_supertrend(
dataframe,
period=self.st_atr_period.value,
multiplier=self.st_multiplier.value
)
dataframe['st_uptrend'] = dataframe['st_direction'] == 1
# === MACD指标(动量确认)===
macd = ta.MACD(dataframe,
fastperiod=self.macd_fast.value,
slowperiod=self.macd_slow.value,
signalperiod=self.macd_signal.value)
dataframe['macd_hist'] = macd['macdhist']
dataframe['macd_bullish'] = (macd['macdhist'] > 0) & (macd['macdhist'] > macd['macdhist'].shift(1))
# === RSI指标(超买过滤)===
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=self.rsi_period.value)
dataframe['rsi_ok'] = dataframe['rsi'] < self.rsi_overbought.value
# === ADX指标(趋势强度 - 市场过滤器)===
dataframe['adx'] = ta.ADX(dataframe, timeperiod=self.adx_period.value)
dataframe['trending_market'] = dataframe['adx'] > self.adx_threshold.value
# === 成交量确认(简化)===
dataframe['volume_ma20'] = dataframe['volume'].rolling(20).mean()
dataframe['volume_surge'] = dataframe['volume'] > (dataframe['volume_ma20'] * self.volume_multiplier.value)
# === ATR(用于动态止损)===
dataframe['atr'] = ta.ATR(dataframe, timeperiod=self.st_atr_period.value)
# === 波动率计算(用于仓位管理)===
dataframe['price_change'] = dataframe['close'].pct_change()
dataframe['volatility'] = dataframe['price_change'].rolling(20).std() * np.sqrt(24 * 60 / 15) # 15m to daily
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""定义入场条件"""
# 多头入场条件 - 简化版本(4个核心信号确认)
dataframe.loc[
(
# 1. 趋势确认:Supertrend 上升趋势
(dataframe['st_uptrend'] == True) &
# 2. 动量确认:MACD 看涨
(dataframe['macd_bullish'] == True) &
# 3. 市场过滤:只在强趋势市场交易
(dataframe['trending_market'] == True) &
# 4. 成交量确认:成交量放大
(dataframe['volume_surge'] == True) &
# 5. 风险过滤:RSI 未超买
(dataframe['rsi_ok'] == True) &
# 基础有效性检查
(dataframe['volume'] > 0)
),
'enter_long'
] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""定义出场条件 - 简化版本"""
# 趋势反转退出(简化条件)
dataframe.loc[
(
# Supertrend 转向或 RSI 超买
(dataframe['st_uptrend'] == False) |
(dataframe['rsi'] > 80)
),
'exit_long'
] = 1
return dataframe
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
proposed_stake: float, min_stake: Optional[float], max_stake: float,
leverage: float, entry_tag: Optional[str], side: str,
**kwargs) -> float:
"""基于波动率的动态仓位管理"""
# 获取最新数据
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
if dataframe is None or len(dataframe) == 0:
return proposed_stake * 0.02 # 2% 默认仓位
latest = dataframe.iloc[-1]
current_volatility = latest.get('volatility', 0.02) # 默认波动率 2%
# 获取账户余额
account_balance = self.wallets.get_total_stake_amount()
# 基于波动率的仓位计算 - 波动率越高仓位越小
base_risk = 0.02 # 2% 基础风险
volatility_factor = min(current_volatility / 0.02, 3.0) if current_volatility > 0 else 1.0 # 最大 3倍波动率调整
adjusted_risk = base_risk / max(volatility_factor, 1.0)
position_size = account_balance * adjusted_risk
# 应用最小/最大限制
if min_stake:
position_size = max(position_size, min_stake)
position_size = min(position_size, max_stake)
return position_size
def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime,
current_rate: float, current_profit: float, **kwargs) -> float:
"""简化的3级止损系统(来自成功策略)"""
# 获取最新数据
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
if dataframe is None or len(dataframe) == 0:
return self.stoploss
latest = dataframe.iloc[-1]
atr = latest.get('atr', 0.01)
# 初始止损基于ATR
initial_stop = -self.atr_stop_multiplier.value * atr / current_rate
# 3级盈利保护系统
if current_profit > self.profit_threshold_3.value: # >20% 利润
return current_profit - 0.08 # 保护 8% 利润
elif current_profit > self.profit_threshold_2.value: # >8% 利润
return current_profit - 0.04 # 保护 4% 利润
elif current_profit > self.profit_threshold_1.value: # >3% 利润
return current_profit - 0.02 # 保护 2% 利润
else:
return initial_stop
def custom_exit(self, pair: str, trade: Trade, current_time: datetime, current_rate: float,
current_profit: float, **kwargs) -> Union[str, None]:
"""简化的自定义出场逻辑"""
# 获取最新数据
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
if dataframe is None or len(dataframe) == 0:
return None
latest = dataframe.iloc[-1]
# RSI极度超买退出
if latest['rsi'] > 80:
return "rsi_extreme_overbought"
# Supertrend趋势反转
if not latest['st_uptrend']:
return "trend_reversal"
return None