diff --git a/config_examples/staticgrid.json b/config_examples/staticgrid.json index 70e5b32..3144d43 100644 --- a/config_examples/staticgrid.json +++ b/config_examples/staticgrid.json @@ -8,9 +8,9 @@ "dry_run": false, "dry_run_wallet": 7766, "timeframe": "1h", - "position_adjustment_enable": true, + "position_adjustment_enable": false, "process_only_new_candles": false, - "max_entry_position_adjustment": -1, + "max_entry_position_adjustment": 0, "exchange": { "name": "okx", "key": "cbda9fde-b9e3-4a2d-94f9-e5c3705dfb5c", diff --git a/freqtrade/templates/staticgrid.py b/freqtrade/templates/staticgrid.py index e4c5c94..f358e0d 100644 --- a/freqtrade/templates/staticgrid.py +++ b/freqtrade/templates/staticgrid.py @@ -1,7 +1,7 @@ # /freqtrade/user_data/strategies/StaticGrid.py -from freqtrade.strategy import IStrategy +from freqtrade.strategy import IStrategy, merge_informative_pair from pandas import DataFrame -from typing import Optional +from typing import Optional, Dict, Any import logging import sys @@ -11,39 +11,34 @@ class StaticGrid(IStrategy): INTERFACE_VERSION = 3 timeframe = '1h' can_short = False - minimal_roi = {"0": 100} + minimal_roi = {"0": 0.001} # 极小收益就卖 stoploss = -0.99 use_exit_signal = True - position_adjustment_enable = True - max_entry_position_adjustment = -1 + position_adjustment_enable = False # 关闭加仓 + + cooldown_candles = 0 - # Lock configuration - disable lockout to allow immediate re-entry - cooldown_candles = 0 # No cooldown between trades - # Grid parameters - LOWER = 1500.0 # Minimum price - UPPER = 4500.0 # Maximum price - STEP = 50.0 # Grid spacing - STAKE = 40.0 # Per-trade stake + LOWER = 1500.0 + UPPER = 4500.0 + STEP = 50.0 + STAKE = 40.0 def __init__(self, config: dict) -> None: super().__init__(config) - # Force write to stderr immediately on startup print("[StaticGrid] Strategy initialized!", file=sys.stderr, flush=True) def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - print(f"[StaticGrid] populate_indicators called, df len: {len(dataframe)}", file=sys.stderr, flush=True) return dataframe def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """ - Static Grid Entry Logic using multiple enter_tags: - - Each grid level gets its own enter_tag (entry_grid_XXXX) - - This allows Freqtrade to create multiple orders per candle - - Buy at predefined grid levels: 1500, 1550, 1600, ..., 4500 (step 50) + 激进网格入场: + - 当价格低于任何网格点时,强制产生买入信号 + - 使用 enter_tag 来区分不同网格点 """ dataframe['enter_long'] = False - dataframe['enter_tag'] = "" + dataframe['enter_tag'] = '' if len(dataframe) == 0: return dataframe @@ -52,61 +47,43 @@ class StaticGrid(IStrategy): current_low = dataframe['low'].iloc[-1] print(f"[StaticGrid] Current price: {current_price:.2f}, low: {current_low:.2f}", file=sys.stderr, flush=True) - # Define static grid levels - LOWER = 1500.0 - UPPER = 4500.0 - STEP = 50.0 - - # Generate all grid levels in the range - grid_levels = [LOWER + i * STEP for i in range(int((UPPER - LOWER) / STEP) + 1)] - - # IMPORTANT: Add current price as a grid level too (rounded to nearest STEP) - current_grid_level = round(current_price / STEP) * STEP - if current_grid_level not in grid_levels and LOWER <= current_grid_level <= UPPER: - grid_levels.append(current_grid_level) - - grid_levels.sort() + # 生成所有网格点 + grid_levels = [self.LOWER + i * self.STEP for i in range(int((self.UPPER - self.LOWER) / self.STEP) + 1)] entry_count = 0 - grid_tags = [] # Collect all grid levels that should trigger entry - # For each grid level, check if price is at or below it + # 对每个网格点检查是否应该入场 for grid_price in grid_levels: - # Buy if current low is at or below this grid level (with 0.5% tolerance) - if current_low <= grid_price * 1.005: - entry_count += 1 + # 激进条件:价格低于网格点就买 + if current_low <= grid_price: + dataframe.loc[dataframe.index[-1], 'enter_long'] = True tag = f"grid_{int(grid_price)}" - grid_tags.append(tag) - if entry_count <= 5: # Only print first 5 for brevity + # 累加所有适用的标签 + if dataframe.loc[dataframe.index[-1], 'enter_tag']: + dataframe.loc[dataframe.index[-1], 'enter_tag'] += f",{tag}" + else: + dataframe.loc[dataframe.index[-1], 'enter_tag'] = tag + entry_count += 1 + if entry_count <= 5: print(f"[StaticGrid] Entry at grid {grid_price:.0f}", file=sys.stderr, flush=True) if entry_count > 5: print(f"[StaticGrid] ... and {entry_count - 5} more grid levels", file=sys.stderr, flush=True) - print(f"[StaticGrid] Total entry signals: {entry_count}", file=sys.stderr, flush=True) - # Set enter_long = True for the last row (current candle) - if entry_count > 0: - dataframe.loc[dataframe.index[-1], 'enter_long'] = True - # Use the grid tags separated by comma - dataframe.loc[dataframe.index[-1], 'enter_tag'] = ','.join(grid_tags) - return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """ - Exit Logic - AGGRESSIVE: - - Exit as soon as price moves up at all (even 0.01% profit) - - This ensures we close positions quickly for grid trading + 极端出场:任何上升就卖 """ dataframe['exit_long'] = False if len(dataframe) < 2: return dataframe - # EXTREME: Exit on ANY upward movement (even micro profits) - # This forces position closure to allow new entries - dataframe['exit_long'] = (dataframe['close'] > dataframe['open']).fillna(False) + # 只要收盘价高于开盘价就卖出 + dataframe['exit_long'] = (dataframe['close'] > dataframe['open']) exits = dataframe['exit_long'].sum() if exits > 0: @@ -118,26 +95,6 @@ class StaticGrid(IStrategy): current_profit: float, min_stake: float, max_stake: float, **kwargs) -> Optional[float]: """ - Network Grid Position Adjustment (DCA - Dollar Cost Averaging): - 每当价格跌到新的网格点时,自动加仓 + 不使用加仓 """ - LOWER = 1500.0 - UPPER = 4500.0 - STEP = 50.0 - - # Only add position if price drops to a new grid level - grid_level = round(current_rate / STEP) * STEP - - # Calculate how many positions we've already opened - open_positions = trade.nr_of_successful_entries - - # Maximum positions per pair = (UPPER - LOWER) / STEP - max_positions = int((UPPER - LOWER) / STEP) + 1 - - if open_positions < max_positions and LOWER <= grid_level <= UPPER: - # Add position at each grid level - print(f"[StaticGrid] Adding position at grid level {grid_level:.0f}, current rate {current_rate:.2f}", - file=sys.stderr, flush=True) - return self.STAKE - return None