deeptrade-quant 0.1.0__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/PKG-INFO +23 -7
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/README.md +22 -6
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/__init__.py +1 -1
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/core/notifier.py +3 -2
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/pyproject.toml +1 -1
- deeptrade_quant-0.1.0/deeptrade/channels_builtin/stdout/deeptrade_plugin.yaml +0 -25
- deeptrade_quant-0.1.0/deeptrade/channels_builtin/stdout/migrations/20260509_001_init.sql +0 -13
- deeptrade_quant-0.1.0/deeptrade/channels_builtin/stdout/stdout_channel/channel.py +0 -180
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/__init__.py +0 -0
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/deeptrade_plugin.yaml +0 -83
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/limit_up_board/__init__.py +0 -0
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/limit_up_board/calendar.py +0 -65
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/limit_up_board/cli.py +0 -269
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/limit_up_board/config.py +0 -76
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/limit_up_board/data.py +0 -1191
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/limit_up_board/pipeline.py +0 -869
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/limit_up_board/plugin.py +0 -30
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/limit_up_board/profiles.py +0 -85
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/limit_up_board/prompts.py +0 -485
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/limit_up_board/render.py +0 -890
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/limit_up_board/runner.py +0 -1087
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/limit_up_board/runtime.py +0 -164
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/limit_up_board/schemas.py +0 -178
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/migrations/20260509_001_init.sql +0 -188
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/volume_anomaly/__init__.py +0 -0
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/volume_anomaly/deeptrade_plugin.yaml +0 -53
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/volume_anomaly/migrations/20260509_001_init.sql +0 -111
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/volume_anomaly/volume_anomaly/__init__.py +0 -0
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/volume_anomaly/volume_anomaly/calendar.py +0 -52
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/volume_anomaly/volume_anomaly/cli.py +0 -246
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/volume_anomaly/volume_anomaly/data.py +0 -2157
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/volume_anomaly/volume_anomaly/pipeline.py +0 -327
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/volume_anomaly/volume_anomaly/plugin.py +0 -22
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/volume_anomaly/volume_anomaly/profiles.py +0 -49
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/volume_anomaly/volume_anomaly/prompts.py +0 -187
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/volume_anomaly/volume_anomaly/prompts_examples.py +0 -84
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/volume_anomaly/volume_anomaly/render.py +0 -906
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/volume_anomaly/volume_anomaly/runner.py +0 -772
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/volume_anomaly/volume_anomaly/runtime.py +0 -84
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/volume_anomaly/volume_anomaly/schemas.py +0 -97
- deeptrade_quant-0.1.0/deeptrade/strategies_builtin/volume_anomaly/volume_anomaly/stats.py +0 -174
- deeptrade_quant-0.1.0/tests/__init__.py +0 -0
- deeptrade_quant-0.1.0/tests/cli/__init__.py +0 -0
- deeptrade_quant-0.1.0/tests/core/__init__.py +0 -0
- deeptrade_quant-0.1.0/tests/plugins_api/__init__.py +0 -0
- deeptrade_quant-0.1.0/tests/strategies_builtin/__init__.py +0 -0
- deeptrade_quant-0.1.0/tests/strategies_builtin/limit_up_board/__init__.py +0 -0
- deeptrade_quant-0.1.0/tests/strategies_builtin/limit_up_board/test_phase_a_factors.py +0 -250
- deeptrade_quant-0.1.0/tests/strategies_builtin/limit_up_board/test_phase_b_factors.py +0 -164
- deeptrade_quant-0.1.0/tests/strategies_builtin/limit_up_board/test_v04_settings.py +0 -150
- deeptrade_quant-0.1.0/tests/strategies_builtin/volume_anomaly/__init__.py +0 -0
- deeptrade_quant-0.1.0/tests/strategies_builtin/volume_anomaly/test_alpha_features.py +0 -201
- deeptrade_quant-0.1.0/tests/strategies_builtin/volume_anomaly/test_candidate_features.py +0 -343
- deeptrade_quant-0.1.0/tests/strategies_builtin/volume_anomaly/test_dimension_scores.py +0 -128
- deeptrade_quant-0.1.0/tests/strategies_builtin/volume_anomaly/test_prompt_consistency.py +0 -185
- deeptrade_quant-0.1.0/tests/strategies_builtin/volume_anomaly/test_realized_returns.py +0 -165
- deeptrade_quant-0.1.0/tests/strategies_builtin/volume_anomaly/test_screen_rules.py +0 -224
- deeptrade_quant-0.1.0/tests/strategies_builtin/volume_anomaly/test_stats_query.py +0 -166
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/.gitignore +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/LICENSE +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/cli.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/cli_config.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/cli_data.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/cli_plugin.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/core/__init__.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/core/config.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/core/config_migrations.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/core/db.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/core/github_fetch.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/core/llm_client.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/core/llm_manager.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/core/logging_config.py +0 -0
- {deeptrade_quant-0.1.0/deeptrade/channels_builtin → deeptrade_quant-0.2.0/deeptrade/core/migrations}/__init__.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/core/migrations/core/20260509_001_init.sql +0 -0
- {deeptrade_quant-0.1.0/deeptrade/channels_builtin/stdout → deeptrade_quant-0.2.0/deeptrade/core/migrations/core}/__init__.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/core/paths.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/core/plugin_manager.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/core/plugin_source.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/core/registry.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/core/run_status.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/core/secrets.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/core/tushare_client.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/plugins_api/__init__.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/plugins_api/base.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/plugins_api/channel.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/plugins_api/events.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/plugins_api/llm.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/plugins_api/metadata.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/plugins_api/notify.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/deeptrade/theme.py +0 -0
- {deeptrade_quant-0.1.0/deeptrade/channels_builtin/stdout/stdout_channel → deeptrade_quant-0.2.0/tests}/__init__.py +0 -0
- {deeptrade_quant-0.1.0/deeptrade/core/migrations → deeptrade_quant-0.2.0/tests/cli}/__init__.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/cli/test_config_cmd.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/cli/test_plugin_cmd.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/cli/test_routing.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/conftest.py +0 -0
- {deeptrade_quant-0.1.0/deeptrade/core/migrations → deeptrade_quant-0.2.0/tests}/core/__init__.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/core/test_config.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/core/test_config_migrations.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/core/test_db.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/core/test_github_fetch.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/core/test_llm_client.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/core/test_llm_manager.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/core/test_notifier.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/core/test_paths.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/core/test_plugin_install.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/core/test_plugin_source.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/core/test_plugin_upgrade.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/core/test_registry.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/core/test_secrets.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/core/test_tushare_client.py +0 -0
- {deeptrade_quant-0.1.0/deeptrade/strategies_builtin → deeptrade_quant-0.2.0/tests/plugins_api}/__init__.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/plugins_api/test_notify.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/plugins_api/test_protocol.py +0 -0
- {deeptrade_quant-0.1.0 → deeptrade_quant-0.2.0}/tests/test_smoke.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deeptrade-quant
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: LLM-driven A-share (Shanghai/Shenzhen main board) stock screening CLI
|
|
5
5
|
Project-URL: Homepage, https://github.com/ty19880929/deeptrade
|
|
6
6
|
Project-URL: Repository, https://github.com/ty19880929/deeptrade
|
|
@@ -53,10 +53,18 @@ Description-Content-Type: text/markdown
|
|
|
53
53
|
### 安装
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
|
-
#
|
|
56
|
+
# 推荐:pipx 隔离环境(命令名仍是 deeptrade)
|
|
57
|
+
pipx install deeptrade-quant
|
|
58
|
+
# 或
|
|
59
|
+
uv tool install deeptrade-quant
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
> **注**:PyPI 项目名是 `deeptrade-quant`,CLI 命令是 `deeptrade`,Python 包名是 `deeptrade`(`import deeptrade`)。三者不同是 Python 生态常态(同 `pip install scikit-learn` → `import sklearn`)。
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# 开发模式(克隆本仓库,editable install)
|
|
57
66
|
uv sync --all-extras
|
|
58
67
|
uv run pre-commit install
|
|
59
|
-
|
|
60
68
|
# 兜底(无 uv)
|
|
61
69
|
python -m venv .venv && source .venv/bin/activate # Windows: .\.venv\Scripts\activate
|
|
62
70
|
pip install -e ".[dev]"
|
|
@@ -73,12 +81,18 @@ deeptrade config test-llm # 对所有 provider 做连通性自
|
|
|
73
81
|
deeptrade config show # 表格展示当前配置(密钥脱敏)
|
|
74
82
|
```
|
|
75
83
|
|
|
76
|
-
###
|
|
84
|
+
### 安装官方插件并运行
|
|
85
|
+
|
|
86
|
+
官方插件维护在 [DeepTradePluginOfficial](https://github.com/ty19880929/DeepTradePluginOfficial),框架通过短名查注册表 → 拉 GitHub release tarball 自动安装。
|
|
77
87
|
|
|
78
88
|
```bash
|
|
79
|
-
#
|
|
80
|
-
deeptrade plugin
|
|
81
|
-
|
|
89
|
+
# 浏览注册表
|
|
90
|
+
deeptrade plugin search
|
|
91
|
+
|
|
92
|
+
# 按短名安装(注册表 → 最新 release tag)
|
|
93
|
+
deeptrade plugin install limit-up-board
|
|
94
|
+
deeptrade plugin install volume-anomaly
|
|
95
|
+
deeptrade plugin install stdout-channel
|
|
82
96
|
|
|
83
97
|
deeptrade plugin list # 查看已安装
|
|
84
98
|
|
|
@@ -96,6 +110,8 @@ deeptrade volume-anomaly prune --days 30 # 剔除追踪 ≥30 日的标的
|
|
|
96
110
|
deeptrade stdout-channel test
|
|
97
111
|
```
|
|
98
112
|
|
|
113
|
+
> **第三方插件 / 本地开发**:`deeptrade plugin install ./path/to/my-plugin` 仍可装本地目录;`deeptrade plugin install https://github.com/owner/repo` 装完整 git 仓库(仓库根需含 `deeptrade_plugin.yaml`)。详见 [`docs/plugin-development.md`](docs/plugin-development.md)。
|
|
114
|
+
|
|
99
115
|
报告产出在 `~/.deeptrade/reports/<run_id>/`。
|
|
100
116
|
|
|
101
117
|
## 📦 命令矩阵
|
|
@@ -19,10 +19,18 @@
|
|
|
19
19
|
### 安装
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
#
|
|
22
|
+
# 推荐:pipx 隔离环境(命令名仍是 deeptrade)
|
|
23
|
+
pipx install deeptrade-quant
|
|
24
|
+
# 或
|
|
25
|
+
uv tool install deeptrade-quant
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
> **注**:PyPI 项目名是 `deeptrade-quant`,CLI 命令是 `deeptrade`,Python 包名是 `deeptrade`(`import deeptrade`)。三者不同是 Python 生态常态(同 `pip install scikit-learn` → `import sklearn`)。
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# 开发模式(克隆本仓库,editable install)
|
|
23
32
|
uv sync --all-extras
|
|
24
33
|
uv run pre-commit install
|
|
25
|
-
|
|
26
34
|
# 兜底(无 uv)
|
|
27
35
|
python -m venv .venv && source .venv/bin/activate # Windows: .\.venv\Scripts\activate
|
|
28
36
|
pip install -e ".[dev]"
|
|
@@ -39,12 +47,18 @@ deeptrade config test-llm # 对所有 provider 做连通性自
|
|
|
39
47
|
deeptrade config show # 表格展示当前配置(密钥脱敏)
|
|
40
48
|
```
|
|
41
49
|
|
|
42
|
-
###
|
|
50
|
+
### 安装官方插件并运行
|
|
51
|
+
|
|
52
|
+
官方插件维护在 [DeepTradePluginOfficial](https://github.com/ty19880929/DeepTradePluginOfficial),框架通过短名查注册表 → 拉 GitHub release tarball 自动安装。
|
|
43
53
|
|
|
44
54
|
```bash
|
|
45
|
-
#
|
|
46
|
-
deeptrade plugin
|
|
47
|
-
|
|
55
|
+
# 浏览注册表
|
|
56
|
+
deeptrade plugin search
|
|
57
|
+
|
|
58
|
+
# 按短名安装(注册表 → 最新 release tag)
|
|
59
|
+
deeptrade plugin install limit-up-board
|
|
60
|
+
deeptrade plugin install volume-anomaly
|
|
61
|
+
deeptrade plugin install stdout-channel
|
|
48
62
|
|
|
49
63
|
deeptrade plugin list # 查看已安装
|
|
50
64
|
|
|
@@ -62,6 +76,8 @@ deeptrade volume-anomaly prune --days 30 # 剔除追踪 ≥30 日的标的
|
|
|
62
76
|
deeptrade stdout-channel test
|
|
63
77
|
```
|
|
64
78
|
|
|
79
|
+
> **第三方插件 / 本地开发**:`deeptrade plugin install ./path/to/my-plugin` 仍可装本地目录;`deeptrade plugin install https://github.com/owner/repo` 装完整 git 仓库(仓库根需含 `deeptrade_plugin.yaml`)。详见 [`docs/plugin-development.md`](docs/plugin-development.md)。
|
|
80
|
+
|
|
65
81
|
报告产出在 `~/.deeptrade/reports/<run_id>/`。
|
|
66
82
|
|
|
67
83
|
## 📦 命令矩阵
|
|
@@ -7,8 +7,9 @@ Three layers compose top-down:
|
|
|
7
7
|
└─ ChannelPlugin instances (loaded from type=channel plugins)
|
|
8
8
|
|
|
9
9
|
The framework knows nothing about feishu / dingtalk / wechat-work. Channels
|
|
10
|
-
are delivered as
|
|
11
|
-
|
|
10
|
+
are delivered as ``type: channel`` plugins, installed at runtime through
|
|
11
|
+
``deeptrade plugin install`` from the official registry or any local/git
|
|
12
|
+
source. New channels = new plugin packages, zero framework change.
|
|
12
13
|
|
|
13
14
|
Top-level API (used by any plugin that needs to notify):
|
|
14
15
|
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
plugin_id: stdout-channel
|
|
2
|
-
name: Stdout Channel
|
|
3
|
-
version: 0.1.0
|
|
4
|
-
type: channel
|
|
5
|
-
api_version: "1"
|
|
6
|
-
entrypoint: stdout_channel.channel:StdoutChannel
|
|
7
|
-
description: Reference notification channel — fully consumes the payload but only prints "✔ push success" to stdout.
|
|
8
|
-
author: DeepTrade
|
|
9
|
-
|
|
10
|
-
permissions:
|
|
11
|
-
tushare_apis:
|
|
12
|
-
required: []
|
|
13
|
-
optional: []
|
|
14
|
-
llm: false
|
|
15
|
-
llm_tools: false
|
|
16
|
-
|
|
17
|
-
migrations:
|
|
18
|
-
- version: "20260509_001"
|
|
19
|
-
file: migrations/20260509_001_init.sql
|
|
20
|
-
checksum: "sha256:7317d23d4ac91b9a1259e2ba4d990863491de8fe1115e19052b02f83939399cc"
|
|
21
|
-
|
|
22
|
-
tables:
|
|
23
|
-
- name: stdout_channel_log
|
|
24
|
-
description: Audit log of payloads delivered through the stdout channel
|
|
25
|
-
purge_on_uninstall: true
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
-- stdout channel: delivery log so we can verify the payload was actually
|
|
2
|
-
-- consumed (not just acknowledged with a fake "✔ push success").
|
|
3
|
-
CREATE TABLE IF NOT EXISTS stdout_channel_log (
|
|
4
|
-
delivered_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
5
|
-
plugin_id VARCHAR NOT NULL,
|
|
6
|
-
run_id UUID NOT NULL,
|
|
7
|
-
status VARCHAR NOT NULL,
|
|
8
|
-
title VARCHAR NOT NULL,
|
|
9
|
-
section_count INTEGER NOT NULL,
|
|
10
|
-
item_count INTEGER NOT NULL,
|
|
11
|
-
metric_count INTEGER NOT NULL,
|
|
12
|
-
PRIMARY KEY (run_id, plugin_id, delivered_at)
|
|
13
|
-
);
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
"""Stdout reference channel plugin.
|
|
2
|
-
|
|
3
|
-
Implements the framework's ``ChannelPlugin`` Protocol:
|
|
4
|
-
* ``validate_static`` — install-time self-check (no network)
|
|
5
|
-
* ``dispatch(argv)`` — CLI dispatch (subcommands: test, log)
|
|
6
|
-
* ``push(ctx, payload)`` — receive a NotificationPayload from the notifier
|
|
7
|
-
|
|
8
|
-
Behaviour on push:
|
|
9
|
-
* FULLY consume the NotificationPayload (walk every section/item/metric)
|
|
10
|
-
so any structural bug surfaces immediately.
|
|
11
|
-
* Persist a one-row audit record to ``stdout_channel_log``.
|
|
12
|
-
* Emit ONE concise line: "✔ push success (...)".
|
|
13
|
-
|
|
14
|
-
This channel is the zero-dependency target for unit tests of the notify
|
|
15
|
-
plumbing and is safe to ship enabled-by-default in dev installs.
|
|
16
|
-
"""
|
|
17
|
-
|
|
18
|
-
from __future__ import annotations
|
|
19
|
-
|
|
20
|
-
import argparse
|
|
21
|
-
import sys
|
|
22
|
-
from typing import TYPE_CHECKING
|
|
23
|
-
|
|
24
|
-
if TYPE_CHECKING: # pragma: no cover
|
|
25
|
-
from deeptrade.plugins_api.base import PluginContext
|
|
26
|
-
from deeptrade.plugins_api.notify import NotificationPayload
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class StdoutChannel:
|
|
30
|
-
"""Stdout-only IM channel plugin."""
|
|
31
|
-
|
|
32
|
-
metadata = None # injected by framework after install
|
|
33
|
-
|
|
34
|
-
# ----- Plugin Protocol -------------------------------------------------
|
|
35
|
-
|
|
36
|
-
def validate_static(self, ctx: PluginContext) -> None: # noqa: ARG002
|
|
37
|
-
# Sanity: the audit table must exist (created by our own migration).
|
|
38
|
-
# If it's missing, the install pipeline already failed; this is just a
|
|
39
|
-
# belt-and-braces self-check that doesn't touch the network.
|
|
40
|
-
return
|
|
41
|
-
|
|
42
|
-
def dispatch(self, argv: list[str]) -> int:
|
|
43
|
-
"""Channel-side CLI: ``test`` and ``log``.
|
|
44
|
-
|
|
45
|
-
``test`` synthesizes a minimal payload and routes it back through this
|
|
46
|
-
channel's own ``push`` so the user can verify the channel is wired up
|
|
47
|
-
without running a real strategy. ``log`` dumps the most recent
|
|
48
|
-
``stdout_channel_log`` rows.
|
|
49
|
-
"""
|
|
50
|
-
parser = argparse.ArgumentParser(
|
|
51
|
-
prog="deeptrade stdout-channel",
|
|
52
|
-
description="Stdout notification channel — local self-test + audit log.",
|
|
53
|
-
)
|
|
54
|
-
sub = parser.add_subparsers(dest="cmd", required=False)
|
|
55
|
-
|
|
56
|
-
sub.add_parser("test", help="Push a synthetic payload through this channel.")
|
|
57
|
-
log_p = sub.add_parser("log", help="Print recent delivery audit rows.")
|
|
58
|
-
log_p.add_argument("--limit", type=int, default=20)
|
|
59
|
-
|
|
60
|
-
args = parser.parse_args(argv)
|
|
61
|
-
if args.cmd is None:
|
|
62
|
-
parser.print_help()
|
|
63
|
-
return 0
|
|
64
|
-
if args.cmd == "test":
|
|
65
|
-
return self._cmd_test()
|
|
66
|
-
if args.cmd == "log":
|
|
67
|
-
return self._cmd_log(args.limit)
|
|
68
|
-
return 2
|
|
69
|
-
|
|
70
|
-
# ----- ChannelPlugin Protocol ------------------------------------------
|
|
71
|
-
|
|
72
|
-
def push(self, ctx: PluginContext, payload: NotificationPayload) -> None:
|
|
73
|
-
# 1) Walk the payload — counts come from real iteration, never from
|
|
74
|
-
# dict.len(), so we cannot "succeed" without having actually read the
|
|
75
|
-
# plugin's data.
|
|
76
|
-
section_count = len(payload.sections)
|
|
77
|
-
item_count = sum(len(s.items) for s in payload.sections)
|
|
78
|
-
metric_count = len(payload.metrics)
|
|
79
|
-
for section in payload.sections:
|
|
80
|
-
for item in section.items:
|
|
81
|
-
_ = (item.code, item.name, item.rank, item.score, item.label, item.note)
|
|
82
|
-
for k, v in payload.metrics.items():
|
|
83
|
-
_ = (k, v)
|
|
84
|
-
_ = payload.title, payload.summary, payload.report_dir, payload.extras
|
|
85
|
-
|
|
86
|
-
# 2) Persist a delivery audit row.
|
|
87
|
-
ctx.db.execute(
|
|
88
|
-
"INSERT INTO stdout_channel_log(plugin_id, run_id, status, title, "
|
|
89
|
-
"section_count, item_count, metric_count) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
|
90
|
-
(
|
|
91
|
-
payload.plugin_id,
|
|
92
|
-
payload.run_id,
|
|
93
|
-
payload.status.value,
|
|
94
|
-
payload.title,
|
|
95
|
-
section_count,
|
|
96
|
-
item_count,
|
|
97
|
-
metric_count,
|
|
98
|
-
),
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
# 3) One concise line. Use sys.stdout (not rich console) so this stays
|
|
102
|
-
# out of any TUI / strategy console that the caller may have running.
|
|
103
|
-
sys.stdout.write(
|
|
104
|
-
f"✔ push success (channel=stdout-channel run_id={payload.run_id} "
|
|
105
|
-
f"status={payload.status.value})\n"
|
|
106
|
-
)
|
|
107
|
-
sys.stdout.flush()
|
|
108
|
-
|
|
109
|
-
# ----- private helpers -------------------------------------------------
|
|
110
|
-
|
|
111
|
-
def _cmd_test(self) -> int:
|
|
112
|
-
"""Round-trip a synthetic payload through ``deeptrade.notify``.
|
|
113
|
-
|
|
114
|
-
Goes through the framework's notifier layer (not directly through
|
|
115
|
-
``self.push``) so the test exercises the full path: install →
|
|
116
|
-
build_notifier → dispatch → push.
|
|
117
|
-
"""
|
|
118
|
-
import uuid
|
|
119
|
-
|
|
120
|
-
from deeptrade import notify
|
|
121
|
-
from deeptrade.core import paths
|
|
122
|
-
from deeptrade.core.db import Database
|
|
123
|
-
from deeptrade.core.run_status import RunStatus
|
|
124
|
-
from deeptrade.plugins_api.notify import (
|
|
125
|
-
NotificationItem,
|
|
126
|
-
NotificationPayload,
|
|
127
|
-
NotificationSection,
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
payload = NotificationPayload(
|
|
131
|
-
plugin_id="stdout-channel",
|
|
132
|
-
run_id=str(uuid.uuid4()),
|
|
133
|
-
status=RunStatus.SUCCESS,
|
|
134
|
-
title="DeepTrade — stdout channel test",
|
|
135
|
-
summary="Synthetic payload from `deeptrade stdout-channel test`.",
|
|
136
|
-
sections=[
|
|
137
|
-
NotificationSection(
|
|
138
|
-
key="demo",
|
|
139
|
-
title="Demo items",
|
|
140
|
-
items=[
|
|
141
|
-
NotificationItem(
|
|
142
|
-
code="600519.SH", name="贵州茅台", rank=1, score=87.5,
|
|
143
|
-
label="top_candidate", note="演示条目,非真实推荐",
|
|
144
|
-
),
|
|
145
|
-
],
|
|
146
|
-
),
|
|
147
|
-
],
|
|
148
|
-
metrics={"selected": 1},
|
|
149
|
-
)
|
|
150
|
-
db = Database(paths.db_path())
|
|
151
|
-
try:
|
|
152
|
-
notify(db, payload)
|
|
153
|
-
finally:
|
|
154
|
-
db.close()
|
|
155
|
-
return 0
|
|
156
|
-
|
|
157
|
-
def _cmd_log(self, limit: int) -> int:
|
|
158
|
-
from deeptrade.core import paths
|
|
159
|
-
from deeptrade.core.db import Database
|
|
160
|
-
|
|
161
|
-
db = Database(paths.db_path())
|
|
162
|
-
try:
|
|
163
|
-
rows = db.fetchall(
|
|
164
|
-
"SELECT delivered_at, plugin_id, run_id, status, title, "
|
|
165
|
-
"section_count, item_count, metric_count "
|
|
166
|
-
"FROM stdout_channel_log ORDER BY delivered_at DESC LIMIT ?",
|
|
167
|
-
(limit,),
|
|
168
|
-
)
|
|
169
|
-
finally:
|
|
170
|
-
db.close()
|
|
171
|
-
|
|
172
|
-
if not rows:
|
|
173
|
-
sys.stdout.write("(no deliveries yet)\n")
|
|
174
|
-
return 0
|
|
175
|
-
for r in rows:
|
|
176
|
-
sys.stdout.write(
|
|
177
|
-
f"{r[0]} {r[1]:<20} {r[3]:<8} sec={r[5]} item={r[6]} "
|
|
178
|
-
f"metric={r[7]} {r[4]}\n"
|
|
179
|
-
)
|
|
180
|
-
return 0
|
|
File without changes
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
plugin_id: limit-up-board
|
|
2
|
-
name: 打板策略
|
|
3
|
-
version: 0.4.0
|
|
4
|
-
type: strategy
|
|
5
|
-
api_version: "1"
|
|
6
|
-
entrypoint: limit_up_board.plugin:LimitUpBoardPlugin
|
|
7
|
-
description: A 股打板策略:双轮 LLM 漏斗(强势标的分析 → 连板预测)
|
|
8
|
-
author: DeepTrade
|
|
9
|
-
|
|
10
|
-
permissions:
|
|
11
|
-
tushare_apis:
|
|
12
|
-
required:
|
|
13
|
-
- stock_basic
|
|
14
|
-
- trade_cal
|
|
15
|
-
- daily
|
|
16
|
-
- daily_basic
|
|
17
|
-
- stock_st
|
|
18
|
-
- limit_list_d
|
|
19
|
-
- limit_step
|
|
20
|
-
- moneyflow
|
|
21
|
-
- top_list
|
|
22
|
-
- top_inst
|
|
23
|
-
- cyq_perf
|
|
24
|
-
optional:
|
|
25
|
-
- limit_list_ths
|
|
26
|
-
- limit_cpt_list
|
|
27
|
-
- ths_hot
|
|
28
|
-
- dc_hot
|
|
29
|
-
- stk_auction_o
|
|
30
|
-
- anns_d
|
|
31
|
-
- suspend_d
|
|
32
|
-
- stk_limit
|
|
33
|
-
llm: true
|
|
34
|
-
llm_tools: false
|
|
35
|
-
|
|
36
|
-
migrations:
|
|
37
|
-
- version: "20260509_001"
|
|
38
|
-
file: migrations/20260509_001_init.sql
|
|
39
|
-
checksum: "sha256:8f6bc721fedbd94f652fa356779eea7b4ef801483968dabfa6648cf2f639064f"
|
|
40
|
-
|
|
41
|
-
tables:
|
|
42
|
-
- name: lub_stock_basic
|
|
43
|
-
description: stock_basic 落库(限本插件使用)
|
|
44
|
-
purge_on_uninstall: true
|
|
45
|
-
- name: lub_trade_cal
|
|
46
|
-
description: trade_cal 落库
|
|
47
|
-
purge_on_uninstall: true
|
|
48
|
-
- name: lub_daily
|
|
49
|
-
description: daily 行情落库
|
|
50
|
-
purge_on_uninstall: true
|
|
51
|
-
- name: lub_daily_basic
|
|
52
|
-
description: daily_basic 行情指标落库
|
|
53
|
-
purge_on_uninstall: true
|
|
54
|
-
- name: lub_moneyflow
|
|
55
|
-
description: moneyflow 资金流落库
|
|
56
|
-
purge_on_uninstall: true
|
|
57
|
-
- name: lub_limit_list_d
|
|
58
|
-
description: 涨停明细缓存(limit_list_d)
|
|
59
|
-
purge_on_uninstall: true
|
|
60
|
-
- name: lub_limit_ths
|
|
61
|
-
description: 同花顺涨停榜单缓存(limit_list_ths)
|
|
62
|
-
purge_on_uninstall: true
|
|
63
|
-
- name: lub_stage_results
|
|
64
|
-
description: 策略各阶段(R1/R2/final_ranking)结构化结果
|
|
65
|
-
purge_on_uninstall: true
|
|
66
|
-
- name: lub_runs
|
|
67
|
-
description: 本插件 run 历史(替代框架 strategy_runs)
|
|
68
|
-
purge_on_uninstall: true
|
|
69
|
-
- name: lub_events
|
|
70
|
-
description: 本插件 run 事件流(替代框架 strategy_events)
|
|
71
|
-
purge_on_uninstall: true
|
|
72
|
-
- name: lub_top_list
|
|
73
|
-
description: 龙虎榜个股明细(top_list)
|
|
74
|
-
purge_on_uninstall: true
|
|
75
|
-
- name: lub_top_inst
|
|
76
|
-
description: 龙虎榜机构席位明细(top_inst)
|
|
77
|
-
purge_on_uninstall: true
|
|
78
|
-
- name: lub_cyq_perf
|
|
79
|
-
description: 筹码每日指标(cyq_perf)
|
|
80
|
-
purge_on_uninstall: true
|
|
81
|
-
- name: lub_config
|
|
82
|
-
description: 本插件用户可调设置(流通市值 / 股价上限)
|
|
83
|
-
purge_on_uninstall: true
|
deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/limit_up_board/__init__.py
DELETED
|
File without changes
|
deeptrade_quant-0.1.0/deeptrade/strategies_builtin/limit_up_board/limit_up_board/calendar.py
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
"""TradeCalendar — pure helper around tushare trade_cal frames."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import pandas as pd
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class TradeCalendar:
|
|
9
|
-
"""Read-only view over the trade_cal DataFrame.
|
|
10
|
-
|
|
11
|
-
Required columns: cal_date (str YYYYMMDD), is_open (0/1), pretrade_date (str).
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
def __init__(self, df: pd.DataFrame) -> None:
|
|
15
|
-
if not {"cal_date", "is_open"}.issubset(df.columns):
|
|
16
|
-
raise ValueError("trade_cal frame missing required columns")
|
|
17
|
-
|
|
18
|
-
# ⚠ Bug fix: tushare trade_cal returns cal_date as int64 in some
|
|
19
|
-
# environments; JSON cache round-trip can also widen "20260428" → 20260428.
|
|
20
|
-
# Normalize to string up-front so all downstream comparisons are str↔str.
|
|
21
|
-
df = df.copy()
|
|
22
|
-
df["cal_date"] = df["cal_date"].astype(str)
|
|
23
|
-
if "pretrade_date" in df.columns:
|
|
24
|
-
# Some non-trading days have NaN pretrade_date; preserve NaN, stringify the rest
|
|
25
|
-
df["pretrade_date"] = df["pretrade_date"].apply(
|
|
26
|
-
lambda v: str(v) if pd.notna(v) else None
|
|
27
|
-
)
|
|
28
|
-
# is_open is sometimes "1"/"0" strings — coerce to int for ==1 comparison
|
|
29
|
-
df["is_open"] = pd.to_numeric(df["is_open"], errors="coerce").fillna(0).astype(int)
|
|
30
|
-
|
|
31
|
-
# Normalize: deduplicate on cal_date, keeping the SSE/last row
|
|
32
|
-
sorted_df = df.sort_values("cal_date").drop_duplicates("cal_date", keep="last")
|
|
33
|
-
self._df = sorted_df.reset_index(drop=True)
|
|
34
|
-
self._idx: dict[str, int] = {
|
|
35
|
-
str(row.cal_date): i for i, row in enumerate(self._df.itertuples(index=False))
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
def is_open(self, date: str) -> bool:
|
|
39
|
-
idx = self._idx.get(date)
|
|
40
|
-
if idx is None:
|
|
41
|
-
return False
|
|
42
|
-
return int(self._df.at[idx, "is_open"]) == 1
|
|
43
|
-
|
|
44
|
-
def pretrade_date(self, date: str) -> str:
|
|
45
|
-
"""Return the most recent open day strictly BEFORE `date`."""
|
|
46
|
-
# Walk backwards through cal_date sorted index
|
|
47
|
-
candidates = self._df[self._df["cal_date"] < date]
|
|
48
|
-
opens = candidates[candidates["is_open"] == 1]
|
|
49
|
-
if opens.empty:
|
|
50
|
-
raise ValueError(f"no prior open trading day before {date}")
|
|
51
|
-
return str(opens.iloc[-1]["cal_date"])
|
|
52
|
-
|
|
53
|
-
def next_open(self, date: str) -> str:
|
|
54
|
-
"""Return the first open day strictly AFTER `date`."""
|
|
55
|
-
candidates = self._df[self._df["cal_date"] > date]
|
|
56
|
-
opens = candidates[candidates["is_open"] == 1]
|
|
57
|
-
if opens.empty:
|
|
58
|
-
raise ValueError(f"no future open trading day after {date}")
|
|
59
|
-
return str(opens.iloc[0]["cal_date"])
|
|
60
|
-
|
|
61
|
-
def latest_closed_on_or_before(self, date: str) -> str:
|
|
62
|
-
"""Return the latest open day ≤ `date` (i.e. `date` itself if open, else preceding)."""
|
|
63
|
-
if self.is_open(date):
|
|
64
|
-
return date
|
|
65
|
-
return self.pretrade_date(date)
|