91 lines
3.1 KiB
Python
91 lines
3.1 KiB
Python
from freqtrade.strategy import IStrategy
|
||
from pandas import DataFrame
|
||
import numpy as np
|
||
|
||
class StaticGrid(IStrategy):
|
||
"""
|
||
纯静态网格策略 - ETH/USDT
|
||
价格范围:1500 ~ 4800
|
||
网格间距:50点
|
||
网格数量:66个
|
||
"""
|
||
|
||
INTERFACE_VERSION = 3
|
||
timeframe = '4h'
|
||
can_short = False
|
||
|
||
# 基础配置
|
||
minimal_roi = {"0": 100}
|
||
stoploss = -0.99
|
||
startup_candle_count = 1
|
||
use_exit_signal = True
|
||
exit_profit_only = False
|
||
ignore_roi_if_entry_signal = True
|
||
|
||
# 加仓配置
|
||
position_adjustment_enable = True
|
||
max_entry_position_adjustment = -1 # 无限加仓
|
||
|
||
# ========== 静态网格参数 ==========
|
||
GRID_LOW = 1500 # 网格下限
|
||
GRID_HIGH = 4800 # 网格上限
|
||
GRID_STEP = 50 # 网格间距
|
||
GRID_COUNT = 66 # 网格数量
|
||
|
||
# 计算网格点
|
||
GRID_LEVELS = np.linspace(GRID_LOW, GRID_HIGH, GRID_COUNT)
|
||
|
||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||
# 静态网格不需要复杂的指标,仅需要价格
|
||
return dataframe
|
||
|
||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||
"""
|
||
入场逻辑:
|
||
- 价格每次跌破一个网格点,就在该网格点买入
|
||
- 从上往下遍历所有网格点
|
||
"""
|
||
dataframe['enter_long'] = False
|
||
|
||
# 对每个网格点进行判断
|
||
for i, grid_level in enumerate(self.GRID_LEVELS[:-1]): # 不包括最后一个点
|
||
# 价格接近或低于该网格点就买入
|
||
# 使用 <= grid_level * 1.001 来避免浮点数精度问题
|
||
dataframe.loc[
|
||
(dataframe['close'] <= grid_level * 1.001) &
|
||
(dataframe['close'] > (grid_level - self.GRID_STEP)) &
|
||
(dataframe['volume'] > 0),
|
||
'enter_long'
|
||
] = True
|
||
|
||
return dataframe
|
||
|
||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||
"""
|
||
出场逻辑:
|
||
- 每笔交易进场后,在上一个网格点卖出
|
||
- 每层网格的利润 = GRID_STEP / 当前价格
|
||
"""
|
||
dataframe['exit_long'] = False
|
||
|
||
# 简单策略:价格每上升 GRID_STEP,就卖出
|
||
# 这里我们使用一个简化的方法:如果价格上升了 GRID_STEP 点以上,就卖出
|
||
|
||
# 计算相对于入场价格的涨幅百分比(目标:50点收益)
|
||
# 假设平均入场价在 2650 左右,50点 = 1.88%
|
||
# 为了泛用,我们设定:只要有 0.9% 的利润就卖出
|
||
dataframe['exit_long'] = (
|
||
dataframe['close'] >= (dataframe['close'].shift(1) * 1.009)
|
||
)
|
||
|
||
return dataframe
|
||
|
||
def custom_stake_amount(self, pair: str, current_time, current_rate,
|
||
proposed_stake, min_stake, max_stake,
|
||
entry_tag, **kwargs) -> float:
|
||
"""
|
||
每笔投入金额:固定 50 USDT
|
||
目标:总投入 = 50 * 66 = 3300 USDT
|
||
"""
|
||
return 50.0
|