Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 11 additions & 17 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,22 @@

> **记忆活在文件里,不活在上下文里。** 你做到哪、下一步做什么、不许碰什么,全部由上面四个文件 + git 历史决定,**不靠"记住"**。因此 `/clear`、换 subagent、换会话、换模型、进程崩溃——都不影响连续性:任何空白上下文读完这四个文件就能精确接续。长程连续任务见下方「自治连续执行」。

## ⭐ 当前接棒队列(2026-07-15 更新,便宜模型看这里
## ⭐ 当前接棒队列(2026-08-13 更新)

> **便宜模型的机械任务已全部清零**——Phase R + R2 的 RA/RB/RS/RT/RC/RB2/RC2 全部落地,基线 **274 passed, 2 skipped,覆盖率 91.7%**。
> 上一版队列列的 7 个便宜模型任务(RB2.3/RC.5/RC.4/RC2.2/RC2.1/RB2.2/RC.2)**都已完成**,不要重做。
> 用户已拍板:S1 不认沉默;部署+回测 S2;dry-run 开机即跑。落地说明见 `docs/system/08-s1-s2-backtest.md`。
>
> **⚠️ 现在没有「便宜模型可盲取」的任务了。** 剩下的全部需要用户投资判断 + 强模型,详见 `03-tasks.md` 顶部「现状对账」。核心卡点是一条**策略问题、不是工程问题**:
> **不要重做**已写入配置/策略的 P1.1 白名单、S1 回踩信号、S2 部署、`initial_state: running`。
>
> **🔴 头号根因:策略层空转。** S1 趋势跟踪 3.5 年只出 3 笔交易、牛市留出段 0 笔;dry-run 容器 up 9 天却 STOPPED 态 + 0 交易。ADR-005 升档要 ≥30 笔 → 当前 S1 单策略下状态机几十年走不完。**你建的整套安全网下面没有交易可监管。**
> **🔴 新的头号风险:S2 研究回测最大回撤 -91.6%。** 有交易可观察了,但按用户「回撤 <20%」这套 S2 **不能上实盘**。S1 变密之后平均盈亏为负。dry-run 的意义就是把这两件事看清楚。
>
> **下一步真正的工作(按优先级,均需强模型 / 用户拍板):**
> 1. **用户先拍板**:S1 的「长期沉默」是认可的 feature(趋势跟踪本该在牛市外沉默),还是要改(加 pairs/降周期/加次级信号)?
> 2. 🧠 **部署 + 回测 S2**(P1.3/P1.6)——让 dry-run「有交易可观察」最快的路
> 3. 🧠 若要救 S1:先做 P1.1(下市值前 15 币种),再重跑 P1.4 hyperopt
> 4. 把 dry-run bot 从 STOPPED 切 RUNNING(`dry-run.json` 设 `initial_state: running`)
> 5. 🧠 P1.5 jesse 交叉验证(上实盘前的闸)
> **下一步(均需用户 / 强模型):**
> 1. 用户在 **VPS** 上 `cd deploy && docker compose up -d`(本云端无 Docker、币安 451)。
> 2. VPS 上对 15 对跑 `freqtrade download-data`(1d,可选 4h)
> 3. 观察 dry-run,不要切 live
> 4. 🧠 若要救 S2 回撤:另拍板(例如 BTC<EMA200 空仓),不要在没拍板时偷加过滤器
> 5. 🧠 P1.4 按新 S1 信号重跑 hyperopt;P1.5 jesse。
>
> **绝对不要碰**(需强模型/外部集成,碰了会出错):
> - **RB.2 剩余(规则2 敞口)**、**RB2.1 剩余(迁 Postgres)**、**RB.4 的全量 Alembic**:需接 freqtrade REST / 换 DB,属集成决策。
> - 任何标 🧠 的项、`RD` 组(用户用 open design 自理)。
> - 已打 `[x]` 或标 🔶「完成/部分完成」的任务:**不要重做**。
>
> ⚠️ **不要按「第一个 `[ ]`」盲取**——P1 里的 `[ ]` 是需强模型 + 投资判断的策略活,不是便宜模型任务。
> **绝对不要碰**:ADR-005 门槛、关 Protection、`stoploss_on_exchange`、`max_open_trades>3`、RB.2 敞口 / Postgres / Alembic、标 🧠 且未拍板的项。



Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Sentinel 是一个面向**稳健型个人投资者**的加密货币量化交易

## 当前状态

