qka 1.6.4.dev3__tar.gz → 1.6.5.dev5__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.
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/PKG-INFO +70 -79
- qka-1.6.5.dev5/README.md +136 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/examples/buy_and_hold.md +4 -6
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/examples/ma_cross.md +4 -6
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/examples/momentum.md +2 -3
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/examples/multi_factor.md +2 -3
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/examples/rsi_atr.md +2 -3
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/guides/strategy.md +5 -7
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/guides/trading.md +3 -3
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/index.md +5 -8
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/mkdocs.yml +1 -1
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/pyproject.toml +1 -1
- qka-1.6.5.dev5/skills/qka/SKILL.md +58 -0
- qka-1.6.5.dev5/skills/qka/references/backtest.md +108 -0
- qka-1.6.5.dev5/skills/qka/references/broker.md +92 -0
- qka-1.6.5.dev5/skills/qka/references/data.md +103 -0
- qka-1.6.5.dev5/skills/qka/references/report.md +37 -0
- qka-1.6.5.dev5/skills/qka/references/sizing.md +80 -0
- qka-1.6.5.dev5/skills/qka/references/strategy.md +136 -0
- qka-1.6.5.dev5/tools/generate_api_ref.py +262 -0
- qka-1.6.4.dev3/README.md +0 -145
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/.github/workflows/docs.yml +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/.github/workflows/release.yml +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/.gitignore +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/.vscode/settings.json +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/CHANGELOG.md +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/LICENSE +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/advanced/performance.md +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/api/brokers.md +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/api/core.md +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/api/utils.md +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/guides/backtest.md +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/guides/data.md +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/guides/indicators.md +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/guides/report.md +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/guides/sizing.md +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/docs/user-guide/trading.md +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/__init__.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/brokers/__init__.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/brokers/client.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/brokers/server.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/brokers/trade.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/cli.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/core/__init__.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/core/accessor.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/core/backtest.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/core/broker.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/core/data.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/core/report.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/core/sizing.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/core/strategy.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/mcp/__init__.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/mcp/api.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/mcp/server.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/server/__init__.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/server/handlers/__init__.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/server/handlers/class_inspector_handler.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/server/handlers/code_executor_handler.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/server/ws_client.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/server/zmq_server.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/utils/__init__.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/utils/anis.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/utils/logger.py +0 -0
- {qka-1.6.4.dev3 → qka-1.6.5.dev5}/qka/utils/util.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: qka
|
|
3
|
-
Version: 1.6.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 1.6.5.dev5
|
|
4
|
+
Summary: QKA(快量化 / Quant Kit for A-shares)- 简洁易用的 A 股量化回测框架
|
|
5
5
|
Project-URL: Home, https://github.com/zsrl/qka
|
|
6
6
|
Project-URL: Documentation, https://zsrl.github.io/qka
|
|
7
7
|
Project-URL: Repository, https://github.com/zsrl/qka
|
|
@@ -63,6 +63,7 @@ Requires-Dist: python-semantic-release>=9.0.0; extra == 'dev'
|
|
|
63
63
|
Description-Content-Type: text/markdown
|
|
64
64
|
|
|
65
65
|
# QKA — 快量化
|
|
66
|
+
## Quant Kit for A-shares
|
|
66
67
|
|
|
67
68
|
<p align="center">
|
|
68
69
|
<a href="https://qka.quantai.chat" target="_blank">
|
|
@@ -79,119 +80,109 @@ Description-Content-Type: text/markdown
|
|
|
79
80
|
</a>
|
|
80
81
|
</p>
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
## 三行代码跑回测
|
|
83
|
+
**QKA(快量化 / Quant Kit for A-shares)** — 简洁易用的 A 股量化回测框架。
|
|
87
84
|
|
|
88
85
|
```python
|
|
89
|
-
import
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
86
|
+
from qka import Data, Strategy, Backtest
|
|
87
|
+
|
|
88
|
+
class MyStrategy(Strategy):
|
|
89
|
+
def on_bar(self, date):
|
|
90
|
+
close = self.get('close')
|
|
91
|
+
for sym in close.index:
|
|
92
|
+
if sym not in self.broker.positions:
|
|
93
|
+
price = float(close[sym])
|
|
94
|
+
if price > 0:
|
|
95
|
+
size = self.sizing.percent(0.1, price)
|
|
96
|
+
if size >= 100:
|
|
97
|
+
self.broker.buy(sym, price, size)
|
|
98
|
+
|
|
99
|
+
bt = Backtest(Data(['000001.SZ']), MyStrategy(cash=100_000))
|
|
100
|
+
bt.run(benchmark='000300.SH')
|
|
101
|
+
bt.report()
|
|
93
102
|
```
|
|
94
103
|
|
|
95
|
-
|
|
104
|
+
---
|
|
96
105
|
|
|
97
106
|
## 安装
|
|
98
107
|
|
|
99
108
|
```bash
|
|
100
|
-
# 推荐 — 用 uv
|
|
101
|
-
uv add qka
|
|
102
|
-
|
|
103
|
-
# 或
|
|
104
109
|
pip install qka
|
|
105
110
|
```
|
|
106
111
|
|
|
112
|
+
需要 Python 3.10+。
|
|
113
|
+
|
|
107
114
|
## 快速上手
|
|
108
115
|
|
|
109
|
-
###
|
|
116
|
+
### 数据
|
|
110
117
|
|
|
111
118
|
```python
|
|
112
|
-
import
|
|
119
|
+
from qka import Data
|
|
113
120
|
|
|
114
|
-
data =
|
|
121
|
+
data = Data(
|
|
115
122
|
symbols=['000001.SZ', '600000.SH'],
|
|
116
|
-
|
|
117
|
-
adjust='qfq'
|
|
123
|
+
indicators={'sma_5': ('sma', 5), 'rsi_14': ('rsi', 14)},
|
|
118
124
|
)
|
|
119
|
-
df = data.get()
|
|
125
|
+
df = data.get() # 触发下载,返回宽表 DataFrame
|
|
120
126
|
```
|
|
121
127
|
|
|
122
|
-
###
|
|
128
|
+
### 策略
|
|
123
129
|
|
|
124
130
|
```python
|
|
125
|
-
|
|
126
|
-
def on_bar(self, date, get):
|
|
127
|
-
close = get('close')
|
|
128
|
-
# 价格低于10元买入1000股(注意前复权可能导致早期价格为负)
|
|
129
|
-
if '000001.SZ' in close and 0 < close['000001.SZ'] < 10:
|
|
130
|
-
self.broker.buy('000001.SZ', close['000001.SZ'], 1000)
|
|
131
|
-
```
|
|
131
|
+
from qka import Strategy
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
class MyStrategy(Strategy):
|
|
134
|
+
def __init__(self, cash=100_000):
|
|
135
|
+
super().__init__(cash=cash)
|
|
136
|
+
# 自定义状态放这里
|
|
134
137
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
138
|
+
def on_bar(self, date):
|
|
139
|
+
close = self.get('close')
|
|
140
|
+
hist = self.history('close', 20)
|
|
141
|
+
# 写你的交易逻辑
|
|
139
142
|
```
|
|
140
143
|
|
|
141
|
-
|
|
142
|
-
- 📊 净值曲线 + 基准对比(交互式 Plotly 图表)
|
|
143
|
-
- 📉 回撤曲线
|
|
144
|
-
- 📅 月度收益率热力图
|
|
145
|
-
- 📋 交易明细(含手续费)
|
|
146
|
-
- 🏆 绩效指标:年化收益、夏普比率、最大回撤、胜率、盈亏比……
|
|
147
|
-
|
|
148
|
-
### 4. 调整成本参数
|
|
144
|
+
### 回测
|
|
149
145
|
|
|
150
146
|
```python
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
stamp_duty_rate=0.001, # 印花税千分之一
|
|
155
|
-
slippage=0.001 # 滑点 0.1%
|
|
156
|
-
)
|
|
147
|
+
from qka import Backtest
|
|
148
|
+
|
|
149
|
+
bt = Backtest(data, MyStrategy(cash=100_000))
|
|
157
150
|
bt.run(benchmark='000300.SH')
|
|
151
|
+
print(bt.summary()) # 输出绩效指标
|
|
152
|
+
bt.report() # 生成 HTML 报告
|
|
158
153
|
```
|
|
159
154
|
|
|
160
|
-
|
|
155
|
+
### 更多示例
|
|
161
156
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
| 特性 | 说明 |
|
|
157
|
+
| 策略 | 说明 |
|
|
165
158
|
|------|------|
|
|
166
|
-
|
|
|
167
|
-
|
|
|
168
|
-
|
|
|
169
|
-
|
|
|
170
|
-
|
|
|
171
|
-
| 📉 **基准对比** | 自动获取沪深300做基准,曲线叠加展示 |
|
|
172
|
-
| 💰 **成本模型** | 佣金/印花税/滑点全支持,贴近实盘 |
|
|
173
|
-
| 🔧 **模块化** | 核心、经纪商、MCP、Server 各模块可独立使用 |
|
|
174
|
-
| 📝 **文档完善** | [qka.quantai.chat](https://qka.quantai.chat) |
|
|
175
|
-
|
|
176
|
-
## 核心模块
|
|
159
|
+
| [买入持有与定投](https://qka.quantai.chat/examples/buy_and_hold/) | 买入不动 + 每月定投 |
|
|
160
|
+
| [均线交叉](https://qka.quantai.chat/examples/ma_cross/) | 5日线上穿/下穿20日线 |
|
|
161
|
+
| [RSI + ATR 风控](https://qka.quantai.chat/examples/rsi_atr/) | RSI 超卖买入,ATR 止损 |
|
|
162
|
+
| [动量排序选股](https://qka.quantai.chat/examples/momentum/) | 月度动量排序,Top 5 等权 |
|
|
163
|
+
| [多因子打分](https://qka.quantai.chat/examples/multi_factor/) | PE/ROE/动量/波动率打分选股 |
|
|
177
164
|
|
|
178
|
-
|
|
179
|
-
多数据源、自动缓存、并发下载、统一格式。支持日线/分钟线,前复权/后复权。
|
|
165
|
+
## 核心能力
|
|
180
166
|
|
|
181
|
-
|
|
182
|
-
|
|
167
|
+
- **多数据源** — baostock(默认)、akshare、QMT,自动缓存
|
|
168
|
+
- **预计算指标** — sma/ema/macd/rsi/bbands/atr + 自定义因子
|
|
169
|
+
- **事件驱动回测** — 按日推进,`self.get()` 横截面 + `self.history()` 窗口序列
|
|
170
|
+
- **仓位管理** — `self.sizing.percent()` / `self.sizing.fixed_amount()` / `self.sizing.fixed_shares()` / `self.sizing.atr_risk()`
|
|
171
|
+
- **交易模拟** — 佣金万2.5、印花税万5、滑点0.1%,最低佣金5元
|
|
172
|
+
- **HTML 报告** — Plotly 交互图表,累计收益、回撤、月度热力图、交易明细
|
|
173
|
+
- **基准对比** — 自动下载沪深300(或指定指数)做对比
|
|
183
174
|
|
|
184
|
-
|
|
185
|
-
时间序列驱动,支持多资产、成本模型、基准对比。`run()` 执行,`report()` 出报告,`summary()` 打印绩效指标。
|
|
175
|
+
## 文档
|
|
186
176
|
|
|
187
|
-
|
|
188
|
-
集成 QMT 接口,客户端/服务器架构,支持远程交易。
|
|
177
|
+
完整教程、API 参考、示例代码:
|
|
189
178
|
|
|
190
|
-
|
|
179
|
+
👉 **[qka.quantai.chat](https://qka.quantai.chat)**
|
|
191
180
|
|
|
192
|
-
|
|
181
|
+
## 下一步规划
|
|
193
182
|
|
|
194
|
-
|
|
183
|
+
- [ ] 分钟级数据支持
|
|
184
|
+
- [ ] 自适应参数优化
|
|
185
|
+
- [ ] 实盘交易(QMT 接口)
|
|
195
186
|
|
|
196
187
|
## 许可证
|
|
197
188
|
|
|
@@ -199,11 +190,11 @@ bt.run(benchmark='000300.SH')
|
|
|
199
190
|
|
|
200
191
|
## 致谢
|
|
201
192
|
|
|
202
|
-
- [
|
|
193
|
+
- [baostock](http://baostock.com) — 免费 A 股数据
|
|
194
|
+
- [Akshare](https://github.com/akfamily/akshare) — 补充数据源
|
|
203
195
|
- [Plotly](https://plotly.com/python/) — 交互式图表
|
|
204
|
-
- [
|
|
205
|
-
- [xtquant](https://github.com/ShiMiaoYS/xtquant) — QMT Python 接口
|
|
196
|
+
- [xtquant](https://github.com/ShiMiaoYS/xtquant) — QMT 接口
|
|
206
197
|
|
|
207
198
|
---
|
|
208
199
|
|
|
209
|
-
> ⚠️
|
|
200
|
+
> ⚠️ 量化交易存在风险,请充分了解后再使用本框架。
|
qka-1.6.5.dev5/README.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# QKA — 快量化
|
|
2
|
+
## Quant Kit for A-shares
|
|
3
|
+
|
|
4
|
+
<p align="center">
|
|
5
|
+
<a href="https://qka.quantai.chat" target="_blank">
|
|
6
|
+
<img src="https://img.shields.io/badge/文档站-qka.quantai.chat-blue?style=flat" alt="文档站">
|
|
7
|
+
</a>
|
|
8
|
+
<a href="https://pypi.org/project/qka/">
|
|
9
|
+
<img src="https://img.shields.io/pypi/v/qka?color=blue" alt="PyPI">
|
|
10
|
+
</a>
|
|
11
|
+
<a href="https://github.com/zsrl/qka">
|
|
12
|
+
<img src="https://img.shields.io/badge/python-3.10+-blue" alt="Python">
|
|
13
|
+
</a>
|
|
14
|
+
<a href="LICENSE">
|
|
15
|
+
<img src="https://img.shields.io/badge/license-MIT-green" alt="License">
|
|
16
|
+
</a>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
**QKA(快量化 / Quant Kit for A-shares)** — 简洁易用的 A 股量化回测框架。
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
from qka import Data, Strategy, Backtest
|
|
23
|
+
|
|
24
|
+
class MyStrategy(Strategy):
|
|
25
|
+
def on_bar(self, date):
|
|
26
|
+
close = self.get('close')
|
|
27
|
+
for sym in close.index:
|
|
28
|
+
if sym not in self.broker.positions:
|
|
29
|
+
price = float(close[sym])
|
|
30
|
+
if price > 0:
|
|
31
|
+
size = self.sizing.percent(0.1, price)
|
|
32
|
+
if size >= 100:
|
|
33
|
+
self.broker.buy(sym, price, size)
|
|
34
|
+
|
|
35
|
+
bt = Backtest(Data(['000001.SZ']), MyStrategy(cash=100_000))
|
|
36
|
+
bt.run(benchmark='000300.SH')
|
|
37
|
+
bt.report()
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 安装
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install qka
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
需要 Python 3.10+。
|
|
49
|
+
|
|
50
|
+
## 快速上手
|
|
51
|
+
|
|
52
|
+
### 数据
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from qka import Data
|
|
56
|
+
|
|
57
|
+
data = Data(
|
|
58
|
+
symbols=['000001.SZ', '600000.SH'],
|
|
59
|
+
indicators={'sma_5': ('sma', 5), 'rsi_14': ('rsi', 14)},
|
|
60
|
+
)
|
|
61
|
+
df = data.get() # 触发下载,返回宽表 DataFrame
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 策略
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from qka import Strategy
|
|
68
|
+
|
|
69
|
+
class MyStrategy(Strategy):
|
|
70
|
+
def __init__(self, cash=100_000):
|
|
71
|
+
super().__init__(cash=cash)
|
|
72
|
+
# 自定义状态放这里
|
|
73
|
+
|
|
74
|
+
def on_bar(self, date):
|
|
75
|
+
close = self.get('close')
|
|
76
|
+
hist = self.history('close', 20)
|
|
77
|
+
# 写你的交易逻辑
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 回测
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from qka import Backtest
|
|
84
|
+
|
|
85
|
+
bt = Backtest(data, MyStrategy(cash=100_000))
|
|
86
|
+
bt.run(benchmark='000300.SH')
|
|
87
|
+
print(bt.summary()) # 输出绩效指标
|
|
88
|
+
bt.report() # 生成 HTML 报告
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 更多示例
|
|
92
|
+
|
|
93
|
+
| 策略 | 说明 |
|
|
94
|
+
|------|------|
|
|
95
|
+
| [买入持有与定投](https://qka.quantai.chat/examples/buy_and_hold/) | 买入不动 + 每月定投 |
|
|
96
|
+
| [均线交叉](https://qka.quantai.chat/examples/ma_cross/) | 5日线上穿/下穿20日线 |
|
|
97
|
+
| [RSI + ATR 风控](https://qka.quantai.chat/examples/rsi_atr/) | RSI 超卖买入,ATR 止损 |
|
|
98
|
+
| [动量排序选股](https://qka.quantai.chat/examples/momentum/) | 月度动量排序,Top 5 等权 |
|
|
99
|
+
| [多因子打分](https://qka.quantai.chat/examples/multi_factor/) | PE/ROE/动量/波动率打分选股 |
|
|
100
|
+
|
|
101
|
+
## 核心能力
|
|
102
|
+
|
|
103
|
+
- **多数据源** — baostock(默认)、akshare、QMT,自动缓存
|
|
104
|
+
- **预计算指标** — sma/ema/macd/rsi/bbands/atr + 自定义因子
|
|
105
|
+
- **事件驱动回测** — 按日推进,`self.get()` 横截面 + `self.history()` 窗口序列
|
|
106
|
+
- **仓位管理** — `self.sizing.percent()` / `self.sizing.fixed_amount()` / `self.sizing.fixed_shares()` / `self.sizing.atr_risk()`
|
|
107
|
+
- **交易模拟** — 佣金万2.5、印花税万5、滑点0.1%,最低佣金5元
|
|
108
|
+
- **HTML 报告** — Plotly 交互图表,累计收益、回撤、月度热力图、交易明细
|
|
109
|
+
- **基准对比** — 自动下载沪深300(或指定指数)做对比
|
|
110
|
+
|
|
111
|
+
## 文档
|
|
112
|
+
|
|
113
|
+
完整教程、API 参考、示例代码:
|
|
114
|
+
|
|
115
|
+
👉 **[qka.quantai.chat](https://qka.quantai.chat)**
|
|
116
|
+
|
|
117
|
+
## 下一步规划
|
|
118
|
+
|
|
119
|
+
- [ ] 分钟级数据支持
|
|
120
|
+
- [ ] 自适应参数优化
|
|
121
|
+
- [ ] 实盘交易(QMT 接口)
|
|
122
|
+
|
|
123
|
+
## 许可证
|
|
124
|
+
|
|
125
|
+
[MIT](LICENSE)
|
|
126
|
+
|
|
127
|
+
## 致谢
|
|
128
|
+
|
|
129
|
+
- [baostock](http://baostock.com) — 免费 A 股数据
|
|
130
|
+
- [Akshare](https://github.com/akfamily/akshare) — 补充数据源
|
|
131
|
+
- [Plotly](https://plotly.com/python/) — 交互式图表
|
|
132
|
+
- [xtquant](https://github.com/ShiMiaoYS/xtquant) — QMT 接口
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
> ⚠️ 量化交易存在风险,请充分了解后再使用本框架。
|
|
@@ -12,9 +12,8 @@ from qka import Data, Strategy, Broker, Backtest
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class BuyAndHold(Strategy):
|
|
15
|
-
def __init__(self):
|
|
16
|
-
super().__init__()
|
|
17
|
-
self.broker = Broker(initial_cash=100_000)
|
|
15
|
+
def __init__(self, cash=100_000):
|
|
16
|
+
super().__init__(cash=cash)
|
|
18
17
|
self.bought = False
|
|
19
18
|
|
|
20
19
|
def on_bar(self, date):
|
|
@@ -50,9 +49,8 @@ from qka import Data, Strategy, Broker, Backtest
|
|
|
50
49
|
|
|
51
50
|
|
|
52
51
|
class MonthlyDCA(Strategy):
|
|
53
|
-
def __init__(self):
|
|
54
|
-
super().__init__()
|
|
55
|
-
self.broker = Broker(initial_cash=100_000)
|
|
52
|
+
def __init__(self, cash=100_000):
|
|
53
|
+
super().__init__(cash=cash)
|
|
56
54
|
|
|
57
55
|
def on_bar(self, date):
|
|
58
56
|
# 每月 1 号买入
|
|
@@ -12,9 +12,8 @@ from qka import Data, Strategy, Broker, Backtest
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class MaCross(Strategy):
|
|
15
|
-
def __init__(self):
|
|
16
|
-
super().__init__()
|
|
17
|
-
self.broker = Broker(initial_cash=100_000)
|
|
15
|
+
def __init__(self, cash=100_000):
|
|
16
|
+
super().__init__(cash=cash)
|
|
18
17
|
|
|
19
18
|
def on_bar(self, date):
|
|
20
19
|
close = self.get('close')
|
|
@@ -78,9 +77,8 @@ from qka import Data, Strategy, Broker, Backtest
|
|
|
78
77
|
|
|
79
78
|
|
|
80
79
|
class MultiMaCross(Strategy):
|
|
81
|
-
def __init__(self):
|
|
82
|
-
super().__init__()
|
|
83
|
-
self.broker = Broker(initial_cash=1_000_000)
|
|
80
|
+
def __init__(self, cash=1_000_000):
|
|
81
|
+
super().__init__(cash=cash)
|
|
84
82
|
|
|
85
83
|
def on_bar(self, date):
|
|
86
84
|
close = self.get('close')
|
|
@@ -10,9 +10,8 @@ from qka import Data, Strategy, Broker, Backtest
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class Momentum(Strategy):
|
|
13
|
-
def __init__(self):
|
|
14
|
-
super().__init__()
|
|
15
|
-
self.broker = Broker(initial_cash=1_000_000)
|
|
13
|
+
def __init__(self, cash=1_000_000):
|
|
14
|
+
super().__init__(cash=cash)
|
|
16
15
|
self.last_month = None
|
|
17
16
|
|
|
18
17
|
def on_bar(self, date):
|
|
@@ -10,9 +10,8 @@ from qka import Data, Strategy, Broker, Backtest
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class MultiFactor(Strategy):
|
|
13
|
-
def __init__(self):
|
|
14
|
-
super().__init__()
|
|
15
|
-
self.broker = Broker(initial_cash=1_000_000)
|
|
13
|
+
def __init__(self, cash=1_000_000):
|
|
14
|
+
super().__init__(cash=cash)
|
|
16
15
|
self.last_month = None
|
|
17
16
|
|
|
18
17
|
def on_bar(self, date):
|
|
@@ -10,9 +10,8 @@ from qka import Data, Strategy, Broker, Backtest
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class RsiAtrStrategy(Strategy):
|
|
13
|
-
def __init__(self):
|
|
14
|
-
super().__init__()
|
|
15
|
-
self.broker = Broker(initial_cash=1_000_000)
|
|
13
|
+
def __init__(self, cash=1_000_000):
|
|
14
|
+
super().__init__(cash=cash)
|
|
16
15
|
|
|
17
16
|
def on_bar(self, date):
|
|
18
17
|
close = self.get('close')
|
|
@@ -7,12 +7,11 @@
|
|
|
7
7
|
## 基本结构
|
|
8
8
|
|
|
9
9
|
```python
|
|
10
|
-
from qka import Strategy
|
|
10
|
+
from qka import Strategy
|
|
11
11
|
|
|
12
12
|
class MyStrategy(Strategy):
|
|
13
|
-
def __init__(self):
|
|
14
|
-
super().__init__()
|
|
15
|
-
self.broker = Broker(initial_cash=100_000)
|
|
13
|
+
def __init__(self, cash=100_000):
|
|
14
|
+
super().__init__(cash=cash)
|
|
16
15
|
|
|
17
16
|
def on_bar(self, date):
|
|
18
17
|
close = self.get('close')
|
|
@@ -80,9 +79,8 @@ size = self.sizing.atr_risk(0.02, price, atr) # ATR 风控仓位
|
|
|
80
79
|
|
|
81
80
|
```python
|
|
82
81
|
class MyStrategy(Strategy):
|
|
83
|
-
def __init__(self):
|
|
84
|
-
super().__init__()
|
|
85
|
-
self.broker = Broker(initial_cash=100_000)
|
|
82
|
+
def __init__(self, cash=100_000):
|
|
83
|
+
super().__init__(cash=cash)
|
|
86
84
|
self.bought = False # 自定义状态
|
|
87
85
|
self.entry_prices = {} # 入场价格记录
|
|
88
86
|
```
|
|
@@ -41,12 +41,12 @@ self.broker.sell('000001.SZ', price, size)
|
|
|
41
41
|
|
|
42
42
|
```python
|
|
43
43
|
self.broker.cash # 当前可用资金(¥85,000)
|
|
44
|
-
self.broker.positions # {'000001.SZ': {'size': 1000, '
|
|
44
|
+
self.broker.positions # {'000001.SZ': {'size': 1000, 'avg_price': 10.2}}
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
`positions` 中每只股票包含:
|
|
48
48
|
- `size` — 持仓股数
|
|
49
|
-
- `
|
|
49
|
+
- `avg_price` — 平均买入成本
|
|
50
50
|
|
|
51
51
|
## 完整的买卖流程
|
|
52
52
|
|
|
@@ -70,7 +70,7 @@ def on_bar(self, date):
|
|
|
70
70
|
# 涨幅超过 20% 则卖出
|
|
71
71
|
else:
|
|
72
72
|
pos = self.broker.positions[sym]
|
|
73
|
-
cost = pos['
|
|
73
|
+
cost = pos['avg_price']
|
|
74
74
|
if price / cost - 1 > 0.2:
|
|
75
75
|
self.broker.sell(sym, price, pos['size'])
|
|
76
76
|
```
|
|
@@ -5,8 +5,7 @@ from qka import Data, Strategy, Broker, Backtest
|
|
|
5
5
|
|
|
6
6
|
class MyStrategy(Strategy):
|
|
7
7
|
def __init__(self):
|
|
8
|
-
super().__init__()
|
|
9
|
-
self.broker = Broker(100_000)
|
|
8
|
+
super().__init__(cash=100_000)
|
|
10
9
|
def on_bar(self, date):
|
|
11
10
|
close = self.get('close')
|
|
12
11
|
if close is not None and '000001.SZ' in close.index:
|
|
@@ -39,9 +38,8 @@ from qka import Data, Strategy, Broker, Backtest
|
|
|
39
38
|
class BuyAndHold(Strategy):
|
|
40
39
|
"""买入平安银行,一直持有"""
|
|
41
40
|
|
|
42
|
-
def __init__(self):
|
|
43
|
-
super().__init__()
|
|
44
|
-
self.broker = Broker(initial_cash=100_000)
|
|
41
|
+
def __init__(self, cash=100_000):
|
|
42
|
+
super().__init__(cash=cash)
|
|
45
43
|
self.bought = False
|
|
46
44
|
|
|
47
45
|
def on_bar(self, date):
|
|
@@ -119,9 +117,8 @@ bt.report(title='买入持有策略')
|
|
|
119
117
|
from qka import Data, Strategy, Broker, Backtest
|
|
120
118
|
|
|
121
119
|
class BuyAndHold(Strategy):
|
|
122
|
-
def __init__(self):
|
|
123
|
-
super().__init__()
|
|
124
|
-
self.broker = Broker(initial_cash=100_000)
|
|
120
|
+
def __init__(self, cash=100_000):
|
|
121
|
+
super().__init__(cash=cash)
|
|
125
122
|
self.bought = False
|
|
126
123
|
|
|
127
124
|
def on_bar(self, date):
|
|
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "qka"
|
|
7
7
|
dynamic = ["version"]
|
|
8
|
-
description = "
|
|
8
|
+
description = "QKA(快量化 / Quant Kit for A-shares)- 简洁易用的 A 股量化回测框架"
|
|
9
9
|
authors = [{name = "myc", email = "mayuanchi1029@gmail.com"}]
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
license = {file = "LICENSE"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qka
|
|
3
|
+
description: >
|
|
4
|
+
QKA 框架使用技能。当用户需要基于 QKA 框架编写 A 股量化策略、运行回测、
|
|
5
|
+
处理股票数据、生成报告时使用。涵盖 QKA 全部核心 API 的使用方法。
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# QKA 框架技能
|
|
9
|
+
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
QKA 是一个 A 股量化交易回测框架。核心流程:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
Data(symbols) → Strategy(策略类) → Backtest(回测) → Report(报告)
|
|
16
|
+
↑
|
|
17
|
+
indicators(预计算指标)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**类名约束:** 自定义策略类必须命名为 `MyStrategy`,继承 `Strategy`
|
|
21
|
+
|
|
22
|
+
## 能力边界
|
|
23
|
+
|
|
24
|
+
**能做的策略类型:**
|
|
25
|
+
- 趋势跟踪(双均线、海龟突破、MACD)
|
|
26
|
+
- 均值回归(RSI、Bollinger Bands)
|
|
27
|
+
- 多因子选股(PE/ROE/动量/波动率打分选股,周期 rebalance)
|
|
28
|
+
- 等权/市值加权组合
|
|
29
|
+
- 定投(固定间隔买入固定金额)
|
|
30
|
+
- 大盘 MA 择时、股债轮动
|
|
31
|
+
|
|
32
|
+
**做不了的:**
|
|
33
|
+
- 分钟级/高频(无分钟数据)
|
|
34
|
+
- 期权、期货
|
|
35
|
+
- 机器学习选股(无特征工程管道)
|
|
36
|
+
- 实盘交易
|
|
37
|
+
- 事件驱动(无财报/公告订阅)
|
|
38
|
+
- 多周期策略(仅单周期)
|
|
39
|
+
|
|
40
|
+
## A 股交易规则
|
|
41
|
+
|
|
42
|
+
1. 买入股数必须是 100 的整数倍(一手)
|
|
43
|
+
2. 价格必须 > 0 且不是 NaN
|
|
44
|
+
3. 资金不足时不买入
|
|
45
|
+
4. `sizing.percent()` 和 `sizing.fixed()` 已自动按手取整
|
|
46
|
+
|
|
47
|
+
## 模块索引
|
|
48
|
+
|
|
49
|
+
| 模块 | 文件 | 用途 |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| **Data** | references/data.md | 数据获取、缓存、预计算指标 |
|
|
52
|
+
| **Strategy** | references/strategy.md | 策略编写、on_bar、get/history |
|
|
53
|
+
| **Broker** | references/broker.md | 交易模拟、费用计算 |
|
|
54
|
+
| **Sizing** | references/sizing.md | 仓位计算 |
|
|
55
|
+
| **Backtest** | references/backtest.md | 回测引擎、benchmark |
|
|
56
|
+
| **Report** | references/report.md | 回测报告生成 |
|
|
57
|
+
|
|
58
|
+
按需查阅对应文件,每个文件包含精确的 API 签名、用法示例和常见错误。
|