移除 Redis、精简配置,新增 Docker 支持

- position_closer: 去掉 Redis 依赖,平仓条件仅名义+未实现盈亏
- requirements: 移除 redis
- settings.toml: 仅保留实际使用的配置项
- 新增 Dockerfile(仅安装依赖)、docker-compose(挂载代码与配置)
- 新增 .dockerignore、.gitignore(含 nohup.log)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
yhydev
2026-02-04 10:06:30 +08:00
parent 2b72dc40ae
commit 48d31cd1d0
16 changed files with 1245 additions and 31 deletions

View File

@@ -21,7 +21,7 @@ from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from binance import AsyncClient as BinanceAsyncClient
# 第三方与 I/O 依赖在下方 async 函数内按需导入,便于单测时只导入纯逻辑而不触发 binance/redis
# 第三方与 I/O 依赖在下方 async 函数内按需导入,便于单测时只导入纯逻辑而不触发 binance
# ---------- 纯逻辑(无 I/O可单独单元测试----------
@@ -289,22 +289,18 @@ async def run_ws_listener(
symbols_to_close: set[str],
by_symbol: dict[str, list[dict]],
precisions: dict[str, dict],
redis_key: str,
redis_url: str,
redis_contracts: set[str],
dry_run: bool = False,
ws_connection_timeout: float = 30,
) -> None:
"""
创建 BinanceSocketManager订阅需平仓合约的 ticker
收到 WS 事件后按规则下平仓单(每个 symbol 只下一次)。
dry_run=True 时只打印将下的单,不真实下单、不从 Redis 移除
dry_run=True 时只打印将下的单,不真实下单。
ws_connection_timeout: 建立 WebSocket 连接的超时(秒),超时则退出,避免 async with socket 处无限挂起。
"""
from binance.enums import FuturesType
from binance.ws.streams import BinanceSocketManager
from loguru import logger
from redis.asyncio import Redis as Aioredis
if not symbols_to_close:
logger.info("无需平仓的交易对,退出 WS 监听")
@@ -336,15 +332,6 @@ async def run_ws_listener(
dry_run=dry_run,
)
symbols_order_placed.add(symbol)
if not dry_run and symbol in redis_contracts:
redis_client = Aioredis.from_url(redis_url, decode_responses=True)
try:
await redis_client.srem(redis_key, symbol)
logger.info("已从 Redis 平仓集合移除: {}", symbol)
except Exception as e:
logger.warning("从 Redis 移除 {} 失败: {}", symbol, e)
finally:
await redis_client.aclose()
# 仅对「建立连接」阶段加超时,避免网络不可达时 async with socket 无限挂起
try:
@@ -382,7 +369,6 @@ async def run_ws_listener(
async def main_async() -> None:
from binance import AsyncClient as BinanceAsyncClient
from loguru import logger
from redis.asyncio import Redis as Aioredis
from config import settings
@@ -402,14 +388,12 @@ async def main_async() -> None:
else:
dry_run = bool(getattr(settings, "dry_run", True)) # 默认 dry-run
if dry_run:
logger.info("【DRY-RUN】仅测试全流程不会真实下单、不会从 Redis 移除")
logger.info("【DRY-RUN】仅测试全流程不会真实下单")
base_url = getattr(settings, "binance_base_url", None) or "https://fapi.binance.com"
testnet = "testnet" in str(base_url).lower()
redis_url = getattr(settings, "redis_url", None) or "redis://localhost:6379/0"
notional_threshold = float(getattr(settings, "notional_close_threshold", None) or 20)
min_profit = float(getattr(settings, "close_min_profit", None) or 0.05)
redis_key = getattr(settings, "redis_close_key", None) or "close_position:contracts"
ws_connection_timeout = float(getattr(settings, "ws_connection_timeout", None) or 30)
client = await BinanceAsyncClient.create(
@@ -434,14 +418,6 @@ async def main_async() -> None:
symbol, unrealized, long_n, short_n,
)
try:
redis_client = Aioredis.from_url(redis_url, decode_responses=True)
redis_contracts = set(await redis_client.smembers(redis_key) or [])
await redis_client.aclose()
except Exception as e:
logger.warning("读取 Redis 平仓集合失败,仅按名义价值判断: {}", e)
redis_contracts = set()
symbols_to_close, by_symbol_filtered = get_symbols_to_close(
by_symbol,
notional_threshold=notional_threshold,
@@ -469,9 +445,6 @@ async def main_async() -> None:
symbols_to_close=symbols_to_close,
by_symbol=by_symbol_filtered,
precisions=precisions,
redis_key=redis_key,
redis_url=redis_url,
redis_contracts=redis_contracts,
dry_run=dry_run,
ws_connection_timeout=ws_connection_timeout,
)