🚧 **Phase 0 / 1 / 2 已落地(268 passed, 2 skipped),Phase 3 看板 / Phase 4 实盘未开始。**
🚧 **Phase 0 / 1 / 2 工程已落地。2026-08-13:S1 不再只靠金叉(15 币 + 回踩),S2 已部署配置;研究回测见 `docs/system/08-s1-s2-backtest.md`。S2 最大回撤 -91%,只许 dry-run。Phase 3 看板 / Phase 4 实盘未开始。**

按 `docs/system/03-tasks.md` 的 Phase 0-4 推进:

Expand Down
23 changes: 14 additions & 9 deletions deploy/RUNBOOK.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,22 @@ chmod 600 .env
# 3. 启动
docker compose up -d

# 4. 查看状态
# 4. 查看状态(S1=8080,S2=8081,两个 bot 都应是 running 而不是 stopped)
docker compose ps
docker compose logs -f freqtrade
docker compose logs -f freqtrade-s2
# curl -fsS http://localhost:8080/api/v1/ping
# curl -fsS http://localhost:8081/api/v1/ping
```

## 3. 访问

- **FreqUI(Web 界面)**:http://localhost:8080
- **FreqUI S1**:http://localhost:8080
- **FreqUI S2**:http://localhost:8081
- 用户名:`sentinel`
- 密码:`API_PASSWORD` 的值
- **REST API**:http://localhost:8080/api/v1/
- **日志**:`/freqtrade/user_data/logs/freqtrade.log`(容器内路径),宿主对应 `deploy/user_data/logs/`
- **REST API**:http://localhost:8080/api/v1/ (S2 为 8081)
- **日志**:宿主 `deploy/user_data/logs/freqtrade.log` 与 `freqtrade-s2.log`

## 4. 常用命令

Expand All @@ -63,10 +67,11 @@ docker compose restart freqtrade
docker compose down -v
rm -rf user_data/*

# 重新下载历史数据(Phase 1 需要
# 重新下载历史数据(P1.1:15 个 USDT 现货,1d
docker compose run --rm freqtrade download-data \
--exchange okx --pairs BTC/USDT ETH/USDT \
--timeframes 1d 4h --days 1500
--exchange binance \
--pairs BTC/USDT ETH/USDT SOL/USDT XRP/USDT ADA/USDT DOGE/USDT AVAX/USDT DOT/USDT LINK/USDT BCH/USDT LTC/USDT UNI/USDT ATOM/USDT FIL/USDT NEAR/USDT \
--timeframes 1d 4h --days 2200
```

## 5. 明早起床后:激活 Telegram
Expand Down Expand Up @@ -193,8 +198,8 @@ sudo ufw allow from 127.0.0.1 to any port 8080 proto tcp
sudo ufw allow from A.B.C.D to any port 8080 proto tcp

# 其余入站到 8000/8080 一律拒绝(默认 deny incoming 已覆盖,此处显式声明更直观)
sudo ufw deny 8000/tcp
sudo ufw deny 8080/tcp
sudo ufw allow from 127.0.0.1 to any port 8081 proto tcp
sudo ufw deny 8081/tcp

sudo ufw enable
sudo ufw status verbose
Expand Down
31 changes: 31 additions & 0 deletions deploy/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ services:
HTTPS_PROXY: "${HTTPS_PROXY:-}"
http_proxy: "${HTTP_PROXY:-}"
https_proxy: "${HTTPS_PROXY:-}"
FREQTRADE_CONFIG_IN: /freqtrade/user_data/config/dry-run.json
FREQTRADE_STRATEGY: S1TrendFollow
FREQTRADE_DB_URL: sqlite:///user_data/tradesv3.sqlite
FREQTRADE_LOGFILE: /freqtrade/user_data/logs/freqtrade.log
# 用 host 网络模式:让容器共享宿主机网络栈,能直接访问 127.0.0.1:7890 上的本地代理
# 这是国内环境下让容器内 Python 访问交易所最可靠的方式
# (之前用 bridge 模式 + host.docker.internal 在 OrbStack 下不可达)
Expand All @@ -47,6 +51,33 @@ services:
retries: 3
start_period: 60s

freqtrade-s2:
image: freqtradeorg/freqtrade:stable
container_name: sentinel-freqtrade-s2
restart: unless-stopped
env_file:
- .env
environment:
HTTP_PROXY: "${HTTP_PROXY:-}"
HTTPS_PROXY: "${HTTPS_PROXY:-}"
http_proxy: "${HTTP_PROXY:-}"
https_proxy: "${HTTPS_PROXY:-}"
FREQTRADE_CONFIG_IN: /freqtrade/user_data/config/dry-run-s2.json
FREQTRADE_STRATEGY: S2MomentumRotation
FREQTRADE_DB_URL: sqlite:///user_data/tradesv3-s2.sqlite
FREQTRADE_LOGFILE: /freqtrade/user_data/logs/freqtrade-s2.log
network_mode: host
volumes:
- ./user_data:/freqtrade/user_data
- ./start.sh:/freqtrade/start.sh:ro
entrypoint: ["/bin/sh", "/freqtrade/start.sh"]
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8081/api/v1/ping"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s

