From 77887be4fb0352a7f36fedc0441bd4f971fa892d Mon Sep 17 00:00:00 2001 From: yhydev Date: Mon, 2 Feb 2026 02:31:21 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=A7=E4=BB=93=E4=BD=8D=E5=B9=B3=E4=BB=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- position_closer.py | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/position_closer.py b/position_closer.py index 6faa7ec..16c79a6 100644 --- a/position_closer.py +++ b/position_closer.py @@ -1,8 +1,10 @@ """ 币安永续合约定时平仓脚本。 -平仓触发条件:合约多空名义价值总和 > 阈值(默认 50 USDT)且未实现盈亏 > 0(盈利); -或在 Redis 指定 Set 中的合约强制平仓。 +平仓触发条件(满足其一即平仓): +- 在 Redis 指定 Set 中的合约强制平仓; +- 小仓位:多空名义价值总和 < 30 USDT 且未实现盈亏 > 0.03; +- 大仓位:多空名义价值总和 > 50 USDT 且未实现盈亏 > 0.3。 流程: 1. 获取当前持仓; @@ -105,15 +107,23 @@ def should_close_symbol( unrealized_profit: float, threshold: float, in_redis_set: bool = False, + small_threshold: float = 30, + small_min_profit: float = 0.03, + large_min_profit: float = 0.3, ) -> bool: """ 是否对该合约执行平仓。 - 条件:在 Redis 集合中 或 (多空名义价值总和 > threshold 且 未实现盈亏 > 0,即盈利状态)。 + 条件(满足其一即平仓): + - 在 Redis 集合中; + - 多空名义价值总和 < small_threshold 且 未实现盈亏 > small_min_profit(小仓位); + - 多空名义价值总和 > threshold 且 未实现盈亏 > large_min_profit(大仓位)。 """ if in_redis_set: return True total_notional = long_notional + short_notional - if total_notional > threshold and unrealized_profit > 0: + if total_notional < small_threshold and unrealized_profit > small_min_profit: + return True + if total_notional > threshold and unrealized_profit > large_min_profit: return True return False @@ -122,10 +132,13 @@ def get_symbols_to_close( by_symbol: dict[str, list[dict]], threshold: float, redis_contracts: set[str], + small_threshold: float = 30, + small_min_profit: float = 0.03, + large_min_profit: float = 0.3, ) -> tuple[set[str], dict[str, list[dict]]]: """ - 根据持仓、阈值和 Redis 集合,得到需要平仓的交易对及其持仓子集。 - 平仓条件:在 Redis 中 或 (多空名义价值总和 > threshold 且 盈利)。 + 根据持仓和 Redis 集合,得到需要平仓的交易对及其持仓子集。 + 平仓条件:在 Redis 中 或 (小仓位且盈利>small_min_profit) 或 (大仓位且盈利>large_min_profit)。 返回 (symbols_to_close, by_symbol_filtered)。 """ symbols_to_close: set[str] = set() @@ -133,7 +146,10 @@ def get_symbols_to_close( long_n, short_n = get_notional_by_side(sym_positions) unrealized_profit = get_unrealized_profit(sym_positions) in_redis = symbol in redis_contracts - if should_close_symbol(long_n, short_n, unrealized_profit, threshold, in_redis): + if should_close_symbol( + long_n, short_n, unrealized_profit, threshold, in_redis, + small_threshold, small_min_profit, large_min_profit, + ): symbols_to_close.add(symbol) by_symbol_filtered = {k: v for k, v in by_symbol.items() if k in symbols_to_close} return symbols_to_close, by_symbol_filtered @@ -410,6 +426,9 @@ async def main_async() -> None: testnet = "testnet" in str(base_url).lower() redis_url = getattr(settings, "redis_url", None) or "redis://localhost:6379/0" threshold = float(getattr(settings, "notional_threshold", None) or 50) + small_threshold = float(getattr(settings, "notional_small_close_threshold", None) or 30) + small_min_profit = float(getattr(settings, "small_close_min_profit", None) or 0.03) + large_min_profit = float(getattr(settings, "notional_large_close_min_profit", None) or 0.3) redis_key = getattr(settings, "redis_close_key", None) or "close_position:contracts" ws_connection_timeout = float(getattr(settings, "ws_connection_timeout", None) or 30) @@ -430,7 +449,8 @@ async def main_async() -> None: redis_contracts = set() symbols_to_close, by_symbol_filtered = get_symbols_to_close( - by_symbol, threshold, redis_contracts + by_symbol, threshold, redis_contracts, + small_threshold, small_min_profit, large_min_profit, ) for symbol, sym_positions in by_symbol_filtered.items(): long_n, short_n = get_notional_by_side(sym_positions)