hikyuu 2.6.8.4__py3-none-manylinux2014_x86_64.whl → 2.6.9__py3-none-manylinux2014_x86_64.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.
- hikyuu/__init__.py +5 -12
- hikyuu/__init__.pyi +612 -587
- hikyuu/analysis/__init__.pyi +589 -563
- hikyuu/analysis/analysis.pyi +590 -564
- hikyuu/core.py +2 -0
- hikyuu/core.pyi +591 -565
- hikyuu/cpp/__init__.pyi +2 -2
- hikyuu/cpp/core310.pyi +446 -13
- hikyuu/cpp/core310.so +0 -0
- hikyuu/cpp/core311.pyi +440 -13
- hikyuu/cpp/core311.so +0 -0
- hikyuu/cpp/core312.pyi +440 -13
- hikyuu/cpp/core312.so +0 -0
- hikyuu/cpp/core313.pyi +446 -13
- hikyuu/cpp/core313.so +0 -0
- hikyuu/cpp/i18n/zh_CN/hikyuu.mo +0 -0
- hikyuu/cpp/libboost_charconv-mt.so +0 -0
- hikyuu/cpp/libboost_charconv-mt.so.1.88.0 +0 -0
- hikyuu/cpp/libboost_chrono-mt.so +0 -0
- hikyuu/cpp/libboost_chrono-mt.so.1.88.0 +0 -0
- hikyuu/cpp/libboost_date_time-mt.so +0 -0
- hikyuu/cpp/libboost_date_time-mt.so.1.88.0 +0 -0
- hikyuu/cpp/libboost_serialization-mt.so +0 -0
- hikyuu/cpp/libboost_serialization-mt.so.1.88.0 +0 -0
- hikyuu/cpp/libboost_system-mt.so +0 -0
- hikyuu/cpp/libboost_system-mt.so.1.88.0 +0 -0
- hikyuu/cpp/libboost_thread-mt.so +0 -0
- hikyuu/cpp/libboost_thread-mt.so.1.88.0 +0 -0
- hikyuu/cpp/libboost_wserialization-mt.so +0 -0
- hikyuu/cpp/libboost_wserialization-mt.so.1.88.0 +0 -0
- hikyuu/cpp/libhikyuu.so +0 -0
- hikyuu/cpp/libsqlite3.so +0 -0
- hikyuu/data/clickhouse_upgrade/createdb.sql +105 -105
- hikyuu/data/common.py +3 -3
- hikyuu/data/common_clickhouse.py +1 -1
- hikyuu/data/download_block.py +318 -0
- hikyuu/data/em_block_to_clickhouse.py +26 -74
- hikyuu/data/em_block_to_mysql.py +25 -75
- hikyuu/data/em_block_to_sqlite.py +26 -78
- hikyuu/data/hku_config_template.py +3 -3
- hikyuu/data/pytdx_to_clickhouse.py +15 -11
- hikyuu/data/pytdx_to_h5.py +6 -2
- hikyuu/data/pytdx_to_mysql.py +5 -1
- hikyuu/data/pytdx_weight_to_clickhouse.py +1 -1
- hikyuu/data/pytdx_weight_to_mysql.py +1 -1
- hikyuu/data/pytdx_weight_to_sqlite.py +1 -1
- hikyuu/data/zh_bond10_to_clickhouse.py +1 -1
- hikyuu/draw/drawplot/__init__.pyi +8 -8
- hikyuu/draw/drawplot/bokeh_draw.pyi +603 -578
- hikyuu/draw/drawplot/common.pyi +1 -1
- hikyuu/draw/drawplot/echarts_draw.pyi +605 -580
- hikyuu/draw/drawplot/matplotlib_draw.py +4 -74
- hikyuu/draw/drawplot/matplotlib_draw.pyi +615 -590
- hikyuu/draw/elder.pyi +11 -11
- hikyuu/draw/kaufman.pyi +18 -18
- hikyuu/draw/volume.pyi +10 -10
- hikyuu/examples/notebook/Demo/Demo1.ipynb +48 -33
- hikyuu/extend.pyi +599 -573
- hikyuu/fetcher/stock/zh_block_em.py +50 -18
- hikyuu/gui/HikyuuTDX.py +81 -30
- hikyuu/gui/data/CollectSpotThread.py +1 -1
- hikyuu/gui/data/EscapetimeThread.py +8 -14
- hikyuu/gui/data/ImportBlockInfoTask.py +3 -10
- hikyuu/gui/data/MainWindow.py +1168 -715
- hikyuu/gui/data/SchedImportThread.py +2 -2
- hikyuu/gui/data/UsePytdxImportToH5Thread.py +3 -3
- hikyuu/gui/data/UseQmtImportToH5Thread.py +2 -2
- hikyuu/gui/data/UseTdxImportToH5Thread.py +3 -3
- hikyuu/gui/data/tool.py +32 -25
- hikyuu/gui/dataserver.py +5 -3
- hikyuu/hub.pyi +6 -6
- hikyuu/include/hikyuu/DataType.h +4 -16
- hikyuu/include/hikyuu/KData.h +6 -3
- hikyuu/include/hikyuu/KDataPrivatedBufferImp.h +1 -1
- hikyuu/include/hikyuu/KDataSharedBufferImp.h +1 -1
- hikyuu/include/hikyuu/KQuery.h +2 -2
- hikyuu/include/hikyuu/Stock.h +3 -0
- hikyuu/include/hikyuu/StockManager.h +13 -3
- hikyuu/include/hikyuu/config.h +3 -0
- hikyuu/include/hikyuu/data_driver/BaseInfoDriver.h +8 -0
- hikyuu/include/hikyuu/data_driver/BlockInfoDriver.h +6 -0
- hikyuu/include/hikyuu/data_driver/KDataDriver.h +26 -1
- hikyuu/include/hikyuu/data_driver/base_info/mysql/MySQLBaseInfoDriver.h +1 -1
- hikyuu/include/hikyuu/data_driver/base_info/sqlite/SQLiteBaseInfoDriver.h +1 -1
- hikyuu/include/hikyuu/data_driver/block_info/mysql/MySQLBlockInfoDriver.h +2 -1
- hikyuu/include/hikyuu/data_driver/block_info/qianlong/QLBlockInfoDriver.h +2 -1
- hikyuu/include/hikyuu/data_driver/block_info/sqlite/SQLiteBlockInfoDriver.h +2 -1
- hikyuu/include/hikyuu/data_driver/kdata/DoNothingKDataDriver.h +1 -1
- hikyuu/include/hikyuu/data_driver/kdata/cvs/KDataTempCsvDriver.h +1 -1
- hikyuu/include/hikyuu/data_driver/kdata/hdf5/H5KDataDriver.h +1 -1
- hikyuu/include/hikyuu/data_driver/kdata/mysql/MySQLKDataDriver.h +1 -1
- hikyuu/include/hikyuu/data_driver/kdata/sqlite/SQLiteKDataDriver.h +1 -1
- hikyuu/include/hikyuu/data_driver/kdata/tdx/TdxKDataDriver.h +1 -1
- hikyuu/include/hikyuu/hikyuu.h +1 -1
- hikyuu/include/hikyuu/indicator/build_in.h +1 -0
- hikyuu/include/hikyuu/indicator/crt/CYCLE.h +4 -4
- hikyuu/include/hikyuu/indicator/crt/HSL.h +2 -2
- hikyuu/include/hikyuu/indicator/crt/QUANTILE_TRUNC.h +30 -0
- hikyuu/include/hikyuu/indicator/crt/TURNOVER.h +1 -0
- hikyuu/include/hikyuu/indicator/crt/ZSCORE.h +2 -2
- hikyuu/include/hikyuu/indicator/imp/IQuantileTrunc.h +25 -0
- hikyuu/include/hikyuu/misc.h +38 -0
- hikyuu/include/hikyuu/plugin/dataserver.h +2 -1
- hikyuu/include/hikyuu/plugin/extind.h +37 -0
- hikyuu/include/hikyuu/plugin/hkuextra.h +0 -18
- hikyuu/include/hikyuu/plugin/hkuviews.h +36 -0
- hikyuu/include/hikyuu/plugin/interface/DataServerPluginInterface.h +2 -2
- hikyuu/include/hikyuu/plugin/interface/ExtendIndicatorsPluginInterface.h +12 -0
- hikyuu/include/hikyuu/plugin/interface/HkuExtraPluginInterface.h +0 -14
- hikyuu/include/hikyuu/plugin/interface/HkuViewsPluginInterface.h +34 -0
- hikyuu/include/hikyuu/plugin/interface/plugins.h +8 -1
- hikyuu/include/hikyuu/python/pybind_utils.h +6 -1
- hikyuu/include/hikyuu/strategy/RunSystemInStrategy.h +3 -0
- hikyuu/include/hikyuu/trade_manage/Performance.h +4 -4
- hikyuu/include/hikyuu/trade_manage/TradeManagerBase.h +10 -1
- hikyuu/include/hikyuu/trade_sys/moneymanager/imp/FixedCapitalFundsMM.h +0 -4
- hikyuu/include/hikyuu/trade_sys/multifactor/MultiFactorBase.h +36 -3
- hikyuu/include/hikyuu/trade_sys/multifactor/NormalizeBase.h +125 -0
- hikyuu/include/hikyuu/trade_sys/multifactor/ScoresFilterBase.h +125 -0
- hikyuu/include/hikyuu/trade_sys/multifactor/build_in.h +3 -0
- hikyuu/include/hikyuu/trade_sys/multifactor/buildin_norm.h +36 -0
- hikyuu/include/hikyuu/trade_sys/multifactor/buildin_scfilter.h +51 -0
- hikyuu/include/hikyuu/trade_sys/multifactor/filter/GroupSCFilter.h +24 -0
- hikyuu/include/hikyuu/trade_sys/multifactor/filter/IgnoreLessOrEqualValueSCFilter.h +24 -0
- hikyuu/include/hikyuu/trade_sys/multifactor/filter/IgnoreNanSCFilter.h +24 -0
- hikyuu/include/hikyuu/trade_sys/multifactor/filter/MinAmountPercentSCFilter.h +25 -0
- hikyuu/include/hikyuu/trade_sys/multifactor/filter/PriceSCFilter.h +24 -0
- hikyuu/include/hikyuu/trade_sys/multifactor/filter/TopNSCFilter.h +24 -0
- hikyuu/include/hikyuu/trade_sys/multifactor/filter/__init__.py +1 -0
- hikyuu/include/hikyuu/trade_sys/multifactor/imp/EqualWeightMultiFactor.h +1 -1
- hikyuu/include/hikyuu/trade_sys/multifactor/imp/ICIRMultiFactor.h +1 -1
- hikyuu/include/hikyuu/trade_sys/multifactor/imp/ICMultiFactor.h +1 -1
- hikyuu/include/hikyuu/trade_sys/multifactor/imp/WeightMultiFactor.h +1 -1
- hikyuu/include/hikyuu/trade_sys/multifactor/normalize/NormMinMax.h +23 -0
- hikyuu/include/hikyuu/trade_sys/multifactor/normalize/NormQuantile.h +28 -0
- hikyuu/include/hikyuu/trade_sys/multifactor/normalize/NormQuantileUniform.h +28 -0
- hikyuu/include/hikyuu/trade_sys/multifactor/normalize/NormZScore.h +25 -0
- hikyuu/include/hikyuu/trade_sys/multifactor/normalize/__init__.py +1 -0
- hikyuu/include/hikyuu/trade_sys/multifactor/normalize/quantile_trunc.h +16 -0
- hikyuu/include/hikyuu/trade_sys/portfolio/Portfolio.h +7 -0
- hikyuu/include/hikyuu/trade_sys/portfolio/imp/SimplePortfolio.h +7 -0
- hikyuu/include/hikyuu/trade_sys/portfolio/imp/WithoutAFPortfolio.h +7 -0
- hikyuu/include/hikyuu/trade_sys/selector/SelectorBase.h +49 -0
- hikyuu/include/hikyuu/trade_sys/selector/build_in.h +1 -0
- hikyuu/include/hikyuu/trade_sys/selector/crt/SE_MultiFactor2.h +40 -0
- hikyuu/include/hikyuu/trade_sys/selector/imp/MultiFactorSelector.h +0 -3
- hikyuu/include/hikyuu/trade_sys/selector/imp/MultiFactorSelector2.h +49 -0
- hikyuu/include/hikyuu/trade_sys/selector/imp/logic/OperatorSelector.h +1 -1
- hikyuu/include/hikyuu/trade_sys/selector/imp/logic/OperatorValueSelector.h +1 -1
- hikyuu/include/hikyuu/trade_sys/signal/imp/BandSignal2.h +0 -4
- hikyuu/include/hikyuu/trade_sys/signal/imp/logic/AddValueSignal.h +2 -2
- hikyuu/include/hikyuu/trade_sys/signal/imp/logic/DivValueSignal.h +2 -2
- hikyuu/include/hikyuu/trade_sys/signal/imp/logic/MulValueSignal.h +2 -2
- hikyuu/include/hikyuu/trade_sys/signal/imp/logic/OperatorSignal.h +1 -1
- hikyuu/include/hikyuu/trade_sys/signal/imp/logic/OperatorValueSignal.h +4 -4
- hikyuu/include/hikyuu/trade_sys/signal/imp/logic/SubValueSignal.h +2 -2
- hikyuu/include/hikyuu/trade_sys/system/System.h +14 -1
- hikyuu/include/hikyuu/utilities/SpendTimer.h +17 -7
- hikyuu/include/hikyuu/utilities/arithmetic.h +55 -0
- hikyuu/include/hikyuu/utilities/db_connect/mysql/MySQLConnect.h +1 -1
- hikyuu/include/hikyuu/utilities/db_connect/mysql/MySQLStatement.h +1 -1
- hikyuu/include/hikyuu/utilities/db_connect/sqlite/SQLiteConnect.h +1 -1
- hikyuu/include/hikyuu/utilities/db_connect/sqlite/SQLiteStatement.h +1 -1
- hikyuu/include/hikyuu/utilities/plugin/PluginLoader.h +4 -1
- hikyuu/include/hikyuu/version.h +4 -4
- hikyuu/plugin/libbacktest.so +0 -0
- hikyuu/plugin/libclickhousedriver.so +0 -0
- hikyuu/plugin/libdataserver.so +0 -0
- hikyuu/plugin/libdevice.so +0 -0
- hikyuu/plugin/libextind.so +0 -0
- hikyuu/plugin/libhkuextra.so +0 -0
- hikyuu/plugin/libhkuviews.so +0 -0
- hikyuu/plugin/libimport2hdf5.so +0 -0
- hikyuu/plugin/libtmreport.so +0 -0
- hikyuu/trade_manage/__init__.pyi +603 -578
- hikyuu/trade_manage/broker.pyi +3 -3
- hikyuu/trade_manage/broker_easytrader.pyi +1 -1
- hikyuu/trade_manage/trade.pyi +603 -578
- hikyuu/util/__init__.pyi +2 -2
- hikyuu/util/singleton.pyi +1 -1
- {hikyuu-2.6.8.4.dist-info → hikyuu-2.6.9.dist-info}/METADATA +13 -13
- {hikyuu-2.6.8.4.dist-info → hikyuu-2.6.9.dist-info}/RECORD +185 -156
- {hikyuu-2.6.8.4.dist-info → hikyuu-2.6.9.dist-info}/top_level.txt +2 -1
- hikyuu/cpp/core39.pyi +0 -14385
- hikyuu/cpp/core39.so +0 -0
- hikyuu/data_driver/__init__.py +0 -49
- hikyuu/data_driver/jqdata_data_driver.py +0 -277
- hikyuu/data_driver/pytdx_data_driver.py +0 -292
- hikyuu/fetcher/stock/zh_stock_a_huatai.py +0 -51
- hikyuu/fetcher/stock/zh_stock_a_pytdx.py +0 -129
- hikyuu/gui/data/CollectToMemThread.py +0 -123
- hikyuu/gui/data/CollectToMySQLThread.py +0 -178
- hikyuu/gui/start_huatai_insight.py +0 -510
- hikyuu/tools/update_block_info.py +0 -168
- {hikyuu-2.6.8.4.dist-info → hikyuu-2.6.9.dist-info}/WHEEL +0 -0
- {hikyuu-2.6.8.4.dist-info → hikyuu-2.6.9.dist-info}/entry_points.txt +0 -0
|
@@ -17,7 +17,7 @@ from hikyuu.util import *
|
|
|
17
17
|
em_num_per_page = 100
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
@hku_catch(ret=[], trace=
|
|
20
|
+
@hku_catch(ret=[], trace=False)
|
|
21
21
|
def get_hybk_names():
|
|
22
22
|
"""获取所有行业(板块代码,板块名称)列表"""
|
|
23
23
|
url = "https://19.push2.eastmoney.com/api/qt/clist/get"
|
|
@@ -50,7 +50,7 @@ def get_hybk_names():
|
|
|
50
50
|
return ret
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
@hku_catch(ret=[], trace=
|
|
53
|
+
@hku_catch(ret=[], trace=False)
|
|
54
54
|
def get_hybk_cons_code(blk_code):
|
|
55
55
|
"获取指定行业板块成分代码列表"
|
|
56
56
|
url = "http://30.push2.eastmoney.com/api/qt/clist/get"
|
|
@@ -83,16 +83,19 @@ def get_hybk_cons_code(blk_code):
|
|
|
83
83
|
return ret
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
@hku_catch(ret={}, trace=
|
|
86
|
+
@hku_catch(ret={}, trace=False)
|
|
87
87
|
def get_all_hybk_info(code_market_dict, sep=""):
|
|
88
88
|
"""获取所有行业板块列表"""
|
|
89
89
|
blk_list = get_hybk_names()
|
|
90
|
+
time.sleep(random.uniform(1, 3))
|
|
90
91
|
ret = {}
|
|
91
|
-
|
|
92
|
+
total = len(blk_list)
|
|
93
|
+
for i, blk in enumerate(blk_list):
|
|
92
94
|
stk_codes = get_hybk_cons_code(blk[0])
|
|
93
|
-
hku_info(f"获取行业板块{blk[1]}成分: {len(stk_codes)}")
|
|
95
|
+
hku_info(f"{i}|{total} 获取行业板块{blk[1]}成分: {len(stk_codes)}")
|
|
94
96
|
ret[blk[1]] = [
|
|
95
97
|
f"{code_market_dict[stk_code]}{sep}{stk_code}" for stk_code in stk_codes if stk_code in code_market_dict]
|
|
98
|
+
time.sleep(random.uniform(1, 3))
|
|
96
99
|
return ret
|
|
97
100
|
|
|
98
101
|
|
|
@@ -431,21 +434,23 @@ def stock_board_concept_cons_em(symbol: str = "融资融券") -> pd.DataFrame:
|
|
|
431
434
|
return temp_df
|
|
432
435
|
|
|
433
436
|
|
|
434
|
-
@hku_catch(ret={}, trace=
|
|
437
|
+
@hku_catch(ret={}, trace=False)
|
|
435
438
|
def get_all_gnbk_info(code_market_dict, sep=""):
|
|
436
439
|
"""获取所有概念版本列表"""
|
|
437
440
|
blk_names = stock_board_concept_name_em()['板块名称']
|
|
438
441
|
ret = {}
|
|
442
|
+
total = len(blk_names)
|
|
439
443
|
for i, blk_name in enumerate(blk_names):
|
|
440
444
|
stk_codes = stock_board_concept_cons_em(blk_name)
|
|
441
445
|
stk_codes = stk_codes['代码'].to_list()
|
|
442
|
-
hku_info(f"{i} 获取概念板块{blk_name}成分: {len(stk_codes)}")
|
|
446
|
+
hku_info(f"{i}|{total} 获取概念板块{blk_name}成分: {len(stk_codes)}")
|
|
443
447
|
ret[blk_name] = [
|
|
444
448
|
f"{code_market_dict[stk_code]}{sep}{stk_code}" for stk_code in stk_codes if stk_code in code_market_dict]
|
|
449
|
+
time.sleep(random.uniform(1, 3))
|
|
445
450
|
return ret
|
|
446
451
|
|
|
447
452
|
|
|
448
|
-
@hku_catch(ret=[], trace=
|
|
453
|
+
@hku_catch(ret=[], trace=False)
|
|
449
454
|
def get_dybk_names():
|
|
450
455
|
"""获取所有地域板块名称列表"""
|
|
451
456
|
url = "http://13.push2.eastmoney.com/api/qt/clist/get"
|
|
@@ -478,7 +483,7 @@ def get_dybk_names():
|
|
|
478
483
|
return ret
|
|
479
484
|
|
|
480
485
|
|
|
481
|
-
@hku_catch(ret={}, trace=
|
|
486
|
+
@hku_catch(ret={}, trace=False)
|
|
482
487
|
def get_all_dybk_info(code_market_dict, sep=""):
|
|
483
488
|
"""获取所有地域板块列表"""
|
|
484
489
|
blk_list = get_dybk_names()
|
|
@@ -499,10 +504,12 @@ def get_all_dybk_info(code_market_dict, sep=""):
|
|
|
499
504
|
}
|
|
500
505
|
|
|
501
506
|
ret = {}
|
|
502
|
-
|
|
507
|
+
total = len(blk_list)
|
|
508
|
+
for i, v in enumerate(blk_list):
|
|
503
509
|
blk_code, blk_name = v[0], v[1]
|
|
504
510
|
params["fs"] = f"b:{blk_code} f:!50"
|
|
505
511
|
params["pn"] = 1
|
|
512
|
+
time.sleep(random.uniform(1, 3))
|
|
506
513
|
r = requests.get(url, params=params, timeout=15)
|
|
507
514
|
data = r.json()
|
|
508
515
|
if data["data"] is None:
|
|
@@ -522,15 +529,34 @@ def get_all_dybk_info(code_market_dict, sep=""):
|
|
|
522
529
|
ret[blk_name].extend(
|
|
523
530
|
[f"{code_market_dict[v['f12']]}{sep}{v['f12']}" for v in stk_json if v["f12"] in code_market_dict])
|
|
524
531
|
time.sleep(random.uniform(1, 3))
|
|
525
|
-
hku_info(f'获取地域板块{blk_name}成分: {len(ret[blk_name])}')
|
|
532
|
+
hku_info(f'{i}|{total} 获取地域板块{blk_name}成分: {len(ret[blk_name])}')
|
|
526
533
|
|
|
527
534
|
return ret
|
|
528
535
|
|
|
529
536
|
|
|
530
|
-
@hku_catch(ret={}, trace=
|
|
537
|
+
@hku_catch(ret={}, trace=False)
|
|
531
538
|
def get_all_zsbk_info(code_market_dict, sep=""):
|
|
532
539
|
"""获取所有指数成分股列表"""
|
|
533
540
|
blk_info = ak.index_stock_info()
|
|
541
|
+
blk_info['index_code'] = blk_info['index_code'].astype(str) # 确保是字符串类型
|
|
542
|
+
df_000 = blk_info[blk_info['index_code'].str.startswith('000')].reset_index(drop=True) # 000前缀
|
|
543
|
+
df_399 = blk_info[blk_info['index_code'].str.startswith('399')].reset_index(drop=True) # 399前缀
|
|
544
|
+
|
|
545
|
+
# 2. 交替合并两个DataFrame
|
|
546
|
+
merged_rows = []
|
|
547
|
+
max_length = max(len(df_000), len(df_399)) # 取两个DataFrame的最大长度
|
|
548
|
+
|
|
549
|
+
for i in range(max_length):
|
|
550
|
+
# 先加000前缀的行(如果存在)
|
|
551
|
+
if i < len(df_000):
|
|
552
|
+
merged_rows.append(df_000.iloc[i])
|
|
553
|
+
# 再加399前缀的行(如果存在)
|
|
554
|
+
if i < len(df_399):
|
|
555
|
+
merged_rows.append(df_399.iloc[i])
|
|
556
|
+
|
|
557
|
+
# 3. 转换为DataFrame
|
|
558
|
+
blk_info = pd.DataFrame(merged_rows).reset_index(drop=True)
|
|
559
|
+
|
|
534
560
|
blk_codes = blk_info["index_code"]
|
|
535
561
|
blk_names = blk_info["display_name"]
|
|
536
562
|
ret = {}
|
|
@@ -542,17 +568,23 @@ def get_all_zsbk_info(code_market_dict, sep=""):
|
|
|
542
568
|
# 沪深指数有重复,避免深指覆盖
|
|
543
569
|
if blk_name in ret:
|
|
544
570
|
continue
|
|
571
|
+
|
|
572
|
+
time.sleep(random.uniform(1, 3))
|
|
545
573
|
try:
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
574
|
+
if blk_code[:3] == "399":
|
|
575
|
+
stk_codes = ak.index_stock_cons(symbol=blk_code)
|
|
576
|
+
stk_codes = stk_codes['品种代码'].to_list()
|
|
577
|
+
else:
|
|
578
|
+
stk_codes = ak.index_stock_cons_csindex(symbol=blk_code)
|
|
579
|
+
stk_codes = stk_codes['成分券代码'].to_list()
|
|
580
|
+
hku_info("{}|{} 获取指数板块 {}|{} 成分: {}", i, total, blk_code, blk_name, len(stk_codes))
|
|
549
581
|
ret[blk_name] = [
|
|
550
582
|
f"{code_market_dict[stk_code]}{sep}{stk_code}" for stk_code in stk_codes if stk_code in code_market_dict]
|
|
551
583
|
except KeyboardInterrupt:
|
|
552
584
|
break
|
|
553
|
-
except:
|
|
554
|
-
|
|
555
|
-
|
|
585
|
+
except Exception as e:
|
|
586
|
+
print(f"Failed! {i}, {blk_code}, {blk_name}")
|
|
587
|
+
# raise e
|
|
556
588
|
return ret
|
|
557
589
|
|
|
558
590
|
|
hikyuu/gui/HikyuuTDX.py
CHANGED
|
@@ -12,11 +12,10 @@ from logging.handlers import QueueListener
|
|
|
12
12
|
# 优先加载,处理 VS 17.10 升级后依赖 dll 不兼容问题
|
|
13
13
|
import hikyuu
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
from
|
|
18
|
-
from
|
|
19
|
-
from PyQt5.QtGui import QIcon, QTextCursor, QFont, QPalette, QPixmap
|
|
15
|
+
# 替换PyQt5导入为PySide6
|
|
16
|
+
from PySide6.QtWidgets import QApplication, QMainWindow, QFileDialog, QMessageBox
|
|
17
|
+
from PySide6.QtCore import Slot, QObject, Signal
|
|
18
|
+
from PySide6.QtGui import QIcon, QTextCursor, QFont, QPalette, QPixmap
|
|
20
19
|
|
|
21
20
|
import mysql.connector
|
|
22
21
|
from mysql.connector import errorcode
|
|
@@ -43,7 +42,7 @@ from hikyuu.util import *
|
|
|
43
42
|
|
|
44
43
|
class EmittingStream(QObject):
|
|
45
44
|
"""输出重定向至QT"""
|
|
46
|
-
textWritten =
|
|
45
|
+
textWritten = Signal(str)
|
|
47
46
|
|
|
48
47
|
def write(self, text):
|
|
49
48
|
self.textWritten.emit(str(text))
|
|
@@ -249,7 +248,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
249
248
|
except:
|
|
250
249
|
pass
|
|
251
250
|
|
|
252
|
-
@
|
|
251
|
+
@Slot()
|
|
253
252
|
def on_save_pushButton_clicked(self):
|
|
254
253
|
try:
|
|
255
254
|
self.saveConfig()
|
|
@@ -333,7 +332,22 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
333
332
|
icon = QIcon(f"{current_dir}/images/hikyuu_small.png")
|
|
334
333
|
star_img = QPixmap(f"{current_dir}/images/star.png")
|
|
335
334
|
self.label_44.setPixmap(star_img)
|
|
335
|
+
# 修改 label_46 的 HTML 文本,直接在 HTML 中设置字体大小
|
|
336
|
+
|
|
337
|
+
label_46_txt = """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
|
338
|
+
<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css">
|
|
339
|
+
p, li { white-space: pre-wrap; }
|
|
340
|
+
hr { height: 1px; border-width: 0; }
|
|
341
|
+
li.unchecked::marker { content: "\2610"; }
|
|
342
|
+
li.checked::marker { content: "\2612"; }
|
|
343
|
+
</style></head><body style="font-weight:400; font-style:normal;">
|
|
344
|
+
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span>Hikyuu </span><span style="font-weight:700;">专注于量化交易领域的核心技术构建,涵盖交易模型开发、极速计算引擎、高效回测框架及实盘拓展能力</span><span>,定位为量化交易计算引擎,为量化交易爱好者提供高性能底层架构支持。随着社区规模扩大,分散了作者在策略研究上的精力。为保障项目的可持续性,现对捐赠用户提供部分额外功能作为回馈,感谢社区伙伴的支持!</span></p>
|
|
345
|
+
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span>捐赠功能以插件的方式提供,采用独立授权许可,完全在 hikyuu 之外,对喜欢自行编译扩展的朋友没有影响。因插件许可授权需要采集硬件信息,如有疑虑只要不申请试用许可和正式许可授权,不会触发硬件信息采集,如申请,视为同意采集。</span></p>
|
|
346
|
+
<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span>详情参见:</span><a href="https://hikyuu.readthedocs.io/zh-cn/latest/vip/vip-plan.html"><span style="text-decoration: underline; color:#3586ff;">捐赠权益</span></a><span style="font-weight:700;"> ,感谢大家的支持!</span></p></body></html>
|
|
347
|
+
"""
|
|
348
|
+
self.label_46.setText(label_46_txt)
|
|
336
349
|
self.label_46.setOpenExternalLinks(True)
|
|
350
|
+
|
|
337
351
|
self.label_license.setText(view_license())
|
|
338
352
|
self.fetch_trial_pushButton.setEnabled(not is_valid_license())
|
|
339
353
|
|
|
@@ -434,6 +448,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
434
448
|
if (not is_valid_license()) or hdf5_enable or mysql_enable:
|
|
435
449
|
clickhouse_enable = False
|
|
436
450
|
self.enable_clickhouse_radioButton.setChecked(clickhouse_enable)
|
|
451
|
+
self.enable_clickhouse_radioButton.setEnabled(is_valid_license())
|
|
437
452
|
self.clickhouse_tmpdir_lineEdit.setText(import_config.get('clickhouse', 'tmpdir', fallback='d:/stock'))
|
|
438
453
|
self.clickhouse_tmpdir_pushButton.setEnabled(clickhouse_enable)
|
|
439
454
|
clickhouse_ip = import_config.get('clickhouse', 'host', fallback='127.0.0.1')
|
|
@@ -618,7 +633,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
618
633
|
'5MIN': self.hdf5_5min_progressBar
|
|
619
634
|
}
|
|
620
635
|
|
|
621
|
-
@
|
|
636
|
+
@Slot()
|
|
622
637
|
def on_fetch_trial_pushButton_clicked(self):
|
|
623
638
|
email = self.email_lineEdit.text()
|
|
624
639
|
info = fetch_trial_license(email)
|
|
@@ -626,7 +641,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
626
641
|
self.label_license.setText(view_license())
|
|
627
642
|
self.fetch_trial_pushButton.setEnabled(not is_valid_license())
|
|
628
643
|
|
|
629
|
-
@
|
|
644
|
+
@Slot()
|
|
630
645
|
def on_pytdx_radioButton_clicked(self):
|
|
631
646
|
if self.pytdx_radioButton.isChecked():
|
|
632
647
|
self.tdx_radioButton.setChecked(False)
|
|
@@ -634,7 +649,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
634
649
|
self.use_download = 'pytdx'
|
|
635
650
|
self.on_tdx_or_pytdx_toggled()
|
|
636
651
|
|
|
637
|
-
@
|
|
652
|
+
@Slot()
|
|
638
653
|
def on_tdx_radioButton_clicked(self):
|
|
639
654
|
if self.tdx_radioButton.isChecked():
|
|
640
655
|
self.pytdx_radioButton.setChecked(False)
|
|
@@ -642,6 +657,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
642
657
|
self.use_download = 'tdx'
|
|
643
658
|
self.on_tdx_or_pytdx_toggled()
|
|
644
659
|
|
|
660
|
+
@Slot()
|
|
645
661
|
def on_qmt_radioButton_clicked(self):
|
|
646
662
|
if self.qmt_radioButton.isChecked():
|
|
647
663
|
self.tdx_radioButton.setChecked(False)
|
|
@@ -675,7 +691,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
675
691
|
self.time_start_dateEdit.setEnabled(False)
|
|
676
692
|
self.use_tdx_number_spinBox.setEnabled(False)
|
|
677
693
|
|
|
678
|
-
@
|
|
694
|
+
@Slot()
|
|
679
695
|
def on_select_tdx_dir_pushButton_clicked(self):
|
|
680
696
|
dlg = QFileDialog()
|
|
681
697
|
dlg.setFileMode(QFileDialog.Directory)
|
|
@@ -685,7 +701,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
685
701
|
dirname = dlg.selectedFiles()
|
|
686
702
|
self.tdx_dir_lineEdit.setText(dirname[0])
|
|
687
703
|
|
|
688
|
-
@
|
|
704
|
+
@Slot()
|
|
689
705
|
def on_hdf5_dir_pushButton_clicked(self):
|
|
690
706
|
dlg = QFileDialog()
|
|
691
707
|
dlg.setFileMode(QFileDialog.Directory)
|
|
@@ -695,21 +711,21 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
695
711
|
dirname = dlg.selectedFiles()
|
|
696
712
|
self.hdf5_dir_lineEdit.setText(dirname[0])
|
|
697
713
|
|
|
698
|
-
@
|
|
714
|
+
@Slot()
|
|
699
715
|
def on_enable_hdf55_radioButton_clicked(self):
|
|
700
716
|
if self.enable_hdf55_radioButton.isChecked():
|
|
701
717
|
self.enable_mysql_radioButton.setChecked(False)
|
|
702
718
|
self.enable_clickhouse_radioButton.setChecked(False)
|
|
703
719
|
self.on_enable_database_toggled(hdf5=True, mysql=False, clickhouse=False)
|
|
704
720
|
|
|
705
|
-
@
|
|
721
|
+
@Slot()
|
|
706
722
|
def on_enable_mysql_radioButton_clicked(self):
|
|
707
723
|
if self.enable_mysql_radioButton.isChecked():
|
|
708
724
|
self.enable_hdf55_radioButton.setChecked(False)
|
|
709
725
|
self.enable_clickhouse_radioButton.setChecked(False)
|
|
710
726
|
self.on_enable_database_toggled(hdf5=False, mysql=True, clickhouse=False)
|
|
711
727
|
|
|
712
|
-
@
|
|
728
|
+
@Slot()
|
|
713
729
|
def on_enable_clickhouse_radioButton_clicked(self):
|
|
714
730
|
if self.enable_clickhouse_radioButton.isChecked():
|
|
715
731
|
self.enable_hdf55_radioButton.setChecked(False)
|
|
@@ -732,7 +748,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
732
748
|
self.clickhouse_test_pushButton.setEnabled(clickhouse)
|
|
733
749
|
self.clickhouse_tmpdir_pushButton.setEnabled(clickhouse)
|
|
734
750
|
|
|
735
|
-
@
|
|
751
|
+
@Slot()
|
|
736
752
|
def on_mysql_tmpdir_pushButton_clicked(self):
|
|
737
753
|
dlg = QFileDialog()
|
|
738
754
|
dlg.setFileMode(QFileDialog.Directory)
|
|
@@ -742,7 +758,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
742
758
|
dirname = dlg.selectedFiles()
|
|
743
759
|
self.mysql_tmpdir_lineEdit.setText(dirname[0])
|
|
744
760
|
|
|
745
|
-
@
|
|
761
|
+
@Slot()
|
|
746
762
|
def on_clickhouse_tmpdir_pushButton_clicked(self):
|
|
747
763
|
if not is_valid_license():
|
|
748
764
|
QMessageBox.critical(self, "clickhouse引擎", "需要捐赠授权才能使用clickhouse引擎")
|
|
@@ -756,7 +772,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
756
772
|
dirname = dlg.selectedFiles()
|
|
757
773
|
self.clickhouse_tmpdir_lineEdit.setText(dirname[0])
|
|
758
774
|
|
|
759
|
-
@
|
|
775
|
+
@Slot()
|
|
760
776
|
def on_mysql_test_pushButton_clicked(self):
|
|
761
777
|
"""测试数据库连接"""
|
|
762
778
|
db_config = {
|
|
@@ -780,7 +796,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
780
796
|
|
|
781
797
|
QMessageBox.about(self, "测试数据库连接", " 连接成功!")
|
|
782
798
|
|
|
783
|
-
@
|
|
799
|
+
@Slot()
|
|
784
800
|
def on_clickhouse_test_pushButton_clicked(self):
|
|
785
801
|
"""测试数据库连接"""
|
|
786
802
|
db_config = {
|
|
@@ -821,7 +837,8 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
821
837
|
if msg_name == 'ESCAPE_TIME':
|
|
822
838
|
self.escape_time = msg_task_name
|
|
823
839
|
self.import_status_label.setText(
|
|
824
|
-
"耗时:{:>.2f} 秒 ({:>.2f}分钟) {}".format(
|
|
840
|
+
"耗时:{:>.2f} 秒 ({:>.2f}分钟) {}".format(
|
|
841
|
+
self.escape_time, self.escape_time / 60, datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
|
|
825
842
|
)
|
|
826
843
|
|
|
827
844
|
elif msg_name == 'HDF5_IMPORT':
|
|
@@ -890,7 +907,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
890
907
|
if msg[2] != 'FINISHED':
|
|
891
908
|
self.import_detail_textEdit.append(msg[2])
|
|
892
909
|
|
|
893
|
-
@
|
|
910
|
+
@Slot()
|
|
894
911
|
def on_start_import_pushButton_clicked(self):
|
|
895
912
|
try:
|
|
896
913
|
self.saveConfig()
|
|
@@ -965,7 +982,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
965
982
|
self.escape_time_thread.message.connect(self.on_message_from_thread)
|
|
966
983
|
self.escape_time_thread.start()
|
|
967
984
|
|
|
968
|
-
@
|
|
985
|
+
@Slot()
|
|
969
986
|
def on_sched_import_pushButton_clicked(self):
|
|
970
987
|
self.sched_import_pushButton.setEnabled(False)
|
|
971
988
|
if self._is_sched_import_running:
|
|
@@ -993,7 +1010,7 @@ class MyMainWindow(QMainWindow, Ui_MainWindow):
|
|
|
993
1010
|
self.sched_import_pushButton.setText("停止定时导入")
|
|
994
1011
|
self.sched_import_pushButton.setEnabled(True)
|
|
995
1012
|
|
|
996
|
-
@
|
|
1013
|
+
@Slot()
|
|
997
1014
|
def on_collect_start_pushButton_clicked(self):
|
|
998
1015
|
if self._is_collect_running:
|
|
999
1016
|
if self.collect_spot_thread is not None and self.collect_spot_thread.isRunning():
|
|
@@ -1033,6 +1050,41 @@ def start():
|
|
|
1033
1050
|
sys.exit(app.exec())
|
|
1034
1051
|
|
|
1035
1052
|
|
|
1053
|
+
def is_font_installed(font_name):
|
|
1054
|
+
"""检查字体是否安装"""
|
|
1055
|
+
if sys.platform == "win32":
|
|
1056
|
+
try:
|
|
1057
|
+
import winreg
|
|
1058
|
+
# 打开注册表中的字体项
|
|
1059
|
+
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts")
|
|
1060
|
+
i = 0
|
|
1061
|
+
while True:
|
|
1062
|
+
try:
|
|
1063
|
+
name, value, _ = winreg.EnumValue(key, i)
|
|
1064
|
+
if font_name in name:
|
|
1065
|
+
winreg.CloseKey(key)
|
|
1066
|
+
return True
|
|
1067
|
+
i += 1
|
|
1068
|
+
except WindowsError:
|
|
1069
|
+
break
|
|
1070
|
+
winreg.CloseKey(key)
|
|
1071
|
+
except:
|
|
1072
|
+
# 如果注册表检查失败,则尝试创建字体对象
|
|
1073
|
+
try:
|
|
1074
|
+
f = QFont(font_name)
|
|
1075
|
+
return f.exactMatch()
|
|
1076
|
+
except:
|
|
1077
|
+
pass
|
|
1078
|
+
return False
|
|
1079
|
+
else:
|
|
1080
|
+
# 非Windows系统简单检查
|
|
1081
|
+
try:
|
|
1082
|
+
f = QFont(font_name)
|
|
1083
|
+
return f.exactMatch()
|
|
1084
|
+
except:
|
|
1085
|
+
return False
|
|
1086
|
+
|
|
1087
|
+
|
|
1036
1088
|
if __name__ == "__main__":
|
|
1037
1089
|
import requests
|
|
1038
1090
|
import urllib
|
|
@@ -1040,14 +1092,13 @@ if __name__ == "__main__":
|
|
|
1040
1092
|
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
|
1041
1093
|
logging.getLogger("pytdx").setLevel(logging.WARNING)
|
|
1042
1094
|
|
|
1043
|
-
# 自适应分辨率,防止字体显示不全
|
|
1044
|
-
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps)
|
|
1045
|
-
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
|
|
1046
|
-
|
|
1047
1095
|
app = QApplication(sys.argv)
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1096
|
+
if sys.platform == 'win32':
|
|
1097
|
+
# 检查Microsoft YaHei字体是否存在
|
|
1098
|
+
if is_font_installed('Microsoft YaHei'):
|
|
1099
|
+
f = QFont('Microsoft YaHei')
|
|
1100
|
+
f.setPixelSize(12)
|
|
1101
|
+
app.setFont(f)
|
|
1051
1102
|
|
|
1052
1103
|
if (len(sys.argv) > 1 and sys.argv[1] == '0'):
|
|
1053
1104
|
FORMAT = '%(asctime)-15s [%(levelname)s]: %(message)s [%(name)s::%(funcName)s]'
|
|
@@ -6,7 +6,7 @@ import logging
|
|
|
6
6
|
import time
|
|
7
7
|
import datetime
|
|
8
8
|
from math import ceil
|
|
9
|
-
from
|
|
9
|
+
from PySide6.QtCore import QThread, QWaitCondition, QMutex
|
|
10
10
|
|
|
11
11
|
from hikyuu.util import *
|
|
12
12
|
from hikyuu.gui.spot_server import collect, release_nng_senders
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
# cp936
|
|
4
4
|
|
|
5
5
|
import time
|
|
6
|
-
from
|
|
6
|
+
from PySide6.QtCore import QThread, Signal
|
|
7
7
|
|
|
8
8
|
class EscapetimeThread(QThread):
|
|
9
|
-
message =
|
|
9
|
+
message = Signal(list)
|
|
10
10
|
|
|
11
11
|
def __init__(self):
|
|
12
12
|
super(self.__class__, self).__init__()
|
|
@@ -14,19 +14,13 @@ class EscapetimeThread(QThread):
|
|
|
14
14
|
self.msg_name = 'ESCAPE_TIME'
|
|
15
15
|
self.init_time = time.time()
|
|
16
16
|
|
|
17
|
-
def
|
|
18
|
-
self.working
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def send_message(self, msg):
|
|
23
|
-
self.message.emit([self.msg_name] + msg)
|
|
17
|
+
def run(self):
|
|
18
|
+
while self.working:
|
|
19
|
+
time.sleep(1)
|
|
20
|
+
current_time = time.time()
|
|
21
|
+
self.message.emit([self.msg_name, round(current_time - self.init_time, 1)])
|
|
24
22
|
|
|
25
23
|
def stop(self):
|
|
26
24
|
self.working = False
|
|
25
|
+
self.quit()
|
|
27
26
|
self.wait()
|
|
28
|
-
|
|
29
|
-
def run(self):
|
|
30
|
-
while self.working:
|
|
31
|
-
self.msleep(10)
|
|
32
|
-
self.send_message([(time.time() - self.init_time),])
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
|
|
7
7
|
import sqlite3
|
|
8
8
|
import mysql.connector
|
|
9
|
-
from hikyuu.data.common import MARKET, get_stk_code_name_list
|
|
10
9
|
from hikyuu.data.em_block_to_mysql import em_import_block_to_mysql
|
|
11
10
|
from hikyuu.data.em_block_to_sqlite import em_import_block_to_sqlite
|
|
12
11
|
from hikyuu.data.em_block_to_clickhouse import em_import_block_to_clickhouse
|
|
@@ -14,11 +13,10 @@ from hikyuu.util import *
|
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
class ImportBlockInfoTask:
|
|
17
|
-
def __init__(self, log_queue, queue, config
|
|
16
|
+
def __init__(self, log_queue, queue, config):
|
|
18
17
|
self.log_queue = log_queue
|
|
19
18
|
self.queue = queue
|
|
20
19
|
self.config = config
|
|
21
|
-
self.categorys = categorys
|
|
22
20
|
self.task_name = 'IMPORT_BLOCKINFO'
|
|
23
21
|
self.status = "no run"
|
|
24
22
|
|
|
@@ -52,16 +50,11 @@ class ImportBlockInfoTask:
|
|
|
52
50
|
|
|
53
51
|
count = 0
|
|
54
52
|
try:
|
|
55
|
-
|
|
56
|
-
for market in (MARKET.SH, MARKET.SZ, MARKET.BJ):
|
|
57
|
-
x = get_stk_code_name_list(market)
|
|
58
|
-
for v in x:
|
|
59
|
-
code_market_dict[v["code"]] = market
|
|
60
|
-
count = import_block(connect, code_market_dict, self.categorys)
|
|
53
|
+
count = import_block(connect)
|
|
61
54
|
except Exception as e:
|
|
62
55
|
hku_error(str(e))
|
|
63
56
|
|
|
64
57
|
connect.close()
|
|
65
58
|
|
|
66
|
-
self.queue.put([self.task_name, "BLOCKINFO", f"
|
|
59
|
+
self.queue.put([self.task_name, "BLOCKINFO", f"板块信息更新完毕: {count}", None, None])
|
|
67
60
|
self.status = "finished"
|