低回撤1分钟多因子策略: 因子1:短期趋势(EMA金叉+价格在EMA上方) 因子2:量能确认(成交量温和放大) 因子3:波动率控制(ATR低于阈值,避免剧烈波动) 因子4:回撤控制(当前价格距近期高点回撤≤3%) 因子5:RSI中性偏强(40-65区间,避免超买超卖)
Timeframe
1m
Direction
Long Only
Stoploss
-2.0%
Trailing Stop
Yes
ROI
0m: 4.0%, 30m: 2.0%, 60m: 1.0%, 90m: 0.5%
Interface Version
N/A
Startup Candles
40
Indicators
3
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
from freqtrade.strategy import IStrategy, merge_informative_pair
from freqtrade.exchange import timeframe_to_minutes
from typing import Dict, List, Optional, Tuple, Union
from pandas import DataFrame
import numpy as np
import pandas as pd
from technical import qtpylib
from technical.indicators import RSI, ATR, EMA
class LowDrawdown1mMultiFactor(IStrategy):
"""
低回撤1分钟多因子策略:
因子1:短期趋势(EMA金叉+价格在EMA上方)
因子2:量能确认(成交量温和放大)
因子3:波动率控制(ATR低于阈值,避免剧烈波动)
因子4:回撤控制(当前价格距近期高点回撤≤3%)
因子5:RSI中性偏强(40-65区间,避免超买超卖)
"""
# ================================== 基础配置 ==================================
# 策略名称
strategy_name = "LowDrawdown1mMultiFactor"
# 策略作者
author = "Freqtrade"
# 策略版本
version = "1.0"
# 时间周期(1分钟K线,核心周期)
timeframe = '1m'
# 最小数据量(确保指标计算可靠)
minimal_roi = {
"0": 0.04, # 持有0分钟(立即)获利4%止盈
"30": 0.02, # 持有30分钟获利2%止盈
"60": 0.01, # 持有60分钟获利1%止盈
"90": 0.005 # 持有90分钟获利0.5%止盈(防止长时间持仓)
}
# 止损配置(严格控制回撤)
stoploss = -0.02 # 固定止损2%(单笔最大亏损)
trailing_stop = True # 启用移动止盈
trailing_stop_positive = 0.01 # 获利1%后启动移动止盈
trailing_stop_positive_offset = 0.02 # 移动止盈偏移(最大允许回吐2%)
trailing_only_offset_is_reached = True # 仅在达到偏移后启动移动止盈
# 仓位配置(轻仓为主)
initial_state = "running"
max_entry_position_adjustment = 1 # 单品种最多1个仓位
stake_amount = "30%" # 每次开仓使用账户30%资金(可调整)
stake_currency = "USDT"
order_types = {
"entry": "limit",
"exit": "limit",
"stoploss": "market",
"stoploss_on_exchange": False
}
# 回测相关配置
startup_candle_count = 40 # 启动所需最小K线数量(确保指标计算)
exchange_interval = 1 # 交易所数据间隔(1分钟)
# ================================== 可优化参数 ==================================
# 因子参数(可通过hyperopt调整)
EMA_SHORT = 5 # 短期EMA周期
EMA_LONG = 10 # 长期EMA周期
ATR_PERIOD = 14 # ATR周期
ATR_MAX = 0.03 # 最大波动率(ATR占比≤3%才开仓)
VOLUME_WINDOW = 20 # 成交量均值窗口
VOLUME_MULT = 1.2 # 成交量放大倍数(≥1.2倍均值)
DRAW_DOWN_WINDOW = 10 # 回撤计算窗口(近10根K线)
DRAW_DOWN_MAX = 0.03 # 最大允许回撤(≤3%)
RSI_PERIOD = 14 # RSI周期
RSI_LOW = 40 # RSI下限(≥40,避免弱市)
RSI_HIGH = 65 # RSI上限(≤65,避免超买)
# ================================== 指标计算 ==================================
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""计算所有需要的指标(多因子核心)"""
# 1. 趋势指标:EMA金叉/死叉
dataframe['ema_short'] = EMA(dataframe, length=self.EMA_SHORT)
dataframe['ema_long'] = EMA(dataframe, length=self.EMA_LONG)
dataframe['ema_golden'] = qtpylib.crossed_above(dataframe['ema_short'], dataframe['ema_long']) # EMA金叉
dataframe['ema_death'] = qtpylib.crossed_below(dataframe['ema_short'], dataframe['ema_long']) # EMA死叉
dataframe['price_above_ema'] = dataframe['close'] > dataframe['ema_short'] # 价格在短期EMA上方
# 2. 波动率指标:ATR(控制波动风险)
dataframe['atr'] = ATR(dataframe, length=self.ATR_PERIOD)
dataframe['atr_ratio'] = dataframe['atr'] / dataframe['close'] # ATR占当前价格比例
dataframe['low_volatility'] = dataframe['atr_ratio'] <= self.ATR_MAX # 低波动率标记
# 3. 量能指标:成交量温和放大
dataframe['volume_mean'] = dataframe['volume'].rolling(window=self.VOLUME_WINDOW).mean()
dataframe['volume_amplified'] = dataframe['volume'] >= dataframe['volume_mean'] * self.VOLUME_MULT # 成交量放大标记
# 4. 回撤控制指标:近期价格回撤≤3%
dataframe['high_10'] = dataframe['high'].rolling(window=self.DRAW_DOWN_WINDOW).max() # 近10根K线高点
dataframe['draw_down'] = (dataframe['high_10'] - dataframe['close']) / dataframe['high_10'] # 回撤比例
dataframe['low_drawdown'] = dataframe['draw_down'] <= self.DRAW_DOWN_MAX # 低回撤标记
# 5. 强弱指标:RSI中性偏强
dataframe['rsi'] = RSI(dataframe, length=self.RSI_PERIOD)
dataframe['rsi_neutral'] = (dataframe['rsi'] >= self.RSI_LOW) & (dataframe['rsi'] <= self.RSI_HIGH) # RSI中性标记
# 综合因子得分(1-5分,越高信号越可靠)
dataframe['factor_score'] = 0
dataframe.loc[dataframe['price_above_ema'], 'factor_score'] += 1
dataframe.loc[dataframe['low_volatility'], 'factor_score'] += 1
dataframe.loc[dataframe['volume_amplified'], 'factor_score'] += 1
dataframe.loc[dataframe['low_drawdown'], 'factor_score'] += 1
dataframe.loc[dataframe['rsi_neutral'], 'factor_score'] += 1
return dataframe
# ================================== 开仓信号 ==================================
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""生成开仓信号(多因子共振,≥4分才开仓)"""
dataframe.loc[
(
dataframe['factor_score'] >= 4 # 综合得分≥4(至少4个因子满足)
& dataframe['ema_golden'] # EMA金叉(趋势确认)
& dataframe['price_above_ema'] # 价格在短期EMA上方(趋势强劲)
& dataframe['low_volatility'] # 波动率低(风险可控)
& dataframe['volume_amplified'] # 量能放大(资金支撑)
& (dataframe['close'] > dataframe['open']) # 当前K线收阳(短期强势)
& (dataframe['volume'] > 0) # 成交量不为0(有效交易)
),
'enter_long'] = 1
# 禁止开空(仅做多,降低回撤)
dataframe['enter_short'] = 0
return dataframe
# ================================== 平仓信号 ==================================
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""生成平仓信号(触发止损/止盈或因子失效)"""
dataframe.loc[
(
dataframe['ema_death'] # EMA死叉(趋势反转)
| (dataframe['rsi'] > 75) # RSI超买(75以上,获利了结)
| (dataframe['atr_ratio'] > 0.05) # 波动率突增(超过5%,规避风险)
| (dataframe['draw_down'] > 0.05) # 回撤超过5%(趋势走弱)
| (dataframe['factor_score'] < 2) # 综合得分<2(因子大面积失效)
),
'exit_long'] = 1
# 无空头平仓信号
dataframe['exit_short'] = 0
return dataframe
# ================================== 风险控制增强 ==================================
def custom_stoploss(self, pair: str, trade: 'Trade', current_time: pd.Timestamp,
current_rate: float, current_profit: float, **kwargs) -> Optional[float]:
"""自定义止损(增强回撤控制)"""
# 获利≥3%时,止损上移到成本价(确保不亏损)
if current_profit >= 0.03:
return 0.0 # 止损价=成本价
# 获利≥1%时,止损上移到获利0.5%(仅允许少量回吐)
elif current_profit >= 0.01:
return current_profit - 0.005
# 未获利时,使用固定止损
return None
def check_entry_condition(self, pair: str, dataframe: DataFrame, metadata: dict) -> bool:
"""额外的开仓条件检查(控制整体回撤)"""
# 1. 过滤流动性差的交易对(成交量均值≥1000USDT)
volume_mean = dataframe['volume'].rolling(window=20).mean().iloc[-1]
if volume_mean < 1000:
return False
# 2. 整体账户回撤≤10%才允许开新仓(避免连续亏损)
if self.wallets.get_total_stake_amount() / self.wallets.initial_balance < 0.9:
return False
return True