# ============================================================
# AI service (P2 — Phase 2.1 wired up)
# Same host network mode as freqtrade so it can listen on 127.0.0.1:8000
Expand Down
27 changes: 19 additions & 8 deletions deploy/start.sh
Original file line number Diff line number Diff line change
@@ -1,24 +1,35 @@
#!/bin/sh
# Sentinel freqtrade startup script.
# Replaces ${API_PASSWORD} and ${API_JWT_SECRET} placeholders from env,
# Replaces ${API_PASSWORD} / ${API_JWT_SECRET} / webhook URL from env,
# then launches freqtrade trade.
#
# Per-bot overrides (S1 vs S2):
# FREQTRADE_CONFIG_IN default /freqtrade/user_data/config/dry-run.json
# FREQTRADE_STRATEGY default S1TrendFollow
# FREQTRADE_DB_URL default sqlite:///user_data/tradesv3.sqlite
set -e

export FREQTRADE_CONFIG_IN="${FREQTRADE_CONFIG_IN:-/freqtrade/user_data/config/dry-run.json}"
export FREQTRADE_STRATEGY="${FREQTRADE_STRATEGY:-S1TrendFollow}"
export FREQTRADE_DB_URL="${FREQTRADE_DB_URL:-sqlite:///user_data/tradesv3.sqlite}"
export FREQTRADE_LOGFILE="${FREQTRADE_LOGFILE:-/freqtrade/user_data/logs/freqtrade.log}"

python3 - <<'PYEOF'
import os, sys
import os

src = open("/freqtrade/user_data/config/dry-run.json").read()
src_path = os.environ["FREQTRADE_CONFIG_IN"]
src = open(src_path).read()
dst = (
src
.replace("${API_PASSWORD}", os.environ.get("API_PASSWORD", ""))
.replace("${API_JWT_SECRET}", os.environ.get("API_JWT_SECRET", ""))
.replace("${AI_SERVICE_WEBHOOK_URL}", os.environ.get("AI_SERVICE_WEBHOOK_URL", "http://127.0.0.1:8000"))
)
open("/tmp/dry-run-runtime.json", "w").write(dst)
open("/tmp/freqtrade-runtime.json", "w").write(dst)
PYEOF

