qka 1.0.3.dev1__tar.gz → 1.0.4.dev1__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.
Files changed (66) hide show
  1. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/PKG-INFO +1 -1
  2. qka-1.0.4.dev1/docs/user-guide/backtest.md +465 -0
  3. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/examples/simple_backtest_demo.py +5 -8
  4. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/mkdocs.yml +0 -1
  5. qka-1.0.4.dev1/qka/__init__.py +40 -0
  6. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/core/__init__.py +2 -2
  7. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/core/backtest.py +328 -357
  8. qka-1.0.4.dev1/qka/core/plot.py +218 -0
  9. qka-1.0.3.dev1/docs/user-guide/backtest.md +0 -418
  10. qka-1.0.3.dev1/qka/__init__.py +0 -24
  11. qka-1.0.3.dev1/qka/core/data/config.py +0 -40
  12. qka-1.0.3.dev1/qka/core/data/factory.py +0 -37
  13. qka-1.0.3.dev1/qka/core/data/sources.py +0 -40
  14. qka-1.0.3.dev1/qka/core/plot.py +0 -90
  15. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/.github/workflows/docs.yml +0 -0
  16. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/.github/workflows/release.yml +0 -0
  17. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/.gitignore +0 -0
  18. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/.vscode/settings.json +0 -0
  19. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/CHANGELOG.md +0 -0
  20. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/LICENSE +0 -0
  21. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/README.md +0 -0
  22. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/A/350/202/241/345/270/202/345/234/272/350/257/201/345/210/270/344/273/243/347/240/201/345/221/275/345/220/215/350/247/204/345/210/231.md" +0 -0
  23. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/api/brokers/index.md +0 -0
  24. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/api/core/config.md +0 -0
  25. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/api/core/events.md +0 -0
  26. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/api/core/index.md +0 -0
  27. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/api/index.md +0 -0
  28. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/api/mcp/index.md +0 -0
  29. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/api/utils/index.md +0 -0
  30. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/api/utils/logger.md +0 -0
  31. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/api/utils/tools.md +0 -0
  32. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/enhanced_features_phase1.md +0 -0
  33. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/examples/index.md +0 -0
  34. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/getting-started/concepts.md +0 -0
  35. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/getting-started/first-strategy.md +0 -0
  36. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/getting-started/installation.md +0 -0
  37. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/index.md +0 -0
  38. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/user-guide/config.md +0 -0
  39. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/user-guide/data.md +0 -0
  40. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/user-guide/events.md +0 -0
  41. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/user-guide/logging.md +0 -0
  42. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/user-guide/strategy.md +0 -0
  43. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/docs/user-guide/trading.md +0 -0
  44. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/examples/basic_test.py +0 -0
  45. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/examples/enhanced_features_demo.py +0 -0
  46. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/examples/simple_demo.py +0 -0
  47. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/pyproject.toml +0 -0
  48. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/brokers/__init__.py +0 -0
  49. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/brokers/client.py +0 -0
  50. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/brokers/server.py +0 -0
  51. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/brokers/trade.py +0 -0
  52. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/core/config.py +0 -0
  53. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/core/data/__init__.py +0 -0
  54. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/core/data/akshare.py +0 -0
  55. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/core/data/base.py +0 -0
  56. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/core/data/qmt.py +0 -0
  57. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/core/events.py +0 -0
  58. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/mcp/__init__.py +0 -0
  59. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/mcp/api.py +0 -0
  60. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/mcp/server.py +0 -0
  61. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/utils/__init__.py +0 -0
  62. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/utils/anis.py +0 -0
  63. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/utils/logger.py +0 -0
  64. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/utils/tools.py +0 -0
  65. {qka-1.0.3.dev1 → qka-1.0.4.dev1}/qka/utils/util.py +0 -0
  66. {qka-1.0.3.dev1 → qka-1.0.4.dev1}//345/267/245/344/275/234/350/277/233/345/272/246/350/256/260/345/275/225.md" +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qka
3
- Version: 1.0.3.dev1
3
+ Version: 1.0.4.dev1
4
4
  Summary: 快捷量化助手(Quick Quantitative Assistant)- 简洁易用的A股量化交易框架
5
5
  Project-URL: Home, https://github.com/zsrl/qka
