first add
This commit is contained in:
parent
e66eac733d
commit
2efedb9745
60
config_examples/smartbbgrid.json
Normal file
60
config_examples/smartbbgrid.json
Normal file
@ -0,0 +1,60 @@
|
||||
{
|
||||
"strategy": "SmartBBGrid",
|
||||
"$schema": "https://schema.freqtrade.io/schema.json",
|
||||
"redis": {
|
||||
"url": "redis://192.168.1.215:6379/0"
|
||||
},
|
||||
"trading_mode": "spot",
|
||||
"margin_mode": "isolated",
|
||||
"max_open_trades": 55,
|
||||
"stake_currency": "USDT",
|
||||
"stake_amount": "unlimited",
|
||||
"tradable_balance_ratio": 1,
|
||||
"process_only_new_candles": false,
|
||||
"dry_run": true,
|
||||
"timeframe": "4h",
|
||||
"dry_run_wallet": 3000,
|
||||
"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": 200,
|
||||
"exchange": {
|
||||
"name": "okx",
|
||||
"key": "314e75b0-1113-47e8-ad01-1fca7e3c0496",
|
||||
"secret": "9C8B170390F46EA6FB87592AD46F5A34",
|
||||
"password": "nekFoylf:Om0",
|
||||
"ccxt_config": {
|
||||
"enableRateLimit": true,
|
||||
"rateLimit": 500
|
||||
},
|
||||
"pair_whitelist": ["BTC/USDT", "ETH/USDT", "SOL/USDT"]
|
||||
},
|
||||
"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": "SmartBBGrid-2025",
|
||||
"initial_state": "running",
|
||||
"force_entry_enable": false,
|
||||
"internals": {
|
||||
"process_throttle_secs": 5,
|
||||
"heartbeat_interval": 20,
|
||||
"loglevel": "INFO"
|
||||
}
|
||||
}
|
||||
3
freqtrade/templates/smartbbgrid.json
Normal file
3
freqtrade/templates/smartbbgrid.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"strategy_name": "SmartBBGrid"
|
||||
}
|
||||
102
freqtrade/templates/smartbbgrid.py
Normal file
102
freqtrade/templates/smartbbgrid.py
Normal file
@ -0,0 +1,102 @@
|
||||
# user_data/strategies/SmartBBGrid.py
|
||||
from freqtrade.strategy import IStrategy
|
||||
from pandas import DataFrame
|
||||
import talib.abstract as ta
|
||||
|
||||
class SmartBBGrid(IStrategy):
|
||||
INTERFACE_VERSION = 3
|
||||
timeframe = '4h'
|
||||
can_short = False
|
||||
|
||||
minimal_roi = {"0": 100} # 不自动ROI
|
||||
stoploss = -0.99
|
||||
startup_candle_count = 200
|
||||
use_exit_signal = True
|
||||
exit_profit_only = False
|
||||
ignore_roi_if_entry_signal = True
|
||||
|
||||
# ---------- 指标 ----------
|
||||
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
# 布林带(20期 2.3倍)
|
||||
bb = ta.BBANDS(dataframe, timeperiod=20, nbdevup=2.3, nbdevdn=2.3)
|
||||
dataframe['bb_lower'] = bb['lowerband']
|
||||
dataframe['bb_upper'] = bb['upperband']
|
||||
dataframe['bb_mid'] = bb['middleband']
|
||||
dataframe['bb_width'] = (dataframe['bb_upper'] - dataframe['bb_lower']) / dataframe['bb_mid']
|
||||
|
||||
# ADX
|
||||
dataframe['adx'] = ta.ADX(dataframe, timeperiod=14)
|
||||
return dataframe
|
||||
|
||||
# ---------- 买入 ----------
|
||||
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
dataframe['enter_long'] = False
|
||||
|
||||
# 震荡或强牛市都允许在下轨补仓
|
||||
oscillating = (dataframe['adx'] < 24) & (dataframe['bb_width'] > 0.04)
|
||||
strong_bull = dataframe['adx'] > 30
|
||||
|
||||
dataframe.loc[
|
||||
((oscillating | strong_bull) &
|
||||
(dataframe['close'] <= dataframe['bb_lower'] * 1.006) &
|
||||
(dataframe['volume'] > 0)),
|
||||
'enter_long'] = True
|
||||
return dataframe
|
||||
|
||||
# ---------- 卖出 ----------
|
||||
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
dataframe['exit_long'] = False
|
||||
|
||||
# 只有震荡市才卖,牛市死拿
|
||||
dataframe.loc[
|
||||
(dataframe['adx'] < 24) & (
|
||||
(dataframe['close'] >= dataframe['bb_upper'] * 0.994) | # 碰到上轨卖
|
||||
(dataframe['close'] >= dataframe['bb_mid'] * 1.13) # 赚13%全清
|
||||
),
|
||||
'exit_long'] = True
|
||||
return dataframe
|
||||
|
||||
# ---------- 每币25-30个订单 ----------
|
||||
|
||||
def custom_stake_amount(self, pair: str, current_time, current_rate,
|
||||
proposed_stake, min_stake, max_stake,
|
||||
entry_tag, **kwargs) -> float:
|
||||
|
||||
# 目标:每个币对保持 25-30 个订单
|
||||
TARGET_ORDERS_PER_PAIR = 27 # 中位数
|
||||
|
||||
# 1. 拿到当前钱包总余额
|
||||
total_balance = self.wallets.get_total_stake_amount()
|
||||
|
||||
# 2. 定义每个币对的资金占比
|
||||
weights = {
|
||||
'BTC/USDT': 0.30,
|
||||
'ETH/USDT': 0.30,
|
||||
'SOL/USDT': 0.40,
|
||||
}
|
||||
|
||||
# 3. 该币对应该占的总金额
|
||||
target_for_this_pair = total_balance * weights.get(pair, 0.33)
|
||||
|
||||
# 4. 该币对已经占了多少
|
||||
used_for_this_pair = self.wallets.get_used_for_pair(pair)
|
||||
|
||||
# 5. 还剩多少可以投入
|
||||
available = target_for_this_pair - used_for_this_pair
|
||||
|
||||
if available <= 0:
|
||||
return 0
|
||||
|
||||
# 6. 根据目标订单数,计算每笔应该投多少
|
||||
# 假设还需要投入的订单数 = 目标订单数 - 当前订单数
|
||||
current_trades_for_pair = len([t for t in self.trades if t.pair == pair])
|
||||
remaining_orders = max(1, TARGET_ORDERS_PER_PAIR - current_trades_for_pair)
|
||||
|
||||
# 平均分配剩余资金给剩余订单
|
||||
per_order_stake = available / remaining_orders
|
||||
|
||||
# 取最小值(不超过可用资金)
|
||||
stake = min(per_order_stake, proposed_stake)
|
||||
stake = max(stake, min_stake * 2) # 防止太小
|
||||
|
||||
return stake
|
||||
Loading…
x
Reference in New Issue
Block a user