Add freqtrade quant strategies and deploy docs

This commit is contained in:
wiki-agent
2026-08-23 04:11:24 +00:00
parent 09ecdbb654
commit 523483f26d
73 changed files with 10346 additions and 0 deletions
@@ -0,0 +1,197 @@
{
"max_open_trades": 2,
"stake_currency": "USDT",
"stake_amount": "unlimited",
"tradable_balance_ratio": 0.99,
"fiat_display_currency": "USD",
"dry_run": false,
"timeframe": "15m",
"stoploss": -0.80,
"cancel_open_orders_on_exit": false,
"trading_mode": "futures",
"margin_mode": "isolated",
"collateral": "USDT",
"unfilledtimeout": {
"entry": 10,
"exit": 10,
"exit_timeout_count": 0,
"unit": "minutes"
},
"entry_pricing": {
"price_side": "ask",
"use_order_book": true,
"order_book_top": 1,
"price_last_balance": 0.0,
"check_depth_of_market": {
"enabled": false,
"bids_to_ask_delta": 1
}
},
"exit_pricing": {
"price_side": "same",
"use_order_book": true,
"order_book_top": 1,
"price_last_balance": 0.0
},
"exchange": {
"name": "okx",
"key": "e756108d-f14c-4777-8351-cd989f389dd2",
"secret": "BC4579AEE9816ED4A38218910B6EC278",
"password": "30l9L666.",
"ccxt_config": {
"hostname": "www.okx.cab"
},
"ccxt_async_config": {
"hostname": "www.okx.cab"
},
"pair_whitelist": [
"BTC/USDT:USDT",
"ETH/USDT:USDT"
],
"pair_blacklist": []
},
"pairlists": [
{
"method": "StaticPairList"
}
],
"api_server": {
"enabled": true,
"listen_ip_address": "0.0.0.0",
"listen_port": 8080,
"verbosity": "error",
"enable_openapi": true,
"jwt_secret_key": "somethingRandomSomethingRandom123",
"CORS_origins": [
"*"
],
"username": "liam",
"password": "30l9L666"
},
"bot_name": "freqtrade",
"force_entry_enable": true,
"webhook": {
"enabled": true,
"url": "https://open.feishu.cn/open-apis/bot/v2/hook/2b1bc9a6-b470-447f-b783-1b253dcf522c",
"format": "json",
"timeout": 10,
"entry": {
"msg_type": "interactive",
"card": {
"header": {
"title": {
"content": "🟢 交易信号: {pair}",
"tag": "plain_text"
},
"template": "blue"
},
"elements": [
{
"tag": "div",
"text": {
"content": "方向: {direction}\n入场价: {open_rate}\n金额: {stake_amount:.2f} {stake_currency}\n杠杆: {leverage}x\n信号: {enter_tag}",
"tag": "lark_md"
}
},
{
"tag": "hr"
},
{
"tag": "div",
"text": {
"content": "时间: {open_date}",
"tag": "lark_md"
}
}
]
}
},
"entry_fill": {
"msg_type": "interactive",
"card": {
"header": {
"title": {
"content": "✅ 入场成交: {pair}",
"tag": "plain_text"
},
"template": "green"
},
"elements": [
{
"tag": "div",
"text": {
"content": "成交价: {open_rate}\n数量: {amount}\n金额: {stake_amount:.2f} {stake_currency}\n杠杆: {leverage}x",
"tag": "lark_md"
}
}
]
}
},
"exit": {
"msg_type": "interactive",
"card": {
"header": {
"title": {
"content": "🔴 退出信号: {pair}",
"tag": "plain_text"
},
"template": "red"
},
"elements": [
{
"tag": "div",
"text": {
"content": "当前价: {current_rate}\n盈亏率: {profit_ratio:.2%}\n原因: {exit_reason}",
"tag": "lark_md"
}
}
]
}
},
"exit_fill": {
"msg_type": "interactive",
"card": {
"header": {
"title": {
"content": "✅ 退出成交: {pair}",
"tag": "plain_text"
},
"template": "green"
},
"elements": [
{
"tag": "div",
"text": {
"content": "退出价: {close_rate}\n盈亏率: {profit_ratio:.2%}\n盈亏额: {profit_amount:.4f}\n原因: {exit_reason}",
"tag": "lark_md"
}
}
]
}
},
"entry_cancel": {
"msg_type": "interactive",
"card": {
"header": {
"title": {
"content": "⚠ 入场取消: {pair}",
"tag": "plain_text"
},
"template": "yellow"
},
"elements": [
{
"tag": "div",
"text": {
"content": "原因: {reason}\n数量: {amount}\n价格: {open_rate}",
"tag": "lark_md"
}
}
]
}
}
},
"initial_state": "running",
"strategy": "MultiAssetChannelBreakoutV5",
"strategy_path": "user_data/strategies/"
}
@@ -0,0 +1,141 @@
{
"max_open_trades": 5,
"stake_currency": "USDT",
"stake_amount": "unlimited",
"tradable_balance_ratio": 0.99,
"fiat_display_currency": "USD",
"dry_run": false,
"timeframe": "5m",
"stoploss": -0.10,
"cancel_open_orders_on_exit": false,
"trading_mode": "futures",
"margin_mode": "isolated",
"collateral": "USDT",
"unfilledtimeout": {
"entry": 10,
"exit": 10,
"exit_timeout_count": 0,
"unit": "minutes"
},
"entry_pricing": {
"price_side": "ask",
"use_order_book": true,
"order_book_top": 1,
"price_last_balance": 0.0,
"check_depth_of_market": {
"enabled": false,
"bids_to_ask_delta": 1
}
},
"exit_pricing": {
"price_side": "same",
"use_order_book": true,
"order_book_top": 1,
"price_last_balance": 0.0
},
"exchange": {
"name": "okx",
"key": "e756108d-f14c-4777-8351-cd989f389dd2",
"secret": "BC4579AEE9816ED4A38218910B6EC278",
"password": "30l9L666.",
"ccxt_config": {
"hostname": "www.okx.cab"
},
"ccxt_async_config": {
"hostname": "www.okx.cab"
},
"pair_whitelist": [
"BTC/USDT:USDT",
"ETH/USDT:USDT",
"TRX/USDT:USDT"
],
"pair_blacklist": []
},
"pairlists": [
{"method": "StaticPairList"}
],
"api_server": {
"enabled": true,
"listen_ip_address": "0.0.0.0",
"listen_port": 8080,
"verbosity": "error",
"enable_openapi": true,
"jwt_secret_key": "somethingRandomSomethingRandom123",
"CORS_origins": ["*"],
"username": "liam",
"password": "30l9L666"
},
"bot_name": "freqtrade",
"force_entry_enable": true,
"webhook": {
"enabled": true,
"url": "https://open.feishu.cn/open-apis/bot/v2/hook/2b1bc9a6-b470-447f-b783-1b253dcf522c",
"format": "json",
"timeout": 10,
"entry": {
"msg_type": "interactive",
"card": {
"header": {
"title": {"content": "🟢 交易信号: {pair}", "tag": "plain_text"},
"template": "blue"
},
"elements": [
{"tag": "div", "text": {"content": "方向: {direction}\n入场价: {open_rate}\n金额: {stake_amount:.2f} {stake_currency}\n杠杆: {leverage}x\n信号: {enter_tag}", "tag": "lark_md"}},
{"tag": "hr"},
{"tag": "div", "text": {"content": "时间: {open_date}", "tag": "lark_md"}}
]
}
},
"entry_fill": {
"msg_type": "interactive",
"card": {
"header": {
"title": {"content": "✅ 入场成交: {pair}", "tag": "plain_text"},
"template": "green"
},
"elements": [
{"tag": "div", "text": {"content": "成交价: {open_rate}\n数量: {amount}\n金额: {stake_amount:.2f} {stake_currency}\n杠杆: {leverage}x", "tag": "lark_md"}}
]
}
},
"exit": {
"msg_type": "interactive",
"card": {
"header": {
"title": {"content": "🔴 退出信号: {pair}", "tag": "plain_text"},
"template": "red"
},
"elements": [
{"tag": "div", "text": {"content": "当前价: {current_rate}\n盈亏率: {profit_ratio:.2%}\n原因: {exit_reason}", "tag": "lark_md"}}
]
}
},
"exit_fill": {
"msg_type": "interactive",
"card": {
"header": {
"title": {"content": "✅ 退出成交: {pair}", "tag": "plain_text"},
"template": "green"
},
"elements": [
{"tag": "div", "text": {"content": "退出价: {close_rate}\n盈亏率: {profit_ratio:.2%}\n盈亏额: {profit_amount:.4f}\n原因: {exit_reason}", "tag": "lark_md"}}
]
}
},
"entry_cancel": {
"msg_type": "interactive",
"card": {
"header": {
"title": {"content": "⚠ 入场取消: {pair}", "tag": "plain_text"},
"template": "yellow"
},
"elements": [
{"tag": "div", "text": {"content": "原因: {reason}\n数量: {amount}\n价格: {open_rate}", "tag": "lark_md"}}
]
}
}
},
"initial_state": "running",
"strategy": "QuantDingerStrategy",
"strategy_path": "user_data/strategies/"
}
@@ -0,0 +1,187 @@
import pandas as pd
import talib.abstract as ta
from functools import reduce
from datetime import datetime
from freqtrade.strategy import (IStrategy, IntParameter, DecimalParameter)
from freqtrade.persistence import Trade
class MultiAssetChannelBreakoutV5(IStrategy):
"""
多币种通道突破策略 V5。
策略核心思想:
1) 用 ATR 构建波动率自适应通道,避免固定阈值在不同波动阶段失效;
2) 用长周期均线 + ADX 过滤震荡,仅在趋势和动量共振时入场;
3) 用动态下轨出场 + 自定义分段止损,兼顾跟踪利润与回撤控制;
4) 用入场二次确认减少信号触发后追高与滑点风险。
说明:
- 当前默认参数来自 `MultiAssetChannelBreakoutV3.json` 的优化结果;
- 策略为单向做多(can_short=False),期货模式下通过 leverage() 固定 10x。
"""
INTERFACE_VERSION = 3
# --- 1) 基础交易设置 ---
# 关闭 ROI 快速止盈,完全依赖信号出场 + custom_stoploss 风控。
minimal_roi = {"0": 100}
# 硬止损作为最后防线(保证金维度 -80% = 价格 -8%,10x 杠杆下接近爆仓线但能扛住正常波动)。
stoploss = -0.80
trailing_stop = False
use_custom_stoploss = True
timeframe = "15m"
can_short = False
# 预热 K 线数量:覆盖长均线与通道计算窗口,避免初期信号失真。
startup_candle_count = 600
# --- 2) 可优化参数(默认值已填入优化结果) ---
# 上轨窗口:越大越平滑,越小越敏感。
up_line_span = IntParameter(100, 400, default=340, space="buy", optimize=True)
# 下轨窗口:用于退出通道底边计算。
buy_stop_profit_span = IntParameter(50, 200, default=141, space="buy", optimize=True)
# 长均线天数(会换算成 15m 周期)。
ma_span_long_days = IntParameter(1, 5, default=2, space="buy", optimize=True)
# 动量阈值:过滤弱趋势。
adx_threshold = IntParameter(15, 40, default=28, space="buy", optimize=True)
# 上轨波动率偏移:ATR * offset。
up_line_offset = DecimalParameter(-0.2, 0.4, default=-0.18, decimals=2, space="buy", optimize=True)
# 下轨波动率偏移:ATR * offset,用于构建动态退出线。
buy_stop_profit_offset = DecimalParameter(-0.2, 0.2, default=0.19, decimals=2, space="sell", optimize=True)
def populate_indicators(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
"""
计算策略使用的全部指标。
指标列表:
- n_value: ATR(10),用于描述近期真实波动率;
- ma_long: 长周期均线(天数 * 96 根 15m K);
- up_line: 历史高点通道上轨 + ATR 偏移;
- bottom_line: 历史低点通道下轨;
- adx: ADX(14) 动量强度指标。
"""
dataframe["n_value"] = ta.ATR(dataframe, timeperiod=10)
ma_length = self.ma_span_long_days.value * 96
dataframe["ma_long"] = ta.SMA(dataframe, timeperiod=ma_length)
base_up_line = dataframe["high"].rolling(window=self.up_line_span.value).max().shift(1)
dataframe["up_line"] = base_up_line + (dataframe["n_value"] * self.up_line_offset.value)
dataframe["bottom_line"] = dataframe["low"].rolling(window=self.buy_stop_profit_span.value).min().shift(1)
dataframe["adx"] = ta.ADX(dataframe, timeperiod=14)
return dataframe
def populate_entry_trend(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
"""
入场逻辑(做多):
- 指标有效(ATR、上轨非空);
- 收盘价在长均线上方(趋势过滤);
- ADX 高于阈值(动量过滤);
- 收盘价突破动态上轨(突破确认)。
"""
conditions = []
conditions.append(dataframe["n_value"].notnull())
conditions.append(dataframe["up_line"].notnull())
conditions.append(dataframe["close"] > dataframe["ma_long"])
conditions.append(dataframe["adx"] > self.adx_threshold.value)
conditions.append(dataframe["close"] > dataframe["up_line"])
if conditions:
is_entry = reduce(lambda x, y: x & y, conditions)
dataframe.loc[is_entry, "enter_long"] = 1
dataframe.loc[is_entry, "enter_tag"] = "trend_breakout"
return dataframe
def populate_exit_trend(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
"""
出场逻辑:
- 构建动态退出线:bottom_line + ATR * buy_stop_profit_offset
- 收盘价跌破退出线时触发平仓信号。
"""
offset = self.buy_stop_profit_offset.value
exit_line = dataframe["bottom_line"] + (dataframe["n_value"] * offset)
exit_condition = dataframe["close"] < exit_line
dataframe.loc[exit_condition, "exit_long"] = 1
dataframe.loc[exit_condition, "exit_tag"] = "channel_exit"
return dataframe
def leverage(self, pair: str, current_time: datetime, current_rate: float,
proposed_leverage: float, max_leverage: float, entry_tag: str, side: str,
**kwargs) -> float:
"""
统一固定 10x 杠杆。
"""
return 10.0
def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime,
current_rate: float, current_profit: float, **kwargs) -> float:
"""
分段动态止损(所有阈值通过 trade.leverage 动态联动杠杆):
- 盈利 > 价格+30%: 允许 10% 价格回撤;
- 盈利 > 价格+15%: 允许 10% 价格回撤;
- 盈利 > 价格+5%: 将止损上移到保本上方约 5%(覆盖手续费与滑点);
- 其余阶段: 交由全局硬止损处理。
"""
L = trade.leverage
if current_profit > 0.30 * L:
return 0.10 * L
if current_profit > 0.15 * L:
return 0.10 * L
if current_profit > 0.05 * L:
breakeven_target = trade.open_rate * 1.05
return (current_rate - breakeven_target) / current_rate * L
return L
def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float,
time_in_force: str, current_time: datetime, entry_tag: str,
side: str, **kwargs) -> bool:
"""
入场二次确认(防追高与防假突破):
- 取触发信号的已收盘 K 线 (iloc[-2]) 作为基准;
- 实时下单价不能低穿信号 K 线的均线和上轨(防假突破被瞬间砸回);
- 下单价较信号 K 线收盘价高出 0.5% 以上,放弃交易(防滑点追高)。
"""
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
# 确保数据量足够回溯
if len(dataframe) < 3:
return False
# --- 1. 动态寻找真正的"信号 K 线" ---
# 解决 Freqtrade 实盘中 DataFrame 最后一根 K 线可能是正在运行的新 K 线,
# 也可能是刚刚收盘的信号 K 线的"索引漂移"问题。
signal_candle = None
# 倒序检查最后 3 根 K 线,定位打上 enter_long=1 标签的那一根
for i in range(-1, -4, -1):
if dataframe['enter_long'].iloc[i] == 1:
signal_candle = dataframe.iloc[i]
break
# 如果最近几根都没信号(比如极端网络延迟造成的陈旧发单),果断放弃交易
if signal_candle is None:
return False
# --- 2. 核心校验:必须与信号当期的指标进行对比 ---
# 解决"突破极值瞬间跳升"导致订单被错杀的问题
# 防假突破被瞬间砸回:实时下单价 (rate) 不能低穿【信号发生时】的均线和上轨
if rate <= signal_candle["ma_long"]:
return False
if rate <= signal_candle["up_line"]:
return False
# 防滑点追高:实时下单价 (rate) 较【信号发生时】的收盘价不能偏离过高
# 注意:此处允许 1% 的追高滑点,如果在 15m 级别觉得 1% 的滑点成本太大,可以改为 1.005 (0.5%)
if rate > signal_candle["close"] * 1.01:
return False
return True
@@ -0,0 +1,187 @@
import pandas as pd
import talib.abstract as ta
from functools import reduce
from datetime import datetime
from freqtrade.strategy import (IStrategy, IntParameter, DecimalParameter)
from freqtrade.persistence import Trade
class MultiAssetChannelBreakoutV5(IStrategy):
"""
多币种通道突破策略 V5。
策略核心思想:
1) 用 ATR 构建波动率自适应通道,避免固定阈值在不同波动阶段失效;
2) 用长周期均线 + ADX 过滤震荡,仅在趋势和动量共振时入场;
3) 用动态下轨出场 + 自定义分段止损,兼顾跟踪利润与回撤控制;
4) 用入场二次确认减少信号触发后追高与滑点风险。
说明:
- 当前默认参数来自 `MultiAssetChannelBreakoutV3.json` 的优化结果;
- 策略为单向做多(can_short=False),期货模式下通过 leverage() 固定 10x。
"""
INTERFACE_VERSION = 3
# --- 1) 基础交易设置 ---
# 关闭 ROI 快速止盈,完全依赖信号出场 + custom_stoploss 风控。
minimal_roi = {"0": 100}
# 硬止损作为最后防线(保证金维度 -80% = 价格 -8%,10x 杠杆下接近爆仓线但能扛住正常波动)。
stoploss = -0.80
trailing_stop = False
use_custom_stoploss = True
timeframe = "15m"
can_short = False
# 预热 K 线数量:覆盖长均线与通道计算窗口,避免初期信号失真。
startup_candle_count = 600
# --- 2) 可优化参数(默认值已填入优化结果) ---
# 上轨窗口:越大越平滑,越小越敏感。
up_line_span = IntParameter(100, 400, default=340, space="buy", optimize=True)
# 下轨窗口:用于退出通道底边计算。
buy_stop_profit_span = IntParameter(50, 200, default=141, space="buy", optimize=True)
# 长均线天数(会换算成 15m 周期)。
ma_span_long_days = IntParameter(1, 5, default=2, space="buy", optimize=True)
# 动量阈值:过滤弱趋势。
adx_threshold = IntParameter(15, 40, default=28, space="buy", optimize=True)
# 上轨波动率偏移:ATR * offset。
up_line_offset = DecimalParameter(-0.2, 0.4, default=-0.18, decimals=2, space="buy", optimize=True)
# 下轨波动率偏移:ATR * offset,用于构建动态退出线。
buy_stop_profit_offset = DecimalParameter(-0.2, 0.2, default=0.19, decimals=2, space="sell", optimize=True)
def populate_indicators(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
"""
计算策略使用的全部指标。
指标列表:
- n_value: ATR(10),用于描述近期真实波动率;
- ma_long: 长周期均线(天数 * 96 根 15m K);
- up_line: 历史高点通道上轨 + ATR 偏移;
- bottom_line: 历史低点通道下轨;
- adx: ADX(14) 动量强度指标。
"""
dataframe["n_value"] = ta.ATR(dataframe, timeperiod=10)
ma_length = self.ma_span_long_days.value * 96
dataframe["ma_long"] = ta.SMA(dataframe, timeperiod=ma_length)
base_up_line = dataframe["high"].rolling(window=self.up_line_span.value).max().shift(1)
dataframe["up_line"] = base_up_line + (dataframe["n_value"] * self.up_line_offset.value)
dataframe["bottom_line"] = dataframe["low"].rolling(window=self.buy_stop_profit_span.value).min().shift(1)
dataframe["adx"] = ta.ADX(dataframe, timeperiod=14)
return dataframe
def populate_entry_trend(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
"""
入场逻辑(做多):
- 指标有效(ATR、上轨非空);
- 收盘价在长均线上方(趋势过滤);
- ADX 高于阈值(动量过滤);
- 收盘价突破动态上轨(突破确认)。
"""
conditions = []
conditions.append(dataframe["n_value"].notnull())
conditions.append(dataframe["up_line"].notnull())
conditions.append(dataframe["close"] > dataframe["ma_long"])
conditions.append(dataframe["adx"] > self.adx_threshold.value)
conditions.append(dataframe["close"] > dataframe["up_line"])
if conditions:
is_entry = reduce(lambda x, y: x & y, conditions)
dataframe.loc[is_entry, "enter_long"] = 1
dataframe.loc[is_entry, "enter_tag"] = "trend_breakout"
return dataframe
def populate_exit_trend(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
"""
出场逻辑:
- 构建动态退出线:bottom_line + ATR * buy_stop_profit_offset
- 收盘价跌破退出线时触发平仓信号。
"""
offset = self.buy_stop_profit_offset.value
exit_line = dataframe["bottom_line"] + (dataframe["n_value"] * offset)
exit_condition = dataframe["close"] < exit_line
dataframe.loc[exit_condition, "exit_long"] = 1
dataframe.loc[exit_condition, "exit_tag"] = "channel_exit"
return dataframe
def leverage(self, pair: str, current_time: datetime, current_rate: float,
proposed_leverage: float, max_leverage: float, entry_tag: str, side: str,
**kwargs) -> float:
"""
统一固定 10x 杠杆。
"""
return 10.0
def custom_stoploss(self, pair: str, trade: Trade, current_time: datetime,
current_rate: float, current_profit: float, **kwargs) -> float:
"""
分段动态止损(所有阈值通过 trade.leverage 动态联动杠杆):
- 盈利 > 价格+30%: 允许 10% 价格回撤;
- 盈利 > 价格+15%: 允许 10% 价格回撤;
- 盈利 > 价格+5%: 将止损上移到保本上方约 5%(覆盖手续费与滑点);
- 其余阶段: 交由全局硬止损处理。
"""
L = trade.leverage
if current_profit > 0.30 * L:
return 0.10 * L
if current_profit > 0.15 * L:
return 0.10 * L
if current_profit > 0.05 * L:
breakeven_target = trade.open_rate * 1.05
return (current_rate - breakeven_target) / current_rate * L
return L
def confirm_trade_entry(self, pair: str, order_type: str, amount: float, rate: float,
time_in_force: str, current_time: datetime, entry_tag: str,
side: str, **kwargs) -> bool:
"""
入场二次确认(防追高与防假突破):
- 取触发信号的已收盘 K 线 (iloc[-2]) 作为基准;
- 实时下单价不能低穿信号 K 线的均线和上轨(防假突破被瞬间砸回);
- 下单价较信号 K 线收盘价高出 0.5% 以上,放弃交易(防滑点追高)。
"""
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
# 确保数据量足够回溯
if len(dataframe) < 3:
return False
# --- 1. 动态寻找真正的"信号 K 线" ---
# 解决 Freqtrade 实盘中 DataFrame 最后一根 K 线可能是正在运行的新 K 线,
# 也可能是刚刚收盘的信号 K 线的"索引漂移"问题。
signal_candle = None
# 倒序检查最后 3 根 K 线,定位打上 enter_long=1 标签的那一根
for i in range(-1, -4, -1):
if dataframe['enter_long'].iloc[i] == 1:
signal_candle = dataframe.iloc[i]
break
# 如果最近几根都没信号(比如极端网络延迟造成的陈旧发单),果断放弃交易
if signal_candle is None:
return False
# --- 2. 核心校验:必须与信号当期的指标进行对比 ---
# 解决"突破极值瞬间跳升"导致订单被错杀的问题
# 防假突破被瞬间砸回:实时下单价 (rate) 不能低穿【信号发生时】的均线和上轨
if rate <= signal_candle["ma_long"]:
return False
if rate <= signal_candle["up_line"]:
return False
# 防滑点追高:实时下单价 (rate) 较【信号发生时】的收盘价不能偏离过高
# 注意:此处允许 1% 的追高滑点,如果在 15m 级别觉得 1% 的滑点成本太大,可以改为 1.005 (0.5%)
if rate > signal_candle["close"] * 1.01:
return False
return True