feat(config, market_scanner, position_manager, strategy): 引入市场节奏自动识别与流动性检查功能

在 `config.py` 中新增市场节奏自动识别配置,支持低波动期参数切换。更新 `market_scanner.py` 以根据市场波动情况动态调整策略,并在扫描时计算中位数以判断市场状态。同时,在 `position_manager.py` 中实现时间止损逻辑,确保在低波动期内有效管理持仓。新增流动性检查功能于 `strategy.py`,在开仓前评估市场深度与价差,提升交易决策的准确性与风险控制能力。
This commit is contained in:
薇薇安 2026-02-17 10:41:47 +08:00
parent 42480ef886
commit 48c3f946cc
8 changed files with 350 additions and 882 deletions

View File

@ -0,0 +1,100 @@
# 持仓与成交量低迷期优化分析
基于 `持仓记录_2026-02-17T02-22-51.json` 与「昨天到今天稳定小亏损、成交量较低」的反馈,做原因归纳和优化方案;并对照你已有的币安接口文档,标出能直接帮助的接口。
---
## 一、当前持仓快照摘要2026-02-17
| 项目 | 数值 |
|------|------|
| 持仓数 | 9 |
| 多单 / 空单 | 2 / 7偏空 |
| 总浮盈(USDT) | 约 +0.75(该快照) |
| 浮盈笔数 / 浮亏笔数 | 5 / 4 |
| 浮亏标的 | FILUSDT, XLMUSDT, HUSDT, WLDUSDT |
说明:若「昨天到今天」整体是稳定小亏损,多半是**已平仓单**的净亏损或**持仓从浮盈回吐**;成交量低会放大滑点、费率占比和假突破,容易加剧小亏。
---
## 二、成交量偏低时「稳定小亏」的常见原因
1. **滑点与冲击成本**
成交量小 → 盘口薄,市价/条件单成交价差大,开平仓都被「多砍一点」,积少成多。
2. **资金费率占比变高**
持仓过夜/过结算,费率不变但单笔盈利变小,净收益容易被费率吃掉甚至变负。
3. **假突破增多**
波动主要来自少量大单,技术信号(突破、金叉等)更容易假突破,开仓胜率下降。
4. **止盈难触发、止损先到**
波动不足时价格磨蹭,止盈距离难达到,反而先触发止损或长时间横盘后小亏出场。
5. **多空结构不利**
若做多时多头拥挤(费率负、多空比极端),或做空时空头拥挤,结构不利会放大「小亏」。
---
## 三、你已有的币安文档与可落地的优化
下面按「文档 → 能帮上什么」对照,方便你按文档实现或扩展。
| 文档 | 能帮助的优化 |
|------|----------------|
| **行情接口REST.txt** | exchangeInfo规则/合约信息、ticker/深度/K 线:用于**成交量/深度过滤**(如 24h 量、盘口深度)、**流动性检查**;低量标的可直接从扫描候选剔除或降权。 |
| **行情ws接口.txt / ws行情推送.txt** | 实时 ticker、深度、K 线:可做**入场前二次确认**(如信号满足时再查一次深度或最近成交),减少在极薄盘口下单。 |
| **订单交易更新推送.txt** | ORDER_TRADE_UPDATENEW/FILLED/TRADE已有 User Data 时可用于**成交回报、部分成交处理**;结合「条件单触发」可更快更新 DB、减少重复操作。 |
| **条件订单交易更新推送.txt** | 条件单/ALGO 状态:**止损/止盈/跟踪止损**触发后的实时反馈,便于统计「因何平仓」、优化 SL/TP 参数。 |
| **ws交易接口.txt** | WS 下单order.place / algoOrder.place已实现「WS 条件单 + REST 回退」,**减少下单超时**,在弱网或低流动性时更稳。 |
| **用户余额.txt** | 账户余额/可用保证金:用于**按可用保证金动态控仓**,避免在低量、高波动时过度开仓。 |
| **账户信息流连接.txt** | 账户/持仓推送:与现有 User Data 一致,**实时保证金与强平风险**,可做风控与告警。 |
---
## 四、可落地的优化方案(按优先级)
### 1. 成交量/流动性过滤(直接缓解「低量小亏」)
- **扫描阶段**:在现有 `MIN_VOLUME_24H_STRICT` 上,可再设「**最低 24h 成交额**」或「**相对前几日量比**」门槛,低量币不进 TOP_N。
- **开仓前**:用 **行情接口REST** 的深度(如 `GET /fapi/v1/depth`)或 24h ticker对当前 symbol 做一次**流动性检查**(例如买一卖一价差、前几档挂单量),价差过大或挂单过薄则跳过或减小仓位。
- **文档**`行情接口REST.txt` 中的 ticker、depth、K 线即可支持上述逻辑。
### 2. 资金费率与多空结构(减少「结构不利」导致的磨损)
- **开仓前**:已实现的「资金费率过滤」继续保留;可适当**收紧阈值**(如做多时 `lastFundingRate > 0.0005` 就跳过),在低波动期减少费率侵蚀。
- **扫描阶段**:已实现的「扫描阶段资金费率过滤」可保持或略加强(如 `SCAN_FUNDING_RATE_MAX_ABS` 从 0.001 降到 0.0008),避免把「费率极端」的币选进候选。
- 若有**大户多空比 / taker 买卖比**接口(在行情或衍生文档中),可作为**排序或过滤**:与开仓方向一致则优先,极端反向则跳过或降权。
### 3. 出场优化(止盈难触发、亏损单拿太久)
- **跟踪止损**:文档与策略建议里已多次提到;在浮盈达到 X% 后改为 `TRAILING_STOP_MARKET`**锁定部分利润**,避免回吐成小亏。
- **时间/无盈利止损**:持仓超过 N 小时且浮盈 < 某阈值(或浮亏)→ 市价平仓或收紧止损,减少在低波动里「耗着」造成的资金占用和小亏。
- **条件单推送**:结合「条件订单交易更新推送」统计**止损/止盈/跟踪止损**的触发比例,用于调 SL/TP 距离和跟踪止损参数。
### 4. 开仓节奏与仓位(低量期少开、小开)
- **降低开仓频率**:低量日可适当增大 `SCAN_INTERVAL` 或提高 `MIN_SIGNAL_STRENGTH`,减少「为做而做」的次优单。
- **单笔仓位**:在配置里略降 `MAX_POSITION_PERCENT` 或固定风险比例,**单笔亏损上限变小**,整体回撤更可控。
- **余额与风控**:用「用户余额」或账户信息流,**按可用保证金**动态限制总敞口,避免在波动放大时超额开仓。
### 5. 监控与统计(用现有接口即可)
- **按平仓时间统计**:已实现「按平仓时间」筛选与统计,可看**每日/每周「平仓笔数、平仓盈亏」**,区分「开仓日」与「平仓日」表现。
- **按标的/按方向**:统计哪些 symbol、多/空在低量期亏损集中,用于**黑名单或降权**(例如某几类币在低量期一律不开或只做一侧)。
---
## 五、小结与建议顺序
- **可能原因**:成交量低 → 滑点大、费率占比高、假突破多、止盈难触发而止损/横盘小亏多;若再叠加多空结构不利,会放大「稳定小亏」。
- **文档利用**:你已有的行情 REST/WS、订单与条件单推送、WS 交易、用户余额与账户流,**足够**支撑:流动性过滤、资金费率/多空过滤、跟踪止损与时间止损、按保证金控仓、以及统计与监控。
- **建议实施顺序**
1. 加强**成交量/深度过滤**(扫描 + 开仓前检查);
2. 略**收紧资金费率**阈值、保持或略加强扫描阶段费率过滤;
3. 上**跟踪止损**与**时间/无盈利止损**
4. 低量期**降频、降单笔仓位**,并用余额/账户流做风控;
5. 用**按平仓时间统计**与条件单推送,持续观察「谁在亏、因何平仓」,再微调标的与参数。
如需,我可以按上述某一条(例如「开仓前深度检查」或「时间止损参数」)写出具体实现步骤或伪代码,直接对接到你现有 `market_scanner` / `strategy` / `position_manager`

