双均线交叉策略 (Double Moving Average Crossover Strategy)
Timeframe
1h
Direction
Long Only
Stoploss
-8.0%
Trailing Stop
No
ROI
0m: 6.0%, 180m: 5.0%, 360m: 4.0%, 720m: 3.0%
Interface Version
3
Startup Candles
N/A
Indicators
3
# 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
from datetime import datetime, timedelta, timezone
from pandas import DataFrame
from typing import Optional, Union
from freqtrade.strategy import (
IStrategy,
Trade,
Order,
PairLocks,
informative, # @informative decorator
# Hyperopt Parameters
BooleanParameter,
CategoricalParameter,
DecimalParameter,
IntParameter,
RealParameter,
# timeframe helpers
timeframe_to_minutes,
timeframe_to_next_date,
timeframe_to_prev_date,
# Strategy helper functions
merge_informative_pair,
stoploss_from_absolute,
stoploss_from_open,
)
# --------------------------------
# Add your lib to import here
import talib.abstract as ta
from technical import qtpylib
class DoubleMAStrategy(IStrategy):
"""
双均线交叉策略 (Double Moving Average Crossover Strategy)
交易逻辑:
- 买入信号:快线上穿慢线(金叉)
- 卖出信号:快线下穿慢线(死叉)
可优化参数:
- fast_ma_period: 快线周期 (5-50)
- slow_ma_period: 慢线周期 (20-100)
- ma_type: 均线类型 (SMA/EMA/WMA)
"""
# Strategy interface version
INTERFACE_VERSION = 3
# 是否允许做空
can_short: bool = False
# 最小收益目标
minimal_roi = {
"1440": 0.02, # 24小时内获利2%
"720": 0.03, # 12小时内获利3%
"360": 0.04, # 6小时内获利4%
"180": 0.05, # 3小时内获利5%
"0": 0.06 # 立即获利6%
}
# 止损设置
stoploss = -0.08
# 追踪止损
trailing_stop = False
trailing_only_offset_is_reached = False
trailing_stop_positive = 0.01
trailing_stop_positive_offset = 0.0
# 最佳时间周期
timeframe = "1h"
# 只在新的K线产生信号
process_only_new_candles = True
# 退出信号设置
use_exit_signal = True
exit_profit_only = False
ignore_roi_if_entry_signal = False
# 启动所需的最小K线数量
startup_candle_count: int = 50
# ========================================
# 可优化参数定义
# ========================================
# 均线周期参数
fast_ma_period = IntParameter(
low=5, high=50, default=10,
space="buy", optimize=True, load=True
)
slow_ma_period = IntParameter(
low=20, high=100, default=30,
space="buy", optimize=True, load=True
)
# 均线类型选择
ma_type = CategoricalParameter(
["SMA", "EMA", "WMA"], # SMA:简单移动平均, EMA:指数移动平均, WMA:加权移动平均
default="EMA",
space="buy",
optimize=True,
load=True
)
# 信号确认参数
min_volume_multiplier = DecimalParameter(
low=0.5, high=3.0, default=1.0,
space="buy", optimize=True, load=True
)
# 趋势过滤参数
trend_filter_period = IntParameter(
low=50, high=200, default=100,
space="buy", optimize=True, load=True
)
# ========================================
# 策略方法
# ========================================
def informative_pairs(self):
"""
定义额外的参考数据
这里可以添加更大时间周期的数据作为趋势参考
"""
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
计算所有需要的指标
"""
# 根据选择的均线类型计算快慢线
if self.ma_type.value == "SMA":
# 简单移动平均线
dataframe['fast_ma'] = ta.SMA(dataframe, timeperiod=self.fast_ma_period.value)
dataframe['slow_ma'] = ta.SMA(dataframe, timeperiod=self.slow_ma_period.value)
elif self.ma_type.value == "EMA":
# 指数移动平均线
dataframe['fast_ma'] = ta.EMA(dataframe, timeperiod=self.fast_ma_period.value)
dataframe['slow_ma'] = ta.EMA(dataframe, timeperiod=self.slow_ma_period.value)
elif self.ma_type.value == "WMA":
# 加权移动平均线
dataframe['fast_ma'] = ta.WMA(dataframe, timeperiod=self.fast_ma_period.value)
dataframe['slow_ma'] = ta.WMA(dataframe, timeperiod=self.slow_ma_period.value)
# 趋势过滤指标 - 使用更大周期的EMA判断整体趋势
dataframe['trend_filter'] = ta.EMA(dataframe, timeperiod=self.trend_filter_period.value)
# 成交量指标
dataframe['volume_sma'] = ta.SMA(dataframe['volume'], timeperiod=20)
# 计算均线交叉信号
dataframe['ma_cross_up'] = qtpylib.crossed_above(dataframe['fast_ma'], dataframe['slow_ma'])
dataframe['ma_cross_down'] = qtpylib.crossed_below(dataframe['fast_ma'], dataframe['slow_ma'])
# 计算趋势方向 (快线相对于慢线的斜率)
dataframe['fast_ma_slope'] = dataframe['fast_ma'] - dataframe['fast_ma'].shift(1)
dataframe['slow_ma_slope'] = dataframe['slow_ma'] - dataframe['slow_ma'].shift(1)
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
生成买入信号
买入条件:
1. 金叉信号(快线上穿慢线)
2. 价格在快线上方(确认上涨趋势)
3. 成交量放大(确认信号强度)
4. 整体趋势向上(可选)
"""
dataframe.loc[
(
# 主要信号:金叉
dataframe['ma_cross_up']
# 价格确认:当前价格高于快线
& (dataframe['close'] > dataframe['fast_ma'])
# 成交量确认:成交量大于平均水平
& (dataframe['volume'] > dataframe['volume_sma'] * self.min_volume_multiplier.value)
# 可选:整体趋势向上(价格高于趋势线)
& (dataframe['close'] > dataframe['trend_filter'])
# 确保成交量不为0
& (dataframe['volume'] > 0)
),
'enter_long'
] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
生成卖出信号
卖出条件:
1. 死叉信号(快线下穿慢线)
2. 或价格跌破慢线
"""
dataframe.loc[
(
# 主要信号:死叉
dataframe['ma_cross_down']
# 或者价格跌破慢线
| (dataframe['close'] < dataframe['slow_ma'])
),
'exit_long'
] = 1
return dataframe
# ========================================
# 可选:自定义方法
# ========================================
def confirm_trade_entry(self, pair: str, order_type: str, amount: float,
rate: float, time_in_force: str, current_time: datetime,
entry_tag: Optional[str], side: str, **kwargs) -> bool:
"""
可选:确认交易进入
可以在这里添加额外的交易确认逻辑
"""
return True
def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str,
amount: float, rate: float, time_in_force: str,
exit_reason: str, current_time: datetime, **kwargs) -> bool:
"""
可选:确认交易退出
可以在这里添加额外的退出确认逻辑
"""
return True
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 # 使用1倍杠杆(现货交易)
def custom_stake_amount(self, pair: str, current_time: datetime, current_rate: float,
proposed_stake: float, min_stake: float, max_stake: float,
leverage: float, entry_tag: Optional[str], side: str, **kwargs) -> float:
"""
可选:自定义仓位大小
"""
return proposed_stake
# ========================================
# 绘图配置(可选)
# ========================================
plot_config = {
"main_plot": {
"fast_ma": {"color": "blue"},
"slow_ma": {"color": "red"},
"trend_filter": {"color": "green"},
},
"subplots": {
"Volume": {
"volume": {"color": "purple"},
"volume_sma": {"color": "orange"},
}
}
}