Timeframe
5m
Direction
Long & Short
Stoploss
-26.5%
Trailing Stop
Yes
ROI
0m: 15.0%, 30m: 10.0%, 60m: 5.0%
Interface Version
N/A
Startup Candles
N/A
Indicators
1
freqtrade/freqtrade-strategies
author@: lenik
from functools import reduce
from pandas import DataFrame
from freqtrade.strategy import IStrategy
import talib.abstract as ta
from datetime import datetime, timedelta
from freqtrade.persistence import Trade
from typing import Optional
class TrendFollowingStrategy(IStrategy):
INTERFACE_VERSION: int = 3
minimal_roi = {
"0": 0.15,
"30": 0.1,
"60": 0.05
}
stoploss = -0.265
trailing_stop = True
trailing_stop_positive = 0.05
trailing_stop_positive_offset = 0.1
trailing_only_offset_is_reached = False
can_short = True
timeframe = "5m"
# 关键时间点:25分钟
key_time = 25
# 用于存储25分钟后的信号
signal_after_keytime = {} # 格式: {pair: {'signal_time': datetime, 'position': str}}
def bot_start(self, **kwargs) -> None:
"""初始化信号存储字典"""
self.signal_after_keytime = {}
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Calculate OBV
dataframe['obv'] = ta.OBV(dataframe['close'], dataframe['volume'])
# Add your trend following indicators here
dataframe['trend'] = dataframe['close'].ewm(span=20, adjust=False).mean()
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[:, 'enter_long'] = 0
dataframe.loc[:, 'enter_short'] = 0
# Add your trend following buy signals here
dataframe.loc[
(dataframe['close'] > dataframe['trend']) &
(dataframe['close'].shift(1) <= dataframe['trend'].shift(1)) &
(dataframe['obv'] > dataframe['obv'].shift(1)),
'enter_long'] = 1
# Add your trend following sell signals here
dataframe.loc[
(dataframe['close'] < dataframe['trend']) &
(dataframe['close'].shift(1) >= dataframe['trend'].shift(1)) &
(dataframe['obv'] < dataframe['obv'].shift(1)),
'enter_short'] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[:, 'exit_long'] = 0
dataframe.loc[:, 'exit_short'] = 0
# Add your trend following exit signals for long positions here
dataframe.loc[
(dataframe['close'] < dataframe['trend']) &
(dataframe['close'].shift(1) >= dataframe['trend'].shift(1)) &
(dataframe['obv'] > dataframe['obv'].shift(1)),
'exit_long'] = 1
# Add your trend following exit signals for short positions here
dataframe.loc[
(dataframe['close'] > dataframe['trend']) &
(dataframe['close'].shift(1) <= dataframe['trend'].shift(1)) &
(dataframe['obv'] < dataframe['obv'].shift(1)),
'exit_short'] = 1
return dataframe
def custom_exit(self, pair: str, trade: Trade, current_time: datetime, current_rate: float,
current_profit: float, **kwargs):
try:
# 计算持仓时间(分钟)
hold_time = (current_time - trade.open_date_utc).total_seconds() / 60
# 获取当前分析的数据
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze()
# 检查是否已经超过25分钟
if hold_time >= self.key_time:
# 检查是否是第一次到达25分钟
if pair not in self.signal_after_keytime:
# 记录当前状态
self.signal_after_keytime[pair] = {
'signal_time': current_time,
'position': 'long' if trade.is_long else 'short'
}
return None
# 检查是否有反向信号
if trade.is_long:
has_short_signal = (
(last_candle['close'] < last_candle['trend']) and
(dataframe['close'].iloc[-2] >= dataframe['trend'].iloc[-2]) and
(last_candle['obv'] < dataframe['obv'].iloc[-2])
)
if has_short_signal:
del self.signal_after_keytime[pair] # 清除信号记录
return "reverse_to_short"
if trade.is_short:
has_long_signal = (
(last_candle['close'] > last_candle['trend']) and
(dataframe['close'].iloc[-2] <= dataframe['trend'].iloc[-2]) and
(last_candle['obv'] > dataframe['obv'].iloc[-2])
)
if has_long_signal:
del self.signal_after_keytime[pair] # 清除信号记录
return "reverse_to_long"
# 如果没有反向信号,继续持仓
return None
except Exception as e:
return None
return None
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:
"""使用5倍杠杆"""
return 5.0