diff --git a/config_examples/staticgrid.json b/config_examples/staticgrid.json index fd42a2c..a0f2416 100644 --- a/config_examples/staticgrid.json +++ b/config_examples/staticgrid.json @@ -1,35 +1,21 @@ { - "strategy": "StaticGrid", - "$schema": "https://schema.freqtrade.io/schema.json", - "trading_mode": "spot", - "margin_mode": "isolated", - "max_open_trades": 100, + "strategy": "EthTrueStaticGrid", + "max_open_trades": 150, "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, + "stake_amount": 40, + "tradable_balance_ratio": 0.99, + "dry_run": false, + "timeframe": "1h", "position_adjustment_enable": true, - "amount_reserve_percent": 0.05, + "max_entry_position_adjustment": -1, + "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", + "price_side": "other", "use_order_book": true, "order_book_top": 1 }, @@ -38,13 +24,13 @@ "use_order_book": true, "order_book_top": 1 }, + + "exchange": { + "name": "okx", + "pair_whitelist": ["ETH/USDT"], + "ccxt_config": {"enableRateLimit": true} + }, + "pairlists": [{"method": "StaticPairList"}], - "bot_name": "StaticGrid-ETH", - "initial_state": "running", - "force_entry_enable": false, - "internals": { - "process_throttle_secs": 5, - "heartbeat_interval": 20, - "loglevel": "INFO" - } -} + "bot_name": "ETH-1500to4500-Grid" +} \ No newline at end of file diff --git a/freqtrade/templates/staticgrid.py b/freqtrade/templates/staticgrid.py index c9cf27e..c3cdc92 100644 --- a/freqtrade/templates/staticgrid.py +++ b/freqtrade/templates/staticgrid.py @@ -1,85 +1,47 @@ +# user_data/strategies/EthTrueStaticGrid.py ← 复制整个文件 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' + timeframe = '1h' # 1h 或 4h 都行,建议 1h 更灵敏 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) - + max_entry_position_adjustment = -1 + + # ================== 永续静态网格参数 ================== + LOWER = 1500.0 + UPPER = 4500.0 + GRID_STEP = 50.0 # 每格 50 USDT + GRID_COUNT = int((UPPER - LOWER) / GRID_STEP) # = 60 格 + + STAKE_PER_ORDER = 40 # 每张单 40 USDT(60格 × 40 × 2 ≈ 4800 USDT 吃满) + def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - # 静态网格不需要复杂的指标,仅需要价格 - return dataframe - - def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - """ - 入场逻辑: - - 只要价格低于或等于任何网格点,就在该网格点买入 - - 简单机械化:price <= grid_level * 1.002 就买入 - """ - dataframe['enter_long'] = False - - # 检查价格是否接近任何网格点 - for grid_level in self.GRID_LEVELS[:-1]: # 不包括最高点 - # 价格接近该网格点就买入(给 0.2% 容差以处理浮点数) - dataframe.loc[ - (dataframe['close'] <= grid_level * 1.002) & - (dataframe['volume'] > 0), - 'enter_long' - ] = True - - return dataframe - - def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - """ - 出场逻辑: - - 价格上升超过 GRID_STEP(50点),就卖出获利 - - 相对于入场点上升 50 点 - - 在 2650 价位,50 点 ≈ 1.89%,保险起见用 1.5% - """ - dataframe['exit_long'] = False - - # 只要价格反弹 1.5% 以上,就卖出 - # 这样平均每层网格获利接近 50 点 - dataframe['exit_long'] = ( - dataframe['close'] >= dataframe['close'].shift(1) * 1.015 - ) - 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 + def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + price = dataframe['close'].iloc[-1] + + # 从 1500 到 4450 每 50 USDT 一个价位,只要价格跌到或跌破这个价,就买入 + for level in range(self.GRID_COUNT): + buy_price = self.LOWER + level * self.GRID_STEP + if price <= buy_price: + dataframe.loc[dataframe['low'] <= buy_price, 'enter_long'] = True + return dataframe + + def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: + price = dataframe['close'].iloc[-1] + + # 从 1550 到 4500 每 50 USDT 一个价位,只要价格涨到或超过这个价,就卖出 + for level in range(1, self.GRID_COUNT + 1): + sell_price = self.LOWER + level * self.GRID_STEP + if price >= sell_price: + dataframe.loc[dataframe['high'] >= sell_price, 'exit_long'] = True + return dataframe + + def custom_stake_amount(self, **kwargs) -> float: + return self.STAKE_PER_ORDER \ No newline at end of file