exec freqtrade trade \
--logfile /freqtrade/user_data/logs/freqtrade.log \
--db-url "sqlite:///user_data/tradesv3.sqlite" \
--config /tmp/dry-run-runtime.json \
--strategy S1TrendFollow
--logfile "${FREQTRADE_LOGFILE}" \
--db-url "${FREQTRADE_DB_URL}" \
--config /tmp/freqtrade-runtime.json \
--strategy "${FREQTRADE_STRATEGY}"
15 changes: 14 additions & 1 deletion deploy/user_data/config/config.template.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,20 @@
"secret": "${EXCHANGE_SECRET}",
"pair_whitelist": [
"BTC/USDT",
"ETH/USDT"
"ETH/USDT",
"SOL/USDT",
"XRP/USDT",
"ADA/USDT",
"DOGE/USDT",
"AVAX/USDT",
"DOT/USDT",
"LINK/USDT",
"BCH/USDT",
"LTC/USDT",
"UNI/USDT",
"ATOM/USDT",
"FIL/USDT",
"NEAR/USDT"
],
"pair_blacklist": [
"BNB/.*",
Expand Down
127 changes: 127 additions & 0 deletions deploy/user_data/config/dry-run-s2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
{
"$schema": "https://www.freqtrade.io/en/stable/schema.json",
"_comment": "S2 dry-run. 独立容器/端口/SQLite。与 S1 共用 whitelist 与铁律风控。",
"_sentinel_phase": "P1.6 — S2 dry-run, initial_state running",

"max_open_trades": 3,
"stake_currency": "USDT",
"stake_amount": 50,
"tradable_balance_ratio": 0.99,
"fiat_display_currency": "USD",
"timeframe": "1d",
"dry_run": true,
"initial_state": "running",
"cancel_open_orders_on_exit": false,

"exchange": {
"name": "binance",
"key": "",
"secret": "",
"pair_whitelist": [
"BTC/USDT",
"ETH/USDT",
"SOL/USDT",
"XRP/USDT",
"ADA/USDT",
"DOGE/USDT",
"AVAX/USDT",
"DOT/USDT",
"LINK/USDT",
"BCH/USDT",
"LTC/USDT",
"UNI/USDT",
"ATOM/USDT",
"FIL/USDT",
"NEAR/USDT"
],
"pair_blacklist": ["BNB/.*", ".*UP/.*", ".*DOWN/.*"],
"enable_ws": false,
"ccxt_config": {
"enableRateLimit": true,
"timeout": 30000,
"aiohttp_trust_env": true,
"options": {
"defaultType": "spot",
"fetchMarkets": ["spot"]
}
},
"ccxt_async_config": {
"enableRateLimit": true,
"timeout": 30000,
"httpsProxy": "http://127.0.0.1:7890",
"options": {
"defaultType": "spot",
"fetchMarkets": ["spot"]
}
}
},

"strategy": "S2MomentumRotation",

"stoploss": -0.10,
"stoploss_on_exchange": true,
"stoploss_on_exchange_interval": 60,
"stoploss_on_exchange_market_ratio": -0.01,

"entry_pricing": {"price_side": "same", "use_order_book": false},
"exit_pricing": {"price_side": "same", "use_order_book": false},

"pairlists": [
{"method": "StaticPairList"}
],

"telegram": {
"enabled": false,
"token": "",
"chat_id": "",
"notification_settings": {
"status": "on", "warning": "on", "startup": "on",
"entry": "on", "entry_fill": "on", "entry_cancel": "on",
"exit": "on", "exit_fill": "on", "exit_cancel": "on",
"protection_trigger": "on", "protection_trigger_global": "on"
}
},

"webhook": {
"enabled": true,
"url": "${AI_SERVICE_WEBHOOK_URL}",
"format": "json",
"retries": 2,
"retry_delay": 5,
"timeout": 10,
"exit_fill": {
"trade_id": "{trade_id}",
"strategy": "S2MomentumRotation",
"pair": "{pair}",
"direction": "{direction}",
"open_rate": "{open_rate}",
"close_rate": "{close_rate}",
"profit_ratio": "{profit_ratio}",
"profit_amount": "{profit_amount}",
"open_date": "{open_date}",
"close_date": "{close_date}",
"exit_reason": "{exit_reason}",
"enter_tag": "{enter_tag}",
"stake_amount": "{stake_amount}",
"stake_currency": "{stake_currency}",
"is_final_exit": "{is_final_exit}",
"sub_trade": "{sub_trade}",
"side": "long"
}
},

"api_server": {
"enabled": true,
"listen_ip_address": "0.0.0.0",
"listen_port": 8081,
"verbosity": "info",
"jwt_secret_key": "${API_JWT_SECRET}",
"CORS_origins": ["http://localhost:8081"],
"username": "sentinel",
"password": "${API_PASSWORD}"
},

"db_url": "sqlite:///user_data/tradesv3-s2.sqlite",
"verbosity": 3,
"logfile": "user_data/logs/freqtrade-s2.log"
}
25 changes: 21 additions & 4 deletions deploy/user_data/config/dry-run.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://www.freqtrade.io/en/stable/schema.json",
"_comment": "由 config.template.json 生成。dry-run/live 唯一差异是 dry_run 字段。",
"_sentinel_phase": "Phase 0 — 跑通流程,不实盘",
"_comment": "S1 dry-run. dry-run/live 唯一差异应是 dry_run 字段(ADR-005)。",
"_sentinel_phase": "P1.6 — S1 dry-run, initial_state running",

"max_open_trades": 3,
"stake_currency": "USDT",
Expand All @@ -10,13 +10,30 @@
"fiat_display_currency": "USD",
"timeframe": "1d",
"dry_run": true,
"initial_state": "running",
"cancel_open_orders_on_exit": false,

"exchange": {
"name": "binance",
"key": "",
"secret": "",
"pair_whitelist": ["BTC/USDT", "ETH/USDT"],
"pair_whitelist": [
"BTC/USDT",
"ETH/USDT",
"SOL/USDT",
"XRP/USDT",
"ADA/USDT",
"DOGE/USDT",
"AVAX/USDT",
"DOT/USDT",
"LINK/USDT",
"BCH/USDT",
"LTC/USDT",
"UNI/USDT",
"ATOM/USDT",
"FIL/USDT",
"NEAR/USDT"
],
"pair_blacklist": ["BNB/.*", ".*UP/.*", ".*DOWN/.*"],
"enable_ws": false,
"ccxt_config": {
Expand Down Expand Up @@ -107,4 +124,4 @@
"db_url": "sqlite:///user_data/tradesv3.sqlite",
"verbosity": 3,
"logfile": "user_data/logs/freqtrade.log"
}
}
Loading