Files
crypto-atr-signal/README.md
T

8.4 KiB
Raw Blame History

Crypto ATR Signal

Version: v1.3.1

扫描 Binance Futures 交易对,在 4 小时周期识别已收盘 K 线的大阳 / 大阴信号,并通过 FastAPI 网页展示。

核心逻辑

  • 数据源:Binance Futures
  • 市场:
    • CryptoUSDT Perpetual crypto 合约
    • TradFiBinance Futures 传统金融类合约
  • 周期:4H
  • ATRTradingView 默认 ATR(14, RMA)
  • 默认过滤:High - Low >= ATR * 1.5
  • 方向:
    • Close > Open:大阳
    • Close < Open:大阴
  • 已收盘判定:只接受 close_time <= 当前 UTC 时间 的 K 线
  • 页面时间:按 Europe/Madrid 显示

v1.2 变化

  • 增加 TradFi 市场模块。
  • 首页增加 Crypto / TradFi 市场切换。
  • Crypto 和 TradFi 使用独立参数,不共用 ATR 长度、过滤倍数、实体过滤设置。
  • 数据库增加 market_type,旧 Crypto 数据会自动迁移为 CRYPTO
  • 扫描命令增加 --market crypto / --market tradfi

v1.2.1 变化

  • TradFi 使用休市友好逻辑:按 Binance 实际返回的已收盘 K 线处理,不把休市时间段强行当作漏档。
  • Crypto 保持严格 4H 时间轴检查。
  • 新增 scan_runs 扫描记录表。

v1.3.0 变化

  • 增加 --market all,一次完成 Crypto 与 TradFi 扫描。
  • 增加 Discord 聚合推送,一个总开关、每轮一条消息。
  • 页面增加“全部”视图,支持按市场分组或合并排序。
  • 页面默认视图、市场入口、分组和版本信息可通过 .env 控制。

v1.3.1 变化

  • Discord 汇总使用当前最新 K 线信号总数,重复扫描不会误报为 0。
  • 增加扫描进程锁,避免 Cron 任务重叠。
  • 增加 /health 健康检查接口。
  • TradFi 新部署默认启用实体占比 0.5 过滤。

项目结构

crypto-atr-signal
├── scanner.py          # 定时扫描:拉 K 线、补缺口、算 ATR、写 signals
├── webapp.py           # FastAPI 网页展示
├── templates/
│   └── index.html
├── data/app.db         # SQLite 数据库,运行后生成
├── .env.example
├── requirements.txt
├── VERSION
├── CHANGELOG.md
└── README.md

获取与更新项目

推荐使用 SSH 克隆。Gitea 的 SSH 服务使用 2222 端口:

git clone ssh://git@git.polarisx.net:2222/mikemoi/crypto-atr-signal.git
cd crypto-atr-signal

也可以使用 HTTPS

git clone https://git.polarisx.net/mikemoi/crypto-atr-signal.git
cd crypto-atr-signal

私有仓库通过 HTTPS 克隆时,请使用 Gitea 用户名和访问令牌,不要把账户密码写进命令或脚本。

服务器已经部署过项目时,使用以下命令获取最新版本:

cd /www/wwwroot/crypto-atr-signal
git pull --ff-only origin main
.venv/bin/pip install -r requirements.txt
sudo systemctl restart crypto-atr-signal

.envdata/app.db、日志和虚拟环境已被 .gitignore 排除,执行 git pull 不会覆盖这些本地运行数据。更新前不要删除 data 目录或 .env 文件。

安装

cd /www/wwwroot/crypto-atr-signal
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
cp .env.example .env
chmod 600 .env

配置

CRYPTO_ATR_LENGTH=14
CRYPTO_ATR_MULTIPLE=1.5
CRYPTO_BODY_RATIO_FILTER_ENABLED=false
CRYPTO_MIN_BODY_RATIO=0.5

TRADFI_ATR_LENGTH=14
TRADFI_ATR_MULTIPLE=1.5
TRADFI_BODY_RATIO_FILTER_ENABLED=true
TRADFI_MIN_BODY_RATIO=0.5

DISCORD_ENABLED=false
DISCORD_WEBHOOK_URL=

PAGE_DEFAULT_VIEW=all
PAGE_SHOW_ALL=true
PAGE_SHOW_CRYPTO=true
PAGE_SHOW_TRADFI=true
PAGE_GROUP_BY_MARKET=true
PAGE_SHOW_VERSION=true

SCAN_LOCK_PATH=data/scanner.lock
HEALTH_MAX_SCAN_AGE_HOURS=8

INIT_KLINES_LIMIT=40
CONCURRENCY=10
MAX_RETRIES=3
RATE_LIMIT_BACKOFF=30
KLINES_RETENTION_PER_SYMBOL=500
SIGNAL_RETENTION_DAYS=90
DB_PATH=data/app.db

扫描

首次运行会为对应市场的每个品种下载最近 INIT_KLINES_LIMIT 根 4H 已收盘 K 线,用于初始化 ATR。