6
6
  Project-URL: Documentation, https://zsrl.github.io/qka
@@ -0,0 +1,465 @@
1
+ # 回测分析
2
+
3
+ QKA 提供了简洁易用的回测功能,帮助您快速验证交易策略的有效性。
4
+
5
+ ## 快速开始
6
+
7
+ ### 三步完成回测
8
+
9
+ QKA 回测非常简单,只需三步:
10
+
11
+ ```python
12
+ import qka
13
+
14
+ # 第1步:获取数据
15
+ data_obj = qka.data(stocks=['000001', '000002']) # 默认使用akshare数据源
16
+
17
+ # 第2步:定义策略
18
+ class SimpleStrategy(qka.Strategy):
19
+ def on_bar(self, data, broker, current_date):
20
+ for symbol, df in data.items():
21
+ if len(df) >= 20:
22
+ price = df['close'].iloc[-1]
23
+ ma20 = df['close'].rolling(20).mean().iloc[-1]
24
+
25
+ if price > ma20: # 突破均线买入
26
+ broker.buy(symbol, 0.5, price)
27
+ elif price < ma20: # 跌破均线卖出
28
+ broker.sell(symbol, 1.0, price)
29
+
30
+ # 第3步:运行回测并查看结果
31
+ result = qka.backtest(data_obj, SimpleStrategy(), start_time='2023-01-01', end_time='2023-12-31')
32
+
33
+ print(f"总收益率: {result['total_return']:.2%}")
34
+ print(f"年化收益率: {result['annual_return']:.2%}")
35
+ print(f"夏普比率: {result['sharpe_ratio']:.2f}")
36
+ ```
37
+
38
+ > **数据源说明**: 默认使用akshare数据源。如需使用其他数据源,可以调用 `set_source('qmt')` 或在 `data()` 函数中指定 `source` 参数。
39
+
40
+ ## 策略开发
41
+
42
+ ### 策略基类
43
+
44
+ 所有策略都需要继承 `qka.Strategy` 基类:
45
+
46
+ ```python
47
+ import qka
48
+
49
+ class MyStrategy(qka.Strategy):
50
+ def on_bar(self, data, broker, current_date):
51
+ """
52
+ 每个交易日调用的策略逻辑
53
+
54
+ Args:
55
+ data: 历史数据字典 {股票代码: DataFrame}
56
+ broker: 交易接口
57
+ current_date: 当前日期
58
+ """
59
+ # 在这里实现你的策略逻辑
60
+ pass
61
+
62
+ def on_start(self, broker):
63
+ """回测开始时调用"""
64
+ print(f"策略 {self.name} 开始运行")
65
+
66
+ def on_end(self, broker):
67
+ """回测结束时调用"""
68
+ print(f"策略 {self.name} 运行结束")
69
+ ```
70
+
71
+ ### 策略示例
72
+
73
+ #### 移动平均策略
74
+
75
+ ```python
76
+ class MovingAverageStrategy(qka.Strategy):
77
+ def __init__(self, short_window=5, long_window=20):
78
+ super().__init__()
79
+ self.short_window = short_window
80
+ self.long_window = long_window
81
+
82
+ def on_bar(self, data, broker, current_date):
83
+ for symbol, df in data.items():
84
+ if len(df) < self.long_window:
85
+ continue
86
+
87
+ # 计算短期和长期移动平均
88
+ short_ma = df['close'].rolling(self.short_window).mean().iloc[-1]
89
+ long_ma = df['close'].rolling(self.long_window).mean().iloc[-1]
90
+ current_price = df['close'].iloc[-1]
91
+
92
+ # 金叉买入,死叉卖出
93
+ if short_ma > long_ma and broker.get_position(symbol) == 0:
94
+ broker.buy(symbol, 0.3, current_price) # 用30%资金买入
95
+ elif short_ma < long_ma and broker.get_position(symbol) > 0:
96
+ broker.sell(symbol, 1.0, current_price) # 全部卖出
97
+ ```
98
+
99
+ #### 布林带策略
100
+
101
+ ```python
102
+ class BollingerBandStrategy(qka.Strategy):
103
+ def __init__(self, window=20, num_std=2):
104
+ super().__init__()
105
+ self.window = window
106
+ self.num_std = num_std
107
+
108
+ def on_bar(self, data, broker, current_date):
109
+ for symbol, df in data.items():
110
+ if len(df) < self.window:
111
+ continue
112
+
113
+ # 计算布林带
114
+ close_prices = df['close']
115
+ rolling_mean = close_prices.rolling(self.window).mean().iloc[-1]
116
+ rolling_std = close_prices.rolling(self.window).std().iloc[-1]
117
+
118
+ upper_band = rolling_mean + (rolling_std * self.num_std)
119
+ lower_band = rolling_mean - (rolling_std * self.num_std)
120
+ current_price = close_prices.iloc[-1]
121
+
122
+ # 价格突破下轨买入,突破上轨卖出
123
+ if current_price < lower_band and broker.get_position(symbol) == 0:
124
+ broker.buy(symbol, 0.4, current_price)
125
+ elif current_price > upper_band and broker.get_position(symbol) > 0:
126
+ broker.sell(symbol, 1.0, current_price)
127
+ ```
128
+
129
+ ## 交易接口
130
+
131
+ ### Broker 类
132
+
133
+ `Broker` 类提供了所有交易相关的功能:
134
+
135
+ ```python
136
+ # 获取当前持仓
137
+ position = broker.get_position('000001') # 返回持仓股数
138
+
139
+ # 获取可用现金
140
+ cash = broker.get_cash()
141
+
142
+ # 获取所有持仓
143
+ positions = broker.get_positions() # 返回 {股票代码: 持仓数量}
144
+
145
+ # 计算总资产
146
+ prices = {'000001': 10.5, '000002': 8.3}
147
+ total_value = broker.get_total_value(prices)
148
+ ```
149
+
150
+ ### 买入操作
151
+
152
+ ```python
153
+ # 按比例买入(推荐)
154
+ broker.buy('000001', 0.3, price) # 用30%的资金买入
155
+
156
+ # 按股数买入
157
+ broker.buy('000001', 1000, price) # 买入1000股(自动调整为整手)
158
+
159
+ # 买入条件检查
160
+ if broker.get_cash() > 10000: # 现金充足
161
+ if broker.get_position('000001') == 0: # 没有持仓
162
+ broker.buy('000001', 0.2, current_price)
163
+ ```
164
+
165
+ ### 卖出操作
166
+
167
+ ```python
168
+ # 按比例卖出
169
+ broker.sell('000001', 0.5, price) # 卖出50%的持仓
170
+ broker.sell('000001', 1.0, price) # 全部卖出
171
+
172
+ # 按股数卖出
173
+ broker.sell('000001', 500, price) # 卖出500股
174
+
175
+ # 卖出条件检查
176
+ if broker.get_position('000001') > 0: # 有持仓
177
+ broker.sell('000001', 1.0, current_price) # 全部卖出
178
+ ```
179
+
180
+ ## 回测配置
181
+
182
+ ### 基本配置
183
+
184
+ ```python
185
+ import qka
186
+
187
+ # 自定义 Broker 配置
188
+ custom_broker = qka.Broker(
189
+ initial_cash=500000, # 初始资金50万
190
+ commission_rate=0.0003 # 手续费率0.03%
191
+ )
192
+
193
+ # 使用自定义配置运行回测
194
+ result = qka.backtest(
195
+ data=data_obj,
196
+ strategy=MyStrategy(),
197
+ broker=custom_broker,
198
+ start_time='2023-01-01',
199
+ end_time='2023-12-31'
200
+ )
201
+ ```
202
+
203
+ ### 数据获取
204
+
205
+ ```python
206
+ import qka
207
+
208
+ # 使用默认数据源(akshare)
209
+ data_obj = qka.data(stocks=['000001'])
210
+
211
+ # 多只股票
212
+ data_obj = qka.data(stocks=['000001', '000002', '600000'])
213
+
214
+ # 设置全局数据源
215
+ qka.set_source('qmt')
216
+ data_obj = qka.data(stocks=['000001.SZ', '600000.SH']) # QMT格式股票代码
217
+
218
+ # 临时指定数据源
219
+ data_obj = qka.data(stocks=['000001'], source='akshare')
220
+ ```
221
+
222
+ ## 回测结果分析
223
+
224
+ ### 基本指标
225
+
226
+ 回测结果包含以下关键指标:
227
+
228
+ ```python
229
+ # 基本收益指标
230
+ print(f"初始资金: {result['initial_capital']:,.0f}")
231
+ print(f"最终资产: {result['final_value']:,.0f}")
232
+ print(f"总收益率: {result['total_return']:.2%}")
233
+ print(f"年化收益率: {result['annual_return']:.2%}")
234
+
235
+ # 风险指标
236
+ print(f"收益波动率: {result['volatility']:.2%}")
237
+ print(f"夏普比率: {result['sharpe_ratio']:.2f}")
238
+ print(f"最大回撤: {result['max_drawdown']:.2%}")
239
+
240
+ # 交易指标
241
+ print(f"总交易次数: {result['total_trades']}")
242
+ print(f"总手续费: {result['total_commission']:,.2f}")
243
+ print(f"胜率: {result['win_rate']:.2%}")
244
+ print(f"交易天数: {result['trading_days']}")
245
+ ```
246
+
247
+ ### 详细数据
248
+
249
+ ```python
250
+ # 每日净值数据
251
+ daily_values = result['daily_values']
252
+ for record in daily_values[:5]: # 显示前5天
253
+ print(f"日期: {record['date']}, 总资产: {record['total_value']:,.2f}")
254
+
255
+ # 交易记录
256
+ trades = result['trades']
257
+ for trade in trades[:5]: # 显示前5笔交易
258
+ print(f"{trade['date']}: {trade['action']} {trade['symbol']} "
259
+ f"{trade['shares']}股 @{trade['price']}")
260
+
261
+ # 最终持仓
262
+ positions = result['positions']
263
+ print(f"最终持仓: {positions}")
264
+ ```
265
+
266
+ ## 结果可视化
267
+
268
+ ```python
269
+ import qka
270
+
271
+ # 绘制回测结果图表
272
+ qka.plot(result)
273
+ ```
274
+
275
+ ## 策略开发技巧
276
+
277
+ ### 数据处理
278
+
279
+ ```python
280
+ def on_bar(self, data, broker, current_date):
281
+ for symbol, df in data.items():
282
+ # 检查数据长度
283
+ if len(df) < 20:
284
+ continue
285
+
286
+ # 获取最新价格
287
+ current_price = df['close'].iloc[-1]
288
+
289
+ # 计算技术指标
290
+ sma_20 = df['close'].rolling(20).mean().iloc[-1]
291
+ rsi = self.calculate_rsi(df['close'], 14)
292
+
293
+ # 处理缺失值
294
+ if pd.isna(sma_20) or pd.isna(rsi):
295
+ continue
296
+
297
+ # 策略逻辑
298
+ if rsi < 30 and current_price > sma_20:
299
+ broker.buy(symbol, 0.2, current_price)
300
+ ```
301
+
302
+ ### 风险控制
303
+
304
+ ```python
305
+ def on_bar(self, data, broker, current_date):
306
+ for symbol, df in data.items():
307
+ current_price = df['close'].iloc[-1]
308
+ position = broker.get_position(symbol)
309
+
310
+ # 止损逻辑
311
+ if position > 0:
312
+ avg_cost = broker.avg_costs.get(symbol, current_price)
313
+ if current_price < avg_cost * 0.95: # 5%止损
314
+ broker.sell(symbol, 1.0, current_price)
315
+ continue
316
+
317
+ # 仓位控制
318
+ total_value = broker.get_total_value({symbol: current_price})
319
+ position_value = position * current_price
320
+ position_ratio = position_value / total_value
321
+
322
+ if position_ratio > 0.3: # 单只股票最大30%仓位
323
+ continue
324
+
325
+ # 买入逻辑
326
+ # ...
327
+ ```
328
+
329
+ ### 多股票策略
330
+
331
+ ```python
332
+ class MultiStockStrategy(qka.Strategy):
333
+ def on_bar(self, data, broker, current_date):
334
+ # 收集所有股票的信号
335
+ signals = {}
336
+ for symbol, df in data.items():
337
+ if len(df) >= 20:
338
+ signal = self.calculate_signal(df)
339
+ signals[symbol] = signal
340
+
341
+ # 按信号强度排序
342
+ sorted_signals = sorted(signals.items(),
343
+ key=lambda x: x[1], reverse=True)
344
+
345
+ # 只选择前3只股票
346
+ selected_stocks = sorted_signals[:3]
347
+
348
+ # 平均分配资金
349
+ for symbol, signal in selected_stocks:
350
+ if signal > 0.5 and broker.get_position(symbol) == 0:
351
+ broker.buy(symbol, 0.3, data[symbol]['close'].iloc[-1])
352
+ ```
353
+
354
+ ## 最佳实践
355
+
356
+ ### 1. 数据质量检查
357
+
358
+ ```python
359
+ def on_bar(self, data, broker, current_date):
360
+ for symbol, df in data.items():
361
+ # 检查价格合理性
362
+ current_price = df['close'].iloc[-1]
363
+ if current_price <= 0 or pd.isna(current_price):
364
+ continue
365
+
366
+ # 检查成交量
367
+ volume = df['volume'].iloc[-1]
368
+ if volume <= 0:
369
+ continue
370
+
371
+ # 策略逻辑
372
+ # ...
373
+ ```
374
+
375
+ ### 2. 参数化策略
376
+
377
+ ```python
378
+ class ParameterizedStrategy(qka.Strategy):
379
+ def __init__(self, ma_period=20, position_size=0.3, stop_loss=0.05):
380
+ super().__init__()
381
+ self.ma_period = ma_period
382
+ self.position_size = position_size
383
+ self.stop_loss = stop_loss
384
+
385
+ def on_bar(self, data, broker, current_date):
386
+ for symbol, df in data.items():
387
+ if len(df) < self.ma_period:
388
+ continue
389
+
390
+ current_price = df['close'].iloc[-1]
391
+ ma = df['close'].rolling(self.ma_period).mean().iloc[-1]
392
+
393
+ # 使用参数化的逻辑
394
+ if current_price > ma:
395
+ broker.buy(symbol, self.position_size, current_price)
396
+ ```
397
+
398
+ ### 3. 策略状态管理
399
+
400
+ ```python
401
+ class StatefulStrategy(qka.Strategy):
402
+ def __init__(self):
403
+ super().__init__()
404
+ self.last_signal = {}
405
+ self.entry_prices = {}
406
+
407
+ def on_bar(self, data, broker, current_date):
408
+ for symbol, df in data.items():
409
+ # 保存策略状态
410
+ current_signal = self.calculate_signal(df)
411
+ last_signal = self.last_signal.get(symbol, 0)
412
+
413
+ # 信号变化时才交易
414
+ if current_signal != last_signal:
415
+ if current_signal > 0:
416
+ price = df['close'].iloc[-1]
417
+ broker.buy(symbol, 0.3, price)
418
+ self.entry_prices[symbol] = price
419
+ else:
420
+ broker.sell(symbol, 1.0, df['close'].iloc[-1])
421
+ self.entry_prices.pop(symbol, None)
422
+
423
+ self.last_signal[symbol] = current_signal
424
+ ```
425
+
426
+ ## 常见问题
427
+
428
+ ### Q: 如何处理停牌股票?
429
+
430
+ ```python
431
+ def on_bar(self, data, broker, current_date):
432
+ for symbol, df in data.items():
433
+ # 检查是否停牌
434
+ if current_date not in df.index:
435
+ continue # 跳过停牌股票
436
+
437
+ current_price = df.loc[current_date, 'close']
438
+ if current_price == 0:
439
+ continue # 价格为0可能是停牌
440
+ ```
441
+
442
+ ### Q: 如何避免未来函数?
443
+
444
+ ```python
445
+ def on_bar(self, data, broker, current_date):
446
+ for symbol, df in data.items():
447
+ # 只使用当前日期之前的数据
448
+ historical_data = df.loc[:current_date]
449
+
450
+ # 计算指标时确保不使用未来数据
451
+ sma = historical_data['close'].rolling(20).mean().iloc[-1]
452
+ ```
453
+
454
+ ### Q: 如何处理数据缺失?
455
+
456
+ ```python
457
+ def on_bar(self, data, broker, current_date):
458
+ for symbol, df in data.items():
459
+ # 检查关键数据是否缺失
460
+ if df[['open', 'high', 'low', 'close', 'volume']].iloc[-1].isna().any():
461
+ continue
462
+
463
+ # 使用前向填充处理缺失值
464
+ df_filled = df.fillna(method='ffill')
465
+ ```
@@ -3,13 +3,10 @@ QKA 简化回测API演示 - 极简版本
3
3
  只需3步:获取数据 -> 定义策略 -> 运行回测
