350 lines
12 KiB
Markdown
350 lines
12 KiB
Markdown
# Universe Selection Engine (USE)
|
||
|
||
一个基于币安实时数据的加密货币标的池筛选引擎,支持 **多报价币扫描** 与三种主流量化策略:**趋势跟踪**、**均值回归**、**统计套利**。
|
||
|
||
> 所有阈值、报价币、代理地址、K 线周期等参数均通过 `config/config.yaml` 管理,**零硬编码**。
|
||
|
||
---
|
||
|
||
## 一、项目特点
|
||
|
||
- ✅ **多报价币混扫**:USDT / USDC / BUSD / BTC 任选组合,一次扫描多个计价市场
|
||
- ✅ **按报价币独立阈值**:BTC 交叉盘流动性差,可单独放宽成交额门槛
|
||
- ✅ **自适应稳定币黑名单**:扫 USDC 时不会误杀 USDC 标的
|
||
- ✅ **上市天数过滤**:剔除刚上线的新币
|
||
- ✅ **K 线拉取带重试**:网络抖动不会丢失标的
|
||
- ✅ **异步并发 + 限频**:使用 `asyncio.Semaphore` 防 429 封禁
|
||
- ✅ **三种策略并行**:趋势 / 均值回归 / 统计套利
|
||
|
||
---
|
||
|
||
## 二、快速开始
|
||
|
||
### 2.1 环境要求
|
||
|
||
- Python >= 3.10
|
||
- Windows / Linux / macOS 全平台
|
||
- **代理工具**(国内访问币安 API 必需)
|
||
|
||
### 2.2 安装
|
||
|
||
```bash
|
||
cd crypto_use
|
||
pip install -r requirements.txt
|
||
```
|
||
|
||
依赖:`ccxt`, `pandas`, `numpy`, `statsmodels`, `pyyaml`, `scipy`
|
||
|
||
### 2.3 代理配置
|
||
|
||
> ⚠️ **国内直连币安 API 会被阻断,必须配置代理**。
|
||
|
||
编辑 `config/config.yaml`,修改 `exchange.proxy`:
|
||
|
||
```yaml
|
||
exchange:
|
||
proxy: "http://127.0.0.1:7890" # 改成你的代理地址
|
||
```
|
||
|
||
如不需要代理,填 `null`。系统会判断:有代理则注入自定义 aiohttp session(`ThreadedResolver` 绕过 aiodns DNS 失败问题),无代理则走 ccxt 默认行为。
|
||
|
||
### 2.4 运行
|
||
|
||
```bash
|
||
python main.py
|
||
```
|
||
|
||
输出结果保存到 `output/universe_results.json`。**任何目录下运行均可**,项目根路径自动锁定 `main.py` 所在位置。
|
||
|
||
---
|
||
|
||
## 三、输出说明
|
||
|
||
```json
|
||
{
|
||
"timestamp": "2026-07-14 07:24:52",
|
||
"timeframe": "1h",
|
||
"quote_currencies": ["USDT", "USDC"],
|
||
"trend_universe": ["BTC/USDT", "ETH/USDT", "BNB/USDT", ...],
|
||
"mr_universe": [],
|
||
"starb_pairs": []
|
||
}
|
||
```
|
||
|
||
| 字段 | 类型 | 含义 |
|
||
|------|------|------|
|
||
| `timestamp` | string | 运行时间 |
|
||
| `timeframe` | string | 使用的 K 线周期 |
|
||
| `quote_currencies` | list | 本次扫描的报价币列表 |
|
||
| `trend_universe` | list | 趋势跟踪策略标的池 |
|
||
| `mr_universe` | list | 均值回归策略标的池 |
|
||
| `starb_pairs` | list | 统计套利配对池,格式 `[["ETH/USDT", "SOL/USDT"], ...]` |
|
||
|
||
---
|
||
|
||
## 四、配置参数详解
|
||
|
||
所有参数集中在 `config/config.yaml`,共 8 个顶级字段。
|
||
|
||
### 4.1 `exchange` 交易所设置
|
||
|
||
```yaml
|
||
exchange:
|
||
name: binance # 交易所名称(ccxt 支持列表)
|
||
market: spot # spot=现货, future=U本位合约
|
||
proxy: "http://127.0.0.1:7890" # 代理地址,留空或 null 直连
|
||
```
|
||
|
||
### 4.2 `data` 数据设置
|
||
|
||
```yaml
|
||
data:
|
||
timeframe: 1h # K线周期:1m, 5m, 15m, 1h, 4h, 1d
|
||
lookback_candles: 500 # 拉取历史K线根数
|
||
max_concurrency: 15 # K 线并发拉取上限(防 429)
|
||
```
|
||
|
||
| 参数 | 调小 | 调大 |
|
||
|------|------|------|
|
||
| `timeframe` | 1m/5m → 捕捉短期波动,适合日内 | 1d → 过滤噪声,适合长线 |
|
||
| `lookback_candles` | 100 → 计算快但统计不显著 | 1000+ → 更稳健但增加 API 压力 |
|
||
| `max_concurrency` | 5~8 → 更安全 | 20 → 更快但易触发 429 |
|
||
|
||
### 4.3 `base_filter` 基础流动性过滤
|
||
|
||
```yaml
|
||
base_filter:
|
||
# 报价币列表 —— 引擎会扫描所有这些计价市场,写几个就扫几个
|
||
# 支持混配:['USDT', 'USDC'] 会同时扫 USDT 对和 USDC 对
|
||
quote_currencies:
|
||
- USDT
|
||
- USDC
|
||
# 单一计价模式(兼容老配置),如果 quote_currencies 未设置则使用此值
|
||
quote_currency: USDT
|
||
min_quote_volume_24h: 20000000 # 默认成交额门槛(按对应报价币计算)
|
||
# 按报价币覆盖成交额门槛 —— 低流动性报价币可单独放宽
|
||
# 未列出的报价币沿用 min_quote_volume_24h
|
||
volume_thresholds:
|
||
BTC: 50 # BTC 交叉盘流动性远低于 USDT 对
|
||
BUSD: 5000000 # BUSD 对同样冷门
|
||
USDC: 5000000 # USDC 对略低于 USDT
|
||
max_spread_pct: 0.05 # 最大买卖价差 (%)
|
||
min_listing_days: 90 # 最小上市天数(0 = 不限制)
|
||
# 报价币对应的稳定币黑名单(不同计价场景需要不同定义)
|
||
stablecoin_bases:
|
||
USDT: [USDC, FDUSD, DAI, TUSD, BUSD, EUR, TRY]
|
||
USDC: [USDT, FDUSD, DAI, TUSD, BUSD, EUR, TRY]
|
||
BUSD: [USDT, USDC, FDUSD, DAI, TUSD, EUR, TRY]
|
||
BTC: [USDT, USDC, FDUSD, DAI, TUSD, BUSD, EUR, TRY, WBTC]
|
||
USD: [USDT, USDC, FDUSD, DAI, TUSD, BUSD, EUR, TRY]
|
||
exclude_stablecoins: true # 是否启用稳定币过滤
|
||
```
|
||
|
||
**核心设计**:扫 USDT 时,`USDC/FDUSD/DAI...` 这些 base 会被当作稳定币排除;扫 USDC 时不会误杀 USDC 标的;扫 BTC 时还会排除 `WBTC`(防止 WBTC/BTC 这种没意义的循环对)。
|
||
|
||
### 4.4 `trend_filter` 趋势跟踪过滤
|
||
|
||
```yaml
|
||
trend_filter:
|
||
min_annualized_vol: 0.40 # 最小年化波动率(40%)
|
||
min_hurst: 0.55 # 最小 Hurst 指数(>0.5 表示趋势持续)
|
||
```
|
||
|
||
### 4.5 `mean_reversion_filter` 均值回归过滤
|
||
|
||
```yaml
|
||
mean_reversion_filter:
|
||
max_adf_pvalue: 0.05 # ADF 检验最大 p-value(<0.05 表示平稳)
|
||
max_hurst: 0.45 # 最大 Hurst 指数(<0.5 表示反持续)
|
||
max_kurtosis: 10.0 # 最大峰度(剔除极端肥尾/黑天鹅币)
|
||
```
|
||
|
||
### 4.6 `starb_filter` 统计套利过滤
|
||
|
||
```yaml
|
||
starb_filter:
|
||
max_coint_pvalue: 0.05 # 协整检验最大 p-value
|
||
# 板块分类 —— 键为板块名,值为标的列表
|
||
# 标的格式必须为 BASE/QUOTE,必须在 quote_currencies 里有对应 quote
|
||
sectors:
|
||
L1: ["ETH/USDT", "SOL/USDT", "AVAX/USDT", "ADA/USDT", "DOT/USDT", "NEAR/USDT"]
|
||
DeFi: ["UNI/USDT", "AAVE/USDT", "MKR/USDT", "SNX/USDT", "COMP/USDT", "LDO/USDT"]
|
||
Meme: ["DOGE/USDT", "SHIB/USDT", "PEPE/USDT", "WIF/USDT", "FLOKI/USDT", "BONK/USDT"]
|
||
AI: ["RNDR/USDT", "FET/USDT", "AGIX/USDT", "TAO/USDT", "ARKM/USDT"]
|
||
# 交叉盘示例:
|
||
# BTC_Pairs: ["ETH/BTC", "SOL/BTC", "AVAX/BTC"]
|
||
```
|
||
|
||
> ⚠️ 板块分类需要**根据市场叙事动态更新**,不是一成不变的。
|
||
|
||
### 4.7 `fetcher` K 线拉取设置
|
||
|
||
```yaml
|
||
fetcher:
|
||
max_retries: 3 # 单个标的最大重试次数
|
||
retry_delay: 1.0 # 重试基础间隔(秒),实际为 retry_delay × 第几次
|
||
```
|
||
|
||
### 4.8 `output` 输出设置
|
||
|
||
```yaml
|
||
output:
|
||
save_path: "./output/universe_results.json" # 相对路径相对项目根,也可写绝对路径
|
||
```
|
||
|
||
---
|
||
|
||
## 五、参数调优指南
|
||
|
||
### 5.1 标的池太少?→ 放宽阈值
|
||
|
||
| 场景 | 操作 |
|
||
|------|------|
|
||
| 没有任何标的过基础过滤 | 降低 `min_quote_volume_24h` 或在 `volume_thresholds` 给冷门 quote 设小门槛 |
|
||
| 趋势池为空 | 降低 `min_hurst`(如 0.55 → 0.52)或降低 `min_annualized_vol`(0.40 → 0.25) |
|
||
| 均值回归池为空 | 降低 `max_kurtosis`(10.0 → 15.0)或提高 `max_hurst`(0.45 → 0.50) |
|
||
| 套利配对为空 | 提高 `max_coint_pvalue`(0.05 → 0.10)或扩大板块覆盖 |
|
||
|
||
### 5.2 标的池太多?→ 收紧阈值
|
||
|
||
| 场景 | 操作 |
|
||
|------|------|
|
||
| 趋势池全是"死币" | 提高 `min_hurst` 到 0.60+ |
|
||
| 均值回归池出现单边下跌币 | 降低 `max_kurtosis` 到 5.0 以下 |
|
||
| 套利配对太多 | 降低 `max_coint_pvalue` 到 0.01 |
|
||
|
||
### 5.3 多报价币策略
|
||
|
||
| 需求 | 配置示例 |
|
||
|------|----------|
|
||
| 同时扫 USDT + USDC 主流市场 | `quote_currencies: [USDT, USDC]` |
|
||
| 只扫 BTC 交叉盘(量化做 BTC 对统计套利) | `quote_currencies: [BTC]` + `volume_thresholds.BTC: 50` |
|
||
| 全量扫描(不推荐,慢) | `quote_currencies: [USDT, USDC, BUSD, BTC, USD]` + 对应 `volume_thresholds` |
|
||
|
||
---
|
||
|
||
## 六、与实盘对接
|
||
|
||
### 6.1 读取结果
|
||
|
||
```python
|
||
import json
|
||
from pathlib import Path
|
||
|
||
ROOT = Path(__file__).resolve().parent
|
||
with open(ROOT / "output" / "universe_results.json", "r", encoding="utf-8") as f:
|
||
universe = json.load(f)
|
||
|
||
trend_symbols = universe["trend_universe"] # 趋势策略使用
|
||
mr_symbols = universe["mr_universe"] # 均值回归策略使用
|
||
starb_pairs = universe["starb_pairs"] # 统计套利策略使用
|
||
quote_currencies = universe["quote_currencies"] # 本次扫描的报价币
|
||
```
|
||
|
||
### 6.2 定时调度
|
||
|
||
**建议执行频率**:每天凌晨 00:00 UTC 运行一次(流动性/统计量在日内变化不大)。
|
||
|
||
**Linux cron 示例**:
|
||
```bash
|
||
0 0 * * * cd /path/to/crypto_use && /usr/bin/python main.py >> /var/log/use_cron.log 2>&1
|
||
```
|
||
|
||
**Windows 任务计划程序**:新建基本任务 → 触发器"每天 00:00" → 操作"启动程序" `python main.py`,起始于 `crypto_use` 目录。
|
||
|
||
---
|
||
|
||
## 七、项目结构
|
||
|
||
```
|
||
crypto_use/
|
||
├── config/
|
||
│ └── config.yaml # 全局配置(零硬编码的唯一来源)
|
||
├── universe_selector/
|
||
│ ├── __init__.py
|
||
│ ├── fetcher.py # 异步数据拉取(ccxt + 限频 + 重试)
|
||
│ ├── filters.py # 三种策略过滤器(Hurst/ADF/Coint)
|
||
│ ├── engine.py # 流水线控制器
|
||
│ └── utils.py # 统计算法辅助函数
|
||
├── output/
|
||
│ └── universe_results.json # 筛选结果(每次运行覆盖)
|
||
├── main.py # 入口脚本
|
||
├── use_engine.log # 运行日志(每次追加)
|
||
├── requirements.txt # 依赖包
|
||
└── README.md # 本文件
|
||
```
|
||
|
||
---
|
||
|
||
## 八、常见问题
|
||
|
||
**Q: 运行报 DNS 错误?**
|
||
A: 确认代理 7890 端口已启动,且 `config.yaml` 的 `exchange.proxy` 已正确填写。本项目在有代理时会自动注入 `ThreadedResolver`,绕过 aiodns 在代理环境下的 DNS 失败问题。
|
||
|
||
**Q: 报 429 限频?**
|
||
A: 降低 `data.max_concurrency` 到 8~10;或降低 `fetcher.max_retries` 减少重试风暴。
|
||
|
||
**Q: 某些标的 K 线拉不到?**
|
||
A: 项目对每个标的自动重试 3 次(指数退避),最终失败会在日志中输出 ERROR 但不中断流程。如大量失败,检查网络或降低并发。
|
||
|
||
**Q: 均值回归池一直是空的?**
|
||
A: 这是正常现象。`max_hurst < 0.45 + ADF p < 0.05 + kurtosis < 10` 三条件同时满足的标的在币安全市场现货里极少。降低 `max_kurtosis` 到 15+ 或提高 `max_hurst` 到 0.50 试试。
|
||
|
||
**Q: 统计套利配对一直是 0?**
|
||
A: 在 `starb_filter.sectors` 里扩大板块覆盖,或提高 `max_coint_pvalue` 到 0.10。
|
||
|
||
**Q: 想扫描 BTC 交叉盘但出不了标的?**
|
||
A: 在 `base_filter.volume_thresholds.BTC` 设置小门槛(如 50 BTC)。BTC 交叉盘流动性远低于 USDT 对,必须单独配置门槛。
|
||
|
||
**Q: 想看某币是因什么原因被过滤掉的?**
|
||
A: 当前版本未提供 verbose 调试模式。如需要可临时将 `fetcher.py` 中 `get_liquid_symbols` 的循环里加 `print(f"[skip] {symbol}: 原因")`。
|
||
|
||
**Q: 支持合约市场吗?**
|
||
A: 支持。把 `exchange.market` 改成 `future` 即可。但注意币安合约 API 的 ticker 字段与现货略有差异,可能需要根据实际情况微调。
|
||
|
||
**Q: 在哪个目录运行 main.py?**
|
||
A: 任意目录均可。项目根路径通过 `Path(__file__).resolve().parent` 自动锁定,配置/输出/日志路径与 cwd 无关。
|
||
|
||
---
|
||
|
||
## 九、扩展开发
|
||
|
||
### 9.1 新增一种策略过滤器
|
||
|
||
在 `universe_selector/filters.py` 的 `StrategyFilters` 类里添加新方法,例如:
|
||
|
||
```python
|
||
def filter_breakout(self, data_dict: dict[str, pd.DataFrame]) -> list[str]:
|
||
"""突破策略:检测近期价格是否突破 N 日高点"""
|
||
universe = []
|
||
for sym, df in data_dict.items():
|
||
close = df['close'].values
|
||
high_20d = close[:-1][-20*24:].max() # 前 20 天最高
|
||
if close[-1] > high_20d:
|
||
universe.append(sym)
|
||
return universe
|
||
```
|
||
|
||
然后在 `engine.py` 的 `run_pipeline` 中调用:
|
||
```python
|
||
results['breakout_universe'] = self.filters.filter_breakout(data_dict)
|
||
```
|
||
|
||
### 9.2 接入实盘自动下单
|
||
|
||
引擎输出 `output/universe_results.json` 后,下游策略可订阅文件变化(`watchdog` 库)或定时轮询,将新标的池与持仓比对,自动调整下单白名单。
|
||
|
||
---
|
||
|
||
## 十、版本
|
||
|
||
| 版本 | 日期 | 变更 |
|
||
|------|------|------|
|
||
| 1.0 | 2026-07 | 初始版本(USDT only) |
|
||
| 1.1 | 2026-07 | 多报价币 / 按 quote 独立门槛 / 上市天数 / K 线重试 / 路径稳健化 |
|
||
|
||
---
|
||
|
||
## 十一、许可
|
||
|
||
仅供学习和研究使用。加密货币交易有风险,请自行评估。 |