qka 2.3.1.dev2__py3-none-any.whl → 2.3.2.dev2__py3-none-any.whl

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/core/data.py CHANGED
@@ -4,7 +4,10 @@ QKA数据模块
4
4
  提供统一的数据获取、缓存和管理功能,支持多数据源、多周期、多因子的数据获取。
5
5
  """
6
6
 
7
+ import contextlib
8
+ import io
7
9
  import os
10
+ import threading
8
11
  from pathlib import Path
9
12
  from tqdm import tqdm
10
13
  from concurrent.futures import ThreadPoolExecutor, as_completed
@@ -1108,13 +1111,22 @@ class Data():
1108
1111
  # ── TickFlow 数据源 ────────────────────────────────────────
1109
1112
 
1110
1113
  _tf_client = None # 进程级复用,避免重复初始化
1114
+ _tf_client_lock = threading.Lock()
1111
1115
 
1112
1116
  @classmethod
1113
1117
  def _tickflow_client(cls):
1114
1118
  """惰性创建并复用 TickFlow 客户端(当前走免费服务,无需 api_key)。"""
1115
1119
  if cls._tf_client is None:
1116
- from tickflow import TickFlow
1117
- cls._tf_client = TickFlow.free()
1120
+ with cls._tf_client_lock:
1121
+ if cls._tf_client is None:
1122
+ from tickflow import TickFlow
1123
+ # TickFlow.free() 会往 stdout 打一段带 emoji 的「免费档」说明。
1124
+ # stdout 被重定向到文件、且编码非 UTF-8 时(如打包版把后端输出
1125
+ # 写入 GBK 日志),print emoji 会抛 UnicodeEncodeError 而中断下载,
1126
+ # 故创建期间丢弃其标准输出。(redirect_stdout 改的是全局 sys.stdout,
1127
+ # 并发首次创建会互相覆盖,故用锁串行化。)
1128
+ with contextlib.redirect_stdout(io.StringIO()):
1129
+ cls._tf_client = TickFlow.free()
1118
1130
  return cls._tf_client
1119
1131
 
1120
1132
  @staticmethod
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: qka
3
- Version: 2.3.1.dev2
3
+ Version: 2.3.2.dev2
4
4
  Summary: QKA(快量化 / Quant Kit for A-shares)- 简洁易用的 A 股量化回测框架
5
5
  Project-URL: Home, https://github.com/zsrl/qka
6
6
  Project-URL: Repository, https://github.com/zsrl/qka
@@ -5,7 +5,7 @@ qka/core/accessor.py,sha256=iEZrteVe8nqv3s5Va2l3Vz50N2S6X0IOElKq9Ik3Wno,2893
5
5
  qka/core/analysis.py,sha256=EXCO4qhzd2av5Yb4jihcNji1V-VFPOceUHKtg-q8bLs,11142
6
6
  qka/core/backtest.py,sha256=kzMAFbyGFvGE--Qypiot6wAp0jTiEsOPbaPd8Zs3o1M,13541
7
7
  qka/core/broker.py,sha256=FxeHh9qZ9M6FNFLd8EXwztA4kmC9zZzkrXin2hdVFa4,9662
8
- qka/core/data.py,sha256=srnN8_XAbJzxQslgNYV3ocPlZyQUmpz2ikTbh60VAHE,55299
8
+ qka/core/data.py,sha256=NFMQseRTRWeHK0qW9n2W3vYopxd9d1ukoOrNS1DMyPM,56052
9
9
  qka/core/indicator.py,sha256=l6KxGw75YbnDGzVs04--f-9gLiwAYKfQ8JhuTTNHADU,6453
10
10
  qka/core/report.py,sha256=TaZoxWk7ZIPLhA9Ss9UOmxWY2ymzKJRUnxSzmyPcBTI,22386
11
11
  qka/core/simulate.py,sha256=bdThckUFj0Y3GyAj5ahLIGv3HetJFTbyxbEcX2SUKn0,2915
@@ -20,8 +20,8 @@ qka/skills/qka/references/broker.md,sha256=wr62v1asRM-wBdsADIsB406eXm_ENYcrwGMAN
20
20
  qka/skills/qka/references/data.md,sha256=FeJlfcBylAywCngQhbG0y1x3Vgqf_tgyGtz5my8i84U,21768
21
21
  qka/skills/qka/references/sizing.md,sha256=3SsX2ddQoHjE177dberW0Q7wYxW-M_2DG_-sV3CCo9A,656
22
22
  qka/skills/qka/references/strategy.md,sha256=e6nZHaWu8SDbbka_nX6XJslTRwp-oOQEMLZS10FZMog,4461
23
- qka-2.3.1.dev2.dist-info/METADATA,sha256=5k1VjjZB1IUPWZOvcWKml403ULnVRZOeKXqrkS9JJ6Y,7138
24
- qka-2.3.1.dev2.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
25
- qka-2.3.1.dev2.dist-info/entry_points.txt,sha256=quG9zg-rOKKtbg-6FiXkoxkUUTMltMBD0hZ0QUnJ6RM,37
26
- qka-2.3.1.dev2.dist-info/licenses/LICENSE,sha256=3iIG35SnJNF11yIzm3vxa2QUvy9SS5rktM3O1DL2vqM,1075
27
- qka-2.3.1.dev2.dist-info/RECORD,,
23
+ qka-2.3.2.dev2.dist-info/METADATA,sha256=x7aDnWE5B1BzgVZ37OqPh2eNWB9uZJ4wB0oBLEFVDhg,7138
24
+ qka-2.3.2.dev2.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
25
+ qka-2.3.2.dev2.dist-info/entry_points.txt,sha256=quG9zg-rOKKtbg-6FiXkoxkUUTMltMBD0hZ0QUnJ6RM,37
26
+ qka-2.3.2.dev2.dist-info/licenses/LICENSE,sha256=3iIG35SnJNF11yIzm3vxa2QUvy9SS5rktM3O1DL2vqM,1075
27
+ qka-2.3.2.dev2.dist-info/RECORD,,