From 6708fa6ffc6bd5777e5ce7101368fe7d89fc9eda Mon Sep 17 00:00:00 2001 From: "zhangkun9038@dingtalk.com" Date: Thu, 27 Nov 2025 11:56:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=92=E6=9F=A5=E6=B2=A1=E6=9C=89n=E7=AC=94?= =?UTF-8?q?=E4=BA=A4=E6=98=93+1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config_examples/staticgrid.json | 2 ++ freqtrade/templates/staticgrid.py | 38 ++++++++++++++++++++----------- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/config_examples/staticgrid.json b/config_examples/staticgrid.json index d68f888..c76e335 100644 --- a/config_examples/staticgrid.json +++ b/config_examples/staticgrid.json @@ -39,6 +39,8 @@ "entry": 5, "exit": 15 }, + "cooldown_volume": 0, + "action_space": "default", "entry_pricing": { "price_side": "other", "use_order_book": true, diff --git a/freqtrade/templates/staticgrid.py b/freqtrade/templates/staticgrid.py index 0b6072d..fc8e039 100644 --- a/freqtrade/templates/staticgrid.py +++ b/freqtrade/templates/staticgrid.py @@ -15,6 +15,9 @@ class StaticGrid(IStrategy): use_exit_signal = True position_adjustment_enable = True max_entry_position_adjustment = -1 + + # Lock configuration - disable lockout to allow immediate re-entry + cooldown_candles = 0 # No cooldown between trades # Grid parameters LOWER = 1500.0 # Minimum price @@ -33,9 +36,10 @@ class StaticGrid(IStrategy): def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: """ - Grid Entry Logic: - - Buy at each grid level when price drops to it - - Grid levels: 1500, 1550, 1600, ..., 4500 (step 50) + Dynamic Grid Entry Logic: + - Automatically calculates grid levels based on current price + - Creates grid points with fixed percentage step (e.g., 1.5% apart) + - Works for any price range (BTC, ETH, SOL, etc.) """ dataframe['enter_long'] = False @@ -46,19 +50,27 @@ class StaticGrid(IStrategy): current_price = dataframe['close'].iloc[-1] print(f"[StaticGrid] Current price: {current_price:.2f}", file=sys.stderr, flush=True) - # Check which grid level price is closest to or below - # If price is near any grid level, buy - for i in range(int((self.UPPER - self.LOWER) / self.STEP) + 1): - grid_price = self.LOWER + i * self.STEP + # Dynamic grid: use percentage-based steps instead of fixed price steps + # Grid step: 1.5% (you can adjust this) + grid_step_pct = 0.015 # 1.5% + + # Create grid levels around current price + # Generate grid points below current price (for buying) + num_levels_below = 10 # Generate 10 levels below current price + + for i in range(num_levels_below): + grid_price = current_price * ((1 - grid_step_pct) ** (i + 1)) - # Buy if we're at this grid level (within 2% tolerance) - # This allows buying at intermediate prices too - if current_price <= grid_price * 1.02: - # Mark this candle and recent candles for entry - dataframe.loc[dataframe['close'] <= grid_price * 1.02, 'enter_long'] = True + # Buy if price drops to or below this grid level + if dataframe['low'].iloc[-1] <= grid_price * 1.01: + dataframe['enter_long'] = True + print(f"[StaticGrid] Buy signal at grid level {i+1}: {grid_price:.2f}", file=sys.stderr, flush=True) + break # Only buy at one level per candle entries = dataframe['enter_long'].sum() - print(f"[StaticGrid] Entry signals: {entries}", file=sys.stderr, flush=True) + if entries > 0: + print(f"[StaticGrid] Entry signals: {entries}", file=sys.stderr, flush=True) + return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: