Compare commits
507 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2028251fc1 | |||
| 339f5e6db0 | |||
| 71a91484a3 | |||
| 86cf722117 | |||
| 2a33f74252 | |||
| 271865fa3d | |||
| 9c19afc8d4 | |||
| 8605efa2ed | |||
| cd23ea74a6 | |||
| 8dda7500df | |||
| 886b6dcc5b | |||
| a8d6795837 | |||
| 51e454b0f6 | |||
| 1522117eeb | |||
| a354811a6e | |||
| 3d7d754ba3 | |||
| 38e3e00fe9 | |||
| a1bf760a28 | |||
| c5d3d9d6c1 | |||
| e26a67176c | |||
| 860ebef4a7 | |||
| a90876d772 | |||
| 245b85ad27 | |||
| 425fc701bc | |||
| eca6d091e9 | |||
| 6ab27cebcd | |||
| 20e0c2cb9f | |||
| c3c7243dd7 | |||
| f7e5329915 | |||
| e7e733d9a9 | |||
| afe361ce47 | |||
| 0b8e5a0914 | |||
| 4bc238b014 | |||
| d41028b766 | |||
| 75a4175522 | |||
| 993189ce13 | |||
| 2181c81aba | |||
| baf928d064 | |||
| f19500bcd9 | |||
| 25ed46e3f2 | |||
| 7f22bffbc6 | |||
| 7352d10254 | |||
| 3f6e67661b | |||
| 09a763e47d | |||
| 22e6b68e6d | |||
| 55e94fe059 | |||
| 747434a65e | |||
| f6ea0dc399 | |||
| a00699aec3 | |||
| 4b4dca9e3c | |||
| fa7ff739a0 | |||
| fdbbde08df | |||
| 83ce50b24e | |||
| f9c2a63cbc | |||
| 94c65cbd6e | |||
| 644dcdf092 | |||
| d89aff3ad6 | |||
| 9f3395de2f | |||
| 28a329cb63 | |||
| 1c2c012dd7 | |||
| 05864d72c2 | |||
| 722c511543 | |||
| 26bc19f047 | |||
| c81ba147cc | |||
| 90be23e845 | |||
| 2ce67da8e8 | |||
| d049c5d317 | |||
| 845884fc67 | |||
| c73e36309e | |||
| 21c80f2ac9 | |||
| a908dccaba | |||
| 4bcf88b5cb | |||
| f360242188 | |||
| f53f2814ab | |||
| e5051fb309 | |||
| 1dc7914701 | |||
| 58e2bf3e8b | |||
| 19debee581 | |||
| 1755f67eca | |||
| 6886de0bad | |||
| f04a91efe6 | |||
| b43e33e24f | |||
| b5a061e758 | |||
| 4ef3b40353 | |||
| 4a79e010c4 | |||
| 791cc750da | |||
| c8231ea194 | |||
| aaccdcfc16 | |||
| f993a89a21 | |||
| 9dc363270e | |||
| 9a83dfe209 | |||
| 32c42b8447 | |||
| a2075ba73e | |||
| 846f3de525 | |||
| a7b75895e6 | |||
| d870178b83 | |||
| 7ebe1671b2 | |||
| cb4f6aaa4b | |||
| eb175820e9 | |||
| 890659f173 | |||
| ca499c6104 | |||
| 54f1857fa2 | |||
| 6f1ae14b3d | |||
| 29d59d6a53 | |||
| 58a4dafe9a | |||
| 9e0591c676 | |||
| ed3033d793 | |||
| b6156e0049 | |||
| 8e3c00641f | |||
| f11f89e760 | |||
| 0096467d14 | |||
| 8a9dee267f | |||
| 910c938d0a | |||
| 0a9e3aa95c | |||
| b64c742fc9 | |||
| 789ab43dbe | |||
| 61e8da1e8b | |||
| 40be3a5ab7 | |||
| 4ccfb838f6 | |||
| 58e9c8f85e | |||
| eb0eddbc9d | |||
| c5f40cba2b | |||
| a7216428ab | |||
| 77f66bf200 | |||
| 488b931959 | |||
| b89cba3b6e | |||
| e7f8e9201e | |||
| 301a464f29 | |||
| a4be294c06 | |||
| 1a163c0a43 | |||
| 2a60d47b2d | |||
| 64b24fd6a6 | |||
| 60ff45f098 | |||
| 67a09b1de8 | |||
| 7e7666adfb | |||
| 6876515160 | |||
| 1bc12a32c6 | |||
| 6def61fae3 | |||
| 10ee7614b5 | |||
| 221e8c3cad | |||
| 29c080f8e0 | |||
| 7a01535802 | |||
| f467f94fe9 | |||
| 913c7d5be6 | |||
| 0f5fe801e2 | |||
| 977d62bddf | |||
| 3ed8dabc76 | |||
| eb2afb3c55 | |||
| ee3c1bcdca | |||
| d2028ed0ee | |||
| 3ae7def999 | |||
| c9229d64bf | |||
| 3923818508 | |||
| 4a3e6a2a1d | |||
| 00d76ba20f | |||
| 5b346a5760 | |||
| a43cb35d9a | |||
| 8597e47596 | |||
| 88d460d484 | |||
| ed1ec6f14a | |||
| 7eb098def6 | |||
| 972ef4f910 | |||
| 4e614eb9ed | |||
| 547eedeec4 | |||
| 19b46d19fd | |||
| debfb116fd | |||
| 3c21680763 | |||
| bc08a5852d | |||
| a2d4507028 | |||
| 17cd835e5d | |||
| ac018cb618 | |||
| 220aab9b63 | |||
| 72dddc5106 | |||
| 12574ae88a | |||
| 426afb8dbe | |||
| 38ac258497 | |||
| 7938628485 | |||
| e3cd2a75de | |||
| bc797cb1db | |||
| 0ed2eabf0d | |||
| 5e0ce43415 | |||
| eea4d4ff8f | |||
| d74d0aeae0 | |||
| e11c13747a | |||
| 899a2de931 | |||
| fa2127d66c | |||
| d5f3f315dc | |||
| 1c155328b4 | |||
| 3093d07167 | |||
| 79420904f4 | |||
| 3119486105 | |||
| b3548240cc | |||
| f21e4d1166 | |||
| 9e1343981d | |||
| 2f7e6355a1 | |||
| 023bf6a814 | |||
| 9198aa0dcd | |||
| 82c910fbf8 | |||
| 778a215ad7 | |||
| faf21da955 | |||
| 0a14fe73c1 | |||
| 27c116f872 | |||
| a244850b25 | |||
| 8f4ae8ad31 | |||
| 813ecdd4ac | |||
| 217e752ee6 | |||
| 173f09300b | |||
| aabbbef0a9 | |||
| 53e55aa4b4 | |||
| 041692a763 | |||
| 572239f69c | |||
| 0f12e0a8ea | |||
| 2269bc51ff | |||
| d5e6132b13 | |||
| 89148bb119 | |||
| 549d8a015c | |||
| c4c8ad172a | |||
| 0bda44248f | |||
| 33b3e5f54b | |||
| e70e6c7b13 | |||
| b7f3a5c289 | |||
| 7a0d015416 | |||
| afb771fef1 | |||
| e5e1d5edcc | |||
| c2a40e3cc5 | |||
| 4126784056 | |||
| af7fb44650 | |||
| 5bd3f3250a | |||
| f27b4bc1ec | |||
| 3a20546782 | |||
| 35117ba84e | |||
| cd2dfac2ba | |||
| c7aae67881 | |||
| f7ba7c2f7d | |||
| f435e9dfaa | |||
| d9b8069906 | |||
| 57f8d6761c | |||
| 77ab7503a1 | |||
| 06ffb6ee0f | |||
| 78c44fdeab | |||
| cb2fcd283a | |||
| 3f6e4329d9 | |||
| 353c09ea0d | |||
| ee9608dc80 | |||
| 8842f0b869 | |||
| 01ca035c2a | |||
| d7272c9722 | |||
| 48afc8ebe3 | |||
| c6142dc246 | |||
| edcc04e88c | |||
| 10128d18bc | |||
| eb5c6a658b | |||
| 8f71dbe874 | |||
| 6e6cb7caac | |||
| e280220951 | |||
| c9d40e5e52 | |||
| b30129f83f | |||
| 4e86595f2a | |||
| 35b23836e3 | |||
| 0540b585c7 | |||
| 018b4d5601 | |||
| bde8c517e0 | |||
| 480f6d78e8 | |||
| 57dad1ffdf | |||
| 7d6f0ac55b | |||
| 2777419a10 | |||
| 836b37cc7e | |||
| 4686cf049a | |||
| 195eeae295 | |||
| 1f767f16e4 | |||
| b057122d71 | |||
| 95e46ab803 | |||
| 12c4e55f24 | |||
| b50eebe37c | |||
| 4c7197ad99 | |||
| f0d5b47f50 | |||
| 4a0b0def1d | |||
| 19a4a5194d | |||
| 717a3d5694 | |||
| 83a7465996 | |||
| 8838f1f221 | |||
| f16dcac202 | |||
| bfb5e22be9 | |||
| 0939274113 | |||
| a21b962bf1 | |||
| 6f934ecbbf | |||
| cbb7f954f5 | |||
| ee7be3e7f3 | |||
| 60f3437c73 | |||
| 1909eea654 | |||
| ab8b2a74e2 | |||
| c2a0cea3f4 | |||
| c025c06fac | |||
| e15eca76f3 | |||
| da3975e42e | |||
| 142b6de0f6 | |||
| ec30a3999c | |||
| 944a211e4a | |||
| 0bedb2e972 | |||
| 61f63c456b | |||
| 280e59eb25 | |||
| bcb229fc9d | |||
| cfc1d42c09 | |||
| d6823a2903 | |||
| 8d2da921ee | |||
| 1e765f4b2b | |||
| 8ecc70a61c | |||
| f6ef06f659 | |||
| e6907dfbbe | |||
| 982497d65a | |||
| 5fcf649c79 | |||
| 8afaea1ea6 | |||
| 9e0d89bd01 | |||
| 036501b70c | |||
| 27f4f5e2ee | |||
| 8d37b2cba3 | |||
| 09cd680e4a | |||
| 4df2cb4253 | |||
| 9e17814e37 | |||
| 1fa98425e7 | |||
| d27ccbea8f | |||
| 1bda78ceb2 | |||
| c4753ffb89 | |||
| c4bac23c48 | |||
| 8e492987ec | |||
| 337a6bc54f | |||
| 96b5096284 | |||
| acb61a413b | |||
| 95895d53b6 | |||
| 58c9f36a75 | |||
| 44657e0484 | |||
| 5eb9b9f5c5 | |||
| bb53beb22d | |||
| 551c86264a | |||
| 04fd84757c | |||
| 6f6545ce52 | |||
| c9c8388250 | |||
| 9f0a30a040 | |||
| 843d87422d | |||
| baf94b4feb | |||
| 68733eb4f9 | |||
| bf2d668d3c | |||
| fdea5bb610 | |||
| 1b31c61aac | |||
| e8a55a0f85 | |||
| 6e45604d93 | |||
| 02472f19cb | |||
| edfe935fb4 | |||
| c97cc2823c | |||
| 40dbafe851 | |||
| 6aaa328a24 | |||
| 0ce14c8822 | |||
| dbd8764b0d | |||
| 944673cac1 | |||
| 66d0721c12 | |||
| e4893a6306 | |||
| 8714bb6fd3 | |||
| daf023b403 | |||
| f3af6e2a53 | |||
| d1ab2d5172 | |||
| 9f255f13dd | |||
| b70ce510ef | |||
| b6d116ec7a | |||
| f99900ac40 | |||
| 5a97e14f3e | |||
| 08a61fd4ae | |||
| af7a397816 | |||
| 3d11b91869 | |||
| ff83f6eebc | |||
| f41af0bf1c | |||
| d092f213a7 | |||
| 5214794f95 | |||
| 9eb10ba771 | |||
| db8a9296a7 | |||
| f4361e3eeb | |||
| 23ba725c89 | |||
| 44546d1a96 | |||
| d3a44b23db | |||
| 4abe8a6ca9 | |||
| f5bdaee886 | |||
| bb0f328f2f | |||
| b733e551a0 | |||
| aaa72c7961 | |||
| 823aeda42a | |||
| 886f7740f2 | |||
| 79962d2cf3 | |||
| 88f7f0cfca | |||
| d339971c26 | |||
| 2e0bde9cc2 | |||
| 1ee9eb02c3 | |||
| 12e44ab26d | |||
| 4b3373a68d | |||
| 576f6fbcfc | |||
| 0d2ce9c126 | |||
| 0b91d26f71 | |||
| 68e03ccd97 | |||
| aa966114b1 | |||
| 6975da8575 | |||
| ef4b2f17ca | |||
| d84a265b67 | |||
| fd6391b734 | |||
| 0d27e13275 | |||
| 279648de56 | |||
| e3e53ff7f5 | |||
| 5ef6affabf | |||
| f5f302b97e | |||
| 189b27e076 | |||
| f68197b775 | |||
| 75a64c5d24 | |||
| 43fa1ad1f3 | |||
| 7f225c7407 | |||
| 25879dd007 | |||
| 27921213b0 | |||
| 2cfc1a490f | |||
| 99f13817f8 | |||
| 3570a6900e | |||
| 7bbb5663c9 | |||
| 9027708a61 | |||
| 299b20acc5 | |||
| dda022d3c3 | |||
| 5e66600727 | |||
| 4a3afdfb48 | |||
| 3163912266 | |||
| 6cc3382526 | |||
| 11a50c02cd | |||
| afb191f90a | |||
| b29c54f126 | |||
| 68d8a97db5 | |||
| 27a00f026a | |||
| 6c26d4739e | |||
| 5680ab515e | |||
| 6571fc9029 | |||
| 2ad9e049f3 | |||
| 799a4d6b8b | |||
| 3db84d07e3 | |||
| 444088baf3 | |||
| 86188e6611 | |||
| 30e40dc34c | |||
| 8913138dc3 | |||
| 2d52bfac80 | |||
| 5fdfc67438 | |||
| 2a3f36d34f | |||
| 75aa4b1391 | |||
| e82fd15bb7 | |||
| 090b9c6215 | |||
| 38f6bc240e | |||
| c1647822fb | |||
| d6d1ac5818 | |||
| e1c14977e6 | |||
| 05586242f0 | |||
| ae0c44e20d | |||
| 806bb074ab | |||
| 814fe67a21 | |||
| 659c0969fe | |||
| 3b494932c7 | |||
| fc6f85e76c | |||
| 65594c28bd | |||
| a1096155b8 | |||
| 6547029a89 | |||
| d87081205d | |||
| d7fa596e68 | |||
| 2a3d264c8f | |||
| 6745262412 | |||
| 5a0d18cf99 | |||
| 1092816359 | |||
| f580e4542d | |||
| 99eb16dbd8 | |||
| d520ba6904 | |||
| d3753f1aee | |||
| 8e1492e4f0 | |||
| d4a76f05d2 | |||
| 5e4f885f80 | |||
| e62a3f3351 | |||
| 81f7a7c451 | |||
| ff1bcd69d2 | |||
| eb6788091d | |||
| 96ab7e997c | |||
| 43cd98f2d5 | |||
| 22b2db34fc | |||
| 0d5b20c0db | |||
| a4cd966370 | |||
| 7223b54ec4 | |||
| 8b069294b7 | |||
| df99eb5fb5 | |||
| 3c0c62997f | |||
| 4904a86e03 | |||
| a268a93027 | |||
| 7fb87d6030 | |||
| fa9e6be36d | |||
| 5137d5ed17 | |||
| e526d6af76 | |||
| e81343ae91 | |||
| ea429b2694 | |||
| 21894334f8 | |||
| f688a504e1 | |||
| 7bb6ee1154 | |||
| 88fe4bbe56 | |||
| eec57610dc | |||
| 3a740235ac | |||
| efe7a57e60 | |||
| c0ad50a7b5 | |||
| 65b911994c | |||
| 9deb58a38a | |||
| eb975b0133 | |||
| df28e6dfb8 | |||
| 4923b32bbe | |||
| 9f67de3677 |
@@ -1,5 +1,10 @@
|
||||
# Shell 脚本在仓库内统一 LF,避免 Linux 上 bash: pipefail: invalid option name(CRLF)
|
||||
*.sh text eol=lf
|
||||
deploy/** text eol=lf
|
||||
# 文档统一 LF,避免 Windows 编辑后产生 CRLF 脏 diff
|
||||
docs/** text eol=lf
|
||||
# XMind 为 ZIP 二进制;须覆盖上面 docs/** 的 text/eol,否则入库会损坏打不开
|
||||
*.xmind -text -diff -merge -eol
|
||||
docs/**/*.xmind -text -diff -merge -eol
|
||||
# .env 模板统一 LF,避免 Linux PM2 source 报 $'\r': command not found
|
||||
**/.env.example text eol=lf
|
||||
|
||||
@@ -15,14 +15,20 @@
|
||||
**/.env.backup*
|
||||
**/.env.bak
|
||||
**/.env.local
|
||||
|
||||
# Cursor 本机规则/配置(勿提交;只留本地)
|
||||
.cursor/
|
||||
|
||||
manual_trading_hub/hub_settings.json
|
||||
manual_trading_hub/hub_backup_state.json
|
||||
manual_trading_hub/hub_fund_history.json
|
||||
manual_trading_hub/hub_supervisor_state.json
|
||||
manual_trading_hub/hub_ai_summaries.json
|
||||
manual_trading_hub/hub_ai_chat.json
|
||||
manual_trading_hub/amp_stats_history.json
|
||||
manual_trading_hub/hub_ai_fund_history.json
|
||||
manual_trading_hub/data/
|
||||
backups/
|
||||
|
||||
# 数据库与上传(运行时生成)
|
||||
**/*.sqlite
|
||||
|
||||
@@ -1,66 +1,66 @@
|
||||
# AI 复盘与模型配置说明
|
||||
|
||||
四个 `crypto_monitor_*` 实例共用仓库根目录 **`ai_client.py`**(通过 `PYTHONPATH=..` 导入)。用于 **交易记录与复盘** 页的 AI 点评、短评建议,以及从复盘截图提取结构化 JSON。
|
||||
三个 `crypto_monitor_*` 实例共用仓库根目录 **`ai_client.py`**(通过 `PYTHONPATH=..` 导入).用于 **交易记录与复盘** 页的 AI 点评,短评建议,以及从复盘截图提取结构化 JSON.
|
||||
|
||||
---
|
||||
|
||||
## 一、二选一:`AI_PROVIDER`
|
||||
## 一,二选一:`AI_PROVIDER`
|
||||
|
||||
| 值 | 说明 |
|
||||
|----|------|
|
||||
| **`openai`**(默认) | OpenAI 兼容 **Chat Completions** 接口 |
|
||||
| **`ollama`** | 本机 Ollama **`/api/generate`**(流式 NDJSON) |
|
||||
| **`openai`**(默认) | OpenAI 兼容 **Chat Completions** 接口 |
|
||||
| **`ollama`** | 本机 Ollama **`/api/generate`**(流式 NDJSON) |
|
||||
|
||||
在对应子目录 **`.env`** 中设置(各所 `.env.example` 已含模板):
|
||||
在对应子目录 **`.env`** 中设置(各所 `.env.example` 已含模板):
|
||||
|
||||
```bash
|
||||
AI_PROVIDER=openai
|
||||
AI_TIMEOUT_SECONDS=120
|
||||
|
||||
# OpenAI 兼容网关(默认)
|
||||
# OpenAI 兼容网关(默认)
|
||||
OPENAI_API_BASE=https://op.bz121.com/v1
|
||||
OPENAI_API_KEY=你的密钥
|
||||
OPENAI_MODEL=gemma4:e4b
|
||||
|
||||
# 本机 Ollama(仅当 AI_PROVIDER=ollama)
|
||||
# 本机 Ollama(仅当 AI_PROVIDER=ollama)
|
||||
OLLAMA_API=http://127.0.0.1:11434/api/generate
|
||||
AI_MODEL=huihui_ai/deepseek-r1-abliterated:latest
|
||||
```
|
||||
|
||||
### OpenAI 兼容网关
|
||||
|
||||
- **Base URL**:`https://op.bz121.com/v1`(请求路径为 `{base}/chat/completions`)。
|
||||
- **API Key**:在 [op.bz121.com](https://op.bz121.com/) 登录后,于 **`gateway.json`** 页面复制(与网关账号一致)。
|
||||
- **默认模型**:`gemma4:e4b`(可通过 `OPENAI_MODEL` 覆盖)。
|
||||
- **Base URL**:`https://op.bz121.com/v1`(请求路径为 `{base}/chat/completions`).
|
||||
- **API Key**:在 [op.bz121.com](https://op.bz121.com/) 登录后,于 **`gateway.json`** 页面复制(与网关账号一致).
|
||||
- **默认模型**:`gemma4:e4b`(可通过 `OPENAI_MODEL` 覆盖).
|
||||
|
||||
### Ollama
|
||||
|
||||
- 需本机已安装并拉取对应模型;`AI_PROVIDER=ollama` 时使用 `OLLAMA_API` 与 `AI_MODEL`。
|
||||
- 四所 `app.py` **不再** 直连 Ollama;统一走 `ai_client.ai_generate` / `ai_review` / `ai_short_advice`。
|
||||
- 需本机已安装并拉取对应模型;`AI_PROVIDER=ollama` 时使用 `OLLAMA_API` 与 `AI_MODEL`.
|
||||
- 三所 `app.py` **不再** 直连 Ollama;统一走 `ai_client.ai_generate` / `ai_review` / `ai_short_advice`.
|
||||
|
||||
---
|
||||
|
||||
## 二、部署注意
|
||||
## 二,部署注意
|
||||
|
||||
1. **PM2 / 手工启动**:`ecosystem.config.cjs` 中 **`PYTHONPATH=..`** 必须包含仓库根,否则无法 `from ai_client import ...`。
|
||||
2. 修改 `.env` 后重启对应实例,例如:`pm2 restart crypto_binance`(名称以你机器为准)。
|
||||
3. **`git pull`** 不会改 `.env`;若 `.env.example` 新增 AI 变量,请手动补进本机 `.env`。
|
||||
4. **勿** 将含真实 `OPENAI_API_KEY` 的 `.env` 提交 Git。
|
||||
1. **PM2 / 手工启动**:`ecosystem.config.cjs` 中 **`PYTHONPATH=..`** 必须包含仓库根,否则无法 `from ai_client import ...`.
|
||||
2. 修改 `.env` 后重启对应实例,例如:`pm2 restart crypto_binance`(名称以你机器为准).
|
||||
3. **`git pull`** 不会改 `.env`;若 `.env.example` 新增 AI 变量,请手动补进本机 `.env`.
|
||||
4. **勿** 将含真实 `OPENAI_API_KEY` 的 `.env` 提交 Git.
|
||||
|
||||
---
|
||||
|
||||
## 三、功能入口(网页)
|
||||
## 三,功能入口(网页)
|
||||
|
||||
登录后进入 **「交易记录与复盘」**:
|
||||
登录后进入 **「交易记录与复盘」**:
|
||||
|
||||
- 单条记录 **AI 复盘** / **短评**(依赖上述配置)。
|
||||
- 上传复盘图后 **从图片提取** 字段(内部调用 `ai_generate`,与所选 provider 一致)。
|
||||
- 单条记录 **AI 复盘** / **短评**(依赖上述配置).
|
||||
- 上传复盘图后 **从图片提取** 字段(内部调用 `ai_generate`,与所选 provider 一致).
|
||||
|
||||
若请求超时或返回错误,请检查:密钥是否有效、网关是否可达、`AI_TIMEOUT_SECONDS` 是否过短、Ollama 是否已启动(仅 ollama 模式)。
|
||||
若请求超时或返回错误,请检查:密钥是否有效,网关是否可达,`AI_TIMEOUT_SECONDS` 是否过短,Ollama 是否已启动(仅 ollama 模式).
|
||||
|
||||
---
|
||||
|
||||
## 四、相关文件
|
||||
## 四,相关文件
|
||||
|
||||
| 路径 | 说明 |
|
||||
|------|------|
|
||||
|
||||
@@ -1,88 +1,91 @@
|
||||
# 复盘交易系统(crypto_monitor)
|
||||
|
||||
多交易所 **USDT 永续** 的下单监控、**关键位**、**策略交易**、**止盈止损 / 移动保本** 与 **AI 复盘**,四所独立部署 + 可选 **中控** 聚合监控。
|
||||
|
||||
**远程仓库**:[https://git.bz121.com/dekun/crypto_monitor.git](https://git.bz121.com/dekun/crypto_monitor.git)
|
||||
|
||||
---
|
||||
|
||||
## 部署环境(必读)
|
||||
|
||||
| 项 | 约定 |
|
||||
|----|------|
|
||||
| 系统 | **Ubuntu 22.04 / 24.04** |
|
||||
| 用户 | **root** |
|
||||
| 路径 | **`/opt/crypto_monitor`** |
|
||||
| 进程 | **PM2**(唯一推荐的常驻方式) |
|
||||
|
||||
**环境详解**(Python 3.10+、Node、PM2 安装与启动顺序):**[docs/ubuntu-server.md](./docs/ubuntu-server.md)**
|
||||
**一键 venv**:`bash deploy/setup_env.sh` → **[deploy/README.md](./deploy/README.md)**
|
||||
|
||||
```bash
|
||||
cd /opt
|
||||
git clone https://git.bz121.com/dekun/crypto_monitor.git crypto_monitor
|
||||
cd /opt/crypto_monitor
|
||||
bash deploy/setup_env.sh --install-system-deps
|
||||
```
|
||||
|
||||
配置与运维脚本: **[docs/env-sync-scripts.md](./docs/env-sync-scripts.md)** · **[备份与恢复.md](./备份与恢复.md)**
|
||||
|
||||
---
|
||||
|
||||
## 功能导航
|
||||
|
||||
| 功能 | 说明 | 文档 |
|
||||
|------|------|------|
|
||||
| **关键位监控** | 箱体/收敛自动开仓、阻力支撑提醒、斐波限价;止盈止损方案与 **移动保本** 开关 | 各所 [关键位自动下单说明.md](./crypto_monitor_binance/关键位自动下单说明.md)(Gate/OKX 目录内同名);方案细则 **[关键位止盈止损与移动保本更新说明.md](./关键位止盈止损与移动保本更新说明.md)** |
|
||||
| **实盘下单 / 下单监控** | 首仓、以损定仓;监控内 **止盈 / 止损**、**移动保本**(步进 R、偏移%) | 各所 [使用说明.md](./crypto_monitor_binance/使用说明.md) · 顶栏「实盘下单」`/trade` |
|
||||
| **策略交易** | **趋势回调** + **顺势加仓**(`/strategy` 双栏) | **[策略交易说明.md](./策略交易说明.md)** · 趋势细则 [crypto_monitor_gate_bot/趋势回调策略说明.md](./crypto_monitor_gate_bot/趋势回调策略说明.md) |
|
||||
| **策略交易记录** | 已结束计划快照(最近 100 条)、筛选与展开详情 | [策略交易说明.md §五](./策略交易说明.md) · 顶栏 `/strategy/records` |
|
||||
| **交易复盘** | 平仓记录、错过机会、图表;**AI 点评** | **[AI复盘与模型配置说明.md](./AI复盘与模型配置说明.md)** · 顶栏「交易记录与复盘」`/records` |
|
||||
| **中控** | 多账户持仓/委托聚合、行情 K 线、紧急全平(**不在中控网页下单**) | [manual_trading_hub/使用说明.md](./manual_trading_hub/使用说明.md) · [部署文档.md](./manual_trading_hub/部署文档.md) |
|
||||
|
||||
其它专题:[计仓模式](./docs/position-sizing-mode.md) · [每日自动划转](./docs/auto-transfer-daily.md) · [Chrome 快捷方式图标](./docs/shortcut-icon.md)
|
||||
|
||||
---
|
||||
|
||||
## 仓库目录
|
||||
|
||||
| 目录 | 交易所 / 角色 | 部署文档 |
|
||||
|------|----------------|----------|
|
||||
| `crypto_monitor_binance/` | Binance U 本位永续 | [部署文档.md](./crypto_monitor_binance/部署文档.md) |
|
||||
| `crypto_monitor_gate/` | Gate 主号 | [部署文档.md](./crypto_monitor_gate/部署文档.md) |
|
||||
| `crypto_monitor_gate_bot/` | Gate 机器人 / 趋势户 | [部署文档.md](./crypto_monitor_gate_bot/部署文档.md) |
|
||||
| `crypto_monitor_okx/` | OKX 永续 | [部署文档.md](./crypto_monitor_okx/部署文档.md) |
|
||||
| `manual_trading_hub/` | 中控 + 子代理 | [部署文档.md](./manual_trading_hub/部署文档.md) |
|
||||
| `lib/` | **共用模块**(策略、关键位、交易、中控库、AI、静态与模板) | **[docs/lib-structure.md](./docs/lib-structure.md)** |
|
||||
| `brand/` | 各所共用图标与 manifest | — |
|
||||
| `docs/`、`deploy/`、`scripts/`、`tests/` | 文档、环境、脚本、单元测试 | — |
|
||||
|
||||
共用代码 import 示例:`from lib.strategy.strategy_db import init_strategy_tables`(各所启动时仍将仓库根加入 `PYTHONPATH`)。详见 **[docs/lib-structure.md](./docs/lib-structure.md)**。
|
||||
|
||||
---
|
||||
|
||||
## 技术要点
|
||||
|
||||
- **Python 3.10+**、Flask、ccxt、SQLite(`crypto.db`)
|
||||
- 四所 `.env` 前缀不同(`BINANCE_*` / `GATE_*` / `OKX_*`),**不可混用**
|
||||
- 实盘须 `LIVE_TRADING_ENABLED=true` 且理解 API 权限与 IP 白名单风险
|
||||
- 经 **SOCKS** 访问交易所时配置各所 `*_SOCKS_PROXY` 并安装 PySocks
|
||||
|
||||
---
|
||||
|
||||
## 推荐阅读顺序
|
||||
|
||||
1. [docs/ubuntu-server.md](./docs/ubuntu-server.md) — 装 Python / Node / PM2,PM2 启动四所 + 中控
|
||||
2. 各所 **`.env`**(从 `.env.example` 复制)
|
||||
3. 所用功能对应上表 **功能导航** 文档
|
||||
4. [备份与恢复.md](./备份与恢复.md) — 生产机备份习惯
|
||||
|
||||
---
|
||||
|
||||
## 安全
|
||||
|
||||
- **勿** 将 `.env`、API Secret、`.pem` 提交 Git
|
||||
- 公网暴露中控须配置登录、`HUB_BRIDGE_TOKEN`、HTTPS Cookie
|
||||
- 实盘风险由使用者自行承担
|
||||
|
||||
若子目录 README 与本文冲突,以 **子目录《部署文档》与当前代码** 为准。
|
||||
# 复盘交易系统(crypto_monitor)
|
||||
|
||||
多交易所 **USDT 永续** 的下单监控,**关键位**,**策略交易**,**止盈止损 / 移动保本** 与 **AI 复盘**,三所独立部署 + 可选 **中控** 聚合监控.
|
||||
|
||||
**远程仓库**:[https://git.bz121.com/dekun/crypto_monitor.git](https://git.bz121.com/dekun/crypto_monitor.git)
|
||||
|
||||
---
|
||||
|
||||
## 部署环境(必读)
|
||||
|
||||
| 项 | 约定 |
|
||||
|----|------|
|
||||
| 系统 | **Ubuntu 22.04 / 24.04** |
|
||||
| 用户 | **root** |
|
||||
| 路径 | **`/opt/crypto_monitor`** |
|
||||
| 进程 | **PM2**(唯一推荐的常驻方式) |
|
||||
|
||||
**环境详解**(Python 3.10+,Node,PM2 安装与启动顺序):**[docs/ubuntu-server.md](./docs/ubuntu-server.md)**
|
||||
**一键部署管理器**:`curl -fsSL .../deploy/manage.sh | bash` → **[deploy/README.md](./deploy/README.md)**
|
||||
|
||||
```bash
|
||||
# 新服务器(推荐)
|
||||
curl -fsSL https://git.bz121.com/dekun/crypto_monitor/raw/branch/main/deploy/manage.sh | bash
|
||||
|
||||
# 或手动 clone
|
||||
cd /opt
|
||||
git clone https://git.bz121.com/dekun/crypto_monitor.git crypto_monitor
|
||||
cd /opt/crypto_monitor
|
||||
bash deploy/manage.sh
|
||||
```
|
||||
|
||||
配置与运维脚本: **[docs/env-sync-scripts.md](./docs/env-sync-scripts.md)** · **[备份与恢复.md](./备份与恢复.md)**
|
||||
|
||||
---
|
||||
|
||||
## 功能导航
|
||||
|
||||
| 功能 | 说明 | 文档 |
|
||||
|------|------|------|
|
||||
| **关键位监控** | 箱体/收敛自动开仓,阻力支撑提醒,斐波限价;止盈止损方案与 **移动保本** 开关 | 各所 [关键位自动下单说明.md](./crypto_monitor_binance/关键位自动下单说明.md)(Gate/OKX 目录内同名);方案细则 **[关键位止盈止损与移动保本更新说明.md](./关键位止盈止损与移动保本更新说明.md)** |
|
||||
| **实盘下单 / 下单监控** | 首仓,以损定仓;监控内 **止盈 / 止损**,**移动保本**(步进 R,偏移%) | 各所 [使用说明.md](./crypto_monitor_binance/使用说明.md) · 顶栏「实盘下单」`/trade` |
|
||||
| **策略交易** | **趋势回调** + **顺势加仓**(`/strategy` 双栏) | **[策略交易说明.md](./策略交易说明.md)** · 趋势细则 [docs/trend-pullback-strategy.md](./docs/trend-pullback-strategy.md) |
|
||||
| **策略交易记录** | 已结束计划快照(最近 100 条),筛选与展开详情 | [策略交易说明.md §五](./策略交易说明.md) · 顶栏 `/strategy/records` |
|
||||
| **交易复盘** | 平仓记录,错过机会,图表;**AI 点评** | **[AI复盘与模型配置说明.md](./AI复盘与模型配置说明.md)** · 顶栏「交易记录与复盘」`/records` |
|
||||
| **中控** | 多账户持仓/委托聚合,行情 K 线,紧急全平(**不在中控网页下单**) | [manual_trading_hub/使用说明.md](./manual_trading_hub/使用说明.md) · [部署文档.md](./manual_trading_hub/部署文档.md) |
|
||||
|
||||
其它专题:[计仓模式](./docs/position-sizing-mode.md) · [每日自动划转](./docs/auto-transfer-daily.md) · [Chrome 快捷方式图标](./docs/shortcut-icon.md)
|
||||
|
||||
---
|
||||
|
||||
## 仓库目录
|
||||
|
||||
| 目录 | 交易所 / 角色 | 部署文档 |
|
||||
|------|----------------|----------|
|
||||
| `crypto_monitor_binance/` | Binance U 本位永续 | [部署文档.md](./crypto_monitor_binance/部署文档.md) |
|
||||
| `crypto_monitor_gate/` | Gate | [部署文档.md](./crypto_monitor_gate/部署文档.md) |
|
||||
| `crypto_monitor_okx/` | OKX 永续 | [部署文档.md](./crypto_monitor_okx/部署文档.md) |
|
||||
| `manual_trading_hub/` | 中控 + 子代理 | [部署文档.md](./manual_trading_hub/部署文档.md) |
|
||||
| `lib/` | **共用模块**(策略,关键位,交易,中控库,AI,静态与模板) | **[docs/lib-structure.md](./docs/lib-structure.md)** |
|
||||
| `brand/` | 各所共用图标与 manifest | — |
|
||||
| `docs/`,`deploy/`,`scripts/`,`tests/` | 文档,环境,脚本,单元测试 | — |
|
||||
|
||||
共用代码 import 示例:`from lib.strategy.strategy_db import init_strategy_tables`(各所启动时仍将仓库根加入 `PYTHONPATH`).详见 **[docs/lib-structure.md](./docs/lib-structure.md)**.
|
||||
|
||||
---
|
||||
|
||||
## 技术要点
|
||||
|
||||
- **Python 3.10+**,Flask,ccxt,SQLite(`crypto.db`)
|
||||
- 三所 `.env` 前缀不同(`BINANCE_*` / `GATE_*` / `OKX_*`),**不可混用**
|
||||
- 实盘须 `LIVE_TRADING_ENABLED=true` 且理解 API 权限与 IP 白名单风险
|
||||
- 经 **SOCKS** 访问交易所时配置各所 `*_SOCKS_PROXY` 并安装 PySocks
|
||||
|
||||
---
|
||||
|
||||
## 推荐阅读顺序
|
||||
|
||||
1. [docs/ubuntu-server.md](./docs/ubuntu-server.md) — 装 Python / Node / PM2,PM2 启动三所 + 中控
|
||||
2. 各所 **`.env`**(从 `.env.example` 复制)
|
||||
3. 所用功能对应上表 **功能导航** 文档
|
||||
4. [备份与恢复.md](./备份与恢复.md) — 生产机备份习惯
|
||||
|
||||
---
|
||||
|
||||
## 安全
|
||||
|
||||
- **勿** 将 `.env`,API Secret,`.pem` 提交 Git
|
||||
- 公网暴露中控须配置登录,`HUB_BRIDGE_TOKEN`,HTTPS Cookie
|
||||
- 实盘风险由使用者自行承担
|
||||
|
||||
若子目录 README 与本文冲突,以 **子目录《部署文档》与当前代码** 为准.
|
||||
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 150 B |
|
After Width: | Height: | Size: 127 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 301 B |
|
After Width: | Height: | Size: 389 B |
|
After Width: | Height: | Size: 4.9 KiB |
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<rect width="512" height="512" rx="108" fill="#0c1019"/>
|
||||
<rect x="36" y="36" width="440" height="440" rx="88" fill="#141b2d"/>
|
||||
<rect x="36" y="36" width="440" height="440" rx="88" fill="none" stroke="#F0B90B" stroke-width="12"/>
|
||||
<polygon points="256,150 362,256 256,362 150,256" fill="#F0B90B"/><polygon points="256,210 302,256 256,302 210,256" fill="#1a160a"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 440 B |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 287 B |
|
After Width: | Height: | Size: 265 B |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 507 B |
|
After Width: | Height: | Size: 747 B |
|
After Width: | Height: | Size: 8.6 KiB |
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<rect width="512" height="512" rx="108" fill="#0c1019"/>
|
||||
<rect x="36" y="36" width="440" height="440" rx="88" fill="#141b2d"/>
|
||||
<rect x="36" y="36" width="440" height="440" rx="88" fill="none" stroke="#17E6A1" stroke-width="12"/>
|
||||
<text x="256" y="310" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="220" font-weight="700" fill="#17E6A1">G</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 451 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 133 B |
|
After Width: | Height: | Size: 108 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 254 B |
|
After Width: | Height: | Size: 290 B |
|
After Width: | Height: | Size: 3.8 KiB |
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<rect width="512" height="512" rx="108" fill="#0c1019"/>
|
||||
<rect x="36" y="36" width="440" height="440" rx="88" fill="#141b2d"/>
|
||||
<rect x="36" y="36" width="440" height="440" rx="88" fill="none" stroke="#FFFFFF" stroke-width="12"/>
|
||||
<rect x="168" y="168" width="72" height="72" rx="10" fill="#FFFFFF"/><rect x="272" y="168" width="72" height="72" rx="10" fill="#FFFFFF"/><rect x="168" y="272" width="72" height="72" rx="10" fill="#FFFFFF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 515 B |
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "Binance 交易系统",
|
||||
"short_name": "Binance 交易系统",
|
||||
"description": "Binance 永续交易监控与复盘",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#0b0d14",
|
||||
"theme_color": "#F0B90B",
|
||||
"icons": [
|
||||
{
|
||||
"src": "__ICON_PREFIX__/icon-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "__ICON_PREFIX__/icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "交易监控复盘",
|
||||
"short_name": "监控",
|
||||
"description": "加密货币永续交易监控与复盘",
|
||||
"name": "交易系统",
|
||||
"short_name": "交易系统",
|
||||
"description": "加密货币永续交易监控与复盘(请使用各所独立 manifest)",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#0b0d14",
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "Gate 交易系统",
|
||||
"short_name": "Gate 交易系统",
|
||||
"description": "Gate 永续交易监控与复盘",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#0b0d14",
|
||||
"theme_color": "#17E6A1",
|
||||
"icons": [
|
||||
{
|
||||
"src": "__ICON_PREFIX__/icon-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "__ICON_PREFIX__/icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,20 +1,20 @@
|
||||
{
|
||||
"name": "交易监控复盘",
|
||||
"short_name": "监控",
|
||||
"description": "加密货币永续交易监控与复盘",
|
||||
"name": "OKX 交易系统",
|
||||
"short_name": "OKX 交易系统",
|
||||
"description": "OKX 永续交易监控与复盘",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#0b0d14",
|
||||
"theme_color": "#0b0d14",
|
||||
"theme_color": "#FFFFFF",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/static/icons/icon-192.png",
|
||||
"src": "__ICON_PREFIX__/icon-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/static/icons/icon-512.png",
|
||||
"src": "__ICON_PREFIX__/icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
@@ -1,23 +1,23 @@
|
||||
{
|
||||
"name": "复盘系统中控",
|
||||
"short_name": "中控",
|
||||
"description": "四所交易监控与行情中控",
|
||||
"start_url": "/monitor",
|
||||
"display": "standalone",
|
||||
"background_color": "#0b0e18",
|
||||
"theme_color": "#0b0e18",
|
||||
"icons": [
|
||||
{
|
||||
"src": "__ICON_PREFIX__/icon-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "__ICON_PREFIX__/icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
}
|
||||
]
|
||||
}
|
||||
{
|
||||
"name": "复盘系统中控",
|
||||
"short_name": "中控",
|
||||
"description": "三所交易监控与行情中控",
|
||||
"start_url": "/monitor",
|
||||
"display": "standalone",
|
||||
"background_color": "#0b0e18",
|
||||
"theme_color": "#0b0e18",
|
||||
"icons": [
|
||||
{
|
||||
"src": "__ICON_PREFIX__/icon-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "__ICON_PREFIX__/icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "any maskable"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,206 +1,237 @@
|
||||
# =============================================================================
|
||||
# 环境配置模板(可提交 Git)。程序运行时只读取同目录下的 .env。
|
||||
# 环境配置模板(可提交 Git).程序运行时只读取同目录下的 .env.
|
||||
#
|
||||
# 首次部署 / 新机:
|
||||
# 首次部署 / 新机:
|
||||
# cp .env.example .env
|
||||
# nano .env # 填入真实密钥、端口、代理等
|
||||
# nano .env # 填入真实密钥,端口,代理等
|
||||
#
|
||||
# 升级代码(git pull)前建议备份(.env 不在 Git 中,pull 不会覆盖):
|
||||
# 升级代码(git pull)前建议备份(.env 不在 Git 中,pull 不会覆盖):
|
||||
# cp .env .env.backup.$(date +%Y%m%d)
|
||||
#
|
||||
# 从备份恢复:
|
||||
# 从备份恢复:
|
||||
# cp .env.backup.YYYYMMDD .env
|
||||
# =============================================================================
|
||||
|
||||
APP_ENV=production
|
||||
# 服务监听地址(云服务器通常用 0.0.0.0)
|
||||
# 服务监听地址(云服务器通常用 0.0.0.0)
|
||||
APP_HOST=0.0.0.0
|
||||
# 服务端口
|
||||
APP_PORT=5001
|
||||
# 是否开启调试模式(生产建议 false)
|
||||
# 是否开启调试模式(生产建议 false)
|
||||
APP_DEBUG=false
|
||||
|
||||
# 登录账号
|
||||
APP_USERNAME=admin
|
||||
# 登录密码(请改成你自己的强密码)
|
||||
# 登录密码(请改成你自己的强密码)
|
||||
APP_PASSWORD=admin123
|
||||
# 是否关闭登录校验(局域网可设 true;公网务必 false)
|
||||
# 是否关闭登录校验(局域网可设 true;公网务必 false)
|
||||
APP_AUTH_DISABLED=true
|
||||
# --- 多账户交易中控 manual_trading_hub ---
|
||||
# 中控请求本实例 /api/hub/* 时携带请求头 X-Hub-Token,须与中控启动环境变量 HUB_BRIDGE_TOKEN 一致
|
||||
# 未设置且 APP_AUTH_DISABLED=false 时,仅网页登录后可访问;本机联调可保持 APP_AUTH_DISABLED=true
|
||||
# 中控请求本实例 /api/hub/* 时携带请求头 X-Hub-Token,须与中控启动环境变量 HUB_BRIDGE_TOKEN 一致
|
||||
# 未设置且 APP_AUTH_DISABLED=false 时,仅网页登录后可访问;本机联调可保持 APP_AUTH_DISABLED=true
|
||||
# HUB_BRIDGE_TOKEN=your-long-random-token
|
||||
# Flask 会话密钥(必须替换为长随机字符串)
|
||||
# Flask 会话密钥(必须替换为长随机字符串)
|
||||
FLASK_SECRET_KEY=CHANGE_TO_LONG_RANDOM_SECRET
|
||||
|
||||
# 企业微信机器人 Webhook(用于行情/风控推送)
|
||||
# 企业微信机器人 Webhook(用于行情/风控推送)
|
||||
WECHAT_WEBHOOK=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=REPLACE_WITH_REAL_KEY
|
||||
|
||||
# 数据库文件路径(相对路径会自动按项目目录解析)
|
||||
# 数据库文件路径(相对路径会自动按项目目录解析)
|
||||
DB_PATH=crypto.db
|
||||
# 交易截图上传目录
|
||||
UPLOAD_DIR=static/images
|
||||
|
||||
# 自动备份(scripts/backup_data.sh + cron,可选;默认即可)
|
||||
# 自动备份(scripts/backup_data.sh + cron,可选;默认即可)
|
||||
# BACKUP_ROOT=/root/backups
|
||||
# BACKUP_RETENTION_DAYS=30
|
||||
# BACKUP_INSTANCE=crypto_monitor_binance
|
||||
|
||||
# 已废弃:资金账户仅显示交易所 funding 余额,不再读取此变量
|
||||
# 已废弃:资金账户仅显示交易所 funding 余额,不再读取此变量
|
||||
# TOTAL_CAPITAL=100
|
||||
# 页顶「资金账户」默认仅 Binance Funding 钱包;若 USDT 主要在现货,可改为 true 合并 Spot
|
||||
# 页顶「资金账户」默认仅 Binance Funding 钱包;若 USDT 主要在现货,可改为 true 合并 Spot
|
||||
# BINANCE_FUNDING_INCLUDE_SPOT=false
|
||||
# 计仓:risk=以损定仓(默认);full_margin=合约可用×FULL_MARGIN_BUFFER_RATIO 全仓杠杆(须无仓后重启)
|
||||
# 计仓:risk=以损定仓(默认);full_margin=合约可用×FULL_MARGIN_BUFFER_RATIO 全仓杠杆(须无仓后重启)
|
||||
POSITION_SIZING_MODE=risk
|
||||
# 每天起始基数(U)
|
||||
# 方向限制(默认 false=双向均可;true 时按 TRADE_DIRECTION 限制,修改后须重启)
|
||||
# TRADE_DIRECTION=long_only | short_only | both(或 多/空/双向)
|
||||
TRADE_DIRECTION_RESTRICT_ENABLED=false
|
||||
TRADE_DIRECTION=both
|
||||
# 币种白名单(默认 false=全币种可手输;true 时关键位/下单/策略仅下拉选择)
|
||||
TRADE_SYMBOL_RESTRICT_ENABLED=false
|
||||
TRADE_SYMBOL_WHITELIST=BTC,ETH
|
||||
# 每天起始基数(U)
|
||||
DAILY_START_CAPITAL=30
|
||||
# 日内回撤后基数(U)
|
||||
# 日内回撤后基数(U)
|
||||
DAILY_LOSS_CAPITAL=20
|
||||
# 日内盈利后基数(U)
|
||||
# 日内盈利后基数(U)
|
||||
DAILY_PROFIT_CAPITAL=50
|
||||
# BTC 默认杠杆倍数
|
||||
BTC_LEVERAGE=10
|
||||
# 山寨币默认杠杆倍数
|
||||
ALT_LEVERAGE=5
|
||||
# 交易日重置小时(北京时间)
|
||||
# 交易日重置小时(北京时间)
|
||||
TRADING_DAY_RESET_HOUR=8
|
||||
# 整点前禁止新开仓:true=启用(默认),false=关闭(仍可保留 8 点作为交易日划分)
|
||||
# 整点前禁止新开仓:true=启用(默认),false=关闭(仍可保留 8 点作为交易日划分)
|
||||
TRADING_DAY_RESET_OPEN_GUARD_ENABLED=true
|
||||
|
||||
# 是否开启 Binance 实盘下单(false=只做本地流程,true=真实下单)
|
||||
# 是否开启 Binance 实盘下单(false=只做本地流程,true=真实下单)
|
||||
LIVE_TRADING_ENABLED=true
|
||||
# Binance API Key(需开通合约、万向划转等权限)
|
||||
# Binance API Key(需开通合约,万向划转等权限)
|
||||
BINANCE_API_KEY=REPLACE_WITH_BINANCE_API_KEY
|
||||
# Binance API Secret
|
||||
BINANCE_API_SECRET=REPLACE_WITH_BINANCE_API_SECRET
|
||||
# 保证金模式:cross=全仓,isolated=逐仓
|
||||
# 保证金模式:cross=全仓,isolated=逐仓
|
||||
BINANCE_MARGIN_MODE=cross
|
||||
# 持仓模式:hedge=双向(需账户开启双向持仓,下单带 positionSide);oneway=单向
|
||||
# 持仓模式:hedge=双向(需账户开启双向持仓,下单带 positionSide);oneway=单向
|
||||
BINANCE_POSITION_MODE=hedge
|
||||
# 条件单触发参考价:CONTRACT_PRICE=最新成交价 MARK_PRICE=标记价(更易触发时用标记价)
|
||||
# 条件单触发参考价:CONTRACT_PRICE=最新成交价 MARK_PRICE=标记价(更易触发时用标记价)
|
||||
BINANCE_TRIGGER_WORKING_TYPE=CONTRACT_PRICE
|
||||
# 页面与浏览器标签展示的交易所名称(多环境区分时可改成例如 Binance·测试网)
|
||||
# EXCHANGE_DISPLAY_NAME=Binance
|
||||
# 页面与浏览器标签展示的交易所名称(多环境区分时可改成例如 Binance·测试网)
|
||||
EXCHANGE_DISPLAY_NAME=Binance
|
||||
# 企业微信推送里展示的账户备注
|
||||
# BINANCE_ACCOUNT_LABEL=binance实盘账户
|
||||
# 平仓盈亏估算:false=按仓位历史口径(已实现盈亏+手续费,不含资金费);true=含资金费
|
||||
# 平仓盈亏估算:false=按仓位历史口径(已实现盈亏+手续费,不含资金费);true=含资金费
|
||||
# BINANCE_PNL_INCLUDE_FUNDING=false
|
||||
|
||||
# =============================================================================
|
||||
# 关键位门控(页面「关键位监控」规则条与 _key_hard_checks 共用)
|
||||
# 关键位程序自动下单(与 POSITION_SIZING_MODE 联动,修改后须重启 PM2)
|
||||
# =============================================================================
|
||||
# 【周期】门控 K 线周期,如 5m、15m;仅影响关键位硬条件,不改变顶栏分区
|
||||
# 默认 false = 关闭所有关键位程序自动单(箱体/收敛/斐波/假突破/触价)
|
||||
#
|
||||
# POSITION_SIZING_MODE=risk(以损定仓)
|
||||
# false → 不执行任何关键位自动单;支撑/阻力提醒,人工下单,顺势加仓不受影响
|
||||
# true → 允许关键位全套自动(含触价)
|
||||
#
|
||||
# POSITION_SIZING_MODE=full_margin(全仓杠杆,须无仓切换)
|
||||
# false → 不执行触价自动单
|
||||
# true → 仅回调/突破触价可程序自动开仓;箱体/斐波等仍禁止
|
||||
#
|
||||
# 顺势加仓,趋势回调不受本开关控制;全仓模式下策略自动仍禁止.
|
||||
KEY_AUTO_ORDER_ENABLED=false
|
||||
|
||||
# =============================================================================
|
||||
# 关键位门控(页面「关键位监控」规则条与 _key_hard_checks 共用)
|
||||
# =============================================================================
|
||||
# 【周期】门控 K 线周期,如 5m,15m;仅影响关键位硬条件,不改变顶栏分区
|
||||
KLINE_TIMEFRAME=5m
|
||||
# 【确认K】闭合 K 序列中的棒偏移:突破棒默认 -2(倒数第2根),确认棒默认 -1(倒数第1根)
|
||||
# 【确认K】闭合 K 序列中的棒偏移:突破棒默认 -2(倒数第2根),确认棒默认 -1(倒数第1根)
|
||||
KEY_CONFIRM_BREAKOUT_BAR=-2
|
||||
KEY_CONFIRM_BAR=-1
|
||||
# 【量能】突破棒成交量 > 前 N 根均量 × 倍数(默认 N=20,倍数=1.3 即放大 30%)
|
||||
# 【量能】突破棒成交量 > 前 N 根均量 × 倍数(默认 N=20,倍数=1.3 即放大 30%)
|
||||
KEY_VOLUME_MA_BARS=20
|
||||
KEY_VOLUME_RATIO_MIN=1.3
|
||||
# 【箱体/收敛】突破K收盘越过关键位(占该侧价格%)的下限;无上限(过猛由计划RR过滤)
|
||||
# 【箱体/收敛】突破K收盘越过关键位(占该侧价格%)的下限;无上限(过猛由计划RR过滤)
|
||||
KEY_BREAKOUT_AMP_MIN_PCT=0.03
|
||||
# 已不参与门控,可保留配置项兼容旧环境
|
||||
# 已不参与门控,可保留配置项兼容旧环境
|
||||
KEY_BREAKOUT_AMP_MAX_PCT=0.5
|
||||
# 【阻力/支撑】突破后微信提醒次数与间隔(分钟)
|
||||
# 【阻力/支撑】突破后微信提醒次数与间隔(分钟)
|
||||
KEY_ALERT_MAX_TIMES=3
|
||||
KEY_ALERT_INTERVAL_MINUTES=5
|
||||
# 【日成交量排名】品种须在该排名前 N 名(添加关键位与运行时门控均校验)
|
||||
# 【日成交量排名】品种须在该排名前 N 名(添加关键位与运行时门控均校验)
|
||||
KEY_DAILY_VOLUME_RANK_MAX=30
|
||||
# 【关键位自动开仓盈亏比】按确认K收盘 E 计算,严格大于该值才市价开仓(如 1.5 表示须 >1.5:1)
|
||||
# 【关键位自动开仓盈亏比】按确认K收盘 E 计算,严格大于该值才市价开仓(如 1.5 表示须 >1.5:1)
|
||||
KEY_AUTO_MIN_PLANNED_RR=1.5
|
||||
# 止损:突破 K 极值向外缓冲的百分比(默认 0.5 即 0.5%)
|
||||
# 止损:突破 K 极值向外缓冲的百分比(默认 0.5 即 0.5%)
|
||||
KEY_STOP_OUTSIDE_BREAKOUT_PCT=0.5
|
||||
# 趋势单方案:止损在突破 K 极值外侧的百分比(默认 1 即 1%)
|
||||
# 趋势单方案:止损在突破 K 极值外侧的百分比(默认 1 即 1%)
|
||||
KEY_TREND_STOP_OUTSIDE_PCT=1
|
||||
|
||||
# =============================================================================
|
||||
# 交易执行 / 人工风控(页面「实盘下单」)
|
||||
# 交易执行 / 人工风控(页面「实盘下单」)
|
||||
# =============================================================================
|
||||
# 【最大同时持仓】active 订单数达到该值后禁止人工与关键位自动再加仓(默认 1=单仓)
|
||||
# 【最大同时持仓】active 订单数达到该值后禁止人工与关键位自动再加仓(默认 1=单仓)
|
||||
MAX_ACTIVE_POSITIONS=1
|
||||
# 【人工下单最低盈亏比】按当前价与 SL/TP 计算,低于该值前后端均拒绝(默认 1.4,即须 >=1.4:1)
|
||||
# 【人工下单最低盈亏比】按当前价与 SL/TP 计算,低于该值前后端均拒绝(默认 1.4,即须 >=1.4:1)
|
||||
MANUAL_MIN_PLANNED_RR=1.4
|
||||
# 【关键位连开计仓】true=已有持仓时关键位自动单仍按「无仓时」资金快照算保证金基数
|
||||
KEY_SIZING_USE_ZERO_POSITION_SNAPSHOT=true
|
||||
# 【单日开仓 AI 提醒】本交易日开仓达到该次数时推送企业微信 AI 克制提醒(不拦单)
|
||||
# 【单日开仓 AI 提醒】本交易日开仓达到该次数时推送企业微信 AI 克制提醒(不拦单)
|
||||
DAILY_OPEN_ALERT_THRESHOLD=5
|
||||
# 【单日开仓硬上限】本交易日开仓次数>=该值后禁止一切新开仓直至下一交易日(北京时间 TRADING_DAY_RESET_HOUR 切日);0=不启用
|
||||
# 【单日开仓硬上限】本交易日开仓次数>=该值后禁止一切新开仓直至下一交易日(北京时间 TRADING_DAY_RESET_HOUR 切日);0=不启用
|
||||
DAILY_OPEN_HARD_LIMIT=0
|
||||
|
||||
# =============================================================================
|
||||
# 账户冷静期 / 日冻结风控(手动平仓、外部平仓、复盘情绪标签)
|
||||
# 账户冷静期 / 日冻结风控(手动平仓,外部平仓,复盘情绪标签)
|
||||
# 详见 docs/account-risk-cooldown.md
|
||||
# =============================================================================
|
||||
# RISK_CONTROL_ENABLED=true
|
||||
# RISK_COOLING_HOURS_MANUAL=4
|
||||
# RISK_COOLING_HOURS_MANUAL_JOURNAL=1
|
||||
# RISK_MANUAL_CLOSE_DAILY_LIMIT=2
|
||||
# RISK_MOOD_ISSUES_DAILY_FREEZE=true
|
||||
RISK_CONTROL_ENABLED=true
|
||||
RISK_COOLING_HOURS_MANUAL=4
|
||||
RISK_COOLING_HOURS_MANUAL_JOURNAL=1
|
||||
RISK_MANUAL_CLOSE_DAILY_LIMIT=2
|
||||
# 日亏损次数上限:平仓盈亏<0 计1次;达限当日冻结开仓;0=不启用
|
||||
RISK_DAILY_LOSS_LIMIT=2
|
||||
RISK_MOOD_ISSUES_DAILY_FREEZE=true
|
||||
|
||||
# 资金与仓位刷新周期(秒)
|
||||
# 资金与仓位刷新周期(秒)
|
||||
BALANCE_REFRESH_SECONDS=60
|
||||
# 前端价格快照轮询(秒)
|
||||
# 前端价格快照轮询(秒)
|
||||
PRICE_REFRESH_SECONDS=5
|
||||
# 后台监控轮询周期(秒)
|
||||
# 后台监控轮询周期(秒)
|
||||
MONITOR_POLL_SECONDS=3
|
||||
# 使用可用资金时的缓冲比例(如0.98代表用98%)
|
||||
# 重启后多少秒内不做「外部平仓」同步(避免 API 未就绪误判)
|
||||
RECONCILE_STARTUP_GRACE_SEC=90
|
||||
# 连续多少次轮询确认交易所空仓后,才记为外部平仓(默认 3 次 ≈ 9 秒)
|
||||
RECONCILE_FLAT_CONFIRM_POLLS=3
|
||||
# 使用可用资金时的缓冲比例(如0.98代表用98%)
|
||||
FULL_MARGIN_BUFFER_RATIO=0.98
|
||||
|
||||
# =============================================================================
|
||||
# 自动划转(页顶「将 swap 补足到 XU」;与 DAILY_START_CAPITAL 独立,需一致时请设为相同值)
|
||||
# 自动划转(页顶「将 swap 补足到 XU」;与 DAILY_START_CAPITAL 独立,需一致时请设为相同值)
|
||||
# =============================================================================
|
||||
AUTO_TRANSFER_ENABLED=false
|
||||
# 交易账户(swap)目标余额 U:每日 8 点(北京)自动划入或划出至 funding;持仓中不划转
|
||||
# 交易账户(swap)目标余额 U:每日 8 点(北京)自动划入或划出至 funding;持仓中不划转
|
||||
AUTO_TRANSFER_AMOUNT=30
|
||||
AUTO_TRANSFER_FROM=funding
|
||||
AUTO_TRANSFER_TO=swap
|
||||
TRANSFER_CCY=USDT
|
||||
# 北京时间该整点小时内尝试;账簿按 UTC 自然日去重
|
||||
# 北京时间该整点小时内尝试;账簿按 UTC 自然日去重
|
||||
AUTO_TRANSFER_BJ_HOUR=8
|
||||
# 强制清仓整点(北京时间,默认 0=凌晨00点)
|
||||
# 强制清仓整点(北京时间,默认 0=凌晨00点)
|
||||
FORCE_CLOSE_BJ_HOUR=0
|
||||
# 是否启用强制清仓(默认关闭,true 才会在整点执行)
|
||||
# 是否启用强制清仓(默认关闭,true 才会在整点执行)
|
||||
FORCE_CLOSE_ENABLED=false
|
||||
# 强制清仓执行窗口(分钟,默认 5;该窗口内禁止开仓)
|
||||
FORCE_CLOSE_GRACE_MINUTES=5
|
||||
|
||||
# 推送与AI超时(秒)
|
||||
# 推送与AI超时(秒)
|
||||
WECHAT_TIMEOUT_SECONDS=10
|
||||
AI_TIMEOUT_SECONDS=120
|
||||
|
||||
# AI 提供方:openai(默认,OpenAI 兼容网关)| ollama(本机 Ollama)
|
||||
# AI 提供方:openai(默认,OpenAI 兼容网关)| ollama(本机 Ollama)
|
||||
AI_PROVIDER=openai
|
||||
# OpenAI 兼容接口(示例:https://op.bz121.com/v1 ,账号见 gateway.json)
|
||||
# OpenAI 兼容接口(示例:https://op.bz121.com/v1 ,账号见 gateway.json)
|
||||
OPENAI_API_BASE=https://op.bz121.com/v1
|
||||
OPENAI_API_KEY=你的密钥
|
||||
OPENAI_MODEL=gemma4:e4b
|
||||
# 本机 Ollama(AI_PROVIDER=ollama 时使用)
|
||||
# 本机 Ollama(AI_PROVIDER=ollama 时使用)
|
||||
OLLAMA_API=http://127.0.0.1:11434/api/generate
|
||||
AI_MODEL=huihui_ai/deepseek-r1-abliterated:latest
|
||||
|
||||
# Binance 代理(可选):本机网络不稳定时通过 SSH 动态转发 SOCKS5 出口
|
||||
# 1) 先在本机建立隧道(示例):
|
||||
# Binance 代理(可选):本机网络不稳定时通过 SSH 动态转发 SOCKS5 出口
|
||||
# 1) 先在本机建立隧道(示例):
|
||||
# ssh -N -D 127.0.0.1:1080 user@vps -o ServerAliveInterval=30 -o ExitOnForwardFailure=yes
|
||||
# 2) 再启用下面这一行(推荐 socks5h,让远端解析域名):
|
||||
# 2) 再启用下面这一行(推荐 socks5h,让远端解析域名):
|
||||
# BINANCE_SOCKS_PROXY=socks5h://127.0.0.1:1080
|
||||
#
|
||||
# 如你更偏向 HTTP 代理(VPS 上跑 tinyproxy 之类),可用:
|
||||
# 如你更偏向 HTTP 代理(VPS 上跑 tinyproxy 之类),可用:
|
||||
# BINANCE_HTTP_PROXY=http://127.0.0.1:3128
|
||||
# BINANCE_HTTPS_PROXY=http://127.0.0.1:3128
|
||||
|
||||
# 开仓多周期K线图(可选)
|
||||
# 开仓多周期K线图(可选)
|
||||
# ORDER_CHART_ENABLED=true
|
||||
# ORDER_CHART_TFS=4h,1h,15m,5m
|
||||
# ORDER_CHART_LIMIT=100
|
||||
# ORDER_CHART_DIR=static/images/order_charts
|
||||
# 详见上文 DAILY_OPEN_ALERT_THRESHOLD / DAILY_OPEN_HARD_LIMIT;说明文档 docs/daily-open-limit.md
|
||||
# 以损定仓(按交易账户资金的百分比)
|
||||
# 详见上文 DAILY_OPEN_ALERT_THRESHOLD / DAILY_OPEN_HARD_LIMIT;说明文档 docs/daily-open-limit.md
|
||||
# 以损定仓(按交易账户资金的百分比)
|
||||
# RISK_PERCENT=2
|
||||
# 移动保本触发(达到多少R触发)与偏移(百分比)
|
||||
# 移动保本触发(达到多少R触发)与偏移(百分比)
|
||||
# BREAKEVEN_RR_TRIGGER=1.0
|
||||
# 移动保本阶梯(每多少R继续上移一次,默认1R)
|
||||
# 移动保本阶梯(每多少R继续上移一次,默认1R)
|
||||
# BREAKEVEN_STEP_R=1.0
|
||||
# BREAKEVEN_OFFSET_PCT=0.02
|
||||
# 开单风格默认值:trend / swing
|
||||
# 开单风格默认值:trend / swing
|
||||
# DEFAULT_TRADE_STYLE=trend
|
||||
|
||||
APP_TIMEZONE=Asia/Shanghai
|
||||
# TRADING_DAY_RESET_HOUR 现在表示「北京时间」整点,默认 8 点起算新交易日;开仓整点限制见 TRADING_DAY_RESET_OPEN_GUARD_ENABLED
|
||||
# TRADING_DAY_RESET_HOUR 现在表示「北京时间」整点,默认 8 点起算新交易日;开仓整点限制见 TRADING_DAY_RESET_OPEN_GUARD_ENABLED
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
# crypto_monitor_binance
|
||||
|
||||
基于 **Flask** 的加密货币 **下单监控 / 关键位监控 / 交易复盘** 小系统,行情与实盘接口统一走 **Binance(USDT-M 永续)**,通过 **ccxt** 访问。
|
||||
基于 **Flask** 的加密货币 **下单监控 / 关键位监控 / 交易复盘** 小系统,行情与实盘接口统一走 **Binance(USDT-M 永续)**,通过 **ccxt** 访问.
|
||||
|
||||
## 功能概要
|
||||
|
||||
- **关键位监控**:价格与硬条件校验、企业微信推送(可选)
|
||||
- **下单监控**:本地风控(含移动保本逻辑)、触达止盈/止损后尝试市价平仓并记账
|
||||
- **策略交易**:顶栏 `/strategy`(趋势回调 + 顺势加仓),见仓库根 [策略交易说明.md](../策略交易说明.md)
|
||||
- **AI 复盘**:OpenAI 兼容网关(默认)或 Ollama,见 [AI复盘与模型配置说明.md](../AI复盘与模型配置说明.md)
|
||||
- **实盘(可选)**:`LIVE_TRADING_ENABLED=true` 且配置 `BINANCE_API_KEY` / `BINANCE_API_SECRET` 时,支持合约开仓、平仓、余额读取与内部划转(依赖 API 权限)
|
||||
- **止盈止损(Binance)**:市价成交后挂 **`STOP_MARKET`**(止损)、**`TAKE_PROFIT_MARKET`**(止盈);双向持仓带 `positionSide`;不显式传 `reduceOnly`(避免 API `-1106`)。触发参考价由 `BINANCE_TRIGGER_WORKING_TYPE` 控制(最新价 / 标记价)
|
||||
- **关键位监控**:价格与硬条件校验,企业微信推送(可选)
|
||||
- **下单监控**:本地风控(含移动保本逻辑),触达止盈/止损后尝试市价平仓并记账
|
||||
- **策略交易**:顶栏 `/strategy`(趋势回调 + 顺势加仓),见仓库根 [策略交易说明.md](../策略交易说明.md)
|
||||
- **AI 复盘**:OpenAI 兼容网关(默认)或 Ollama,见 [AI复盘与模型配置说明.md](../AI复盘与模型配置说明.md)
|
||||
- **实盘(可选)**:`LIVE_TRADING_ENABLED=true` 且配置 `BINANCE_API_KEY` / `BINANCE_API_SECRET` 时,支持合约开仓,平仓,余额读取与内部划转(依赖 API 权限)
|
||||
- **止盈止损(Binance)**:市价成交后挂 **`STOP_MARKET`**(止损),**`TAKE_PROFIT_MARKET`**(止盈);双向持仓带 `positionSide`;不显式传 `reduceOnly`(避免 API `-1106`).触发参考价由 `BINANCE_TRIGGER_WORKING_TYPE` 控制(最新价 / 标记价)
|
||||
|
||||
## 环境要求
|
||||
|
||||
- Python 3.10+(建议)
|
||||
- 依赖:`flask`、`requests`、`ccxt`、`werkzeug`、`Pillow`(K 线图可选);经 SOCKS 代理时需 **`PySocks`**
|
||||
- Python 3.10+(建议)
|
||||
- 依赖:`flask`,`requests`,`ccxt`,`werkzeug`,`Pillow`(K 线图可选);经 SOCKS 代理时需 **`PySocks`**
|
||||
|
||||
安装示例:
|
||||
安装示例:
|
||||
|
||||
```bash
|
||||
# 推荐在 /opt/crypto_monitor 执行仓库根目录 deploy/setup_env.sh
|
||||
@@ -25,31 +25,31 @@ source .venv/bin/activate
|
||||
pip install -r ../requirements.txt
|
||||
```
|
||||
|
||||
页面上的 **「当日资金(交易账户)」** 与 **「可开仓」可用 U** 仅统计 **Binance U 本位永续合约账户**(`fetch_balance` 的 `swap` / FAPI `assets` 中的 USDT),**不会**再用现货余额顶替。
|
||||
页面上的 **「当日资金(交易账户)」** 与 **「可开仓」可用 U** 仅统计 **Binance U 本位永续合约账户**(`fetch_balance` 的 `swap` / FAPI `assets` 中的 USDT),**不会**再用现货余额顶替.
|
||||
|
||||
## 配置说明(`.env.example` → `.env`)
|
||||
## 配置说明(`.env.example` → `.env`)
|
||||
|
||||
- **`.env.example`**:模板(可提交 Git);首次:`cp .env.example .env` 后编辑。
|
||||
- **`.env`**:本机真实配置(勿提交);`app.py` 只读此文件。`git pull` 不覆盖 `.env`;升级前可 `cp .env .env.backup.$(date +%Y%m%d)`。
|
||||
- **`.env.example`**:模板(可提交 Git);首次:`cp .env.example .env` 后编辑.
|
||||
- **`.env`**:本机真实配置(勿提交);`app.py` 只读此文件.`git pull` 不覆盖 `.env`;升级前可 `cp .env .env.backup.$(date +%Y%m%d)`.
|
||||
|
||||
与 Binance 相关的常用变量:
|
||||
与 Binance 相关的常用变量:
|
||||
|
||||
| 变量 | 说明 |
|
||||
|------|------|
|
||||
| `BINANCE_API_KEY` / `BINANCE_API_SECRET` | 币安 API(需合约等权限) |
|
||||
| `LIVE_TRADING_ENABLED` | `true` 时允许真实下单;`false` 仅本地逻辑 |
|
||||
| `BINANCE_API_KEY` / `BINANCE_API_SECRET` | 币安 API(需合约等权限) |
|
||||
| `LIVE_TRADING_ENABLED` | `true` 时允许真实下单;`false` 仅本地逻辑 |
|
||||
| `BINANCE_MARGIN_MODE` | `cross` 全仓 / `isolated` 逐仓 |
|
||||
| `BINANCE_POSITION_MODE` | `hedge` 双向(需账户开启双向持仓)/ `oneway` 单向 |
|
||||
| `BINANCE_TRIGGER_WORKING_TYPE` | `CONTRACT_PRICE` 或 `MARK_PRICE`(条件单触发参考) |
|
||||
| `BINANCE_SOCKS_PROXY` / `BINANCE_HTTP_PROXY` | 可选代理(与部署文档一致) |
|
||||
| `EXCHANGE_DISPLAY_NAME` | 页面展示的交易所名称,默认 `Binance` |
|
||||
| `BINANCE_POSITION_MODE` | `hedge` 双向(需账户开启双向持仓)/ `oneway` 单向 |
|
||||
| `BINANCE_TRIGGER_WORKING_TYPE` | `CONTRACT_PRICE` 或 `MARK_PRICE`(条件单触发参考) |
|
||||
| `BINANCE_SOCKS_PROXY` / `BINANCE_HTTP_PROXY` | 可选代理(与部署文档一致) |
|
||||
| `EXCHANGE_DISPLAY_NAME` | 页面展示的交易所名称,默认 `Binance` |
|
||||
| `BINANCE_ACCOUNT_LABEL` | 推送文案中的账户备注 |
|
||||
|
||||
其余变量(登录、企业微信、风控参数、**`AI_PROVIDER` / `OPENAI_*` / `OLLAMA_*`**、数据库路径等)见 **`.env.example` 内注释** 或 `app.py` 顶部默认值。
|
||||
其余变量(登录,企业微信,风控参数,**`AI_PROVIDER` / `OPENAI_*` / `OLLAMA_*`**,数据库路径等)见 **`.env.example` 内注释** 或 `app.py` 顶部默认值.
|
||||
|
||||
## 运行
|
||||
|
||||
生产环境使用 **PM2**(`ecosystem.config.cjs`)。临时调试:
|
||||
生产环境使用 **PM2**(`ecosystem.config.cjs`).临时调试:
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_binance
|
||||
@@ -57,13 +57,13 @@ source .venv/bin/activate
|
||||
python app.py
|
||||
```
|
||||
|
||||
环境说明见 [docs/ubuntu-server.md](../docs/ubuntu-server.md)。
|
||||
环境说明见 [docs/ubuntu-server.md](../docs/ubuntu-server.md).
|
||||
|
||||
默认监听端口由 `.env` 的 `APP_PORT` 决定(未设置时多为 `5000`)。
|
||||
默认监听端口由 `.env` 的 `APP_PORT` 决定(未设置时多为 `5000`).
|
||||
|
||||
## 部署(Linux / PM2 / SSH SOCKS)
|
||||
## 部署(Linux / PM2 / SSH SOCKS)
|
||||
|
||||
详见 **[部署文档.md](./部署文档.md)**(Ubuntu + PM2 + 可选 SOCKS 访问 Binance)。
|
||||
详见 **[部署文档.md](./部署文档.md)**(Ubuntu + PM2 + 可选 SOCKS 访问 Binance).
|
||||
|
||||
## 自检脚本
|
||||
|
||||
@@ -71,13 +71,13 @@ python app.py
|
||||
python scripts/verify_binance_funding.py
|
||||
```
|
||||
|
||||
用于核对 Key 前缀(不含 Secret)并尝试读取资金钱包 / 合约钱包 USDT(需网络与 API 权限)。
|
||||
用于核对 Key 前缀(不含 Secret)并尝试读取资金钱包 / 合约钱包 USDT(需网络与 API 权限).
|
||||
|
||||
## 数据与脚本
|
||||
|
||||
- 默认 SQLite:`crypto.db`(路径由 `DB_PATH` 指定)
|
||||
- `scripts/fix_breakeven_labels.py`:批量修正「止损」但盈亏为正的记录标签(见部署文档附录)
|
||||
- 默认 SQLite:`crypto.db`(路径由 `DB_PATH` 指定)
|
||||
- `scripts/fix_breakeven_labels.py`:批量修正「止损」但盈亏为正的记录标签(见部署文档附录)
|
||||
|
||||
## 风险与合规
|
||||
|
||||
实盘交易有亏损风险。请自行确认 API 权限、IP 白名单、杠杆与保证金模式与币安账户设置一致,并遵守当地法律法规与 Binance 用户协议。
|
||||
实盘交易有亏损风险.请自行确认 API 权限,IP 白名单,杠杆与保证金模式与币安账户设置一致,并遵守当地法律法规与 Binance 用户协议.
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/**
|
||||
* PM2 进程定义(Ubuntu / Linux)。
|
||||
* PM2 进程定义(Ubuntu / Linux).
|
||||
*
|
||||
* 仅托管 Flask 应用。**SSH SOCKS 隧道**用 `ssh -D` 常驻(可用 tmux / autossh),勿交给 PM2。
|
||||
* 与 `.env` 里 `BINANCE_SOCKS_PROXY` 端口一致即可;不必交给 PM2。
|
||||
* 仅托管 Flask 应用.**SSH SOCKS 隧道**用 `ssh -D` 常驻(可用 tmux / autossh),勿交给 PM2.
|
||||
* 与 `.env` 里 `BINANCE_SOCKS_PROXY` 端口一致即可;不必交给 PM2.
|
||||
*
|
||||
* 使用前:项目根目录存在 `.venv`,且已安装依赖(走 SOCKS 时需 PySocks)。
|
||||
* 使用前:项目根目录存在 `.venv`,且已安装依赖(走 SOCKS 时需 PySocks).
|
||||
*
|
||||
* 启动:
|
||||
* 启动:
|
||||
* pm2 start ecosystem.config.cjs
|
||||
* 保存开机列表:
|
||||
* 保存开机列表:
|
||||
* pm2 save && pm2 startup
|
||||
*/
|
||||
const path = require("path");
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
一次性修复历史交易记录标签:
|
||||
将 trade_records 里“止损但实际盈利”的记录改为“保本止盈”。
|
||||
一次性修复历史交易记录标签:
|
||||
将 trade_records 里“止损但实际盈利”的记录改为“保本止盈”.
|
||||
|
||||
默认条件(可通过参数修改):
|
||||
默认条件(可通过参数修改):
|
||||
- monitor_type = 下单监控
|
||||
- result = 止损
|
||||
- pnl_amount > 0
|
||||
|
||||
用法示例:
|
||||
1) 仅预览(不落库):
|
||||
用法示例:
|
||||
1) 仅预览(不落库):
|
||||
python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run
|
||||
|
||||
2) 执行修复:
|
||||
2) 执行修复:
|
||||
python scripts/fix_breakeven_labels.py --db ./crypto.db --apply
|
||||
"""
|
||||
|
||||
|
||||
@@ -115,15 +115,15 @@ def build_section(order_loop: str) -> str:
|
||||
{{% endif %}}
|
||||
</{t}>
|
||||
<{t} class="rule-tip" id="order-rule-tip">
|
||||
规则:最多 {{{{ max_active_positions }}}} 仓;BTC {{{{ btc_leverage }}}}x / 山寨 {{{{ alt_leverage }}}}x;
|
||||
{{% if can_trade %}}可开仓{{% else %}}不可开仓(持仓已满或未到北京时间 {{{{ reset_hour }}}}:00){{% endif %}};
|
||||
规则:最多 {{{{ max_active_positions }}}} 仓;BTC {{{{ btc_leverage }}}}x / 山寨 {{{{ alt_leverage }}}}x;
|
||||
{{% if can_trade %}}可开仓{{% else %}}不可开仓(持仓已满或未到北京时间 {{{{ reset_hour }}}}:00){{% endif %}};
|
||||
人工开仓盈亏比不得低于 {{{{ manual_min_planned_rr }}}}:1
|
||||
</{t}>
|
||||
<{t} class="rule-tip">
|
||||
以损定仓:风险 {{{{ risk_percent }}}}% |移动保本:下单可勾选关闭;开启时 {{{{ breakeven_rr_trigger }}}}R 触发(每 1R 阶梯上移),偏移 {{{{ breakeven_offset_pct }}}}%
|
||||
以损定仓:风险 {{{{ risk_percent }}}}% |移动保本:下单可勾选关闭;开启时 {{{{ breakeven_rr_trigger }}}}R 触发(每 1R 阶梯上移),偏移 {{{{ breakeven_offset_pct }}}}%
|
||||
</{t}>
|
||||
<{t} class="rule-tip">
|
||||
划转:自动划转 {{{{ '开启' if auto_transfer_enabled else '关闭' }}}}(每天<strong>北京时间 {{{{ auto_transfer_bj_hour }}}}:00</strong>起该整点小时内尝试;账簿按 <strong>UTC 自然日</strong>去重;界面时间为北京;将 {{{{ auto_transfer_to }}}} 补足到 {{{{ auto_transfer_amount }}}}U,来自 {{{{ auto_transfer_from }}}})
|
||||
划转:自动划转 {{{{ '开启' if auto_transfer_enabled else '关闭' }}}}(每天<strong>北京时间 {{{{ auto_transfer_bj_hour }}}}:00</strong>起该整点小时内尝试;账簿按 <strong>UTC 自然日</strong>去重;界面时间为北京;将 {{{{ auto_transfer_to }}}} 补足到 {{{{ auto_transfer_amount }}}}U,来自 {{{{ auto_transfer_from }}}})
|
||||
</{t}>
|
||||
<form action="/manual_transfer" method="post" class="form-row">
|
||||
<input name="amount" type="number" min="0.01" step="0.01" placeholder="手动划转金额U" required>
|
||||
@@ -145,8 +145,8 @@ def build_section(order_loop: str) -> str:
|
||||
<option value="">方向</option><option value="long">做多</option><option value="short">做空</option>
|
||||
</select>
|
||||
<select id="sltp-mode" name="sltp_mode">
|
||||
<option value="price">止盈止损:价格模式</option>
|
||||
<option value="pct">止盈止损:百分比模式</option>
|
||||
<option value="price">止盈止损:价格模式</option>
|
||||
<option value="pct">止盈止损:百分比模式</option>
|
||||
</select>
|
||||
<select name="trade_style" required>
|
||||
<option value="trend">趋势单</option>
|
||||
@@ -154,17 +154,17 @@ def build_section(order_loop: str) -> str:
|
||||
</select>
|
||||
<input id="order-leverage" name="leverage" type="number" min="1" step="1" placeholder="杠杆(可选)">
|
||||
<label style="display:flex;align-items:center;gap:4px;font-size:.82rem;color:#cfd3ef">
|
||||
<input type="checkbox" name="breakeven_enabled" value="1" checked> 启用移动保本(关闭则仅保留初始止损与交易所挂单)
|
||||
<input type="checkbox" name="breakeven_enabled" value="1" checked> 启用移动保本(关闭则仅保留初始止损与交易所挂单)
|
||||
</label>
|
||||
<label style="display:flex;align-items:center;gap:4px;font-size:.82rem;color:#cfd3ef">
|
||||
<input type="checkbox" name="order_chart" value="true"> 开仓后生成多周期K线图(各周期100根,含开平仓标记)
|
||||
<input type="checkbox" name="order_chart" value="true"> 开仓后生成多周期K线图(各周期100根,含开平仓标记)
|
||||
</label>
|
||||
<span style="display:flex;align-items:center;padding:0 10px;font-size:.8rem;color:#8fc8ff">成交价自动取交易所实时+成交回报</span>
|
||||
<input id="order-sl" name="sl" step="any" placeholder="止损价格" required>
|
||||
<input id="order-tp" name="tgt" step="any" placeholder="止盈价格" required>
|
||||
<input id="order-sl-pct" name="sl_pct" type="number" min="0.01" step="0.01" placeholder="止损%" style="display:none">
|
||||
<input id="order-tp-pct" name="tp_pct" type="number" min="0.01" step="0.01" placeholder="止盈%" style="display:none">
|
||||
<button type="submit">开仓(以损定仓)</button>
|
||||
<button type="submit">开仓(以损定仓)</button>
|
||||
</form>
|
||||
</{t}>
|
||||
<{t} class="card">
|
||||
@@ -218,7 +218,7 @@ if(addOrderForm){
|
||||
const mode = (document.getElementById("sltp-mode")||{}).value || "price";
|
||||
let sl, tp, entry;
|
||||
if(mode === "pct"){
|
||||
alert("百分比模式请确认盈亏比后再提交;建议使用价格模式以便校验。");
|
||||
alert("百分比模式请确认盈亏比后再提交;建议使用价格模式以便校验.");
|
||||
return;
|
||||
}
|
||||
sl = Number((document.getElementById("order-sl")||{}).value);
|
||||
@@ -231,12 +231,12 @@ if(addOrderForm){
|
||||
if(px) entry = Number(px);
|
||||
const rr = calcClientRr(direction, entry, sl, tp);
|
||||
if(rr === null || rr < MANUAL_MIN_PLANNED_RR){
|
||||
alert(`计划盈亏比 ${rr === null ? '无效' : rr.toFixed(2)}:1 低于最低要求 ${MANUAL_MIN_PLANNED_RR}:1,已阻止人工下单。`);
|
||||
alert(`计划盈亏比 ${rr === null ? '无效' : rr.toFixed(2)}:1 低于最低要求 ${MANUAL_MIN_PLANNED_RR}:1,已阻止人工下单.`);
|
||||
return;
|
||||
}
|
||||
addOrderForm.submit();
|
||||
})
|
||||
.catch(()=>{ ev.preventDefault(); alert("无法校验盈亏比,请稍后重试"); });
|
||||
.catch(()=>{ ev.preventDefault(); alert("无法校验盈亏比,请稍后重试"); });
|
||||
ev.preventDefault();
|
||||
});
|
||||
}
|
||||
@@ -244,27 +244,27 @@ if(addOrderForm){
|
||||
text = text.replace("refreshOrderDefaults();", hook + "\nrefreshOrderDefaults();")
|
||||
if "max_active_positions" not in text and "order-rule-tip" in text:
|
||||
text = text.replace(
|
||||
"规则:单仓;",
|
||||
"规则:最多 {{ max_active_positions }} 仓;",
|
||||
"规则:单仓;",
|
||||
"规则:最多 {{ max_active_positions }} 仓;",
|
||||
)
|
||||
# account snapshot tip
|
||||
old_tip = '`规则:单仓;BTC {{ btc_leverage }}x'
|
||||
old_tip = '`规则:单仓;BTC {{ btc_leverage }}x'
|
||||
if old_tip in text:
|
||||
text = text.replace(
|
||||
old_tip,
|
||||
"`规则:最多 ${data.max_active_positions || {{ max_active_positions }}} 仓;BTC {{ btc_leverage }}x",
|
||||
"`规则:最多 ${data.max_active_positions || {{ max_active_positions }}} 仓;BTC {{ btc_leverage }}x",
|
||||
)
|
||||
text = text.replace(
|
||||
'const canTradeText = data.can_trade ? "可开仓" : "不可开仓(有持仓或未到北京时间 {{ reset_hour }}:00)";',
|
||||
'const canTradeText = data.can_trade ? "可开仓" : `不可开仓(持仓 ${data.active_count||0}/${data.max_active_positions||{{ max_active_positions }}} 或未到北京时间 {{ reset_hour }}:00)`;',
|
||||
'const canTradeText = data.can_trade ? "可开仓" : "不可开仓(有持仓或未到北京时间 {{ reset_hour }}:00)";',
|
||||
'const canTradeText = data.can_trade ? "可开仓" : `不可开仓(持仓 ${data.active_count||0}/${data.max_active_positions||{{ max_active_positions }}} 或未到北京时间 {{ reset_hour }}:00)`;',
|
||||
)
|
||||
text = text.replace(
|
||||
"if(!data.in_top30){",
|
||||
"const rankMax = data.rank_max || 30;\n if(!data.in_top30){",
|
||||
)
|
||||
text = text.replace(
|
||||
"不在前30,已拦截",
|
||||
"不在前${rankMax},已拦截",
|
||||
"不在前30,已拦截",
|
||||
"不在前${rankMax},已拦截",
|
||||
)
|
||||
# conditional price refresh
|
||||
if "data-page" in text and "refreshPriceSnapshotConditional" not in text:
|
||||
|
||||
@@ -68,8 +68,8 @@ if "key_monitor_page" not in g:
|
||||
" can_trade = trading_day_reset_allows_new_open(now) and active_count == 0\n conn.close()\n return render_template(",
|
||||
""" can_trade = trading_day_reset_allows_new_open(now) and active_count < MAX_ACTIVE_POSITIONS
|
||||
key_gate_rule_text = (
|
||||
f"周期 {KLINE_TIMEFRAME}|确认K:突破棒偏移 {KEY_CONFIRM_BREAKOUT_BAR}、确认棒偏移 {KEY_CONFIRM_BAR}|"
|
||||
f"量能:突破量 > 前{KEY_VOLUME_MA_BARS}均量×{KEY_VOLUME_RATIO_MIN}|"
|
||||
f"周期 {KLINE_TIMEFRAME}|确认K:突破棒偏移 {KEY_CONFIRM_BREAKOUT_BAR},确认棒偏移 {KEY_CONFIRM_BAR}|"
|
||||
f"量能:突破量 > 前{KEY_VOLUME_MA_BARS}均量×{KEY_VOLUME_RATIO_MIN}|"
|
||||
f"自动开仓盈亏比 > {KEY_AUTO_MIN_PLANNED_RR}:1|日成交量排名前 {KEY_DAILY_VOLUME_RANK_MAX}"
|
||||
)
|
||||
conn.close()
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"""
|
||||
python scripts/verify_binance_funding.py
|
||||
|
||||
打印 BINANCE_API_KEY 前 8 位便于与 Binance 控制台核对(不含 Secret)。用于服务器自检。
|
||||
对比 App:资产 → 资金账户(Funding) / 现货账户(Spot) / U本位合约。
|
||||
打印 BINANCE_API_KEY 前 8 位便于与 Binance 控制台核对(不含 Secret).用于服务器自检.
|
||||
对比 App:资产 → 资金账户(Funding) / 现货账户(Spot) / U本位合约.
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
@@ -30,9 +30,9 @@ def main():
|
||||
k = (os.getenv("BINANCE_API_KEY") or "").strip()
|
||||
s = (os.getenv("BINANCE_API_SECRET") or "").strip()
|
||||
if not k or "REPLACE" in k.upper():
|
||||
print("WARN: BINANCE_API_KEY 为空或仍像占位符,请核对 .env")
|
||||
print("WARN: BINANCE_API_KEY 为空或仍像占位符,请核对 .env")
|
||||
if not s or "REPLACE" in s.upper():
|
||||
print("WARN: BINANCE_API_SECRET 为空或仍像占位符,请核对 .env")
|
||||
print("WARN: BINANCE_API_SECRET 为空或仍像占位符,请核对 .env")
|
||||
print("BINANCE_API_KEY prefix (8 chars):", (k[:8] + "…") if len(k) > 8 else "(short)")
|
||||
print("BINANCE_FUNDING_INCLUDE_SPOT:", os.getenv("BINANCE_FUNDING_INCLUDE_SPOT", "false"))
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 181 B After Width: | Height: | Size: 150 B |
|
Before Width: | Height: | Size: 162 B After Width: | Height: | Size: 127 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 497 B After Width: | Height: | Size: 301 B |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 4.9 KiB |
@@ -1,17 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0%" stop-color="#22d3ee"/>
|
||||
<stop offset="100%" stop-color="#34d399"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="512" height="512" rx="108" fill="#0c1019"/>
|
||||
<rect x="36" y="36" width="440" height="440" rx="88" fill="#141b2d"/>
|
||||
<rect x="36" y="36" width="440" height="440" rx="88" fill="none" stroke="url(#g)" stroke-width="12"/>
|
||||
<path d="M120 320 L200 248 L280 272 L392 168" fill="none" stroke="url(#g)" stroke-width="20" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="392" cy="168" r="18" fill="#34d399"/>
|
||||
<rect x="168" y="268" width="28" height="64" rx="6" fill="#f87171"/>
|
||||
<line x1="182" y1="248" x2="182" y2="340" stroke="#f87171" stroke-width="10" stroke-linecap="round"/>
|
||||
<rect x="268" y="220" width="28" height="96" rx="6" fill="#34d399"/>
|
||||
<line x1="282" y1="200" x2="282" y2="340" stroke="#34d399" stroke-width="10" stroke-linecap="round"/>
|
||||
<rect x="36" y="36" width="440" height="440" rx="88" fill="none" stroke="#F0B90B" stroke-width="12"/>
|
||||
<polygon points="256,150 362,256 256,362 150,256" fill="#F0B90B"/><polygon points="256,210 302,256 256,302 210,256" fill="#1a160a"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 440 B |
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "交易监控复盘",
|
||||
"short_name": "监控",
|
||||
"description": "加密货币永续交易监控与复盘",
|
||||
"name": "Binance 交易系统",
|
||||
"short_name": "Binance 交易系统",
|
||||
"description": "Binance 永续交易监控与复盘",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#0b0d14",
|
||||
"theme_color": "#0b0d14",
|
||||
"theme_color": "#F0B90B",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/static/icons/icon-192.png",
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
<div class="row" style="justify-content:space-between">
|
||||
<div class="row">
|
||||
<a class="btn" href="/">返回首页</a>
|
||||
<strong style="color:#dbe4ff">实盘下单放大(100根K线)</strong>
|
||||
<strong style="color:#dbe4ff">实盘下单放大(100根K线)</strong>
|
||||
</div>
|
||||
<div class="status">最近刷新:<span id="updated-at">--</span></div>
|
||||
<div class="status">最近刷新:<span id="updated-at">--</span></div>
|
||||
</div>
|
||||
{% if orders %}
|
||||
<div class="row" style="margin-top:10px">
|
||||
@@ -53,7 +53,7 @@
|
||||
<span id="load-status" class="status"></span>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="empty">当前没有激活订单,无法展示放大K线。</div>
|
||||
<div class="empty">当前没有激活订单,无法展示放大K线.</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,139 +1,139 @@
|
||||
# 使用说明
|
||||
|
||||
**本文件对应仓库:`crypto_monitor_binance`(Binance U 本位永续)。**
|
||||
功能、界面与 **Gate.io USDT 永续版**(目录 `crypto_monitor_gate`)基本一致,差异主要在 **`.env` 里交易所密钥与部分参数名**(`BINANCE_*` / `GATE_*`),文末有对照。
|
||||
|
||||
**部署、代理、PM2 等**请参考本仓库说明或 **`crypto_monitor_gate`** 下的 **`部署文档.md`**(该文以 Gate + SSH SOCKS 为例;Binance 侧将 API 与密钥改为 `BINANCE_*` 即可类比)。
|
||||
**关键位自动开仓的规则、RR、结案原因**见本目录 **`关键位自动下单说明.md`**。
|
||||
|
||||
---
|
||||
|
||||
## 1. 它能做什么
|
||||
|
||||
面向个人盘面的 **Web 控制台**,主要能力包括:
|
||||
|
||||
| 模块 | 说明 |
|
||||
|------|------|
|
||||
| **关键位监控** | 录入上/下沿与类型,按 **5m 收线** 做硬条件过滤;符合条件后 **企业微信** 提醒,部分类型可 **自动市价开仓**(见第 4 节与专门文档)。 |
|
||||
| **实盘下单监控** | 手工填止损/止盈,**以损定仓** 市价开单,挂上条件止盈止损,并在页面跟踪浮盈亏、保本逻辑等。 |
|
||||
| **交易记录 / 复盘** | 平仓结果、盈亏、错过的单等归档与导出;可选 **AI 复盘**(见仓库根 [AI复盘与模型配置说明.md](../AI复盘与模型配置说明.md))。 |
|
||||
| **策略交易** | 顶栏 `/strategy`:**趋势回调**(左)与 **顺势加仓**(右)左右并列;细则见 [策略交易说明.md](../策略交易说明.md)。 |
|
||||
| **策略交易记录** | 顶栏 `/strategy/records`:趋势/顺势分两栏、可筛选,库内保留最近 100 条结束快照。 |
|
||||
|
||||
后台按 **`MONITOR_POLL_SECONDS`**(默认几秒)轮询行情与监控逻辑。**切勿**在未理解规则时同时运行两套程序共用一个实盘账户。
|
||||
|
||||
---
|
||||
|
||||
## 2. 运行前必须配置(`.env`)
|
||||
|
||||
首次在本目录执行 **`cp .env.example .env`**,再编辑 `.env`(`.env` 勿提交 Git;`git pull` 不会改你的 `.env`,升级前建议 `cp .env .env.backup.$(date +%Y%m%d)`)。
|
||||
|
||||
至少检查以下项(具体键名以 **`.env.example`** 为准):
|
||||
|
||||
| 类别 | 说明 |
|
||||
|------|------|
|
||||
| **登录网页** | `APP_PASSWORD`:打开站点后的登录口令。`FLASK_SECRET_KEY`:Session 密钥,请勿使用默认值。 |
|
||||
| **企业微信** | `WECHAT_WEBHOOK`:告警与关键位推送机器人的 Webhook。 |
|
||||
| **是否真下单** | `LIVE_TRADING_ENABLED=false`:**不会**向交易所发送开仓指令(适合测试流程)。改为 `true` 且密钥正确才会实盘。 |
|
||||
| **交易所 API** | **本仓库:** `BINANCE_API_KEY`、`BINANCE_API_SECRET`;永续相关见 `BINANCE_MARGIN_MODE`、`BINANCE_POSITION_MODE`、`BINANCE_TRIGGER_WORKING_TYPE` 等。**勿**把 `.env` 提交到 Git。 |
|
||||
| **关键位 RR / 止损外扩** | `KEY_AUTO_MIN_PLANNED_RR`、`KEY_STOP_OUTSIDE_BREAKOUT_PCT`(详见 `关键位自动下单说明.md`)。 |
|
||||
| **AI 复盘** | 默认 `AI_PROVIDER=openai`,`OPENAI_API_BASE=https://op.bz121.com/v1`、`OPENAI_API_KEY`、`OPENAI_MODEL=gemma4:e4b`;或 `AI_PROVIDER=ollama` + `OLLAMA_API` / `AI_MODEL`。详见 [AI复盘与模型配置说明.md](../AI复盘与模型配置说明.md)。 |
|
||||
|
||||
网络需要代理时可配置 **`BINANCE_SOCKS_PROXY` / `BINANCE_HTTP_PROXY`**(与 Gate 版 `GATE_*_PROXY` 用法类似)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 如何启动与登录
|
||||
|
||||
1. 准备 Python 虚拟环境并安装依赖(如 `flask`、`requests`、`ccxt`、按需 `Pillow`、`PySocks` 等),配置好 `.env`。
|
||||
2. 启动 Flask 应用(可用 **`ecosystem.config.cjs`** 交给 PM2,或本地 `python app.py` / `flask run`,以你当前脚本为准)。
|
||||
3. 浏览器访问站点,打开 **`/login`**,使用 **`.env` 里的 `APP_PASSWORD`** 登录。
|
||||
|
||||
登录后顶栏:**关键位监控** | **实盘下单**(默认首页)| **策略交易**(`/strategy`,趋势回调 + 顺势加仓双栏)| **策略交易记录**(`/strategy/records`,最近 100 条结束快照)| **交易记录与复盘** | **统计分析**。
|
||||
|
||||
---
|
||||
|
||||
## 4. 关键位监控(顶栏「关键位监控」→ `/key_monitor`)
|
||||
|
||||
### 4.1 添加一条关键位
|
||||
|
||||
1. **币种**:如 `BTC` 或 `BTC/USDT`(会规范成内部符号)。
|
||||
2. **类型**(必选其一):
|
||||
|
||||
| 类型 | 行为摘要 |
|
||||
|------|----------|
|
||||
| **箱体突破** | 通过门控且计划 RR 达标 → **自动市价开仓**(需 `LIVE_TRADING_ENABLED=true` 且无其他持仓占位)。结案后本条从列表消失并记入历史。 |
|
||||
| **收敛突破** | 同上(自动开仓类)。 |
|
||||
| **关键阻力位** | **不自动开仓**;触发后 **发 1 次微信**,然后本条 **结案进历史**。 |
|
||||
| **关键支撑位** | 同上(仅提醒)。 |
|
||||
| **回调触价开仓** | **不挂交易所限价**;标记价回调触达 E 后 **下一轮询市价开仓**(RR 门槛同 `KEY_AUTO_MIN_PLANNED_RR`);有效期 **24h** |
|
||||
| **突破触价开仓** | **不挂交易所限价**;标记价 **穿越 E 立即市价开仓**;先触 SL/TP 侧失效;有效期 **24h** |
|
||||
|
||||
3. **方向**:做多 / 做空(回调/突破触价、箱体 / 收敛 / 斐波必选;阻力/支撑不选)。
|
||||
4. **价位**:箱体/收敛/阻力/支撑填 **上沿 / 下沿**;触价填 **入场 E / 止损 SL / 止盈 TP**。
|
||||
|
||||
**限制:**
|
||||
活跃持仓数达到 **`MAX_ACTIVE_POSITIONS`**(默认 1)时,**不允许**再添加「**箱体突破** / **收敛突破**」;仍可添加「**关键阻力位 / 支撑位**」。
|
||||
若 **4h EMA55** 与你的方向逆势,页面会 **额外 Flash 提示**,**不阻挡**提交。
|
||||
|
||||
### 4.2 触发后会发生什么(简版)
|
||||
|
||||
- **箱体 / 收敛**:门控通过后算计划 SL/TP 与 RR;不达标 → 微信说明 + **`rr_insufficient`** 结案;达标 → **市价开仓**,成功 **`auto_opened`** / 失败 **`exchange_failed`**,均不重试同一关键位。
|
||||
- **阻力 / 支撑**:仅 **单次推送** → **`key_level_alert_only`** 结案。
|
||||
|
||||
详细公式与字段见 **`关键位自动下单说明.md`**。
|
||||
|
||||
### 4.3 列表与历史
|
||||
|
||||
当前条目与历史记录的用法与 Gate 版相同;结案后可在历史区查阅 **`close_reason`**。
|
||||
|
||||
---
|
||||
|
||||
## 5. 实盘下单(顶栏「实盘下单」→ `/trade`)
|
||||
|
||||
- 持仓上限由 **`MAX_ACTIVE_POSITIONS`** 控制(默认 1)。
|
||||
- **人工开仓**计划盈亏比不得低于 **`MANUAL_MIN_PLANNED_RR`**(默认 1.4:1)。
|
||||
- 填写币种、方向、杠杆(可选)、止损/止盈(价格或百分比按表单)。
|
||||
- 移动保本等选项按页面与 `.env` 默认。
|
||||
|
||||
开仓成功后卡片 **「来源」**:手工一般为 **下单监控**;关键位自动为 **关键位监控**。
|
||||
|
||||
---
|
||||
|
||||
## 6. 企业微信
|
||||
|
||||
推送逻辑与 Gate 版一致;未配置 **`WECHAT_WEBHOOK`** 时可能没有消息,请以 **交易所端** 核对持仓与挂单。
|
||||
|
||||
---
|
||||
|
||||
## 7. 强烈建议的风险与运维习惯
|
||||
|
||||
1. **先用 `LIVE_TRADING_ENABLED=false`** 熟悉流程再实盘。
|
||||
2. **API 权限**最小化,密钥勿泄露。
|
||||
3. **同一账户避免多程序重复开仓**。
|
||||
4. **自动备份**:服务器上执行 `bash scripts/install_backup_cron.sh`(每天北京时间 0:00 → `/root/backups`,保留 30 天);升级前也可 `bash scripts/backup_data.sh` 手动跑一次。
|
||||
5. 升级代码后留意 **首轮启动**有无数据库迁移报错。
|
||||
|
||||
---
|
||||
|
||||
## 8. 常见问题(简要)
|
||||
|
||||
| 现象 | 可自查 |
|
||||
|------|--------|
|
||||
| 关键位永远不触发 | 门控五项、日成交量排名、`KLINE_TIMEFRAME`。 |
|
||||
| 有信号但不自动开仓 | `LIVE_TRADING_ENABLED`、RR 阈值、是否已有持仓、API/保证金错误信息。 |
|
||||
| 加不了箱体/收敛 | 是否已有持仓。 |
|
||||
| 推送收不到 | Webhook、网络。 |
|
||||
|
||||
---
|
||||
|
||||
## 9. Gate 版(`crypto_monitor_gate`)差异速查
|
||||
|
||||
| 项目 | Binance 本仓库 | Gate 版 |
|
||||
|------|----------------|--------|
|
||||
| API 变量 | `BINANCE_API_KEY`、`BINANCE_API_SECRET`、`BINANCE_*` | `GATE_API_KEY`、`GATE_API_SECRET`、`GATE_*` |
|
||||
| 代理示例 | `BINANCE_SOCKS_PROXY` | `GATE_SOCKS_PROXY` |
|
||||
| TP/SL 实现 | `_binance_place_tp_sl_orders` | `_gate_place_tp_sl_orders`、`GATE_TPSL_*` |
|
||||
| 资金舍入口径 | **`FUNDS_DECIMALS`**(与记账一致) | 以 Gate 仓库实现为准 |
|
||||
|
||||
业务流程(登录、四种关键位、手工单、单仓)两份程序对齐;仅需更换目录与 `.env`。
|
||||
# 使用说明
|
||||
|
||||
**本文件对应仓库:`crypto_monitor_binance`(Binance U 本位永续).**
|
||||
功能,界面与 **Gate.io USDT 永续版**(目录 `crypto_monitor_gate`)基本一致,差异主要在 **`.env` 里交易所密钥与部分参数名**(`BINANCE_*` / `GATE_*`),文末有对照.
|
||||
|
||||
**部署,代理,PM2 等**请参考本仓库说明或 **`crypto_monitor_gate`** 下的 **`部署文档.md`**(该文以 Gate + SSH SOCKS 为例;Binance 侧将 API 与密钥改为 `BINANCE_*` 即可类比).
|
||||
**关键位自动开仓的规则,RR,结案原因**见本目录 **`关键位自动下单说明.md`**.
|
||||
|
||||
---
|
||||
|
||||
## 1. 它能做什么
|
||||
|
||||
面向个人盘面的 **Web 控制台**,主要能力包括:
|
||||
|
||||
| 模块 | 说明 |
|
||||
|------|------|
|
||||
| **关键位监控** | 录入上/下沿与类型,按 **5m 收线** 做硬条件过滤;符合条件后 **企业微信** 提醒,部分类型可 **自动市价开仓**(见第 4 节与专门文档). |
|
||||
| **实盘下单监控** | 手工填止损/止盈,**以损定仓** 市价开单,挂上条件止盈止损,并在页面跟踪浮盈亏,保本逻辑等. |
|
||||
| **交易记录 / 复盘** | 平仓结果,盈亏,错过的单等归档与导出;可选 **AI 复盘**(见仓库根 [AI复盘与模型配置说明.md](../AI复盘与模型配置说明.md)). |
|
||||
| **策略交易** | 顶栏 `/strategy`:**趋势回调**(左)与 **顺势加仓**(右)左右并列;细则见 [策略交易说明.md](../策略交易说明.md). |
|
||||
| **策略交易记录** | 顶栏 `/strategy/records`:趋势/顺势分两栏,可筛选,库内保留最近 100 条结束快照. |
|
||||
|
||||
后台按 **`MONITOR_POLL_SECONDS`**(默认几秒)轮询行情与监控逻辑.**切勿**在未理解规则时同时运行两套程序共用一个实盘账户.
|
||||
|
||||
---
|
||||
|
||||
## 2. 运行前必须配置(`.env`)
|
||||
|
||||
首次在本目录执行 **`cp .env.example .env`**,再编辑 `.env`(`.env` 勿提交 Git;`git pull` 不会改你的 `.env`,升级前建议 `cp .env .env.backup.$(date +%Y%m%d)`).
|
||||
|
||||
至少检查以下项(具体键名以 **`.env.example`** 为准):
|
||||
|
||||
| 类别 | 说明 |
|
||||
|------|------|
|
||||
| **登录网页** | `APP_PASSWORD`:打开站点后的登录口令.`FLASK_SECRET_KEY`:Session 密钥,请勿使用默认值. |
|
||||
| **企业微信** | `WECHAT_WEBHOOK`:告警与关键位推送机器人的 Webhook. |
|
||||
| **是否真下单** | `LIVE_TRADING_ENABLED=false`:**不会**向交易所发送开仓指令(适合测试流程).改为 `true` 且密钥正确才会实盘. |
|
||||
| **交易所 API** | **本仓库:** `BINANCE_API_KEY`,`BINANCE_API_SECRET`;永续相关见 `BINANCE_MARGIN_MODE`,`BINANCE_POSITION_MODE`,`BINANCE_TRIGGER_WORKING_TYPE` 等.**勿**把 `.env` 提交到 Git. |
|
||||
| **关键位 RR / 止损外扩** | `KEY_AUTO_MIN_PLANNED_RR`,`KEY_STOP_OUTSIDE_BREAKOUT_PCT`(详见 `关键位自动下单说明.md`). |
|
||||
| **AI 复盘** | 默认 `AI_PROVIDER=openai`,`OPENAI_API_BASE=https://op.bz121.com/v1`,`OPENAI_API_KEY`,`OPENAI_MODEL=gemma4:e4b`;或 `AI_PROVIDER=ollama` + `OLLAMA_API` / `AI_MODEL`.详见 [AI复盘与模型配置说明.md](../AI复盘与模型配置说明.md). |
|
||||
|
||||
网络需要代理时可配置 **`BINANCE_SOCKS_PROXY` / `BINANCE_HTTP_PROXY`**(与 Gate 版 `GATE_*_PROXY` 用法类似).
|
||||
|
||||
---
|
||||
|
||||
## 3. 如何启动与登录
|
||||
|
||||
1. 准备 Python 虚拟环境并安装依赖(如 `flask`,`requests`,`ccxt`,按需 `Pillow`,`PySocks` 等),配置好 `.env`.
|
||||
2. 启动 Flask 应用(可用 **`ecosystem.config.cjs`** 交给 PM2,或本地 `python app.py` / `flask run`,以你当前脚本为准).
|
||||
3. 浏览器访问站点,打开 **`/login`**,使用 **`.env` 里的 `APP_PASSWORD`** 登录.
|
||||
|
||||
登录后顶栏:**关键位监控** | **实盘下单**(默认首页)| **策略交易**(`/strategy`,趋势回调 + 顺势加仓双栏)| **策略交易记录**(`/strategy/records`,最近 100 条结束快照)| **交易记录与复盘** | **统计分析**.
|
||||
|
||||
---
|
||||
|
||||
## 4. 关键位监控(顶栏「关键位监控」→ `/key_monitor`)
|
||||
|
||||
### 4.1 添加一条关键位
|
||||
|
||||
1. **币种**:如 `BTC` 或 `BTC/USDT`(会规范成内部符号).
|
||||
2. **类型**(必选其一):
|
||||
|
||||
| 类型 | 行为摘要 |
|
||||
|------|----------|
|
||||
| **箱体突破** | 通过门控且计划 RR 达标 → **自动市价开仓**(需 `LIVE_TRADING_ENABLED=true` 且无其他持仓占位).结案后本条从列表消失并记入历史. |
|
||||
| **收敛突破** | 同上(自动开仓类). |
|
||||
| **关键阻力位** | **不自动开仓**;触发后 **发 1 次微信**,然后本条 **结案进历史**. |
|
||||
| **关键支撑位** | 同上(仅提醒). |
|
||||
| **回调触价开仓** | **不挂交易所限价**;标记价回调触达 E 后 **下一轮询市价开仓**(RR 门槛同 `KEY_AUTO_MIN_PLANNED_RR`);有效期 **24h** |
|
||||
| **突破触价开仓** | **不挂交易所限价**;标记价 **穿越 E 立即市价开仓**;先触 SL/TP 侧失效;有效期 **24h** |
|
||||
|
||||
3. **方向**:做多 / 做空(回调/突破触价,箱体 / 收敛 / 斐波必选;阻力/支撑不选).
|
||||
4. **价位**:箱体/收敛/阻力/支撑填 **上沿 / 下沿**;触价填 **入场 E / 止损 SL / 止盈 TP**.
|
||||
|
||||
**限制:**
|
||||
活跃持仓数达到 **`MAX_ACTIVE_POSITIONS`**(默认 1)时,**不允许**再添加「**箱体突破** / **收敛突破**」;仍可添加「**关键阻力位 / 支撑位**」.
|
||||
若 **4h EMA55** 与你的方向逆势,页面会 **额外 Flash 提示**,**不阻挡**提交.
|
||||
|
||||
### 4.2 触发后会发生什么(简版)
|
||||
|
||||
- **箱体 / 收敛**:门控通过后算计划 SL/TP 与 RR;不达标 → 微信说明 + **`rr_insufficient`** 结案;达标 → **市价开仓**,成功 **`auto_opened`** / 失败 **`exchange_failed`**,均不重试同一关键位.
|
||||
- **阻力 / 支撑**:仅 **单次推送** → **`key_level_alert_only`** 结案.
|
||||
|
||||
详细公式与字段见 **`关键位自动下单说明.md`**.
|
||||
|
||||
### 4.3 列表与历史
|
||||
|
||||
当前条目与历史记录的用法与 Gate 版相同;结案后可在历史区查阅 **`close_reason`**.
|
||||
|
||||
---
|
||||
|
||||
## 5. 实盘下单(顶栏「实盘下单」→ `/trade`)
|
||||
|
||||
- 持仓上限由 **`MAX_ACTIVE_POSITIONS`** 控制(默认 1).
|
||||
- **人工开仓**计划盈亏比不得低于 **`MANUAL_MIN_PLANNED_RR`**(默认 1.4:1).
|
||||
- 填写币种,方向,杠杆(可选),止损/止盈(价格或百分比按表单).
|
||||
- 移动保本等选项按页面与 `.env` 默认.
|
||||
|
||||
开仓成功后卡片 **「来源」**:手工一般为 **下单监控**;关键位自动为 **关键位监控**.
|
||||
|
||||
---
|
||||
|
||||
## 6. 企业微信
|
||||
|
||||
推送逻辑与 Gate 版一致;未配置 **`WECHAT_WEBHOOK`** 时可能没有消息,请以 **交易所端** 核对持仓与挂单.
|
||||
|
||||
---
|
||||
|
||||
## 7. 强烈建议的风险与运维习惯
|
||||
|
||||
1. **先用 `LIVE_TRADING_ENABLED=false`** 熟悉流程再实盘.
|
||||
2. **API 权限**最小化,密钥勿泄露.
|
||||
3. **同一账户避免多程序重复开仓**.
|
||||
4. **自动备份**:服务器上执行 `bash scripts/install_backup_cron.sh`(每天北京时间 0:00 → `/root/backups`,保留 30 天);升级前也可 `bash scripts/backup_data.sh` 手动跑一次.
|
||||
5. 升级代码后留意 **首轮启动**有无数据库迁移报错.
|
||||
|
||||
---
|
||||
|
||||
## 8. 常见问题(简要)
|
||||
|
||||
| 现象 | 可自查 |
|
||||
|------|--------|
|
||||
| 关键位永远不触发 | 门控五项,日成交量排名,`KLINE_TIMEFRAME`. |
|
||||
| 有信号但不自动开仓 | `LIVE_TRADING_ENABLED`,RR 阈值,是否已有持仓,API/保证金错误信息. |
|
||||
| 加不了箱体/收敛 | 是否已有持仓. |
|
||||
| 推送收不到 | Webhook,网络. |
|
||||
|
||||
---
|
||||
|
||||
## 9. Gate 版(`crypto_monitor_gate`)差异速查
|
||||
|
||||
| 项目 | Binance 本仓库 | Gate 版 |
|
||||
|------|----------------|--------|
|
||||
| API 变量 | `BINANCE_API_KEY`,`BINANCE_API_SECRET`,`BINANCE_*` | `GATE_API_KEY`,`GATE_API_SECRET`,`GATE_*` |
|
||||
| 代理示例 | `BINANCE_SOCKS_PROXY` | `GATE_SOCKS_PROXY` |
|
||||
| TP/SL 实现 | `_binance_place_tp_sl_orders` | `_gate_place_tp_sl_orders`,`GATE_TPSL_*` |
|
||||
| 资金舍入口径 | **`FUNDS_DECIMALS`**(与记账一致) | 以 Gate 仓库实现为准 |
|
||||
|
||||
业务流程(登录,四种关键位,手工单,单仓)两份程序对齐;仅需更换目录与 `.env`.
|
||||
|
||||
@@ -1,175 +1,192 @@
|
||||
# 关键位监控说明(自动开仓 + 人工盯盘)
|
||||
|
||||
**适用:`crypto_monitor_gate`(Gate U 本位永续)**
|
||||
Binance / OKX 见各自目录下同名文档;共享逻辑在仓库根目录 `key_monitor_lib.py`。
|
||||
|
||||
本文档与 `.env`、`check_key_monitors`、`add_key`、`_key_hard_checks`、`_process_key_rs_level_alert` 一致。
|
||||
|
||||
---
|
||||
|
||||
## 一、监控类型总览
|
||||
|
||||
| 录入类型 | 录入时选方向 | 自动市价开仓 | 触发与结案 |
|
||||
|----------|--------------|--------------|------------|
|
||||
| **箱体突破** | **必选** 多/空 | **是**(门控 + RR) | 条件满足 → 开仓或 `rr_insufficient` / `exchange_failed` → **一次性删除** |
|
||||
| **收敛突破** | **必选** 多/空 | **是**(同上) | 同上 |
|
||||
| **关键阻力位** | **不选**(`direction=watch`) | **否** | 5m 收盘突破上/下沿 → 微信 **3 次** → `key_level_alert_done` |
|
||||
| **关键支撑位** | **不选** | **否** | 同上(与阻力位**相同规则**:填上沿+下沿,程序双向监控) |
|
||||
| 斐波回调 0.618 / 0.786 | 必选 | 限价挂单逻辑 | 见斐波说明(**不在下文展开**) |
|
||||
| **回调触价开仓** | **必选** 多/空 | **程序盯价 → 回调触 E 后市价** | 见下文 **§四** |
|
||||
| **突破触价开仓** | **必选** 多/空 | **程序盯价 → 穿越 E 立即市价** | 见下文 **§四** |
|
||||
|
||||
**添加时(箱体/收敛/斐波/触价):** 品种须 **日成交量排名前 `KEY_DAILY_VOLUME_RANK_MAX`(默认 30)**;上沿 **>** 下沿(触价开仓填 E/SL/TP,上下沿仅作展示占位)。
|
||||
|
||||
---
|
||||
|
||||
## 二、关键阻力位 / 关键支撑位(人工盯盘)
|
||||
|
||||
### 2.1 录入
|
||||
|
||||
- 填写 **上沿 `upper`** 与 **下沿 `lower`**(程序同时监控两侧,**无法预先判定**做多还是做空)。
|
||||
- 页面 **不显示、不要求** 方向;库中 `direction` 初始为 `watch`,**首次突破后** 写入 `long`(向上突破上沿)或 `short`(向下突破下沿)。
|
||||
|
||||
### 2.2 触发(极简)
|
||||
|
||||
- 周期:**`KLINE_TIMEFRAME`(默认 5m)最近一根已闭合 K** 的 **收盘价**(非影线)。
|
||||
- **向上突破上沿:** `收盘 > upper` → 推断方向 **多 / 向上**,本次监控任务开始按节奏提醒。
|
||||
- **向下突破下沿:** `收盘 < lower` → 推断方向 **空 / 向下**,本次任务同样开始提醒。
|
||||
- **任一侧突破即结束本条监控周期**(不会在突破后再等待另一侧;上沿、下沿谁先满足用谁,同根 K 仅可能满足一侧)。
|
||||
|
||||
**不参与:** 量能、二确 K、越过幅度下限、日成交排名(运行时)、计划 RR、自动开仓。
|
||||
|
||||
### 2.3 微信提醒次数
|
||||
|
||||
| 配置 | 默认 | 含义 |
|
||||
|------|------|------|
|
||||
| `KEY_ALERT_MAX_TIMES` | `3` | 突破后最多推送 3 次 |
|
||||
| `KEY_ALERT_INTERVAL_MINUTES` | `5` | 相邻两次推送至少间隔 5 分钟 |
|
||||
|
||||
- 第 1 次:首次检测到突破的当次轮询(若已闭合 5m 满足条件)。
|
||||
- 第 2、3 次:仅按间隔推送(**不要求**价格仍在箱外)。
|
||||
- 第 3 次推送后:写入 `key_monitor_history`,`close_reason=**key_level_alert_done**`,从 `key_monitors` **删除**。
|
||||
|
||||
### 2.4 与箱体/收敛的区别
|
||||
|
||||
| 项目 | 阻力/支撑 | 箱体/收敛 |
|
||||
|------|-----------|-----------|
|
||||
| 方向 | 程序推断 | 人工选择 |
|
||||
| K 线根数 | 1 根闭合 5m | 2 根(突破 K + 确认 K) |
|
||||
| 提醒次数 | 3 次后结案 | 自动单:触发后 1 次业务推送并结案 |
|
||||
|
||||
---
|
||||
|
||||
## 三、箱体突破 / 收敛突破(自动开仓)
|
||||
|
||||
### 3.1 K 线结构(默认索引)
|
||||
|
||||
| 角色 | 环境变量 | 默认 | 含义 |
|
||||
|------|----------|------|------|
|
||||
| 突破 K | `KEY_CONFIRM_BREAKOUT_BAR` | `-2` | 倒数第 2 根闭合 K |
|
||||
| 确认 K | `KEY_CONFIRM_BAR` | `-1` | 倒数第 1 根闭合 K |
|
||||
|
||||
### 3.2 硬门控(须全部通过)
|
||||
|
||||
1. **有效突破(收盘越界)**
|
||||
- 多:`突破 K 收盘 > upper`
|
||||
- 空:`突破 K 收盘 < lower`
|
||||
|
||||
2. **突破越过幅度(仅下限)**
|
||||
- 多:`(突破 K 收盘 − upper) / upper × 100 > KEY_BREAKOUT_AMP_MIN_PCT`(默认 **0.03%**)
|
||||
- 空:`(lower − 突破 K 收盘) / lower × 100 >` 同上
|
||||
- **无上限**;突破过猛由 **计划 RR** 过滤。
|
||||
- **不再**使用 K 线实体占开盘价比例;`KEY_BREAKOUT_AMP_MAX_PCT` **已不参与门控**。
|
||||
|
||||
3. **确认 K 不进箱体**
|
||||
- 多:确认 K 收盘 **`> upper`**(不得在 `[lower, upper]` 内)
|
||||
- 空:确认 K 收盘 **`< lower`**
|
||||
|
||||
4. **量能:** 突破 K 成交量 > 前 `KEY_VOLUME_MA_BARS`(默认 20)根均量 × `KEY_VOLUME_RATIO_MIN`(默认 1.3)
|
||||
|
||||
5. **日成交量排名:** 运行时仍须前 `KEY_DAILY_VOLUME_RANK_MAX`(默认 30)
|
||||
|
||||
6. **计划 RR(最后经济门控):** 按确认 K 收盘 **E** 计算 SL/TP 后,`RR` **严格大于** `KEY_AUTO_MIN_PLANNED_RR`(默认 1.5)才市价开仓
|
||||
|
||||
### 3.3 止损 / 止盈(确认 K 收盘为 E)
|
||||
|
||||
箱体高 **H = |upper − lower|**。止损锚在 **突破 K 极值** 外侧:
|
||||
|
||||
| 方向 | 止损(标准/趋势方案) |
|
||||
|------|------------------------|
|
||||
| 多 | 突破 K **最低价** × (1 − `KEY_STOP_OUTSIDE_BREAKOUT_PCT`%) |
|
||||
| 空 | 突破 K **最高价** × (1 + `KEY_STOP_OUTSIDE_BREAKOUT_PCT`%) |
|
||||
|
||||
止盈方案见下表(与改版前一致):
|
||||
|
||||
| 方案 | `sl_tp_mode` | 多:SL / TP | 空:SL / TP |
|
||||
|------|--------------|-------------|-------------|
|
||||
| 标准突破 | `standard` | 突破 K 低外侧% / **E+H** | 突破 K 高外侧% / **E−H** |
|
||||
| 箱体 1R·止盈 1.5H | `box_1p5` | **E−H** / **E+1.5×H** | **E+H** / **E−1.5×H** |
|
||||
| 趋势单·自填止盈 | `trend_manual` | 突破 K 低 × (1−`KEY_TREND_STOP_OUTSIDE_PCT`%) / **录入止盈** | 突破 K 高外侧% / **录入止盈** |
|
||||
|
||||
### 3.4 一次性结案(`close_reason`)
|
||||
|
||||
| `close_reason` | 含义 |
|
||||
|----------------|------|
|
||||
| `box_opposite_break` | 标记价先突破反向边界(多:≤下沿;空:≥上沿) |
|
||||
| `rr_insufficient` | 门控通过但 RR 不达标或 SL/TP 几何无效 |
|
||||
| `exchange_failed` | RR 达标但实盘/交易所等原因未开仓 |
|
||||
| `auto_opened` | RR 达标且市价开仓成功 |
|
||||
| `key_level_alert_done` | 阻力/支撑 **3 次提醒** 完成 |
|
||||
|
||||
---
|
||||
|
||||
## 四、回调 / 突破触价开仓(程序触价,无交易所挂单)
|
||||
|
||||
### 4.1 录入
|
||||
|
||||
- **回调触价开仓**:方向必选多/空;填写 **计划入场价 E**、**止损 SL**、**止盈 TP**(做多须 `SL < E < TP`)。
|
||||
- **突破触价开仓**:同上;添加时当前价须在突破方向一侧(做多:价低于 E;做空:价高于 E)。
|
||||
- 计划 RR 以 **E** 为基准,须 **严格大于** `KEY_AUTO_MIN_PLANNED_RR`(默认 1.5)。
|
||||
- 可选移动保本、时间平仓;**全仓杠杆模式**下可用。
|
||||
|
||||
### 4.2 触发与结案
|
||||
|
||||
| 类型 | 触发条件(标记价) |
|
||||
|------|-------------------|
|
||||
| **回调触价** | 做多 `≤ E`;做空 `≥ E` → 下一轮询市价开仓 |
|
||||
| **突破触价** | 做多**向上穿越** E;做空**向下穿越** E → **立即**市价开仓 |
|
||||
|
||||
- 未成交前标记价先触 **TP 侧** → `trigger_tp_invalidate`。
|
||||
- **突破触价**另:未穿越 E 先触 **SL 侧** → `trigger_sl_invalidate`。
|
||||
- **24h** 未触发 → `trigger_entry_expired`。
|
||||
- 成功 → `trigger_entry_filled`;触发后开仓失败 → `trigger_exchange_failed`。
|
||||
|
||||
### 4.3 计仓与占位
|
||||
|
||||
- **以损定仓**:按 E、SL 反推保证金,触发时重算;**全仓杠杆**:可用×缓冲比例,BTC/ETH 10x、其它 5x。
|
||||
- **占当日开仓意图**(已开 + 待触发),未成交不占持仓;同币仅 1 条触价监控(含回调/突破)。
|
||||
|
||||
共享逻辑:`trigger_entry_key_monitor_lib.py`;轮询:`check_trigger_entry_key_monitors`。
|
||||
|
||||
---
|
||||
|
||||
## 五、环境与参数(`.env` 摘要)
|
||||
|
||||
| 变量 | 箱体/收敛 | 阻力/支撑 |
|
||||
|------|-----------|-----------|
|
||||
| `KEY_BREAKOUT_AMP_MIN_PCT` | 突破越过下限(默认 0.03) | 不用 |
|
||||
| `KEY_BREAKOUT_AMP_MAX_PCT` | **已废弃门控** | 不用 |
|
||||
| `KEY_VOLUME_*` / `KEY_CONFIRM_*` | 用 | 不用 |
|
||||
| `KEY_AUTO_MIN_PLANNED_RR` | 用 | 不用 |
|
||||
| `KEY_ALERT_MAX_TIMES` / `KEY_ALERT_INTERVAL_MINUTES` | 不用 | 用(默认 3 次 / 5 分钟) |
|
||||
| `KEY_DAILY_VOLUME_RANK_MAX` | 添加时 + 运行时 | **仅添加时** |
|
||||
|
||||
---
|
||||
|
||||
## 六、相关代码
|
||||
|
||||
| 说明 | 位置 |
|
||||
|------|------|
|
||||
| 共享判定 | `key_monitor_lib.py` |
|
||||
| 主循环 | `check_key_monitors` |
|
||||
| 自动门控 | `_key_hard_checks` |
|
||||
| 阻力/支撑提醒 | `_process_key_rs_level_alert` |
|
||||
| 录入 | `add_key` |
|
||||
| 开仓 | `_market_open_for_key_monitor` |
|
||||
# 关键位监控说明(自动开仓 + 人工盯盘)
|
||||
|
||||
**适用:Gate / Binance / OKX 三所实例(共用 `lib/key_monitor/key_auto_order_lib.py`)**
|
||||
|
||||
## 环境开关 `KEY_AUTO_ORDER_ENABLED`(默认 `false`)
|
||||
|
||||
| 计仓模式 | 开关 | 关键位程序自动单 |
|
||||
|----------|------|------------------|
|
||||
| `risk`(以损定仓) | `false` | **全部关闭**(含触价);支撑/阻力微信提醒仍可用 |
|
||||
| `risk` | `true` | 箱体/收敛/斐波/假突破/触价均可自动(旧行为) |
|
||||
| `full_margin`(全仓) | `false` | 全部关闭(含触价) |
|
||||
| `full_margin` | `true` | **仅触价**自动;箱体/斐波等仍禁止 |
|
||||
|
||||
**不受本开关影响:** 人工实盘下单,关键支撑/阻力提醒,**顺势加仓**(`risk` 下),趋势回调(`risk` 下).全仓模式下策略自动仍禁止.
|
||||
|
||||
修改 `.env` 后须 **重启 PM2**.复盘「开仓类型」与统计分段会随开关联动隐藏关键位选项.
|
||||
|
||||
---
|
||||
|
||||
**适用:`crypto_monitor_binance`(Binance U 本位)**
|
||||
Gate / OKX 见各自目录下同名文档;共享逻辑在 `lib/key_monitor/`.
|
||||
|
||||
本文档与 `.env`,`check_key_monitors`,`add_key`,`_key_hard_checks`,`_process_key_rs_level_alert` 一致.
|
||||
|
||||
---
|
||||
|
||||
## 一,监控类型总览
|
||||
|
||||
| 录入类型 | 录入时选方向 | 自动市价开仓 | 触发与结案 |
|
||||
|----------|--------------|--------------|------------|
|
||||
| **箱体突破** | **必选** 多/空 | **是**(门控 + RR) | 条件满足 → 开仓或 `rr_insufficient` / `exchange_failed` → **一次性删除** |
|
||||
| **收敛突破** | **必选** 多/空 | **是**(同上) | 同上 |
|
||||
| **关键阻力位** | **不选**(`direction=watch`) | **否** | 5m 收盘突破上/下沿 → 微信 **3 次** → `key_level_alert_done` |
|
||||
| **关键支撑位** | **不选** | **否** | 同上(与阻力位**相同规则**:填上沿+下沿,程序双向监控) |
|
||||
| 斐波回调 0.618 / 0.786 | 必选 | 限价挂单逻辑 | 见斐波说明(**不在下文展开**) |
|
||||
| **回调触价开仓** | **必选** 多/空 | **程序盯价 → 回调触 E 后市价** | 见下文 **§四** |
|
||||
| **突破触价开仓** | **必选** 多/空 | **程序盯价 → 穿越 E 立即市价** | 见下文 **§四** |
|
||||
|
||||
**添加时(箱体/收敛/斐波/触价):** 品种须 **日成交量排名前 `KEY_DAILY_VOLUME_RANK_MAX`(默认 30)**;上沿 **>** 下沿(触价开仓填 E/SL/TP,上下沿仅作展示占位).
|
||||
|
||||
---
|
||||
|
||||
## 二,关键阻力位 / 关键支撑位(人工盯盘)
|
||||
|
||||
### 2.1 录入
|
||||
|
||||
- 填写 **上沿 `upper`** 与 **下沿 `lower`**(程序同时监控两侧,**无法预先判定**做多还是做空).
|
||||
- 页面 **不显示,不要求** 方向;库中 `direction` 初始为 `watch`,**首次突破后** 写入 `long`(向上突破上沿)或 `short`(向下突破下沿).
|
||||
|
||||
### 2.2 触发(极简)
|
||||
|
||||
- 周期:**`KLINE_TIMEFRAME`(默认 5m)最近一根已闭合 K** 的 **收盘价**(非影线).
|
||||
- **向上突破上沿:** `收盘 > upper` → 推断方向 **多 / 向上**,本次监控任务开始按节奏提醒.
|
||||
- **向下突破下沿:** `收盘 < lower` → 推断方向 **空 / 向下**,本次任务同样开始提醒.
|
||||
- **任一侧突破即结束本条监控周期**(不会在突破后再等待另一侧;上沿,下沿谁先满足用谁,同根 K 仅可能满足一侧).
|
||||
|
||||
**不参与:** 量能,二确 K,越过幅度下限,日成交排名(运行时),计划 RR,自动开仓.
|
||||
|
||||
### 2.3 微信提醒次数
|
||||
|
||||
| 配置 | 默认 | 含义 |
|
||||
|------|------|------|
|
||||
| `KEY_ALERT_MAX_TIMES` | `3` | 突破后最多推送 3 次 |
|
||||
| `KEY_ALERT_INTERVAL_MINUTES` | `5` | 相邻两次推送至少间隔 5 分钟 |
|
||||
|
||||
- 第 1 次:首次检测到突破的当次轮询(若已闭合 5m 满足条件).
|
||||
- 第 2,3 次:仅按间隔推送(**不要求**价格仍在箱外).
|
||||
- 第 3 次推送后:写入 `key_monitor_history`,`close_reason=**key_level_alert_done**`,从 `key_monitors` **删除**.
|
||||
|
||||
### 2.4 与箱体/收敛的区别
|
||||
|
||||
| 项目 | 阻力/支撑 | 箱体/收敛 |
|
||||
|------|-----------|-----------|
|
||||
| 方向 | 程序推断 | 人工选择 |
|
||||
| K 线根数 | 1 根闭合 5m | 2 根(突破 K + 确认 K) |
|
||||
| 提醒次数 | 3 次后结案 | 自动单:触发后 1 次业务推送并结案 |
|
||||
|
||||
---
|
||||
|
||||
## 三,箱体突破 / 收敛突破(自动开仓)
|
||||
|
||||
### 3.1 K 线结构(默认索引)
|
||||
|
||||
| 角色 | 环境变量 | 默认 | 含义 |
|
||||
|------|----------|------|------|
|
||||
| 突破 K | `KEY_CONFIRM_BREAKOUT_BAR` | `-2` | 倒数第 2 根闭合 K |
|
||||
| 确认 K | `KEY_CONFIRM_BAR` | `-1` | 倒数第 1 根闭合 K |
|
||||
|
||||
### 3.2 硬门控(须全部通过)
|
||||
|
||||
1. **有效突破(收盘越界)**
|
||||
- 多:`突破 K 收盘 > upper`
|
||||
- 空:`突破 K 收盘 < lower`
|
||||
|
||||
2. **突破越过幅度(仅下限)**
|
||||
- 多:`(突破 K 收盘 − upper) / upper × 100 > KEY_BREAKOUT_AMP_MIN_PCT`(默认 **0.03%**)
|
||||
- 空:`(lower − 突破 K 收盘) / lower × 100 >` 同上
|
||||
- **无上限**;突破过猛由 **计划 RR** 过滤.
|
||||
- **不再**使用 K 线实体占开盘价比例;`KEY_BREAKOUT_AMP_MAX_PCT` **已不参与门控**.
|
||||
|
||||
3. **确认 K 不进箱体**
|
||||
- 多:确认 K 收盘 **`> upper`**(不得在 `[lower, upper]` 内)
|
||||
- 空:确认 K 收盘 **`< lower`**
|
||||
|
||||
4. **量能:** 突破 K 成交量 > 前 `KEY_VOLUME_MA_BARS`(默认 20)根均量 × `KEY_VOLUME_RATIO_MIN`(默认 1.3)
|
||||
|
||||
5. **日成交量排名:** 运行时仍须前 `KEY_DAILY_VOLUME_RANK_MAX`(默认 30)
|
||||
|
||||
6. **计划 RR(最后经济门控):** 按确认 K 收盘 **E** 计算 SL/TP 后,`RR` **严格大于** `KEY_AUTO_MIN_PLANNED_RR`(默认 1.5)才市价开仓
|
||||
|
||||
### 3.3 止损 / 止盈(确认 K 收盘为 E)
|
||||
|
||||
箱体高 **H = |upper − lower|**.止损锚在 **突破 K 极值** 外侧:
|
||||
|
||||
| 方向 | 止损(标准/趋势方案) |
|
||||
|------|------------------------|
|
||||
| 多 | 突破 K **最低价** × (1 − `KEY_STOP_OUTSIDE_BREAKOUT_PCT`%) |
|
||||
| 空 | 突破 K **最高价** × (1 + `KEY_STOP_OUTSIDE_BREAKOUT_PCT`%) |
|
||||
|
||||
止盈方案见下表(与改版前一致):
|
||||
|
||||
| 方案 | `sl_tp_mode` | 多:SL / TP | 空:SL / TP |
|
||||
|------|--------------|-------------|-------------|
|
||||
| 标准突破 | `standard` | 突破 K 低外侧% / **E+H** | 突破 K 高外侧% / **E−H** |
|
||||
| 箱体 1R·止盈 1.5H | `box_1p5` | **E−H** / **E+1.5×H** | **E+H** / **E−1.5×H** |
|
||||
| 趋势单·自填止盈 | `trend_manual` | 突破 K 低 × (1−`KEY_TREND_STOP_OUTSIDE_PCT`%) / **录入止盈** | 突破 K 高外侧% / **录入止盈** |
|
||||
|
||||
### 3.4 一次性结案(`close_reason`)
|
||||
|
||||
| `close_reason` | 含义 |
|
||||
|----------------|------|
|
||||
| `box_opposite_break` | 标记价先突破反向边界(多:≤下沿;空:≥上沿) |
|
||||
| `rr_insufficient` | 门控通过但 RR 不达标或 SL/TP 几何无效 |
|
||||
| `exchange_failed` | RR 达标但实盘/交易所等原因未开仓 |
|
||||
| `auto_opened` | RR 达标且市价开仓成功 |
|
||||
| `key_level_alert_done` | 阻力/支撑 **3 次提醒** 完成 |
|
||||
|
||||
---
|
||||
|
||||
## 四,回调 / 突破触价开仓(程序触价,无交易所挂单)
|
||||
|
||||
### 4.1 录入
|
||||
|
||||
- **回调触价开仓**:方向必选多/空;填写 **计划入场价 E**,**止损 SL**,**止盈 TP**(做多须 `SL < E < TP`).
|
||||
- **突破触价开仓**:同上;添加时当前价须在突破方向一侧(做多:价低于 E;做空:价高于 E).
|
||||
- 计划 RR 以 **E** 为基准,须 **严格大于** `KEY_AUTO_MIN_PLANNED_RR`(默认 1.5).
|
||||
- 可选移动保本,时间平仓;**全仓杠杆模式**下可用.
|
||||
|
||||
### 4.2 触发与结案
|
||||
|
||||
| 类型 | 触发条件(标记价) |
|
||||
|------|-------------------|
|
||||
| **回调触价** | 做多 `≤ E`;做空 `≥ E` → 下一轮询市价开仓 |
|
||||
| **突破触价** | 做多**向上穿越** E;做空**向下穿越** E → **立即**市价开仓 |
|
||||
|
||||
- 未成交前标记价先触 **TP 侧** → `trigger_tp_invalidate`.
|
||||
- **突破触价**另:未穿越 E 先触 **SL 侧** → `trigger_sl_invalidate`.
|
||||
- **24h** 未触发 → `trigger_entry_expired`.
|
||||
- 成功 → `trigger_entry_filled`;触发后开仓失败 → `trigger_exchange_failed`.
|
||||
|
||||
### 4.3 计仓与占位
|
||||
|
||||
- **以损定仓**:按 E,SL 反推保证金,触发时重算;**全仓杠杆**:可用×缓冲比例,BTC/ETH 10x,其它 5x.
|
||||
- **占当日开仓意图**(已开 + 待触发),未成交不占持仓;同币仅 1 条触价监控(含回调/突破).
|
||||
|
||||
共享逻辑:`trigger_entry_key_monitor_lib.py`;轮询:`check_trigger_entry_key_monitors`.
|
||||
|
||||
---
|
||||
|
||||
## 五,环境与参数(`.env` 摘要)
|
||||
|
||||
| 变量 | 箱体/收敛 | 阻力/支撑 |
|
||||
|------|-----------|-----------|
|
||||
| `KEY_BREAKOUT_AMP_MIN_PCT` | 突破越过下限(默认 0.03) | 不用 |
|
||||
| `KEY_BREAKOUT_AMP_MAX_PCT` | **已废弃门控** | 不用 |
|
||||
| `KEY_VOLUME_*` / `KEY_CONFIRM_*` | 用 | 不用 |
|
||||
| `KEY_AUTO_MIN_PLANNED_RR` | 用 | 不用 |
|
||||
| `KEY_ALERT_MAX_TIMES` / `KEY_ALERT_INTERVAL_MINUTES` | 不用 | 用(默认 3 次 / 5 分钟) |
|
||||
| `KEY_DAILY_VOLUME_RANK_MAX` | 添加时 + 运行时 | **仅添加时** |
|
||||
|
||||
---
|
||||
|
||||
## 六,相关代码
|
||||
|
||||
| 说明 | 位置 |
|
||||
|------|------|
|
||||
| 共享判定 | `key_monitor_lib.py` |
|
||||
| 主循环 | `check_key_monitors` |
|
||||
| 自动门控 | `_key_hard_checks` |
|
||||
| 阻力/支撑提醒 | `_process_key_rs_level_alert` |
|
||||
| 录入 | `add_key` |
|
||||
| 开仓 | `_market_open_for_key_monitor` |
|
||||
|
||||
@@ -1,147 +1,147 @@
|
||||
# 界面与风控更新说明(Binance 实例)
|
||||
|
||||
## 顶栏导航(4 项)
|
||||
|
||||
| 顺序 | 名称 | 路由 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 1 | 关键位监控 | `/key_monitor` | 关键位添加、实时门控、历史 |
|
||||
| 2 | 实盘下单 | `/trade` | 人工开仓、划转、实时持仓(**默认首页** `/` → `/trade`) |
|
||||
| 3 | 交易记录与复盘 | `/records` | 交易记录、复盘表单、AI 历史(受顶栏 UTC 时间窗筛选) |
|
||||
| 4 | 统计分析 | `/stats` | 按北京时间交易日切日 + 分品类统计块 |
|
||||
|
||||
## 关键位监控页
|
||||
|
||||
- 标题去掉「5m」;规则条从 `.env` 读取(周期、确认K、量能、自动开仓盈亏比、日成交量排名)。
|
||||
- 左列:活跃关键位,**pos-card** 样式展示现价/距上沿/距下沿/门控。
|
||||
- 右列:关键位历史(失效/结案),与左列等高滚动;**受顶栏 UTC 列表时间窗筛选**(默认 UTC 当日)。
|
||||
- 监控类型新增:**斐波回调0.618**、**斐波回调0.786**(与 Gate 主站同一套规则,计算逻辑见仓库根目录 `fib_key_monitor_lib.py`)。
|
||||
|
||||
### 斐波关键位监控(方案 A:交易所限价)
|
||||
|
||||
| 项 | 说明 |
|
||||
|----|------|
|
||||
| 同币互斥 | 每个币种只能有一条斐波监控(0.618 与 0.786 不可并存) |
|
||||
| 上下沿 | 上沿 **H**、下沿 **L**(须 H > L) |
|
||||
| 挂单价 E | **做多** `E = H − ratio × (H − L)`(自 H 向下回撤);**做空** `E = L + ratio × (H − L)`(自 L 向上反弹) |
|
||||
| 做多 | 限价 @ E,止损 L,止盈 H |
|
||||
| 做空 | 限价 @ E,止损 H,止盈 L |
|
||||
| 添加后 | **立即**在 Binance U 本位挂限价单;卡片显示 **挂E**、限价单 ID |
|
||||
| 失效 | 以**标记价**判断:做多且标记价 ≥ H、做空且标记价 ≤ L,且限价**未成交** → 撤销该限价单并结案 |
|
||||
| 成交后 | 挂交易所 TP/SL(含 Algo 通道条件单)→ 写入 **实盘下单监控**(`monitor_type=关键位监控`,`key_signal_type=斐波回调…`)→ 从关键位列表移除 |
|
||||
| 撤单 | 仅撤本条斐波的订单 ID,**不会**对该合约 `cancel_all_orders` / 全撤 Algo,避免误伤其他委托 |
|
||||
| 盈亏比 | 计划 RR 须 > `KEY_AUTO_MIN_PLANNED_RR`;0.618 理论约 1.6:1,0.786 约 3.7:1 |
|
||||
| 日成交量 | 与箱体/收敛相同,须在前 `KEY_DAILY_VOLUME_RANK_MAX` 名内方可添加 |
|
||||
|
||||
后台轮询:`check_fib_key_monitors()`;箱体/收敛仍走 `check_key_monitors()`。
|
||||
|
||||
手动删除关键位时,未成交斐波会先撤限价再删库。
|
||||
|
||||
### 箱体 / 收敛自动开仓(来源标注)
|
||||
|
||||
- 自动开仓写入 `order_monitors.key_signal_type`:`箱体突破` 或 `收敛突破`。
|
||||
- 持仓与交易记录展示「来源 · 信号类型」。
|
||||
|
||||
## 列表时间窗(UTC,全站顶栏)
|
||||
|
||||
共用模块:仓库根目录 `history_window_lib.py`(Gate / Binance 主站一致)。
|
||||
|
||||
| 项 | 说明 |
|
||||
|----|------|
|
||||
| 默认 | **UTC 当日**(`win_preset=utc_today`,从 UTC 0:00 至当前时刻) |
|
||||
| 可选 | 近 24 小时、近 7 天、自定义起止(UTC,`datetime-local`) |
|
||||
| 作用范围 | 关键位历史、交易记录列表、复盘记录 API、AI 历史 API、导出「交易记录」「关键位历史」 |
|
||||
| 与统计的关系 | **仅影响列表/导出**;**统计分析页仍按北京时间 `TRADING_DAY_RESET_HOUR`(默认 8:00)切交易日** |
|
||||
| 库内时间 | DB 存北京时间字符串;后端用 `utc_window_to_bj_sql_strings()` 换算后再 SQL 比较 |
|
||||
| 切换方式 | 顶栏「列表筛选(UTC)」→ 选预设 → **应用**(保留当前路由,如 `/records?win_preset=…`) |
|
||||
|
||||
查询参数示例:
|
||||
|
||||
- `?win_preset=utc_today`
|
||||
- `?win_preset=utc_last24h` / `utc_last7d`
|
||||
- `?win_preset=custom&from_utc=2026-05-18 00:00:00&to_utc=2026-05-19 12:00:00`
|
||||
|
||||
## 交易记录与复盘
|
||||
|
||||
- 交易记录盈亏以**本地估算**为准(平仓时按成交/计划价计算);盈亏列可标注 **估**。
|
||||
- 与币安 App 不一致时,请在「核对修改」或复盘中 **手工填写** `reviewed_pnl_amount` 覆盖展示(不再提供批量「同步交易所盈亏」)。
|
||||
- **列表默认只显示当前 UTC 时间窗内**的记录(见上节);导出 CSV 同步该时间窗。
|
||||
- 表头 **「止损(开仓)」**:展示开仓快照 `initial_stop_loss`(无则回退 `stop_loss`);核对/复盘仍可用有效止损字段。
|
||||
- 平仓写入 `trade_records` 时:`stop_loss` 与 `initial_stop_loss` 均写入**开仓时止损快照**;`key_signal_type` 保留箱体/收敛/斐波来源(`fib_key_monitor_lib.key_signal_type_for_trade_record`)。
|
||||
- **开仓类型**(`entry_reason`):机器单平仓入库时,若未手填,按 `key_signal_type` 自动映射(见下表);列表/导出「开仓类型」列 = 复盘核对值优先,否则入库值,否则按信号映射。
|
||||
|
||||
| `key_signal_type` | 自动写入的 `entry_reason` |
|
||||
|-------------------|---------------------------|
|
||||
| 箱体突破 | 关键位箱体突破 |
|
||||
| 收敛突破 | 关键位收敛突破 |
|
||||
| 斐波回调0.618 | 关键位斐波0.618 |
|
||||
| 斐波回调0.786 | 关键位斐波0.786 |
|
||||
|
||||
- 复盘表单 **开仓类型** 下拉新增上述四条固定文案(与趋势/波段类并列)。
|
||||
- 复盘 **离场触发** 新增 **「止盈」**;从交易记录「填入复盘」时,若结果为「止盈/保本止盈/移动止盈/止损/手动平仓」会自动选中对应触发项,并按 `key_signal_type` 预填开仓类型。
|
||||
- 勾选「保存时自动生成多周期 K 线图」时:以 **平仓时间** 为锚点,各周期向前约 `ORDER_CHART_LIMIT`(默认 100)根 K 线(`_fetch_ohlcv_ending_at`),不再固定拉「最近 100 根」。
|
||||
- `/api/journals`、`/api/reviews` 支持同一时间窗 query,与列表一致。
|
||||
|
||||
### 导出(交易记录 v3)
|
||||
|
||||
- 文件名:`trade_records_v3_YYYYMMDD.csv`
|
||||
- 相对 v2 增加:`key_signal_type`、`initial_stop_loss`(及开仓快照列)、`planned_rr`、`actual_rr`、`risk_amount`、交易所盈亏与时间字段等;末列「开仓类型」为有效展示文案。
|
||||
- 「关键位历史」导出同样受 UTC 时间窗限制。
|
||||
|
||||
## 实盘下单页
|
||||
|
||||
- 左列:实盘下单监控(表单、划转、规则)。
|
||||
- 右列:实时持仓(独立模块)。
|
||||
- **人工开仓门控**:计划盈亏比 < `MANUAL_MIN_PLANNED_RR`(默认 **1.4**)时前端弹窗 + 后端拒绝。
|
||||
- **移动保本**(勾选启用):监控轮询达到触发 RR 后,止损阶梯上移时**同步交易所**——**先撤**该合约全部 TP/SL(含 Algo 条件单)**再挂**新止损 + 原止盈(`replace_active_monitor_tpsl_on_exchange`)。仅交易所成功后才写库;失败发企业微信告警。未配置实盘 API 时仍只更新本地。
|
||||
|
||||
## 统计分析页(`/stats`)
|
||||
|
||||
| 项 | 说明 |
|
||||
|----|------|
|
||||
| 切日 | **北京时间**;交易日边界 = 每日 `TRADING_DAY_RESET_HOUR:00`(`.env` 默认 **8**) |
|
||||
| 品类下拉 | 页顶 **「统计品类」** 下拉切换(默认「全部交易」):全部交易、下单监控、关键位箱体突破、关键位收敛结构、关键位斐波0.618、关键位斐波0.786;一次只显示所选品类的日/周/月 |
|
||||
| URL | 切换后写入 `stats_segment=`(如 `all`、`manual`、`key_box`、`key_conv`、`key_fib618`、`key_fib786`),刷新 `/stats` 可保持选项 |
|
||||
| 每块指标 | 日 / 周 / 月:开单次数、平仓笔数、胜率、净盈亏、回撤、连续亏损等(与原口径一致) |
|
||||
| 开单次数 | 人工块:`monitor_type=下单监控` 且无 `key_signal_type`;关键位块:按 `order_monitors.key_signal_type` 计数 |
|
||||
| 不受 UTC 窗影响 | 统计始终基于库内全部已平仓记录,按北京交易日归类,**不**随顶栏 UTC 列表窗切换 |
|
||||
|
||||
## 持仓与计仓
|
||||
|
||||
- `MAX_ACTIVE_POSITIONS` 默认 **1**(可在 `.env` 调大)。
|
||||
- 关键位自动开仓:在已有持仓时,若 `KEY_SIZING_USE_ZERO_POSITION_SNAPSHOT=true`,按**首笔开仓前**交易账户资金快照计仓(字段 `trading_sessions.key_sizing_capital_snapshot`)。
|
||||
|
||||
## 配置
|
||||
|
||||
详见 `.env.example` 中「关键位门控」「交易执行 / 人工风控」注释段。
|
||||
|
||||
## 自动备份(服务器)
|
||||
|
||||
- 脚本:`scripts/backup_data.sh`(`crypto.db` + `static/images`)
|
||||
- 定时:`scripts/install_backup_cron.sh` → 每天 **北京时间 0:00**,目录 **`/root/backups/<实例名>/YYYY-MM-DD/`**,保留 **30** 天
|
||||
- 详见 `部署文档.md` 第 5.4 节(自动备份)
|
||||
|
||||
## 数据库(启动时自动迁移)
|
||||
|
||||
`key_monitors` 斐波字段:`fib_limit_order_id`、`fib_entry_price`、`fib_stop_loss`、`fib_take_profit`、`fib_order_amount`、`fib_margin_capital`、`fib_leverage`。
|
||||
|
||||
`trade_records` / `order_monitors`:`key_signal_type`、`exchange_realized_pnl`、`exchange_opened_at`、`exchange_closed_at`、`exchange_sync_key`、`entry_reason`、`reviewed_entry_reason`、`initial_stop_loss`。
|
||||
|
||||
**历史数据**:本次**不做**旧记录的批量回填(`entry_reason` / `initial_stop_loss` / `key_signal_type` 等);仅**新产生**的平仓与复盘按新逻辑写入。旧行展示可回退已有字段。
|
||||
|
||||
## 涉及文件(便于排查)
|
||||
|
||||
| 路径 | 说明 |
|
||||
|------|------|
|
||||
| `history_window_lib.py` | UTC 时间窗解析与转北京时间 SQL 字符串 |
|
||||
| `fib_key_monitor_lib.py` | 斐波计算、`KEY_ENTRY_REASON_BY_SIGNAL`、`entry_reason_from_key_signal` |
|
||||
| `crypto_monitor_binance/app.py` | 列表筛选、统计分块、导出 v3、复盘 K 线锚点、入库逻辑 |
|
||||
| `crypto_monitor_binance/templates/index.html` | 顶栏时间窗、统计分块 UI、止损(开仓)列、复盘预填 |
|
||||
|
||||
## 升级步骤
|
||||
|
||||
1. `git pull` 后对比 `.env.example`,把新增变量合并进本地 `.env`。
|
||||
2. 在 VPS 上为 Binance / Gate / Gate Bot **各执行一次** `bash scripts/install_backup_cron.sh`(若尚未安装)。
|
||||
3. 重启 Binance 实例(如 `pm2 restart crypto_binance`);SQLite 会自动 `ALTER` 缺列(斐波、交易所盈亏、`entry_reason` 等)。
|
||||
4. 浏览器强刷(Ctrl+F5)避免旧版 `index.html` 缓存。
|
||||
5. 打开任意页确认顶栏出现 **「列表筛选(UTC)」**;`/stats` 可见分品类统计与「北京 8:00 切日」说明。
|
||||
6. 建议先用测试币验证斐波:限价挂出、标记价失效撤单、成交后 TP/SL 与订单监控是否正常;平仓后检查交易记录止损(开仓)与开仓类型。
|
||||
# 界面与风控更新说明(Binance 实例)
|
||||
|
||||
## 顶栏导航(4 项)
|
||||
|
||||
| 顺序 | 名称 | 路由 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 1 | 关键位监控 | `/key_monitor` | 关键位添加,实时门控,历史 |
|
||||
| 2 | 实盘下单 | `/trade` | 人工开仓,划转,实时持仓(**默认首页** `/` → `/trade`) |
|
||||
| 3 | 交易记录与复盘 | `/records` | 交易记录,复盘表单,AI 历史(受顶栏 UTC 时间窗筛选) |
|
||||
| 4 | 统计分析 | `/stats` | 按北京时间交易日切日 + 分品类统计块 |
|
||||
|
||||
## 关键位监控页
|
||||
|
||||
- 标题去掉「5m」;规则条从 `.env` 读取(周期,确认K,量能,自动开仓盈亏比,日成交量排名).
|
||||
- 左列:活跃关键位,**pos-card** 样式展示现价/距上沿/距下沿/门控.
|
||||
- 右列:关键位历史(失效/结案),与左列等高滚动;**受顶栏 UTC 列表时间窗筛选**(默认 UTC 当日).
|
||||
- 监控类型新增:**斐波回调0.618**,**斐波回调0.786**(与 Gate 主站同一套规则,计算逻辑见仓库根目录 `fib_key_monitor_lib.py`).
|
||||
|
||||
### 斐波关键位监控(方案 A:交易所限价)
|
||||
|
||||
| 项 | 说明 |
|
||||
|----|------|
|
||||
| 同币互斥 | 每个币种只能有一条斐波监控(0.618 与 0.786 不可并存) |
|
||||
| 上下沿 | 上沿 **H**,下沿 **L**(须 H > L) |
|
||||
| 挂单价 E | **做多** `E = H − ratio × (H − L)`(自 H 向下回撤);**做空** `E = L + ratio × (H − L)`(自 L 向上反弹) |
|
||||
| 做多 | 限价 @ E,止损 L,止盈 H |
|
||||
| 做空 | 限价 @ E,止损 H,止盈 L |
|
||||
| 添加后 | **立即**在 Binance U 本位挂限价单;卡片显示 **挂E**,限价单 ID |
|
||||
| 失效 | 以**标记价**判断:做多且标记价 ≥ H,做空且标记价 ≤ L,且限价**未成交** → 撤销该限价单并结案 |
|
||||
| 成交后 | 挂交易所 TP/SL(含 Algo 通道条件单)→ 写入 **实盘下单监控**(`monitor_type=关键位监控`,`key_signal_type=斐波回调…`)→ 从关键位列表移除 |
|
||||
| 撤单 | 仅撤本条斐波的订单 ID,**不会**对该合约 `cancel_all_orders` / 全撤 Algo,避免误伤其他委托 |
|
||||
| 盈亏比 | 计划 RR 须 > `KEY_AUTO_MIN_PLANNED_RR`;0.618 理论约 1.6:1,0.786 约 3.7:1 |
|
||||
| 日成交量 | 与箱体/收敛相同,须在前 `KEY_DAILY_VOLUME_RANK_MAX` 名内方可添加 |
|
||||
|
||||
后台轮询:`check_fib_key_monitors()`;箱体/收敛仍走 `check_key_monitors()`.
|
||||
|
||||
手动删除关键位时,未成交斐波会先撤限价再删库.
|
||||
|
||||
### 箱体 / 收敛自动开仓(来源标注)
|
||||
|
||||
- 自动开仓写入 `order_monitors.key_signal_type`:`箱体突破` 或 `收敛突破`.
|
||||
- 持仓与交易记录展示「来源 · 信号类型」.
|
||||
|
||||
## 列表时间窗(UTC,全站顶栏)
|
||||
|
||||
共用模块:仓库根目录 `history_window_lib.py`(Gate / Binance 主站一致).
|
||||
|
||||
| 项 | 说明 |
|
||||
|----|------|
|
||||
| 默认 | **UTC 当日**(`win_preset=utc_today`,从 UTC 0:00 至当前时刻) |
|
||||
| 可选 | 近 24 小时,近 7 天,自定义起止(UTC,`datetime-local`) |
|
||||
| 作用范围 | 关键位历史,交易记录列表,复盘记录 API,AI 历史 API,导出「交易记录」「关键位历史」 |
|
||||
| 与统计的关系 | **仅影响列表/导出**;**统计分析页仍按北京时间 `TRADING_DAY_RESET_HOUR`(默认 8:00)切交易日** |
|
||||
| 库内时间 | DB 存北京时间字符串;后端用 `utc_window_to_bj_sql_strings()` 换算后再 SQL 比较 |
|
||||
| 切换方式 | 顶栏「列表筛选(UTC)」→ 选预设 → **应用**(保留当前路由,如 `/records?win_preset=…`) |
|
||||
|
||||
查询参数示例:
|
||||
|
||||
- `?win_preset=utc_today`
|
||||
- `?win_preset=utc_last24h` / `utc_last7d`
|
||||
- `?win_preset=custom&from_utc=2026-05-18 00:00:00&to_utc=2026-05-19 12:00:00`
|
||||
|
||||
## 交易记录与复盘
|
||||
|
||||
- 交易记录盈亏以**本地估算**为准(平仓时按成交/计划价计算);盈亏列可标注 **估**.
|
||||
- 与币安 App 不一致时,请在「核对修改」或复盘中 **手工填写** `reviewed_pnl_amount` 覆盖展示(不再提供批量「同步交易所盈亏」).
|
||||
- **列表默认只显示当前 UTC 时间窗内**的记录(见上节);导出 CSV 同步该时间窗.
|
||||
- 表头 **「止损(开仓)」**:展示开仓快照 `initial_stop_loss`(无则回退 `stop_loss`);核对/复盘仍可用有效止损字段.
|
||||
- 平仓写入 `trade_records` 时:`stop_loss` 与 `initial_stop_loss` 均写入**开仓时止损快照**;`key_signal_type` 保留箱体/收敛/斐波来源(`fib_key_monitor_lib.key_signal_type_for_trade_record`).
|
||||
- **开仓类型**(`entry_reason`):机器单平仓入库时,若未手填,按 `key_signal_type` 自动映射(见下表);列表/导出「开仓类型」列 = 复盘核对值优先,否则入库值,否则按信号映射.
|
||||
|
||||
| `key_signal_type` | 自动写入的 `entry_reason` |
|
||||
|-------------------|---------------------------|
|
||||
| 箱体突破 | 关键位箱体突破 |
|
||||
| 收敛突破 | 关键位收敛突破 |
|
||||
| 斐波回调0.618 | 关键位斐波0.618 |
|
||||
| 斐波回调0.786 | 关键位斐波0.786 |
|
||||
|
||||
- 复盘表单 **开仓类型** 下拉新增上述四条固定文案(与趋势/波段类并列).
|
||||
- 复盘 **离场触发** 新增 **「止盈」**;从交易记录「填入复盘」时,若结果为「止盈/保本止盈/移动止盈/止损/手动平仓」会自动选中对应触发项,并按 `key_signal_type` 预填开仓类型.
|
||||
- 勾选「保存时自动生成多周期 K 线图」时:以 **平仓时间** 为锚点,各周期向前约 `ORDER_CHART_LIMIT`(默认 100)根 K 线(`_fetch_ohlcv_ending_at`),不再固定拉「最近 100 根」.
|
||||
- `/api/journals`,`/api/reviews` 支持同一时间窗 query,与列表一致.
|
||||
|
||||
### 导出(交易记录 v3)
|
||||
|
||||
- 文件名:`trade_records_v3_YYYYMMDD.csv`
|
||||
- 相对 v2 增加:`key_signal_type`,`initial_stop_loss`(及开仓快照列),`planned_rr`,`actual_rr`,`risk_amount`,交易所盈亏与时间字段等;末列「开仓类型」为有效展示文案.
|
||||
- 「关键位历史」导出同样受 UTC 时间窗限制.
|
||||
|
||||
## 实盘下单页
|
||||
|
||||
- 左列:实盘下单监控(表单,划转,规则).
|
||||
- 右列:实时持仓(独立模块).
|
||||
- **人工开仓门控**:计划盈亏比 < `MANUAL_MIN_PLANNED_RR`(默认 **1.4**)时前端弹窗 + 后端拒绝.
|
||||
- **移动保本**(勾选启用):监控轮询达到触发 RR 后,止损阶梯上移时**同步交易所**——**先撤**该合约全部 TP/SL(含 Algo 条件单)**再挂**新止损 + 原止盈(`replace_active_monitor_tpsl_on_exchange`).仅交易所成功后才写库;失败发企业微信告警.未配置实盘 API 时仍只更新本地.
|
||||
|
||||
## 统计分析页(`/stats`)
|
||||
|
||||
| 项 | 说明 |
|
||||
|----|------|
|
||||
| 切日 | **北京时间**;交易日边界 = 每日 `TRADING_DAY_RESET_HOUR:00`(`.env` 默认 **8**) |
|
||||
| 品类下拉 | 页顶 **「统计品类」** 下拉切换(默认「全部交易」):全部交易,下单监控,关键位箱体突破,关键位收敛结构,关键位斐波0.618,关键位斐波0.786;一次只显示所选品类的日/周/月 |
|
||||
| URL | 切换后写入 `stats_segment=`(如 `all`,`manual`,`key_box`,`key_conv`,`key_fib618`,`key_fib786`),刷新 `/stats` 可保持选项 |
|
||||
| 每块指标 | 日 / 周 / 月:开单次数,平仓笔数,胜率,净盈亏,回撤,连续亏损等(与原口径一致) |
|
||||
| 开单次数 | 人工块:`monitor_type=下单监控` 且无 `key_signal_type`;关键位块:按 `order_monitors.key_signal_type` 计数 |
|
||||
| 不受 UTC 窗影响 | 统计始终基于库内全部已平仓记录,按北京交易日归类,**不**随顶栏 UTC 列表窗切换 |
|
||||
|
||||
## 持仓与计仓
|
||||
|
||||
- `MAX_ACTIVE_POSITIONS` 默认 **1**(可在 `.env` 调大).
|
||||
- 关键位自动开仓:在已有持仓时,若 `KEY_SIZING_USE_ZERO_POSITION_SNAPSHOT=true`,按**首笔开仓前**交易账户资金快照计仓(字段 `trading_sessions.key_sizing_capital_snapshot`).
|
||||
|
||||
## 配置
|
||||
|
||||
详见 `.env.example` 中「关键位门控」「交易执行 / 人工风控」注释段.
|
||||
|
||||
## 自动备份(服务器)
|
||||
|
||||
- 脚本:`scripts/backup_data.sh`(`crypto.db` + `static/images`)
|
||||
- 定时:`scripts/install_backup_cron.sh` → 每天 **北京时间 0:00**,目录 **`/root/backups/<实例名>/YYYY-MM-DD/`**,保留 **30** 天
|
||||
- 详见 `部署文档.md` 第 5.4 节(自动备份)
|
||||
|
||||
## 数据库(启动时自动迁移)
|
||||
|
||||
`key_monitors` 斐波字段:`fib_limit_order_id`,`fib_entry_price`,`fib_stop_loss`,`fib_take_profit`,`fib_order_amount`,`fib_margin_capital`,`fib_leverage`.
|
||||
|
||||
`trade_records` / `order_monitors`:`key_signal_type`,`exchange_realized_pnl`,`exchange_opened_at`,`exchange_closed_at`,`exchange_sync_key`,`entry_reason`,`reviewed_entry_reason`,`initial_stop_loss`.
|
||||
|
||||
**历史数据**:本次**不做**旧记录的批量回填(`entry_reason` / `initial_stop_loss` / `key_signal_type` 等);仅**新产生**的平仓与复盘按新逻辑写入.旧行展示可回退已有字段.
|
||||
|
||||
## 涉及文件(便于排查)
|
||||
|
||||
| 路径 | 说明 |
|
||||
|------|------|
|
||||
| `history_window_lib.py` | UTC 时间窗解析与转北京时间 SQL 字符串 |
|
||||
| `fib_key_monitor_lib.py` | 斐波计算,`KEY_ENTRY_REASON_BY_SIGNAL`,`entry_reason_from_key_signal` |
|
||||
| `crypto_monitor_binance/app.py` | 列表筛选,统计分块,导出 v3,复盘 K 线锚点,入库逻辑 |
|
||||
| `crypto_monitor_binance/templates/index.html` | 顶栏时间窗,统计分块 UI,止损(开仓)列,复盘预填 |
|
||||
|
||||
## 升级步骤
|
||||
|
||||
1. `git pull` 后对比 `.env.example`,把新增变量合并进本地 `.env`.
|
||||
2. 在 VPS 上为 Binance / Gate / **各执行一次** `bash scripts/install_backup_cron.sh`(若尚未安装).
|
||||
3. 重启 Binance 实例(如 `pm2 restart crypto_binance`);SQLite 会自动 `ALTER` 缺列(斐波,交易所盈亏,`entry_reason` 等).
|
||||
4. 浏览器强刷(Ctrl+F5)避免旧版 `index.html` 缓存.
|
||||
5. 打开任意页确认顶栏出现 **「列表筛选(UTC)」**;`/stats` 可见分品类统计与「北京 8:00 切日」说明.
|
||||
6. 建议先用测试币验证斐波:限价挂出,标记价失效撤单,成交后 TP/SL 与订单监控是否正常;平仓后检查交易记录止损(开仓)与开仓类型.
|
||||
|
||||
@@ -1,389 +1,389 @@
|
||||
# `crypto_monitor_binance` 部署指南:SSH SOCKS + Binance + PM2(Ubuntu)
|
||||
|
||||
项目功能、环境变量总览见 **[README.md](./README.md)**。Ubuntu 环境(Python / Node / PM2)见 **[docs/ubuntu-server.md](../docs/ubuntu-server.md)**。
|
||||
|
||||
本文面向:**在本机或 VPS 上运行本项目**,但 **直连 Binance API 不稳定、超时或被网络策略拦截** 的场景。思路是:
|
||||
|
||||
- 本机用 `ssh -D` 做动态转发,把 **SOCKS5 出口**放到能稳定访问 Binance 的机器(常见为一台境外 VPS)
|
||||
- 项目在 `.env` 中设置 **`BINANCE_SOCKS_PROXY=socks5h://127.0.0.1:1080`**(或你实际端口),`ccxt` 经 SOCKS 访问交易所
|
||||
- **SSH 隧道**:用 `ssh -D` 在本机常驻(可用 **tmux** 或 **autossh** 保持连接),**不要** 把 `ssh` 交给 PM2
|
||||
- 使用 **PM2** 仅托管 **Flask 应用**;仓库根目录 **`ecosystem.config.cjs`** 默认进程名为 **`crypto-monitor-binance`**
|
||||
|
||||
> 安全提醒:不要把 `.env`、私钥 `.pem`、Binance API Key / Secret 提交到 Git;下文只用占位符。
|
||||
|
||||
---
|
||||
|
||||
## 0. 你需要准备的东西
|
||||
|
||||
- 一台 **Ubuntu**(或同类 Linux)运行项目的机器(下文称「本机」)
|
||||
- 一台可 SSH 登录、且 **能正常访问 Binance API** 的 VPS(示例:`HostName` 填你的服务器 IP,用户如 `root`)
|
||||
- SSH:**私钥登录**(推荐,便于隧道脚本无人值守)
|
||||
- 本机已安装:`python3`、`python3-venv`、`pip`、`curl`、`ssh`、`git`(可选)、`node` + `npm`(安装 PM2)
|
||||
- Binance 账户:已开通 **USDT-M 永续合约**;API Key 勾选 **合约**、**万向划转**(若使用资金↔合约划转)等所需权限,并配置 **IP 白名单**(若启用)
|
||||
|
||||
---
|
||||
|
||||
## 1. 获取代码与目录
|
||||
|
||||
将包含 `app.py` 的项目放到固定目录,例如:
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/crypto_monitor
|
||||
cd /opt/crypto_monitor
|
||||
git clone https://git.bz121.com/dekun/crypto_monitor.git
|
||||
cd crypto_monitor/crypto_monitor_binance
|
||||
```
|
||||
|
||||
下文用 **`/opt/crypto_monitor/crypto_monitor_binance`** 仅为示例,请换成你的实际绝对路径。
|
||||
|
||||
拉取代码后,若目录下尚无 `.env`,先从模板生成(**勿**把填好密钥的 `.env` 提交 Git):
|
||||
|
||||
```bash
|
||||
cp -n .env.example .env # -n:已存在 .env 时不覆盖
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 配置 SSH 私钥与 `~/.ssh/config`
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
# 私钥示例:~/.ssh/vps1.pem
|
||||
chmod 600 ~/.ssh/vps1.pem
|
||||
```
|
||||
|
||||
编辑 `~/.ssh/config`(示例别名 **`bn-vps`**,与你手工启动 `ssh -D ... bn-vps` 一致即可):
|
||||
|
||||
```sshconfig
|
||||
Host bn-vps
|
||||
HostName 你的_VPS_IP
|
||||
User root
|
||||
IdentityFile ~/.ssh/vps1.pem
|
||||
IdentitiesOnly yes
|
||||
ServerAliveInterval 30
|
||||
ServerAliveCountMax 3
|
||||
ExitOnForwardFailure yes
|
||||
BatchMode yes
|
||||
```
|
||||
|
||||
测试:
|
||||
|
||||
```bash
|
||||
ssh bn-vps true
|
||||
```
|
||||
|
||||
> 若尚未完全改为密钥登录,可暂时注释 `BatchMode yes`,调试完成后再打开。
|
||||
|
||||
---
|
||||
|
||||
## 3. 手工验证:SSH SOCKS + Binance API
|
||||
|
||||
### 3.1 本地 SOCKS(示例端口 1080)
|
||||
|
||||
```bash
|
||||
ssh -N -D 127.0.0.1:1080 bn-vps
|
||||
```
|
||||
|
||||
保持运行,另开终端继续。
|
||||
|
||||
### 3.2 验证经 SOCKS 可访问 Binance(公开接口)
|
||||
|
||||
```bash
|
||||
curl -4 -sS --max-time 15 --proxy socks5h://127.0.0.1:1080 https://api.binance.com/api/v3/time
|
||||
```
|
||||
|
||||
应返回 JSON(含 `serverTime` 字段)。若此处失败,**不要先启动应用**:先修隧道或 VPS 出站。
|
||||
|
||||
---
|
||||
|
||||
## 4. Python 虚拟环境
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_binance
|
||||
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
python -m pip install -U pip
|
||||
pip install flask requests ccxt werkzeug PySocks Pillow
|
||||
```
|
||||
|
||||
走 SOCKS 时 **必须** 安装 **`PySocks`**,否则易出现代理相关报错。
|
||||
|
||||
可选:
|
||||
|
||||
```bash
|
||||
export PYTHONDONTWRITEBYTECODE=1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 配置环境变量(`.env.example` → `.env`)
|
||||
|
||||
| 文件 | 是否进 Git | 说明 |
|
||||
|------|------------|------|
|
||||
| **`.env.example`** | ✅ 是 | 变量模板与注释,可随 `git pull` 更新 |
|
||||
| **`.env`** | ❌ 否 | 本机真实配置;`app.py` **只读此文件** |
|
||||
|
||||
### 5.1 首次配置
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_binance
|
||||
|
||||
cp -n .env.example .env # 已存在 .env 时不覆盖
|
||||
nano .env # 填入 API、登录密码、端口、代理等
|
||||
```
|
||||
|
||||
### 5.2 备份与 `git pull`
|
||||
|
||||
- **`.env` 已被仓库根目录 `.gitignore` 忽略**:`git pull` **不会**覆盖或删除你本地的 `.env`。
|
||||
- 若远端更新了 **`.env.example`**(新增变量名),pull 后请对照模板,**手动把新行补进你的 `.env`**(不会自动合并进 `.env`)。
|
||||
- **建议在每次 `git pull` 或大批量改配置前备份**:
|
||||
|
||||
```bash
|
||||
cp .env .env.backup.$(date +%Y%m%d)
|
||||
# 恢复示例:cp .env.backup.20260516 .env
|
||||
```
|
||||
|
||||
- **换机 / 迁移**:用 `scp` 复制整份 `.env` 到新机器对应目录;或在新机重新 `cp .env.example .env` 后填写。
|
||||
|
||||
### 5.3 AI 复盘与模型(可选)
|
||||
|
||||
四所共用仓库根目录 **`ai_client.py`**(PM2 的 **`PYTHONPATH=..`** 须包含仓库根)。在 `.env` 中配置 **`AI_PROVIDER`**:
|
||||
|
||||
| 模式 | 主要变量 |
|
||||
|------|----------|
|
||||
| **`openai`**(默认) | `OPENAI_API_BASE=https://op.bz121.com/v1`、`OPENAI_API_KEY`、`OPENAI_MODEL=gemma4:e4b` |
|
||||
| **`ollama`** | `OLLAMA_API`、`AI_MODEL`(本机 Ollama) |
|
||||
|
||||
密钥在 [op.bz121.com](https://op.bz121.com/) 的 **`gateway.json`** 页面获取。改 `.env` 后需 **`pm2 restart`** 对应进程。详见根目录 **[AI复盘与模型配置说明.md](../AI复盘与模型配置说明.md)**。
|
||||
|
||||
### 5.4 自动备份(数据库 + 复盘图片)
|
||||
|
||||
默认每天 **北京时间 0:00** 备份到 **`/root/backups`**,保留 **30 天** 后自动删除更早的目录。
|
||||
|
||||
备份内容(路径来自 `.env` 的 `DB_PATH`、`UPLOAD_DIR`):
|
||||
|
||||
- `crypto.db`(优先 `sqlite3 .backup` 热备)
|
||||
- `static/images` 打包为 `static_images.tar.gz`
|
||||
|
||||
目录结构示例:
|
||||
|
||||
```text
|
||||
/root/backups/crypto_monitor_binance/2026-05-17/
|
||||
crypto.db
|
||||
static_images.tar.gz
|
||||
manifest.txt
|
||||
```
|
||||
|
||||
**一次性安装定时任务**(在对应项目目录执行,Binance / Gate 各执行一次):
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_binance
|
||||
chmod +x scripts/backup_data.sh scripts/install_backup_cron.sh
|
||||
bash scripts/install_backup_cron.sh
|
||||
```
|
||||
|
||||
Gate 实例:
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
bash scripts/install_backup_cron.sh
|
||||
```
|
||||
|
||||
Gate Bot 实例(趋势回调等):
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate_bot
|
||||
bash scripts/install_backup_cron.sh
|
||||
```
|
||||
|
||||
**立即试跑**(不写 cron):
|
||||
|
||||
```bash
|
||||
bash scripts/backup_data.sh
|
||||
```
|
||||
|
||||
日志默认:`/var/log/crypto-monitor-backup-<项目目录名>.log`。可选在 `.env` 中覆盖:`BACKUP_ROOT`、`BACKUP_RETENTION_DAYS`、`BACKUP_INSTANCE`。
|
||||
|
||||
**恢复示例**(先停 PM2,再覆盖文件):
|
||||
|
||||
```bash
|
||||
pm2 stop crypto-monitor-binance
|
||||
cp /root/backups/crypto_monitor_binance/2026-05-16/crypto.db ./crypto.db
|
||||
tar -xzf /root/backups/crypto_monitor_binance/2026-05-16/static_images.tar.gz -C .
|
||||
pm2 start ecosystem.config.cjs
|
||||
```
|
||||
|
||||
建议安装:`apt install -y sqlite3`(热备更稳)。
|
||||
|
||||
### 5.5 必填项检查(Binance + 代理)
|
||||
|
||||
与交易所相关的变量使用 **`BINANCE_`** 前缀(与代码一致)。至少确认:
|
||||
|
||||
```env
|
||||
APP_HOST=127.0.0.1
|
||||
APP_PORT=5000
|
||||
|
||||
# 实盘(按需)
|
||||
LIVE_TRADING_ENABLED=false
|
||||
BINANCE_API_KEY=你的_Key
|
||||
BINANCE_API_SECRET=你的_Secret
|
||||
|
||||
# 保证金:cross=全仓 isolated=逐仓(与币安账户/习惯一致)
|
||||
BINANCE_MARGIN_MODE=cross
|
||||
|
||||
# 持仓模式:hedge=双向(需在币安开启双向持仓);oneway=单向
|
||||
BINANCE_POSITION_MODE=hedge
|
||||
|
||||
# 条件单触发参考:CONTRACT_PRICE=最新成交价 MARK_PRICE=标记价
|
||||
BINANCE_TRIGGER_WORKING_TYPE=CONTRACT_PRICE
|
||||
|
||||
# 经本机 SSH 动态转发访问 Binance(端口与隧道一致)
|
||||
BINANCE_SOCKS_PROXY=socks5h://127.0.0.1:1080
|
||||
|
||||
# 若不用 SOCKS,可改用 HTTP 代理(一般二选一)
|
||||
# BINANCE_HTTP_PROXY=http://127.0.0.1:7890
|
||||
# BINANCE_HTTPS_PROXY=http://127.0.0.1:7890
|
||||
```
|
||||
|
||||
说明:**推荐 `socks5h://`**,由 SOCKS 端解析域名,与 `curl --proxy socks5h://...` 行为一致。
|
||||
|
||||
**止盈止损说明(应用逻辑)**:实盘开仓后,程序会在 Binance USDT-M 永续上挂 **`STOP_MARKET`(止损)** 与 **`TAKE_PROFIT_MARKET`(止盈)**;`BINANCE_POSITION_MODE=hedge` 时会自动带 **`positionSide`**,须与币安合约「双向持仓」开关一致。不显式传 **`reduceOnly`**(否则易触发 API **`-1106`**:`Parameter 'reduceOnly' sent when not required`)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 自检脚本(可选)
|
||||
|
||||
在已配置 `.env` 且网络可达的前提下:
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_binance
|
||||
source .venv/bin/activate
|
||||
python scripts/verify_binance_funding.py
|
||||
```
|
||||
|
||||
用于粗测资金钱包与合约钱包 USDT 读取(需有效 API 与权限)。
|
||||
|
||||
---
|
||||
|
||||
## 7. 手工启动 Flask(验证)
|
||||
|
||||
1. SOCKS 已监听 `127.0.0.1:1080`(若使用代理)
|
||||
2. 已 `source .venv/bin/activate`
|
||||
3. `.env` 已按需配置 `BINANCE_SOCKS_PROXY` 等
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_binance
|
||||
source .venv/bin/activate
|
||||
python app.py
|
||||
```
|
||||
|
||||
浏览器访问:`http://127.0.0.1:5000`(或你在 `.env` 中的端口)。
|
||||
|
||||
---
|
||||
|
||||
## 8. 安装 PM2
|
||||
|
||||
```bash
|
||||
sudo npm i -g pm2
|
||||
pm2 -v
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. PM2:使用仓库内 `ecosystem.config.cjs`(推荐)
|
||||
|
||||
在项目根目录:
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_binance
|
||||
pm2 start ecosystem.config.cjs
|
||||
pm2 status
|
||||
pm2 logs --lines 200
|
||||
```
|
||||
|
||||
默认只启动 **`crypto-monitor-binance`**(`.venv/bin/python app.py`)。
|
||||
|
||||
### 本机已可直连 Binance、不需要隧道时
|
||||
|
||||
`.env` 里应 **去掉或留空** `BINANCE_SOCKS_PROXY`(除非仍要走别的代理),再 `pm2 start ecosystem.config.cjs`。
|
||||
|
||||
### 开机自启
|
||||
|
||||
```bash
|
||||
pm2 save
|
||||
pm2 startup
|
||||
# 按屏幕提示执行一条 sudo 命令
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 等价手工命令(不使用 ecosystem 文件时)
|
||||
|
||||
### 10.1 SSH SOCKS(自行后台常驻,不推荐用 PM2)
|
||||
|
||||
示例(前台调试;生产请用 **PM2**,见本文 §6 与 [docs/ubuntu-server.md](../docs/ubuntu-server.md)):
|
||||
|
||||
```bash
|
||||
ssh -N -D 127.0.0.1:1080 bn-vps \
|
||||
-o ServerAliveInterval=30 -o ServerAliveCountMax=3 \
|
||||
-o ExitOnForwardFailure=yes
|
||||
```
|
||||
|
||||
### 10.2 Flask
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_binance
|
||||
pm2 start /opt/crypto_monitor/crypto_monitor_binance/.venv/bin/python --name crypto-monitor-binance -- \
|
||||
/opt/crypto_monitor/crypto_monitor_binance/app.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. 交易所「连接不上」排查清单
|
||||
|
||||
1. **`.env` 是否为 Binance 变量**:`BINANCE_SOCKS_PROXY` / `BINANCE_HTTP_PROXY` / `BINANCE_API_KEY` / `BINANCE_API_SECRET` 等前缀需与代码一致。
|
||||
2. **隧道是否在本机端口监听**(若配置了 `BINANCE_SOCKS_PROXY`):
|
||||
```bash
|
||||
ss -lntp | grep 1080 || true
|
||||
```
|
||||
3. **curl 复测 Binance**(与第 3.2 节相同);curl 不通则应用也不会通。
|
||||
4. **PySocks**:`pip show PySocks`,缺失则 `pip install PySocks`。
|
||||
5. **SSH 隧道连不上**:检查私钥权限、`~/.ssh/config`、VPS 出站与端口是否与 `.env` 一致。
|
||||
6. **API 权限与 IP 白名单**:Secret 错误、权限不足、未放行当前出口 IP 时,私有接口会失败。
|
||||
7. **启动顺序**:若走代理,先保证 SOCKS 已监听,再 `pm2 start` 应用(或重启应用)。
|
||||
|
||||
---
|
||||
|
||||
## 12. 推荐启动顺序(习惯)
|
||||
|
||||
1. 若走代理:先启动并确认 SSH SOCKS 已监听,再 `curl --proxy socks5h://127.0.0.1:1080 https://api.binance.com/api/v3/time` 成功
|
||||
2. `pm2 start ecosystem.config.cjs`
|
||||
3. 再确认页面与余额等接口正常
|
||||
|
||||
---
|
||||
|
||||
## 13. 免责声明
|
||||
|
||||
交易所有合规与地区政策要求。请确保使用方式符合当地法律法规与交易所条款。本文仅描述网络与工程部署路径。
|
||||
|
||||
---
|
||||
|
||||
## 附录:数据库标签修复脚本 `scripts/fix_breakeven_labels.py`
|
||||
|
||||
在 Ubuntu 上:
|
||||
|
||||
1)预览(不写库):
|
||||
|
||||
```bash
|
||||
python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run
|
||||
```
|
||||
|
||||
2)确认后执行:
|
||||
|
||||
```bash
|
||||
python scripts/fix_breakeven_labels.py --db ./crypto.db --apply
|
||||
```
|
||||
|
||||
默认修复条件:`monitor_type='下单监控'` 且 `result='止损'` 且 `pnl_amount > 0` → 改为 `result='保本止盈'`。
|
||||
# `crypto_monitor_binance` 部署指南:SSH SOCKS + Binance + PM2(Ubuntu)
|
||||
|
||||
项目功能,环境变量总览见 **[README.md](./README.md)**.Ubuntu 环境(Python / Node / PM2)见 **[docs/ubuntu-server.md](../docs/ubuntu-server.md)**.
|
||||
|
||||
本文面向:**在本机或 VPS 上运行本项目**,但 **直连 Binance API 不稳定,超时或被网络策略拦截** 的场景.思路是:
|
||||
|
||||
- 本机用 `ssh -D` 做动态转发,把 **SOCKS5 出口**放到能稳定访问 Binance 的机器(常见为一台境外 VPS)
|
||||
- 项目在 `.env` 中设置 **`BINANCE_SOCKS_PROXY=socks5h://127.0.0.1:1080`**(或你实际端口),`ccxt` 经 SOCKS 访问交易所
|
||||
- **SSH 隧道**:用 `ssh -D` 在本机常驻(可用 **tmux** 或 **autossh** 保持连接),**不要** 把 `ssh` 交给 PM2
|
||||
- 使用 **PM2** 仅托管 **Flask 应用**;仓库根目录 **`ecosystem.config.cjs`** 默认进程名为 **`crypto-monitor-binance`**
|
||||
|
||||
> 安全提醒:不要把 `.env`,私钥 `.pem`,Binance API Key / Secret 提交到 Git;下文只用占位符.
|
||||
|
||||
---
|
||||
|
||||
## 0. 你需要准备的东西
|
||||
|
||||
- 一台 **Ubuntu**(或同类 Linux)运行项目的机器(下文称「本机」)
|
||||
- 一台可 SSH 登录,且 **能正常访问 Binance API** 的 VPS(示例:`HostName` 填你的服务器 IP,用户如 `root`)
|
||||
- SSH:**私钥登录**(推荐,便于隧道脚本无人值守)
|
||||
- 本机已安装:`python3`,`python3-venv`,`pip`,`curl`,`ssh`,`git`(可选),`node` + `npm`(安装 PM2)
|
||||
- Binance 账户:已开通 **USDT-M 永续合约**;API Key 勾选 **合约**,**万向划转**(若使用资金↔合约划转)等所需权限,并配置 **IP 白名单**(若启用)
|
||||
|
||||
---
|
||||
|
||||
## 1. 获取代码与目录
|
||||
|
||||
将包含 `app.py` 的项目放到固定目录,例如:
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/crypto_monitor
|
||||
cd /opt/crypto_monitor
|
||||
git clone https://git.bz121.com/dekun/crypto_monitor.git
|
||||
cd crypto_monitor/crypto_monitor_binance
|
||||
```
|
||||
|
||||
下文用 **`/opt/crypto_monitor/crypto_monitor_binance`** 仅为示例,请换成你的实际绝对路径.
|
||||
|
||||
拉取代码后,若目录下尚无 `.env`,先从模板生成(**勿**把填好密钥的 `.env` 提交 Git):
|
||||
|
||||
```bash
|
||||
cp -n .env.example .env # -n:已存在 .env 时不覆盖
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 配置 SSH 私钥与 `~/.ssh/config`
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
# 私钥示例:~/.ssh/vps1.pem
|
||||
chmod 600 ~/.ssh/vps1.pem
|
||||
```
|
||||
|
||||
编辑 `~/.ssh/config`(示例别名 **`bn-vps`**,与你手工启动 `ssh -D ... bn-vps` 一致即可):
|
||||
|
||||
```sshconfig
|
||||
Host bn-vps
|
||||
HostName 你的_VPS_IP
|
||||
User root
|
||||
IdentityFile ~/.ssh/vps1.pem
|
||||
IdentitiesOnly yes
|
||||
ServerAliveInterval 30
|
||||
ServerAliveCountMax 3
|
||||
ExitOnForwardFailure yes
|
||||
BatchMode yes
|
||||
```
|
||||
|
||||
测试:
|
||||
|
||||
```bash
|
||||
ssh bn-vps true
|
||||
```
|
||||
|
||||
> 若尚未完全改为密钥登录,可暂时注释 `BatchMode yes`,调试完成后再打开.
|
||||
|
||||
---
|
||||
|
||||
## 3. 手工验证:SSH SOCKS + Binance API
|
||||
|
||||
### 3.1 本地 SOCKS(示例端口 1080)
|
||||
|
||||
```bash
|
||||
ssh -N -D 127.0.0.1:1080 bn-vps
|
||||
```
|
||||
|
||||
保持运行,另开终端继续.
|
||||
|
||||
### 3.2 验证经 SOCKS 可访问 Binance(公开接口)
|
||||
|
||||
```bash
|
||||
curl -4 -sS --max-time 15 --proxy socks5h://127.0.0.1:1080 https://api.binance.com/api/v3/time
|
||||
```
|
||||
|
||||
应返回 JSON(含 `serverTime` 字段).若此处失败,**不要先启动应用**:先修隧道或 VPS 出站.
|
||||
|
||||
---
|
||||
|
||||
## 4. Python 虚拟环境
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_binance
|
||||
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
python -m pip install -U pip
|
||||
pip install flask requests ccxt werkzeug PySocks Pillow
|
||||
```
|
||||
|
||||
走 SOCKS 时 **必须** 安装 **`PySocks`**,否则易出现代理相关报错.
|
||||
|
||||
可选:
|
||||
|
||||
```bash
|
||||
export PYTHONDONTWRITEBYTECODE=1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 配置环境变量(`.env.example` → `.env`)
|
||||
|
||||
| 文件 | 是否进 Git | 说明 |
|
||||
|------|------------|------|
|
||||
| **`.env.example`** | ✅ 是 | 变量模板与注释,可随 `git pull` 更新 |
|
||||
| **`.env`** | ❌ 否 | 本机真实配置;`app.py` **只读此文件** |
|
||||
|
||||
### 5.1 首次配置
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_binance
|
||||
|
||||
cp -n .env.example .env # 已存在 .env 时不覆盖
|
||||
nano .env # 填入 API,登录密码,端口,代理等
|
||||
```
|
||||
|
||||
### 5.2 备份与 `git pull`
|
||||
|
||||
- **`.env` 已被仓库根目录 `.gitignore` 忽略**:`git pull` **不会**覆盖或删除你本地的 `.env`.
|
||||
- 若远端更新了 **`.env.example`**(新增变量名),pull 后请对照模板,**手动把新行补进你的 `.env`**(不会自动合并进 `.env`).
|
||||
- **建议在每次 `git pull` 或大批量改配置前备份**:
|
||||
|
||||
```bash
|
||||
cp .env .env.backup.$(date +%Y%m%d)
|
||||
# 恢复示例:cp .env.backup.20260516 .env
|
||||
```
|
||||
|
||||
- **换机 / 迁移**:用 `scp` 复制整份 `.env` 到新机器对应目录;或在新机重新 `cp .env.example .env` 后填写.
|
||||
|
||||
### 5.3 AI 复盘与模型(可选)
|
||||
|
||||
三所共用仓库根目录 **`ai_client.py`**(PM2 的 **`PYTHONPATH=..`** 须包含仓库根).在 `.env` 中配置 **`AI_PROVIDER`**:
|
||||
|
||||
| 模式 | 主要变量 |
|
||||
|------|----------|
|
||||
| **`openai`**(默认) | `OPENAI_API_BASE=https://op.bz121.com/v1`,`OPENAI_API_KEY`,`OPENAI_MODEL=gemma4:e4b` |
|
||||
| **`ollama`** | `OLLAMA_API`,`AI_MODEL`(本机 Ollama) |
|
||||
|
||||
密钥在 [op.bz121.com](https://op.bz121.com/) 的 **`gateway.json`** 页面获取.改 `.env` 后需 **`pm2 restart`** 对应进程.详见根目录 **[AI复盘与模型配置说明.md](../AI复盘与模型配置说明.md)**.
|
||||
|
||||
### 5.4 自动备份(数据库 + 复盘图片)
|
||||
|
||||
默认每天 **北京时间 0:00** 备份到 **`/root/backups`**,保留 **30 天** 后自动删除更早的目录.
|
||||
|
||||
备份内容(路径来自 `.env` 的 `DB_PATH`,`UPLOAD_DIR`):
|
||||
|
||||
- `crypto.db`(优先 `sqlite3 .backup` 热备)
|
||||
- `static/images` 打包为 `static_images.tar.gz`
|
||||
|
||||
目录结构示例:
|
||||
|
||||
```text
|
||||
/root/backups/crypto_monitor_binance/2026-05-17/
|
||||
crypto.db
|
||||
static_images.tar.gz
|
||||
manifest.txt
|
||||
```
|
||||
|
||||
**一次性安装定时任务**(在对应项目目录执行,Binance / Gate 各执行一次):
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_binance
|
||||
chmod +x scripts/backup_data.sh scripts/install_backup_cron.sh
|
||||
bash scripts/install_backup_cron.sh
|
||||
```
|
||||
|
||||
Gate 实例:
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
bash scripts/install_backup_cron.sh
|
||||
```
|
||||
|
||||
实例(趋势回调等):
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
bash scripts/install_backup_cron.sh
|
||||
```
|
||||
|
||||
**立即试跑**(不写 cron):
|
||||
|
||||
```bash
|
||||
bash scripts/backup_data.sh
|
||||
```
|
||||
|
||||
日志默认:`/var/log/crypto-monitor-backup-<项目目录名>.log`.可选在 `.env` 中覆盖:`BACKUP_ROOT`,`BACKUP_RETENTION_DAYS`,`BACKUP_INSTANCE`.
|
||||
|
||||
**恢复示例**(先停 PM2,再覆盖文件):
|
||||
|
||||
```bash
|
||||
pm2 stop crypto-monitor-binance
|
||||
cp /root/backups/crypto_monitor_binance/2026-05-16/crypto.db ./crypto.db
|
||||
tar -xzf /root/backups/crypto_monitor_binance/2026-05-16/static_images.tar.gz -C .
|
||||
pm2 start ecosystem.config.cjs
|
||||
```
|
||||
|
||||
建议安装:`apt install -y sqlite3`(热备更稳).
|
||||
|
||||
### 5.5 必填项检查(Binance + 代理)
|
||||
|
||||
与交易所相关的变量使用 **`BINANCE_`** 前缀(与代码一致).至少确认:
|
||||
|
||||
```env
|
||||
APP_HOST=127.0.0.1
|
||||
APP_PORT=5000
|
||||
|
||||
# 实盘(按需)
|
||||
LIVE_TRADING_ENABLED=false
|
||||
BINANCE_API_KEY=你的_Key
|
||||
BINANCE_API_SECRET=你的_Secret
|
||||
|
||||
# 保证金:cross=全仓 isolated=逐仓(与币安账户/习惯一致)
|
||||
BINANCE_MARGIN_MODE=cross
|
||||
|
||||
# 持仓模式:hedge=双向(需在币安开启双向持仓);oneway=单向
|
||||
BINANCE_POSITION_MODE=hedge
|
||||
|
||||
# 条件单触发参考:CONTRACT_PRICE=最新成交价 MARK_PRICE=标记价
|
||||
BINANCE_TRIGGER_WORKING_TYPE=CONTRACT_PRICE
|
||||
|
||||
# 经本机 SSH 动态转发访问 Binance(端口与隧道一致)
|
||||
BINANCE_SOCKS_PROXY=socks5h://127.0.0.1:1080
|
||||
|
||||
# 若不用 SOCKS,可改用 HTTP 代理(一般二选一)
|
||||
# BINANCE_HTTP_PROXY=http://127.0.0.1:7890
|
||||
# BINANCE_HTTPS_PROXY=http://127.0.0.1:7890
|
||||
```
|
||||
|
||||
说明:**推荐 `socks5h://`**,由 SOCKS 端解析域名,与 `curl --proxy socks5h://...` 行为一致.
|
||||
|
||||
**止盈止损说明(应用逻辑)**:实盘开仓后,程序会在 Binance USDT-M 永续上挂 **`STOP_MARKET`(止损)** 与 **`TAKE_PROFIT_MARKET`(止盈)**;`BINANCE_POSITION_MODE=hedge` 时会自动带 **`positionSide`**,须与币安合约「双向持仓」开关一致.不显式传 **`reduceOnly`**(否则易触发 API **`-1106`**:`Parameter 'reduceOnly' sent when not required`).
|
||||
|
||||
---
|
||||
|
||||
## 6. 自检脚本(可选)
|
||||
|
||||
在已配置 `.env` 且网络可达的前提下:
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_binance
|
||||
source .venv/bin/activate
|
||||
python scripts/verify_binance_funding.py
|
||||
```
|
||||
|
||||
用于粗测资金钱包与合约钱包 USDT 读取(需有效 API 与权限).
|
||||
|
||||
---
|
||||
|
||||
## 7. 手工启动 Flask(验证)
|
||||
|
||||
1. SOCKS 已监听 `127.0.0.1:1080`(若使用代理)
|
||||
2. 已 `source .venv/bin/activate`
|
||||
3. `.env` 已按需配置 `BINANCE_SOCKS_PROXY` 等
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_binance
|
||||
source .venv/bin/activate
|
||||
python app.py
|
||||
```
|
||||
|
||||
浏览器访问:`http://127.0.0.1:5000`(或你在 `.env` 中的端口).
|
||||
|
||||
---
|
||||
|
||||
## 8. 安装 PM2
|
||||
|
||||
```bash
|
||||
sudo npm i -g pm2
|
||||
pm2 -v
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. PM2:使用仓库内 `ecosystem.config.cjs`(推荐)
|
||||
|
||||
在项目根目录:
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_binance
|
||||
pm2 start ecosystem.config.cjs
|
||||
pm2 status
|
||||
pm2 logs --lines 200
|
||||
```
|
||||
|
||||
默认只启动 **`crypto-monitor-binance`**(`.venv/bin/python app.py`).
|
||||
|
||||
### 本机已可直连 Binance,不需要隧道时
|
||||
|
||||
`.env` 里应 **去掉或留空** `BINANCE_SOCKS_PROXY`(除非仍要走别的代理),再 `pm2 start ecosystem.config.cjs`.
|
||||
|
||||
### 开机自启
|
||||
|
||||
```bash
|
||||
pm2 save
|
||||
pm2 startup
|
||||
# 按屏幕提示执行一条 sudo 命令
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 等价手工命令(不使用 ecosystem 文件时)
|
||||
|
||||
### 10.1 SSH SOCKS(自行后台常驻,不推荐用 PM2)
|
||||
|
||||
示例(前台调试;生产请用 **PM2**,见本文 §6 与 [docs/ubuntu-server.md](../docs/ubuntu-server.md)):
|
||||
|
||||
```bash
|
||||
ssh -N -D 127.0.0.1:1080 bn-vps \
|
||||
-o ServerAliveInterval=30 -o ServerAliveCountMax=3 \
|
||||
-o ExitOnForwardFailure=yes
|
||||
```
|
||||
|
||||
### 10.2 Flask
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_binance
|
||||
pm2 start /opt/crypto_monitor/crypto_monitor_binance/.venv/bin/python --name crypto-monitor-binance -- \
|
||||
/opt/crypto_monitor/crypto_monitor_binance/app.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. 交易所「连接不上」排查清单
|
||||
|
||||
1. **`.env` 是否为 Binance 变量**:`BINANCE_SOCKS_PROXY` / `BINANCE_HTTP_PROXY` / `BINANCE_API_KEY` / `BINANCE_API_SECRET` 等前缀需与代码一致.
|
||||
2. **隧道是否在本机端口监听**(若配置了 `BINANCE_SOCKS_PROXY`):
|
||||
```bash
|
||||
ss -lntp | grep 1080 || true
|
||||
```
|
||||
3. **curl 复测 Binance**(与第 3.2 节相同);curl 不通则应用也不会通.
|
||||
4. **PySocks**:`pip show PySocks`,缺失则 `pip install PySocks`.
|
||||
5. **SSH 隧道连不上**:检查私钥权限,`~/.ssh/config`,VPS 出站与端口是否与 `.env` 一致.
|
||||
6. **API 权限与 IP 白名单**:Secret 错误,权限不足,未放行当前出口 IP 时,私有接口会失败.
|
||||
7. **启动顺序**:若走代理,先保证 SOCKS 已监听,再 `pm2 start` 应用(或重启应用).
|
||||
|
||||
---
|
||||
|
||||
## 12. 推荐启动顺序(习惯)
|
||||
|
||||
1. 若走代理:先启动并确认 SSH SOCKS 已监听,再 `curl --proxy socks5h://127.0.0.1:1080 https://api.binance.com/api/v3/time` 成功
|
||||
2. `pm2 start ecosystem.config.cjs`
|
||||
3. 再确认页面与余额等接口正常
|
||||
|
||||
---
|
||||
|
||||
## 13. 免责声明
|
||||
|
||||
交易所有合规与地区政策要求.请确保使用方式符合当地法律法规与交易所条款.本文仅描述网络与工程部署路径.
|
||||
|
||||
---
|
||||
|
||||
## 附录:数据库标签修复脚本 `scripts/fix_breakeven_labels.py`
|
||||
|
||||
在 Ubuntu 上:
|
||||
|
||||
1)预览(不写库):
|
||||
|
||||
```bash
|
||||
python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run
|
||||
```
|
||||
|
||||
2)确认后执行:
|
||||
|
||||
```bash
|
||||
python scripts/fix_breakeven_labels.py --db ./crypto.db --apply
|
||||
```
|
||||
|
||||
默认修复条件:`monitor_type='下单监控'` 且 `result='止损'` 且 `pnl_amount > 0` → 改为 `result='保本止盈'`.
|
||||
|
||||
@@ -1,104 +1,127 @@
|
||||
# =============================================================================
|
||||
# 环境配置模板(可提交 Git)。程序运行时只读取同目录下的 .env。
|
||||
# 环境配置模板(可提交 Git).程序运行时只读取同目录下的 .env.
|
||||
#
|
||||
# 首次部署 / 新机:
|
||||
# 首次部署 / 新机:
|
||||
# cp .env.example .env
|
||||
# nano .env # 填入真实密钥、端口、代理等
|
||||
# nano .env # 填入真实密钥,端口,代理等
|
||||
#
|
||||
# 升级代码(git pull)前建议备份(.env 不在 Git 中,pull 不会覆盖):
|
||||
# 升级代码(git pull)前建议备份(.env 不在 Git 中,pull 不会覆盖):
|
||||
# cp .env .env.backup.$(date +%Y%m%d)
|
||||
#
|
||||
# 从备份恢复:
|
||||
# 从备份恢复:
|
||||
# cp .env.backup.YYYYMMDD .env
|
||||
# =============================================================================
|
||||
|
||||
APP_ENV=production
|
||||
# 服务监听地址(云服务器通常用 0.0.0.0)
|
||||
# 服务监听地址(云服务器通常用 0.0.0.0)
|
||||
APP_HOST=0.0.0.0
|
||||
# 服务端口
|
||||
APP_PORT=5000
|
||||
# 是否开启调试模式(生产建议 false)
|
||||
# 是否开启调试模式(生产建议 false)
|
||||
APP_DEBUG=false
|
||||
|
||||
# 登录账号
|
||||
APP_USERNAME=admin
|
||||
# 登录密码(请改成你自己的强密码)
|
||||
# 登录密码(请改成你自己的强密码)
|
||||
APP_PASSWORD=admin123
|
||||
# 是否关闭登录校验(局域网可设 true;公网务必 false)
|
||||
# 是否关闭登录校验(局域网可设 true;公网务必 false)
|
||||
APP_AUTH_DISABLED=true
|
||||
# --- 多账户交易中控 manual_trading_hub ---
|
||||
# 中控请求本实例 /api/hub/* 时携带请求头 X-Hub-Token,须与中控启动环境变量 HUB_BRIDGE_TOKEN 一致
|
||||
# 未设置且 APP_AUTH_DISABLED=false 时,仅网页登录后可访问;本机联调可保持 APP_AUTH_DISABLED=true
|
||||
# 中控请求本实例 /api/hub/* 时携带请求头 X-Hub-Token,须与中控启动环境变量 HUB_BRIDGE_TOKEN 一致
|
||||
# 未设置且 APP_AUTH_DISABLED=false 时,仅网页登录后可访问;本机联调可保持 APP_AUTH_DISABLED=true
|
||||
# HUB_BRIDGE_TOKEN=your-long-random-token
|
||||
# Flask 会话密钥(必须替换为长随机字符串)
|
||||
# Flask 会话密钥(必须替换为长随机字符串)
|
||||
FLASK_SECRET_KEY=CHANGE_TO_LONG_RANDOM_SECRET
|
||||
|
||||
# 企业微信机器人 Webhook(用于行情/风控推送)
|
||||
# 企业微信机器人 Webhook(用于行情/风控推送)
|
||||
WECHAT_WEBHOOK=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=REPLACE_WITH_REAL_KEY
|
||||
|
||||
# 数据库文件路径(相对路径会自动按项目目录解析)
|
||||
# 数据库文件路径(相对路径会自动按项目目录解析)
|
||||
DB_PATH=crypto.db
|
||||
# 交易截图上传目录
|
||||
UPLOAD_DIR=static/images
|
||||
|
||||
# 自动备份(scripts/backup_data.sh + cron,可选;默认即可)
|
||||
# 自动备份(scripts/backup_data.sh + cron,可选;默认即可)
|
||||
# BACKUP_ROOT=/root/backups
|
||||
# BACKUP_RETENTION_DAYS=30
|
||||
# BACKUP_INSTANCE=crypto_monitor_gate
|
||||
|
||||
# 已废弃:资金账户仅显示交易所 funding 余额,不再读取此变量
|
||||
# 已废弃:资金账户仅显示交易所 funding 余额,不再读取此变量
|
||||
# TOTAL_CAPITAL=100
|
||||
# 计仓:risk=以损定仓(默认);full_margin=合约可用×FULL_MARGIN_BUFFER_RATIO 全仓杠杆(须无仓后重启)
|
||||
# 计仓:risk=以损定仓(默认);full_margin=合约可用×FULL_MARGIN_BUFFER_RATIO 全仓杠杆(须无仓后重启)
|
||||
POSITION_SIZING_MODE=risk
|
||||
# 每天起始基数(U)
|
||||
# 方向限制(默认 false=双向均可;true 时按 TRADE_DIRECTION 限制,修改后须重启)
|
||||
# TRADE_DIRECTION=long_only | short_only | both(或 多/空/双向)
|
||||
TRADE_DIRECTION_RESTRICT_ENABLED=false
|
||||
TRADE_DIRECTION=both
|
||||
# 币种白名单(默认 false=全币种可手输;true 时关键位/下单/策略仅下拉选择)
|
||||
TRADE_SYMBOL_RESTRICT_ENABLED=false
|
||||
TRADE_SYMBOL_WHITELIST=BTC,ETH
|
||||
# 每天起始基数(U)
|
||||
DAILY_START_CAPITAL=30
|
||||
# 日内回撤后基数(U)
|
||||
# 日内回撤后基数(U)
|
||||
DAILY_LOSS_CAPITAL=20
|
||||
# 日内盈利后基数(U)
|
||||
# 日内盈利后基数(U)
|
||||
DAILY_PROFIT_CAPITAL=50
|
||||
# BTC 默认杠杆倍数
|
||||
BTC_LEVERAGE=10
|
||||
# 山寨币默认杠杆倍数
|
||||
ALT_LEVERAGE=5
|
||||
# 交易日重置小时(北京时间)
|
||||
# 交易日重置小时(北京时间)
|
||||
TRADING_DAY_RESET_HOUR=8
|
||||
# 整点前禁止新开仓:true=启用(默认),false=关闭(仍可保留 8 点作为交易日划分)
|
||||
# 整点前禁止新开仓:true=启用(默认),false=关闭(仍可保留 8 点作为交易日划分)
|
||||
TRADING_DAY_RESET_OPEN_GUARD_ENABLED=true
|
||||
|
||||
# 是否开启 Gate 实盘下单(false=只做本地流程,true=真实下单)
|
||||
# 是否开启 Gate 实盘下单(false=只做本地流程,true=真实下单)
|
||||
LIVE_TRADING_ENABLED=true
|
||||
# Gate API Key(实盘)
|
||||
# Gate API Key(实盘)
|
||||
GATE_API_KEY=REPLACE_WITH_GATE_API_KEY
|
||||
# Gate API Secret(实盘)
|
||||
# Gate API Secret(实盘)
|
||||
GATE_API_SECRET=REPLACE_WITH_GATE_API_SECRET
|
||||
# 保证金模式:cross=全仓,isolated=逐仓
|
||||
# 保证金模式:cross=全仓,isolated=逐仓
|
||||
GATE_TD_MODE=cross
|
||||
# 持仓筛选:hedge=双向持仓下按多空腿过滤;其它值(如 single)不按腿过滤
|
||||
# 持仓筛选:hedge=双向持仓下按多空腿过滤;其它值(如 single)不按腿过滤
|
||||
GATE_POS_MODE=hedge
|
||||
# 永续止盈止损:是否优先用官方仓位类触发单(POST price_orders,close-*-position);false=仅用旧版两张 ccxt 条件单
|
||||
# 永续止盈止损:是否优先用官方仓位类触发单(POST price_orders,close-*-position);false=仅用旧版两张 ccxt 条件单
|
||||
GATE_TPSL_USE_POSITION_ORDER=true
|
||||
# 触发单超时(秒),默认 604800=7 天;设为 0 或负数则不向 API 传 expiration
|
||||
# 触发单超时(秒),默认 604800=7 天;设为 0 或负数则不向 API 传 expiration
|
||||
GATE_TPSL_TRIGGER_EXPIRATION=604800
|
||||
# 触发参考价:0=最新成交 1=标记价 2=指数价(非法值按 0)
|
||||
# 触发参考价:0=最新成交 1=标记价 2=指数价(非法值按 0)
|
||||
GATE_TPSL_PRICE_TYPE=0
|
||||
# 仓位类 TP/SL 相对现价的最小间距(%),避免 Gate 1026「触发价须高于/低于现价」
|
||||
# 仓位类 TP/SL 相对现价的最小间距(%),避免 Gate 1026「触发价须高于/低于现价」
|
||||
GATE_TPSL_LAST_PRICE_GAP_PCT=0.05
|
||||
# 页面与浏览器标签展示的交易所名称(多环境区分时可改成例如 Gate·模拟)
|
||||
# EXCHANGE_DISPLAY_NAME=Gate.io
|
||||
# 页面与浏览器标签展示的交易所名称(多环境区分时可改成例如 Gate·模拟)
|
||||
EXCHANGE_DISPLAY_NAME=Gate.io
|
||||
|
||||
# =============================================================================
|
||||
# 关键位门控(页面「关键位监控」规则条与 _key_hard_checks 共用)
|
||||
# 关键位程序自动下单(与 POSITION_SIZING_MODE 联动,修改后须重启 PM2)
|
||||
# =============================================================================
|
||||
# 【周期】门控 K 线周期,如 5m、15m
|
||||
# 默认 false = 关闭所有关键位程序自动单(箱体/收敛/斐波/假突破/触价)
|
||||
#
|
||||
# POSITION_SIZING_MODE=risk(以损定仓)
|
||||
# false → 不执行任何关键位自动单;支撑/阻力提醒,人工下单,顺势加仓不受影响
|
||||
# true → 允许关键位全套自动(含触价)
|
||||
#
|
||||
# POSITION_SIZING_MODE=full_margin(全仓杠杆,须无仓切换)
|
||||
# false → 不执行触价自动单
|
||||
# true → 仅回调/突破触价可程序自动开仓;箱体/斐波等仍禁止
|
||||
#
|
||||
# 顺势加仓,趋势回调不受本开关控制;全仓模式下策略自动仍禁止.
|
||||
KEY_AUTO_ORDER_ENABLED=false
|
||||
|
||||
# =============================================================================
|
||||
# 关键位门控(页面「关键位监控」规则条与 _key_hard_checks 共用)
|
||||
# =============================================================================
|
||||
# 【周期】门控 K 线周期,如 5m,15m
|
||||
KLINE_TIMEFRAME=5m
|
||||
# 【确认K】闭合 K 序列中的棒偏移:突破棒默认 -2,确认棒默认 -1
|
||||
# 【确认K】闭合 K 序列中的棒偏移:突破棒默认 -2,确认棒默认 -1
|
||||
KEY_CONFIRM_BREAKOUT_BAR=-2
|
||||
KEY_CONFIRM_BAR=-1
|
||||
# 【量能】突破棒成交量 > 前 N 根均量 × 倍数
|
||||
KEY_VOLUME_MA_BARS=20
|
||||
KEY_VOLUME_RATIO_MIN=1.3
|
||||
# 【突破K实体幅度】占开盘价百分比区间
|
||||
# 【箱体/收敛】突破K收盘越过关键位下限%;无上限(过猛由计划RR过滤)
|
||||
# 【箱体/收敛】突破K收盘越过关键位下限%;无上限(过猛由计划RR过滤)
|
||||
KEY_BREAKOUT_AMP_MIN_PCT=0.03
|
||||
KEY_BREAKOUT_AMP_MAX_PCT=0.5
|
||||
# 【阻力/支撑】突破后微信提醒
|
||||
@@ -108,71 +131,75 @@ KEY_ALERT_INTERVAL_MINUTES=5
|
||||
KEY_DAILY_VOLUME_RANK_MAX=30
|
||||
# 【关键位自动开仓盈亏比】严格大于该值才市价开仓
|
||||
KEY_AUTO_MIN_PLANNED_RR=1.5
|
||||
# 止损:突破 K 极值向外缓冲的百分比(默认 0.5 即 0.5%)
|
||||
# 止损:突破 K 极值向外缓冲的百分比(默认 0.5 即 0.5%)
|
||||
KEY_STOP_OUTSIDE_BREAKOUT_PCT=0.5
|
||||
# 趋势单方案:止损在突破 K 极值外侧的百分比(默认 1 即 1%)
|
||||
# 趋势单方案:止损在突破 K 极值外侧的百分比(默认 1 即 1%)
|
||||
KEY_TREND_STOP_OUTSIDE_PCT=1
|
||||
KEY_ALERT_MAX_TIMES=3
|
||||
KEY_ALERT_INTERVAL_MINUTES=5
|
||||
|
||||
# =============================================================================
|
||||
# 交易执行 / 人工风控(页面「实盘下单」)
|
||||
# 交易执行 / 人工风控(页面「实盘下单」)
|
||||
# =============================================================================
|
||||
# 【最大同时持仓】默认 1=单仓
|
||||
MAX_ACTIVE_POSITIONS=1
|
||||
# 【人工下单最低盈亏比】低于该值前后端均拒绝(默认 1.4,即须 >=1.4:1)
|
||||
# 【人工下单最低盈亏比】低于该值前后端均拒绝(默认 1.4,即须 >=1.4:1)
|
||||
MANUAL_MIN_PLANNED_RR=1.4
|
||||
# 【关键位连开计仓】已有持仓时按无仓时资金快照算基数
|
||||
KEY_SIZING_USE_ZERO_POSITION_SNAPSHOT=true
|
||||
# 【单日开仓 AI 提醒】本交易日开仓达到该次数时推送企业微信 AI 克制提醒(不拦单)
|
||||
# 【单日开仓 AI 提醒】本交易日开仓达到该次数时推送企业微信 AI 克制提醒(不拦单)
|
||||
DAILY_OPEN_ALERT_THRESHOLD=5
|
||||
# 【单日开仓硬上限】本交易日开仓次数>=该值后禁止一切新开仓直至下一交易日(北京时间 TRADING_DAY_RESET_HOUR 切日);0=不启用
|
||||
# 【单日开仓硬上限】本交易日开仓次数>=该值后禁止一切新开仓直至下一交易日(北京时间 TRADING_DAY_RESET_HOUR 切日);0=不启用
|
||||
DAILY_OPEN_HARD_LIMIT=0
|
||||
|
||||
# =============================================================================
|
||||
# 账户冷静期 / 日冻结风控(手动平仓、外部平仓、复盘情绪标签)
|
||||
# 账户冷静期 / 日冻结风控(手动平仓,外部平仓,复盘情绪标签)
|
||||
# 详见 docs/account-risk-cooldown.md
|
||||
# =============================================================================
|
||||
# RISK_CONTROL_ENABLED=true
|
||||
# RISK_COOLING_HOURS_MANUAL=4
|
||||
# RISK_COOLING_HOURS_MANUAL_JOURNAL=1
|
||||
# RISK_MANUAL_CLOSE_DAILY_LIMIT=2
|
||||
# RISK_MOOD_ISSUES_DAILY_FREEZE=true
|
||||
RISK_CONTROL_ENABLED=true
|
||||
RISK_COOLING_HOURS_MANUAL=4
|
||||
RISK_COOLING_HOURS_MANUAL_JOURNAL=1
|
||||
RISK_MANUAL_CLOSE_DAILY_LIMIT=2
|
||||
# 日亏损次数上限:平仓盈亏<0 计1次;达限当日冻结开仓;0=不启用
|
||||
RISK_DAILY_LOSS_LIMIT=2
|
||||
RISK_MOOD_ISSUES_DAILY_FREEZE=true
|
||||
|
||||
# 资金与仓位刷新周期(秒)
|
||||
# 资金与仓位刷新周期(秒)
|
||||
BALANCE_REFRESH_SECONDS=60
|
||||
# 前端价格快照轮询(秒)
|
||||
# 前端价格快照轮询(秒)
|
||||
PRICE_REFRESH_SECONDS=5
|
||||
# 后台监控轮询周期(秒)
|
||||
# 后台监控轮询周期(秒)
|
||||
MONITOR_POLL_SECONDS=3
|
||||
# 重启后多少秒内不做「外部平仓」同步(避免 API 未就绪误判)
|
||||
# 重启后多少秒内不做「外部平仓」同步(避免 API 未就绪误判)
|
||||
RECONCILE_STARTUP_GRACE_SEC=90
|
||||
# 连续多少次轮询确认交易所空仓后,才记为外部平仓(默认 3 次 ≈ 9 秒)
|
||||
# 连续多少次轮询确认交易所空仓后,才记为外部平仓(默认 3 次 ≈ 9 秒)
|
||||
RECONCILE_FLAT_CONFIRM_POLLS=3
|
||||
# 使用可用资金时的缓冲比例(如0.98代表用98%)
|
||||
# 使用可用资金时的缓冲比例(如0.98代表用98%)
|
||||
FULL_MARGIN_BUFFER_RATIO=0.98
|
||||
|
||||
# =============================================================================
|
||||
# 自动划转(页顶「将 swap 补足到 XU」;与 DAILY_START_CAPITAL 独立,需一致时请设为相同值)
|
||||
# 自动划转(页顶「将 swap 补足到 XU」;与 DAILY_START_CAPITAL 独立,需一致时请设为相同值)
|
||||
# =============================================================================
|
||||
AUTO_TRANSFER_ENABLED=false
|
||||
# 交易账户(swap)目标余额 U:每日 8 点(北京)自动划入或划出至 funding;持仓中不划转
|
||||
# 交易账户(swap)目标余额 U:每日 8 点(北京)自动划入或划出至 funding;持仓中不划转
|
||||
AUTO_TRANSFER_AMOUNT=30
|
||||
AUTO_TRANSFER_FROM=funding
|
||||
AUTO_TRANSFER_TO=swap
|
||||
TRANSFER_CCY=USDT
|
||||
# 北京时间该整点小时内尝试;账簿按 UTC 自然日去重
|
||||
# 北京时间该整点小时内尝试;账簿按 UTC 自然日去重
|
||||
AUTO_TRANSFER_BJ_HOUR=8
|
||||
# 强制清仓整点(北京时间,默认 0=凌晨00点)
|
||||
# 强制清仓整点(北京时间,默认 0=凌晨00点)
|
||||
FORCE_CLOSE_BJ_HOUR=0
|
||||
# 是否启用强制清仓(默认关闭,true 才会在整点执行)
|
||||
# 是否启用强制清仓(默认关闭,true 才会在整点执行)
|
||||
FORCE_CLOSE_ENABLED=false
|
||||
# 强制清仓执行窗口(分钟,默认 5;该窗口内禁止开仓)
|
||||
FORCE_CLOSE_GRACE_MINUTES=5
|
||||
|
||||
# 推送与AI超时(秒)
|
||||
# 推送与AI超时(秒)
|
||||
WECHAT_TIMEOUT_SECONDS=10
|
||||
AI_TIMEOUT_SECONDS=120
|
||||
|
||||
# AI 提供方:openai(默认)| ollama
|
||||
# AI 提供方:openai(默认)| ollama
|
||||
AI_PROVIDER=openai
|
||||
OPENAI_API_BASE=https://op.bz121.com/v1
|
||||
OPENAI_API_KEY=你的密钥
|
||||
@@ -180,31 +207,31 @@ OPENAI_MODEL=gemma4:e4b
|
||||
OLLAMA_API=http://127.0.0.1:11434/api/generate
|
||||
AI_MODEL=huihui_ai/deepseek-r1-abliterated:latest
|
||||
|
||||
# Gate 代理(可选):本机网络不稳定时通过 SSH 动态转发 SOCKS5 出口
|
||||
# 1) 先在本机建立隧道(示例):
|
||||
# Gate 代理(可选):本机网络不稳定时通过 SSH 动态转发 SOCKS5 出口
|
||||
# 1) 先在本机建立隧道(示例):
|
||||
# ssh -N -D 127.0.0.1:1080 root@你的VPS_IP -o ServerAliveInterval=30 -o ExitOnForwardFailure=yes
|
||||
# 2) 再启用下面这一行(推荐 socks5h,让远端解析域名):
|
||||
# 2) 再启用下面这一行(推荐 socks5h,让远端解析域名):
|
||||
# GATE_SOCKS_PROXY=socks5h://127.0.0.1:1080
|
||||
#
|
||||
# 如你更偏向 HTTP 代理(VPS 上跑 tinyproxy 之类),可用:
|
||||
# 如你更偏向 HTTP 代理(VPS 上跑 tinyproxy 之类),可用:
|
||||
# GATE_HTTP_PROXY=http://127.0.0.1:3128
|
||||
# GATE_HTTPS_PROXY=http://127.0.0.1:3128
|
||||
|
||||
# 开仓多周期K线图(可选)
|
||||
# 开仓多周期K线图(可选)
|
||||
# ORDER_CHART_ENABLED=true
|
||||
# ORDER_CHART_TFS=4h,1h,15m,5m
|
||||
# ORDER_CHART_LIMIT=100
|
||||
# ORDER_CHART_DIR=static/images/order_charts
|
||||
# 详见 DAILY_OPEN_ALERT_THRESHOLD / DAILY_OPEN_HARD_LIMIT;说明文档 docs/daily-open-limit.md
|
||||
# 以损定仓(按交易账户资金的百分比)
|
||||
# 详见 DAILY_OPEN_ALERT_THRESHOLD / DAILY_OPEN_HARD_LIMIT;说明文档 docs/daily-open-limit.md
|
||||
# 以损定仓(按交易账户资金的百分比)
|
||||
# RISK_PERCENT=2
|
||||
# 移动保本触发(达到多少R触发)与偏移(百分比)
|
||||
# 移动保本触发(达到多少R触发)与偏移(百分比)
|
||||
# BREAKEVEN_RR_TRIGGER=1.0
|
||||
# 移动保本阶梯(每多少R继续上移一次,默认1R)
|
||||
# 移动保本阶梯(每多少R继续上移一次,默认1R)
|
||||
# BREAKEVEN_STEP_R=1.0
|
||||
# BREAKEVEN_OFFSET_PCT=0.02
|
||||
# 开单风格默认值:trend / swing
|
||||
# 开单风格默认值:trend / swing
|
||||
# DEFAULT_TRADE_STYLE=trend
|
||||
|
||||
APP_TIMEZONE=Asia/Shanghai
|
||||
# TRADING_DAY_RESET_HOUR 现在表示「北京时间」整点,默认 8 点起算新交易日;开仓整点限制见 TRADING_DAY_RESET_OPEN_GUARD_ENABLED
|
||||
# TRADING_DAY_RESET_HOUR 现在表示「北京时间」整点,默认 8 点起算新交易日;开仓整点限制见 TRADING_DAY_RESET_OPEN_GUARD_ENABLED
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
# crypto_monitor_gate
|
||||
|
||||
基于 **Flask** 的加密货币 **下单监控 / 关键位监控 / 交易复盘** 小系统,行情与实盘接口统一走 **Gate.io USDT 永续**,通过 **ccxt** 访问。
|
||||
基于 **Flask** 的加密货币 **下单监控 / 关键位监控 / 交易复盘** 小系统,行情与实盘接口统一走 **Gate.io USDT 永续**,通过 **ccxt** 访问.
|
||||
|
||||
## 文档导航
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| **[使用说明.md](./使用说明.md)** | 日常怎么用:登录、关键位四类、手工开仓、单仓与微信等 |
|
||||
| **[关键位自动下单说明.md](./关键位自动下单说明.md)** | 关键位自动开仓的 RR、止盈止损、结案原因与 `.env` |
|
||||
| **[部署文档.md](./部署文档.md)** | Ubuntu、PM2、**SSH SOCKS** 访问 Gate API 等 |
|
||||
| **[使用说明.md](./使用说明.md)** | 日常怎么用:登录,关键位四类,手工开仓,单仓与微信等 |
|
||||
| **[关键位自动下单说明.md](./关键位自动下单说明.md)** | 关键位自动开仓的 RR,止盈止损,结案原因与 `.env` |
|
||||
| **[部署文档.md](./部署文档.md)** | Ubuntu,PM2,**SSH SOCKS** 访问 Gate API 等 |
|
||||
|
||||
另:**Binance U 本位** 对等实现见同级的 **`crypto_monitor_binance`** 仓库。
|
||||
另:**Binance U 本位** 对等实现见同级的 **`crypto_monitor_binance`** 仓库.
|
||||
|
||||
---
|
||||
|
||||
## 功能概要
|
||||
|
||||
- **关键位监控**:5m 收线硬条件、企业微信推送;**箱体 / 收敛** 在 RR 达标时可 **自动市价开仓**(见专门文档);**阻力 / 支撑** 仅单次提醒结案
|
||||
- **下单监控**:本地风控(含移动保本)、止盈/止损触达后轮询尝试平仓并记账
|
||||
- **实盘(可选)**:`LIVE_TRADING_ENABLED=true` 且配置 **`GATE_API_KEY` / `GATE_API_SECRET`** 时,支持开仓、挂单 TP/SL、余额与划转(权限依账户而定)
|
||||
- **止盈止损(Gate)**:市价成交后经 **`_gate_place_tp_sl_orders`** 挂单;优先 **仓位类 `price_orders`**(受 `GATE_TPSL_USE_POSITION_ORDER`、`GATE_TPSL_PRICE_TYPE`、`GATE_POS_MODE` 等影响)
|
||||
- **关键位监控**:5m 收线硬条件,企业微信推送;**箱体 / 收敛** 在 RR 达标时可 **自动市价开仓**(见专门文档);**阻力 / 支撑** 仅单次提醒结案
|
||||
- **下单监控**:本地风控(含移动保本),止盈/止损触达后轮询尝试平仓并记账
|
||||
- **实盘(可选)**:`LIVE_TRADING_ENABLED=true` 且配置 **`GATE_API_KEY` / `GATE_API_SECRET`** 时,支持开仓,挂单 TP/SL,余额与划转(权限依账户而定)
|
||||
- **止盈止损(Gate)**:市价成交后经 **`_gate_place_tp_sl_orders`** 挂单;优先 **仓位类 `price_orders`**(受 `GATE_TPSL_USE_POSITION_ORDER`,`GATE_TPSL_PRICE_TYPE`,`GATE_POS_MODE` 等影响)
|
||||
|
||||
---
|
||||
|
||||
## 环境要求
|
||||
|
||||
- Python 3.10+(建议)
|
||||
- 依赖:`flask`、`requests`、`ccxt`、`werkzeug`、`PySocks`(经 SOCKS 代理时);`Pillow`(K 线导出等可选用)
|
||||
- Python 3.10+(建议)
|
||||
- 依赖:`flask`,`requests`,`ccxt`,`werkzeug`,`PySocks`(经 SOCKS 代理时);`Pillow`(K 线导出等可选用)
|
||||
|
||||
安装示例:
|
||||
安装示例:
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
@@ -36,41 +36,41 @@ source .venv/bin/activate
|
||||
pip install -r ../requirements.txt
|
||||
```
|
||||
|
||||
## 配置(`.env.example` → `.env`)
|
||||
## 配置(`.env.example` → `.env`)
|
||||
|
||||
- **`.env.example`**:模板(可提交 Git);首次:`cp .env.example .env` 后编辑。
|
||||
- **`.env`**:本机真实配置(勿提交);`git pull` 不覆盖;升级前建议备份(见《部署文档》§5.2)。
|
||||
- **`.env.example`**:模板(可提交 Git);首次:`cp .env.example .env` 后编辑.
|
||||
- **`.env`**:本机真实配置(勿提交);`git pull` 不覆盖;升级前建议备份(见《部署文档》§5.2).
|
||||
|
||||
项目启动时加载**仓库根目录**下的 `.env`。常用项:
|
||||
项目启动时加载**仓库根目录**下的 `.env`.常用项:
|
||||
|
||||
| 变量 | 说明 |
|
||||
|------|------|
|
||||
| `GATE_API_KEY` / `GATE_API_SECRET` | Gate API(需合约与对应权限) |
|
||||
| `LIVE_TRADING_ENABLED` | `true` 允许真实下单;`false` 仅本地与推送逻辑 |
|
||||
| `GATE_API_KEY` / `GATE_API_SECRET` | Gate API(需合约与对应权限) |
|
||||
| `LIVE_TRADING_ENABLED` | `true` 允许真实下单;`false` 仅本地与推送逻辑 |
|
||||
| `GATE_MARGIN_MODE` / `GATE_POS_MODE` | 保证金与持仓模式 |
|
||||
| `GATE_TPSL_USE_POSITION_ORDER` / `GATE_TPSL_PRICE_TYPE` 等 | 条件止盈止损行为 |
|
||||
| `GATE_SOCKS_PROXY` | 可选;直连不稳时 SSH 动态转发(详见部署文档) |
|
||||
| `GATE_SOCKS_PROXY` | 可选;直连不稳时 SSH 动态转发(详见部署文档) |
|
||||
| `APP_PASSWORD` / `FLASK_SECRET_KEY` | Web 登录与 Session |
|
||||
| `WECHAT_WEBHOOK` | 企业微信机器人 |
|
||||
| `EXCHANGE_DISPLAY_NAME` / `GATE_ACCOUNT_LABEL` | 页面与推送展示的账户文案 |
|
||||
|
||||
其余见 **`.env.example` 内注释** 或 **`app.py` 顶部默认值**。
|
||||
其余见 **`.env.example` 内注释** 或 **`app.py` 顶部默认值**.
|
||||
|
||||
## 运行
|
||||
|
||||
生产使用 **PM2**(`ecosystem.config.cjs`)。调试:
|
||||
生产使用 **PM2**(`ecosystem.config.cjs`).调试:
|
||||
|
||||
```bash
|
||||
source .venv/bin/activate && python app.py
|
||||
```
|
||||
|
||||
见 [docs/ubuntu-server.md](../docs/ubuntu-server.md)。
|
||||
见 [docs/ubuntu-server.md](../docs/ubuntu-server.md).
|
||||
|
||||
端口由 **`APP_PORT`** 控制(未设置默认 **5000**)。浏览器登录 **`/login`**,口令为 **`APP_PASSWORD`**。
|
||||
端口由 **`APP_PORT`** 控制(未设置默认 **5000**).浏览器登录 **`/login`**,口令为 **`APP_PASSWORD`**.
|
||||
|
||||
## 部署(Linux / PM2 / SSH SOCKS)
|
||||
## 部署(Linux / PM2 / SSH SOCKS)
|
||||
|
||||
见 **[部署文档.md](./部署文档.md)**。
|
||||
见 **[部署文档.md](./部署文档.md)**.
|
||||
|
||||
## 自检脚本
|
||||
|
||||
@@ -78,13 +78,13 @@ source .venv/bin/activate && python app.py
|
||||
python scripts/verify_gate_funding.py
|
||||
```
|
||||
|
||||
用于核对密钥前缀(不落 Secret)、资金/合约可读性等(需网络与权限)。
|
||||
用于核对密钥前缀(不落 Secret),资金/合约可读性等(需网络与权限).
|
||||
|
||||
## 数据与脚本
|
||||
|
||||
- 默认 SQLite:由 **`DB_PATH`** 指定(常见为项目下 `crypto.db`)
|
||||
- `scripts/fix_breakeven_labels.py`:修正「止损」但盈亏为正的记录标签(参见部署文档说明)
|
||||
- 默认 SQLite:由 **`DB_PATH`** 指定(常见为项目下 `crypto.db`)
|
||||
- `scripts/fix_breakeven_labels.py`:修正「止损」但盈亏为正的记录标签(参见部署文档说明)
|
||||
|
||||
## 风险与合规
|
||||
|
||||
实盘有亏损风险。请确认 API 权限、IP 白名单、杠杆与保证金模式与 **Gate.io** 后台一致,并遵守当地法律法规与交易所用户协议。
|
||||
实盘有亏损风险.请确认 API 权限,IP 白名单,杠杆与保证金模式与 **Gate.io** 后台一致,并遵守当地法律法规与交易所用户协议.
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/**
|
||||
* PM2 进程定义(Ubuntu / Linux)。
|
||||
* PM2 进程定义(Ubuntu / Linux).
|
||||
*
|
||||
* 仅托管 Flask 应用。**SSH SOCKS 隧道**用 `ssh -D` 常驻(可用 tmux / autossh),勿交给 PM2。
|
||||
* 与 `.env` 里 `GATE_SOCKS_PROXY` 端口一致即可;不必交给 PM2。
|
||||
* 仅托管 Flask 应用.**SSH SOCKS 隧道**用 `ssh -D` 常驻(可用 tmux / autossh),勿交给 PM2.
|
||||
* 与 `.env` 里 `GATE_SOCKS_PROXY` 端口一致即可;不必交给 PM2.
|
||||
*
|
||||
* 使用前:项目根目录存在 `.venv`,且已安装依赖(走 SOCKS 时需 PySocks)。
|
||||
* 使用前:项目根目录存在 `.venv`,且已安装依赖(走 SOCKS 时需 PySocks).
|
||||
*
|
||||
* 启动:
|
||||
* 启动:
|
||||
* pm2 start ecosystem.config.cjs
|
||||
* 保存开机列表:
|
||||
* 保存开机列表:
|
||||
* pm2 save && pm2 startup
|
||||
*/
|
||||
const path = require("path");
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
一次性修复历史交易记录标签:
|
||||
将 trade_records 里“止损但实际盈利”的记录改为“保本止盈”。
|
||||
一次性修复历史交易记录标签:
|
||||
将 trade_records 里“止损但实际盈利”的记录改为“保本止盈”.
|
||||
|
||||
默认条件(可通过参数修改):
|
||||
默认条件(可通过参数修改):
|
||||
- monitor_type = 下单监控
|
||||
- result = 止损
|
||||
- pnl_amount > 0
|
||||
|
||||
用法示例:
|
||||
1) 仅预览(不落库):
|
||||
用法示例:
|
||||
1) 仅预览(不落库):
|
||||
python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run
|
||||
|
||||
2) 执行修复:
|
||||
2) 执行修复:
|
||||
python scripts/fix_breakeven_labels.py --db ./crypto.db --apply
|
||||
"""
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
"""
|
||||
在项目根目录执行(会加载根目录 .env):
|
||||
在项目根目录执行(会加载根目录 .env):
|
||||
python scripts/verify_gate_funding.py
|
||||
|
||||
依次探测:[0] swap 余额(与 App「交易账户」同源);[1]–[3] 现货 / 统一账户资金路径。
|
||||
打印 GATE_API_KEY 前 8 位便于与 Gate 控制台核对(不含 Secret)。用于服务器自检。
|
||||
依次探测:[0] swap 余额(与 App「交易账户」同源);[1]–[3] 现货 / 统一账户资金路径.
|
||||
打印 GATE_API_KEY 前 8 位便于与 Gate 控制台核对(不含 Secret).用于服务器自检.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -39,12 +39,12 @@ def main():
|
||||
k = (os.getenv("GATE_API_KEY") or "").strip()
|
||||
s = (os.getenv("GATE_API_SECRET") or "").strip()
|
||||
if not k or "REPLACE" in k.upper():
|
||||
print("WARN: GATE_API_KEY 为空或仍像占位符,请核对 .env")
|
||||
print("WARN: GATE_API_KEY 为空或仍像占位符,请核对 .env")
|
||||
if not s or "REPLACE" in s.upper():
|
||||
print("WARN: GATE_API_SECRET 为空或仍像占位符,请核对 .env")
|
||||
print("WARN: GATE_API_SECRET 为空或仍像占位符,请核对 .env")
|
||||
print("GATE_API_KEY prefix (8 chars):", (k[:8] + "…") if len(k) > 8 else "(short)")
|
||||
|
||||
# 0) swap — 与 App「交易账户」余额同源(优先看此项是否与网页一致)
|
||||
# 0) swap — 与 App「交易账户」余额同源(优先看此项是否与网页一致)
|
||||
try:
|
||||
bal = mod.exchange.fetch_balance({"type": "swap"})
|
||||
v0 = mod._extract_usdt_total(bal)
|
||||
|
||||
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 181 B After Width: | Height: | Size: 287 B |
|
Before Width: | Height: | Size: 162 B After Width: | Height: | Size: 265 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 497 B After Width: | Height: | Size: 507 B |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 8.6 KiB |
@@ -1,17 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0%" stop-color="#22d3ee"/>
|
||||
<stop offset="100%" stop-color="#34d399"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="512" height="512" rx="108" fill="#0c1019"/>
|
||||
<rect x="36" y="36" width="440" height="440" rx="88" fill="#141b2d"/>
|
||||
<rect x="36" y="36" width="440" height="440" rx="88" fill="none" stroke="url(#g)" stroke-width="12"/>
|
||||
<path d="M120 320 L200 248 L280 272 L392 168" fill="none" stroke="url(#g)" stroke-width="20" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="392" cy="168" r="18" fill="#34d399"/>
|
||||
<rect x="168" y="268" width="28" height="64" rx="6" fill="#f87171"/>
|
||||
<line x1="182" y1="248" x2="182" y2="340" stroke="#f87171" stroke-width="10" stroke-linecap="round"/>
|
||||
<rect x="268" y="220" width="28" height="96" rx="6" fill="#34d399"/>
|
||||
<line x1="282" y1="200" x2="282" y2="340" stroke="#34d399" stroke-width="10" stroke-linecap="round"/>
|
||||
<rect x="36" y="36" width="440" height="440" rx="88" fill="none" stroke="#17E6A1" stroke-width="12"/>
|
||||
<text x="256" y="310" text-anchor="middle" font-family="Arial, Helvetica, sans-serif" font-size="220" font-weight="700" fill="#17E6A1">G</text>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 451 B |
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "交易监控复盘",
|
||||
"short_name": "监控",
|
||||
"description": "加密货币永续交易监控与复盘",
|
||||
"name": "Gate 交易系统",
|
||||
"short_name": "Gate 交易系统",
|
||||
"description": "Gate 永续交易监控与复盘",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#0b0d14",
|
||||
"theme_color": "#0b0d14",
|
||||
"theme_color": "#17E6A1",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/static/icons/icon-192.png",
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN" data-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<script src="/static/instance_theme.js?v=4"></script>
|
||||
|
||||
<title>登录 · {{ exchange_display }}</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
background: #0a0a10;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
color: #fff;
|
||||
}
|
||||
.login-box {
|
||||
background: #12121a;
|
||||
padding: 2.5rem;
|
||||
border-radius: 16px;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
border: 1px solid #242435;
|
||||
box-shadow: 0 8px 24px rgba(0,0,0,0.3);
|
||||
}
|
||||
.login-box h2 {
|
||||
margin-bottom: 2rem;
|
||||
text-align: center;
|
||||
font-size: 1.5rem;
|
||||
background: linear-gradient(90deg, #4cc2ff, #7b42ff);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
.form-group {
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.9rem;
|
||||
color: #a9a9ff;
|
||||
}
|
||||
.form-group input {
|
||||
width: 100%;
|
||||
padding: 0.85rem 1rem;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #2e2e45;
|
||||
background: #1a1a29;
|
||||
color: #fff;
|
||||
font-size: 0.95rem;
|
||||
outline: none;
|
||||
}
|
||||
.form-group input:focus {
|
||||
border-color: #4cc2ff;
|
||||
}
|
||||
button {
|
||||
width: 100%;
|
||||
padding: 0.9rem;
|
||||
border-radius: 10px;
|
||||
border: none;
|
||||
background: linear-gradient(90deg, #4285f4, #7b42ff);
|
||||
color: #fff;
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: 0.2s;
|
||||
}
|
||||
button:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
.flash {
|
||||
padding: 0.8rem;
|
||||
margin-bottom: 1rem;
|
||||
background: #331e24;
|
||||
color: #ff6666;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
.exchange-line {
|
||||
text-align: center;
|
||||
font-size: 0.82rem;
|
||||
color: #8892b0;
|
||||
margin: -0.5rem 0 1.25rem;
|
||||
}
|
||||
.exchange-line strong {
|
||||
color: #b8f5d0;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/static/instance_theme.css?v=4">
|
||||
|
||||
</head>
|
||||
<div class="login-theme-bar">
|
||||
<div class="theme-toggle instance-theme-toggle" role="group" aria-label="界面主题">
|
||||
<button type="button" class="theme-toggle-btn is-active" data-theme-value="dark" aria-pressed="true" title="暗色主题">
|
||||
<svg class="theme-icon" viewBox="0 0 24 24" width="18" height="18" aria-hidden="true">
|
||||
<path fill="currentColor" d="M12.1 3a9 9 0 1 0 8.9 11 6.5 6.5 0 1 1-8.9-11z"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button type="button" class="theme-toggle-btn" data-theme-value="light" aria-pressed="false" title="亮色主题">
|
||||
<svg class="theme-icon" viewBox="0 0 24 24" width="18" height="18" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||||
<circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<body>
|
||||
<div class="login-box">
|
||||
<h2>交易监控系统登录</h2>
|
||||
<p class="exchange-line">交易所:<strong>{{ exchange_display }}</strong></p>
|
||||
{% with messages = get_flashed_messages() %}
|
||||
{% if messages %}
|
||||
<div class="flash">{{ messages[0] }}</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
<form method="POST" autocomplete="off">
|
||||
<div class="form-group">
|
||||
<label>账号</label>
|
||||
<input type="text" name="username" required placeholder="请输入账号" autocomplete="off" autocapitalize="off" spellcheck="false">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>密码</label>
|
||||
<input type="password" name="password" required placeholder="请输入密码" autocomplete="new-password">
|
||||
</div>
|
||||
<button type="submit">登录</button>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -29,9 +29,9 @@
|
||||
<div class="row" style="justify-content:space-between">
|
||||
<div class="row">
|
||||
<a class="btn" href="/">返回首页</a>
|
||||
<strong style="color:#dbe4ff">实盘下单放大(100根K线)</strong>
|
||||
<strong style="color:#dbe4ff">实盘下单放大(100根K线)</strong>
|
||||
</div>
|
||||
<div class="status">最近刷新:<span id="updated-at">--</span></div>
|
||||
<div class="status">最近刷新:<span id="updated-at">--</span></div>
|
||||
</div>
|
||||
{% if orders %}
|
||||
<div class="row" style="margin-top:10px">
|
||||
@@ -53,7 +53,7 @@
|
||||
<span id="load-status" class="status"></span>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="empty">当前没有激活订单,无法展示放大K线。</div>
|
||||
<div class="empty">当前没有激活订单,无法展示放大K线.</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,147 +1,147 @@
|
||||
# 使用说明
|
||||
|
||||
**本文件对应仓库:`crypto_monitor_gate`(Gate.io USDT 永续)。**
|
||||
功能、界面与 **Binance U 本位版**(目录 `crypto_monitor_binance`)基本一致,差异主要在 **`.env` 里交易所密钥与部分参数名**(`GATE_*` / `BINANCE_*`),文末有对照。
|
||||
|
||||
**更细的部署(SSH 代理、PM2、依赖安装)** 见同目录 **`部署文档.md`**。
|
||||
**关键位自动开仓的规则、RR、结案原因** 见 **`关键位自动下单说明.md`**。
|
||||
|
||||
---
|
||||
|
||||
## 1. 它能做什么
|
||||
|
||||
面向个人盘面的 **Web 控制台**,主要能力包括:
|
||||
|
||||
| 模块 | 说明 |
|
||||
|------|------|
|
||||
| **关键位监控** | 录入上/下沿与类型,按 **5m 收线** 做硬条件过滤;符合条件后 **企业微信** 提醒,部分类型可 **自动市价开仓**(见第 4 节与专门文档)。 |
|
||||
| **实盘下单监控** | 手工填止损/止盈,**以损定仓** 市价开单,挂上条件止盈止损,并在页面跟踪浮盈亏、保本逻辑等。 |
|
||||
| **交易记录 / 复盘** | 平仓结果、盈亏、错过的单等归档与导出;可选 **AI 复盘**(见 [AI复盘与模型配置说明.md](../AI复盘与模型配置说明.md))。 |
|
||||
| **策略交易** | 顶栏 `/strategy`:趋势回调 + 顺势加仓双栏;见 [策略交易说明.md](../策略交易说明.md)。 |
|
||||
|
||||
后台按 **`MONITOR_POLL_SECONDS`**(默认几秒)轮询行情与监控逻辑。**切勿**在未理解规则时同时运行两套程序共用一个实盘账户。
|
||||
|
||||
---
|
||||
|
||||
## 2. 运行前必须配置(`.env`)
|
||||
|
||||
首次在本目录执行 **`cp .env.example .env`**,再编辑 `.env`(`.env` 勿提交 Git;`git pull` 不会改你的 `.env`,升级前建议 `cp .env .env.backup.$(date +%Y%m%d)`)。
|
||||
|
||||
至少检查以下项(具体键名以 **`.env.example`** 为准):
|
||||
|
||||
| 类别 | 说明 |
|
||||
|------|------|
|
||||
| **登录网页** | `APP_PASSWORD`:打开站点后的登录口令。`FLASK_SECRET_KEY`:Session 密钥,请勿使用默认值。 |
|
||||
| **企业微信** | `WECHAT_WEBHOOK`:告警与关键位推送机器人的 Webhook。 |
|
||||
| **是否真下单** | `LIVE_TRADING_ENABLED=false`:**不会**向交易所发送开仓指令(适合测试流程)。改为 `true` 且密钥正确才会实盘。 |
|
||||
| **交易所 API** | **本仓库:** `GATE_API_KEY`、`GATE_API_SECRET`;合约相关见 `GATE_MARGIN_MODE`、`GATE_POS_MODE`、`GATE_TPSL_*` 等。**勿**把 `.env` 提交到 Git。 |
|
||||
| **关键位 RR / 止损外扩** | `KEY_AUTO_MIN_PLANNED_RR`、`KEY_STOP_OUTSIDE_BREAKOUT_PCT`(详见 `关键位自动下单说明.md`)。 |
|
||||
| **AI 复盘** | `AI_PROVIDER=openai`(默认)或 `ollama`;变量见 `.env.example` 与 [AI复盘与模型配置说明.md](../AI复盘与模型配置说明.md)。 |
|
||||
|
||||
网络不稳定时可为 Gate 配置 **`GATE_SOCKS_PROXY`** 等(见 **`部署文档.md`**)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 如何启动与登录
|
||||
|
||||
1. 按 **`部署文档.md`** 建好虚拟环境、安装依赖(如 `flask`、`requests`、`ccxt`、按需 `Pillow`、`PySocks` 等),配置好 `.env`。
|
||||
2. 启动 Flask 应用(本仓库可用 **`ecosystem.config.cjs`** 交给 PM2,或本地 `python app.py` / `flask run`,以你当前脚本为准)。
|
||||
3. 浏览器访问站点,打开 **`/login`**,使用 **`.env` 里的 `APP_PASSWORD`** 登录。
|
||||
|
||||
登录后顶栏:**关键位监控** | **实盘下单** | **策略交易**(`/strategy`)| **策略交易记录**(`/strategy/records`)| **交易记录与复盘** | **统计分析**。
|
||||
|
||||
---
|
||||
|
||||
## 4. 关键位监控(顶栏「关键位监控」→ `/key_monitor`)
|
||||
|
||||
### 4.1 添加一条关键位
|
||||
|
||||
1. **币种**:如 `BTC` 或 `BTC/USDT`(会规范成内部符号)。
|
||||
2. **类型**(必选其一):
|
||||
|
||||
| 类型 | 行为摘要 |
|
||||
|------|----------|
|
||||
| **箱体突破** | 通过门控且计划 RR 达标 → **自动市价开仓**(需 `LIVE_TRADING_ENABLED=true` 且无其他持仓占位)。结案后本条从列表消失并记入历史。 |
|
||||
| **收敛突破** | 同上(自动开仓类)。 |
|
||||
| **关键阻力位** | **不自动开仓**;触发后 **发 1 次微信**,然后本条 **结案进历史**。 |
|
||||
| **关键支撑位** | 同上(仅提醒)。 |
|
||||
| **回调触价开仓** | **不挂交易所限价**;标记价回调触达 E 后 **下一轮询市价开仓**(RR 门槛同 `KEY_AUTO_MIN_PLANNED_RR`);有效期 **24h** |
|
||||
| **突破触价开仓** | **不挂交易所限价**;标记价 **穿越 E 立即市价开仓**;先触 SL/TP 侧失效;有效期 **24h** |
|
||||
|
||||
3. **方向**:做多 / 做空(触价开仓 / 箱体 / 收敛 / 斐波必选;阻力/支撑不选)。
|
||||
4. **价位**:箱体/收敛/阻力/支撑填 **上沿 / 下沿**;触价开仓填 **入场 E / 止损 SL / 止盈 TP**。
|
||||
|
||||
**限制:**
|
||||
活跃持仓数达到 **`MAX_ACTIVE_POSITIONS`**(默认 1)时,**不允许**再添加「**箱体突破** / **收敛突破**」;仍可添加「**关键阻力位 / 支撑位**」。
|
||||
若 **4h EMA55** 与你的方向逆势,页面会 **额外 Flash 提示**,**不阻挡**提交。
|
||||
|
||||
### 4.2 触发后会发生什么(简版)
|
||||
|
||||
- **箱体 / 收敛**:门控通过后计算计划 SL/TP 与 RR;不达标则 **微信说明 + `rr_insufficient` 结案**;达标则尝试 **市价开仓**,成功 **`auto_opened`**,失败 **`exchange_failed`**——均 **不重试同一关键位**。
|
||||
- **阻力 / 支撑**:仅 **单次推送** → **`key_level_alert_only`** 结案。
|
||||
|
||||
详细公式、结案字段、与企业微信文案口径见 **`关键位自动下单说明.md`**。
|
||||
|
||||
### 4.3 列表与历史
|
||||
|
||||
- 当前条目可 **删除**(会按规则记入历史的情形见页面说明)。
|
||||
- **关键位历史**:已结案记录;可配合导出链接(若有)做备份。
|
||||
|
||||
---
|
||||
|
||||
## 5. 实盘下单(顶栏「实盘下单」→ `/trade`)
|
||||
|
||||
用于 **自己点按钮** 开单:
|
||||
|
||||
- 持仓上限由 **`MAX_ACTIVE_POSITIONS`** 控制(默认 1,与关键位自动单共用)。
|
||||
- **人工开仓**时计划盈亏比不得低于 **`MANUAL_MIN_PLANNED_RR`**(默认 1.4:1),否则页面弹窗且后端拒绝。
|
||||
- 填写币种、方向、杠杆(可选)、止损/止盈(价格或百分比按表单说明)。
|
||||
- 勾选是否启用 **移动保本** 等行为以 `.env`/页面默认值为准。
|
||||
|
||||
平仓通过页面 **平仓**(或等价入口),会从交易所市价处理并更新记录。**删除/误操作可能造成真实盈亏**,请先确认环境与方向。
|
||||
|
||||
开仓成功后持仓卡片上会显示 **「来源」**:手工单一般为 **下单监控**;来自关键位自动单的为 **关键位监控**。
|
||||
|
||||
---
|
||||
|
||||
## 6. 企业微信会看到什么
|
||||
|
||||
- 关键位:按类型与结案结果推送(RR 不足、下单失败、自动开仓成功、仅阻力支撑提醒等),**每条关键位结案路径原则上一条主推送**(详见 `关键位自动下单说明.md`)。
|
||||
- 手工开仓、平仓、部分异常也会在规则满足时推送(以代码与配置为准)。
|
||||
|
||||
若未配置 **`WECHAT_WEBHOOK`** 或网络失败,可能只是看不到推送,不代表逻辑未执行;要紧操作请以 **交易所端持仓与挂单** 为准核对。
|
||||
|
||||
---
|
||||
|
||||
## 7. 强烈建议的风险与运维习惯
|
||||
|
||||
1. **先用 `LIVE_TRADING_ENABLED=false`** 验证页面、录入、推送,再开小资金开实盘。
|
||||
2. **API 权限**:仅开所需合约权限;勿泄露密钥;定期轮换。
|
||||
3. **单进程控盘**:同一账户避免本程序与其他机器人 **重复开仓**。
|
||||
4. **自动备份**:服务器上执行 `bash scripts/install_backup_cron.sh`(每天北京时间 0:00 → `/root/backups`,保留 30 天);升级前也可 `bash scripts/backup_data.sh` 手动跑一次。
|
||||
5. **升级代码后**:启动时会跑 **数据库迁移**(如新列 `order_monitors.monitor_type`);首次启动关注一下日志或无报错页面。
|
||||
|
||||
---
|
||||
|
||||
## 8. 常见问题(简要)
|
||||
|
||||
| 现象 | 可自查 |
|
||||
|------|--------|
|
||||
| 关键位永远不触发 | 5m 门控是否全通过(页面门控摘要)、币种日成交量是否在规则内、`KLINE_TIMEFRAME`。 |
|
||||
| 有信号但不自动开仓 | `LIVE_TRADING_ENABLED`、`KEY_AUTO_MIN_PLANNED_RR`、计划 RR、是否已有持仓、API/余额报错(微信或日志)。 |
|
||||
| 加不了箱体/收敛 | 是否已有活跃持仓;先平仓或改用「阻力/支撑位」仅提醒。 |
|
||||
| 推送收不到 | `WECHAT_WEBHOOK`、企业微信机器人配额与网络。 |
|
||||
|
||||
---
|
||||
|
||||
## 9. Binance 版(`crypto_monitor_binance`)差异速查
|
||||
|
||||
| 项目 | Gate 本仓库 | Binance 版 |
|
||||
|------|-------------|------------|
|
||||
| API 变量 | `GATE_API_KEY`、`GATE_API_SECRET`、`GATE_*` | `BINANCE_API_KEY`、`BINANCE_API_SECRET`、`BINANCE_*` |
|
||||
| 实盘开关 | `LIVE_TRADING_ENABLED`(通用) | 同上 |
|
||||
| 止盈止损挂载路径 | `_gate_place_tp_sl_orders` 与 `GATE_TPSL_*` | `_binance_place_tp_sl_orders`(U 本位条件单) |
|
||||
| 资金显示舍入 | 以本仓库为准 | 与 **`FUNDS_DECIMALS`** 等一致 |
|
||||
| 专门文档 | **`关键位自动下单说明.md`**(各仓库有一份,开头标明交易所) | 同左 |
|
||||
|
||||
操作流程(登录、关键位四类、手工单、单仓)**两份程序一致**:换目录、换 `.env` 即可对照使用。
|
||||
# 使用说明
|
||||
|
||||
**本文件对应仓库:`crypto_monitor_gate`(Gate.io USDT 永续).**
|
||||
功能,界面与 **Binance U 本位版**(目录 `crypto_monitor_binance`)基本一致,差异主要在 **`.env` 里交易所密钥与部分参数名**(`GATE_*` / `BINANCE_*`),文末有对照.
|
||||
|
||||
**更细的部署(SSH 代理,PM2,依赖安装)** 见同目录 **`部署文档.md`**.
|
||||
**关键位自动开仓的规则,RR,结案原因** 见 **`关键位自动下单说明.md`**.
|
||||
|
||||
---
|
||||
|
||||
## 1. 它能做什么
|
||||
|
||||
面向个人盘面的 **Web 控制台**,主要能力包括:
|
||||
|
||||
| 模块 | 说明 |
|
||||
|------|------|
|
||||
| **关键位监控** | 录入上/下沿与类型,按 **5m 收线** 做硬条件过滤;符合条件后 **企业微信** 提醒,部分类型可 **自动市价开仓**(见第 4 节与专门文档). |
|
||||
| **实盘下单监控** | 手工填止损/止盈,**以损定仓** 市价开单,挂上条件止盈止损,并在页面跟踪浮盈亏,保本逻辑等. |
|
||||
| **交易记录 / 复盘** | 平仓结果,盈亏,错过的单等归档与导出;可选 **AI 复盘**(见 [AI复盘与模型配置说明.md](../AI复盘与模型配置说明.md)). |
|
||||
| **策略交易** | 顶栏 `/strategy`:趋势回调 + 顺势加仓双栏;见 [策略交易说明.md](../策略交易说明.md). |
|
||||
|
||||
后台按 **`MONITOR_POLL_SECONDS`**(默认几秒)轮询行情与监控逻辑.**切勿**在未理解规则时同时运行两套程序共用一个实盘账户.
|
||||
|
||||
---
|
||||
|
||||
## 2. 运行前必须配置(`.env`)
|
||||
|
||||
首次在本目录执行 **`cp .env.example .env`**,再编辑 `.env`(`.env` 勿提交 Git;`git pull` 不会改你的 `.env`,升级前建议 `cp .env .env.backup.$(date +%Y%m%d)`).
|
||||
|
||||
至少检查以下项(具体键名以 **`.env.example`** 为准):
|
||||
|
||||
| 类别 | 说明 |
|
||||
|------|------|
|
||||
| **登录网页** | `APP_PASSWORD`:打开站点后的登录口令.`FLASK_SECRET_KEY`:Session 密钥,请勿使用默认值. |
|
||||
| **企业微信** | `WECHAT_WEBHOOK`:告警与关键位推送机器人的 Webhook. |
|
||||
| **是否真下单** | `LIVE_TRADING_ENABLED=false`:**不会**向交易所发送开仓指令(适合测试流程).改为 `true` 且密钥正确才会实盘. |
|
||||
| **交易所 API** | **本仓库:** `GATE_API_KEY`,`GATE_API_SECRET`;合约相关见 `GATE_MARGIN_MODE`,`GATE_POS_MODE`,`GATE_TPSL_*` 等.**勿**把 `.env` 提交到 Git. |
|
||||
| **关键位 RR / 止损外扩** | `KEY_AUTO_MIN_PLANNED_RR`,`KEY_STOP_OUTSIDE_BREAKOUT_PCT`(详见 `关键位自动下单说明.md`). |
|
||||
| **AI 复盘** | `AI_PROVIDER=openai`(默认)或 `ollama`;变量见 `.env.example` 与 [AI复盘与模型配置说明.md](../AI复盘与模型配置说明.md). |
|
||||
|
||||
网络不稳定时可为 Gate 配置 **`GATE_SOCKS_PROXY`** 等(见 **`部署文档.md`**).
|
||||
|
||||
---
|
||||
|
||||
## 3. 如何启动与登录
|
||||
|
||||
1. 按 **`部署文档.md`** 建好虚拟环境,安装依赖(如 `flask`,`requests`,`ccxt`,按需 `Pillow`,`PySocks` 等),配置好 `.env`.
|
||||
2. 启动 Flask 应用(本仓库可用 **`ecosystem.config.cjs`** 交给 PM2,或本地 `python app.py` / `flask run`,以你当前脚本为准).
|
||||
3. 浏览器访问站点,打开 **`/login`**,使用 **`.env` 里的 `APP_PASSWORD`** 登录.
|
||||
|
||||
登录后顶栏:**关键位监控** | **实盘下单** | **策略交易**(`/strategy`)| **策略交易记录**(`/strategy/records`)| **交易记录与复盘** | **统计分析**.
|
||||
|
||||
---
|
||||
|
||||
## 4. 关键位监控(顶栏「关键位监控」→ `/key_monitor`)
|
||||
|
||||
### 4.1 添加一条关键位
|
||||
|
||||
1. **币种**:如 `BTC` 或 `BTC/USDT`(会规范成内部符号).
|
||||
2. **类型**(必选其一):
|
||||
|
||||
| 类型 | 行为摘要 |
|
||||
|------|----------|
|
||||
| **箱体突破** | 通过门控且计划 RR 达标 → **自动市价开仓**(需 `LIVE_TRADING_ENABLED=true` 且无其他持仓占位).结案后本条从列表消失并记入历史. |
|
||||
| **收敛突破** | 同上(自动开仓类). |
|
||||
| **关键阻力位** | **不自动开仓**;触发后 **发 1 次微信**,然后本条 **结案进历史**. |
|
||||
| **关键支撑位** | 同上(仅提醒). |
|
||||
| **回调触价开仓** | **不挂交易所限价**;标记价回调触达 E 后 **下一轮询市价开仓**(RR 门槛同 `KEY_AUTO_MIN_PLANNED_RR`);有效期 **24h** |
|
||||
| **突破触价开仓** | **不挂交易所限价**;标记价 **穿越 E 立即市价开仓**;先触 SL/TP 侧失效;有效期 **24h** |
|
||||
|
||||
3. **方向**:做多 / 做空(触价开仓 / 箱体 / 收敛 / 斐波必选;阻力/支撑不选).
|
||||
4. **价位**:箱体/收敛/阻力/支撑填 **上沿 / 下沿**;触价开仓填 **入场 E / 止损 SL / 止盈 TP**.
|
||||
|
||||
**限制:**
|
||||
活跃持仓数达到 **`MAX_ACTIVE_POSITIONS`**(默认 1)时,**不允许**再添加「**箱体突破** / **收敛突破**」;仍可添加「**关键阻力位 / 支撑位**」.
|
||||
若 **4h EMA55** 与你的方向逆势,页面会 **额外 Flash 提示**,**不阻挡**提交.
|
||||
|
||||
### 4.2 触发后会发生什么(简版)
|
||||
|
||||
- **箱体 / 收敛**:门控通过后计算计划 SL/TP 与 RR;不达标则 **微信说明 + `rr_insufficient` 结案**;达标则尝试 **市价开仓**,成功 **`auto_opened`**,失败 **`exchange_failed`**——均 **不重试同一关键位**.
|
||||
- **阻力 / 支撑**:仅 **单次推送** → **`key_level_alert_only`** 结案.
|
||||
|
||||
详细公式,结案字段,与企业微信文案口径见 **`关键位自动下单说明.md`**.
|
||||
|
||||
### 4.3 列表与历史
|
||||
|
||||
- 当前条目可 **删除**(会按规则记入历史的情形见页面说明).
|
||||
- **关键位历史**:已结案记录;可配合导出链接(若有)做备份.
|
||||
|
||||
---
|
||||
|
||||
## 5. 实盘下单(顶栏「实盘下单」→ `/trade`)
|
||||
|
||||
用于 **自己点按钮** 开单:
|
||||
|
||||
- 持仓上限由 **`MAX_ACTIVE_POSITIONS`** 控制(默认 1,与关键位自动单共用).
|
||||
- **人工开仓**时计划盈亏比不得低于 **`MANUAL_MIN_PLANNED_RR`**(默认 1.4:1),否则页面弹窗且后端拒绝.
|
||||
- 填写币种,方向,杠杆(可选),止损/止盈(价格或百分比按表单说明).
|
||||
- 勾选是否启用 **移动保本** 等行为以 `.env`/页面默认值为准.
|
||||
|
||||
平仓通过页面 **平仓**(或等价入口),会从交易所市价处理并更新记录.**删除/误操作可能造成真实盈亏**,请先确认环境与方向.
|
||||
|
||||
开仓成功后持仓卡片上会显示 **「来源」**:手工单一般为 **下单监控**;来自关键位自动单的为 **关键位监控**.
|
||||
|
||||
---
|
||||
|
||||
## 6. 企业微信会看到什么
|
||||
|
||||
- 关键位:按类型与结案结果推送(RR 不足,下单失败,自动开仓成功,仅阻力支撑提醒等),**每条关键位结案路径原则上一条主推送**(详见 `关键位自动下单说明.md`).
|
||||
- 手工开仓,平仓,部分异常也会在规则满足时推送(以代码与配置为准).
|
||||
|
||||
若未配置 **`WECHAT_WEBHOOK`** 或网络失败,可能只是看不到推送,不代表逻辑未执行;要紧操作请以 **交易所端持仓与挂单** 为准核对.
|
||||
|
||||
---
|
||||
|
||||
## 7. 强烈建议的风险与运维习惯
|
||||
|
||||
1. **先用 `LIVE_TRADING_ENABLED=false`** 验证页面,录入,推送,再开小资金开实盘.
|
||||
2. **API 权限**:仅开所需合约权限;勿泄露密钥;定期轮换.
|
||||
3. **单进程控盘**:同一账户避免本程序与其他机器人 **重复开仓**.
|
||||
4. **自动备份**:服务器上执行 `bash scripts/install_backup_cron.sh`(每天北京时间 0:00 → `/root/backups`,保留 30 天);升级前也可 `bash scripts/backup_data.sh` 手动跑一次.
|
||||
5. **升级代码后**:启动时会跑 **数据库迁移**(如新列 `order_monitors.monitor_type`);首次启动关注一下日志或无报错页面.
|
||||
|
||||
---
|
||||
|
||||
## 8. 常见问题(简要)
|
||||
|
||||
| 现象 | 可自查 |
|
||||
|------|--------|
|
||||
| 关键位永远不触发 | 5m 门控是否全通过(页面门控摘要),币种日成交量是否在规则内,`KLINE_TIMEFRAME`. |
|
||||
| 有信号但不自动开仓 | `LIVE_TRADING_ENABLED`,`KEY_AUTO_MIN_PLANNED_RR`,计划 RR,是否已有持仓,API/余额报错(微信或日志). |
|
||||
| 加不了箱体/收敛 | 是否已有活跃持仓;先平仓或改用「阻力/支撑位」仅提醒. |
|
||||
| 推送收不到 | `WECHAT_WEBHOOK`,企业微信机器人配额与网络. |
|
||||
|
||||
---
|
||||
|
||||
## 9. Binance 版(`crypto_monitor_binance`)差异速查
|
||||
|
||||
| 项目 | Gate 本仓库 | Binance 版 |
|
||||
|------|-------------|------------|
|
||||
| API 变量 | `GATE_API_KEY`,`GATE_API_SECRET`,`GATE_*` | `BINANCE_API_KEY`,`BINANCE_API_SECRET`,`BINANCE_*` |
|
||||
| 实盘开关 | `LIVE_TRADING_ENABLED`(通用) | 同上 |
|
||||
| 止盈止损挂载路径 | `_gate_place_tp_sl_orders` 与 `GATE_TPSL_*` | `_binance_place_tp_sl_orders`(U 本位条件单) |
|
||||
| 资金显示舍入 | 以本仓库为准 | 与 **`FUNDS_DECIMALS`** 等一致 |
|
||||
| 专门文档 | **`关键位自动下单说明.md`**(各仓库有一份,开头标明交易所) | 同左 |
|
||||
|
||||
操作流程(登录,关键位四类,手工单,单仓)**两份程序一致**:换目录,换 `.env` 即可对照使用.
|
||||
|
||||
@@ -1,175 +1,192 @@
|
||||
# 关键位监控说明(自动开仓 + 人工盯盘)
|
||||
|
||||
**适用:`crypto_monitor_gate`(Gate U 本位永续)**
|
||||
Binance / OKX 见各自目录下同名文档;共享逻辑在仓库根目录 `key_monitor_lib.py`。
|
||||
|
||||
本文档与 `.env`、`check_key_monitors`、`add_key`、`_key_hard_checks`、`_process_key_rs_level_alert` 一致。
|
||||
|
||||
---
|
||||
|
||||
## 一、监控类型总览
|
||||
|
||||
| 录入类型 | 录入时选方向 | 自动市价开仓 | 触发与结案 |
|
||||
|----------|--------------|--------------|------------|
|
||||
| **箱体突破** | **必选** 多/空 | **是**(门控 + RR) | 条件满足 → 开仓或 `rr_insufficient` / `exchange_failed` → **一次性删除** |
|
||||
| **收敛突破** | **必选** 多/空 | **是**(同上) | 同上 |
|
||||
| **关键阻力位** | **不选**(`direction=watch`) | **否** | 5m 收盘突破上/下沿 → 微信 **3 次** → `key_level_alert_done` |
|
||||
| **关键支撑位** | **不选** | **否** | 同上(与阻力位**相同规则**:填上沿+下沿,程序双向监控) |
|
||||
| 斐波回调 0.618 / 0.786 | 必选 | 限价挂单逻辑 | 见斐波说明(**不在下文展开**) |
|
||||
| **回调触价开仓** | **必选** 多/空 | **程序盯价 → 回调触 E 后市价** | 见下文 **§四** |
|
||||
| **突破触价开仓** | **必选** 多/空 | **程序盯价 → 穿越 E 立即市价** | 见下文 **§四** |
|
||||
|
||||
**添加时(箱体/收敛/斐波/触价):** 品种须 **日成交量排名前 `KEY_DAILY_VOLUME_RANK_MAX`(默认 30)**;上沿 **>** 下沿(触价开仓填 E/SL/TP,上下沿仅作展示占位)。
|
||||
|
||||
---
|
||||
|
||||
## 二、关键阻力位 / 关键支撑位(人工盯盘)
|
||||
|
||||
### 2.1 录入
|
||||
|
||||
- 填写 **上沿 `upper`** 与 **下沿 `lower`**(程序同时监控两侧,**无法预先判定**做多还是做空)。
|
||||
- 页面 **不显示、不要求** 方向;库中 `direction` 初始为 `watch`,**首次突破后** 写入 `long`(向上突破上沿)或 `short`(向下突破下沿)。
|
||||
|
||||
### 2.2 触发(极简)
|
||||
|
||||
- 周期:**`KLINE_TIMEFRAME`(默认 5m)最近一根已闭合 K** 的 **收盘价**(非影线)。
|
||||
- **向上突破上沿:** `收盘 > upper` → 推断方向 **多 / 向上**,本次监控任务开始按节奏提醒。
|
||||
- **向下突破下沿:** `收盘 < lower` → 推断方向 **空 / 向下**,本次任务同样开始提醒。
|
||||
- **任一侧突破即结束本条监控周期**(不会在突破后再等待另一侧;上沿、下沿谁先满足用谁,同根 K 仅可能满足一侧)。
|
||||
|
||||
**不参与:** 量能、二确 K、越过幅度下限、日成交排名(运行时)、计划 RR、自动开仓。
|
||||
|
||||
### 2.3 微信提醒次数
|
||||
|
||||
| 配置 | 默认 | 含义 |
|
||||
|------|------|------|
|
||||
| `KEY_ALERT_MAX_TIMES` | `3` | 突破后最多推送 3 次 |
|
||||
| `KEY_ALERT_INTERVAL_MINUTES` | `5` | 相邻两次推送至少间隔 5 分钟 |
|
||||
|
||||
- 第 1 次:首次检测到突破的当次轮询(若已闭合 5m 满足条件)。
|
||||
- 第 2、3 次:仅按间隔推送(**不要求**价格仍在箱外)。
|
||||
- 第 3 次推送后:写入 `key_monitor_history`,`close_reason=**key_level_alert_done**`,从 `key_monitors` **删除**。
|
||||
|
||||
### 2.4 与箱体/收敛的区别
|
||||
|
||||
| 项目 | 阻力/支撑 | 箱体/收敛 |
|
||||
|------|-----------|-----------|
|
||||
| 方向 | 程序推断 | 人工选择 |
|
||||
| K 线根数 | 1 根闭合 5m | 2 根(突破 K + 确认 K) |
|
||||
| 提醒次数 | 3 次后结案 | 自动单:触发后 1 次业务推送并结案 |
|
||||
|
||||
---
|
||||
|
||||
## 三、箱体突破 / 收敛突破(自动开仓)
|
||||
|
||||
### 3.1 K 线结构(默认索引)
|
||||
|
||||
| 角色 | 环境变量 | 默认 | 含义 |
|
||||
|------|----------|------|------|
|
||||
| 突破 K | `KEY_CONFIRM_BREAKOUT_BAR` | `-2` | 倒数第 2 根闭合 K |
|
||||
| 确认 K | `KEY_CONFIRM_BAR` | `-1` | 倒数第 1 根闭合 K |
|
||||
|
||||
### 3.2 硬门控(须全部通过)
|
||||
|
||||
1. **有效突破(收盘越界)**
|
||||
- 多:`突破 K 收盘 > upper`
|
||||
- 空:`突破 K 收盘 < lower`
|
||||
|
||||
2. **突破越过幅度(仅下限)**
|
||||
- 多:`(突破 K 收盘 − upper) / upper × 100 > KEY_BREAKOUT_AMP_MIN_PCT`(默认 **0.03%**)
|
||||
- 空:`(lower − 突破 K 收盘) / lower × 100 >` 同上
|
||||
- **无上限**;突破过猛由 **计划 RR** 过滤。
|
||||
- **不再**使用 K 线实体占开盘价比例;`KEY_BREAKOUT_AMP_MAX_PCT` **已不参与门控**。
|
||||
|
||||
3. **确认 K 不进箱体**
|
||||
- 多:确认 K 收盘 **`> upper`**(不得在 `[lower, upper]` 内)
|
||||
- 空:确认 K 收盘 **`< lower`**
|
||||
|
||||
4. **量能:** 突破 K 成交量 > 前 `KEY_VOLUME_MA_BARS`(默认 20)根均量 × `KEY_VOLUME_RATIO_MIN`(默认 1.3)
|
||||
|
||||
5. **日成交量排名:** 运行时仍须前 `KEY_DAILY_VOLUME_RANK_MAX`(默认 30)
|
||||
|
||||
6. **计划 RR(最后经济门控):** 按确认 K 收盘 **E** 计算 SL/TP 后,`RR` **严格大于** `KEY_AUTO_MIN_PLANNED_RR`(默认 1.5)才市价开仓
|
||||
|
||||
### 3.3 止损 / 止盈(确认 K 收盘为 E)
|
||||
|
||||
箱体高 **H = |upper − lower|**。止损锚在 **突破 K 极值** 外侧:
|
||||
|
||||
| 方向 | 止损(标准/趋势方案) |
|
||||
|------|------------------------|
|
||||
| 多 | 突破 K **最低价** × (1 − `KEY_STOP_OUTSIDE_BREAKOUT_PCT`%) |
|
||||
| 空 | 突破 K **最高价** × (1 + `KEY_STOP_OUTSIDE_BREAKOUT_PCT`%) |
|
||||
|
||||
止盈方案见下表(与改版前一致):
|
||||
|
||||
| 方案 | `sl_tp_mode` | 多:SL / TP | 空:SL / TP |
|
||||
|------|--------------|-------------|-------------|
|
||||
| 标准突破 | `standard` | 突破 K 低外侧% / **E+H** | 突破 K 高外侧% / **E−H** |
|
||||
| 箱体 1R·止盈 1.5H | `box_1p5` | **E−H** / **E+1.5×H** | **E+H** / **E−1.5×H** |
|
||||
| 趋势单·自填止盈 | `trend_manual` | 突破 K 低 × (1−`KEY_TREND_STOP_OUTSIDE_PCT`%) / **录入止盈** | 突破 K 高外侧% / **录入止盈** |
|
||||
|
||||
### 3.4 一次性结案(`close_reason`)
|
||||
|
||||
| `close_reason` | 含义 |
|
||||
|----------------|------|
|
||||
| `box_opposite_break` | 标记价先突破反向边界(多:≤下沿;空:≥上沿) |
|
||||
| `rr_insufficient` | 门控通过但 RR 不达标或 SL/TP 几何无效 |
|
||||
| `exchange_failed` | RR 达标但实盘/交易所等原因未开仓 |
|
||||
| `auto_opened` | RR 达标且市价开仓成功 |
|
||||
| `key_level_alert_done` | 阻力/支撑 **3 次提醒** 完成 |
|
||||
|
||||
---
|
||||
|
||||
## 四、回调 / 突破触价开仓(程序触价,无交易所挂单)
|
||||
|
||||
### 4.1 录入
|
||||
|
||||
- **回调触价开仓**:方向必选多/空;填写 **计划入场价 E**、**止损 SL**、**止盈 TP**(做多须 `SL < E < TP`)。
|
||||
- **突破触价开仓**:同上;添加时当前价须在突破方向一侧(做多:价低于 E;做空:价高于 E)。
|
||||
- 计划 RR 以 **E** 为基准,须 **严格大于** `KEY_AUTO_MIN_PLANNED_RR`(默认 1.5)。
|
||||
- 可选移动保本、时间平仓;**全仓杠杆模式**下可用。
|
||||
|
||||
### 4.2 触发与结案
|
||||
|
||||
| 类型 | 触发条件(标记价) |
|
||||
|------|-------------------|
|
||||
| **回调触价** | 做多 `≤ E`;做空 `≥ E` → 下一轮询市价开仓 |
|
||||
| **突破触价** | 做多**向上穿越** E;做空**向下穿越** E → **立即**市价开仓 |
|
||||
|
||||
- 未成交前标记价先触 **TP 侧** → `trigger_tp_invalidate`。
|
||||
- **突破触价**另:未穿越 E 先触 **SL 侧** → `trigger_sl_invalidate`。
|
||||
- **24h** 未触发 → `trigger_entry_expired`。
|
||||
- 成功 → `trigger_entry_filled`;触发后开仓失败 → `trigger_exchange_failed`。
|
||||
|
||||
### 4.3 计仓与占位
|
||||
|
||||
- **以损定仓**:按 E、SL 反推保证金,触发时重算;**全仓杠杆**:可用×缓冲比例,BTC/ETH 10x、其它 5x。
|
||||
- **占当日开仓意图**(已开 + 待触发),未成交不占持仓;同币仅 1 条触价监控(含回调/突破)。
|
||||
|
||||
共享逻辑:`trigger_entry_key_monitor_lib.py`;轮询:`check_trigger_entry_key_monitors`。
|
||||
|
||||
---
|
||||
|
||||
## 五、环境与参数(`.env` 摘要)
|
||||
|
||||
| 变量 | 箱体/收敛 | 阻力/支撑 |
|
||||
|------|-----------|-----------|
|
||||
| `KEY_BREAKOUT_AMP_MIN_PCT` | 突破越过下限(默认 0.03) | 不用 |
|
||||
| `KEY_BREAKOUT_AMP_MAX_PCT` | **已废弃门控** | 不用 |
|
||||
| `KEY_VOLUME_*` / `KEY_CONFIRM_*` | 用 | 不用 |
|
||||
| `KEY_AUTO_MIN_PLANNED_RR` | 用 | 不用 |
|
||||
| `KEY_ALERT_MAX_TIMES` / `KEY_ALERT_INTERVAL_MINUTES` | 不用 | 用(默认 3 次 / 5 分钟) |
|
||||
| `KEY_DAILY_VOLUME_RANK_MAX` | 添加时 + 运行时 | **仅添加时** |
|
||||
|
||||
---
|
||||
|
||||
## 六、相关代码
|
||||
|
||||
| 说明 | 位置 |
|
||||
|------|------|
|
||||
| 共享判定 | `key_monitor_lib.py` |
|
||||
| 主循环 | `check_key_monitors` |
|
||||
| 自动门控 | `_key_hard_checks` |
|
||||
| 阻力/支撑提醒 | `_process_key_rs_level_alert` |
|
||||
| 录入 | `add_key` |
|
||||
| 开仓 | `_market_open_for_key_monitor` |
|
||||
# 关键位监控说明(自动开仓 + 人工盯盘)
|
||||
|
||||
**适用:Gate / Binance / OKX 三所实例(共用 `lib/key_monitor/key_auto_order_lib.py`)**
|
||||
|
||||
## 环境开关 `KEY_AUTO_ORDER_ENABLED`(默认 `false`)
|
||||
|
||||
| 计仓模式 | 开关 | 关键位程序自动单 |
|
||||
|----------|------|------------------|
|
||||
| `risk`(以损定仓) | `false` | **全部关闭**(含触价);支撑/阻力微信提醒仍可用 |
|
||||
| `risk` | `true` | 箱体/收敛/斐波/假突破/触价均可自动(旧行为) |
|
||||
| `full_margin`(全仓) | `false` | 全部关闭(含触价) |
|
||||
| `full_margin` | `true` | **仅触价**自动;箱体/斐波等仍禁止 |
|
||||
|
||||
**不受本开关影响:** 人工实盘下单,关键支撑/阻力提醒,**顺势加仓**(`risk` 下),趋势回调(`risk` 下).全仓模式下策略自动仍禁止.
|
||||
|
||||
修改 `.env` 后须 **重启 PM2**.复盘「开仓类型」与统计分段会随开关联动隐藏关键位选项.
|
||||
|
||||
---
|
||||
|
||||
**适用:`crypto_monitor_gate`(Gate U 本位永续)**
|
||||
Binance / OKX 见各自目录下同名文档;共享逻辑在 `lib/key_monitor/`.
|
||||
|
||||
本文档与 `.env`,`check_key_monitors`,`add_key`,`_key_hard_checks`,`_process_key_rs_level_alert` 一致.
|
||||
|
||||
---
|
||||
|
||||
## 一,监控类型总览
|
||||
|
||||
| 录入类型 | 录入时选方向 | 自动市价开仓 | 触发与结案 |
|
||||
|----------|--------------|--------------|------------|
|
||||
| **箱体突破** | **必选** 多/空 | **是**(门控 + RR) | 条件满足 → 开仓或 `rr_insufficient` / `exchange_failed` → **一次性删除** |
|
||||
| **收敛突破** | **必选** 多/空 | **是**(同上) | 同上 |
|
||||
| **关键阻力位** | **不选**(`direction=watch`) | **否** | 5m 收盘突破上/下沿 → 微信 **3 次** → `key_level_alert_done` |
|
||||
| **关键支撑位** | **不选** | **否** | 同上(与阻力位**相同规则**:填上沿+下沿,程序双向监控) |
|
||||
| 斐波回调 0.618 / 0.786 | 必选 | 限价挂单逻辑 | 见斐波说明(**不在下文展开**) |
|
||||
| **回调触价开仓** | **必选** 多/空 | **程序盯价 → 回调触 E 后市价** | 见下文 **§四** |
|
||||
| **突破触价开仓** | **必选** 多/空 | **程序盯价 → 穿越 E 立即市价** | 见下文 **§四** |
|
||||
|
||||
**添加时(箱体/收敛/斐波/触价):** 品种须 **日成交量排名前 `KEY_DAILY_VOLUME_RANK_MAX`(默认 30)**;上沿 **>** 下沿(触价开仓填 E/SL/TP,上下沿仅作展示占位).
|
||||
|
||||
---
|
||||
|
||||
## 二,关键阻力位 / 关键支撑位(人工盯盘)
|
||||
|
||||
### 2.1 录入
|
||||
|
||||
- 填写 **上沿 `upper`** 与 **下沿 `lower`**(程序同时监控两侧,**无法预先判定**做多还是做空).
|
||||
- 页面 **不显示,不要求** 方向;库中 `direction` 初始为 `watch`,**首次突破后** 写入 `long`(向上突破上沿)或 `short`(向下突破下沿).
|
||||
|
||||
### 2.2 触发(极简)
|
||||
|
||||
- 周期:**`KLINE_TIMEFRAME`(默认 5m)最近一根已闭合 K** 的 **收盘价**(非影线).
|
||||
- **向上突破上沿:** `收盘 > upper` → 推断方向 **多 / 向上**,本次监控任务开始按节奏提醒.
|
||||
- **向下突破下沿:** `收盘 < lower` → 推断方向 **空 / 向下**,本次任务同样开始提醒.
|
||||
- **任一侧突破即结束本条监控周期**(不会在突破后再等待另一侧;上沿,下沿谁先满足用谁,同根 K 仅可能满足一侧).
|
||||
|
||||
**不参与:** 量能,二确 K,越过幅度下限,日成交排名(运行时),计划 RR,自动开仓.
|
||||
|
||||
### 2.3 微信提醒次数
|
||||
|
||||
| 配置 | 默认 | 含义 |
|
||||
|------|------|------|
|
||||
| `KEY_ALERT_MAX_TIMES` | `3` | 突破后最多推送 3 次 |
|
||||
| `KEY_ALERT_INTERVAL_MINUTES` | `5` | 相邻两次推送至少间隔 5 分钟 |
|
||||
|
||||
- 第 1 次:首次检测到突破的当次轮询(若已闭合 5m 满足条件).
|
||||
- 第 2,3 次:仅按间隔推送(**不要求**价格仍在箱外).
|
||||
- 第 3 次推送后:写入 `key_monitor_history`,`close_reason=**key_level_alert_done**`,从 `key_monitors` **删除**.
|
||||
|
||||
### 2.4 与箱体/收敛的区别
|
||||
|
||||
| 项目 | 阻力/支撑 | 箱体/收敛 |
|
||||
|------|-----------|-----------|
|
||||
| 方向 | 程序推断 | 人工选择 |
|
||||
| K 线根数 | 1 根闭合 5m | 2 根(突破 K + 确认 K) |
|
||||
| 提醒次数 | 3 次后结案 | 自动单:触发后 1 次业务推送并结案 |
|
||||
|
||||
---
|
||||
|
||||
## 三,箱体突破 / 收敛突破(自动开仓)
|
||||
|
||||
### 3.1 K 线结构(默认索引)
|
||||
|
||||
| 角色 | 环境变量 | 默认 | 含义 |
|
||||
|------|----------|------|------|
|
||||
| 突破 K | `KEY_CONFIRM_BREAKOUT_BAR` | `-2` | 倒数第 2 根闭合 K |
|
||||
| 确认 K | `KEY_CONFIRM_BAR` | `-1` | 倒数第 1 根闭合 K |
|
||||
|
||||
### 3.2 硬门控(须全部通过)
|
||||
|
||||
1. **有效突破(收盘越界)**
|
||||
- 多:`突破 K 收盘 > upper`
|
||||
- 空:`突破 K 收盘 < lower`
|
||||
|
||||
2. **突破越过幅度(仅下限)**
|
||||
- 多:`(突破 K 收盘 − upper) / upper × 100 > KEY_BREAKOUT_AMP_MIN_PCT`(默认 **0.03%**)
|
||||
- 空:`(lower − 突破 K 收盘) / lower × 100 >` 同上
|
||||
- **无上限**;突破过猛由 **计划 RR** 过滤.
|
||||
- **不再**使用 K 线实体占开盘价比例;`KEY_BREAKOUT_AMP_MAX_PCT` **已不参与门控**.
|
||||
|
||||
3. **确认 K 不进箱体**
|
||||
- 多:确认 K 收盘 **`> upper`**(不得在 `[lower, upper]` 内)
|
||||
- 空:确认 K 收盘 **`< lower`**
|
||||
|
||||
4. **量能:** 突破 K 成交量 > 前 `KEY_VOLUME_MA_BARS`(默认 20)根均量 × `KEY_VOLUME_RATIO_MIN`(默认 1.3)
|
||||
|
||||
5. **日成交量排名:** 运行时仍须前 `KEY_DAILY_VOLUME_RANK_MAX`(默认 30)
|
||||
|
||||
6. **计划 RR(最后经济门控):** 按确认 K 收盘 **E** 计算 SL/TP 后,`RR` **严格大于** `KEY_AUTO_MIN_PLANNED_RR`(默认 1.5)才市价开仓
|
||||
|
||||
### 3.3 止损 / 止盈(确认 K 收盘为 E)
|
||||
|
||||
箱体高 **H = |upper − lower|**.止损锚在 **突破 K 极值** 外侧:
|
||||
|
||||
| 方向 | 止损(标准/趋势方案) |
|
||||
|------|------------------------|
|
||||
| 多 | 突破 K **最低价** × (1 − `KEY_STOP_OUTSIDE_BREAKOUT_PCT`%) |
|
||||
| 空 | 突破 K **最高价** × (1 + `KEY_STOP_OUTSIDE_BREAKOUT_PCT`%) |
|
||||
|
||||
止盈方案见下表(与改版前一致):
|
||||
|
||||
| 方案 | `sl_tp_mode` | 多:SL / TP | 空:SL / TP |
|
||||
|------|--------------|-------------|-------------|
|
||||
| 标准突破 | `standard` | 突破 K 低外侧% / **E+H** | 突破 K 高外侧% / **E−H** |
|
||||
| 箱体 1R·止盈 1.5H | `box_1p5` | **E−H** / **E+1.5×H** | **E+H** / **E−1.5×H** |
|
||||
| 趋势单·自填止盈 | `trend_manual` | 突破 K 低 × (1−`KEY_TREND_STOP_OUTSIDE_PCT`%) / **录入止盈** | 突破 K 高外侧% / **录入止盈** |
|
||||
|
||||
### 3.4 一次性结案(`close_reason`)
|
||||
|
||||
| `close_reason` | 含义 |
|
||||
|----------------|------|
|
||||
| `box_opposite_break` | 标记价先突破反向边界(多:≤下沿;空:≥上沿) |
|
||||
| `rr_insufficient` | 门控通过但 RR 不达标或 SL/TP 几何无效 |
|
||||
| `exchange_failed` | RR 达标但实盘/交易所等原因未开仓 |
|
||||
| `auto_opened` | RR 达标且市价开仓成功 |
|
||||
| `key_level_alert_done` | 阻力/支撑 **3 次提醒** 完成 |
|
||||
|
||||
---
|
||||
|
||||
## 四,回调 / 突破触价开仓(程序触价,无交易所挂单)
|
||||
|
||||
### 4.1 录入
|
||||
|
||||
- **回调触价开仓**:方向必选多/空;填写 **计划入场价 E**,**止损 SL**,**止盈 TP**(做多须 `SL < E < TP`).
|
||||
- **突破触价开仓**:同上;添加时当前价须在突破方向一侧(做多:价低于 E;做空:价高于 E).
|
||||
- 计划 RR 以 **E** 为基准,须 **严格大于** `KEY_AUTO_MIN_PLANNED_RR`(默认 1.5).
|
||||
- 可选移动保本,时间平仓;**全仓杠杆模式**下可用.
|
||||
|
||||
### 4.2 触发与结案
|
||||
|
||||
| 类型 | 触发条件(标记价) |
|
||||
|------|-------------------|
|
||||
| **回调触价** | 做多 `≤ E`;做空 `≥ E` → 下一轮询市价开仓 |
|
||||
| **突破触价** | 做多**向上穿越** E;做空**向下穿越** E → **立即**市价开仓 |
|
||||
|
||||
- 未成交前标记价先触 **TP 侧** → `trigger_tp_invalidate`.
|
||||
- **突破触价**另:未穿越 E 先触 **SL 侧** → `trigger_sl_invalidate`.
|
||||
- **24h** 未触发 → `trigger_entry_expired`.
|
||||
- 成功 → `trigger_entry_filled`;触发后开仓失败 → `trigger_exchange_failed`.
|
||||
|
||||
### 4.3 计仓与占位
|
||||
|
||||
- **以损定仓**:按 E,SL 反推保证金,触发时重算;**全仓杠杆**:可用×缓冲比例,BTC/ETH 10x,其它 5x.
|
||||
- **占当日开仓意图**(已开 + 待触发),未成交不占持仓;同币仅 1 条触价监控(含回调/突破).
|
||||
|
||||
共享逻辑:`trigger_entry_key_monitor_lib.py`;轮询:`check_trigger_entry_key_monitors`.
|
||||
|
||||
---
|
||||
|
||||
## 五,环境与参数(`.env` 摘要)
|
||||
|
||||
| 变量 | 箱体/收敛 | 阻力/支撑 |
|
||||
|------|-----------|-----------|
|
||||
| `KEY_BREAKOUT_AMP_MIN_PCT` | 突破越过下限(默认 0.03) | 不用 |
|
||||
| `KEY_BREAKOUT_AMP_MAX_PCT` | **已废弃门控** | 不用 |
|
||||
| `KEY_VOLUME_*` / `KEY_CONFIRM_*` | 用 | 不用 |
|
||||
| `KEY_AUTO_MIN_PLANNED_RR` | 用 | 不用 |
|
||||
| `KEY_ALERT_MAX_TIMES` / `KEY_ALERT_INTERVAL_MINUTES` | 不用 | 用(默认 3 次 / 5 分钟) |
|
||||
| `KEY_DAILY_VOLUME_RANK_MAX` | 添加时 + 运行时 | **仅添加时** |
|
||||
|
||||
---
|
||||
|
||||
## 六,相关代码
|
||||
|
||||
| 说明 | 位置 |
|
||||
|------|------|
|
||||
| 共享判定 | `key_monitor_lib.py` |
|
||||
| 主循环 | `check_key_monitors` |
|
||||
| 自动门控 | `_key_hard_checks` |
|
||||
| 阻力/支撑提醒 | `_process_key_rs_level_alert` |
|
||||
| 录入 | `add_key` |
|
||||
| 开仓 | `_market_open_for_key_monitor` |
|
||||
|
||||
@@ -1,148 +1,148 @@
|
||||
# 界面与风控更新说明(Gate 实例)
|
||||
|
||||
## 顶栏导航(4 项)
|
||||
|
||||
| 顺序 | 名称 | 路由 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 1 | 关键位监控 | `/key_monitor` | 关键位添加、实时门控、历史 |
|
||||
| 2 | 实盘下单 | `/trade` | 人工开仓、划转、实时持仓(**默认首页** `/` → `/trade`) |
|
||||
| 3 | 交易记录与复盘 | `/records` | 交易记录、复盘表单、AI 历史(受顶栏 UTC 时间窗筛选) |
|
||||
| 4 | 统计分析 | `/stats` | 按北京时间交易日切日 + 分品类统计块 |
|
||||
|
||||
## 关键位监控页
|
||||
|
||||
- 标题去掉「5m」;规则条从 `.env` 读取(周期、确认K、量能、自动开仓盈亏比、日成交量排名)。
|
||||
- 左列:活跃关键位,**pos-card** 样式展示现价/距上沿/距下沿/门控。
|
||||
- 右列:关键位历史(失效/结案),与左列等高滚动;**受顶栏 UTC 列表时间窗筛选**(默认 UTC 当日)。
|
||||
- 监控类型新增:**斐波回调0.618**、**斐波回调0.786**(与 Binance 主站同一套规则,计算逻辑见仓库根目录 `fib_key_monitor_lib.py`)。
|
||||
|
||||
### 斐波关键位监控(方案 A:交易所限价)
|
||||
|
||||
| 项 | 说明 |
|
||||
|----|------|
|
||||
| 同币互斥 | 每个币种只能有一条斐波监控(0.618 与 0.786 不可并存) |
|
||||
| 上下沿 | 上沿 **H**、下沿 **L**(须 H > L) |
|
||||
| 挂单价 E | **做多** `E = H − ratio × (H − L)`(自 H 向下回撤);**做空** `E = L + ratio × (H − L)`(自 L 向上反弹) |
|
||||
| 做多 | 限价 @ E,止损 L,止盈 H |
|
||||
| 做空 | 限价 @ E,止损 H,止盈 L |
|
||||
| 添加后 | **立即**在 Gate 挂限价单;卡片显示 **挂E**、限价单 ID |
|
||||
| 失效 | 以**标记价**判断:做多且标记价 ≥ H、做空且标记价 ≤ L,且限价**未成交** → 撤销该限价单并结案(不写历史开仓) |
|
||||
| 成交后 | 按仓位挂交易所 TP/SL → 写入 **实盘下单监控**(`monitor_type=关键位监控`,`key_signal_type=斐波回调0.618/0.786`)→ 从关键位列表移除 |
|
||||
| 撤单 | 仅撤本条斐波的 `fib_limit_order_id`,**不会** `cancel_all`,避免误伤其他委托 |
|
||||
| 盈亏比 | 计划 RR 须 > `KEY_AUTO_MIN_PLANNED_RR`(与箱体/收敛一致);0.618 理论约 1.6:1,0.786 约 3.7:1 |
|
||||
| 日成交量 | 与箱体/收敛相同,须在前 `KEY_DAILY_VOLUME_RANK_MAX` 名内方可添加 |
|
||||
|
||||
后台轮询:`check_fib_key_monitors()`(标记价失效 / 成交检测);箱体/收敛仍走 `check_key_monitors()`,互不干扰。
|
||||
|
||||
手动删除关键位时,若斐波限价尚未成交,会先撤交易所限价再删库记录。
|
||||
|
||||
### 箱体 / 收敛自动开仓(来源标注)
|
||||
|
||||
- 自动开仓写入 `order_monitors.key_signal_type`:`箱体突破` 或 `收敛突破`。
|
||||
- 持仓卡片、交易记录列表会显示「来源 · 信号类型」。
|
||||
|
||||
## 列表时间窗(UTC,全站顶栏)
|
||||
|
||||
共用模块:仓库根目录 `history_window_lib.py`(Gate / Binance 主站一致)。
|
||||
|
||||
| 项 | 说明 |
|
||||
|----|------|
|
||||
| 默认 | **UTC 当日**(`win_preset=utc_today`,从 UTC 0:00 至当前时刻) |
|
||||
| 可选 | 近 24 小时、近 7 天、自定义起止(UTC,`datetime-local`) |
|
||||
| 作用范围 | 关键位历史、交易记录列表、复盘记录 API、AI 历史 API、导出「交易记录」「关键位历史」 |
|
||||
| 与统计的关系 | **仅影响列表/导出**;**统计分析页仍按北京时间 `TRADING_DAY_RESET_HOUR`(默认 8:00)切交易日** |
|
||||
| 库内时间 | DB 存北京时间字符串;后端用 `utc_window_to_bj_sql_strings()` 换算后再 SQL 比较 |
|
||||
| 切换方式 | 顶栏「列表筛选(UTC)」→ 选预设 → **应用**(保留当前路由,如 `/records?win_preset=…`) |
|
||||
|
||||
查询参数示例:
|
||||
|
||||
- `?win_preset=utc_today`
|
||||
- `?win_preset=utc_last24h` / `utc_last7d`
|
||||
- `?win_preset=custom&from_utc=2026-05-18 00:00:00&to_utc=2026-05-19 12:00:00`
|
||||
|
||||
## 交易记录与复盘
|
||||
|
||||
- 平仓记录可同步交易所已实现盈亏(Gate 仓位历史等);列表盈亏列优先显示交易所数据,标注 **所** / **估**。
|
||||
- 记录页提供 **立即同步**(`POST /api/sync_exchange_pnl`),用于补全或刷新 `exchange_realized_pnl` 等字段。
|
||||
- 未做人工复盘时,展示以交易所盈亏为准(有同步数据时)。
|
||||
- **列表默认只显示当前 UTC 时间窗内**的记录(见上节);导出 CSV 同步该时间窗。
|
||||
- 表头 **「止损(开仓)」**:展示开仓快照 `initial_stop_loss`(无则回退 `stop_loss`);核对/复盘仍可用有效止损字段。
|
||||
- 平仓写入 `trade_records` 时:`stop_loss` 与 `initial_stop_loss` 均写入**开仓时止损快照**;`key_signal_type` 保留箱体/收敛/斐波来源(`fib_key_monitor_lib.key_signal_type_for_trade_record`)。
|
||||
- **开仓类型**(`entry_reason`):机器单平仓入库时,若未手填,按 `key_signal_type` 自动映射(见下表);列表/导出「开仓类型」列 = 复盘核对值优先,否则入库值,否则按信号映射。
|
||||
|
||||
| `key_signal_type` | 自动写入的 `entry_reason` |
|
||||
|-------------------|---------------------------|
|
||||
| 箱体突破 | 关键位箱体突破 |
|
||||
| 收敛突破 | 关键位收敛突破 |
|
||||
| 斐波回调0.618 | 关键位斐波0.618 |
|
||||
| 斐波回调0.786 | 关键位斐波0.786 |
|
||||
|
||||
- 复盘表单 **开仓类型** 下拉新增上述四条固定文案(与趋势/波段类并列)。
|
||||
- 复盘 **离场触发** 新增 **「止盈」**;从交易记录「填入复盘」时,若结果为「止盈/保本止盈/移动止盈/止损/手动平仓」会自动选中对应触发项,并按 `key_signal_type` 预填开仓类型。
|
||||
- 勾选「保存时自动生成多周期 K 线图」时:以 **平仓时间** 为锚点,各周期向前约 `ORDER_CHART_LIMIT`(默认 100)根 K 线(`_fetch_ohlcv_ending_at`),不再固定拉「最近 100 根」。
|
||||
- `/api/journals`、`/api/reviews` 支持同一时间窗 query,与列表一致。
|
||||
|
||||
### 导出(交易记录 v3)
|
||||
|
||||
- 文件名:`trade_records_v3_YYYYMMDD.csv`
|
||||
- 相对 v2 增加:`key_signal_type`、`initial_stop_loss`(及开仓快照列)、`planned_rr`、`actual_rr`、`risk_amount`、交易所盈亏与时间字段等;末列「开仓类型」为有效展示文案。
|
||||
- 「关键位历史」导出同样受 UTC 时间窗限制。
|
||||
|
||||
## 实盘下单页
|
||||
|
||||
- 左列:实盘下单监控(表单、划转、规则)。
|
||||
- 右列:实时持仓(独立模块)。
|
||||
- **人工开仓门控**:计划盈亏比 < `MANUAL_MIN_PLANNED_RR`(默认 **1.4**)时前端弹窗 + 后端拒绝。
|
||||
- **移动保本**(勾选启用):监控轮询达到触发 RR 后,止损阶梯上移时**同步交易所**——调用与页面「挂止盈止损」相同的 **先撤后挂**(`replace_active_monitor_tpsl_on_exchange`:撤该合约全部 TP/SL 条件单 → 按新止损 + 原止盈重挂)。仅交易所成功后才写库;失败发企业微信告警,本地止损不变。未配置实盘 API 时仍只更新本地(与旧行为一致)。
|
||||
|
||||
## 统计分析页(`/stats`)
|
||||
|
||||
| 项 | 说明 |
|
||||
|----|------|
|
||||
| 切日 | **北京时间**;交易日边界 = 每日 `TRADING_DAY_RESET_HOUR:00`(`.env` 默认 **8**) |
|
||||
| 品类下拉 | 页顶 **「统计品类」** 下拉切换(默认「全部交易」):全部交易、下单监控、关键位箱体突破、关键位收敛结构、关键位斐波0.618、关键位斐波0.786;一次只显示所选品类的日/周/月 |
|
||||
| URL | 切换后写入 `stats_segment=`(如 `all`、`manual`、`key_box`、`key_conv`、`key_fib618`、`key_fib786`),刷新 `/stats` 可保持选项 |
|
||||
| 每块指标 | 日 / 周 / 月:开单次数、平仓笔数、胜率、净盈亏、回撤、连续亏损等(与原口径一致) |
|
||||
| 开单次数 | 人工块:`monitor_type=下单监控` 且无 `key_signal_type`;关键位块:按 `order_monitors.key_signal_type` 计数 |
|
||||
| 不受 UTC 窗影响 | 统计始终基于库内全部已平仓记录,按北京交易日归类,**不**随顶栏 UTC 列表窗切换 |
|
||||
|
||||
## 持仓与计仓
|
||||
|
||||
- `MAX_ACTIVE_POSITIONS` 默认 **1**(可在 `.env` 调大)。
|
||||
- 关键位自动开仓:在已有持仓时,若 `KEY_SIZING_USE_ZERO_POSITION_SNAPSHOT=true`,按**首笔开仓前**交易账户资金快照计仓(`trading_sessions.key_sizing_capital_snapshot`)。
|
||||
|
||||
## 配置
|
||||
|
||||
详见 `.env.example` 中「关键位门控」「交易执行 / 人工风控」注释段。Gate 专用项(`GATE_*`、止盈止损触发等)保持原有段落不变。
|
||||
|
||||
## 自动备份(服务器)
|
||||
|
||||
- 脚本:`scripts/backup_data.sh`(`crypto.db` + `static/images`)
|
||||
- 定时:`scripts/install_backup_cron.sh` → 每天 **北京时间 0:00**,目录 **`/root/backups/<实例名>/YYYY-MM-DD/`**,保留 **30** 天
|
||||
- 详见 `部署文档.md` 第 5.4 节(自动备份)
|
||||
|
||||
## 数据库(启动时自动迁移)
|
||||
|
||||
`key_monitors` 新增斐波字段(示例):`fib_limit_order_id`、`fib_entry_price`、`fib_stop_loss`、`fib_take_profit`、`fib_order_amount`、`fib_margin_capital`、`fib_leverage`。
|
||||
|
||||
`trade_records` / `order_monitors` 新增或沿用:`key_signal_type`、`exchange_realized_pnl`、`exchange_opened_at`、`exchange_closed_at`、`exchange_sync_key`、`entry_reason`、`reviewed_entry_reason`、`initial_stop_loss`。
|
||||
|
||||
**历史数据**:本次**不做**旧记录的批量回填(`entry_reason` / `initial_stop_loss` / `key_signal_type` 等);仅**新产生**的平仓与复盘按新逻辑写入。旧行展示可回退已有字段。
|
||||
|
||||
## 涉及文件(便于排查)
|
||||
|
||||
| 路径 | 说明 |
|
||||
|------|------|
|
||||
| `history_window_lib.py` | UTC 时间窗解析与转北京时间 SQL 字符串 |
|
||||
| `fib_key_monitor_lib.py` | 斐波计算、`KEY_ENTRY_REASON_BY_SIGNAL`、`entry_reason_from_key_signal` |
|
||||
| `crypto_monitor_gate/app.py` | 列表筛选、统计分块、导出 v3、复盘 K 线锚点、入库逻辑 |
|
||||
| `crypto_monitor_gate/templates/index.html` | 顶栏时间窗、统计分块 UI、止损(开仓)列、复盘预填 |
|
||||
|
||||
## 升级步骤
|
||||
|
||||
1. `git pull` 后对比 `.env.example`,把新增变量合并进本地 `.env`。
|
||||
2. 在 VPS 上为 Binance / Gate / Gate Bot **各执行一次** `bash scripts/install_backup_cron.sh`(若尚未安装)。
|
||||
3. 重启 Gate 实例服务(如 `pm2 restart crypto_gate`);首次启动会自动 `ALTER TABLE` 缺列(斐波、交易所盈亏、`entry_reason` 等)。
|
||||
4. 浏览器强刷(Ctrl+F5)避免旧版 `index.html` 缓存。
|
||||
5. 打开任意页确认顶栏出现 **「列表筛选(UTC)」**;`/stats` 可见分品类统计与「北京 8:00 切日」说明。
|
||||
6. 建议在测试币上先添加一条斐波监控,确认:限价已挂出、标记价失效会撤单、成交后出现持仓监控且 TP/SL 已挂上;平仓后交易记录止损(开仓)与开仓类型是否正确。
|
||||
# 界面与风控更新说明(Gate 实例)
|
||||
|
||||
## 顶栏导航(4 项)
|
||||
|
||||
| 顺序 | 名称 | 路由 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 1 | 关键位监控 | `/key_monitor` | 关键位添加,实时门控,历史 |
|
||||
| 2 | 实盘下单 | `/trade` | 人工开仓,划转,实时持仓(**默认首页** `/` → `/trade`) |
|
||||
| 3 | 交易记录与复盘 | `/records` | 交易记录,复盘表单,AI 历史(受顶栏 UTC 时间窗筛选) |
|
||||
| 4 | 统计分析 | `/stats` | 按北京时间交易日切日 + 分品类统计块 |
|
||||
|
||||
## 关键位监控页
|
||||
|
||||
- 标题去掉「5m」;规则条从 `.env` 读取(周期,确认K,量能,自动开仓盈亏比,日成交量排名).
|
||||
- 左列:活跃关键位,**pos-card** 样式展示现价/距上沿/距下沿/门控.
|
||||
- 右列:关键位历史(失效/结案),与左列等高滚动;**受顶栏 UTC 列表时间窗筛选**(默认 UTC 当日).
|
||||
- 监控类型新增:**斐波回调0.618**,**斐波回调0.786**(与 Binance 主站同一套规则,计算逻辑见仓库根目录 `fib_key_monitor_lib.py`).
|
||||
|
||||
### 斐波关键位监控(方案 A:交易所限价)
|
||||
|
||||
| 项 | 说明 |
|
||||
|----|------|
|
||||
| 同币互斥 | 每个币种只能有一条斐波监控(0.618 与 0.786 不可并存) |
|
||||
| 上下沿 | 上沿 **H**,下沿 **L**(须 H > L) |
|
||||
| 挂单价 E | **做多** `E = H − ratio × (H − L)`(自 H 向下回撤);**做空** `E = L + ratio × (H − L)`(自 L 向上反弹) |
|
||||
| 做多 | 限价 @ E,止损 L,止盈 H |
|
||||
| 做空 | 限价 @ E,止损 H,止盈 L |
|
||||
| 添加后 | **立即**在 Gate 挂限价单;卡片显示 **挂E**,限价单 ID |
|
||||
| 失效 | 以**标记价**判断:做多且标记价 ≥ H,做空且标记价 ≤ L,且限价**未成交** → 撤销该限价单并结案(不写历史开仓) |
|
||||
| 成交后 | 按仓位挂交易所 TP/SL → 写入 **实盘下单监控**(`monitor_type=关键位监控`,`key_signal_type=斐波回调0.618/0.786`)→ 从关键位列表移除 |
|
||||
| 撤单 | 仅撤本条斐波的 `fib_limit_order_id`,**不会** `cancel_all`,避免误伤其他委托 |
|
||||
| 盈亏比 | 计划 RR 须 > `KEY_AUTO_MIN_PLANNED_RR`(与箱体/收敛一致);0.618 理论约 1.6:1,0.786 约 3.7:1 |
|
||||
| 日成交量 | 与箱体/收敛相同,须在前 `KEY_DAILY_VOLUME_RANK_MAX` 名内方可添加 |
|
||||
|
||||
后台轮询:`check_fib_key_monitors()`(标记价失效 / 成交检测);箱体/收敛仍走 `check_key_monitors()`,互不干扰.
|
||||
|
||||
手动删除关键位时,若斐波限价尚未成交,会先撤交易所限价再删库记录.
|
||||
|
||||
### 箱体 / 收敛自动开仓(来源标注)
|
||||
|
||||
- 自动开仓写入 `order_monitors.key_signal_type`:`箱体突破` 或 `收敛突破`.
|
||||
- 持仓卡片,交易记录列表会显示「来源 · 信号类型」.
|
||||
|
||||
## 列表时间窗(UTC,全站顶栏)
|
||||
|
||||
共用模块:仓库根目录 `history_window_lib.py`(Gate / Binance 主站一致).
|
||||
|
||||
| 项 | 说明 |
|
||||
|----|------|
|
||||
| 默认 | **UTC 当日**(`win_preset=utc_today`,从 UTC 0:00 至当前时刻) |
|
||||
| 可选 | 近 24 小时,近 7 天,自定义起止(UTC,`datetime-local`) |
|
||||
| 作用范围 | 关键位历史,交易记录列表,复盘记录 API,AI 历史 API,导出「交易记录」「关键位历史」 |
|
||||
| 与统计的关系 | **仅影响列表/导出**;**统计分析页仍按北京时间 `TRADING_DAY_RESET_HOUR`(默认 8:00)切交易日** |
|
||||
| 库内时间 | DB 存北京时间字符串;后端用 `utc_window_to_bj_sql_strings()` 换算后再 SQL 比较 |
|
||||
| 切换方式 | 顶栏「列表筛选(UTC)」→ 选预设 → **应用**(保留当前路由,如 `/records?win_preset=…`) |
|
||||
|
||||
查询参数示例:
|
||||
|
||||
- `?win_preset=utc_today`
|
||||
- `?win_preset=utc_last24h` / `utc_last7d`
|
||||
- `?win_preset=custom&from_utc=2026-05-18 00:00:00&to_utc=2026-05-19 12:00:00`
|
||||
|
||||
## 交易记录与复盘
|
||||
|
||||
- 平仓记录可同步交易所已实现盈亏(Gate 仓位历史等);列表盈亏列优先显示交易所数据,标注 **所** / **估**.
|
||||
- 记录页提供 **立即同步**(`POST /api/sync_exchange_pnl`),用于补全或刷新 `exchange_realized_pnl` 等字段.
|
||||
- 未做人工复盘时,展示以交易所盈亏为准(有同步数据时).
|
||||
- **列表默认只显示当前 UTC 时间窗内**的记录(见上节);导出 CSV 同步该时间窗.
|
||||
- 表头 **「止损(开仓)」**:展示开仓快照 `initial_stop_loss`(无则回退 `stop_loss`);核对/复盘仍可用有效止损字段.
|
||||
- 平仓写入 `trade_records` 时:`stop_loss` 与 `initial_stop_loss` 均写入**开仓时止损快照**;`key_signal_type` 保留箱体/收敛/斐波来源(`fib_key_monitor_lib.key_signal_type_for_trade_record`).
|
||||
- **开仓类型**(`entry_reason`):机器单平仓入库时,若未手填,按 `key_signal_type` 自动映射(见下表);列表/导出「开仓类型」列 = 复盘核对值优先,否则入库值,否则按信号映射.
|
||||
|
||||
| `key_signal_type` | 自动写入的 `entry_reason` |
|
||||
|-------------------|---------------------------|
|
||||
| 箱体突破 | 关键位箱体突破 |
|
||||
| 收敛突破 | 关键位收敛突破 |
|
||||
| 斐波回调0.618 | 关键位斐波0.618 |
|
||||
| 斐波回调0.786 | 关键位斐波0.786 |
|
||||
|
||||
- 复盘表单 **开仓类型** 下拉新增上述四条固定文案(与趋势/波段类并列).
|
||||
- 复盘 **离场触发** 新增 **「止盈」**;从交易记录「填入复盘」时,若结果为「止盈/保本止盈/移动止盈/止损/手动平仓」会自动选中对应触发项,并按 `key_signal_type` 预填开仓类型.
|
||||
- 勾选「保存时自动生成多周期 K 线图」时:以 **平仓时间** 为锚点,各周期向前约 `ORDER_CHART_LIMIT`(默认 100)根 K 线(`_fetch_ohlcv_ending_at`),不再固定拉「最近 100 根」.
|
||||
- `/api/journals`,`/api/reviews` 支持同一时间窗 query,与列表一致.
|
||||
|
||||
### 导出(交易记录 v3)
|
||||
|
||||
- 文件名:`trade_records_v3_YYYYMMDD.csv`
|
||||
- 相对 v2 增加:`key_signal_type`,`initial_stop_loss`(及开仓快照列),`planned_rr`,`actual_rr`,`risk_amount`,交易所盈亏与时间字段等;末列「开仓类型」为有效展示文案.
|
||||
- 「关键位历史」导出同样受 UTC 时间窗限制.
|
||||
|
||||
## 实盘下单页
|
||||
|
||||
- 左列:实盘下单监控(表单,划转,规则).
|
||||
- 右列:实时持仓(独立模块).
|
||||
- **人工开仓门控**:计划盈亏比 < `MANUAL_MIN_PLANNED_RR`(默认 **1.4**)时前端弹窗 + 后端拒绝.
|
||||
- **移动保本**(勾选启用):监控轮询达到触发 RR 后,止损阶梯上移时**同步交易所**——调用与页面「挂止盈止损」相同的 **先撤后挂**(`replace_active_monitor_tpsl_on_exchange`:撤该合约全部 TP/SL 条件单 → 按新止损 + 原止盈重挂).仅交易所成功后才写库;失败发企业微信告警,本地止损不变.未配置实盘 API 时仍只更新本地(与旧行为一致).
|
||||
|
||||
## 统计分析页(`/stats`)
|
||||
|
||||
| 项 | 说明 |
|
||||
|----|------|
|
||||
| 切日 | **北京时间**;交易日边界 = 每日 `TRADING_DAY_RESET_HOUR:00`(`.env` 默认 **8**) |
|
||||
| 品类下拉 | 页顶 **「统计品类」** 下拉切换(默认「全部交易」):全部交易,下单监控,关键位箱体突破,关键位收敛结构,关键位斐波0.618,关键位斐波0.786;一次只显示所选品类的日/周/月 |
|
||||
| URL | 切换后写入 `stats_segment=`(如 `all`,`manual`,`key_box`,`key_conv`,`key_fib618`,`key_fib786`),刷新 `/stats` 可保持选项 |
|
||||
| 每块指标 | 日 / 周 / 月:开单次数,平仓笔数,胜率,净盈亏,回撤,连续亏损等(与原口径一致) |
|
||||
| 开单次数 | 人工块:`monitor_type=下单监控` 且无 `key_signal_type`;关键位块:按 `order_monitors.key_signal_type` 计数 |
|
||||
| 不受 UTC 窗影响 | 统计始终基于库内全部已平仓记录,按北京交易日归类,**不**随顶栏 UTC 列表窗切换 |
|
||||
|
||||
## 持仓与计仓
|
||||
|
||||
- `MAX_ACTIVE_POSITIONS` 默认 **1**(可在 `.env` 调大).
|
||||
- 关键位自动开仓:在已有持仓时,若 `KEY_SIZING_USE_ZERO_POSITION_SNAPSHOT=true`,按**首笔开仓前**交易账户资金快照计仓(`trading_sessions.key_sizing_capital_snapshot`).
|
||||
|
||||
## 配置
|
||||
|
||||
详见 `.env.example` 中「关键位门控」「交易执行 / 人工风控」注释段.Gate 专用项(`GATE_*`,止盈止损触发等)保持原有段落不变.
|
||||
|
||||
## 自动备份(服务器)
|
||||
|
||||
- 脚本:`scripts/backup_data.sh`(`crypto.db` + `static/images`)
|
||||
- 定时:`scripts/install_backup_cron.sh` → 每天 **北京时间 0:00**,目录 **`/root/backups/<实例名>/YYYY-MM-DD/`**,保留 **30** 天
|
||||
- 详见 `部署文档.md` 第 5.4 节(自动备份)
|
||||
|
||||
## 数据库(启动时自动迁移)
|
||||
|
||||
`key_monitors` 新增斐波字段(示例):`fib_limit_order_id`,`fib_entry_price`,`fib_stop_loss`,`fib_take_profit`,`fib_order_amount`,`fib_margin_capital`,`fib_leverage`.
|
||||
|
||||
`trade_records` / `order_monitors` 新增或沿用:`key_signal_type`,`exchange_realized_pnl`,`exchange_opened_at`,`exchange_closed_at`,`exchange_sync_key`,`entry_reason`,`reviewed_entry_reason`,`initial_stop_loss`.
|
||||
|
||||
**历史数据**:本次**不做**旧记录的批量回填(`entry_reason` / `initial_stop_loss` / `key_signal_type` 等);仅**新产生**的平仓与复盘按新逻辑写入.旧行展示可回退已有字段.
|
||||
|
||||
## 涉及文件(便于排查)
|
||||
|
||||
| 路径 | 说明 |
|
||||
|------|------|
|
||||
| `history_window_lib.py` | UTC 时间窗解析与转北京时间 SQL 字符串 |
|
||||
| `fib_key_monitor_lib.py` | 斐波计算,`KEY_ENTRY_REASON_BY_SIGNAL`,`entry_reason_from_key_signal` |
|
||||
| `crypto_monitor_gate/app.py` | 列表筛选,统计分块,导出 v3,复盘 K 线锚点,入库逻辑 |
|
||||
| `crypto_monitor_gate/templates/index.html` | 顶栏时间窗,统计分块 UI,止损(开仓)列,复盘预填 |
|
||||
|
||||
## 升级步骤
|
||||
|
||||
1. `git pull` 后对比 `.env.example`,把新增变量合并进本地 `.env`.
|
||||
2. 在 VPS 上为 Binance / Gate / **各执行一次** `bash scripts/install_backup_cron.sh`(若尚未安装).
|
||||
3. 重启 Gate 实例服务(如 `pm2 restart crypto_gate`);首次启动会自动 `ALTER TABLE` 缺列(斐波,交易所盈亏,`entry_reason` 等).
|
||||
4. 浏览器强刷(Ctrl+F5)避免旧版 `index.html` 缓存.
|
||||
5. 打开任意页确认顶栏出现 **「列表筛选(UTC)」**;`/stats` 可见分品类统计与「北京 8:00 切日」说明.
|
||||
6. 建议在测试币上先添加一条斐波监控,确认:限价已挂出,标记价失效会撤单,成交后出现持仓监控且 TP/SL 已挂上;平仓后交易记录止损(开仓)与开仓类型是否正确.
|
||||
|
||||
@@ -1,305 +1,305 @@
|
||||
# `crypto_monitor_gate` 部署指南:SSH SOCKS + Gate.io + PM2(Ubuntu)
|
||||
|
||||
Ubuntu 环境(Python / Node / PM2、/opt 路径)见 **[docs/ubuntu-server.md](../docs/ubuntu-server.md)**。
|
||||
|
||||
本文面向:**在本机运行本项目**,但 **直连 Gate.io API 不稳定或被重置** 的场景。思路是:
|
||||
|
||||
- 本机用 `ssh -D` 做动态转发,把 **SOCKS5 出口**放到能正常访问 Gate 的机器(常见为一台境外 VPS)
|
||||
- 项目在 `.env` 中设置 **`GATE_SOCKS_PROXY=socks5h://127.0.0.1:1080`**(或你实际端口),`ccxt` 经 SOCKS 访问交易所
|
||||
- **SSH 隧道**:用 `ssh -D` 在本机常驻(可用 **tmux** 或 **autossh** 保持连接),**不要** 把 `ssh` 交给 PM2
|
||||
- 使用 **PM2** 仅托管 **Flask 应用**;仓库根目录 **`ecosystem.config.cjs`** 只定义 `crypto-monitor-gate`
|
||||
|
||||
> 安全提醒:不要把 `.env`、私钥 `.pem`、Gate API Key 提交到 Git;下文只用占位符。
|
||||
|
||||
---
|
||||
|
||||
## 0. 你需要准备的东西
|
||||
|
||||
- 一台 **Ubuntu**(或同类 Linux)运行项目的机器(下文称「本机」)
|
||||
- 一台可 SSH 登录、且 **能正常访问 Gate.io API** 的 VPS(示例:`HostName` 填你的服务器 IP,用户如 `root`)
|
||||
- SSH:**私钥登录**(推荐,便于隧道脚本无人值守)
|
||||
- 本机已安装:`python3`、`python3-venv`、`pip`、`curl`、`ssh`、`git`(可选)、`node` + `npm`(安装 PM2)
|
||||
|
||||
---
|
||||
|
||||
## 1. 获取代码与目录
|
||||
|
||||
将包含 `app.py` 的项目放到固定目录,例如:
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/crypto_monitor
|
||||
cd /opt/crypto_monitor
|
||||
git clone https://git.bz121.com/dekun/crypto_monitor.git
|
||||
cd crypto_monitor/crypto_monitor_gate
|
||||
```
|
||||
|
||||
下文用 **`/opt/crypto_monitor/crypto_monitor_gate`** 仅为示例,请换成你的实际绝对路径。
|
||||
|
||||
拉取代码后,若目录下尚无 `.env`:
|
||||
|
||||
```bash
|
||||
cp -n .env.example .env
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 配置 SSH 私钥与 `~/.ssh/config`
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
# 私钥示例:~/.ssh/vps1.pem
|
||||
chmod 600 ~/.ssh/vps1.pem
|
||||
```
|
||||
|
||||
编辑 `~/.ssh/config`(示例别名 **`gate-vps`**,与你手工启动 `ssh -D ... gate-vps` 一致即可):
|
||||
|
||||
```sshconfig
|
||||
Host gate-vps
|
||||
HostName 你的_VPS_IP
|
||||
User root
|
||||
IdentityFile ~/.ssh/vps1.pem
|
||||
IdentitiesOnly yes
|
||||
ServerAliveInterval 30
|
||||
ServerAliveCountMax 3
|
||||
ExitOnForwardFailure yes
|
||||
BatchMode yes
|
||||
```
|
||||
|
||||
测试:
|
||||
|
||||
```bash
|
||||
ssh gate-vps true
|
||||
```
|
||||
|
||||
> 若尚未完全改为密钥登录,可暂时注释 `BatchMode yes`,调试完成后再打开。
|
||||
|
||||
---
|
||||
|
||||
## 3. 手工验证:SSH SOCKS + Gate API
|
||||
|
||||
### 3.1 本地 SOCKS(示例端口 1080)
|
||||
|
||||
```bash
|
||||
ssh -N -D 127.0.0.1:1080 gate-vps
|
||||
```
|
||||
|
||||
保持运行,另开终端继续。
|
||||
|
||||
### 3.2 验证经 SOCKS 可访问 Gate
|
||||
|
||||
```bash
|
||||
curl -4 -sS --max-time 15 --proxy socks5h://127.0.0.1:1080 https://api.gateio.ws/api/v4/spot/time
|
||||
```
|
||||
|
||||
应返回 JSON(含服务器时间字段)。若此处失败,**不要先启动应用**:先修隧道或 VPS 出站。
|
||||
|
||||
---
|
||||
|
||||
## 4. Python 虚拟环境
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
python -m pip install -U pip
|
||||
pip install flask requests ccxt werkzeug PySocks Pillow
|
||||
```
|
||||
|
||||
走 SOCKS 时 **必须** 安装 **`PySocks`**,否则易出现代理相关报错。
|
||||
|
||||
可选:
|
||||
|
||||
```bash
|
||||
export PYTHONDONTWRITEBYTECODE=1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 配置环境变量(`.env.example` → `.env`)
|
||||
|
||||
| 文件 | 是否进 Git | 说明 |
|
||||
|------|------------|------|
|
||||
| **`.env.example`** | ✅ 是 | 变量模板与注释,可随 `git pull` 更新 |
|
||||
| **`.env`** | ❌ 否 | 本机真实配置;`app.py` **只读此文件** |
|
||||
|
||||
### 5.1 首次配置
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
|
||||
cp -n .env.example .env
|
||||
nano .env
|
||||
```
|
||||
|
||||
### 5.2 备份与 `git pull`
|
||||
|
||||
- **`.env` 不在 Git 中**:`git pull` **不会**覆盖本地 `.env`。
|
||||
- 远端若更新 **`.env.example`**,pull 后请**手动**把新增变量补进你的 `.env`。
|
||||
- **升级前备份**:`cp .env .env.backup.$(date +%Y%m%d)`;恢复:`cp .env.backup.YYYYMMDD .env`。
|
||||
- **换机**:`scp` 复制 `.env`,或新机 `cp .env.example .env` 后重填。
|
||||
|
||||
### 5.3 AI 复盘与模型(可选)
|
||||
|
||||
共用根目录 **`ai_client.py`**(`PYTHONPATH=..`)。`.env` 中 **`AI_PROVIDER=openai`**(默认)时使用 `OPENAI_API_BASE=https://op.bz121.com/v1`、`OPENAI_API_KEY`、`OPENAI_MODEL=gemma4:e4b`;改 **`ollama`** 则用 `OLLAMA_API` + `AI_MODEL`。详见 **[AI复盘与模型配置说明.md](../AI复盘与模型配置说明.md)**。
|
||||
|
||||
### 5.4 自动备份(数据库 + 复盘图片)
|
||||
|
||||
与 Binance 实例相同:每天 **北京时间 0:00** → **`/root/backups`**,保留 **30 天**。
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
chmod +x scripts/backup_data.sh scripts/install_backup_cron.sh
|
||||
bash scripts/install_backup_cron.sh
|
||||
bash scripts/backup_data.sh # 试跑
|
||||
```
|
||||
|
||||
备份目录:`/root/backups/crypto_monitor_gate/YYYY-MM-DD/`。详见 Binance 项目 `部署文档.md` 第 5.4 节(恢复步骤、可选 `.env` 变量相同)。
|
||||
|
||||
若还部署了 **`crypto_monitor_gate_bot`**,请在该目录同样执行 `bash scripts/install_backup_cron.sh`。
|
||||
|
||||
### 5.5 必填项检查(Gate + 代理)
|
||||
|
||||
与交易所相关的变量必须是 **Gate** 前缀(**不要**再写 OKX 变量,否则代理不会生效、密钥也不会被识别)。至少确认:
|
||||
|
||||
```env
|
||||
APP_HOST=127.0.0.1
|
||||
APP_PORT=5000
|
||||
|
||||
# 实盘(按需)
|
||||
LIVE_TRADING_ENABLED=false
|
||||
GATE_API_KEY=你的_Key
|
||||
GATE_API_SECRET=你的_Secret
|
||||
|
||||
# 经本机 SSH 动态转发访问 Gate(端口与隧道一致)
|
||||
GATE_SOCKS_PROXY=socks5h://127.0.0.1:1080
|
||||
|
||||
# 若不用 SOCKS,可改用 HTTP 代理(一般二选一)
|
||||
# GATE_HTTP_PROXY=http://127.0.0.1:7890
|
||||
# GATE_HTTPS_PROXY=http://127.0.0.1:7890
|
||||
```
|
||||
|
||||
说明:**推荐 `socks5h://`**,由 SOCKS 端解析域名,与 `curl --proxy socks5h://...` 行为一致。
|
||||
|
||||
---
|
||||
|
||||
## 6. 手工启动 Flask(验证)
|
||||
|
||||
1. SOCKS 已监听 `127.0.0.1:1080`
|
||||
2. 已 `source .venv/bin/activate`
|
||||
3. `.env` 已含 `GATE_SOCKS_PROXY`
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
source .venv/bin/activate
|
||||
python app.py
|
||||
```
|
||||
|
||||
浏览器访问:`http://127.0.0.1:5000`(或你在 `.env` 中的端口)。
|
||||
|
||||
---
|
||||
|
||||
## 7. 安装 PM2
|
||||
|
||||
```bash
|
||||
sudo npm i -g pm2
|
||||
pm2 -v
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. PM2:使用仓库内 `ecosystem.config.cjs`(推荐)
|
||||
|
||||
在项目根目录:
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
pm2 start ecosystem.config.cjs
|
||||
pm2 status
|
||||
pm2 logs --lines 200
|
||||
```
|
||||
|
||||
默认只启动 **`crypto-monitor-gate`**(`.venv/bin/python app.py`)。
|
||||
|
||||
### 本机已可直连 Gate、不需要隧道时
|
||||
|
||||
`.env` 里应 **去掉或留空** `GATE_SOCKS_PROXY`(除非仍要走别的代理),再 `pm2 start ecosystem.config.cjs`。
|
||||
|
||||
### 开机自启
|
||||
|
||||
```bash
|
||||
pm2 save
|
||||
pm2 startup
|
||||
# 按屏幕提示执行一条 sudo 命令
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 等价手工命令(不使用 ecosystem 文件时)
|
||||
|
||||
### 9.1 SSH SOCKS(自行后台常驻,不推荐用 PM2)
|
||||
|
||||
示例(前台调试;生产请用 **PM2**,见本文与 [docs/ubuntu-server.md](../docs/ubuntu-server.md)):
|
||||
|
||||
```bash
|
||||
ssh -N -D 127.0.0.1:1080 gate-vps \
|
||||
-o ServerAliveInterval=30 -o ServerAliveCountMax=3 \
|
||||
-o ExitOnForwardFailure=yes
|
||||
```
|
||||
|
||||
### 9.2 Flask
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
pm2 start /opt/crypto_monitor/crypto_monitor_gate/.venv/bin/python --name crypto-monitor-gate -- \
|
||||
/opt/crypto_monitor/crypto_monitor_gate/app.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 交易所「连接不上」排查清单
|
||||
|
||||
1. **`.env` 是否为 Gate 变量**:必须是 `GATE_SOCKS_PROXY` / `GATE_API_KEY` / `GATE_API_SECRET`,不是 OKX。
|
||||
2. **隧道是否在本机端口监听**(若配置了 `GATE_SOCKS_PROXY`):
|
||||
```bash
|
||||
ss -lntp | grep 1080 || true
|
||||
```
|
||||
3. **curl 复测 Gate**(与第 3.2 节相同);curl 不通则应用也不会通。
|
||||
4. **PySocks**:`pip show PySocks`,缺失则 `pip install PySocks`。
|
||||
5. **SSH 隧道连不上**:检查私钥权限、`~/.ssh/config`、VPS 出站与端口是否与 `.env` 一致。
|
||||
6. **启动顺序**:先保证 SOCKS 已监听,再 `pm2 start` 应用(或重启应用)。
|
||||
|
||||
---
|
||||
|
||||
## 11. 推荐启动顺序(习惯)
|
||||
|
||||
1. 若走代理:先启动并确认 SSH SOCKS 已监听,再 `curl --proxy socks5h://127.0.0.1:1080 https://api.gateio.ws/api/v4/spot/time` 成功
|
||||
2. `pm2 start ecosystem.config.cjs`
|
||||
3. 再确认页面与余额等接口正常
|
||||
|
||||
---
|
||||
|
||||
## 12. 免责声明
|
||||
|
||||
交易所有合规与地区政策要求。请确保使用方式符合当地法律法规与交易所条款。本文仅描述网络与工程部署路径。
|
||||
|
||||
---
|
||||
|
||||
## 附录:数据库标签修复脚本 `scripts/fix_breakeven_labels.py`
|
||||
|
||||
在 Ubuntu 上:
|
||||
|
||||
1)预览(不写库):
|
||||
|
||||
```bash
|
||||
python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run
|
||||
```
|
||||
|
||||
2)确认后执行:
|
||||
|
||||
```bash
|
||||
python scripts/fix_breakeven_labels.py --db ./crypto.db --apply
|
||||
```
|
||||
|
||||
默认修复条件:`monitor_type='下单监控'` 且 `result='止损'` 且 `pnl_amount > 0` → 改为 `result='保本止盈'`。
|
||||
# `crypto_monitor_gate` 部署指南:SSH SOCKS + Gate.io + PM2(Ubuntu)
|
||||
|
||||
Ubuntu 环境(Python / Node / PM2,/opt 路径)见 **[docs/ubuntu-server.md](../docs/ubuntu-server.md)**.
|
||||
|
||||
本文面向:**在本机运行本项目**,但 **直连 Gate.io API 不稳定或被重置** 的场景.思路是:
|
||||
|
||||
- 本机用 `ssh -D` 做动态转发,把 **SOCKS5 出口**放到能正常访问 Gate 的机器(常见为一台境外 VPS)
|
||||
- 项目在 `.env` 中设置 **`GATE_SOCKS_PROXY=socks5h://127.0.0.1:1080`**(或你实际端口),`ccxt` 经 SOCKS 访问交易所
|
||||
- **SSH 隧道**:用 `ssh -D` 在本机常驻(可用 **tmux** 或 **autossh** 保持连接),**不要** 把 `ssh` 交给 PM2
|
||||
- 使用 **PM2** 仅托管 **Flask 应用**;仓库根目录 **`ecosystem.config.cjs`** 只定义 `crypto-monitor-gate`
|
||||
|
||||
> 安全提醒:不要把 `.env`,私钥 `.pem`,Gate API Key 提交到 Git;下文只用占位符.
|
||||
|
||||
---
|
||||
|
||||
## 0. 你需要准备的东西
|
||||
|
||||
- 一台 **Ubuntu**(或同类 Linux)运行项目的机器(下文称「本机」)
|
||||
- 一台可 SSH 登录,且 **能正常访问 Gate.io API** 的 VPS(示例:`HostName` 填你的服务器 IP,用户如 `root`)
|
||||
- SSH:**私钥登录**(推荐,便于隧道脚本无人值守)
|
||||
- 本机已安装:`python3`,`python3-venv`,`pip`,`curl`,`ssh`,`git`(可选),`node` + `npm`(安装 PM2)
|
||||
|
||||
---
|
||||
|
||||
## 1. 获取代码与目录
|
||||
|
||||
将包含 `app.py` 的项目放到固定目录,例如:
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/crypto_monitor
|
||||
cd /opt/crypto_monitor
|
||||
git clone https://git.bz121.com/dekun/crypto_monitor.git
|
||||
cd crypto_monitor/crypto_monitor_gate
|
||||
```
|
||||
|
||||
下文用 **`/opt/crypto_monitor/crypto_monitor_gate`** 仅为示例,请换成你的实际绝对路径.
|
||||
|
||||
拉取代码后,若目录下尚无 `.env`:
|
||||
|
||||
```bash
|
||||
cp -n .env.example .env
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 配置 SSH 私钥与 `~/.ssh/config`
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
# 私钥示例:~/.ssh/vps1.pem
|
||||
chmod 600 ~/.ssh/vps1.pem
|
||||
```
|
||||
|
||||
编辑 `~/.ssh/config`(示例别名 **`gate-vps`**,与你手工启动 `ssh -D ... gate-vps` 一致即可):
|
||||
|
||||
```sshconfig
|
||||
Host gate-vps
|
||||
HostName 你的_VPS_IP
|
||||
User root
|
||||
IdentityFile ~/.ssh/vps1.pem
|
||||
IdentitiesOnly yes
|
||||
ServerAliveInterval 30
|
||||
ServerAliveCountMax 3
|
||||
ExitOnForwardFailure yes
|
||||
BatchMode yes
|
||||
```
|
||||
|
||||
测试:
|
||||
|
||||
```bash
|
||||
ssh gate-vps true
|
||||
```
|
||||
|
||||
> 若尚未完全改为密钥登录,可暂时注释 `BatchMode yes`,调试完成后再打开.
|
||||
|
||||
---
|
||||
|
||||
## 3. 手工验证:SSH SOCKS + Gate API
|
||||
|
||||
### 3.1 本地 SOCKS(示例端口 1080)
|
||||
|
||||
```bash
|
||||
ssh -N -D 127.0.0.1:1080 gate-vps
|
||||
```
|
||||
|
||||
保持运行,另开终端继续.
|
||||
|
||||
### 3.2 验证经 SOCKS 可访问 Gate
|
||||
|
||||
```bash
|
||||
curl -4 -sS --max-time 15 --proxy socks5h://127.0.0.1:1080 https://api.gateio.ws/api/v4/spot/time
|
||||
```
|
||||
|
||||
应返回 JSON(含服务器时间字段).若此处失败,**不要先启动应用**:先修隧道或 VPS 出站.
|
||||
|
||||
---
|
||||
|
||||
## 4. Python 虚拟环境
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
python -m pip install -U pip
|
||||
pip install flask requests ccxt werkzeug PySocks Pillow
|
||||
```
|
||||
|
||||
走 SOCKS 时 **必须** 安装 **`PySocks`**,否则易出现代理相关报错.
|
||||
|
||||
可选:
|
||||
|
||||
```bash
|
||||
export PYTHONDONTWRITEBYTECODE=1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 配置环境变量(`.env.example` → `.env`)
|
||||
|
||||
| 文件 | 是否进 Git | 说明 |
|
||||
|------|------------|------|
|
||||
| **`.env.example`** | ✅ 是 | 变量模板与注释,可随 `git pull` 更新 |
|
||||
| **`.env`** | ❌ 否 | 本机真实配置;`app.py` **只读此文件** |
|
||||
|
||||
### 5.1 首次配置
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
|
||||
cp -n .env.example .env
|
||||
nano .env
|
||||
```
|
||||
|
||||
### 5.2 备份与 `git pull`
|
||||
|
||||
- **`.env` 不在 Git 中**:`git pull` **不会**覆盖本地 `.env`.
|
||||
- 远端若更新 **`.env.example`**,pull 后请**手动**把新增变量补进你的 `.env`.
|
||||
- **升级前备份**:`cp .env .env.backup.$(date +%Y%m%d)`;恢复:`cp .env.backup.YYYYMMDD .env`.
|
||||
- **换机**:`scp` 复制 `.env`,或新机 `cp .env.example .env` 后重填.
|
||||
|
||||
### 5.3 AI 复盘与模型(可选)
|
||||
|
||||
共用根目录 **`ai_client.py`**(`PYTHONPATH=..`).`.env` 中 **`AI_PROVIDER=openai`**(默认)时使用 `OPENAI_API_BASE=https://op.bz121.com/v1`,`OPENAI_API_KEY`,`OPENAI_MODEL=gemma4:e4b`;改 **`ollama`** 则用 `OLLAMA_API` + `AI_MODEL`.详见 **[AI复盘与模型配置说明.md](../AI复盘与模型配置说明.md)**.
|
||||
|
||||
### 5.4 自动备份(数据库 + 复盘图片)
|
||||
|
||||
与 Binance 实例相同:每天 **北京时间 0:00** → **`/root/backups`**,保留 **30 天**.
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
chmod +x scripts/backup_data.sh scripts/install_backup_cron.sh
|
||||
bash scripts/install_backup_cron.sh
|
||||
bash scripts/backup_data.sh # 试跑
|
||||
```
|
||||
|
||||
备份目录:`/root/backups/crypto_monitor_gate/YYYY-MM-DD/`.详见 Binance 项目 `部署文档.md` 第 5.4 节(恢复步骤,可选 `.env` 变量相同).
|
||||
|
||||
若还部署了 **`crypto_monitor_okx`**,请在该目录同样执行 `bash scripts/install_backup_cron.sh`.
|
||||
|
||||
### 5.5 必填项检查(Gate + 代理)
|
||||
|
||||
与交易所相关的变量必须是 **Gate** 前缀(**不要**再写 OKX 变量,否则代理不会生效,密钥也不会被识别).至少确认:
|
||||
|
||||
```env
|
||||
APP_HOST=127.0.0.1
|
||||
APP_PORT=5000
|
||||
|
||||
# 实盘(按需)
|
||||
LIVE_TRADING_ENABLED=false
|
||||
GATE_API_KEY=你的_Key
|
||||
GATE_API_SECRET=你的_Secret
|
||||
|
||||
# 经本机 SSH 动态转发访问 Gate(端口与隧道一致)
|
||||
GATE_SOCKS_PROXY=socks5h://127.0.0.1:1080
|
||||
|
||||
# 若不用 SOCKS,可改用 HTTP 代理(一般二选一)
|
||||
# GATE_HTTP_PROXY=http://127.0.0.1:7890
|
||||
# GATE_HTTPS_PROXY=http://127.0.0.1:7890
|
||||
```
|
||||
|
||||
说明:**推荐 `socks5h://`**,由 SOCKS 端解析域名,与 `curl --proxy socks5h://...` 行为一致.
|
||||
|
||||
---
|
||||
|
||||
## 6. 手工启动 Flask(验证)
|
||||
|
||||
1. SOCKS 已监听 `127.0.0.1:1080`
|
||||
2. 已 `source .venv/bin/activate`
|
||||
3. `.env` 已含 `GATE_SOCKS_PROXY`
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
source .venv/bin/activate
|
||||
python app.py
|
||||
```
|
||||
|
||||
浏览器访问:`http://127.0.0.1:5000`(或你在 `.env` 中的端口).
|
||||
|
||||
---
|
||||
|
||||
## 7. 安装 PM2
|
||||
|
||||
```bash
|
||||
sudo npm i -g pm2
|
||||
pm2 -v
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. PM2:使用仓库内 `ecosystem.config.cjs`(推荐)
|
||||
|
||||
在项目根目录:
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
pm2 start ecosystem.config.cjs
|
||||
pm2 status
|
||||
pm2 logs --lines 200
|
||||
```
|
||||
|
||||
默认只启动 **`crypto-monitor-gate`**(`.venv/bin/python app.py`).
|
||||
|
||||
### 本机已可直连 Gate,不需要隧道时
|
||||
|
||||
`.env` 里应 **去掉或留空** `GATE_SOCKS_PROXY`(除非仍要走别的代理),再 `pm2 start ecosystem.config.cjs`.
|
||||
|
||||
### 开机自启
|
||||
|
||||
```bash
|
||||
pm2 save
|
||||
pm2 startup
|
||||
# 按屏幕提示执行一条 sudo 命令
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 等价手工命令(不使用 ecosystem 文件时)
|
||||
|
||||
### 9.1 SSH SOCKS(自行后台常驻,不推荐用 PM2)
|
||||
|
||||
示例(前台调试;生产请用 **PM2**,见本文与 [docs/ubuntu-server.md](../docs/ubuntu-server.md)):
|
||||
|
||||
```bash
|
||||
ssh -N -D 127.0.0.1:1080 gate-vps \
|
||||
-o ServerAliveInterval=30 -o ServerAliveCountMax=3 \
|
||||
-o ExitOnForwardFailure=yes
|
||||
```
|
||||
|
||||
### 9.2 Flask
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
pm2 start /opt/crypto_monitor/crypto_monitor_gate/.venv/bin/python --name crypto-monitor-gate -- \
|
||||
/opt/crypto_monitor/crypto_monitor_gate/app.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 交易所「连接不上」排查清单
|
||||
|
||||
1. **`.env` 是否为 Gate 变量**:必须是 `GATE_SOCKS_PROXY` / `GATE_API_KEY` / `GATE_API_SECRET`,不是 OKX.
|
||||
2. **隧道是否在本机端口监听**(若配置了 `GATE_SOCKS_PROXY`):
|
||||
```bash
|
||||
ss -lntp | grep 1080 || true
|
||||
```
|
||||
3. **curl 复测 Gate**(与第 3.2 节相同);curl 不通则应用也不会通.
|
||||
4. **PySocks**:`pip show PySocks`,缺失则 `pip install PySocks`.
|
||||
5. **SSH 隧道连不上**:检查私钥权限,`~/.ssh/config`,VPS 出站与端口是否与 `.env` 一致.
|
||||
6. **启动顺序**:先保证 SOCKS 已监听,再 `pm2 start` 应用(或重启应用).
|
||||
|
||||
---
|
||||
|
||||
## 11. 推荐启动顺序(习惯)
|
||||
|
||||
1. 若走代理:先启动并确认 SSH SOCKS 已监听,再 `curl --proxy socks5h://127.0.0.1:1080 https://api.gateio.ws/api/v4/spot/time` 成功
|
||||
2. `pm2 start ecosystem.config.cjs`
|
||||
3. 再确认页面与余额等接口正常
|
||||
|
||||
---
|
||||
|
||||
## 12. 免责声明
|
||||
|
||||
交易所有合规与地区政策要求.请确保使用方式符合当地法律法规与交易所条款.本文仅描述网络与工程部署路径.
|
||||
|
||||
---
|
||||
|
||||
## 附录:数据库标签修复脚本 `scripts/fix_breakeven_labels.py`
|
||||
|
||||
在 Ubuntu 上:
|
||||
|
||||
1)预览(不写库):
|
||||
|
||||
```bash
|
||||
python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run
|
||||
```
|
||||
|
||||
2)确认后执行:
|
||||
|
||||
```bash
|
||||
python scripts/fix_breakeven_labels.py --db ./crypto.db --apply
|
||||
```
|
||||
|
||||
默认修复条件:`monitor_type='下单监控'` 且 `result='止损'` 且 `pnl_amount > 0` → 改为 `result='保本止盈'`.
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
# =============================================================================
|
||||
# 环境配置模板(可提交 Git)。程序运行时只读取同目录下的 .env。
|
||||
#
|
||||
# 首次部署 / 新机:
|
||||
# cp .env.example .env
|
||||
# nano .env # 填入真实密钥、端口、代理等
|
||||
#
|
||||
# 升级代码(git pull)前建议备份(.env 不在 Git 中,pull 不会覆盖):
|
||||
# cp .env .env.backup.$(date +%Y%m%d)
|
||||
#
|
||||
# 从备份恢复:
|
||||
# cp .env.backup.YYYYMMDD .env
|
||||
# =============================================================================
|
||||
|
||||
APP_ENV=production
|
||||
# 服务监听地址(云服务器通常用 0.0.0.0)
|
||||
APP_HOST=0.0.0.0
|
||||
# 服务端口
|
||||
APP_PORT=5002
|
||||
# 是否开启调试模式(生产建议 false)
|
||||
APP_DEBUG=false
|
||||
|
||||
# 登录账号
|
||||
APP_USERNAME=admin
|
||||
# 登录密码(请改成你自己的强密码)
|
||||
APP_PASSWORD=admin123
|
||||
# 是否关闭登录校验(局域网可设 true;公网务必 false)
|
||||
APP_AUTH_DISABLED=true
|
||||
# --- 多账户交易中控 manual_trading_hub ---
|
||||
# 中控请求本实例 /api/hub/* 时携带请求头 X-Hub-Token,须与中控启动环境变量 HUB_BRIDGE_TOKEN 一致
|
||||
# 未设置且 APP_AUTH_DISABLED=false 时,仅网页登录后可访问;本机联调可保持 APP_AUTH_DISABLED=true
|
||||
# HUB_BRIDGE_TOKEN=your-long-random-token
|
||||
# Flask 会话密钥(必须替换为长随机字符串)
|
||||
FLASK_SECRET_KEY=CHANGE_TO_LONG_RANDOM_SECRET
|
||||
|
||||
# 企业微信机器人 Webhook(用于行情/风控推送)
|
||||
WECHAT_WEBHOOK=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=REPLACE_WITH_REAL_KEY
|
||||
|
||||
# 数据库文件路径(相对路径会自动按项目目录解析)
|
||||
DB_PATH=crypto.db
|
||||
# 交易截图上传目录
|
||||
UPLOAD_DIR=static/images
|
||||
|
||||
# 自动备份(scripts/backup_data.sh + cron,可选;默认即可)
|
||||
# BACKUP_ROOT=/root/backups
|
||||
# BACKUP_RETENTION_DAYS=30
|
||||
# BACKUP_INSTANCE=crypto_monitor_gate_bot
|
||||
|
||||
# 已废弃:资金账户仅显示交易所 funding 余额,不再读取此变量
|
||||
# TOTAL_CAPITAL=100
|
||||
# 计仓:risk=以损定仓(默认);full_margin=合约可用×FULL_MARGIN_BUFFER_RATIO 全仓杠杆(须无仓后重启)
|
||||
POSITION_SIZING_MODE=risk
|
||||
# 每天起始基数(U)
|
||||
DAILY_START_CAPITAL=30
|
||||
# 日内回撤后基数(U)
|
||||
DAILY_LOSS_CAPITAL=20
|
||||
# 日内盈利后基数(U)
|
||||
DAILY_PROFIT_CAPITAL=50
|
||||
# BTC 默认杠杆倍数
|
||||
BTC_LEVERAGE=10
|
||||
# 山寨币默认杠杆倍数
|
||||
ALT_LEVERAGE=5
|
||||
# 交易日重置小时(北京时间)
|
||||
TRADING_DAY_RESET_HOUR=8
|
||||
# 整点前禁止新开仓:true=启用(默认),false=关闭(仍可保留 8 点作为交易日划分)
|
||||
TRADING_DAY_RESET_OPEN_GUARD_ENABLED=true
|
||||
|
||||
# 是否开启 Gate 实盘下单(false=只做本地流程,true=真实下单)
|
||||
LIVE_TRADING_ENABLED=true
|
||||
# Gate API Key(实盘)
|
||||
GATE_API_KEY=REPLACE_WITH_GATE_API_KEY
|
||||
# Gate API Secret(实盘)
|
||||
GATE_API_SECRET=REPLACE_WITH_GATE_API_SECRET
|
||||
# 保证金模式:cross=全仓,isolated=逐仓
|
||||
GATE_TD_MODE=cross
|
||||
# 持仓筛选:hedge=双向持仓下按多空腿过滤;其它值(如 single)不按腿过滤
|
||||
GATE_POS_MODE=hedge
|
||||
# 永续止盈止损:是否优先用官方仓位类触发单(POST price_orders,close-*-position);false=仅用旧版两张 ccxt 条件单
|
||||
GATE_TPSL_USE_POSITION_ORDER=true
|
||||
# 触发单超时(秒),默认 604800=7 天;设为 0 或负数则不向 API 传 expiration
|
||||
GATE_TPSL_TRIGGER_EXPIRATION=604800
|
||||
# 触发参考价:0=最新成交 1=标记价 2=指数价(非法值按 0)
|
||||
GATE_TPSL_PRICE_TYPE=0
|
||||
# 仓位类 TP/SL 相对现价的最小间距(%),避免 Gate 1026「触发价须高于/低于现价」
|
||||
GATE_TPSL_LAST_PRICE_GAP_PCT=0.05
|
||||
# 页面与浏览器标签展示的交易所名称(多环境区分时可改成例如 Gate·模拟)
|
||||
# EXCHANGE_DISPLAY_NAME=Gate.io
|
||||
|
||||
# =============================================================================
|
||||
# 关键位门控(页面「关键位监控」规则条与 _key_hard_checks 共用)
|
||||
# =============================================================================
|
||||
# 【周期】门控 K 线周期,如 5m、15m
|
||||
KLINE_TIMEFRAME=5m
|
||||
# 【确认K】闭合 K 序列中的棒偏移:突破棒默认 -2,确认棒默认 -1
|
||||
KEY_CONFIRM_BREAKOUT_BAR=-2
|
||||
KEY_CONFIRM_BAR=-1
|
||||
# 【量能】突破棒成交量 > 前 N 根均量 × 倍数
|
||||
KEY_VOLUME_MA_BARS=20
|
||||
KEY_VOLUME_RATIO_MIN=1.3
|
||||
# 【突破K实体幅度】占开盘价百分比区间
|
||||
# 【箱体/收敛】突破K收盘越过关键位下限%;无上限(过猛由计划RR过滤)
|
||||
KEY_BREAKOUT_AMP_MIN_PCT=0.03
|
||||
KEY_BREAKOUT_AMP_MAX_PCT=0.5
|
||||
# 【阻力/支撑】突破后微信提醒
|
||||
KEY_ALERT_MAX_TIMES=3
|
||||
KEY_ALERT_INTERVAL_MINUTES=5
|
||||
# 【日成交量排名】品种须在该排名前 N 名
|
||||
KEY_DAILY_VOLUME_RANK_MAX=30
|
||||
# 【关键位自动开仓盈亏比】严格大于该值才市价开仓
|
||||
KEY_AUTO_MIN_PLANNED_RR=1.5
|
||||
# 止损:突破 K 极值向外缓冲的百分比(默认 0.5 即 0.5%)
|
||||
KEY_STOP_OUTSIDE_BREAKOUT_PCT=0.5
|
||||
# 趋势单方案:止损在突破 K 极值外侧的百分比(默认 1 即 1%)
|
||||
KEY_TREND_STOP_OUTSIDE_PCT=1
|
||||
KEY_ALERT_MAX_TIMES=3
|
||||
KEY_ALERT_INTERVAL_MINUTES=5
|
||||
|
||||
# =============================================================================
|
||||
# 交易执行 / 人工风控(页面「实盘下单」)
|
||||
# =============================================================================
|
||||
# 【最大同时持仓】默认 1=单仓
|
||||
MAX_ACTIVE_POSITIONS=1
|
||||
# 【人工下单最低盈亏比】低于该值前后端均拒绝(默认 1.4,即须 >=1.4:1)
|
||||
MANUAL_MIN_PLANNED_RR=1.4
|
||||
# 【关键位连开计仓】已有持仓时按无仓时资金快照算基数
|
||||
KEY_SIZING_USE_ZERO_POSITION_SNAPSHOT=true
|
||||
# 【单日开仓 AI 提醒】本交易日开仓达到该次数时推送企业微信 AI 克制提醒(不拦单)
|
||||
DAILY_OPEN_ALERT_THRESHOLD=5
|
||||
# 【单日开仓硬上限】本交易日开仓次数>=该值后禁止一切新开仓直至下一交易日(北京时间 TRADING_DAY_RESET_HOUR 切日);0=不启用
|
||||
DAILY_OPEN_HARD_LIMIT=0
|
||||
|
||||
# =============================================================================
|
||||
# 账户冷静期 / 日冻结风控(手动平仓、外部平仓、复盘情绪标签)
|
||||
# 详见 docs/account-risk-cooldown.md
|
||||
# =============================================================================
|
||||
# RISK_CONTROL_ENABLED=true
|
||||
# RISK_COOLING_HOURS_MANUAL=4
|
||||
# RISK_COOLING_HOURS_MANUAL_JOURNAL=1
|
||||
# RISK_MANUAL_CLOSE_DAILY_LIMIT=2
|
||||
# RISK_MOOD_ISSUES_DAILY_FREEZE=true
|
||||
|
||||
# 资金与仓位刷新周期(秒)
|
||||
BALANCE_REFRESH_SECONDS=60
|
||||
# 前端价格快照轮询(秒)
|
||||
PRICE_REFRESH_SECONDS=5
|
||||
# 后台监控轮询周期(秒)
|
||||
MONITOR_POLL_SECONDS=3
|
||||
# 重启后多少秒内不做「外部平仓」同步(避免 API 未就绪误判)
|
||||
RECONCILE_STARTUP_GRACE_SEC=90
|
||||
# 连续多少次轮询确认交易所空仓后,才记为外部平仓(默认 3 次 ≈ 9 秒)
|
||||
RECONCILE_FLAT_CONFIRM_POLLS=3
|
||||
# 使用可用资金时的缓冲比例(如0.98代表用98%)
|
||||
FULL_MARGIN_BUFFER_RATIO=0.98
|
||||
|
||||
# =============================================================================
|
||||
# 自动划转(页顶「将 swap 补足到 XU」;与 DAILY_START_CAPITAL 独立,需一致时请设为相同值)
|
||||
# =============================================================================
|
||||
AUTO_TRANSFER_ENABLED=false
|
||||
# 交易账户(swap)目标余额 U:每日 8 点(北京)自动划入或划出至 funding;持仓中不划转
|
||||
AUTO_TRANSFER_AMOUNT=30
|
||||
AUTO_TRANSFER_FROM=funding
|
||||
AUTO_TRANSFER_TO=swap
|
||||
TRANSFER_CCY=USDT
|
||||
# 北京时间该整点小时内尝试;账簿按 UTC 自然日去重
|
||||
AUTO_TRANSFER_BJ_HOUR=8
|
||||
# 强制清仓整点(北京时间,默认 0=凌晨00点)
|
||||
FORCE_CLOSE_BJ_HOUR=0
|
||||
# 是否启用强制清仓(默认关闭,true 才会在整点执行)
|
||||
FORCE_CLOSE_ENABLED=false
|
||||
|
||||
# 推送与AI超时(秒)
|
||||
WECHAT_TIMEOUT_SECONDS=10
|
||||
AI_TIMEOUT_SECONDS=120
|
||||
|
||||
# AI 提供方:openai(默认)| ollama
|
||||
AI_PROVIDER=openai
|
||||
OPENAI_API_BASE=https://op.bz121.com/v1
|
||||
OPENAI_API_KEY=你的密钥
|
||||
OPENAI_MODEL=gemma4:e4b
|
||||
OLLAMA_API=http://127.0.0.1:11434/api/generate
|
||||
AI_MODEL=huihui_ai/deepseek-r1-abliterated:latest
|
||||
|
||||
# Gate 代理(可选):本机网络不稳定时通过 SSH 动态转发 SOCKS5 出口
|
||||
# 1) 先在本机建立隧道(示例):
|
||||
# ssh -N -D 127.0.0.1:1080 root@你的VPS_IP -o ServerAliveInterval=30 -o ExitOnForwardFailure=yes
|
||||
# 2) 再启用下面这一行(推荐 socks5h,让远端解析域名):
|
||||
# GATE_SOCKS_PROXY=socks5h://127.0.0.1:1080
|
||||
#
|
||||
# 如你更偏向 HTTP 代理(VPS 上跑 tinyproxy 之类),可用:
|
||||
# GATE_HTTP_PROXY=http://127.0.0.1:3128
|
||||
# GATE_HTTPS_PROXY=http://127.0.0.1:3128
|
||||
|
||||
# 开仓多周期K线图(可选)
|
||||
# ORDER_CHART_ENABLED=true
|
||||
# ORDER_CHART_TFS=4h,1h,15m,5m
|
||||
# ORDER_CHART_LIMIT=100
|
||||
# ORDER_CHART_DIR=static/images/order_charts
|
||||
# 详见 DAILY_OPEN_ALERT_THRESHOLD / DAILY_OPEN_HARD_LIMIT;说明文档 docs/daily-open-limit.md
|
||||
# 以损定仓(按交易账户资金的百分比)
|
||||
# RISK_PERCENT=2
|
||||
# 移动保本触发(达到多少R触发)与偏移(百分比)
|
||||
# BREAKEVEN_RR_TRIGGER=1.0
|
||||
# 移动保本阶梯(每多少R继续上移一次,默认1R)
|
||||
# BREAKEVEN_STEP_R=1.0
|
||||
# BREAKEVEN_OFFSET_PCT=0.02
|
||||
# 开单风格默认值:trend / swing
|
||||
# DEFAULT_TRADE_STYLE=trend
|
||||
|
||||
APP_TIMEZONE=Asia/Shanghai
|
||||
# TRADING_DAY_RESET_HOUR 现在表示「北京时间」整点,默认 8 点起算新交易日;开仓整点限制见 TRADING_DAY_RESET_OPEN_GUARD_ENABLED
|
||||
@@ -1,90 +0,0 @@
|
||||
# crypto_monitor_gate
|
||||
|
||||
基于 **Flask** 的加密货币 **下单监控 / 关键位监控 / 交易复盘** 小系统,行情与实盘接口统一走 **Gate.io USDT 永续**,通过 **ccxt** 访问。
|
||||
|
||||
## 文档导航
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| **[使用说明.md](./使用说明.md)** | 日常怎么用:登录、关键位四类、手工开仓、单仓与微信等 |
|
||||
| **[关键位自动下单说明.md](./关键位自动下单说明.md)** | 关键位自动开仓的 RR、止盈止损、结案原因与 `.env` |
|
||||
| **[部署文档.md](./部署文档.md)** | Ubuntu、PM2、**SSH SOCKS** 访问 Gate API 等 |
|
||||
|
||||
另:**Binance U 本位** 对等实现见同级的 **`crypto_monitor_binance`** 仓库。
|
||||
|
||||
---
|
||||
|
||||
## 功能概要
|
||||
|
||||
- **关键位监控**:5m 收线硬条件、企业微信推送;**箱体 / 收敛** 在 RR 达标时可 **自动市价开仓**(见专门文档);**阻力 / 支撑** 仅单次提醒结案
|
||||
- **下单监控**:本地风控(含移动保本)、止盈/止损触达后轮询尝试平仓并记账
|
||||
- **实盘(可选)**:`LIVE_TRADING_ENABLED=true` 且配置 **`GATE_API_KEY` / `GATE_API_SECRET`** 时,支持开仓、挂单 TP/SL、余额与划转(权限依账户而定)
|
||||
- **止盈止损(Gate)**:市价成交后经 **`_gate_place_tp_sl_orders`** 挂单;优先 **仓位类 `price_orders`**(受 `GATE_TPSL_USE_POSITION_ORDER`、`GATE_TPSL_PRICE_TYPE`、`GATE_POS_MODE` 等影响)
|
||||
|
||||
---
|
||||
|
||||
## 环境要求
|
||||
|
||||
- Python 3.10+(建议)
|
||||
- 依赖:`flask`、`requests`、`ccxt`、`werkzeug`、`PySocks`(经 SOCKS 代理时);`Pillow`(K 线导出等可选用)
|
||||
|
||||
安装示例:
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate
|
||||
source .venv/bin/activate
|
||||
pip install -r ../requirements.txt
|
||||
```
|
||||
|
||||
## 配置(`.env.example` → `.env`)
|
||||
|
||||
- **`.env.example`**:模板(可提交 Git);首次:`cp .env.example .env` 后编辑。
|
||||
- **`.env`**:本机真实配置(勿提交);`git pull` 不覆盖;升级前建议备份(见《部署文档》§5.2)。
|
||||
|
||||
项目启动时加载**仓库根目录**下的 `.env`。常用项:
|
||||
|
||||
| 变量 | 说明 |
|
||||
|------|------|
|
||||
| `GATE_API_KEY` / `GATE_API_SECRET` | Gate API(需合约与对应权限) |
|
||||
| `LIVE_TRADING_ENABLED` | `true` 允许真实下单;`false` 仅本地与推送逻辑 |
|
||||
| `GATE_MARGIN_MODE` / `GATE_POS_MODE` | 保证金与持仓模式 |
|
||||
| `GATE_TPSL_USE_POSITION_ORDER` / `GATE_TPSL_PRICE_TYPE` 等 | 条件止盈止损行为 |
|
||||
| `GATE_SOCKS_PROXY` | 可选;直连不稳时 SSH 动态转发(详见部署文档) |
|
||||
| `APP_PASSWORD` / `FLASK_SECRET_KEY` | Web 登录与 Session |
|
||||
| `WECHAT_WEBHOOK` | 企业微信机器人 |
|
||||
| `EXCHANGE_DISPLAY_NAME` / `GATE_ACCOUNT_LABEL` | 页面与推送展示的账户文案 |
|
||||
|
||||
其余见 **`.env.example` 内注释** 或 **`app.py` 顶部默认值**。
|
||||
|
||||
## 运行
|
||||
|
||||
生产使用 **PM2**(`ecosystem.config.cjs`)。调试:
|
||||
|
||||
```bash
|
||||
source .venv/bin/activate && python app.py
|
||||
```
|
||||
|
||||
见 [docs/ubuntu-server.md](../docs/ubuntu-server.md)。
|
||||
|
||||
端口由 **`APP_PORT`** 控制(未设置默认 **5000**)。浏览器登录 **`/login`**,口令为 **`APP_PASSWORD`**。
|
||||
|
||||
## 部署(Linux / PM2 / SSH SOCKS)
|
||||
|
||||
见 **[部署文档.md](./部署文档.md)**。
|
||||
|
||||
## 自检脚本
|
||||
|
||||
```bash
|
||||
python scripts/verify_gate_funding.py
|
||||
```
|
||||
|
||||
用于核对密钥前缀(不落 Secret)、资金/合约可读性等(需网络与权限)。
|
||||
|
||||
## 数据与脚本
|
||||
|
||||
- 默认 SQLite:由 **`DB_PATH`** 指定(常见为项目下 `crypto.db`)
|
||||
- `scripts/fix_breakeven_labels.py`:修正「止损」但盈亏为正的记录标签(参见部署文档说明)
|
||||
|
||||
## 风险与合规
|
||||
|
||||
实盘有亏损风险。请确认 API 权限、IP 白名单、杠杆与保证金模式与 **Gate.io** 后台一致,并遵守当地法律法规与交易所用户协议。
|
||||
@@ -1,34 +0,0 @@
|
||||
/**
|
||||
* PM2 进程定义(Ubuntu / Linux)。
|
||||
*
|
||||
* 仅托管 Flask 应用。**SSH SOCKS 隧道**用 `ssh -D` 常驻(可用 tmux / autossh),勿交给 PM2。
|
||||
* 与 `.env` 里 `GATE_SOCKS_PROXY` 端口一致即可;不必交给 PM2。
|
||||
*
|
||||
* 使用前:项目根目录存在 `.venv`,且已安装依赖(走 SOCKS 时需 PySocks)。
|
||||
*
|
||||
* 启动:
|
||||
* pm2 start ecosystem.config.cjs
|
||||
* 保存开机列表:
|
||||
* pm2 save && pm2 startup
|
||||
*/
|
||||
const path = require("path");
|
||||
|
||||
const ROOT = __dirname;
|
||||
const REPO_ROOT = path.join(ROOT, "..");
|
||||
const PY = path.join(ROOT, ".venv", "bin", "python");
|
||||
|
||||
module.exports = {
|
||||
apps: [
|
||||
{
|
||||
name: "crypto_gate_bot",
|
||||
cwd: ROOT,
|
||||
script: path.join(ROOT, "app.py"),
|
||||
interpreter: PY,
|
||||
instances: 1,
|
||||
autorestart: true,
|
||||
watch: false,
|
||||
max_memory_restart: "800M",
|
||||
env: { PYTHONPATH: REPO_ROOT },
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -1,109 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Daily backup: SQLite DB + static/images → /root/backups/<instance>/<YYYY-MM-DD>/
|
||||
# Prune backup folders older than RETENTION_DAYS (default 30).
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
BACKUP_ROOT="${BACKUP_ROOT:-/root/backups}"
|
||||
RETENTION_DAYS="${RETENTION_DAYS:-30}"
|
||||
INSTANCE_NAME="${BACKUP_INSTANCE:-$(basename "$PROJECT_DIR")}"
|
||||
TZ_NAME="${BACKUP_TZ:-Asia/Shanghai}"
|
||||
|
||||
log() {
|
||||
printf '[%s] %s\n' "$(TZ="$TZ_NAME" date '+%Y-%m-%d %H:%M:%S %Z')" "$*"
|
||||
}
|
||||
|
||||
read_env_var() {
|
||||
local key="$1"
|
||||
local default="$2"
|
||||
local line
|
||||
if [[ ! -f .env ]]; then
|
||||
printf '%s' "$default"
|
||||
return
|
||||
fi
|
||||
line="$(grep -E "^${key}=" .env 2>/dev/null | tail -1 || true)"
|
||||
if [[ -z "$line" ]]; then
|
||||
printf '%s' "$default"
|
||||
return
|
||||
fi
|
||||
printf '%s' "${line#*=}" | tr -d '\r'
|
||||
}
|
||||
|
||||
resolve_project_path() {
|
||||
local p="$1"
|
||||
if [[ "$p" == /* ]]; then
|
||||
printf '%s' "$p"
|
||||
else
|
||||
printf '%s' "$PROJECT_DIR/$p"
|
||||
fi
|
||||
}
|
||||
|
||||
prune_old_backups() {
|
||||
local base="$BACKUP_ROOT/$INSTANCE_NAME"
|
||||
[[ -d "$base" ]] || return 0
|
||||
local cutoff
|
||||
cutoff="$(TZ="$TZ_NAME" date -d "-${RETENTION_DAYS} days" +%Y-%m-%d 2>/dev/null || true)"
|
||||
if [[ -z "$cutoff" ]]; then
|
||||
find "$base" -mindepth 1 -maxdepth 1 -type d -mtime +"$RETENTION_DAYS" -print0 |
|
||||
xargs -r -0 rm -rf
|
||||
return 0
|
||||
fi
|
||||
local dir name
|
||||
for dir in "$base"/*/; do
|
||||
[[ -d "$dir" ]] || continue
|
||||
name="$(basename "$dir")"
|
||||
[[ "$name" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] || continue
|
||||
if [[ "$name" < "$cutoff" ]]; then
|
||||
log "prune: remove $dir (older than ${RETENTION_DAYS} days)"
|
||||
rm -rf "$dir"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
DB_REL="$(read_env_var DB_PATH crypto.db)"
|
||||
UPLOAD_REL="$(read_env_var UPLOAD_DIR static/images)"
|
||||
BACKUP_ROOT="$(read_env_var BACKUP_ROOT "$BACKUP_ROOT")"
|
||||
RETENTION_DAYS="$(read_env_var BACKUP_RETENTION_DAYS "$RETENTION_DAYS")"
|
||||
INSTANCE_NAME="$(read_env_var BACKUP_INSTANCE "$INSTANCE_NAME")"
|
||||
|
||||
DB_PATH="$(resolve_project_path "$DB_REL")"
|
||||
UPLOAD_DIR="$(resolve_project_path "$UPLOAD_REL")"
|
||||
DATE_TAG="$(TZ="$TZ_NAME" date +%Y-%m-%d)"
|
||||
DEST="$BACKUP_ROOT/$INSTANCE_NAME/$DATE_TAG"
|
||||
|
||||
if [[ ! -f "$DB_PATH" ]]; then
|
||||
log "error: database not found: $DB_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$DEST"
|
||||
log "start backup instance=$INSTANCE_NAME dest=$DEST"
|
||||
|
||||
if command -v sqlite3 >/dev/null 2>&1; then
|
||||
sqlite3 "$DB_PATH" ".backup '$DEST/crypto.db'"
|
||||
log "db: sqlite3 backup -> $DEST/crypto.db"
|
||||
else
|
||||
cp -a "$DB_PATH" "$DEST/crypto.db"
|
||||
log "db: cp -> $DEST/crypto.db (sqlite3 not installed)"
|
||||
fi
|
||||
|
||||
if [[ -d "$UPLOAD_DIR" ]]; then
|
||||
tar -czf "$DEST/static_images.tar.gz" -C "$(dirname "$UPLOAD_DIR")" "$(basename "$UPLOAD_DIR")"
|
||||
log "images: $UPLOAD_DIR -> $DEST/static_images.tar.gz"
|
||||
else
|
||||
log "warn: upload dir missing, skip images: $UPLOAD_DIR"
|
||||
fi
|
||||
|
||||
{
|
||||
echo "instance=$INSTANCE_NAME"
|
||||
echo "project_dir=$PROJECT_DIR"
|
||||
echo "backup_date=$DATE_TAG"
|
||||
echo "db_path=$DB_PATH"
|
||||
echo "upload_dir=$UPLOAD_DIR"
|
||||
} >"$DEST/manifest.txt"
|
||||
|
||||
prune_old_backups
|
||||
log "done"
|
||||
@@ -1,69 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""One-shot SQLite backup before code deploy. Reads DB_PATH from .env (default crypto.db)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import sqlite3
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
PROJECT_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
def _read_env_db_path() -> Path:
|
||||
env_file = PROJECT_DIR / ".env"
|
||||
default = PROJECT_DIR / "crypto.db"
|
||||
if not env_file.is_file():
|
||||
return default
|
||||
for line in env_file.read_text(encoding="utf-8", errors="replace").splitlines():
|
||||
line = line.strip()
|
||||
if not line or line.startswith("#") or "=" not in line:
|
||||
continue
|
||||
key, val = line.split("=", 1)
|
||||
if key.strip() != "DB_PATH":
|
||||
continue
|
||||
val = val.strip().strip('"').strip("'")
|
||||
p = Path(val)
|
||||
return p if p.is_absolute() else PROJECT_DIR / p
|
||||
return default
|
||||
|
||||
|
||||
def main() -> int:
|
||||
db_path = _read_env_db_path()
|
||||
if not db_path.is_file():
|
||||
print(f"error: database not found: {db_path}")
|
||||
return 1
|
||||
stamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
dest_dir = PROJECT_DIR / "backups" / stamp
|
||||
dest_dir.mkdir(parents=True, exist_ok=True)
|
||||
dest = dest_dir / db_path.name
|
||||
try:
|
||||
src = sqlite3.connect(str(db_path))
|
||||
dst = sqlite3.connect(str(dest))
|
||||
src.backup(dst)
|
||||
dst.close()
|
||||
src.close()
|
||||
method = "sqlite3 backup"
|
||||
except Exception:
|
||||
shutil.copy2(db_path, dest)
|
||||
method = "file copy"
|
||||
manifest = dest_dir / "manifest.txt"
|
||||
manifest.write_text(
|
||||
"\n".join(
|
||||
[
|
||||
f"project_dir={PROJECT_DIR}",
|
||||
f"source_db={db_path}",
|
||||
f"backup_file={dest}",
|
||||
f"method={method}",
|
||||
f"created_at={stamp}",
|
||||
]
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
print(f"ok: {dest} ({method})")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -1,108 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
一次性修复历史交易记录标签:
|
||||
将 trade_records 里“止损但实际盈利”的记录改为“保本止盈”。
|
||||
|
||||
默认条件(可通过参数修改):
|
||||
- monitor_type = 下单监控
|
||||
- result = 止损
|
||||
- pnl_amount > 0
|
||||
|
||||
用法示例:
|
||||
1) 仅预览(不落库):
|
||||
python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run
|
||||
|
||||
2) 执行修复:
|
||||
python scripts/fix_breakeven_labels.py --db ./crypto.db --apply
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import sqlite3
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(description="Fix historical stop-loss records with positive pnl.")
|
||||
parser.add_argument("--db", required=True, help="Path to sqlite db file, e.g. ./crypto.db")
|
||||
parser.add_argument("--monitor-type", default="下单监控", help="Filter by monitor_type (default: 下单监控)")
|
||||
parser.add_argument("--from-result", default="止损", help="Source result label (default: 止损)")
|
||||
parser.add_argument("--to-result", default="保本止盈", help="Target result label (default: 保本止盈)")
|
||||
parser.add_argument("--dry-run", action="store_true", help="Preview only, no write")
|
||||
parser.add_argument("--apply", action="store_true", help="Execute update")
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main() -> int:
|
||||
args = parse_args()
|
||||
db_path = Path(args.db).expanduser().resolve()
|
||||
if not db_path.exists():
|
||||
print(f"[ERR] DB not found: {db_path}")
|
||||
return 1
|
||||
|
||||
if args.dry_run and args.apply:
|
||||
print("[ERR] --dry-run and --apply are mutually exclusive.")
|
||||
return 1
|
||||
if not args.dry_run and not args.apply:
|
||||
print("[INFO] No mode provided, defaulting to --dry-run.")
|
||||
args.dry_run = True
|
||||
|
||||
conn = sqlite3.connect(str(db_path))
|
||||
conn.row_factory = sqlite3.Row
|
||||
cur = conn.cursor()
|
||||
|
||||
where_sql = """
|
||||
monitor_type = ?
|
||||
AND result = ?
|
||||
AND CAST(COALESCE(pnl_amount, 0) AS REAL) > 0
|
||||
"""
|
||||
params = (args.monitor_type, args.from_result)
|
||||
|
||||
cur.execute(f"SELECT COUNT(*) AS c FROM trade_records WHERE {where_sql}", params)
|
||||
will_change = int(cur.fetchone()["c"])
|
||||
print(f"[INFO] Candidate rows: {will_change}")
|
||||
|
||||
if will_change == 0:
|
||||
print("[INFO] Nothing to update.")
|
||||
conn.close()
|
||||
return 0
|
||||
|
||||
cur.execute(
|
||||
f"""
|
||||
SELECT id, symbol, result, pnl_amount, closed_at
|
||||
FROM trade_records
|
||||
WHERE {where_sql}
|
||||
ORDER BY id DESC
|
||||
LIMIT 10
|
||||
""",
|
||||
params,
|
||||
)
|
||||
sample = cur.fetchall()
|
||||
print("[INFO] Sample (latest 10):")
|
||||
for r in sample:
|
||||
print(
|
||||
f" id={r['id']} symbol={r['symbol']} result={r['result']} "
|
||||
f"pnl={r['pnl_amount']} closed_at={r['closed_at']}"
|
||||
)
|
||||
|
||||
if args.dry_run:
|
||||
print("[DRY-RUN] No write executed.")
|
||||
conn.close()
|
||||
return 0
|
||||
|
||||
cur.execute(
|
||||
f"UPDATE trade_records SET result=? WHERE {where_sql}",
|
||||
(args.to_result, *params),
|
||||
)
|
||||
changed = int(cur.rowcount)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
print(f"[DONE] Updated rows: {changed}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Install daily backup cron: Beijing 00:00 (CRON_TZ=Asia/Shanghai).
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
BACKUP_SCRIPT="$SCRIPT_DIR/backup_data.sh"
|
||||
INSTANCE_NAME="${BACKUP_INSTANCE:-$(basename "$PROJECT_DIR")}"
|
||||
LOG_FILE="${BACKUP_CRON_LOG:-/var/log/crypto-monitor-backup-${INSTANCE_NAME}.log}"
|
||||
|
||||
if [[ ! -x "$BACKUP_SCRIPT" ]]; then
|
||||
chmod +x "$BACKUP_SCRIPT"
|
||||
fi
|
||||
|
||||
TMP="$(mktemp)"
|
||||
trap 'rm -f "$TMP"' EXIT
|
||||
|
||||
{
|
||||
crontab -l 2>/dev/null | grep -vF "$BACKUP_SCRIPT" || true
|
||||
echo "CRON_TZ=Asia/Shanghai"
|
||||
echo "0 0 * * * $BACKUP_SCRIPT >> $LOG_FILE 2>&1"
|
||||
} >"$TMP"
|
||||
|
||||
awk '
|
||||
BEGIN { tz = 0 }
|
||||
/^CRON_TZ=Asia\/Shanghai$/ {
|
||||
if (tz++) next
|
||||
}
|
||||
{ print }
|
||||
' "$TMP" >"${TMP}.2"
|
||||
mv "${TMP}.2" "$TMP"
|
||||
|
||||
crontab "$TMP"
|
||||
echo "Installed cron for $INSTANCE_NAME"
|
||||
echo " Schedule : daily 00:00 Asia/Shanghai"
|
||||
echo " Script : $BACKUP_SCRIPT"
|
||||
echo " Log : $LOG_FILE"
|
||||
crontab -l | grep -F "$BACKUP_SCRIPT" || true
|
||||
@@ -1,93 +0,0 @@
|
||||
"""
|
||||
在项目根目录执行(会加载根目录 .env):
|
||||
python scripts/verify_gate_funding.py
|
||||
|
||||
依次探测:[0] swap 余额(与 App「交易账户」同源);[1]–[3] 现货 / 统一账户资金路径。
|
||||
打印 GATE_API_KEY 前 8 位便于与 Gate 控制台核对(不含 Secret)。用于服务器自检。
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib.util
|
||||
import os
|
||||
import sys
|
||||
|
||||
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
if ROOT not in sys.path:
|
||||
sys.path.insert(0, ROOT)
|
||||
|
||||
|
||||
def _load_app():
|
||||
path = os.path.join(ROOT, "app.py")
|
||||
spec = importlib.util.spec_from_file_location("crypto_app", path)
|
||||
mod = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(mod)
|
||||
return mod
|
||||
|
||||
|
||||
def main():
|
||||
os.chdir(ROOT)
|
||||
mod = _load_app()
|
||||
print("LIVE_TRADING_ENABLED =", os.getenv("LIVE_TRADING_ENABLED"))
|
||||
ok, reason = mod.ensure_exchange_live_ready()
|
||||
print("ensure_exchange_live_ready =", ok, repr(reason))
|
||||
if not ok:
|
||||
print("跳过私有接口探测")
|
||||
return 1
|
||||
|
||||
mod.ensure_markets_loaded()
|
||||
|
||||
k = (os.getenv("GATE_API_KEY") or "").strip()
|
||||
s = (os.getenv("GATE_API_SECRET") or "").strip()
|
||||
if not k or "REPLACE" in k.upper():
|
||||
print("WARN: GATE_API_KEY 为空或仍像占位符,请核对 .env")
|
||||
if not s or "REPLACE" in s.upper():
|
||||
print("WARN: GATE_API_SECRET 为空或仍像占位符,请核对 .env")
|
||||
print("GATE_API_KEY prefix (8 chars):", (k[:8] + "…") if len(k) > 8 else "(short)")
|
||||
|
||||
# 0) swap — 与 App「交易账户」余额同源(优先看此项是否与网页一致)
|
||||
try:
|
||||
bal = mod.exchange.fetch_balance({"type": "swap"})
|
||||
v0 = mod._extract_usdt_total(bal)
|
||||
print("[0] fetch_balance(swap) USDT total =", v0)
|
||||
except Exception as e:
|
||||
print("[0] fetch_balance(swap) FAILED:", type(e).__name__, e)
|
||||
|
||||
# 1) fetch_balance spot + marginMode spot
|
||||
try:
|
||||
bal = mod.exchange.fetch_balance({"type": "spot", "marginMode": "spot"})
|
||||
v = mod._extract_usdt_total(bal)
|
||||
print("[1] fetch_balance(spot,marginMode=spot) USDT total =", v)
|
||||
except Exception as e:
|
||||
print("[1] fetch_balance(spot) FAILED:", type(e).__name__, e)
|
||||
|
||||
# 2) raw spot accounts
|
||||
try:
|
||||
resp = mod.exchange.privateSpotGetAccounts({})
|
||||
v2 = mod._parse_gate_spot_accounts_response_usdt(resp)
|
||||
print("[2] privateSpotGetAccounts USDT =", v2)
|
||||
except Exception as e:
|
||||
print("[2] privateSpotGetAccounts FAILED:", type(e).__name__, e)
|
||||
|
||||
# 3) unified accounts raw
|
||||
try:
|
||||
raw = mod.exchange.privateUnifiedGetAccounts({})
|
||||
body = raw
|
||||
if isinstance(body, dict) and isinstance(body.get("result"), dict):
|
||||
body = body["result"]
|
||||
if isinstance(body, dict):
|
||||
keys = sorted(body.keys())
|
||||
print("[3] unified top-level keys (sample):", keys[:25], "..." if len(keys) > 25 else "")
|
||||
v3 = mod._parse_usdt_from_gate_unified_accounts_body(body) if isinstance(body, dict) else None
|
||||
print("[3] parsed unified USDT =", v3)
|
||||
except Exception as e:
|
||||
print("[3] privateUnifiedGetAccounts FAILED:", type(e).__name__, e)
|
||||
|
||||
fu = mod._fetch_gate_funding_usdt()
|
||||
print(">>> _fetch_gate_funding_usdt() =", fu)
|
||||
f, t = mod.get_exchange_capitals(force=True)
|
||||
print(">>> get_exchange_capitals(force=True) funding, trading =", f, t)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 181 B |
|
Before Width: | Height: | Size: 162 B |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 497 B |
|
Before Width: | Height: | Size: 5.9 KiB |
@@ -1,17 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0%" stop-color="#22d3ee"/>
|
||||
<stop offset="100%" stop-color="#34d399"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="512" height="512" rx="108" fill="#0c1019"/>
|
||||
<rect x="36" y="36" width="440" height="440" rx="88" fill="#141b2d"/>
|
||||
<rect x="36" y="36" width="440" height="440" rx="88" fill="none" stroke="url(#g)" stroke-width="12"/>
|
||||
<path d="M120 320 L200 248 L280 272 L392 168" fill="none" stroke="url(#g)" stroke-width="20" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="392" cy="168" r="18" fill="#34d399"/>
|
||||
<rect x="168" y="268" width="28" height="64" rx="6" fill="#f87171"/>
|
||||
<line x1="182" y1="248" x2="182" y2="340" stroke="#f87171" stroke-width="10" stroke-linecap="round"/>
|
||||
<rect x="268" y="220" width="28" height="96" rx="6" fill="#34d399"/>
|
||||
<line x1="282" y1="200" x2="282" y2="340" stroke="#34d399" stroke-width="10" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB |
@@ -1 +0,0 @@
|
||||
ok2
|
||||
@@ -1,136 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN" data-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<script src="/static/instance_theme.js?v=4"></script>
|
||||
|
||||
<title>登录 · {{ exchange_display }}</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
background: #0a0a10;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
color: #fff;
|
||||
}
|
||||
.login-box {
|
||||
background: #12121a;
|
||||
padding: 2.5rem;
|
||||
border-radius: 16px;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
border: 1px solid #242435;
|
||||
box-shadow: 0 8px 24px rgba(0,0,0,0.3);
|
||||
}
|
||||
.login-box h2 {
|
||||
margin-bottom: 2rem;
|
||||
text-align: center;
|
||||
font-size: 1.5rem;
|
||||
background: linear-gradient(90deg, #4cc2ff, #7b42ff);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
.form-group {
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.9rem;
|
||||
color: #a9a9ff;
|
||||
}
|
||||
.form-group input {
|
||||
width: 100%;
|
||||
padding: 0.85rem 1rem;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #2e2e45;
|
||||
background: #1a1a29;
|
||||
color: #fff;
|
||||
font-size: 0.95rem;
|
||||
outline: none;
|
||||
}
|
||||
.form-group input:focus {
|
||||
border-color: #4cc2ff;
|
||||
}
|
||||
button {
|
||||
width: 100%;
|
||||
padding: 0.9rem;
|
||||
border-radius: 10px;
|
||||
border: none;
|
||||
background: linear-gradient(90deg, #4285f4, #7b42ff);
|
||||
color: #fff;
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: 0.2s;
|
||||
}
|
||||
button:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
.flash {
|
||||
padding: 0.8rem;
|
||||
margin-bottom: 1rem;
|
||||
background: #331e24;
|
||||
color: #ff6666;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
.exchange-line {
|
||||
text-align: center;
|
||||
font-size: 0.82rem;
|
||||
color: #8892b0;
|
||||
margin: -0.5rem 0 1.25rem;
|
||||
}
|
||||
.exchange-line strong {
|
||||
color: #b8f5d0;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/static/instance_theme.css?v=4">
|
||||
|
||||
</head>
|
||||
<div class="login-theme-bar">
|
||||
<div class="theme-toggle instance-theme-toggle" role="group" aria-label="界面主题">
|
||||
<button type="button" class="theme-toggle-btn is-active" data-theme-value="dark" aria-pressed="true" title="暗色主题">
|
||||
<svg class="theme-icon" viewBox="0 0 24 24" width="18" height="18" aria-hidden="true">
|
||||
<path fill="currentColor" d="M12.1 3a9 9 0 1 0 8.9 11 6.5 6.5 0 1 1-8.9-11z"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button type="button" class="theme-toggle-btn" data-theme-value="light" aria-pressed="false" title="亮色主题">
|
||||
<svg class="theme-icon" viewBox="0 0 24 24" width="18" height="18" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round">
|
||||
<circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<body>
|
||||
<div class="login-box">
|
||||
<h2>交易监控系统登录</h2>
|
||||
<p class="exchange-line">交易所:<strong>{{ exchange_display }}</strong></p>
|
||||
{% with messages = get_flashed_messages() %}
|
||||
{% if messages %}
|
||||
<div class="flash">{{ messages[0] }}</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
<form method="POST" autocomplete="off">
|
||||
<div class="form-group">
|
||||
<label>账号</label>
|
||||
<input type="text" name="username" required placeholder="请输入账号" autocomplete="off" autocapitalize="off" spellcheck="false">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>密码</label>
|
||||
<input type="password" name="password" required placeholder="请输入密码" autocomplete="new-password">
|
||||
</div>
|
||||
<button type="submit">登录</button>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,194 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>实盘下单放大 | 100根K线</title>
|
||||
<style>
|
||||
*{margin:0;padding:0;box-sizing:border-box}
|
||||
body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;background:#0b0d14;color:#eaeaea;padding:14px}
|
||||
.container{width:min(98vw,1900px);margin:0 auto}
|
||||
.card{background:#121726;border-radius:10px;padding:12px;border:1px solid #2a3150;margin-bottom:12px}
|
||||
.row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
|
||||
.btn{padding:7px 10px;border-radius:8px;text-decoration:none;border:1px solid #304164;background:#151a2a;color:#8fc8ff;cursor:pointer}
|
||||
.btn:hover{background:#1f2740}
|
||||
select,button{padding:8px 10px;border-radius:8px;border:1px solid #2e2e45;background:#1a1a29;color:#fff}
|
||||
.meta{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:8px;margin-top:10px}
|
||||
.meta-item{background:#141b2f;border:1px solid #27324e;border-radius:8px;padding:8px}
|
||||
.meta-item .k{font-size:.76rem;color:#9fb0d8}
|
||||
.meta-item .v{font-size:1rem;margin-top:4px;word-break:break-all}
|
||||
.status{font-size:.84rem;color:#95a2c2}
|
||||
.status.err{color:#ff8080}
|
||||
#chart-wrap{height:560px;background:#0f1320;border:1px solid #2a3150;border-radius:10px;padding:8px}
|
||||
#chart{width:100%;height:100%}
|
||||
.empty{padding:18px;color:#95a2c2}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="card">
|
||||
<div class="row" style="justify-content:space-between">
|
||||
<div class="row">
|
||||
<a class="btn" href="/">返回首页</a>
|
||||
<strong style="color:#dbe4ff">实盘下单放大(100根K线)</strong>
|
||||
</div>
|
||||
<div class="status">最近刷新:<span id="updated-at">--</span></div>
|
||||
</div>
|
||||
{% if orders %}
|
||||
<div class="row" style="margin-top:10px">
|
||||
<label>订单</label>
|
||||
<select id="order-id">
|
||||
{% for o in orders %}
|
||||
<option value="{{ o.id }}" {% if selected_order and o.id == selected_order.id %}selected{% endif %}>
|
||||
#{{ o.id }} {{ o.symbol }} {{ '做多' if o.direction == 'long' else '做空' }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label>周期</label>
|
||||
<select id="timeframe">
|
||||
{% for tf in ['1m','3m','5m','15m','30m','1h','4h','1d'] %}
|
||||
<option value="{{ tf }}" {% if tf == default_timeframe %}selected{% endif %}>{{ tf }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<button id="manual-refresh" type="button">刷新</button>
|
||||
<span id="load-status" class="status"></span>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="empty">当前没有激活订单,无法展示放大K线。</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if orders %}
|
||||
<div class="card">
|
||||
<div class="meta">
|
||||
<div class="meta-item"><div class="k">交易对</div><div class="v" id="m-symbol">-</div></div>
|
||||
<div class="meta-item"><div class="k">方向</div><div class="v" id="m-direction">-</div></div>
|
||||
<div class="meta-item"><div class="k">成交价</div><div class="v" id="m-entry">-</div></div>
|
||||
<div class="meta-item"><div class="k">止损</div><div class="v" id="m-sl">-</div></div>
|
||||
<div class="meta-item"><div class="k">止盈</div><div class="v" id="m-tp">-</div></div>
|
||||
<div class="meta-item"><div class="k">盈亏比</div><div class="v" id="m-rr">-</div></div>
|
||||
<div class="meta-item"><div class="k">现价</div><div class="v" id="m-price">-</div></div>
|
||||
<div class="meta-item"><div class="k">浮盈亏</div><div class="v" id="m-pnl">-</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div id="chart-wrap"><div id="chart"></div></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if orders %}
|
||||
<script src="https://unpkg.com/lightweight-charts/dist/lightweight-charts.standalone.production.js"></script>
|
||||
<script>
|
||||
const refreshMs = Math.max({{ price_refresh_seconds * 1000 }}, 5000);
|
||||
const orderSelect = document.getElementById("order-id");
|
||||
const tfSelect = document.getElementById("timeframe");
|
||||
const statusEl = document.getElementById("load-status");
|
||||
const updatedAtEl = document.getElementById("updated-at");
|
||||
const chartHost = document.getElementById("chart");
|
||||
const fmt = (v, d=6) => (v === null || typeof v === "undefined" || Number.isNaN(Number(v))) ? "-" : Number(v).toFixed(d);
|
||||
|
||||
let chart = null;
|
||||
let candleSeries = null;
|
||||
let priceLines = [];
|
||||
|
||||
function ensureChart(){
|
||||
if(chart){ return true; }
|
||||
if(!window.LightweightCharts){
|
||||
statusEl.className = "status err";
|
||||
statusEl.innerText = "图表库加载失败";
|
||||
return false;
|
||||
}
|
||||
chart = LightweightCharts.createChart(chartHost, {
|
||||
layout: { background: { color: "#0f1320" }, textColor: "#d6deff" },
|
||||
grid: { vertLines: { color: "#1e263d" }, horzLines: { color: "#1e263d" } },
|
||||
rightPriceScale: { borderColor: "#2a3150" },
|
||||
timeScale: { borderColor: "#2a3150", timeVisible: true, secondsVisible: false },
|
||||
crosshair: { mode: 0 }
|
||||
});
|
||||
candleSeries = chart.addCandlestickSeries({
|
||||
upColor: "#4cd97f",
|
||||
downColor: "#ff6666",
|
||||
borderVisible: false,
|
||||
wickUpColor: "#4cd97f",
|
||||
wickDownColor: "#ff6666"
|
||||
});
|
||||
window.addEventListener("resize", () => {
|
||||
chart.applyOptions({ width: chartHost.clientWidth, height: chartHost.clientHeight });
|
||||
});
|
||||
chart.applyOptions({ width: chartHost.clientWidth, height: chartHost.clientHeight });
|
||||
return true;
|
||||
}
|
||||
|
||||
function resetPriceLines(){
|
||||
if(!candleSeries){ return; }
|
||||
priceLines.forEach(line => {
|
||||
try { candleSeries.removePriceLine(line); } catch (_) {}
|
||||
});
|
||||
priceLines = [];
|
||||
}
|
||||
|
||||
function addLine(price, title, color){
|
||||
if(!candleSeries || typeof price === "undefined" || price === null){ return; }
|
||||
const p = Number(price);
|
||||
if(Number.isNaN(p) || p <= 0){ return; }
|
||||
priceLines.push(candleSeries.createPriceLine({
|
||||
price: p, color, lineWidth: 1, lineStyle: 0, axisLabelVisible: true, title
|
||||
}));
|
||||
}
|
||||
|
||||
function paintOrder(order){
|
||||
document.getElementById("m-symbol").innerText = order.symbol || "-";
|
||||
document.getElementById("m-direction").innerText = (order.direction === "short") ? "做空" : "做多";
|
||||
document.getElementById("m-entry").innerText = order.trigger_price_display || fmt(order.trigger_price, 8);
|
||||
document.getElementById("m-sl").innerText = order.stop_loss_display || fmt(order.stop_loss, 8);
|
||||
document.getElementById("m-tp").innerText = order.take_profit_display || fmt(order.take_profit, 8);
|
||||
document.getElementById("m-rr").innerText = (order.rr_ratio === null || typeof order.rr_ratio === "undefined") ? "-" : `1:${Number(order.rr_ratio).toFixed(2)}`;
|
||||
document.getElementById("m-price").innerText = order.current_price_display || fmt(order.current_price, 8);
|
||||
const pnlEl = document.getElementById("m-pnl");
|
||||
pnlEl.innerText = `${fmt(order.float_pnl, 2)}U (${fmt(order.float_pct, 2)}%)`;
|
||||
pnlEl.style.color = Number(order.float_pnl || 0) > 0 ? "#4cd97f" : (Number(order.float_pnl || 0) < 0 ? "#ff6666" : "#d6deff");
|
||||
}
|
||||
|
||||
async function loadOrderKline(){
|
||||
if(!ensureChart()){ return; }
|
||||
const orderId = orderSelect.value;
|
||||
const timeframe = tfSelect.value;
|
||||
if(!orderId){ return; }
|
||||
statusEl.className = "status";
|
||||
statusEl.innerText = "加载中...";
|
||||
try{
|
||||
const resp = await fetch(`/api/order_kline?order_id=${encodeURIComponent(orderId)}&timeframe=${encodeURIComponent(timeframe)}`);
|
||||
const data = await resp.json();
|
||||
if(!resp.ok || !data.ok){ throw new Error(data.msg || "请求失败"); }
|
||||
const candles = Array.isArray(data.candles) ? data.candles : [];
|
||||
if(!candles.length){
|
||||
statusEl.className = "status err";
|
||||
statusEl.innerText = "暂无K线数据";
|
||||
return;
|
||||
}
|
||||
candleSeries.setData(candles);
|
||||
resetPriceLines();
|
||||
addLine(data.order.trigger_price, "成交价", "#42a5f5");
|
||||
addLine(data.order.stop_loss, "止损", "#ff6666");
|
||||
addLine(data.order.take_profit, "止盈", "#4cd97f");
|
||||
chart.timeScale().fitContent();
|
||||
paintOrder(data.order || {});
|
||||
updatedAtEl.innerText = data.updated_at || "--";
|
||||
statusEl.className = "status";
|
||||
statusEl.innerText = `已加载 ${candles.length} 根K线`;
|
||||
}catch(err){
|
||||
statusEl.className = "status err";
|
||||
statusEl.innerText = err && err.message ? err.message : "加载失败";
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("manual-refresh").addEventListener("click", loadOrderKline);
|
||||
orderSelect.addEventListener("change", loadOrderKline);
|
||||
tfSelect.addEventListener("change", loadOrderKline);
|
||||
loadOrderKline();
|
||||
setInterval(loadOrderKline, refreshMs);
|
||||
</script>
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,147 +0,0 @@
|
||||
# 使用说明
|
||||
|
||||
**本文件对应仓库:`crypto_monitor_gate`(Gate.io USDT 永续)。**
|
||||
功能、界面与 **Binance U 本位版**(目录 `crypto_monitor_binance`)基本一致,差异主要在 **`.env` 里交易所密钥与部分参数名**(`GATE_*` / `BINANCE_*`),文末有对照。
|
||||
|
||||
**更细的部署(SSH 代理、PM2、依赖安装)** 见同目录 **`部署文档.md`**。
|
||||
**关键位自动开仓的规则、RR、结案原因** 见 **`关键位自动下单说明.md`**。
|
||||
|
||||
---
|
||||
|
||||
## 1. 它能做什么
|
||||
|
||||
面向个人盘面的 **Web 控制台**,主要能力包括:
|
||||
|
||||
| 模块 | 说明 |
|
||||
|------|------|
|
||||
| **关键位监控** | 录入上/下沿与类型,按 **5m 收线** 做硬条件过滤;符合条件后 **企业微信** 提醒,部分类型可 **自动市价开仓**(见第 4 节与专门文档)。 |
|
||||
| **实盘下单监控** | 手工填止损/止盈,**以损定仓** 市价开单,挂上条件止盈止损,并在页面跟踪浮盈亏、保本逻辑等。 |
|
||||
| **交易记录 / 复盘** | 平仓结果、盈亏、错过的单等归档与导出;可选 **AI 复盘**(见 [AI复盘与模型配置说明.md](../AI复盘与模型配置说明.md))。 |
|
||||
| **策略交易** | 顶栏 `/strategy`:趋势回调 + 顺势加仓双栏;见 [策略交易说明.md](../策略交易说明.md)。 |
|
||||
|
||||
后台按 **`MONITOR_POLL_SECONDS`**(默认几秒)轮询行情与监控逻辑。**切勿**在未理解规则时同时运行两套程序共用一个实盘账户。
|
||||
|
||||
---
|
||||
|
||||
## 2. 运行前必须配置(`.env`)
|
||||
|
||||
首次在本目录执行 **`cp .env.example .env`**,再编辑 `.env`(`.env` 勿提交 Git;`git pull` 不会改你的 `.env`,升级前建议 `cp .env .env.backup.$(date +%Y%m%d)`)。
|
||||
|
||||
至少检查以下项(具体键名以 **`.env.example`** 为准):
|
||||
|
||||
| 类别 | 说明 |
|
||||
|------|------|
|
||||
| **登录网页** | `APP_PASSWORD`:打开站点后的登录口令。`FLASK_SECRET_KEY`:Session 密钥,请勿使用默认值。 |
|
||||
| **企业微信** | `WECHAT_WEBHOOK`:告警与关键位推送机器人的 Webhook。 |
|
||||
| **是否真下单** | `LIVE_TRADING_ENABLED=false`:**不会**向交易所发送开仓指令(适合测试流程)。改为 `true` 且密钥正确才会实盘。 |
|
||||
| **交易所 API** | **本仓库:** `GATE_API_KEY`、`GATE_API_SECRET`;合约相关见 `GATE_MARGIN_MODE`、`GATE_POS_MODE`、`GATE_TPSL_*` 等。**勿**把 `.env` 提交到 Git。 |
|
||||
| **关键位 RR / 止损外扩** | `KEY_AUTO_MIN_PLANNED_RR`、`KEY_STOP_OUTSIDE_BREAKOUT_PCT`(详见 `关键位自动下单说明.md`)。 |
|
||||
| **AI 复盘** | `AI_PROVIDER=openai`(默认)或 `ollama`;变量见 `.env.example` 与 [AI复盘与模型配置说明.md](../AI复盘与模型配置说明.md)。 |
|
||||
|
||||
网络不稳定时可为 Gate 配置 **`GATE_SOCKS_PROXY`** 等(见 **`部署文档.md`**)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 如何启动与登录
|
||||
|
||||
1. 按 **`部署文档.md`** 建好虚拟环境、安装依赖(如 `flask`、`requests`、`ccxt`、按需 `Pillow`、`PySocks` 等),配置好 `.env`。
|
||||
2. 启动 Flask 应用(本仓库可用 **`ecosystem.config.cjs`** 交给 PM2,或本地 `python app.py` / `flask run`,以你当前脚本为准)。
|
||||
3. 浏览器访问站点,打开 **`/login`**,使用 **`.env` 里的 `APP_PASSWORD`** 登录。
|
||||
|
||||
登录后顶栏:**关键位监控** | **实盘下单** | **策略交易**(`/strategy`)| **策略交易记录**(`/strategy/records`)| **交易记录与复盘** | **统计分析**。
|
||||
|
||||
---
|
||||
|
||||
## 4. 关键位监控(顶栏「关键位监控」→ `/key_monitor`)
|
||||
|
||||
### 4.1 添加一条关键位
|
||||
|
||||
1. **币种**:如 `BTC` 或 `BTC/USDT`(会规范成内部符号)。
|
||||
2. **类型**(必选其一):
|
||||
|
||||
| 类型 | 行为摘要 |
|
||||
|------|----------|
|
||||
| **箱体突破** | 通过门控且计划 RR 达标 → **自动市价开仓**(需 `LIVE_TRADING_ENABLED=true` 且无其他持仓占位)。结案后本条从列表消失并记入历史。 |
|
||||
| **收敛突破** | 同上(自动开仓类)。 |
|
||||
| **关键阻力位** | **不自动开仓**;触发后 **发 1 次微信**,然后本条 **结案进历史**。 |
|
||||
| **关键支撑位** | 同上(仅提醒)。 |
|
||||
| **回调触价开仓** | **不挂交易所限价**;标记价回调触达 E 后 **下一轮询市价开仓**(RR 门槛同 `KEY_AUTO_MIN_PLANNED_RR`);有效期 **24h** |
|
||||
| **突破触价开仓** | **不挂交易所限价**;标记价 **穿越 E 立即市价开仓**;先触 SL/TP 侧失效;有效期 **24h** |
|
||||
|
||||
3. **方向**:做多 / 做空(触价开仓 / 箱体 / 收敛 / 斐波必选;阻力/支撑不选)。
|
||||
4. **价位**:箱体/收敛/阻力/支撑填 **上沿 / 下沿**;触价开仓填 **入场 E / 止损 SL / 止盈 TP**。
|
||||
|
||||
**限制:**
|
||||
活跃持仓数达到 **`MAX_ACTIVE_POSITIONS`**(默认 1)时,**不允许**再添加「**箱体突破** / **收敛突破**」;仍可添加「**关键阻力位 / 支撑位**」。
|
||||
若 **4h EMA55** 与你的方向逆势,页面会 **额外 Flash 提示**,**不阻挡**提交。
|
||||
|
||||
### 4.2 触发后会发生什么(简版)
|
||||
|
||||
- **箱体 / 收敛**:门控通过后计算计划 SL/TP 与 RR;不达标则 **微信说明 + `rr_insufficient` 结案**;达标则尝试 **市价开仓**,成功 **`auto_opened`**,失败 **`exchange_failed`**——均 **不重试同一关键位**。
|
||||
- **阻力 / 支撑**:仅 **单次推送** → **`key_level_alert_only`** 结案。
|
||||
|
||||
详细公式、结案字段、与企业微信文案口径见 **`关键位自动下单说明.md`**。
|
||||
|
||||
### 4.3 列表与历史
|
||||
|
||||
- 当前条目可 **删除**(会按规则记入历史的情形见页面说明)。
|
||||
- **关键位历史**:已结案记录;可配合导出链接(若有)做备份。
|
||||
|
||||
---
|
||||
|
||||
## 5. 实盘下单(顶栏「实盘下单」→ `/trade`)
|
||||
|
||||
用于 **自己点按钮** 开单:
|
||||
|
||||
- 持仓上限由 **`MAX_ACTIVE_POSITIONS`** 控制(默认 1,与关键位自动单共用)。
|
||||
- **人工开仓**时计划盈亏比不得低于 **`MANUAL_MIN_PLANNED_RR`**(默认 1.4:1),否则页面弹窗且后端拒绝。
|
||||
- 填写币种、方向、杠杆(可选)、止损/止盈(价格或百分比按表单说明)。
|
||||
- 勾选是否启用 **移动保本** 等行为以 `.env`/页面默认值为准。
|
||||
|
||||
平仓通过页面 **平仓**(或等价入口),会从交易所市价处理并更新记录。**删除/误操作可能造成真实盈亏**,请先确认环境与方向。
|
||||
|
||||
开仓成功后持仓卡片上会显示 **「来源」**:手工单一般为 **下单监控**;来自关键位自动单的为 **关键位监控**。
|
||||
|
||||
---
|
||||
|
||||
## 6. 企业微信会看到什么
|
||||
|
||||
- 关键位:按类型与结案结果推送(RR 不足、下单失败、自动开仓成功、仅阻力支撑提醒等),**每条关键位结案路径原则上一条主推送**(详见 `关键位自动下单说明.md`)。
|
||||
- 手工开仓、平仓、部分异常也会在规则满足时推送(以代码与配置为准)。
|
||||
|
||||
若未配置 **`WECHAT_WEBHOOK`** 或网络失败,可能只是看不到推送,不代表逻辑未执行;要紧操作请以 **交易所端持仓与挂单** 为准核对。
|
||||
|
||||
---
|
||||
|
||||
## 7. 强烈建议的风险与运维习惯
|
||||
|
||||
1. **先用 `LIVE_TRADING_ENABLED=false`** 验证页面、录入、推送,再开小资金开实盘。
|
||||
2. **API 权限**:仅开所需合约权限;勿泄露密钥;定期轮换。
|
||||
3. **单进程控盘**:同一账户避免本程序与其他机器人 **重复开仓**。
|
||||
4. **自动备份**:服务器上执行 `bash scripts/install_backup_cron.sh`(每天北京时间 0:00 → `/root/backups`,保留 30 天);升级前也可 `bash scripts/backup_data.sh` 手动跑一次。
|
||||
5. **升级代码后**:启动时会跑 **数据库迁移**(如新列 `order_monitors.monitor_type`);首次启动关注一下日志或无报错页面。
|
||||
|
||||
---
|
||||
|
||||
## 8. 常见问题(简要)
|
||||
|
||||
| 现象 | 可自查 |
|
||||
|------|--------|
|
||||
| 关键位永远不触发 | 5m 门控是否全通过(页面门控摘要)、币种日成交量是否在规则内、`KLINE_TIMEFRAME`。 |
|
||||
| 有信号但不自动开仓 | `LIVE_TRADING_ENABLED`、`KEY_AUTO_MIN_PLANNED_RR`、计划 RR、是否已有持仓、API/余额报错(微信或日志)。 |
|
||||
| 加不了箱体/收敛 | 是否已有活跃持仓;先平仓或改用「阻力/支撑位」仅提醒。 |
|
||||
| 推送收不到 | `WECHAT_WEBHOOK`、企业微信机器人配额与网络。 |
|
||||
|
||||
---
|
||||
|
||||
## 9. Binance 版(`crypto_monitor_binance`)差异速查
|
||||
|
||||
| 项目 | Gate 本仓库 | Binance 版 |
|
||||
|------|-------------|------------|
|
||||
| API 变量 | `GATE_API_KEY`、`GATE_API_SECRET`、`GATE_*` | `BINANCE_API_KEY`、`BINANCE_API_SECRET`、`BINANCE_*` |
|
||||
| 实盘开关 | `LIVE_TRADING_ENABLED`(通用) | 同上 |
|
||||
| 止盈止损挂载路径 | `_gate_place_tp_sl_orders` 与 `GATE_TPSL_*` | `_binance_place_tp_sl_orders`(U 本位条件单) |
|
||||
| 资金显示舍入 | 以本仓库为准 | 与 **`FUNDS_DECIMALS`** 等一致 |
|
||||
| 专门文档 | **`关键位自动下单说明.md`**(各仓库有一份,开头标明交易所) | 同左 |
|
||||
|
||||
操作流程(登录、关键位四类、手工单、单仓)**两份程序一致**:换目录、换 `.env` 即可对照使用。
|
||||
@@ -1,143 +0,0 @@
|
||||
# 关键位监控说明(自动开仓 + 人工盯盘)
|
||||
|
||||
**适用:`crypto_monitor_gate`(Gate U 本位永续)**
|
||||
Binance / OKX 见各自目录下同名文档;共享逻辑在仓库根目录 `key_monitor_lib.py`。
|
||||
|
||||
本文档与 `.env`、`check_key_monitors`、`add_key`、`_key_hard_checks`、`_process_key_rs_level_alert` 一致。
|
||||
|
||||
---
|
||||
|
||||
## 一、监控类型总览
|
||||
|
||||
| 录入类型 | 录入时选方向 | 自动市价开仓 | 触发与结案 |
|
||||
|----------|--------------|--------------|------------|
|
||||
| **箱体突破** | **必选** 多/空 | **是**(门控 + RR) | 条件满足 → 开仓或 `rr_insufficient` / `exchange_failed` → **一次性删除** |
|
||||
| **收敛突破** | **必选** 多/空 | **是**(同上) | 同上 |
|
||||
| **关键阻力位** | **不选**(`direction=watch`) | **否** | 5m 收盘突破上/下沿 → 微信 **3 次** → `key_level_alert_done` |
|
||||
| **关键支撑位** | **不选** | **否** | 同上(与阻力位**相同规则**:填上沿+下沿,程序双向监控) |
|
||||
| 斐波回调 0.618 / 0.786 | 必选 | 限价挂单逻辑 | 见斐波说明(**不在下文展开**) |
|
||||
|
||||
**添加时(所有类型):** 品种须 **日成交量排名前 `KEY_DAILY_VOLUME_RANK_MAX`(默认 30)**;上沿 **>** 下沿。
|
||||
|
||||
---
|
||||
|
||||
## 二、关键阻力位 / 关键支撑位(人工盯盘)
|
||||
|
||||
### 2.1 录入
|
||||
|
||||
- 填写 **上沿 `upper`** 与 **下沿 `lower`**(程序同时监控两侧,**无法预先判定**做多还是做空)。
|
||||
- 页面 **不显示、不要求** 方向;库中 `direction` 初始为 `watch`,**首次突破后** 写入 `long`(向上突破上沿)或 `short`(向下突破下沿)。
|
||||
|
||||
### 2.2 触发(极简)
|
||||
|
||||
- 周期:**`KLINE_TIMEFRAME`(默认 5m)最近一根已闭合 K** 的 **收盘价**(非影线)。
|
||||
- **向上突破上沿:** `收盘 > upper` → 推断方向 **多 / 向上**,本次监控任务开始按节奏提醒。
|
||||
- **向下突破下沿:** `收盘 < lower` → 推断方向 **空 / 向下**,本次任务同样开始提醒。
|
||||
- **任一侧突破即结束本条监控周期**(不会在突破后再等待另一侧;上沿、下沿谁先满足用谁,同根 K 仅可能满足一侧)。
|
||||
|
||||
**不参与:** 量能、二确 K、越过幅度下限、日成交排名(运行时)、计划 RR、自动开仓。
|
||||
|
||||
### 2.3 微信提醒次数
|
||||
|
||||
| 配置 | 默认 | 含义 |
|
||||
|------|------|------|
|
||||
| `KEY_ALERT_MAX_TIMES` | `3` | 突破后最多推送 3 次 |
|
||||
| `KEY_ALERT_INTERVAL_MINUTES` | `5` | 相邻两次推送至少间隔 5 分钟 |
|
||||
|
||||
- 第 1 次:首次检测到突破的当次轮询(若已闭合 5m 满足条件)。
|
||||
- 第 2、3 次:仅按间隔推送(**不要求**价格仍在箱外)。
|
||||
- 第 3 次推送后:写入 `key_monitor_history`,`close_reason=**key_level_alert_done**`,从 `key_monitors` **删除**。
|
||||
|
||||
### 2.4 与箱体/收敛的区别
|
||||
|
||||
| 项目 | 阻力/支撑 | 箱体/收敛 |
|
||||
|------|-----------|-----------|
|
||||
| 方向 | 程序推断 | 人工选择 |
|
||||
| K 线根数 | 1 根闭合 5m | 2 根(突破 K + 确认 K) |
|
||||
| 提醒次数 | 3 次后结案 | 自动单:触发后 1 次业务推送并结案 |
|
||||
|
||||
---
|
||||
|
||||
## 三、箱体突破 / 收敛突破(自动开仓)
|
||||
|
||||
### 3.1 K 线结构(默认索引)
|
||||
|
||||
| 角色 | 环境变量 | 默认 | 含义 |
|
||||
|------|----------|------|------|
|
||||
| 突破 K | `KEY_CONFIRM_BREAKOUT_BAR` | `-2` | 倒数第 2 根闭合 K |
|
||||
| 确认 K | `KEY_CONFIRM_BAR` | `-1` | 倒数第 1 根闭合 K |
|
||||
|
||||
### 3.2 硬门控(须全部通过)
|
||||
|
||||
1. **有效突破(收盘越界)**
|
||||
- 多:`突破 K 收盘 > upper`
|
||||
- 空:`突破 K 收盘 < lower`
|
||||
|
||||
2. **突破越过幅度(仅下限)**
|
||||
- 多:`(突破 K 收盘 − upper) / upper × 100 > KEY_BREAKOUT_AMP_MIN_PCT`(默认 **0.03%**)
|
||||
- 空:`(lower − 突破 K 收盘) / lower × 100 >` 同上
|
||||
- **无上限**;突破过猛由 **计划 RR** 过滤。
|
||||
- **不再**使用 K 线实体占开盘价比例;`KEY_BREAKOUT_AMP_MAX_PCT` **已不参与门控**。
|
||||
|
||||
3. **确认 K 不进箱体**
|
||||
- 多:确认 K 收盘 **`> upper`**(不得在 `[lower, upper]` 内)
|
||||
- 空:确认 K 收盘 **`< lower`**
|
||||
|
||||
4. **量能:** 突破 K 成交量 > 前 `KEY_VOLUME_MA_BARS`(默认 20)根均量 × `KEY_VOLUME_RATIO_MIN`(默认 1.3)
|
||||
|
||||
5. **日成交量排名:** 运行时仍须前 `KEY_DAILY_VOLUME_RANK_MAX`(默认 30)
|
||||
|
||||
6. **计划 RR(最后经济门控):** 按确认 K 收盘 **E** 计算 SL/TP 后,`RR` **严格大于** `KEY_AUTO_MIN_PLANNED_RR`(默认 1.5)才市价开仓
|
||||
|
||||
### 3.3 止损 / 止盈(确认 K 收盘为 E)
|
||||
|
||||
箱体高 **H = |upper − lower|**。止损锚在 **突破 K 极值** 外侧:
|
||||
|
||||
| 方向 | 止损(标准/趋势方案) |
|
||||
|------|------------------------|
|
||||
| 多 | 突破 K **最低价** × (1 − `KEY_STOP_OUTSIDE_BREAKOUT_PCT`%) |
|
||||
| 空 | 突破 K **最高价** × (1 + `KEY_STOP_OUTSIDE_BREAKOUT_PCT`%) |
|
||||
|
||||
止盈方案见下表(与改版前一致):
|
||||
|
||||
| 方案 | `sl_tp_mode` | 多:SL / TP | 空:SL / TP |
|
||||
|------|--------------|-------------|-------------|
|
||||
| 标准突破 | `standard` | 突破 K 低外侧% / **E+H** | 突破 K 高外侧% / **E−H** |
|
||||
| 箱体 1R·止盈 1.5H | `box_1p5` | **E−H** / **E+1.5×H** | **E+H** / **E−1.5×H** |
|
||||
| 趋势单·自填止盈 | `trend_manual` | 突破 K 低 × (1−`KEY_TREND_STOP_OUTSIDE_PCT`%) / **录入止盈** | 突破 K 高外侧% / **录入止盈** |
|
||||
|
||||
### 3.4 一次性结案(`close_reason`)
|
||||
|
||||
| `close_reason` | 含义 |
|
||||
|----------------|------|
|
||||
| `box_opposite_break` | 标记价先突破反向边界(多:≤下沿;空:≥上沿) |
|
||||
| `rr_insufficient` | 门控通过但 RR 不达标或 SL/TP 几何无效 |
|
||||
| `exchange_failed` | RR 达标但实盘/交易所等原因未开仓 |
|
||||
| `auto_opened` | RR 达标且市价开仓成功 |
|
||||
| `key_level_alert_done` | 阻力/支撑 **3 次提醒** 完成 |
|
||||
|
||||
---
|
||||
|
||||
## 四、环境与参数(`.env` 摘要)
|
||||
|
||||
| 变量 | 箱体/收敛 | 阻力/支撑 |
|
||||
|------|-----------|-----------|
|
||||
| `KEY_BREAKOUT_AMP_MIN_PCT` | 突破越过下限(默认 0.03) | 不用 |
|
||||
| `KEY_BREAKOUT_AMP_MAX_PCT` | **已废弃门控** | 不用 |
|
||||
| `KEY_VOLUME_*` / `KEY_CONFIRM_*` | 用 | 不用 |
|
||||
| `KEY_AUTO_MIN_PLANNED_RR` | 用 | 不用 |
|
||||
| `KEY_ALERT_MAX_TIMES` / `KEY_ALERT_INTERVAL_MINUTES` | 不用 | 用(默认 3 次 / 5 分钟) |
|
||||
| `KEY_DAILY_VOLUME_RANK_MAX` | 添加时 + 运行时 | **仅添加时** |
|
||||
|
||||
---
|
||||
|
||||
## 五、相关代码
|
||||
|
||||
| 说明 | 位置 |
|
||||
|------|------|
|
||||
| 共享判定 | `key_monitor_lib.py` |
|
||||
| 主循环 | `check_key_monitors` |
|
||||
| 自动门控 | `_key_hard_checks` |
|
||||
| 阻力/支撑提醒 | `_process_key_rs_level_alert` |
|
||||
| 录入 | `add_key` |
|
||||
| 开仓 | `_market_open_for_key_monitor` |
|
||||
@@ -1,148 +0,0 @@
|
||||
# 界面与风控更新说明(Gate 实例)
|
||||
|
||||
## 顶栏导航(4 项)
|
||||
|
||||
| 顺序 | 名称 | 路由 | 说明 |
|
||||
|------|------|------|------|
|
||||
| 1 | 关键位监控 | `/key_monitor` | 关键位添加、实时门控、历史 |
|
||||
| 2 | 实盘下单 | `/trade` | 人工开仓、划转、实时持仓(**默认首页** `/` → `/trade`) |
|
||||
| 3 | 交易记录与复盘 | `/records` | 交易记录、复盘表单、AI 历史(受顶栏 UTC 时间窗筛选) |
|
||||
| 4 | 统计分析 | `/stats` | 按北京时间交易日切日 + 分品类统计块 |
|
||||
|
||||
## 关键位监控页
|
||||
|
||||
- 标题去掉「5m」;规则条从 `.env` 读取(周期、确认K、量能、自动开仓盈亏比、日成交量排名)。
|
||||
- 左列:活跃关键位,**pos-card** 样式展示现价/距上沿/距下沿/门控。
|
||||
- 右列:关键位历史(失效/结案),与左列等高滚动;**受顶栏 UTC 列表时间窗筛选**(默认 UTC 当日)。
|
||||
- 监控类型新增:**斐波回调0.618**、**斐波回调0.786**(与 Binance 主站同一套规则,计算逻辑见仓库根目录 `fib_key_monitor_lib.py`)。
|
||||
|
||||
### 斐波关键位监控(方案 A:交易所限价)
|
||||
|
||||
| 项 | 说明 |
|
||||
|----|------|
|
||||
| 同币互斥 | 每个币种只能有一条斐波监控(0.618 与 0.786 不可并存) |
|
||||
| 上下沿 | 上沿 **H**、下沿 **L**(须 H > L) |
|
||||
| 挂单价 E | **做多** `E = H − ratio × (H − L)`(自 H 向下回撤);**做空** `E = L + ratio × (H − L)`(自 L 向上反弹) |
|
||||
| 做多 | 限价 @ E,止损 L,止盈 H |
|
||||
| 做空 | 限价 @ E,止损 H,止盈 L |
|
||||
| 添加后 | **立即**在 Gate 挂限价单;卡片显示 **挂E**、限价单 ID |
|
||||
| 失效 | 以**标记价**判断:做多且标记价 ≥ H、做空且标记价 ≤ L,且限价**未成交** → 撤销该限价单并结案(不写历史开仓) |
|
||||
| 成交后 | 按仓位挂交易所 TP/SL → 写入 **实盘下单监控**(`monitor_type=关键位监控`,`key_signal_type=斐波回调0.618/0.786`)→ 从关键位列表移除 |
|
||||
| 撤单 | 仅撤本条斐波的 `fib_limit_order_id`,**不会** `cancel_all`,避免误伤其他委托 |
|
||||
| 盈亏比 | 计划 RR 须 > `KEY_AUTO_MIN_PLANNED_RR`(与箱体/收敛一致);0.618 理论约 1.6:1,0.786 约 3.7:1 |
|
||||
| 日成交量 | 与箱体/收敛相同,须在前 `KEY_DAILY_VOLUME_RANK_MAX` 名内方可添加 |
|
||||
|
||||
后台轮询:`check_fib_key_monitors()`(标记价失效 / 成交检测);箱体/收敛仍走 `check_key_monitors()`,互不干扰。
|
||||
|
||||
手动删除关键位时,若斐波限价尚未成交,会先撤交易所限价再删库记录。
|
||||
|
||||
### 箱体 / 收敛自动开仓(来源标注)
|
||||
|
||||
- 自动开仓写入 `order_monitors.key_signal_type`:`箱体突破` 或 `收敛突破`。
|
||||
- 持仓卡片、交易记录列表会显示「来源 · 信号类型」。
|
||||
|
||||
## 列表时间窗(UTC,全站顶栏)
|
||||
|
||||
共用模块:仓库根目录 `history_window_lib.py`(Gate / Binance 主站一致)。
|
||||
|
||||
| 项 | 说明 |
|
||||
|----|------|
|
||||
| 默认 | **UTC 当日**(`win_preset=utc_today`,从 UTC 0:00 至当前时刻) |
|
||||
| 可选 | 近 24 小时、近 7 天、自定义起止(UTC,`datetime-local`) |
|
||||
| 作用范围 | 关键位历史、交易记录列表、复盘记录 API、AI 历史 API、导出「交易记录」「关键位历史」 |
|
||||
| 与统计的关系 | **仅影响列表/导出**;**统计分析页仍按北京时间 `TRADING_DAY_RESET_HOUR`(默认 8:00)切交易日** |
|
||||
| 库内时间 | DB 存北京时间字符串;后端用 `utc_window_to_bj_sql_strings()` 换算后再 SQL 比较 |
|
||||
| 切换方式 | 顶栏「列表筛选(UTC)」→ 选预设 → **应用**(保留当前路由,如 `/records?win_preset=…`) |
|
||||
|
||||
查询参数示例:
|
||||
|
||||
- `?win_preset=utc_today`
|
||||
- `?win_preset=utc_last24h` / `utc_last7d`
|
||||
- `?win_preset=custom&from_utc=2026-05-18 00:00:00&to_utc=2026-05-19 12:00:00`
|
||||
|
||||
## 交易记录与复盘
|
||||
|
||||
- 平仓记录可同步交易所已实现盈亏(Gate 仓位历史等);列表盈亏列优先显示交易所数据,标注 **所** / **估**。
|
||||
- 记录页提供 **立即同步**(`POST /api/sync_exchange_pnl`),用于补全或刷新 `exchange_realized_pnl` 等字段。
|
||||
- 未做人工复盘时,展示以交易所盈亏为准(有同步数据时)。
|
||||
- **列表默认只显示当前 UTC 时间窗内**的记录(见上节);导出 CSV 同步该时间窗。
|
||||
- 表头 **「止损(开仓)」**:展示开仓快照 `initial_stop_loss`(无则回退 `stop_loss`);核对/复盘仍可用有效止损字段。
|
||||
- 平仓写入 `trade_records` 时:`stop_loss` 与 `initial_stop_loss` 均写入**开仓时止损快照**;`key_signal_type` 保留箱体/收敛/斐波来源(`fib_key_monitor_lib.key_signal_type_for_trade_record`)。
|
||||
- **开仓类型**(`entry_reason`):机器单平仓入库时,若未手填,按 `key_signal_type` 自动映射(见下表);列表/导出「开仓类型」列 = 复盘核对值优先,否则入库值,否则按信号映射。
|
||||
|
||||
| `key_signal_type` | 自动写入的 `entry_reason` |
|
||||
|-------------------|---------------------------|
|
||||
| 箱体突破 | 关键位箱体突破 |
|
||||
| 收敛突破 | 关键位收敛突破 |
|
||||
| 斐波回调0.618 | 关键位斐波0.618 |
|
||||
| 斐波回调0.786 | 关键位斐波0.786 |
|
||||
|
||||
- 复盘表单 **开仓类型** 下拉新增上述四条固定文案(与趋势/波段类并列)。
|
||||
- 复盘 **离场触发** 新增 **「止盈」**;从交易记录「填入复盘」时,若结果为「止盈/保本止盈/移动止盈/止损/手动平仓」会自动选中对应触发项,并按 `key_signal_type` 预填开仓类型。
|
||||
- 勾选「保存时自动生成多周期 K 线图」时:以 **平仓时间** 为锚点,各周期向前约 `ORDER_CHART_LIMIT`(默认 100)根 K 线(`_fetch_ohlcv_ending_at`),不再固定拉「最近 100 根」。
|
||||
- `/api/journals`、`/api/reviews` 支持同一时间窗 query,与列表一致。
|
||||
|
||||
### 导出(交易记录 v3)
|
||||
|
||||
- 文件名:`trade_records_v3_YYYYMMDD.csv`
|
||||
- 相对 v2 增加:`key_signal_type`、`initial_stop_loss`(及开仓快照列)、`planned_rr`、`actual_rr`、`risk_amount`、交易所盈亏与时间字段等;末列「开仓类型」为有效展示文案。
|
||||
- 「关键位历史」导出同样受 UTC 时间窗限制。
|
||||
|
||||
## 实盘下单页
|
||||
|
||||
- 左列:实盘下单监控(表单、划转、规则)。
|
||||
- 右列:实时持仓(独立模块)。
|
||||
- **人工开仓门控**:计划盈亏比 < `MANUAL_MIN_PLANNED_RR`(默认 **1.4**)时前端弹窗 + 后端拒绝。
|
||||
- **移动保本**(勾选启用):监控轮询达到触发 RR 后,止损阶梯上移时**同步交易所**——调用与页面「挂止盈止损」相同的 **先撤后挂**(`replace_active_monitor_tpsl_on_exchange`:撤该合约全部 TP/SL 条件单 → 按新止损 + 原止盈重挂)。仅交易所成功后才写库;失败发企业微信告警,本地止损不变。未配置实盘 API 时仍只更新本地(与旧行为一致)。
|
||||
|
||||
## 统计分析页(`/stats`)
|
||||
|
||||
| 项 | 说明 |
|
||||
|----|------|
|
||||
| 切日 | **北京时间**;交易日边界 = 每日 `TRADING_DAY_RESET_HOUR:00`(`.env` 默认 **8**) |
|
||||
| 品类下拉 | 页顶 **「统计品类」** 下拉切换(默认「全部交易」):全部交易、下单监控、关键位箱体突破、关键位收敛结构、关键位斐波0.618、关键位斐波0.786;一次只显示所选品类的日/周/月 |
|
||||
| URL | 切换后写入 `stats_segment=`(如 `all`、`manual`、`key_box`、`key_conv`、`key_fib618`、`key_fib786`),刷新 `/stats` 可保持选项 |
|
||||
| 每块指标 | 日 / 周 / 月:开单次数、平仓笔数、胜率、净盈亏、回撤、连续亏损等(与原口径一致) |
|
||||
| 开单次数 | 人工块:`monitor_type=下单监控` 且无 `key_signal_type`;关键位块:按 `order_monitors.key_signal_type` 计数 |
|
||||
| 不受 UTC 窗影响 | 统计始终基于库内全部已平仓记录,按北京交易日归类,**不**随顶栏 UTC 列表窗切换 |
|
||||
|
||||
## 持仓与计仓
|
||||
|
||||
- `MAX_ACTIVE_POSITIONS` 默认 **1**(可在 `.env` 调大)。
|
||||
- 关键位自动开仓:在已有持仓时,若 `KEY_SIZING_USE_ZERO_POSITION_SNAPSHOT=true`,按**首笔开仓前**交易账户资金快照计仓(`trading_sessions.key_sizing_capital_snapshot`)。
|
||||
|
||||
## 配置
|
||||
|
||||
详见 `.env.example` 中「关键位门控」「交易执行 / 人工风控」注释段。Gate 专用项(`GATE_*`、止盈止损触发等)保持原有段落不变。
|
||||
|
||||
## 自动备份(服务器)
|
||||
|
||||
- 脚本:`scripts/backup_data.sh`(`crypto.db` + `static/images`)
|
||||
- 定时:`scripts/install_backup_cron.sh` → 每天 **北京时间 0:00**,目录 **`/root/backups/<实例名>/YYYY-MM-DD/`**,保留 **30** 天
|
||||
- 详见 `部署文档.md` 第 5.4 节(自动备份)
|
||||
|
||||
## 数据库(启动时自动迁移)
|
||||
|
||||
`key_monitors` 新增斐波字段(示例):`fib_limit_order_id`、`fib_entry_price`、`fib_stop_loss`、`fib_take_profit`、`fib_order_amount`、`fib_margin_capital`、`fib_leverage`。
|
||||
|
||||
`trade_records` / `order_monitors` 新增或沿用:`key_signal_type`、`exchange_realized_pnl`、`exchange_opened_at`、`exchange_closed_at`、`exchange_sync_key`、`entry_reason`、`reviewed_entry_reason`、`initial_stop_loss`。
|
||||
|
||||
**历史数据**:本次**不做**旧记录的批量回填(`entry_reason` / `initial_stop_loss` / `key_signal_type` 等);仅**新产生**的平仓与复盘按新逻辑写入。旧行展示可回退已有字段。
|
||||
|
||||
## 涉及文件(便于排查)
|
||||
|
||||
| 路径 | 说明 |
|
||||
|------|------|
|
||||
| `history_window_lib.py` | UTC 时间窗解析与转北京时间 SQL 字符串 |
|
||||
| `fib_key_monitor_lib.py` | 斐波计算、`KEY_ENTRY_REASON_BY_SIGNAL`、`entry_reason_from_key_signal` |
|
||||
| `crypto_monitor_gate/app.py` | 列表筛选、统计分块、导出 v3、复盘 K 线锚点、入库逻辑 |
|
||||
| `crypto_monitor_gate/templates/index.html` | 顶栏时间窗、统计分块 UI、止损(开仓)列、复盘预填 |
|
||||
|
||||
## 升级步骤
|
||||
|
||||
1. `git pull` 后对比 `.env.example`,把新增变量合并进本地 `.env`。
|
||||
2. 在 VPS 上为 Binance / Gate / Gate Bot **各执行一次** `bash scripts/install_backup_cron.sh`(若尚未安装)。
|
||||
3. 重启 Gate 实例服务(如 `pm2 restart crypto_gate`);首次启动会自动 `ALTER TABLE` 缺列(斐波、交易所盈亏、`entry_reason` 等)。
|
||||
4. 浏览器强刷(Ctrl+F5)避免旧版 `index.html` 缓存。
|
||||
5. 打开任意页确认顶栏出现 **「列表筛选(UTC)」**;`/stats` 可见分品类统计与「北京 8:00 切日」说明。
|
||||
6. 建议在测试币上先添加一条斐波监控,确认:限价已挂出、标记价失效会撤单、成交后出现持仓监控且 TP/SL 已挂上;平仓后交易记录止损(开仓)与开仓类型是否正确。
|
||||
@@ -1,129 +0,0 @@
|
||||
# 趋势回调策略(机器人)说明
|
||||
|
||||
本文描述 **「趋势回调」** 自动交易计划的业务规则与实现口径。
|
||||
|
||||
**四所主站**(Binance / Gate / OKX / 本目录 `crypto_monitor_gate_bot`)均在顶栏 **策略交易 → `/strategy`** 左栏提供同一套逻辑(共用 `strategy_trend_register.py`);本目录侧重 **Gate 子账户 / 机器人** 实例,可与主 Gate 账户隔离部署。
|
||||
|
||||
**检阅备忘**(中控平仓、交易记录、补仓展示、漏记补录):[docs/trend-hub-close-and-trade-records.md](../docs/trend-hub-close-and-trade-records.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 适用场景
|
||||
|
||||
- 单独用于跑策略的 **Gate.io USDT 永续** 子账户(建议与主资金隔离);其它交易所实例同理,使用各自 API 与 `crypto.db`。
|
||||
- 你已明确:**方向、止损价、补仓区间边界价、止盈价、杠杆**,并接受程序按风险预算拆分 **首仓 50% + 多档补仓 50%**。
|
||||
|
||||
---
|
||||
|
||||
## 2. 名词与参数
|
||||
|
||||
| 名称 | 含义 |
|
||||
|------|------|
|
||||
| **合约 USDT 可用余额** | **生成预览**时通过 API 读取的 **swap 账户 USDT `free`** 快照;**确认执行**时再次读取并与快照比对偏差。 |
|
||||
| **风险比例** | 默认 **5%**:指「若整笔计划在 **补仓区间远侧边界**(做多=上沿、做空=下沿)这一侧的最坏价格结构下触及止损」,目标亏损上限约为 **可用余额快照 × 风险比例**(实现上用 `calc_risk_fraction` 与 `prepare_order_amount` 反推总张数,受交易所最小张数与精度约束)。 |
|
||||
| **止损价** | 用户填写;开仓后挂 **交易所仓位类止损触发单**(全平)。 |
|
||||
| **补仓区间边界**(库字段 `add_upper`) | 用户填写;**仅在该价位与止损价构成的区间内** 才允许程序触发剩余 50% 的市价补仓。**界面文案**:做多显示「补仓上沿」,做空显示「补仓下沿」。校验:做多 `止损 < 边界价`;做空 `止损 > 边界价`。 |
|
||||
| **止盈价** | 用户填写的 **固定价格**;**不由交易所条件止盈单触发**,由应用后台 **按标记价/行情价轮询**,达到后 **市价全平**。 |
|
||||
| **杠杆** | 计划内固定写入;用于 `set_leverage` 与名义换算。 |
|
||||
| **补仓档位数** | 默认 **5** 档(环境变量 `TREND_PULLBACK_DCA_LEGS` 可调);程序在满足最小张数前提下可能 **自动减少档数**。 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 执行流程(时间顺序)
|
||||
|
||||
### 3.0 列表时间窗(交易记录 / 计划历史)
|
||||
|
||||
- **交易记录**、**计划历史**(含预览快照)列表与 **交易记录 CSV 导出** 支持 **UTC** 时间筛选(默认 UTC 当日;可选近 24h、近 7d、自定义起止)。
|
||||
- 查询参数:`win_preset`(`utc_today` / `utc_last24h` / `utc_last7d` / `custom`)、自定义时另传 `from_utc`、`to_utc`。
|
||||
- **统计分析**页仍按北京时间 `TRADING_DAY_RESET_HOUR` 切日,不受列表窗影响。
|
||||
|
||||
### 3.1 预览阶段(不下单)
|
||||
|
||||
1. **风控**:与「机器人下单监控」**互斥**——存在活跃机器人持仓或运行中趋势计划时,不可生成预览。
|
||||
2. **读取可用余额快照** `get_available_trading_usdt()`,失败则拒绝。
|
||||
3. **计算**(写入表 `trend_pullback_previews`,并跳转带 `preview_id`):
|
||||
- 在 **补仓区间边界 ↔ 止损** 区间内生成 `N` 个补仓触发价(做多从上沿向止损、做空从下沿向止损);
|
||||
- 将 **剩余 50% 计划张数** 拆成 `N` 份写入 `leg_amounts_json`。
|
||||
4. **预览有效期**:默认 **120 秒**(`TREND_PULLBACK_PREVIEW_TTL_SECONDS`),超时须重新点「生成预览」。
|
||||
|
||||
### 3.2 确认执行(实盘)
|
||||
|
||||
5. 再次校验:预览未过期;**当前可用余额**与预览快照相对偏差 ≤ `TREND_PREVIEW_MAX_BALANCE_DRIFT_PCT`(默认 **5%**),否则拒绝执行并要求重新预览。
|
||||
6. **首仓**:**立即市价** 开立 **总计划张数 × 50%**(不附带交易所止盈单)。
|
||||
7. **止损**:撤销旧条件单后,挂 **仅止损** 的仓位触发单;之后每次补仓成交会 **刷新** 止损挂单。
|
||||
7b. **保本移交下单监控**(可选):首仓完成且交易所有持仓后,可点击「保本移交下单监控」——将止损移至 **持仓均价 ± 偏移%**(默认 **+0.3%** 多 / **−0.3%** 空),仅当新止损 **优于** 当前止损时生效;**本次趋势计划随即结束**,持仓写入 **下单监控**(备注 **趋势回调计划**),交易所在 **同一时刻挂保本止损 + 计划止盈**;后续无论中控平仓或交易所手动平仓,均经下单监控轮询 **`reconcile_external_closes` / `check_order_monitors`** 写入 **交易记录**(含 `trend_plan_id`、开仓类型「趋势回调」),供人工核对。
|
||||
8. **补仓**:当价格 **穿越** 下一档触发价(做多为自上向下穿越,做空为自下向上穿越)时,按该档张数 **市价加仓**;直至 `N` 档执行完毕或计划结束。
|
||||
9. **止盈监控**:后台线程若发现价格触及止盈,则 **市价全平**。
|
||||
10. **止损触发**:若仓位被交易所止损打光,本地检测到 **持仓为 0** 后记账为 **止损** 并结束计划。
|
||||
11. **计划结束**:任一结束路径(止盈 / 止损 / 用户手动结束)均会 **撤单**(条件单 + 普通挂单,尽力而为)。
|
||||
|
||||
### 3.3 取消预览
|
||||
|
||||
用户可「取消预览」删除 `trend_pullback_previews` 中对应记录;过期记录会在新预览或页面加载时清理。
|
||||
|
||||
### 3.4 界面:计划历史与运行中浮动盈亏
|
||||
|
||||
- **计划历史(页顶卡片)**
|
||||
- 仅展示 **`trend_pullback_plans` 中已结束的计划**(`status != 'active'`,如止盈结束、止损结束、手动结束)。
|
||||
- **不包含**仅存在于 `trend_pullback_previews`、从未「确认执行」的预览。
|
||||
- 每行提供 **删除**:删除该计划行,并删除 `trade_records` 中 **`trend_plan_id` 与之相同** 且类型为「趋势回调」的记录(用于与计划一一对应的新数据;历史旧行若无 `trend_plan_id` 则不会随删)。
|
||||
- **运行中的计划(交易执行页)**
|
||||
- 在计划摘要下方展示 **浮盈亏(交易所)**:来自 Gate 当前持仓接口的 **未实现盈亏**(及标记价,若可得);与本地按均价估算可能略有差异,以交易所为准便于对照。
|
||||
- **补仓边界**按方向显示「补仓上沿」或「补仓下沿」(数值仍为 `add_upper` 字段)。
|
||||
- **手动保本**:表单可改偏移 %(默认见 `TREND_PULLBACK_MANUAL_BREAKEVEN_OFFSET_PCT`);成功后显示「已保本」时间与原止损(若与当前不同)。
|
||||
|
||||
### 3.5 交易记录与交易所「已实现盈亏」对齐
|
||||
|
||||
- 平仓时仍会写入一条 **`trade_records`**(`monitor_type=趋势回调`),其中的 **`pnl_amount` 等为本地估算**(`calc_pnl`,不含手续费、资金费等完整账单口径)。
|
||||
- 打开 **「交易执行」或「交易记录」** 页面时,若已配置 **`GATE_API_KEY` / `GATE_API_SECRET`**(不要求 `LIVE_TRADING_ENABLED=true`,只读即可),应用会按节流策略(同进程约 **25 秒**内最多一次)调用 Gate **`fetch_positions_history`(平仓历史)**,为尚未写入 `exchange_sync_key` 的趋势回调记录 **匹配一条平仓记录**,并回填:
|
||||
- **`exchange_realized_pnl`**:交易所口径已实现盈亏(与 App「历史仓位」更接近);
|
||||
- **`exchange_opened_at` / `exchange_closed_at`**:换算为应用时区(默认北京)下的开、平时间字符串。
|
||||
- **交易记录表**展示列「开仓(展示) / 平仓(展示) / 盈亏U(展示)」:对「趋势回调」行,若已同步则优先显示交易所字段(界面小字 **「所」**);未同步前仍显示本地复盘字段(小字 **「估」**)。
|
||||
- 匹配规则概要:同品种、同方向、平仓时间与本地 `closed_at` 接近,并结合 **`trend_plan_id`** 对应计划的 `opened_at` 收窄时间窗;极端情况下若短时间多笔同向同品种,仍存在错配可能,可对照 `exchange_sync_key` 与交易所记录。
|
||||
|
||||
---
|
||||
|
||||
## 4. 与「机器人下单监控」的差异
|
||||
|
||||
| 项目 | 机器人下单监控 | 趋势回调 |
|
||||
|------|------------------|----------|
|
||||
| 开仓 | 单次市价 + 条件止盈+止损 | 首仓 50% 市价 + 多档补仓 + **仅止损在交易所** |
|
||||
| 止盈 | 条件单 + 本地监控 | **仅本地监控市价止盈** |
|
||||
| 仓位基数 | 以损定仓(表单/会话基数) | **可用余额快照 × 风险比例** 推导 |
|
||||
| 移动保本 | 支持(按 R 自动上移) | **保本移交**(结束计划→下单监控;交易所 TP+SL;**无**自动 R 保本) |
|
||||
|
||||
---
|
||||
|
||||
## 5. 风险声明(必读)
|
||||
|
||||
- 市价单存在 **滑点**;极端行情下实际亏损可能 **大于** 理论 5%。
|
||||
- 补仓触发依赖应用 **轮询间隔**(`MONITOR_POLL_SECONDS`),非毫秒级高频。
|
||||
- 交易所 **最小张数 / 精度** 可能导致计划张数被截断,实际风险略低于或偏离纸面计算。
|
||||
- 请使用 **单独 API Key / 子账户**,并先在 `LIVE_TRADING_ENABLED=false` 环境验证流程(若需沙盒请自行对接测试网,本仓库默认实盘接口)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 相关环境变量
|
||||
|
||||
| 变量 | 说明 | 默认 |
|
||||
|------|------|------|
|
||||
| `TREND_PULLBACK_MANUAL_BREAKEVEN_OFFSET_PCT` | 手动保本默认偏移(相对持仓均价,%) | `0.3` |
|
||||
| `TREND_PULLBACK_DCA_LEGS` | 剩余 50% 拆档数量上限 | `5` |
|
||||
| `TREND_PULLBACK_PREVIEW_TTL_SECONDS` | 预览有效时间(秒) | `120` |
|
||||
| `TREND_PREVIEW_MAX_BALANCE_DRIFT_PCT` | 确认执行时允许「当前可用 / 预览快照」最大相对偏差(%) | `5` |
|
||||
| `MONITOR_POLL_SECONDS` | 监控轮询间隔(秒) | `3` |
|
||||
| `LIVE_TRADING_ENABLED` | 是否允许真实下单 | `false` |
|
||||
| `FULL_MARGIN_BUFFER_RATIO` | 计划保证金相对可用余额上限比例 | `0.98` |
|
||||
| `APP_TIMEZONE` | 应用墙钟与「北京日期」同步起点时区(如 `Asia/Shanghai`) | `Asia/Shanghai` |
|
||||
| `EXCHANGE_POSITION_SYNC_FROM_BJ` | 拉取 Gate **平仓历史** 的最早日期(`YYYY-MM-DD`,按 `APP_TIMEZONE` 当日 **00:00** 起算)。**留空**则从近 **90 天** 起拉取 | 空 |
|
||||
| `EXCHANGE_POSITION_HISTORY_LIMIT` | 单次拉取平仓历史条数上限(50–1000) | `200` |
|
||||
|
||||
---
|
||||
|
||||
## 7. 数据库
|
||||
|
||||
- **`trend_pullback_previews`**:未执行的预览行(含 `expires_at_ms`),执行成功或取消后删除;过期可被清理。
|
||||
- **`trend_pullback_plans`**:趋势回调计划。执行后写入一行,`status='active'` 表示运行中;止盈 / 止损 / 手动结束后变为 **`stopped_tp` / `stopped_sl` / `stopped_manual`** 等非 `active` 状态,并出现在页顶 **计划历史**。字段含快照可用余额、计划保证金、总张数、首仓张数、补仓 JSON、网格价 JSON、已补仓档数、均价、`opened_at`、`message`(结束说明)等;**`add_upper`** 存补仓区间远侧边界价(做多=上沿、做空=下沿)。
|
||||
- **`trade_records`**(`monitor_type=趋势回调`):每次计划结束插入一行;含本地估算盈亏等。新写入行带 **`trend_plan_id`** 指向 `trend_pullback_plans.id`。另含 **`exchange_realized_pnl`、`exchange_opened_at`、`exchange_closed_at`、`exchange_sync_key`**,由页面触发的交易所平仓历史同步填充(见 3.5)。
|
||||
|
||||
**CSV 导出**:交易记录导出为 **v3**,包含上述交易所对齐字段及 `trend_plan_id`。
|
||||
@@ -1,339 +0,0 @@
|
||||
# `crypto_monitor_gate_bot` 部署指南:SSH SOCKS + Gate.io + PM2(Ubuntu)
|
||||
|
||||
Ubuntu 环境总览见 **[docs/ubuntu-server.md](../docs/ubuntu-server.md)**。
|
||||
|
||||
本文面向:**在本机运行本项目**,但 **直连 Gate.io API 不稳定或被重置** 的场景。思路是:
|
||||
|
||||
- 本机用 `ssh -D` 做动态转发,把 **SOCKS5 出口**放到能正常访问 Gate 的机器(常见为一台境外 VPS)
|
||||
- 项目在 `.env` 中设置 **`GATE_SOCKS_PROXY=socks5h://127.0.0.1:1080`**(或你实际端口),`ccxt` 经 SOCKS 访问交易所
|
||||
- **SSH 隧道**:用 `ssh -D` 在本机常驻(可用 **tmux** 或 **autossh** 保持连接),**不要** 把 `ssh` 交给 PM2
|
||||
- 使用 **PM2** 仅托管 **Flask 应用**;仓库根目录 **`ecosystem.config.cjs`** 只定义 `crypto-monitor-gate`
|
||||
|
||||
> 安全提醒:不要把 `.env`、私钥 `.pem`、Gate API Key 提交到 Git;下文只用占位符。
|
||||
|
||||
---
|
||||
|
||||
## 0. 你需要准备的东西
|
||||
|
||||
- 一台 **Ubuntu**(或同类 Linux)运行项目的机器(下文称「本机」)
|
||||
- 一台可 SSH 登录、且 **能正常访问 Gate.io API** 的 VPS(示例:`HostName` 填你的服务器 IP,用户如 `root`)
|
||||
- SSH:**私钥登录**(推荐,便于隧道脚本无人值守)
|
||||
- 本机已安装:`python3`、`python3-venv`、`pip`、`curl`、`ssh`、`git`(可选)、`node` + `npm`(安装 PM2)
|
||||
|
||||
---
|
||||
|
||||
## 1. 获取代码与目录
|
||||
|
||||
将包含 `app.py` 的项目放到固定目录,例如:
|
||||
|
||||
```bash
|
||||
mkdir -p /opt/crypto_monitor
|
||||
cd /opt/crypto_monitor
|
||||
git clone https://git.bz121.com/dekun/crypto_monitor.git
|
||||
cd crypto_monitor/crypto_monitor_gate_bot
|
||||
```
|
||||
|
||||
下文用 **`/opt/crypto_monitor/crypto_monitor_gate_bot`** 仅为示例,请换成你的实际绝对路径。
|
||||
|
||||
拉取代码后,若目录下尚无 `.env`:
|
||||
|
||||
```bash
|
||||
cp -n .env.example .env
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 配置 SSH 私钥与 `~/.ssh/config`
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
# 私钥示例:~/.ssh/vps1.pem
|
||||
chmod 600 ~/.ssh/vps1.pem
|
||||
```
|
||||
|
||||
编辑 `~/.ssh/config`(示例别名 **`gate-vps`**,与你手工启动 `ssh -D ... gate-vps` 一致即可):
|
||||
|
||||
```sshconfig
|
||||
Host gate-vps
|
||||
HostName 你的_VPS_IP
|
||||
User root
|
||||
IdentityFile ~/.ssh/vps1.pem
|
||||
IdentitiesOnly yes
|
||||
ServerAliveInterval 30
|
||||
ServerAliveCountMax 3
|
||||
ExitOnForwardFailure yes
|
||||
BatchMode yes
|
||||
```
|
||||
|
||||
测试:
|
||||
|
||||
```bash
|
||||
ssh gate-vps true
|
||||
```
|
||||
|
||||
> 若尚未完全改为密钥登录,可暂时注释 `BatchMode yes`,调试完成后再打开。
|
||||
|
||||
---
|
||||
|
||||
## 3. 手工验证:SSH SOCKS + Gate API
|
||||
|
||||
### 3.1 本地 SOCKS(示例端口 1080)
|
||||
|
||||
```bash
|
||||
ssh -N -D 127.0.0.1:1080 gate-vps
|
||||
```
|
||||
|
||||
保持运行,另开终端继续。
|
||||
|
||||
### 3.2 验证经 SOCKS 可访问 Gate
|
||||
|
||||
```bash
|
||||
curl -4 -sS --max-time 15 --proxy socks5h://127.0.0.1:1080 https://api.gateio.ws/api/v4/spot/time
|
||||
```
|
||||
|
||||
应返回 JSON(含服务器时间字段)。若此处失败,**不要先启动应用**:先修隧道或 VPS 出站。
|
||||
|
||||
---
|
||||
|
||||
## 4. Python 虚拟环境
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate_bot
|
||||
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
python -m pip install -U pip
|
||||
pip install flask requests ccxt werkzeug PySocks Pillow
|
||||
```
|
||||
|
||||
走 SOCKS 时 **必须** 安装 **`PySocks`**,否则易出现代理相关报错。
|
||||
|
||||
可选:
|
||||
|
||||
```bash
|
||||
export PYTHONDONTWRITEBYTECODE=1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 配置环境变量(`.env.example` → `.env`)
|
||||
|
||||
| 文件 | 是否进 Git | 说明 |
|
||||
|------|------------|------|
|
||||
| **`.env.example`** | ✅ 是 | 变量模板与注释,可随 `git pull` 更新 |
|
||||
| **`.env`** | ❌ 否 | 本机真实配置;`app.py` **只读此文件** |
|
||||
|
||||
### 5.1 首次配置
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate_bot
|
||||
|
||||
cp -n .env.example .env
|
||||
nano .env
|
||||
```
|
||||
|
||||
### 5.2 备份与 `git pull`
|
||||
|
||||
- **`.env` 不在 Git 中**:`git pull` **不会**覆盖本地 `.env`。
|
||||
- 远端若更新 **`.env.example`**,pull 后请**手动**把新增变量补进你的 `.env`。
|
||||
- **升级前备份**:`cp .env .env.backup.$(date +%Y%m%d)`;恢复:`cp .env.backup.YYYYMMDD .env`。
|
||||
- **换机**:`scp` 复制 `.env`,或新机 `cp .env.example .env` 后重填。
|
||||
|
||||
### 5.3 AI 复盘与模型(可选)
|
||||
|
||||
共用根目录 **`ai_client.py`**(`PYTHONPATH=..`)。`.env` 默认 **`AI_PROVIDER=openai`** + `OPENAI_API_BASE` / `OPENAI_API_KEY` / `OPENAI_MODEL`;或 **`ollama`** + `OLLAMA_API` / `AI_MODEL`。详见 **[AI复盘与模型配置说明.md](../AI复盘与模型配置说明.md)**。
|
||||
|
||||
### 5.4 自动备份(数据库 + 复盘图片)
|
||||
|
||||
每天 **北京时间 0:00** 备份到 **`/root/backups`**,保留 **30 天**(`crypto.db` + `static/images`)。
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate_bot
|
||||
chmod +x scripts/backup_data.sh scripts/install_backup_cron.sh
|
||||
bash scripts/install_backup_cron.sh
|
||||
bash scripts/backup_data.sh # 试跑
|
||||
```
|
||||
|
||||
备份目录:`/root/backups/crypto_monitor_gate_bot/YYYY-MM-DD/`。与 Binance / Gate 实例规则相同,详见 `crypto_monitor_binance/部署文档.md` 第 5.4 节(恢复步骤、可选 `.env` 变量)。
|
||||
|
||||
若服务器同时跑 **binance、gate、gate_bot** 三个实例,请在**各自项目目录**各执行一次 `install_backup_cron.sh`。
|
||||
|
||||
### 5.4 必填项检查(Gate + 代理)
|
||||
|
||||
与交易所相关的变量必须是 **Gate** 前缀(**不要**再写 OKX 变量,否则代理不会生效、密钥也不会被识别)。至少确认:
|
||||
|
||||
```env
|
||||
APP_HOST=127.0.0.1
|
||||
APP_PORT=5000
|
||||
|
||||
# 实盘(按需)
|
||||
LIVE_TRADING_ENABLED=false
|
||||
GATE_API_KEY=你的_Key
|
||||
GATE_API_SECRET=你的_Secret
|
||||
|
||||
# 经本机 SSH 动态转发访问 Gate(端口与隧道一致)
|
||||
GATE_SOCKS_PROXY=socks5h://127.0.0.1:1080
|
||||
|
||||
# 若不用 SOCKS,可改用 HTTP 代理(一般二选一)
|
||||
# GATE_HTTP_PROXY=http://127.0.0.1:7890
|
||||
# GATE_HTTPS_PROXY=http://127.0.0.1:7890
|
||||
```
|
||||
|
||||
说明:**推荐 `socks5h://`**,由 SOCKS 端解析域名,与 `curl --proxy socks5h://...` 行为一致。
|
||||
|
||||
### 5.4 趋势回调策略(可选)
|
||||
|
||||
若使用「交易执行」页的 **趋势回调** 计划:
|
||||
|
||||
- 详细规则见项目根目录 **`趋势回调策略说明.md`**。
|
||||
- **两阶段**:先「生成预览」(默认 **120 秒**内有效),再「确认执行」;执行时若可用余额与预览快照偏差超过 **5%** 会拒绝(可调 `.env`)。
|
||||
- 补仓档位数默认 **5**,预览有效期与余额偏差阈值可在 `.env` 覆盖:
|
||||
|
||||
```env
|
||||
TREND_PULLBACK_DCA_LEGS=5
|
||||
TREND_PULLBACK_PREVIEW_TTL_SECONDS=120
|
||||
TREND_PREVIEW_MAX_BALANCE_DRIFT_PCT=5
|
||||
```
|
||||
|
||||
- **生成预览**与**确认执行**时都会读取 **Gate 永续账户 USDT 可用余额**;请尽量使用 **单独子账户** 承载策略资金。
|
||||
|
||||
**界面与对账(与策略说明 3.4–3.5 节一致)**
|
||||
|
||||
- 页顶 **计划历史**:仅 **已结束** 的趋势计划(不含未执行预览);可 **删除** 计划行,并删除 `trend_plan_id` 关联的「趋势回调」`trade_records`(新数据;旧行无 `trend_plan_id` 不级联)。
|
||||
- **运行中计划**展示交易所 **未实现盈亏**(浮盈亏)。
|
||||
- **交易记录**:趋势单在配置 API Key 后,打开「交易执行 / 交易记录」页会按节流(约 **25 秒**内同进程最多一次)拉取 Gate **平仓历史**,回填 **`exchange_realized_pnl`** 等;列表展示优先用交易所口径(见策略说明)。
|
||||
|
||||
**与交易所对齐的可选环境变量**
|
||||
|
||||
```env
|
||||
# 平仓历史同步起点:北京日期 YYYY-MM-DD 的 0 点(与 APP_TIMEZONE 一致);留空则从近 90 天拉取
|
||||
# EXCHANGE_POSITION_SYNC_FROM_BJ=2026-05-14
|
||||
# EXCHANGE_POSITION_HISTORY_LIMIT=200
|
||||
```
|
||||
|
||||
说明:同步 **只读** 交易所接口,**不要求** `LIVE_TRADING_ENABLED=true`;无 Key 时不拉取,界面仍可用(浮盈亏可能为「—」、交易记录仍为本地「估」)。
|
||||
|
||||
**交易记录 CSV**:导出为 **v3**,含 `trend_plan_id` 与交易所对齐列(详见策略说明数据库一节)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 手工启动 Flask(验证)
|
||||
|
||||
1. SOCKS 已监听 `127.0.0.1:1080`
|
||||
2. 已 `source .venv/bin/activate`
|
||||
3. `.env` 已含 `GATE_SOCKS_PROXY`
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate_bot
|
||||
source .venv/bin/activate
|
||||
python app.py
|
||||
```
|
||||
|
||||
浏览器访问:`http://127.0.0.1:5000`(或你在 `.env` 中的端口)。
|
||||
|
||||
---
|
||||
|
||||
## 7. 安装 PM2
|
||||
|
||||
```bash
|
||||
sudo npm i -g pm2
|
||||
pm2 -v
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. PM2:使用仓库内 `ecosystem.config.cjs`(推荐)
|
||||
|
||||
在项目根目录:
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate_bot
|
||||
pm2 start ecosystem.config.cjs
|
||||
pm2 status
|
||||
pm2 logs --lines 200
|
||||
```
|
||||
|
||||
默认只启动 **`crypto-monitor-gate`**(`.venv/bin/python app.py`)。
|
||||
|
||||
### 本机已可直连 Gate、不需要隧道时
|
||||
|
||||
`.env` 里应 **去掉或留空** `GATE_SOCKS_PROXY`(除非仍要走别的代理),再 `pm2 start ecosystem.config.cjs`。
|
||||
|
||||
### 开机自启
|
||||
|
||||
```bash
|
||||
pm2 save
|
||||
pm2 startup
|
||||
# 按屏幕提示执行一条 sudo 命令
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 等价手工命令(不使用 ecosystem 文件时)
|
||||
|
||||
### 9.1 SSH SOCKS(自行后台常驻,不推荐用 PM2)
|
||||
|
||||
示例(前台调试;生产请用 **PM2**,见本文与 [docs/ubuntu-server.md](../docs/ubuntu-server.md)):
|
||||
|
||||
```bash
|
||||
ssh -N -D 127.0.0.1:1080 gate-vps \
|
||||
-o ServerAliveInterval=30 -o ServerAliveCountMax=3 \
|
||||
-o ExitOnForwardFailure=yes
|
||||
```
|
||||
|
||||
### 9.2 Flask
|
||||
|
||||
```bash
|
||||
cd /opt/crypto_monitor/crypto_monitor_gate_bot
|
||||
pm2 start /opt/crypto_monitor/crypto_monitor_gate_bot/.venv/bin/python --name crypto-monitor-gate -- \
|
||||
/opt/crypto_monitor/crypto_monitor_gate_bot/app.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 交易所「连接不上」排查清单
|
||||
|
||||
1. **`.env` 是否为 Gate 变量**:必须是 `GATE_SOCKS_PROXY` / `GATE_API_KEY` / `GATE_API_SECRET`,不是 OKX。
|
||||
2. **隧道是否在本机端口监听**(若配置了 `GATE_SOCKS_PROXY`):
|
||||
```bash
|
||||
ss -lntp | grep 1080 || true
|
||||
```
|
||||
3. **curl 复测 Gate**(与第 3.2 节相同);curl 不通则应用也不会通。
|
||||
4. **PySocks**:`pip show PySocks`,缺失则 `pip install PySocks`。
|
||||
5. **SSH 隧道连不上**:检查私钥权限、`~/.ssh/config`、VPS 出站与端口是否与 `.env` 一致。
|
||||
6. **启动顺序**:先保证 SOCKS 已监听,再 `pm2 start` 应用(或重启应用)。
|
||||
|
||||
---
|
||||
|
||||
## 11. 推荐启动顺序(习惯)
|
||||
|
||||
1. 若走代理:先启动并确认 SSH SOCKS 已监听,再 `curl --proxy socks5h://127.0.0.1:1080 https://api.gateio.ws/api/v4/spot/time` 成功
|
||||
2. `pm2 start ecosystem.config.cjs`
|
||||
3. 再确认页面与余额等接口正常
|
||||
|
||||
---
|
||||
|
||||
## 12. 免责声明
|
||||
|
||||
交易所有合规与地区政策要求。请确保使用方式符合当地法律法规与交易所条款。本文仅描述网络与工程部署路径。
|
||||
|
||||
---
|
||||
|
||||
## 附录:数据库标签修复脚本 `scripts/fix_breakeven_labels.py`
|
||||
|
||||
在 Ubuntu 上:
|
||||
|
||||
1)预览(不写库):
|
||||
|
||||
```bash
|
||||
python scripts/fix_breakeven_labels.py --db ./crypto.db --dry-run
|
||||
```
|
||||
|
||||
2)确认后执行:
|
||||
|
||||
```bash
|
||||
python scripts/fix_breakeven_labels.py --db ./crypto.db --apply
|
||||
```
|
||||
|
||||
默认修复条件:`monitor_type='下单监控'` 且 `result='止损'` 且 `pnl_amount > 0` → 改为 `result='保本止盈'`。
|
||||