first add
This commit is contained in:
parent
016f89e921
commit
de1601d9ff
50
config_examples/staticgrid.json
Normal file
50
config_examples/staticgrid.json
Normal file
@ -0,0 +1,50 @@
|
||||
{
|
||||
"strategy": "StaticGrid",
|
||||
"$schema": "https://schema.freqtrade.io/schema.json",
|
||||
"trading_mode": "spot",
|
||||
"margin_mode": "isolated",
|
||||
"max_open_trades": 100,
|
||||
"stake_currency": "USDT",
|
||||
"stake_amount": "unlimited",
|
||||
"tradable_balance_ratio": 1,
|
||||
"process_only_new_candles": false,
|
||||
"dry_run": true,
|
||||
"timeframe": "4h",
|
||||
"dry_run_wallet": 3500,
|
||||
"cancel_open_orders_on_exit": true,
|
||||
"max_entry_position_adjustment": -1,
|
||||
"position_adjustment_enable": true,
|
||||
"amount_reserve_percent": 0.05,
|
||||
"unfilledtimeout": {
|
||||
"entry": 5,
|
||||
"exit": 15
|
||||
},
|
||||
"startup_candle_count": 1,
|
||||
"exchange": {
|
||||
"name": "okx",
|
||||
"pair_whitelist": ["ETH/USDT"],
|
||||
"ccxt_config": {
|
||||
"enableRateLimit": true,
|
||||
"rateLimit": 500
|
||||
}
|
||||
},
|
||||
"entry_pricing": {
|
||||
"price_side": "same",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1
|
||||
},
|
||||
"exit_pricing": {
|
||||
"price_side": "other",
|
||||
"use_order_book": true,
|
||||
"order_book_top": 1
|
||||
},
|
||||
"pairlists": [{"method": "StaticPairList"}],
|
||||
"bot_name": "StaticGrid-ETH",
|
||||
"initial_state": "running",
|
||||
"force_entry_enable": false,
|
||||
"internals": {
|
||||
"process_throttle_secs": 5,
|
||||
"heartbeat_interval": 20,
|
||||
"loglevel": "INFO"
|
||||
}
|
||||
}
|
||||
@ -17,44 +17,3 @@ class SmartBBGrid(IStrategy):
|
||||
position_adjustment_enable = True
|
||||
max_entry_position_adjustment = 1
|
||||
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
# ADX & DI
|
||||
dataframe['adx'] = ta.ADX(dataframe, timeperiod=14)
|
||||
dataframe['plus_di'] = ta.PLUS_DI(dataframe, timeperiod=14)
|
||||
dataframe['minus_di'] = ta.MINUS_DI(dataframe, timeperiod=14)
|
||||
|
||||
# 平衡布林带倍数:既要频繁,又要精准
|
||||
dataframe['bb_mult'] = np.where(
|
||||
dataframe['minus_di'] > dataframe['plus_di'],
|
||||
1.8, # 熊市适度
|
||||
1.6 # 牛市适度 ← 兼顾频率和准确率
|
||||
)
|
||||
|
||||
# qtpylib 动态布林带
|
||||
bollinger = qtpylib.bollinger_bands(
|
||||
qtpylib.typical_price(dataframe),
|
||||
window=20,
|
||||
stds=dataframe['bb_mult']
|
||||
)
|
||||
dataframe['bb_lower'] = bollinger['lower']
|
||||
dataframe['bb_upper'] = bollinger['upper']
|
||||
dataframe['bb_mid'] = bollinger['mid']
|
||||
|
||||
return dataframe
|
||||
|
||||
# ← 这里结束
|
||||
|
||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
# 纯网格逻辑:只要价格接近下轨就买入
|
||||
dataframe['enter_long'] = (
|
||||
(dataframe['close'] <= dataframe['bb_lower'] * 1.02) & # 下轨附近 2% 范围
|
||||
(dataframe['volume'] > 0)
|
||||
)
|
||||
return dataframe
|
||||
|
||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
# 纯网格逻辑:只要小幅反弹就卖出
|
||||
dataframe['exit_long'] = (
|
||||
(dataframe['close'] >= dataframe['bb_lower'] * 1.005) # 反弹 0.5% 就卖
|
||||
)
|
||||
return dataframe
|
||||
|
||||
90
freqtrade/templates/staticgrid.py
Normal file
90
freqtrade/templates/staticgrid.py
Normal file
@ -0,0 +1,90 @@
|
||||
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
|
||||
Loading…
x
Reference in New Issue
Block a user