之后再次运行时:

  • 没有历史数据:初始化最近 40 根 K 线
  • 有历史数据且无缺口:只拉最新 2 根
  • 有缺口:只补中间缺失的 K 线
  • 单个品种失败:记录错误并跳过,不阻塞整轮扫描

手动扫描:

.venv/bin/python scanner.py --market all
.venv/bin/python scanner.py --market crypto
.venv/bin/python scanner.py --market tradfi

Discord 聚合推送只由 --market all 触发。单独扫描某个市场不会发送汇总消息。

Cron

建议服务器使用 UTC 时区。Binance 4H K 线按 UTC 收盘:

00:00 / 04:00 / 08:00 / 12:00 / 16:00 / 20:00 UTC

推荐使用一条聚合 cron

# Binance 4H close + 1 min, UTC;扫描两个市场后发送一条 Discord 汇总
1 0,4,8,12,16,20 * * * cd /www/wwwroot/crypto-atr-signal && .venv/bin/python scanner.py --market all >> scanner.log 2>&1

对应马德里时间:

  • 夏令时:02:01 / 06:01 / 10:01 / 14:01 / 18:01 / 22:01
  • 冬令时:01:01 / 05:01 / 09:01 / 13:01 / 17:01 / 21:01

启动网页

.venv/bin/python -m uvicorn webapp:app --host 127.0.0.1 --port 8000

访问:

  • 全部:http://127.0.0.1:8000/?market=all&sort=desc
  • Cryptohttp://127.0.0.1:8000/?market=crypto&sort=desc
  • TradFihttp://127.0.0.1:8000/?market=tradfi&sort=desc

systemd 常驻网页

[Unit]
Description=Crypto ATR Signal Web
After=network.target

[Service]
WorkingDirectory=/www/wwwroot/crypto-atr-signal
ExecStart=/www/wwwroot/crypto-atr-signal/.venv/bin/python -m uvicorn webapp:app --host 127.0.0.1 --port 8000
Restart=always
RestartSec=3
User=www
Group=www

[Install]
WantedBy=multi-user.target

启用:

sudo systemctl daemon-reload
sudo systemctl enable crypto-atr-signal
sudo systemctl start crypto-atr-signal
sudo systemctl status crypto-atr-signal

Nginx 反向代理

FastAPI 只监听 127.0.0.1:8000,公网访问交给 Nginx

server {
    listen 80;
    server_name signal.example.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

修改域名后执行:

sudo nginx -t
sudo systemctl reload nginx

生产环境建议为域名配置 HTTPS;如果页面只供客户使用,可在 Nginx 增加访问认证。

健康检查

curl http://127.0.0.1:8000/health

数据库正常、Crypto 与 TradFi 最近一次扫描成功且未超过 HEALTH_MAX_SCAN_AGE_HOURS 时返回 HTTP 200。数据库异常、扫描失败或超时未运行时返回 HTTP 503,可直接接入宝塔或 Uptime Kuma。

数据库备份与恢复

使用 SQLite 自带的在线备份命令,不需要停止网页服务:

cd /www/wwwroot/crypto-atr-signal
mkdir -p backups
sqlite3 data/app.db ".backup 'backups/app-$(date +%F-%H%M).db'"

恢复前先停止网页服务,并确保扫描任务没有运行:

sudo systemctl stop crypto-atr-signal
cp backups/app-YYYY-MM-DD-HHMM.db data/app.db
sudo systemctl start crypto-atr-signal

常见故障排查

# 查看网页服务状态和最近日志
sudo systemctl status crypto-atr-signal
sudo journalctl -u crypto-atr-signal -n 100 --no-pager

# 手动执行一轮聚合扫描
cd /www/wwwroot/crypto-atr-signal
.venv/bin/python scanner.py --market all

# 检查网页和数据库健康状态
curl -i http://127.0.0.1:8000/health

如果日志出现 another scanner process is already running,说明上一轮尚未结束,本轮已被进程锁安全跳过,无需手动删除锁文件。

页面功能

  • Crypto / TradFi 市场切换
  • 交易对列表校对时间
  • 最新已收盘 K 线时间
  • 当前信号统计
  • 大阳 / 大阴数量
  • 扫描品种数量
  • ATR 倍数点击切换正序 / 倒序
  • 点击品种跳转 TradingView

数据库

使用 SQLite,并开启 WAL

PRAGMA journal_mode = WAL;

主要表:

  • symbols:交易对列表,按 market_type + symbol 区分市场
  • klines4H K 线和 ATR,按 market_type + symbol + open_time 存储
  • signals:大阳 / 大阴信号,按 market_type + symbol + open_time 存储

资源建议

独立 2C2G VPS 足够运行:

  • FastAPI 常驻
  • SQLite
  • cron 每 4 小时聚合扫描 Crypto 和 TradFi
  • Nginx 反向代理

建议:

  • CONCURRENCY=8~10
  • 服务器时区用 UTC
  • 页面显示马德里时间
  • 不需要 MySQL / PostgreSQL