View File

@ -242,6 +242,19 @@ DEFAULT_TRADING_CONFIG = {
# 扫描阶段资金费率过滤:排除 |lastFundingRate| 过大的标的,避免进入 TOP_N
'SCAN_FUNDING_RATE_FILTER_ENABLED': True,
'SCAN_FUNDING_RATE_MAX_ABS': 0.001, # 绝对值超过 0.1% 则从扫描候选剔除
# ===== 市场节奏自动识别(低波动期 vs 正常期,自动切换参数,无需手动)=====
'MARKET_REGIME_AUTO': True, # 是否根据波动率自动识别并切换低波动期参数
'LOW_VOLATILITY_THRESHOLD': 2.5, # 24h |changePercent| 中位数低于此值判为低波动期(%
'LOW_VOLATILITY_MAX_POSITION_PERCENT': 0.15, # 低波动期单币最大仓位(正常期用 MAX_POSITION_PERCENT
'LOW_VOLATILITY_MIN_SIGNAL_STRENGTH': 9, # 低波动期信号强度门槛(更严)
'LOW_VOLATILITY_SCAN_FUNDING_RATE_MAX_ABS': 0.0005, # 低波动期扫描阶段资金费率更严0.05%
'TIME_STOP_MAX_HOLD_HOURS': 8, # 持仓超过 N 小时且未达最小盈利则考虑平仓(低波动期更适用)
'TIME_STOP_MIN_PNL_PCT_TO_HOLD': 0.0, # 持仓超过时间阈值时,若 pnl% 低于此值则平仓0=允许小亏即走)
'TIME_STOP_ENABLED': True, # 是否启用时间/无盈利止损(可与 regime 结合:仅低波动期或始终启用)
# 开仓前流动性检查(价差/深度):低量期可减少滑点与冲击成本
'LIQUIDITY_CHECK_BEFORE_ENTRY': False, # 默认关闭;开启后开仓前检查盘口价差与深度,不通过则跳过
'LIQUIDITY_MAX_SPREAD_PCT': 0.005, # 买一卖一价差超过此比例0.5%)则跳过
'LIQUIDITY_MIN_DEPTH_USDT': 30000, # 前 5 档买卖深度合计名义价值低于此值USDT则跳过
# 主动买卖量过滤(可选):与方向一致时通过,极端反向时跳过
'TAKER_RATIO_FILTER_ENABLED': False, # 默认关闭,开启后做多要求 buySellRatio≥下限、做空要求≤上限
'MIN_TAKER_BUY_RATIO_FOR_LONG': 0.85, # 做多时最近1h buySellRatio 低于此值则跳过(主动买不足)
@ -369,6 +382,20 @@ for key, value in DEFAULT_TRADING_CONFIG.items():
if key not in TRADING_CONFIG:
TRADING_CONFIG[key] = value
def get_effective_config(key: str, default=None):
"""
按当前市场节奏返回有效配置 MARKET_REGIME_AUTO 且为低波动期
则返回 LOW_VOLATILITY_<key>若存在否则返回 TRADING_CONFIG[key]
用于仓位信号门槛资金费率阈值时间止损等实现自动把握市场节奏
"""
try:
from . import market_regime
return market_regime.get_effective_config(key, default)
except ImportError:
return TRADING_CONFIG.get(key, default)
# 提供一个函数来重新加载配置
def reload_config():
"""重新加载配置(供外部调用)"""

View File

@ -0,0 +1,122 @@
"""
市场节奏自动识别根据当前波动率/成交量判断低波动期正常期
并自动切换参数仓位信号门槛资金费率阈值时间止损等无需手动切换
"""
import logging
import time
from typing import Optional, Any
logger = logging.getLogger(__name__)
REDIS_KEY_REGIME = "market_regime"
REDIS_KEY_UPDATED_AT = "market_regime_updated_at"
REGIME_LOW = "low_volatility"
REGIME_NORMAL = "normal"
TTL_SEC = 3600 # 1 小时内无更新则视为过期,策略侧回退为 normal
def _get_redis():
"""获取 Redis 客户端(与 binance_client 一致)。"""
try:
from . import config
from .redis_cache import RedisCache
rc = RedisCache(
redis_url=getattr(config, "REDIS_URL", "redis://localhost:6379"),
use_tls=getattr(config, "REDIS_USE_TLS", False),
ssl_cert_reqs=getattr(config, "REDIS_SSL_CERT_REQS", "required"),
ssl_ca_certs=getattr(config, "REDIS_SSL_CA_CERTS", None),
username=getattr(config, "REDIS_USERNAME", None),
password=getattr(config, "REDIS_PASSWORD", None),
)
return rc
except Exception as e:
logger.debug("market_regime Redis 不可用: %s", e)
return None
async def update_regime_from_scan(
change_percents: list,
redis_cache: Any = None,
low_volatility_threshold: float = 2.5,
) -> str:
"""
根据本次扫描得到的 24h 涨跌幅列表计算中位数绝对波动更新市场节奏并写入 Redis
change_percents: symbol 24h changePercent 列表可含正负
返回当前写入的 regimelow_volatility normal
"""
if not change_percents:
return REGIME_NORMAL
abs_changes = [abs(float(x)) for x in change_percents if x is not None]
if not abs_changes:
return REGIME_NORMAL
abs_changes.sort()
n = len(abs_changes)
median_abs = abs_changes[n // 2] if n % 2 else (abs_changes[n // 2 - 1] + abs_changes[n // 2]) / 2
regime = REGIME_LOW if median_abs < low_volatility_threshold else REGIME_NORMAL
cache = redis_cache or _get_redis()
if cache:
try:
await cache.connect()
await cache.set(REDIS_KEY_REGIME, regime, ttl=TTL_SEC)
await cache.set(REDIS_KEY_UPDATED_AT, str(int(time.time())), ttl=TTL_SEC)
logger.info(f"市场节奏: median_24h_change={median_abs:.2f}% -> {regime} (阈值={low_volatility_threshold}%)")
except Exception as e:
logger.debug("写入 market_regime 失败: %s", e)
return regime
async def get_regime(redis_cache: Any = None) -> str:
"""从 Redis 读取当前市场节奏;无或过期则返回 normal。"""
cache = redis_cache or _get_redis()
if not cache:
return REGIME_NORMAL
try:
await cache.connect()
r = await cache.get(REDIS_KEY_REGIME)
if r in (REGIME_LOW, REGIME_NORMAL):
return r
ts = await cache.get(REDIS_KEY_UPDATED_AT)
if ts and (time.time() - int(ts)) > TTL_SEC:
return REGIME_NORMAL
except Exception as e:
logger.debug("读取 market_regime 失败: %s", e)
return REGIME_NORMAL
def get_effective_config(key: str, default: Any = None, account_id: int = None) -> Any:
"""
根据当前市场节奏返回有效配置若开启自动节奏且当前为低波动期
则优先返回 LOW_VOLATILITY_<key>否则返回 TRADING_CONFIG[key]
用于仓位信号门槛资金费率阈值时间止损等
"""
try:
from . import config
except ImportError:
import config
cfg = getattr(config, "TRADING_CONFIG", None) or {}
auto = cfg.get("MARKET_REGIME_AUTO")
if not auto:
return cfg.get(key, default)
low_key = f"LOW_VOLATILITY_{key}"
if low_key not in cfg:
return cfg.get(key, default)
# 同步读 Redis 会阻塞;这里用缓存避免每次读 Redis。策略层在每轮扫描后已更新 regime本进程内可用内存缓存
regime = _cached_regime
if regime == REGIME_LOW:
val = cfg.get(low_key)
if val is not None:
return val
return cfg.get(key, default)
# 进程内缓存:由扫描器在每次 scan 结束后异步更新get_effective_config 同步读
_cached_regime: str = REGIME_NORMAL
def set_cached_regime(regime: str) -> None:
global _cached_regime
_cached_regime = regime if regime in (REGIME_LOW, REGIME_NORMAL) else REGIME_NORMAL
def get_cached_regime() -> str:
return _cached_regime

View File

@ -120,9 +120,9 @@ class MarketScanner:
logger.info(f"初步筛选后,需要详细分析的交易对: {len(pre_filtered_symbols)}")
# 扫描阶段资金费率过滤:排除 |lastFundingRate| 过大的标的(文档建议的后续方向
# 扫描阶段资金费率过滤:排除 |lastFundingRate| 过大的标的;低波动期使用更严阈值(有效配置
scan_funding_enabled = cfg.get('SCAN_FUNDING_RATE_FILTER_ENABLED', False)
scan_funding_max_abs = float(cfg.get('SCAN_FUNDING_RATE_MAX_ABS', 0.001))
scan_funding_max_abs = float(config.get_effective_config('SCAN_FUNDING_RATE_MAX_ABS', 0.001))
if scan_funding_enabled and pre_filtered_symbols:
try:
premium_all = await self.client.get_premium_index(None) # 全量,一次请求
@ -228,6 +228,21 @@ class MarketScanner:
self.top_symbols = top_n
# 市场节奏自动识别:用本次扫描的 24h 涨跌幅中位数判断低波动/正常,写入 Redis 并更新进程内缓存
try:
from . import market_regime
except ImportError:
market_regime = None
if market_regime and getattr(self.client, "redis_cache", None):
# 用过滤后的全部结果计算中位数(样本更多),无则用 top_n
source = filtered_results if filtered_results else top_n
change_percents = [r["changePercent"] for r in source if r.get("changePercent") is not None]
threshold = float(cfg.get("LOW_VOLATILITY_THRESHOLD", config.TRADING_CONFIG.get("LOW_VOLATILITY_THRESHOLD", 2.5)))
regime = await market_regime.update_regime_from_scan(
change_percents, self.client.redis_cache, low_volatility_threshold=threshold
)
market_regime.set_cached_regime(regime)
# ⚠️ 已禁用扫描结果缓存,确保每个账户都使用最新的市场数据
# 虽然中间数据K线、技术指标已经缓存但最终扫描结果不缓存
# 这样可以避免使用过期的交易对,确保每个账户都基于最新市场数据扫描

View File

@ -3835,6 +3835,32 @@ class PositionManager:
except Exception as e:
logger.debug(f"从Redis重新加载配置失败: {e}")
# 时间/无盈利止损:持仓超过 N 小时且盈利未达阈值则平仓(低波动期减少磨单)
time_stop_enabled = config.TRADING_CONFIG.get('TIME_STOP_ENABLED', False)
if time_stop_enabled:
max_hold_hours = float(config.get_effective_config('TIME_STOP_MAX_HOLD_HOURS', 8) or 8)
min_pnl_to_hold = float(config.TRADING_CONFIG.get('TIME_STOP_MIN_PNL_PCT_TO_HOLD', 0.0) or 0.0)
entry_time = position_info.get('entryTime')
hold_hours = 0.0
if entry_time:
try:
if isinstance(entry_time, datetime):
hold_hours = (get_beijing_time() - entry_time).total_seconds() / 3600.0
elif isinstance(entry_time, str):
entry_dt = datetime.strptime(entry_time, '%Y-%m-%d %H:%M:%S')
hold_hours = (get_beijing_time() - entry_dt).total_seconds() / 3600.0
else:
hold_hours = (time.time() - (float(entry_time) if isinstance(entry_time, (int, float)) else 0)) / 3600.0
except Exception as e:
logger.debug(f"{symbol} 解析 entryTime 失败: {e}")
if hold_hours >= max_hold_hours and pnl_percent_margin < min_pnl_to_hold:
logger.info(
f"{symbol} [时间止损] 持仓 {hold_hours:.1f}h >= {max_hold_hours}h 且盈亏 {pnl_percent_margin:.2f}% < {min_pnl_to_hold}%,平仓"
)
if await self.close_position(symbol, reason='time_stop'):
logger.info(f"{symbol} [时间止损] 平仓成功")
return
# ⚠️ 优化:已完全移除时间锁限制
# 理由1) 止损和止盈都应该立即执行,不受时间限制
# 2) 交易所级别的止损/止盈单已提供保护

View File

@ -96,9 +96,10 @@ class RiskManager:
margin_value = notional_value / actual_leverage
# 重要语义POSITION_PERCENT 均按“保证金占用比例”计算(更符合 stop_loss/take_profit 的 margin 逻辑)
max_margin_value = available_balance * config.TRADING_CONFIG['MAX_POSITION_PERCENT']
max_position_pct = config.get_effective_config('MAX_POSITION_PERCENT', 0.20)
max_margin_value = available_balance * max_position_pct
min_margin_value = available_balance * config.TRADING_CONFIG['MIN_POSITION_PERCENT']
max_margin_pct = config.TRADING_CONFIG['MAX_POSITION_PERCENT'] * 100
max_margin_pct = max_position_pct * 100
min_margin_pct = config.TRADING_CONFIG['MIN_POSITION_PERCENT'] * 100
logger.info(f" 数量: {quantity:.4f}")
@ -593,8 +594,8 @@ class RiskManager:
logger.info(f" 名义价值: {notional_value:.2f} USDT")
logger.info(f" 保证金: {margin_value:.4f} USDT ({margin_value/total_balance*100:.2f}%)")
# 检查是否超过最大仓位限制
max_position_percent = config.TRADING_CONFIG['MAX_POSITION_PERCENT']
# 检查是否超过最大仓位限制(低波动期自动降低单笔上限)
max_position_percent = config.get_effective_config('MAX_POSITION_PERCENT', 0.20)
# ⚠️ 如果启用了固定风险模型,且计算出的仓位合理(风险可控),则放宽 MAX_POSITION_PERCENT 限制
# 因为固定风险模型的核心是控制亏损额,而不是仓位大小
@ -640,8 +641,9 @@ class RiskManager:
logger.info(f" ✓ 信号强度{signal_strength}使用100%仓位(高质量信号)")
# 根据涨跌幅调整仓位大小(涨跌幅越大,保证金占比可以适当增加)
base_position_percent = config.TRADING_CONFIG['MAX_POSITION_PERCENT'] * signal_multiplier
max_position_percent = config.TRADING_CONFIG['MAX_POSITION_PERCENT'] * signal_multiplier
effective_max = config.get_effective_config('MAX_POSITION_PERCENT', 0.20)
base_position_percent = effective_max * signal_multiplier
max_position_percent = effective_max * signal_multiplier
min_position_percent = config.TRADING_CONFIG['MIN_POSITION_PERCENT']
# 涨跌幅超过5%时,可以适当增加保证金占比,但必须遵守 MAX_POSITION_PERCENT 上限
@ -717,7 +719,7 @@ class RiskManager:
max_position_percent = 0.95
max_margin_value = available_balance * 0.95
else:
max_position_percent = config.TRADING_CONFIG['MAX_POSITION_PERCENT']
max_position_percent = config.get_effective_config('MAX_POSITION_PERCENT', 0.20)
max_margin_value = available_balance * max_position_percent
if min_margin_usdt <= max_margin_value:
@ -761,7 +763,7 @@ class RiskManager:
quantity = quantity * position_scale
final_notional_value = quantity * current_price
final_margin = final_notional_value / actual_leverage if actual_leverage > 0 else final_notional_value
max_margin_cap = available_balance * config.TRADING_CONFIG.get('MAX_POSITION_PERCENT', 0.08)
max_margin_cap = available_balance * config.get_effective_config('MAX_POSITION_PERCENT', 0.20)
if final_margin > max_margin_cap:
final_margin = max_margin_cap
final_notional_value = final_margin * actual_leverage

View File

@ -196,6 +196,10 @@ class TradingStrategy:
if not await self._check_taker_ratio_filter(symbol, trade_direction):
logger.info(f"{symbol} 主动买卖量过滤未通过,跳过开仓")
continue
# 开仓前流动性检查(可选):价差/深度不达标则跳过,低量期减少滑点
if not await self._check_liquidity_before_entry(symbol, symbol_info.get('price')):
logger.info(f"{symbol} 流动性检查未通过,跳过开仓")
continue
entry_reason = trade_signal['reason']
signal_strength = trade_signal.get('strength', 0)
@ -430,6 +434,48 @@ class TradingStrategy:
logger.debug(f"{symbol} 主动买卖量检查失败(放行): {e}")
return True
async def _check_liquidity_before_entry(self, symbol: str, current_price: Optional[float] = None) -> bool:
"""
开仓前流动性检查盘口价差过大或深度过薄则跳过减少低量期滑点与冲击成本
依赖 get_depth(symbol, limit=10)检查买一卖一价差与前 5 档深度USDT
"""
enabled = bool(config.TRADING_CONFIG.get('LIQUIDITY_CHECK_BEFORE_ENTRY', False))
if not enabled:
return True
try:
depth = await self.client.get_depth(symbol, limit=10)
if not depth or not isinstance(depth, dict):
return True
bids = depth.get('bids') or []
asks = depth.get('asks') or []
if not bids or not asks:
logger.info(f"{symbol} 流动性检查:深度为空,跳过开仓")
return False
bid1_p = float(bids[0][0])
ask1_p = float(asks[0][0])
mid = (bid1_p + ask1_p) / 2.0
if mid <= 0:
return True
spread_pct = (ask1_p - bid1_p) / mid
max_spread = float(config.TRADING_CONFIG.get('LIQUIDITY_MAX_SPREAD_PCT', 0.005))
if spread_pct > max_spread:
logger.info(f"{symbol} 流动性检查:价差 {spread_pct*100:.3f}% > {max_spread*100:.2f}%,跳过开仓")
return False
# 前 5 档深度名义价值USDT
depth_usdt = 0.0
for i, (p, q) in enumerate(bids[:5]):
depth_usdt += float(p) * float(q)
for i, (p, q) in enumerate(asks[:5]):
depth_usdt += float(p) * float(q)
min_depth = float(config.TRADING_CONFIG.get('LIQUIDITY_MIN_DEPTH_USDT', 30000))
if depth_usdt < min_depth:
logger.info(f"{symbol} 流动性检查前5档深度 {depth_usdt:.0f} USDT < {min_depth:.0f},跳过开仓")
return False
return True
except Exception as e:
logger.debug(f"{symbol} 流动性检查失败(放行): {e}")
return True
async def _check_volume_confirmation(self, symbol_info: Dict) -> bool:
"""
成交量确认 - 确保有足够的成交量支撑
@ -595,8 +641,8 @@ class TradingStrategy:
signal_strength = 0
reasons.append("❌ 逆4H趋势拒绝交易")
# 判断是否应该交易(信号强度 >= MIN_SIGNAL_STRENGTH 才交易,提高胜率
min_signal_strength = config.TRADING_CONFIG.get('MIN_SIGNAL_STRENGTH', 7)
# 判断是否应该交易(信号强度 >= 有效 MIN_SIGNAL_STRENGTH 才交易;低波动期自动提高门槛
min_signal_strength = config.get_effective_config('MIN_SIGNAL_STRENGTH', 7)
# 强度上限归一到 0-10避免出现 12/10 这种误导显示
try:
signal_strength = max(0, min(int(signal_strength), 10))

View File

@ -1,870 +0,0 @@
[
{
"id": 5110,
"symbol": "1000BONKUSDT",
"side": "BUY",
"quantity": 3531,
"entry_price": 0.006565,
"entry_value_usdt": 23.181015,
"notional_usdt": 23.459964,
"margin_usdt": 5.864991,
"original_notional_usdt": 23.181015,
"original_margin_usdt": 5.79525375,
"mark_price": 0.006644,
"pnl": 0.278949,
"pnl_percent": 4.7561709813365445,
"leverage": 4,
"entry_time": 1771214454,
"stop_loss_price": 0.00636805,
"take_profit_price": 0.00697531,
"take_profit_1": null,
"take_profit_2": null,
"atr": null,
"entry_order_id": null,
"entry_order_type": null,
"open_orders": [
{
"orderId": 2000000460584754,
"type": "TAKE_PROFIT_MARKET",
"side": "SELL",
"stopPrice": 0.006975,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460584735,
"type": "STOP_MARKET",
"side": "SELL",
"stopPrice": 0.006369,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
],
"active_sl_orders": "STOP_MARKET @ 0.006369 (NEW)",
"active_tp_orders": "TAKE_PROFIT_MARKET @ 0.006975 (NEW)",
"binance_open_orders_raw": [
{
"orderId": 2000000460584754,
"type": "TAKE_PROFIT_MARKET",
"side": "SELL",
"stopPrice": 0.006975,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460584735,
"type": "STOP_MARKET",
"side": "SELL",
"stopPrice": 0.006369,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
]
},
{
"id": 5157,
"symbol": "ZECUSDT",
"side": "SELL",
"quantity": 0.077,
"entry_price": 284.54,
"entry_value_usdt": 21.909580000000002,
"notional_usdt": 22.23683,
"margin_usdt": 5.5592075,
"original_notional_usdt": 21.92881912,
"original_margin_usdt": 5.48220478,
"mark_price": 288.79,
"pnl": -0.32725,
"pnl_percent": -5.886630423491117,
"leverage": 4,
"entry_time": 1771226616,
"stop_loss_price": null,
"take_profit_price": null,
"take_profit_1": null,
"take_profit_2": null,
"atr": 14.62428571,
"entry_order_id": 797717260491,
"entry_order_type": "LIMIT",
"open_orders": [
{
"orderId": 2000000460584806,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 266.76,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460584795,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 293.07,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
],
"active_sl_orders": "STOP_MARKET @ 293.07 (NEW)",
"active_tp_orders": "TAKE_PROFIT_MARKET @ 266.76 (NEW)",
"binance_open_orders_raw": [
{
"orderId": 2000000460584806,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 266.76,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460584795,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 293.07,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
]
},
{
"id": 5109,
"symbol": "HYPEUSDT",
"side": "SELL",
"quantity": 0.7,
"entry_price": 30.158,
"entry_value_usdt": 21.110599999999998,
"notional_usdt": 20.984715002999998,
"margin_usdt": 5.2461787507499995,
"original_notional_usdt": 21.1106,
"original_margin_usdt": 5.27765,
"mark_price": 29.97816429,
"pnl": 0.12588499,
"pnl_percent": 2.3995558668679244,
"leverage": 4,
"entry_time": 1771214453,
"stop_loss_price": null,
"take_profit_price": null,
"take_profit_1": null,
"take_profit_2": null,
"atr": null,
"entry_order_id": 5837357832,
"entry_order_type": "LIMIT",
"open_orders": [
{
"orderId": 2000000460584837,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 28.274,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460584833,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 31.062,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
],
"active_sl_orders": "STOP_MARKET @ 31.062 (NEW)",
"active_tp_orders": "TAKE_PROFIT_MARKET @ 28.274 (NEW)",
"binance_open_orders_raw": [
{
"orderId": 2000000460584837,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 28.274,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460584833,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 31.062,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
]
},
{
"id": 5112,
"symbol": "FILUSDT",
"side": "SELL",
"quantity": 22,
"entry_price": 0.963,
"entry_value_usdt": 21.186,
"notional_usdt": 21.37234946,
"margin_usdt": 5.343087365,
"original_notional_usdt": 21.186,
"original_margin_usdt": 5.2965,
"mark_price": 0.97147043,
"pnl": -0.18634946,
"pnl_percent": -3.4876738348073033,
"leverage": 4,
"entry_time": 1771214455,
"stop_loss_price": 0.99189,
"take_profit_price": 0.9028125,
"take_profit_1": null,
"take_profit_2": null,
"atr": null,
"entry_order_id": null,
"entry_order_type": null,
"open_orders": [
{
"orderId": 2000000460584866,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 0.903,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460584857,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 0.991,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
],
"active_sl_orders": "STOP_MARKET @ 0.991 (NEW)",
"active_tp_orders": "TAKE_PROFIT_MARKET @ 0.903 (NEW)",
"binance_open_orders_raw": [
{
"orderId": 2000000460584866,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 0.903,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460584857,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 0.991,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
]
},
{
"id": 5113,
"symbol": "TAKEUSDT",
"side": "SELL",
"quantity": 172,
"entry_price": 0.03629,
"entry_value_usdt": 6.24188,
"notional_usdt": 5.387599,
"margin_usdt": 5.387599,
"original_notional_usdt": 6.24188,
"original_margin_usdt": 6.24188,
"mark_price": 0.03132325,
"pnl": 0.854281,
"pnl_percent": 15.856432522168037,
"leverage": 1,
"entry_time": 1771214456,
"stop_loss_price": 0.0373787,
"take_profit_price": 0.0272175,
"take_profit_1": null,
"take_profit_2": null,
"atr": null,
"entry_order_id": null,
"entry_order_type": null,
"open_orders": [
{
"orderId": 2000000460584904,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 0.02722,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460584895,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 0.03737,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
],
"active_sl_orders": "STOP_MARKET @ 0.03737 (NEW)",
"active_tp_orders": "TAKE_PROFIT_MARKET @ 0.02722 (NEW)",
"binance_open_orders_raw": [
{
"orderId": 2000000460584904,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 0.02722,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460584895,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 0.03737,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
]
},
{
"id": 5135,
"symbol": "ZROUSDT",
"side": "SELL",
"quantity": 13.5,
"entry_price": 1.6807,
"entry_value_usdt": 22.68945,
"notional_usdt": 22.76581086,
"margin_usdt": 5.691452715,
"original_notional_usdt": 22.68945,
"original_margin_usdt": 5.6723625,
"mark_price": 1.68635636,
"pnl": -0.07636086,
"pnl_percent": -1.3416760855932017,
"leverage": 4,
"entry_time": 1771223082,
"stop_loss_price": 1.731121,
"take_profit_price": 1.57565625,
"take_profit_1": 1.57565625,
"take_profit_2": 1.49288286,
"atr": 0.07825714,
"entry_order_id": 6021914660,
"entry_order_type": "LIMIT",
"open_orders": [
{
"orderId": 2000000460584948,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 1.4929,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460584947,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 1.7311,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
],
"active_sl_orders": "STOP_MARKET @ 1.7311 (NEW)",
"active_tp_orders": "TAKE_PROFIT_MARKET @ 1.4929 (NEW)",
"binance_open_orders_raw": [
{
"orderId": 2000000460584948,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 1.4929,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460584947,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 1.7311,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
]
},
{
"id": 5115,
"symbol": "AXSUSDT",
"side": "SELL",
"quantity": 18,
"entry_price": 1.388,
"entry_value_usdt": 24.983999999999998,
"notional_usdt": 24.42318858,
"margin_usdt": 6.105797145,
"original_notional_usdt": 24.984,
"original_margin_usdt": 6.246,
"mark_price": 1.35684381,
"pnl": 0.56081142,
"pnl_percent": 9.184900950390155,
"leverage": 4,
"entry_time": 1771214457,
"stop_loss_price": 1.42964,
"take_profit_price": 1.30125,
"take_profit_1": null,
"take_profit_2": null,
"atr": null,
"entry_order_id": null,
"entry_order_type": null,
"open_orders": [
{
"orderId": 2000000460584986,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 1.302,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460584975,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 1.429,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
],
"active_sl_orders": "STOP_MARKET @ 1.429 (NEW)",
"active_tp_orders": "TAKE_PROFIT_MARKET @ 1.302 (NEW)",
"binance_open_orders_raw": [
{
"orderId": 2000000460584986,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 1.302,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460584975,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 1.429,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
]
},
{
"id": 5137,
"symbol": "XLMUSDT",
"side": "SELL",
"quantity": 127,
"entry_price": 0.16858,
"entry_value_usdt": 21.409660000000002,
"notional_usdt": 21.68884283,
"margin_usdt": 5.4222107075,
"original_notional_usdt": 21.40966,
"original_margin_usdt": 5.352415,
"mark_price": 0.17077829,
"pnl": -0.27918283,
"pnl_percent": -5.1488746022694105,
"leverage": 4,
"entry_time": 1771223321,
"stop_loss_price": 0.1736374,
"take_profit_price": 0.15804375,
"take_profit_1": 0.15804375,
"take_profit_2": 0.15550343,
"atr": 0.00544857,
"entry_order_id": 20994894391,
"entry_order_type": "LIMIT",
"open_orders": [
{
"orderId": 2000000460585021,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 0.15551,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460585020,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 0.17363,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
],
"active_sl_orders": "STOP_MARKET @ 0.17363 (NEW)",
"active_tp_orders": "TAKE_PROFIT_MARKET @ 0.15551 (NEW)",
"binance_open_orders_raw": [
{
"orderId": 2000000460585021,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 0.15551,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460585020,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 0.17363,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
]
},
{
"id": 5116,
"symbol": "DASHUSDT",
"side": "SELL",
"quantity": 0.571,
"entry_price": 37.25,
"entry_value_usdt": 21.26975,
"notional_usdt": 21.304009999999998,
"margin_usdt": 5.3260024999999995,
"original_notional_usdt": 21.26975,
"original_margin_usdt": 5.3174375,
"mark_price": 37.31,
"pnl": -0.03426,
"pnl_percent": -0.6432591798445457,
"leverage": 4,
"entry_time": 1771214458,
"stop_loss_price": 38.3675,
"take_profit_price": 34.921875,
"take_profit_1": null,
"take_profit_2": null,
"atr": null,
"entry_order_id": null,
"entry_order_type": null,
"open_orders": [
{
"orderId": 2000000460585100,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 34.93,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460585093,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 38.36,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
],
"active_sl_orders": "STOP_MARKET @ 38.36 (NEW)",
"active_tp_orders": "TAKE_PROFIT_MARKET @ 34.93 (NEW)",
"binance_open_orders_raw": [
{
"orderId": 2000000460585100,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 34.93,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460585093,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 38.36,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
]
},
{
"id": 5117,
"symbol": "USELESSUSDT",
"side": "BUY",
"quantity": 150,
"entry_price": 0.04083,
"entry_value_usdt": 6.124499999999999,
"notional_usdt": 7.085999999999999,
"margin_usdt": 7.085999999999999,
"original_notional_usdt": 6.1245,
"original_margin_usdt": 6.1245,
"mark_price": 0.04724,
"pnl": 0.9615,
"pnl_percent": 13.56900931414056,
"leverage": 1,
"entry_time": 1771214459,
"stop_loss_price": 0.0396051,
"take_profit_price": 0.0510375,
"take_profit_1": null,
"take_profit_2": null,
"atr": null,
"entry_order_id": null,
"entry_order_type": null,
"open_orders": [
{
"orderId": 2000000460585145,
"type": "TAKE_PROFIT_MARKET",
"side": "SELL",
"stopPrice": 0.05103,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460585138,
"type": "STOP_MARKET",
"side": "SELL",
"stopPrice": 0.03961,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
],
"active_sl_orders": "STOP_MARKET @ 0.03961 (NEW)",
"active_tp_orders": "TAKE_PROFIT_MARKET @ 0.05103 (NEW)",
"binance_open_orders_raw": [
{
"orderId": 2000000460585145,
"type": "TAKE_PROFIT_MARKET",
"side": "SELL",
"stopPrice": 0.05103,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460585138,
"type": "STOP_MARKET",
"side": "SELL",
"stopPrice": 0.03961,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
]
},
{
"id": 5118,
"symbol": "ENAUSDT",
"side": "SELL",
"quantity": 194,
"entry_price": 0.1196,
"entry_value_usdt": 23.2024,
"notional_usdt": 23.53230864,
"margin_usdt": 5.88307716,
"original_notional_usdt": 23.2024,
"original_margin_usdt": 5.8006,
"mark_price": 0.12130056,
"pnl": -0.32990864,
"pnl_percent": -5.607756468725288,
"leverage": 4,
"entry_time": 1771214460,
"stop_loss_price": 0.123188,
"take_profit_price": 0.112125,
"take_profit_1": null,
"take_profit_2": null,
"atr": null,
"entry_order_id": null,
"entry_order_type": null,
"open_orders": [
{
"orderId": 2000000460585199,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 0.1122,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460585168,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 0.1231,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
],
"active_sl_orders": "STOP_MARKET @ 0.1231 (NEW)",
"active_tp_orders": "TAKE_PROFIT_MARKET @ 0.1122 (NEW)",
"binance_open_orders_raw": [
{
"orderId": 2000000460585199,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 0.1122,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460585168,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 0.1231,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
]
},
{
"id": 5151,
"symbol": "WLFIUSDT",
"side": "SELL",
"quantity": 219,
"entry_price": 0.1011,
"entry_value_usdt": 22.1409,
"notional_usdt": 22.23684171,
"margin_usdt": 5.5592104275,
"original_notional_usdt": 22.1409,
"original_margin_usdt": 22.1409,
"mark_price": 0.10153809,
"pnl": -0.09594171,
"pnl_percent": -1.7258154058245532,
"leverage": 4,
"entry_time": 1771226264,
"stop_loss_price": null,
"take_profit_price": null,
"take_profit_1": null,
"take_profit_2": null,
"atr": null,
"entry_order_id": 2846730648,
"entry_order_type": "LIMIT",
"open_orders": [],
"active_sl_orders": "",
"active_tp_orders": "",
"binance_open_orders_raw": []
},
{
"id": 5123,
"symbol": "WLDUSDT",
"side": "SELL",
"quantity": 56,
"entry_price": 0.4028,
"entry_value_usdt": 22.5568,
"notional_usdt": 22.65973696,
"margin_usdt": 5.66493424,
"original_notional_usdt": 22.5568,
"original_margin_usdt": 5.6392,
"mark_price": 0.40463816,
"pnl": -0.10293696,
"pnl_percent": -1.8170901133002384,
"leverage": 4,
"entry_time": 1771214479,
"stop_loss_price": 0.414884,
"take_profit_price": 0.377625,
"take_profit_1": null,
"take_profit_2": null,
"atr": null,
"entry_order_id": null,
"entry_order_type": null,
"open_orders": [
{
"orderId": 2000000460523250,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 0.3777,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460523242,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 0.4148,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
],
"active_sl_orders": "STOP_MARKET @ 0.4148 (NEW)",
"active_tp_orders": "TAKE_PROFIT_MARKET @ 0.3777 (NEW)",
"binance_open_orders_raw": [
{
"orderId": 2000000460523250,
"type": "TAKE_PROFIT_MARKET",
"side": "BUY",
"stopPrice": 0.3777,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
},
{
"orderId": 2000000460523242,
"type": "STOP_MARKET",
"side": "BUY",
"stopPrice": 0.4148,
"price": 0,
"origType": "CONDITIONAL",
"reduceOnly": true,
"status": "NEW"
}
]
}
]