Files
Chan/strategies/SOL5mStrategyV6.py
2026-03-06 22:08:24 +08:00

120 lines
3.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
SOL5mStrategyV6 - 趋势跟随策略 V6(基于V5改进)
核心改进:
- 去掉trend_reversal退出(V5中54笔全亏 -611 USDT
- 完全依赖 ROI + trailing_stop + stoploss 管理退出
- 更激进的trailing1.5%盈利后激活,0.6%回撤
- 保持V5的入场逻辑(EMA排列 + 回调入场 + RSI + MACD + ADX
"""
from datetime import datetime
from typing import Optional
import talib.abstract as ta
from pandas import DataFrame
from freqtrade.persistence import Trade
from freqtrade.strategy import IStrategy
class SOL5mStrategyV6(IStrategy):
INTERFACE_VERSION: int = 3
timeframe = "15m"
can_short = True
startup_candle_count: int = 200
# 止损
stoploss = -0.025
use_custom_stoploss = False
# 更激进的trailing stop
trailing_stop = True
trailing_stop_positive = 0.006 # 0.6% 回撤止盈
trailing_stop_positive_offset = 0.015 # 1.5% 盈利后激活
trailing_only_offset_is_reached = True
# ROI
minimal_roi = {
"0": 0.04, # 4%直接止盈
"60": 0.03, # 1小时后 3%
"180": 0.02, # 3小时后 2%
"360": 0.01, # 6小时后 1%
"720": 0.005, # 12小时后 0.5%
"1440": 0, # 24小时后保本
}
order_types = {
"entry": "market",
"exit": "market",
"stoploss": "market",
"stoploss_on_exchange": False,
}
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# EMA趋势
dataframe["ema20"] = ta.EMA(dataframe, timeperiod=20)
dataframe["ema50"] = ta.EMA(dataframe, timeperiod=50)
dataframe["ema100"] = ta.EMA(dataframe, timeperiod=100)
# RSI
dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14)
# MACD
macd = ta.MACD(dataframe, fastperiod=12, slowperiod=26, signalperiod=9)
dataframe["macd"] = macd["macd"]
dataframe["macdsignal"] = macd["macdsignal"]
dataframe["macdhist"] = macd["macdhist"]
# ADX (趋势强度)
dataframe["adx"] = ta.ADX(dataframe, timeperiod=14)
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# 做多条件(与V5相同)
dataframe.loc[
(dataframe["ema20"] > dataframe["ema50"])
& (dataframe["ema50"] > dataframe["ema100"])
& (dataframe["close"] <= dataframe["ema20"] * 1.005)
& (dataframe["close"] >= dataframe["ema50"])
& (dataframe["rsi"] > 40)
& (dataframe["rsi"] < 65)
& (dataframe["macdhist"] > 0)
& (dataframe["adx"] > 20),
["enter_long", "enter_tag"],
] = (1, "trend_pullback_long")
# 做空条件(与V5相同)
dataframe.loc[
(dataframe["ema20"] < dataframe["ema50"])
& (dataframe["ema50"] < dataframe["ema100"])
& (dataframe["close"] >= dataframe["ema20"] * 0.995)
& (dataframe["close"] <= dataframe["ema50"])
& (dataframe["rsi"] < 60)
& (dataframe["rsi"] > 35)
& (dataframe["macdhist"] < 0)
& (dataframe["adx"] > 20),
["enter_short", "enter_tag"],
] = (1, "trend_pullback_short")
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# 不使用信号退出,完全依赖 ROI + trailing + stoploss
return dataframe
def leverage(
self,
pair: str,
current_time: datetime,
current_rate: float,
proposed_leverage: float,
max_leverage: float,
entry_tag: Optional[str],
side: str,
**kwargs,
) -> float:
return 1.0