最后一次尝试 单币对多交易
This commit is contained in:
parent
1a4560aedc
commit
f8cb87374f
@ -8,9 +8,9 @@
|
|||||||
"dry_run": false,
|
"dry_run": false,
|
||||||
"dry_run_wallet": 7766,
|
"dry_run_wallet": 7766,
|
||||||
"timeframe": "1h",
|
"timeframe": "1h",
|
||||||
"position_adjustment_enable": true,
|
"position_adjustment_enable": false,
|
||||||
"process_only_new_candles": false,
|
"process_only_new_candles": false,
|
||||||
"max_entry_position_adjustment": -1,
|
"max_entry_position_adjustment": 0,
|
||||||
"exchange": {
|
"exchange": {
|
||||||
"name": "okx",
|
"name": "okx",
|
||||||
"key": "cbda9fde-b9e3-4a2d-94f9-e5c3705dfb5c",
|
"key": "cbda9fde-b9e3-4a2d-94f9-e5c3705dfb5c",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# /freqtrade/user_data/strategies/StaticGrid.py
|
# /freqtrade/user_data/strategies/StaticGrid.py
|
||||||
from freqtrade.strategy import IStrategy
|
from freqtrade.strategy import IStrategy, merge_informative_pair
|
||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
from typing import Optional
|
from typing import Optional, Dict, Any
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@ -11,39 +11,34 @@ class StaticGrid(IStrategy):
|
|||||||
INTERFACE_VERSION = 3
|
INTERFACE_VERSION = 3
|
||||||
timeframe = '1h'
|
timeframe = '1h'
|
||||||
can_short = False
|
can_short = False
|
||||||
minimal_roi = {"0": 100}
|
minimal_roi = {"0": 0.001} # 极小收益就卖
|
||||||
stoploss = -0.99
|
stoploss = -0.99
|
||||||
use_exit_signal = True
|
use_exit_signal = True
|
||||||
position_adjustment_enable = True
|
position_adjustment_enable = False # 关闭加仓
|
||||||
max_entry_position_adjustment = -1
|
|
||||||
|
cooldown_candles = 0
|
||||||
|
|
||||||
# Lock configuration - disable lockout to allow immediate re-entry
|
|
||||||
cooldown_candles = 0 # No cooldown between trades
|
|
||||||
|
|
||||||
# Grid parameters
|
# Grid parameters
|
||||||
LOWER = 1500.0 # Minimum price
|
LOWER = 1500.0
|
||||||
UPPER = 4500.0 # Maximum price
|
UPPER = 4500.0
|
||||||
STEP = 50.0 # Grid spacing
|
STEP = 50.0
|
||||||
STAKE = 40.0 # Per-trade stake
|
STAKE = 40.0
|
||||||
|
|
||||||
def __init__(self, config: dict) -> None:
|
def __init__(self, config: dict) -> None:
|
||||||
super().__init__(config)
|
super().__init__(config)
|
||||||
# Force write to stderr immediately on startup
|
|
||||||
print("[StaticGrid] Strategy initialized!", file=sys.stderr, flush=True)
|
print("[StaticGrid] Strategy initialized!", file=sys.stderr, flush=True)
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
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
|
return dataframe
|
||||||
|
|
||||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> 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
|
- 使用 enter_tag 来区分不同网格点
|
||||||
- Buy at predefined grid levels: 1500, 1550, 1600, ..., 4500 (step 50)
|
|
||||||
"""
|
"""
|
||||||
dataframe['enter_long'] = False
|
dataframe['enter_long'] = False
|
||||||
dataframe['enter_tag'] = ""
|
dataframe['enter_tag'] = ''
|
||||||
|
|
||||||
if len(dataframe) == 0:
|
if len(dataframe) == 0:
|
||||||
return dataframe
|
return dataframe
|
||||||
@ -52,61 +47,43 @@ class StaticGrid(IStrategy):
|
|||||||
current_low = dataframe['low'].iloc[-1]
|
current_low = dataframe['low'].iloc[-1]
|
||||||
print(f"[StaticGrid] Current price: {current_price:.2f}, low: {current_low:.2f}", file=sys.stderr, flush=True)
|
print(f"[StaticGrid] Current price: {current_price:.2f}, low: {current_low:.2f}", file=sys.stderr, flush=True)
|
||||||
|
|
||||||
# Define static grid levels
|
# 生成所有网格点
|
||||||
LOWER = 1500.0
|
grid_levels = [self.LOWER + i * self.STEP for i in range(int((self.UPPER - self.LOWER) / self.STEP) + 1)]
|
||||||
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()
|
|
||||||
|
|
||||||
entry_count = 0
|
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:
|
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:
|
if current_low <= grid_price:
|
||||||
entry_count += 1
|
dataframe.loc[dataframe.index[-1], 'enter_long'] = True
|
||||||
tag = f"grid_{int(grid_price)}"
|
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)
|
print(f"[StaticGrid] Entry at grid {grid_price:.0f}", file=sys.stderr, flush=True)
|
||||||
|
|
||||||
if entry_count > 5:
|
if entry_count > 5:
|
||||||
print(f"[StaticGrid] ... and {entry_count - 5} more grid levels", file=sys.stderr, flush=True)
|
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)
|
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
|
return dataframe
|
||||||
|
|
||||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> 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
|
dataframe['exit_long'] = False
|
||||||
|
|
||||||
if len(dataframe) < 2:
|
if len(dataframe) < 2:
|
||||||
return dataframe
|
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'])
|
||||||
dataframe['exit_long'] = (dataframe['close'] > dataframe['open']).fillna(False)
|
|
||||||
|
|
||||||
exits = dataframe['exit_long'].sum()
|
exits = dataframe['exit_long'].sum()
|
||||||
if exits > 0:
|
if exits > 0:
|
||||||
@ -118,26 +95,6 @@ class StaticGrid(IStrategy):
|
|||||||
current_profit: float, min_stake: float,
|
current_profit: float, min_stake: float,
|
||||||
max_stake: float, **kwargs) -> Optional[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
|
return None
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user