120 lines
3.7 KiB
Python
120 lines
3.7 KiB
Python
"""
|
||
SOL5mStrategyV6 - 趋势跟随策略 V6(基于V5改进)
|
||
|
||
核心改进:
|
||
- 去掉trend_reversal退出(V5中54笔全亏 -611 USDT)
|
||
- 完全依赖 ROI + trailing_stop + stoploss 管理退出
|
||
- 更激进的trailing:1.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
|