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

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-04 10:06:30 +08:00

106 lines
5.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 币安永续合约定时平仓
定时从币安获取永续合约持仓,当满足条件时对该合约的多空进行限价平仓。
**技术栈**:币安合约使用 [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 永续合约的读取与交易权限;建议先用测试网验证。