bullet-trade 0.1.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.
- bullet_trade-0.1.0/LICENSE +21 -0
- bullet_trade-0.1.0/MANIFEST.in +22 -0
- bullet_trade-0.1.0/PKG-INFO +108 -0
- bullet_trade-0.1.0/README.md +54 -0
- bullet_trade-0.1.0/bullet_trade/__init__.py +96 -0
- bullet_trade-0.1.0/bullet_trade/__main__.py +7 -0
- bullet_trade-0.1.0/bullet_trade/__version__.py +7 -0
- bullet_trade-0.1.0/bullet_trade/broker/__init__.py +12 -0
- bullet_trade-0.1.0/bullet_trade/broker/base.py +288 -0
- bullet_trade-0.1.0/bullet_trade/broker/qmt.py +850 -0
- bullet_trade-0.1.0/bullet_trade/broker/qmt_remote.py +169 -0
- bullet_trade-0.1.0/bullet_trade/broker/simulator.py +194 -0
- bullet_trade-0.1.0/bullet_trade/cli/__init__.py +6 -0
- bullet_trade-0.1.0/bullet_trade/cli/backtest.py +157 -0
- bullet_trade-0.1.0/bullet_trade/cli/live.py +30 -0
- bullet_trade-0.1.0/bullet_trade/cli/main.py +496 -0
- bullet_trade-0.1.0/bullet_trade/cli/optimize.py +97 -0
- bullet_trade-0.1.0/bullet_trade/cli/report.py +47 -0
- bullet_trade-0.1.0/bullet_trade/compat/__init__.py +6 -0
- bullet_trade-0.1.0/bullet_trade/compat/jqdata.py +73 -0
- bullet_trade-0.1.0/bullet_trade/core/__init__.py +56 -0
- bullet_trade-0.1.0/bullet_trade/core/analysis.py +2542 -0
- bullet_trade-0.1.0/bullet_trade/core/api.py +436 -0
- bullet_trade-0.1.0/bullet_trade/core/async_engine.py +521 -0
- bullet_trade-0.1.0/bullet_trade/core/async_scheduler.py +576 -0
- bullet_trade-0.1.0/bullet_trade/core/engine.py +1740 -0
- bullet_trade-0.1.0/bullet_trade/core/event_bus.py +387 -0
- bullet_trade-0.1.0/bullet_trade/core/event_loop.py +379 -0
- bullet_trade-0.1.0/bullet_trade/core/events.py +367 -0
- bullet_trade-0.1.0/bullet_trade/core/exceptions.py +27 -0
- bullet_trade-0.1.0/bullet_trade/core/globals.py +299 -0
- bullet_trade-0.1.0/bullet_trade/core/live_engine.py +1544 -0
- bullet_trade-0.1.0/bullet_trade/core/live_runtime.py +209 -0
- bullet_trade-0.1.0/bullet_trade/core/message.py +292 -0
- bullet_trade-0.1.0/bullet_trade/core/models.py +273 -0
- bullet_trade-0.1.0/bullet_trade/core/notifications.py +83 -0
- bullet_trade-0.1.0/bullet_trade/core/optimizer.py +458 -0
- bullet_trade-0.1.0/bullet_trade/core/orders.py +272 -0
- bullet_trade-0.1.0/bullet_trade/core/pricing.py +165 -0
- bullet_trade-0.1.0/bullet_trade/core/risk_control.py +321 -0
- bullet_trade-0.1.0/bullet_trade/core/runtime.py +44 -0
- bullet_trade-0.1.0/bullet_trade/core/scheduler.py +479 -0
- bullet_trade-0.1.0/bullet_trade/core/settings.py +217 -0
- bullet_trade-0.1.0/bullet_trade/data/__init__.py +26 -0
- bullet_trade-0.1.0/bullet_trade/data/api.py +1168 -0
- bullet_trade-0.1.0/bullet_trade/data/base.py +23 -0
- bullet_trade-0.1.0/bullet_trade/data/cache.py +390 -0
- bullet_trade-0.1.0/bullet_trade/data/providers/base.py +79 -0
- bullet_trade-0.1.0/bullet_trade/data/providers/jqdata.py +586 -0
- bullet_trade-0.1.0/bullet_trade/data/providers/miniqmt.py +911 -0
- bullet_trade-0.1.0/bullet_trade/data/providers/remote_qmt.py +150 -0
- bullet_trade-0.1.0/bullet_trade/data/providers/tushare.py +486 -0
- bullet_trade-0.1.0/bullet_trade/remote/__init__.py +7 -0
- bullet_trade-0.1.0/bullet_trade/remote/connection.py +288 -0
- bullet_trade-0.1.0/bullet_trade/reporting/__init__.py +425 -0
- bullet_trade-0.1.0/bullet_trade/reporting/templates/__init__.py +1 -0
- bullet_trade-0.1.0/bullet_trade/reporting/templates/default.html +138 -0
- bullet_trade-0.1.0/bullet_trade/server/__init__.py +11 -0
- bullet_trade-0.1.0/bullet_trade/server/adapters/__init__.py +20 -0
- bullet_trade-0.1.0/bullet_trade/server/adapters/base.py +146 -0
- bullet_trade-0.1.0/bullet_trade/server/adapters/qmt.py +264 -0
- bullet_trade-0.1.0/bullet_trade/server/adapters/stub.py +93 -0
- bullet_trade-0.1.0/bullet_trade/server/app.py +392 -0
- bullet_trade-0.1.0/bullet_trade/server/cli.py +66 -0
- bullet_trade-0.1.0/bullet_trade/server/config.py +233 -0
- bullet_trade-0.1.0/bullet_trade/server/protocol.py +38 -0
- bullet_trade-0.1.0/bullet_trade/server/session.py +147 -0
- bullet_trade-0.1.0/bullet_trade/server/tick.py +112 -0
- bullet_trade-0.1.0/bullet_trade/utils/env_loader.py +318 -0
- bullet_trade-0.1.0/bullet_trade/utils/font_config.py +176 -0
- bullet_trade-0.1.0/bullet_trade/utils/portfolio_printer.py +144 -0
- bullet_trade-0.1.0/bullet_trade/utils/strategy_helpers.py +226 -0
- bullet_trade-0.1.0/bullet_trade.egg-info/PKG-INFO +108 -0
- bullet_trade-0.1.0/bullet_trade.egg-info/SOURCES.txt +83 -0
- bullet_trade-0.1.0/bullet_trade.egg-info/dependency_links.txt +1 -0
- bullet_trade-0.1.0/bullet_trade.egg-info/entry_points.txt +2 -0
- bullet_trade-0.1.0/bullet_trade.egg-info/requires.txt +33 -0
- bullet_trade-0.1.0/bullet_trade.egg-info/top_level.txt +2 -0
- bullet_trade-0.1.0/env.example +58 -0
- bullet_trade-0.1.0/jqdata.py +13 -0
- bullet_trade-0.1.0/pyproject.toml +162 -0
- bullet_trade-0.1.0/pytest.ini +19 -0
- bullet_trade-0.1.0/requirements-dev.txt +30 -0
- bullet_trade-0.1.0/requirements.txt +28 -0
- bullet_trade-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 BulletTrade
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# 包含额外文件到源代码分发包
|
|
2
|
+
|
|
3
|
+
include README.md
|
|
4
|
+
include README_EN.md
|
|
5
|
+
include LICENSE
|
|
6
|
+
include PLAN.md
|
|
7
|
+
include REQ.md
|
|
8
|
+
include requirements.txt
|
|
9
|
+
include requirements-dev.txt
|
|
10
|
+
include pytest.ini
|
|
11
|
+
include env.example
|
|
12
|
+
|
|
13
|
+
# 排除文件
|
|
14
|
+
recursive-exclude * __pycache__
|
|
15
|
+
recursive-exclude * *.py[co]
|
|
16
|
+
recursive-exclude tests *
|
|
17
|
+
recursive-exclude docs *
|
|
18
|
+
recursive-exclude examples *
|
|
19
|
+
recursive-exclude scripts *
|
|
20
|
+
exclude .env
|
|
21
|
+
exclude .gitignore
|
|
22
|
+
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bullet-trade
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: BulletTrade - 专业的量化交易系统,兼容聚宽策略,支持多数据源和实盘交易
|
|
5
|
+
Author-email: BulletTrade Team <bullettrade.cn@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/BulletTrade/bullet-trade
|
|
8
|
+
Project-URL: Documentation, https://bullettrade.readthedocs.io
|
|
9
|
+
Project-URL: Repository, https://github.com/BulletTrade/bullet-trade
|
|
10
|
+
Project-URL: Changelog, https://github.com/BulletTrade/bullet-trade/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: 量化交易,quantitative trading,backtest,聚宽,joinquant,algotrading,stock trading,live trading
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Requires-Python: >=3.8
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: pandas>=1.3.0
|
|
28
|
+
Requires-Dist: numpy>=1.21.0
|
|
29
|
+
Requires-Dist: matplotlib>=3.4.0
|
|
30
|
+
Requires-Dist: jqdatasdk>=1.8.0
|
|
31
|
+
Requires-Dist: plotly>=5.15.0
|
|
32
|
+
Requires-Dist: python-dotenv>=0.19.0
|
|
33
|
+
Requires-Dist: pyecharts>=1.9.0
|
|
34
|
+
Requires-Dist: tabulate>=0.9.0
|
|
35
|
+
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
37
|
+
Requires-Dist: pytest-cov>=3.0.0; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest-mock>=3.6.0; extra == "dev"
|
|
39
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
40
|
+
Requires-Dist: pyyaml>=6.0; extra == "dev"
|
|
41
|
+
Requires-Dist: black>=22.0.0; extra == "dev"
|
|
42
|
+
Requires-Dist: flake8>=4.0.0; extra == "dev"
|
|
43
|
+
Requires-Dist: mypy>=0.950; extra == "dev"
|
|
44
|
+
Requires-Dist: isort>=5.10.0; extra == "dev"
|
|
45
|
+
Provides-Extra: tushare
|
|
46
|
+
Requires-Dist: tushare>=1.2.0; extra == "tushare"
|
|
47
|
+
Provides-Extra: qmt
|
|
48
|
+
Requires-Dist: xtquant>=1.0.0; extra == "qmt"
|
|
49
|
+
Provides-Extra: qmtserver
|
|
50
|
+
Requires-Dist: pywin32>=305; platform_system == "Windows" and extra == "qmtserver"
|
|
51
|
+
Provides-Extra: all
|
|
52
|
+
Requires-Dist: bullet-trade[dev,qmt,qmtserver,tushare]; extra == "all"
|
|
53
|
+
Dynamic: license-file
|
|
54
|
+
|
|
55
|
+
# BulletTrade
|
|
56
|
+
|
|
57
|
+
<p>
|
|
58
|
+
<img src="docs/assets/logo.png" alt="BulletTrade Logo" width="100">
|
|
59
|
+
</p>
|
|
60
|
+
|
|
61
|
+
[](https://badge.fury.io/py/bullet-trade)
|
|
62
|
+
[](https://pypi.org/project/bullet-trade/)
|
|
63
|
+
[](https://github.com/BulletTrade/bullet-trade/blob/main/LICENSE)
|
|
64
|
+
|
|
65
|
+
**BulletTrade** 是一个专业的量化交易系统 Python 包,提供完整的回测和实盘交易解决方案。
|
|
66
|
+
|
|
67
|
+
简体中文 | [完整文档](docs/index.md)
|
|
68
|
+
|
|
69
|
+
## ✨ 核心特性
|
|
70
|
+
|
|
71
|
+
- **🔄 聚宽兼容**:`from jqdata import *`
|
|
72
|
+
- **📊 多数据源**:JQData、MiniQMT、TuShare、本地缓存与远程 QMT server 均可切换。
|
|
73
|
+
- **⚡ 回测 & 报告**:分钟/日线回测、真实价格撮合、HTML/PDF 报告一键生成。
|
|
74
|
+
- **💼 实盘接入**:本地 QMT、远程 QMT server、模拟券商按需选择。
|
|
75
|
+
- **🧩 可扩展**:数据/券商接口基于抽象基类,便于自定义实现。
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
## 📖 文档
|
|
79
|
+
|
|
80
|
+
- [文档首页](docs/index.md): 站点 <https://bullettrade.cn/docs/>
|
|
81
|
+
- [回测引擎](docs/backtest.md):真实价格成交、分红送股处理、聚宽代码示例与 CLI 回测。
|
|
82
|
+
- [实盘引擎](docs/live.md):本地 QMT 独立实盘与远程实盘流程。
|
|
83
|
+
- [交易支撑](docs/trade-support.md):聚宽模拟盘接入、远程 QMT 服务与 helper 用法。
|
|
84
|
+
- [扩展能力](docs/quickstart.md):数据/交易提供者设计理念与扩展指引。
|
|
85
|
+
- [数据源指南](docs/data/DATA_PROVIDER_GUIDE.md):聚宽、MiniQMT、Tushare 以及自定义 Provider 配置。
|
|
86
|
+
- [API 文档](docs/api.md):策略可用 API、类模型与工具函数。
|
|
87
|
+
- [QMT 服务配置](docs/qmt-server.md):bullet-trade server 的完整说明。
|
|
88
|
+
- [邀请贡献](docs/contributing.md): 贡献与联系方式。
|
|
89
|
+
|
|
90
|
+
## 🔗 链接
|
|
91
|
+
|
|
92
|
+
- GitHub 仓库:https://github.com/BulletTrade/bullet-trade
|
|
93
|
+
- 官方站点:https://bullettrade.cn/
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
## 📄 许可证
|
|
97
|
+
|
|
98
|
+
[MIT License](LICENSE)
|
|
99
|
+
|
|
100
|
+
## 联系与支持
|
|
101
|
+
|
|
102
|
+
如需交流或反馈,低佣开通QMT等,可扫码添加微信,并在 Issue/PR 中提出建议:
|
|
103
|
+
|
|
104
|
+
<img src="docs/assets/wechat-contact.png" alt="微信二维码" style="max-width: 200px;">
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
**⚠️ 风险提示:** 量化交易存在高风险,因策略、配置或软件缺陷/网络异常等导致的任何损失由使用者自行承担,请先在仿真/小仓位充分验证。
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# BulletTrade
|
|
2
|
+
|
|
3
|
+
<p>
|
|
4
|
+
<img src="docs/assets/logo.png" alt="BulletTrade Logo" width="100">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
[](https://badge.fury.io/py/bullet-trade)
|
|
8
|
+
[](https://pypi.org/project/bullet-trade/)
|
|
9
|
+
[](https://github.com/BulletTrade/bullet-trade/blob/main/LICENSE)
|
|
10
|
+
|
|
11
|
+
**BulletTrade** 是一个专业的量化交易系统 Python 包,提供完整的回测和实盘交易解决方案。
|
|
12
|
+
|
|
13
|
+
简体中文 | [完整文档](docs/index.md)
|
|
14
|
+
|
|
15
|
+
## ✨ 核心特性
|
|
16
|
+
|
|
17
|
+
- **🔄 聚宽兼容**:`from jqdata import *`
|
|
18
|
+
- **📊 多数据源**:JQData、MiniQMT、TuShare、本地缓存与远程 QMT server 均可切换。
|
|
19
|
+
- **⚡ 回测 & 报告**:分钟/日线回测、真实价格撮合、HTML/PDF 报告一键生成。
|
|
20
|
+
- **💼 实盘接入**:本地 QMT、远程 QMT server、模拟券商按需选择。
|
|
21
|
+
- **🧩 可扩展**:数据/券商接口基于抽象基类,便于自定义实现。
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
## 📖 文档
|
|
25
|
+
|
|
26
|
+
- [文档首页](docs/index.md): 站点 <https://bullettrade.cn/docs/>
|
|
27
|
+
- [回测引擎](docs/backtest.md):真实价格成交、分红送股处理、聚宽代码示例与 CLI 回测。
|
|
28
|
+
- [实盘引擎](docs/live.md):本地 QMT 独立实盘与远程实盘流程。
|
|
29
|
+
- [交易支撑](docs/trade-support.md):聚宽模拟盘接入、远程 QMT 服务与 helper 用法。
|
|
30
|
+
- [扩展能力](docs/quickstart.md):数据/交易提供者设计理念与扩展指引。
|
|
31
|
+
- [数据源指南](docs/data/DATA_PROVIDER_GUIDE.md):聚宽、MiniQMT、Tushare 以及自定义 Provider 配置。
|
|
32
|
+
- [API 文档](docs/api.md):策略可用 API、类模型与工具函数。
|
|
33
|
+
- [QMT 服务配置](docs/qmt-server.md):bullet-trade server 的完整说明。
|
|
34
|
+
- [邀请贡献](docs/contributing.md): 贡献与联系方式。
|
|
35
|
+
|
|
36
|
+
## 🔗 链接
|
|
37
|
+
|
|
38
|
+
- GitHub 仓库:https://github.com/BulletTrade/bullet-trade
|
|
39
|
+
- 官方站点:https://bullettrade.cn/
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
## 📄 许可证
|
|
43
|
+
|
|
44
|
+
[MIT License](LICENSE)
|
|
45
|
+
|
|
46
|
+
## 联系与支持
|
|
47
|
+
|
|
48
|
+
如需交流或反馈,低佣开通QMT等,可扫码添加微信,并在 Issue/PR 中提出建议:
|
|
49
|
+
|
|
50
|
+
<img src="docs/assets/wechat-contact.png" alt="微信二维码" style="max-width: 200px;">
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
**⚠️ 风险提示:** 量化交易存在高风险,因策略、配置或软件缺陷/网络异常等导致的任何损失由使用者自行承担,请先在仿真/小仓位充分验证。
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""
|
|
2
|
+
BulletTrade - 专业的量化交易系统
|
|
3
|
+
完整的本地策略回测系统,兼容聚宽API,支持多数据源和实盘交易
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from importlib import import_module
|
|
7
|
+
from typing import Any, TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
import warnings
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
import matplotlib
|
|
13
|
+
# 设置非交互式后端,避免程序挂起
|
|
14
|
+
matplotlib.use('Agg')
|
|
15
|
+
import matplotlib.pyplot as plt # noqa: F401
|
|
16
|
+
except Exception as exc: # pragma: no cover - 兼容运行环境缺少 GUI 依赖的情况
|
|
17
|
+
warnings.warn(f"Matplotlib 初始化失败,将跳过图形相关功能:{exc!r}")
|
|
18
|
+
matplotlib = None # type: ignore
|
|
19
|
+
plt = None # type: ignore
|
|
20
|
+
|
|
21
|
+
# 加载环境变量
|
|
22
|
+
from .utils.env_loader import load_env
|
|
23
|
+
load_env()
|
|
24
|
+
|
|
25
|
+
# 配置中文字体显示
|
|
26
|
+
# from .utils.font_config import setup_chinese_fonts
|
|
27
|
+
# setup_chinese_fonts()
|
|
28
|
+
|
|
29
|
+
# 导入数据模块
|
|
30
|
+
from .data.api import * # noqa: F401,F403
|
|
31
|
+
|
|
32
|
+
# 导入核心模块
|
|
33
|
+
from .core.models import (
|
|
34
|
+
Context, Portfolio, SubPortfolio, Position,
|
|
35
|
+
Trade, Order, OrderStatus, OrderStyle, SecurityUnitData
|
|
36
|
+
)
|
|
37
|
+
from .core.globals import g, log
|
|
38
|
+
from .core.settings import (
|
|
39
|
+
set_benchmark, set_order_cost, set_slippage, set_option,
|
|
40
|
+
OrderCost, FixedSlippage
|
|
41
|
+
)
|
|
42
|
+
from .core.orders import (
|
|
43
|
+
order, order_value, order_target, order_target_value, MarketOrderStyle, LimitOrderStyle
|
|
44
|
+
)
|
|
45
|
+
from .core.scheduler import (
|
|
46
|
+
run_daily, run_weekly, run_monthly, unschedule_all
|
|
47
|
+
)
|
|
48
|
+
from .core.engine import create_backtest, BacktestEngine
|
|
49
|
+
|
|
50
|
+
from .__version__ import __version__
|
|
51
|
+
|
|
52
|
+
_ANALYSIS_EXPORTS = (
|
|
53
|
+
'plot_results',
|
|
54
|
+
'plot_positions',
|
|
55
|
+
'calculate_metrics',
|
|
56
|
+
'print_metrics',
|
|
57
|
+
'export_trades',
|
|
58
|
+
'generate_report',
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
if TYPE_CHECKING: # pragma: no cover - 仅用于类型提示
|
|
62
|
+
from .core import analysis as _analysis_module # noqa: F401,F811
|
|
63
|
+
|
|
64
|
+
__all__ = [
|
|
65
|
+
# 数据模型
|
|
66
|
+
'Context', 'Portfolio', 'SubPortfolio', 'Position',
|
|
67
|
+
'Trade', 'Order', 'OrderStatus', 'OrderStyle', 'SecurityUnitData',
|
|
68
|
+
# 全局对象
|
|
69
|
+
'g', 'log',
|
|
70
|
+
# 设置函数
|
|
71
|
+
'set_benchmark', 'set_order_cost', 'set_slippage', 'set_option',
|
|
72
|
+
'OrderCost', 'FixedSlippage',
|
|
73
|
+
# 订单函数
|
|
74
|
+
'order', 'order_value', 'order_target', 'order_target_value', 'MarketOrderStyle', 'LimitOrderStyle',
|
|
75
|
+
# 调度函数
|
|
76
|
+
'run_daily', 'run_weekly', 'run_monthly', 'unschedule_all',
|
|
77
|
+
# 回测引擎
|
|
78
|
+
'create_backtest', 'BacktestEngine',
|
|
79
|
+
# 版本
|
|
80
|
+
'__version__',
|
|
81
|
+
] + list(_ANALYSIS_EXPORTS)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def __getattr__(name: str) -> Any:
|
|
85
|
+
"""延迟加载分析绘图相关函数,避免在未安装 matplotlib 时导入失败"""
|
|
86
|
+
if name in _ANALYSIS_EXPORTS:
|
|
87
|
+
module = import_module('.core.analysis', __name__)
|
|
88
|
+
attr = getattr(module, name)
|
|
89
|
+
globals()[name] = attr
|
|
90
|
+
return attr
|
|
91
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def __dir__() -> list[str]:
|
|
95
|
+
"""让内建 dir() 同样展示延迟导出的接口"""
|
|
96
|
+
return sorted(set(globals().keys()) | set(_ANALYSIS_EXPORTS))
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""
|
|
2
|
+
BulletTrade 实盘交易模块
|
|
3
|
+
|
|
4
|
+
提供券商对接和实盘交易功能
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .base import BrokerBase
|
|
8
|
+
from .qmt import QmtBroker
|
|
9
|
+
from .qmt_remote import RemoteQmtBroker
|
|
10
|
+
from .simulator import SimulatorBroker
|
|
11
|
+
|
|
12
|
+
__all__ = ['BrokerBase', 'QmtBroker', 'RemoteQmtBroker', 'SimulatorBroker']
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
"""
|
|
2
|
+
券商接口基类
|
|
3
|
+
|
|
4
|
+
定义券商必须实现的接口
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from abc import ABC, abstractmethod
|
|
8
|
+
from typing import Dict, List, Optional, Any
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BrokerBase(ABC):
|
|
13
|
+
"""
|
|
14
|
+
券商接口基类
|
|
15
|
+
|
|
16
|
+
所有券商实现都必须继承此类并实现相关方法
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, account_id: str, account_type: str = 'stock'):
|
|
20
|
+
"""
|
|
21
|
+
初始化券商
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
account_id: 账户ID
|
|
25
|
+
account_type: 账户类型(stock/futures)
|
|
26
|
+
"""
|
|
27
|
+
self.account_id = account_id
|
|
28
|
+
self.account_type = account_type
|
|
29
|
+
self._connected = False
|
|
30
|
+
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def connect(self) -> bool:
|
|
33
|
+
"""
|
|
34
|
+
连接券商
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
是否连接成功
|
|
38
|
+
"""
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
@abstractmethod
|
|
42
|
+
def disconnect(self) -> bool:
|
|
43
|
+
"""
|
|
44
|
+
断开连接
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
是否断开成功
|
|
48
|
+
"""
|
|
49
|
+
pass
|
|
50
|
+
|
|
51
|
+
@abstractmethod
|
|
52
|
+
def get_account_info(self) -> Dict[str, Any]:
|
|
53
|
+
"""
|
|
54
|
+
获取账户信息
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
账户信息字典,包含:
|
|
58
|
+
- total_value: 总资产
|
|
59
|
+
- available_cash: 可用资金
|
|
60
|
+
- positions: 持仓列表
|
|
61
|
+
"""
|
|
62
|
+
pass
|
|
63
|
+
|
|
64
|
+
@abstractmethod
|
|
65
|
+
def get_positions(self) -> List[Dict[str, Any]]:
|
|
66
|
+
"""
|
|
67
|
+
获取持仓
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
持仓列表,每个持仓包含:
|
|
71
|
+
- security: 证券代码
|
|
72
|
+
- amount: 持仓数量
|
|
73
|
+
- avg_cost: 平均成本
|
|
74
|
+
- market_value: 市值
|
|
75
|
+
"""
|
|
76
|
+
raise NotImplementedError
|
|
77
|
+
|
|
78
|
+
@abstractmethod
|
|
79
|
+
async def buy(
|
|
80
|
+
self,
|
|
81
|
+
security: str,
|
|
82
|
+
amount: int,
|
|
83
|
+
price: Optional[float] = None,
|
|
84
|
+
wait_timeout: Optional[float] = None,
|
|
85
|
+
) -> str:
|
|
86
|
+
"""
|
|
87
|
+
买入
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
security: 证券代码
|
|
91
|
+
amount: 买入数量
|
|
92
|
+
price: 委托价格(None为市价)
|
|
93
|
+
wait_timeout: 本次下单等待超时(秒),None 表示使用默认配置
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
订单ID
|
|
97
|
+
"""
|
|
98
|
+
raise NotImplementedError
|
|
99
|
+
|
|
100
|
+
@abstractmethod
|
|
101
|
+
async def sell(
|
|
102
|
+
self,
|
|
103
|
+
security: str,
|
|
104
|
+
amount: int,
|
|
105
|
+
price: Optional[float] = None,
|
|
106
|
+
wait_timeout: Optional[float] = None,
|
|
107
|
+
) -> str:
|
|
108
|
+
"""
|
|
109
|
+
卖出
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
security: 证券代码
|
|
113
|
+
amount: 卖出数量
|
|
114
|
+
price: 委托价格(None为市价)
|
|
115
|
+
wait_timeout: 本次下单等待超时(秒),None 表示使用默认配置
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
订单ID
|
|
119
|
+
"""
|
|
120
|
+
raise NotImplementedError
|
|
121
|
+
|
|
122
|
+
@abstractmethod
|
|
123
|
+
async def cancel_order(self, order_id: str) -> bool:
|
|
124
|
+
"""
|
|
125
|
+
撤销订单
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
order_id: 订单ID
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
是否撤销成功
|
|
132
|
+
"""
|
|
133
|
+
raise NotImplementedError
|
|
134
|
+
|
|
135
|
+
@abstractmethod
|
|
136
|
+
async def get_order_status(self, order_id: str) -> Dict[str, Any]:
|
|
137
|
+
"""
|
|
138
|
+
获取订单状态
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
order_id: 订单ID
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
订单信息字典
|
|
145
|
+
"""
|
|
146
|
+
raise NotImplementedError
|
|
147
|
+
|
|
148
|
+
def is_connected(self) -> bool:
|
|
149
|
+
"""
|
|
150
|
+
检查是否已连接
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
是否已连接
|
|
154
|
+
"""
|
|
155
|
+
return self._connected
|
|
156
|
+
|
|
157
|
+
def run_strategy(self, strategy_file: str, **kwargs):
|
|
158
|
+
"""
|
|
159
|
+
运行策略
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
strategy_file: 策略文件路径
|
|
163
|
+
**kwargs: 其他参数
|
|
164
|
+
"""
|
|
165
|
+
raise NotImplementedError("run_strategy 方法尚未实现")
|
|
166
|
+
|
|
167
|
+
def supports_orders_sync(self) -> bool:
|
|
168
|
+
|
|
169
|
+
"""是否支持订单同步钩子(默认否,可以由子类覆盖)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
引擎会在后台任务中调用 sync_orders。
|
|
174
|
+
|
|
175
|
+
"""
|
|
176
|
+
|
|
177
|
+
return False
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def supports_account_sync(self) -> bool:
|
|
182
|
+
|
|
183
|
+
"""是否支持账户同步钩子(默认否,可以由子类覆盖)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
引擎会按配置定期调用 sync_account。
|
|
188
|
+
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
return False
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def sync_orders(self) -> None:
|
|
196
|
+
|
|
197
|
+
"""同步订单状态,子类可按需实现。
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
推荐返回订单快照列表,格式:
|
|
202
|
+
|
|
203
|
+
[{'order_id': str, 'status': 'filled', 'security': '000001.XSHE', ...}, ...]
|
|
204
|
+
|
|
205
|
+
"""
|
|
206
|
+
|
|
207
|
+
return None
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def sync_account(self) -> None:
|
|
212
|
+
|
|
213
|
+
"""同步账户持仓与资金信息,子类可按需实现。
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
推荐返回 dict:
|
|
218
|
+
|
|
219
|
+
{
|
|
220
|
+
|
|
221
|
+
'available_cash': float,
|
|
222
|
+
|
|
223
|
+
'total_value': float,
|
|
224
|
+
|
|
225
|
+
'positions': [
|
|
226
|
+
|
|
227
|
+
{'security': str, 'amount': int, 'avg_cost': float, 'market_value': float}
|
|
228
|
+
|
|
229
|
+
]
|
|
230
|
+
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
"""
|
|
234
|
+
|
|
235
|
+
return None
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def heartbeat(self) -> None:
|
|
240
|
+
|
|
241
|
+
"""触发一次心跳检测,默认空实现。
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
引擎会按照 HEARTBEAT 配置调用,子类可抛出异常提示重连。
|
|
246
|
+
|
|
247
|
+
"""
|
|
248
|
+
|
|
249
|
+
return None
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def cleanup(self) -> None:
|
|
254
|
+
|
|
255
|
+
"""引擎退出前的清理钩子,默认尝试断开连接。
|
|
256
|
+
|
|
257
|
+
"""
|
|
258
|
+
|
|
259
|
+
try:
|
|
260
|
+
|
|
261
|
+
self.disconnect()
|
|
262
|
+
|
|
263
|
+
except Exception:
|
|
264
|
+
|
|
265
|
+
pass
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def supports_tick_subscription(self) -> bool:
|
|
270
|
+
"""是否支持 tick 订阅(默认否,可以由子类覆盖)。"""
|
|
271
|
+
return False
|
|
272
|
+
|
|
273
|
+
def subscribe_ticks(self, symbols: List[str]) -> None:
|
|
274
|
+
"""订阅指定标的 tick 数据,默认不实现。"""
|
|
275
|
+
raise NotImplementedError("当前券商不支持 tick 订阅")
|
|
276
|
+
|
|
277
|
+
def subscribe_markets(self, markets: List[str]) -> None:
|
|
278
|
+
"""订阅全市场 tick(如 ['SH','SZ']),默认不实现。"""
|
|
279
|
+
raise NotImplementedError("当前券商不支持市场级 tick 订阅")
|
|
280
|
+
|
|
281
|
+
def unsubscribe_ticks(self, symbols: Optional[List[str]] = None) -> None:
|
|
282
|
+
"""取消订阅指定标的 tick,symbols=None 表示取消全部。"""
|
|
283
|
+
return None
|
|
284
|
+
|
|
285
|
+
def get_current_tick(self, symbol: str) -> Optional[Dict[str, Any]]:
|
|
286
|
+
"""返回最近的 tick 快照,默认不提供。"""
|
|
287
|
+
return None
|
|
288
|
+
|