4
4
  """
5
5
 
6
- import pandas as pd
7
- from qka.core.data import data
8
- from qka.core.backtest import backtest, Strategy
9
- from qka.core.plot import plot_backtest
6
+ import qka
10
7
 
11
8
  # 第1步:定义策略
12
- class SimpleStrategy(Strategy):
9
+ class SimpleStrategy(qka.Strategy):
13
10
  def on_bar(self, data, broker, current_date):
14
11
  for symbol, df in data.items():
15
12
  if len(df) < 20: # 需要足够的历史数据
@@ -28,17 +25,17 @@ class SimpleStrategy(Strategy):
28
25
  # 第2步:获取数据并运行回测
29
26
  if __name__ == "__main__":
30
27
  # 获取数据
31
- data_obj = data('akshare', stocks=['000001', '000002'])
28
+ data_obj = qka.data(stocks=['000001', '000002']) # 使用默认数据源
32
29
 
33
30
  # 运行回测
34
- result = backtest(
31
+ result = qka.backtest(
35
32
  data=data_obj,
36
33
  strategy=SimpleStrategy(),
37
34
  start_time='2023-01-01',
38
35
  end_time='2023-12-31'
39
36
  )
40
37
 
41
- plot_backtest(result)
38
+ qka.plot(result)
42
39
 
43
40
  # 第3步:查看结果
44
41
  print(f"总收益率: {result['total_return']:.2%}")
@@ -124,7 +124,6 @@ nav:
124
124
  - 基础概念: getting-started/concepts.md
125
125
  - 用户指南:
126
126
  - 数据获取: user-guide/data.md
127
- - 策略开发: user-guide/strategy.md
128
127
  - 回测分析: user-guide/backtest.md
129
128
  - 实盘交易: user-guide/trading.md
130
129
  - 配置管理: user-guide/config.md
@@ -0,0 +1,40 @@
1
+ """
2
+ QKA - 量化交易框架
3
+
4
+ 统一的访问接口,支持 qka.xxx 的访问模式
5
+ """
6
+
7
+ from importlib.metadata import version, PackageNotFoundError
8
+
9
+ try:
10
+ __version__ = version("qka")
11
+ except PackageNotFoundError:
12
+ __version__ = "0.1.0" # fallback version
13
+
14
+ # 核心功能直接导入
15
+ from qka.core.data import data, set_source, get_source, register_data_source, get_available_sources
16
+ from qka.core.backtest import backtest, Strategy, Broker
17
+ from qka.core.config import config, load_config
18
+ from qka.core.events import event_engine, emit_event
19
+ from qka.core.plot import plot
20
+
21
+ # 子模块导入
22
+ from qka import core, utils, mcp
23
+
24
+ # 交易相关(有依赖的模块暂时不导入,避免导入错误)
25
+ # from qka.brokers.trade import create_trader
26
+ # from qka.brokers.client import QMTClient
27
+ # from qka.brokers.server import QMTServer
28
+
29
+ __all__ = [
30
+ # 核心功能
31
+ 'data', 'backtest', 'Strategy', 'Broker', 'plot',
32
+ # 配置
33
+ 'config', 'load_config',
34
+ # 数据源管理
35
+ 'set_source', 'get_source', 'register_data_source', 'get_available_sources',
36
+ # 事件系统
37
+ 'event_engine', 'emit_event',
38
+ # 子模块
39
+ 'core', 'utils', 'mcp'
40
+ ]
@@ -7,11 +7,11 @@ from .data import data
7
7
  from .backtest import backtest, Strategy
8
8
  from .config import config, load_config
9
9
  from .events import EventType, event_engine, emit_event, start_event_engine, stop_event_engine
10
- from .plot import plot_backtest
10
+ from .plot import plot
11
11
 
12
12
  __all__ = [
13
13
  'data', 'backtest', 'Strategy',
14
14
  'config', 'load_config',
15
15
  'EventType', 'event_engine', 'emit_event', 'start_event_engine', 'stop_event_engine',
16
- 'plot_backtest'
16
+ 'plot'
17
17
  ]