移除 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

105
README.md Normal file
View File

@@ -0,0 +1,105 @@
# 币安永续合约定时平仓
定时从币安获取永续合约持仓,当满足条件时对该合约的多空进行限价平仓。
**技术栈**:币安合约使用 [python-binance](https://github.com/sammchardy/python-binance) 的 **AsyncClientaio 异步接口)**Redis 使用 [redis.asyncio](https://redis.readthedocs.io/en/stable/examples/asyncio_examples.html)(与 aioredis 用法兼容的异步接口)。
## 逻辑
1. **平仓前置条件**(不满足则直接退出,不执行后续平仓):
- 获取当前账户**总未实现盈亏**,写入 Redis Sorted Set历史记录
- 取**近 N 分钟**(默认 5 分钟)内历史中的**最小总未实现盈亏**
- 仅当 **当前总未实现盈亏 - 该最小 > 配置阈值**(默认 2 USDT才继续执行平仓逻辑否则退出。
2. **定时拉取持仓**:按配置间隔调用币安 `GET /fapi/v2/positionRisk` 获取 USDT 永续持仓。
3. **触发条件**(满足其一即对该合约平仓):
- Redis 中指定 key 的 Set 里包含该合约 symbol`BTCUSDT`)时强制平仓;
- 该合约**多空名义价值总和** < `notional_small_close_threshold`(默认 30 USDT**且**未实现盈亏 > `small_close_min_profit`(默认 0.03 USDT
4. **平仓方式**
- **多头**:限价卖出,价格 = 当前价 × 1.003
- **空头**:限价买入,价格 = 当前价 × 0.997。
4. 若因 Redis 触发平仓,平仓后会从该 Set 中移除该 symbol。
## 配置Dynaconf
配置通过 [Dynaconf](https://www.dynaconf.com/) 加载,按优先级:环境变量 > `.secrets.toml` > `settings.toml`。环境变量需加前缀 `BINANCE_POSITION_`(如 `BINANCE_POSITION_BINANCE_API_KEY`)。
- **settings.toml**:所有非敏感配置均在此文件,可直接修改。
- **.secrets.toml**:仅放敏感信息(复制 `.secrets.toml.example``.secrets.toml` 后填写),勿提交。
| 配置项 | 说明 | 所在文件 |
|--------|------|----------|
| `binance_api_key` | 币安 API Key需合约权限 | .secrets.toml |
| `binance_api_secret` | 币安 API Secret | .secrets.toml |
| `binance_base_url` | 合约 API 地址 | settings.toml |
| `redis_url` | Redis 连接 | settings.toml |
| `redis_close_key` | 强制平仓合约的 Redis Set key | settings.toml |
| `redis_unrealized_profit_history_key` | 总未实现盈亏历史的 Sorted Set key用于平仓前置条件默认 `close_position:unrealized_profit_history` | settings.toml |
| `unrealized_profit_window_seconds` | 平仓前置条件:近 N 秒内最小总未实现盈亏作为基准,默认 3005 分钟) | settings.toml |
| `unrealized_profit_min_rise` | 平仓前置条件:当前总未实现盈亏 - 近 N 秒最小 须大于此值USDT才执行平仓默认 2 | settings.toml |
| `notional_threshold` | 大仓位阈值USDT多空价值总和大于此值且盈利大于 notional_large_close_min_profit 时平仓,默认 50 | settings.toml |
| `notional_large_close_min_profit` | 大仓位平仓最低盈利USDT大仓位未实现盈亏须大于此值默认 0.3 | settings.toml |
| `notional_small_close_threshold` | 小仓位平仓阈值USDT多空价值总和小于此值且盈利大于 small_close_min_profit 时平仓,默认 30 | settings.toml |
| `small_close_min_profit` | 小仓位平仓最低盈利USDT小仓位未实现盈亏须大于此值默认 0.03 | settings.toml |
| `interval_seconds` | 轮询间隔(秒),当前流程备用 | settings.toml |
| `dry_run` | 默认 `true`dry-run不真实下单设为 `false``DRY_RUN=0` 时真实下单 | settings.toml |
**默认 dry-run**:脚本默认只跑全流程并打印将下的单,不真实下单、不从 Redis 移除。要真实平仓时,在 `settings.toml` 中设置 `dry_run = false`,或运行前设置环境变量 `DRY_RUN=0`
## 安装与运行
使用项目内 venv 初始化环境并运行:
```bash
# 创建虚拟环境(若尚未创建)
python3 -m venv .venv
# 激活虚拟环境并安装依赖
.venv/bin/pip install -r requirements.txt
# 运行
.venv/bin/python position_closer.py
```
或先激活 venv 再执行:
```bash
source .venv/bin/activate # Linux/macOS
pip install -r requirements.txt
python position_closer.py
```
## 每小时定时运行
项目内提供 `run_position_closer.sh`
```bash
# 运行一次
./run_position_closer.sh
# 前台每 1 小时运行一次循环Ctrl+C 停止)
./run_position_closer.sh loop
```
**用 crontab 每小时整点执行一次**(将路径换成你的项目目录):
```bash
crontab -e
# 添加一行(整点执行):
0 * * * * /home/yanhaoyang/Projects/bn-pc/run_position_closer.sh
```
## 通过 Redis 指定平仓合约
向 Redis Set 添加需要平仓的合约 symbol 即可,下一轮轮询会对其多空进行平仓,并在平仓后从 Set 中移除:
```bash
redis-cli SADD close_position:contracts BTCUSDT ETHUSDT
```
(若修改了 `redis_close_key`,请使用你配置的 key。
## 注意事项
- 支持**单向持仓**positionSide=BOTH与**双向持仓**LONG/SHORT
- 平仓使用**限价单**,若市价偏离较多可能不会立刻成交,需自行在交易所查看或撤单改市价。
- API Key 需有 USDT 永续合约的读取与交易权限;建议先用测试网验证。