hikyuu 2.6.8.4__py3-none-manylinux2014_x86_64.whl → 2.7.0__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 +31 -17
- hikyuu/__init__.pyi +610 -590
- hikyuu/analysis/__init__.pyi +584 -563
- hikyuu/analysis/analysis.pyi +585 -564
- hikyuu/core.py +2 -0
- hikyuu/core.pyi +586 -565
- hikyuu/cpp/__init__.pyi +2 -2
- hikyuu/cpp/core310.pyi +501 -108
- hikyuu/cpp/core310.so +0 -0
- hikyuu/cpp/core311.pyi +495 -108
- hikyuu/cpp/core311.so +0 -0
- hikyuu/cpp/core312.pyi +495 -108
- hikyuu/cpp/core312.so +0 -0
- hikyuu/cpp/core313.pyi +501 -108
- 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 +351 -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/__init__.pyi +1 -1
- hikyuu/draw/drawplot/__init__.pyi +9 -9
- hikyuu/draw/drawplot/bokeh_draw.pyi +600 -580
- hikyuu/draw/drawplot/common.pyi +1 -1
- hikyuu/draw/drawplot/echarts_draw.pyi +602 -582
- hikyuu/draw/drawplot/matplotlib_draw.py +4 -74
- hikyuu/draw/drawplot/matplotlib_draw.pyi +612 -592
- 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.py +0 -7
- hikyuu/extend.pyi +594 -573
- hikyuu/fetcher/stock/zh_block_em.py +12 -40
- hikyuu/gui/HikyuuTDX.py +99 -31
- 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 +1196 -717
- 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/gui/images/liandongxiaopu.png +0 -0
- 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 +4 -1
- hikyuu/include/hikyuu/StockManager.h +13 -3
- 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/device.h +10 -0
- hikyuu/include/hikyuu/plugin/extind.h +37 -0
- hikyuu/include/hikyuu/plugin/hkuextra.h +0 -18
- hikyuu/include/hikyuu/plugin/interface/DataServerPluginInterface.h +2 -2
- hikyuu/include/hikyuu/plugin/interface/DevicePluginInterface.h +2 -0
- hikyuu/include/hikyuu/plugin/interface/ExtendIndicatorsPluginInterface.h +12 -0
- hikyuu/include/hikyuu/plugin/interface/HkuExtraPluginInterface.h +0 -14
- hikyuu/include/hikyuu/plugin/interface/plugins.h +3 -1
- hikyuu/include/hikyuu/python/pybind_utils.h +1 -8
- 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/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/slippage/build_in.h +5 -1
- hikyuu/include/hikyuu/trade_sys/slippage/crt/SP_LogNormal.h +22 -0
- hikyuu/include/hikyuu/trade_sys/slippage/crt/SP_Normal.h +22 -0
- hikyuu/include/hikyuu/trade_sys/slippage/crt/SP_TruncNormal.h +25 -0
- hikyuu/include/hikyuu/trade_sys/slippage/crt/SP_Uniform.h +23 -0
- hikyuu/include/hikyuu/trade_sys/slippage/imp/LogNormalSlippage.h +28 -0
- hikyuu/include/hikyuu/trade_sys/slippage/imp/NormalSlippage.h +28 -0
- hikyuu/include/hikyuu/trade_sys/slippage/imp/TruncNormalSlippage.h +28 -0
- hikyuu/include/hikyuu/trade_sys/slippage/imp/UniformSlippage.h +24 -0
- 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 +5 -5
- hikyuu/plugin/libbacktest.so +0 -0
- hikyuu/plugin/libclickhousedriver.so +0 -0
- hikyuu/plugin/libdataserver.so +0 -0
- hikyuu/{cpp/core39.so → plugin/libdataserver_parquet.so} +0 -0
- hikyuu/plugin/libdevice.so +0 -0
- hikyuu/plugin/libextind.so +0 -0
- hikyuu/plugin/libhkuextra.so +0 -0
- hikyuu/plugin/libimport2hdf5.so +0 -0
- hikyuu/plugin/libtmreport.so +0 -0
- hikyuu/trade_manage/__init__.pyi +599 -579
- hikyuu/trade_manage/broker.pyi +3 -3
- hikyuu/trade_manage/broker_easytrader.pyi +1 -1
- hikyuu/trade_manage/trade.py +0 -2
- hikyuu/trade_manage/trade.pyi +599 -579
- hikyuu/util/__init__.pyi +1 -1
- hikyuu/util/singleton.pyi +1 -1
- {hikyuu-2.6.8.4.dist-info → hikyuu-2.7.0.dist-info}/METADATA +36 -32
- {hikyuu-2.6.8.4.dist-info → hikyuu-2.7.0.dist-info}/RECORD +197 -164
- {hikyuu-2.6.8.4.dist-info → hikyuu-2.7.0.dist-info}/top_level.txt +2 -2
- hikyuu/cpp/core39.pyi +0 -14385
- 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/include/hikyuu/views/arrow_common.h +0 -38
- hikyuu/include/hikyuu/views/arrow_views.h +0 -117
- hikyuu/tools/update_block_info.py +0 -168
- /hikyuu/include/hikyuu/{views → trade_sys/multifactor/filter}/__init__.py +0 -0
- {hikyuu-2.6.8.4.dist-info → hikyuu-2.7.0.dist-info}/WHEEL +0 -0
- {hikyuu-2.6.8.4.dist-info → hikyuu-2.7.0.dist-info}/entry_points.txt +0 -0
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
# coding:utf-8
|
|
2
|
-
#
|
|
3
|
-
# The MIT License (MIT)
|
|
4
|
-
#
|
|
5
|
-
# Created on: 2020-11-29
|
|
6
|
-
# Author: fasiondog
|
|
7
|
-
|
|
8
|
-
import datetime
|
|
9
|
-
from concurrent import futures
|
|
10
|
-
from pytdx.hq import TdxHq_API
|
|
11
|
-
from hikyuu.data.common_pytdx import search_best_tdx
|
|
12
|
-
from hikyuu import get_stock, constant
|
|
13
|
-
from hikyuu.util import *
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@hku_catch(ret=None, callback=lambda quotes: hku_warn(quotes))
|
|
17
|
-
def parse_one_result(quotes):
|
|
18
|
-
result = {}
|
|
19
|
-
hku_check_ignore(quotes, "Invalid input param!")
|
|
20
|
-
try:
|
|
21
|
-
result['datetime'] = datetime.datetime.combine(
|
|
22
|
-
datetime.date.today(), datetime.time.fromisoformat(quotes['servertime'])
|
|
23
|
-
)
|
|
24
|
-
except:
|
|
25
|
-
return None
|
|
26
|
-
|
|
27
|
-
result['market'] = 'SH' if quotes['market'] == 1 else 'SZ'
|
|
28
|
-
result['code'] = quotes['code']
|
|
29
|
-
result['name'] = ''
|
|
30
|
-
result['open'] = quotes['open'] # 今日开盘价
|
|
31
|
-
result['yesterday_close'] = quotes['last_close'] # 昨日收盘价
|
|
32
|
-
result['close'] = quotes['price'] # 当前价格
|
|
33
|
-
result['high'] = quotes['high'] # 今日最高价
|
|
34
|
-
result['low'] = quotes['low'] # 今日最低价
|
|
35
|
-
result['bid'] = float(quotes['bid1']) # 竞买价,即“买一”报价
|
|
36
|
-
result['ask'] = float(quotes['ask1']) # 竞卖价,即“卖一”报价
|
|
37
|
-
# 指数 volumn 需要乘以 0.01
|
|
38
|
-
stk = get_stock(f"{result['market']}{result['code']}")
|
|
39
|
-
if not stk.is_null() and stk.type == constant.STOCKTYPE_INDEX:
|
|
40
|
-
result['volume'] = float(quotes['vol']) * 0.01
|
|
41
|
-
else:
|
|
42
|
-
result['volume'] = float(quotes['vol']) # 成交的股票手数
|
|
43
|
-
result['amount'] = round(quotes['amount'] * 0.0001, 2) # 成交金额,单位为“元”,若要以“万元”为成交金额的单位,需要把该值除以一万
|
|
44
|
-
|
|
45
|
-
result['bid'] = [float(quotes['bid1']), float(quotes['bid2']), float(
|
|
46
|
-
quotes['bid3']), float(quotes['bid4']), float(quotes['bid5'])]
|
|
47
|
-
result['bid_amount'] = [float(quotes['bid_vol1']), float(quotes['bid_vol2']), float(
|
|
48
|
-
quotes['bid_vol3']), float(quotes['bid_vol4']), float(quotes['bid_vol5'])]
|
|
49
|
-
result['ask'] = [float(quotes['ask1']), float(quotes['ask2']), float(
|
|
50
|
-
quotes['ask3']), float(quotes['ask4']), float(quotes['ask5'])]
|
|
51
|
-
result['ask_amount'] = [float(quotes['ask_vol1']), float(quotes['ask_vol2']), float(
|
|
52
|
-
quotes['ask_vol3']), float(quotes['ask_vol4']), float(quotes['ask_vol5'])]
|
|
53
|
-
return result
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
@hku_catch(ret=[], trace=True)
|
|
57
|
-
def request_data(api, stklist, parse_one_result):
|
|
58
|
-
"""请求失败将抛出异常"""
|
|
59
|
-
quotes_list = api.get_security_quotes(stklist)
|
|
60
|
-
result = [parse_one_result(q) for q in quotes_list] if quotes_list is not None else []
|
|
61
|
-
return [r for r in result if r is not None]
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
@hku_catch(ret=([], []))
|
|
65
|
-
def inner_get_spot(stocklist, ip, port, batch_func=None):
|
|
66
|
-
api = TdxHq_API()
|
|
67
|
-
hku_check(api.connect(ip, port), 'Failed connect tdx ({}:{})!'.format(ip, port))
|
|
68
|
-
|
|
69
|
-
count = 0
|
|
70
|
-
tmplist = []
|
|
71
|
-
result = []
|
|
72
|
-
max_size = 80
|
|
73
|
-
err_list = []
|
|
74
|
-
for stk in stocklist:
|
|
75
|
-
tmplist.append((1 if stk.market == 'SH' else 0, stk.code))
|
|
76
|
-
count += 1
|
|
77
|
-
if count >= max_size:
|
|
78
|
-
phase_result = request_data(api, tmplist, parse_one_result)
|
|
79
|
-
if phase_result:
|
|
80
|
-
result.extend(phase_result)
|
|
81
|
-
if batch_func:
|
|
82
|
-
batch_func(phase_result)
|
|
83
|
-
else:
|
|
84
|
-
err_list.extend(tmplist)
|
|
85
|
-
count = 0
|
|
86
|
-
tmplist = []
|
|
87
|
-
if tmplist:
|
|
88
|
-
phase_result = request_data(api, tmplist, parse_one_result)
|
|
89
|
-
if phase_result:
|
|
90
|
-
result.extend(phase_result)
|
|
91
|
-
if batch_func:
|
|
92
|
-
batch_func(phase_result)
|
|
93
|
-
else:
|
|
94
|
-
err_list.extend(tmplist)
|
|
95
|
-
api.disconnect()
|
|
96
|
-
return result, err_list
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
@spend_time
|
|
100
|
-
def get_spot(stocklist, ip, port, batch_func=None):
|
|
101
|
-
hosts = search_best_tdx()
|
|
102
|
-
hosts_cnt = len(hosts)
|
|
103
|
-
num = len(stocklist) // hosts_cnt
|
|
104
|
-
batchslist = []
|
|
105
|
-
for i in range(hosts_cnt):
|
|
106
|
-
batchslist.append([[stk for stk in stocklist[i*num: (i+1)*num]], hosts[i][2], hosts[i][3], batch_func])
|
|
107
|
-
if len(stocklist) % hosts_cnt != 0:
|
|
108
|
-
pos = num * hosts_cnt
|
|
109
|
-
for i in range(hosts_cnt):
|
|
110
|
-
batchslist[i][0].append(stocklist[pos])
|
|
111
|
-
pos += 1
|
|
112
|
-
if pos >= len(stocklist):
|
|
113
|
-
break
|
|
114
|
-
|
|
115
|
-
def do_inner(param):
|
|
116
|
-
ret = inner_get_spot(param[0], param[1], param[2], param[3])
|
|
117
|
-
return ret
|
|
118
|
-
|
|
119
|
-
with futures.ThreadPoolExecutor() as executor:
|
|
120
|
-
res = executor.map(do_inner, batchslist, timeout=10)
|
|
121
|
-
|
|
122
|
-
result = []
|
|
123
|
-
errors = []
|
|
124
|
-
for batch_result in res:
|
|
125
|
-
if batch_result[0]:
|
|
126
|
-
result.extend(batch_result[0])
|
|
127
|
-
if batch_result[1]:
|
|
128
|
-
errors.extend(batch_result[1])
|
|
129
|
-
return result, errors
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/python
|
|
2
|
-
# -*- coding: utf8 -*-
|
|
3
|
-
# cp936
|
|
4
|
-
import logging
|
|
5
|
-
import time
|
|
6
|
-
import datetime
|
|
7
|
-
from math import ceil
|
|
8
|
-
from PyQt5.QtCore import QThread, QWaitCondition, QMutex
|
|
9
|
-
|
|
10
|
-
from hikyuu import Datetime, TimeDelta, hikyuu_init, StockManager, constant
|
|
11
|
-
from hikyuu.util import *
|
|
12
|
-
from hikyuu.fetcher.stock.zh_stock_a_sina_qq import get_spot
|
|
13
|
-
from hikyuu.data.sqlite_mem import SqliteMemDriver
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class CollectToMemThread(QThread):
|
|
17
|
-
def __init__(self, config, hku_config_file, market='SH'):
|
|
18
|
-
super(self.__class__, self).__init__()
|
|
19
|
-
self.working = True
|
|
20
|
-
self._config = config
|
|
21
|
-
self.hku_config_file = hku_config_file
|
|
22
|
-
self.market = market.lower()
|
|
23
|
-
self.marketid = None
|
|
24
|
-
self._interval = TimeDelta(seconds=config.getint('collect', 'interval', fallback=60 * 60))
|
|
25
|
-
self._phase1_start_time = Datetime(
|
|
26
|
-
datetime.datetime.combine(
|
|
27
|
-
datetime.date.today(),
|
|
28
|
-
datetime.time.fromisoformat((config.get('collect', 'phase1_start', fallback='09:05')))
|
|
29
|
-
)
|
|
30
|
-
)
|
|
31
|
-
self._phase1_end_time = Datetime(
|
|
32
|
-
datetime.datetime.combine(
|
|
33
|
-
datetime.date.today(),
|
|
34
|
-
datetime.time.fromisoformat((config.get('collect', 'phase1_end', fallback='09:05')))
|
|
35
|
-
)
|
|
36
|
-
)
|
|
37
|
-
self._use_zhima_proxy = config.getboolean('collect', 'use_zhima_proxy', fallback=False)
|
|
38
|
-
|
|
39
|
-
self.cond = QWaitCondition()
|
|
40
|
-
self.mutex = QMutex()
|
|
41
|
-
|
|
42
|
-
def stop(self):
|
|
43
|
-
if self.working:
|
|
44
|
-
self.working = False
|
|
45
|
-
self.cond.wakeAll()
|
|
46
|
-
self.wait()
|
|
47
|
-
|
|
48
|
-
def __del__(self):
|
|
49
|
-
self.stop()
|
|
50
|
-
|
|
51
|
-
@hku_catch()
|
|
52
|
-
def run(self):
|
|
53
|
-
self.logger.info("{} 数据采集同步线程启动".format(self.market))
|
|
54
|
-
self.db = SqliteMemDriver()
|
|
55
|
-
|
|
56
|
-
hikyuu_init(self.hku_config_file, ignore_preload=True)
|
|
57
|
-
|
|
58
|
-
stk_list = self.get_stock_list()
|
|
59
|
-
hku_warn_if(not stk_list, "从数据库中获取的股票列表为空!", logger=self.logger)
|
|
60
|
-
self.mutex.tryLock()
|
|
61
|
-
|
|
62
|
-
end_delta = self._phase1_end_time - self._phase1_end_time.start_of_day()
|
|
63
|
-
start_delta = self._phase1_start_time - self._phase1_start_time.start_of_day()
|
|
64
|
-
|
|
65
|
-
start = Datetime.now()
|
|
66
|
-
if self._phase1_start_time >= self._phase1_end_time:
|
|
67
|
-
delta = TimeDelta(0)
|
|
68
|
-
elif start >= self._phase1_end_time:
|
|
69
|
-
delta = (self._phase1_start_time + TimeDelta(1) - start)
|
|
70
|
-
elif start < self._phase1_start_time:
|
|
71
|
-
delta = (self._phase1_start_time - start)
|
|
72
|
-
else:
|
|
73
|
-
delta = self._interval * ceil((start - self._phase1_start_time) / self._interval
|
|
74
|
-
) - (start - self._phase1_start_time)
|
|
75
|
-
|
|
76
|
-
hku_info('{} 下次采集时间:{}', self.market, start + delta, logger=self.logger)
|
|
77
|
-
delta = int(delta.total_milliseconds())
|
|
78
|
-
while self.working and not self.cond.wait(self.mutex, int(delta)):
|
|
79
|
-
last_time = Datetime.today() + end_delta
|
|
80
|
-
start = Datetime.now()
|
|
81
|
-
if start >= last_time:
|
|
82
|
-
next_time = Datetime.today() + TimeDelta(1) + start_delta
|
|
83
|
-
hku_info('{} 明日采集时间:{}', self.market, next_time, logger=self.logger)
|
|
84
|
-
delta = next_time - start
|
|
85
|
-
delta = int(delta.total_milliseconds())
|
|
86
|
-
continue
|
|
87
|
-
hku_trace("start:{}".format(start))
|
|
88
|
-
self.collect(stk_list)
|
|
89
|
-
end = Datetime.now()
|
|
90
|
-
x = end - start
|
|
91
|
-
if x + TimeDelta(seconds=1) < self._interval:
|
|
92
|
-
delta = self._interval - x - TimeDelta(seconds=1)
|
|
93
|
-
delta = int(delta.total_milliseconds())
|
|
94
|
-
self.logger.info("{} {:<.2f} 秒后重新采集".format(self.market, delta / 1000))
|
|
95
|
-
# self.sleep(delta)
|
|
96
|
-
|
|
97
|
-
self.db.close()
|
|
98
|
-
self.logger.info("{} 数据采集同步线程终止!".format(self.market))
|
|
99
|
-
|
|
100
|
-
@hku_catch(retry=2, ret=[])
|
|
101
|
-
def get_stock_list(self):
|
|
102
|
-
sm = StockManager.instance()
|
|
103
|
-
return [
|
|
104
|
-
stk.market_code.lower() for stk in sm
|
|
105
|
-
if stk.type in (constant.STOCKTYPE_A, constant.STOCKTYPE_INDEX,
|
|
106
|
-
constant.STOCKTYPE_GEM, constant.STOCKTYPE_A_BJ) and stk.valid and stk.market.lower() == self.market.lower()
|
|
107
|
-
]
|
|
108
|
-
|
|
109
|
-
def record_is_valid(self, record):
|
|
110
|
-
return record['amount'] > 0.0 and record['volume'] > 0.0 \
|
|
111
|
-
and record['high'] >= record['open'] >= record['low'] > 0.0 \
|
|
112
|
-
and record['high'] >= record['close'] >= record['low']
|
|
113
|
-
|
|
114
|
-
@hku_catch()
|
|
115
|
-
def collect(self, stk_list):
|
|
116
|
-
record_list = get_spot(stk_list, source='sina', use_proxy=self._use_zhima_proxy)
|
|
117
|
-
hku_info("{} 网络获取数量:{}".format(self.market, len(record_list)))
|
|
118
|
-
record_list = [r for r in record_list if self.record_is_valid(r)]
|
|
119
|
-
self.db.insert_bars(self.market, record_list, 'day')
|
|
120
|
-
self.db.insert_bars(self.market, record_list, 'min')
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
class_logger(CollectToMemThread)
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/python
|
|
2
|
-
# -*- coding: utf8 -*-
|
|
3
|
-
# cp936
|
|
4
|
-
import logging
|
|
5
|
-
import time
|
|
6
|
-
import datetime
|
|
7
|
-
from math import ceil
|
|
8
|
-
from PyQt5.QtCore import QThread, QWaitCondition, QMutex
|
|
9
|
-
|
|
10
|
-
import mysql.connector
|
|
11
|
-
from mysql.connector import errorcode
|
|
12
|
-
|
|
13
|
-
from hikyuu import Datetime, TimeDelta
|
|
14
|
-
from hikyuu.util import *
|
|
15
|
-
from hikyuu.data.common_mysql import get_stock_list, get_marketid, get_table
|
|
16
|
-
from hikyuu.fetcher.stock.zh_stock_a_sina_qq import get_spot
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class CollectToMySQLThread(QThread):
|
|
20
|
-
def __init__(self, config, market='SH'):
|
|
21
|
-
super(self.__class__, self).__init__()
|
|
22
|
-
self.working = True
|
|
23
|
-
self._config = config
|
|
24
|
-
self.market = market.lower()
|
|
25
|
-
self.marketid = None
|
|
26
|
-
assert config.getboolean("mysql", "enable", fallback=False)
|
|
27
|
-
self._db_config = {
|
|
28
|
-
'user': config['mysql']['usr'],
|
|
29
|
-
'password': config['mysql']['pwd'],
|
|
30
|
-
'host': config['mysql']['host'],
|
|
31
|
-
'port': config['mysql']['port']
|
|
32
|
-
}
|
|
33
|
-
self._connect = None
|
|
34
|
-
self.quotations = [
|
|
35
|
-
'stock',
|
|
36
|
-
] # sina 不支持基金,qq支持,此处屏蔽基金
|
|
37
|
-
# if config['quotation']['stock']:
|
|
38
|
-
# self.quotations.append('stock')
|
|
39
|
-
# if config['quotation']['fund']:
|
|
40
|
-
# self.quotations.append('fund')
|
|
41
|
-
# self.logger.info(self.quotations)
|
|
42
|
-
|
|
43
|
-
self._interval = TimeDelta(seconds=config.getint('collect', 'interval', fallback=60 * 60))
|
|
44
|
-
self._phase1_start_time = Datetime(
|
|
45
|
-
datetime.datetime.combine(
|
|
46
|
-
datetime.date.today(),
|
|
47
|
-
datetime.time.fromisoformat((config.get('collect', 'phase1_start', fallback='09:05')))
|
|
48
|
-
)
|
|
49
|
-
)
|
|
50
|
-
self._phase1_end_time = Datetime(
|
|
51
|
-
datetime.datetime.combine(
|
|
52
|
-
datetime.date.today(),
|
|
53
|
-
datetime.time.fromisoformat((config.get('collect', 'phase1_end', fallback='09:05')))
|
|
54
|
-
)
|
|
55
|
-
)
|
|
56
|
-
self._use_zhima_proxy = config.getboolean('collect', 'use_zhima_proxy', fallback=False)
|
|
57
|
-
|
|
58
|
-
self.cond = QWaitCondition()
|
|
59
|
-
self.mutex = QMutex()
|
|
60
|
-
|
|
61
|
-
def stop(self):
|
|
62
|
-
if self.working:
|
|
63
|
-
self.working = False
|
|
64
|
-
self.cond.wakeAll()
|
|
65
|
-
self.wait()
|
|
66
|
-
if self._connect is not None:
|
|
67
|
-
hku_trace('关闭数据库连接', logger=self.logger)
|
|
68
|
-
self._connect.close()
|
|
69
|
-
|
|
70
|
-
def __del__(self):
|
|
71
|
-
self.stop()
|
|
72
|
-
|
|
73
|
-
@hku_catch()
|
|
74
|
-
def run(self):
|
|
75
|
-
self.logger.info("{} 数据采集同步线程启动".format(self.market))
|
|
76
|
-
stk_list = self.get_stock_list()
|
|
77
|
-
hku_warn_if(not stk_list, "从数据库中获取的股票列表为空!", logger=self.logger)
|
|
78
|
-
self.mutex.tryLock()
|
|
79
|
-
|
|
80
|
-
end_delta = self._phase1_end_time - self._phase1_end_time.start_of_day()
|
|
81
|
-
start_delta = self._phase1_start_time - self._phase1_start_time.start_of_day()
|
|
82
|
-
|
|
83
|
-
start = Datetime.now()
|
|
84
|
-
if self._phase1_start_time >= self._phase1_end_time:
|
|
85
|
-
delta = TimeDelta(0)
|
|
86
|
-
elif start >= self._phase1_end_time:
|
|
87
|
-
delta = (self._phase1_start_time + TimeDelta(1) - start)
|
|
88
|
-
elif start < self._phase1_start_time:
|
|
89
|
-
delta = (self._phase1_start_time - start)
|
|
90
|
-
else:
|
|
91
|
-
delta = self._interval * ceil((start - self._phase1_start_time) / self._interval
|
|
92
|
-
) - (start - self._phase1_start_time)
|
|
93
|
-
|
|
94
|
-
hku_info('{} 下次采集时间:{}', self.market, start + delta, logger=self.logger)
|
|
95
|
-
delta = int(delta.total_milliseconds())
|
|
96
|
-
while self.working and not self.cond.wait(self.mutex, int(delta)):
|
|
97
|
-
last_time = Datetime.today() + end_delta
|
|
98
|
-
start = Datetime.now()
|
|
99
|
-
if start >= last_time:
|
|
100
|
-
next_time = Datetime.today() + TimeDelta(1) + start_delta
|
|
101
|
-
hku_info('{} 明日采集时间:{}', self.market, next_time, logger=self.logger)
|
|
102
|
-
delta = next_time - start
|
|
103
|
-
delta = int(delta.total_milliseconds())
|
|
104
|
-
continue
|
|
105
|
-
hku_trace("start:{}".format(start))
|
|
106
|
-
self.collect(stk_list)
|
|
107
|
-
end = Datetime.now()
|
|
108
|
-
x = end - start
|
|
109
|
-
if x + TimeDelta(seconds=1) < self._interval:
|
|
110
|
-
delta = self._interval - x - TimeDelta(seconds=1)
|
|
111
|
-
delta = int(delta.total_milliseconds())
|
|
112
|
-
self.logger.info("{} {:<.2f} 秒后重新采集".format(self.market, delta / 1000))
|
|
113
|
-
# self.sleep(delta)
|
|
114
|
-
|
|
115
|
-
self.logger.info("{} 数据采集同步线程终止!".format(self.market))
|
|
116
|
-
|
|
117
|
-
def record_is_valid(self, record):
|
|
118
|
-
return record['amount'] > 0.0 and record['volume'] > 0.0 \
|
|
119
|
-
and record['high'] >= record['open'] >= record['low'] > 0.0 \
|
|
120
|
-
and record['high'] >= record['close'] >= record['low']
|
|
121
|
-
|
|
122
|
-
@hku_catch(ret=False)
|
|
123
|
-
def process_one_record(self, record):
|
|
124
|
-
if not self.record_is_valid(record):
|
|
125
|
-
return (0, 0)
|
|
126
|
-
connect = self.get_connect()
|
|
127
|
-
current_date = Datetime(record['datetime'].date()).number
|
|
128
|
-
table = get_table(connect, self.market, record['code'], 'day')
|
|
129
|
-
sql = 'replace into {} (date, open, high, low, close, amount, count) \
|
|
130
|
-
values ({}, {}, {}, {}, {}, {}, {})'.format(
|
|
131
|
-
table, current_date, record['open'], record['high'], record['low'], record['close'], record['amount'],
|
|
132
|
-
record['volume']
|
|
133
|
-
)
|
|
134
|
-
cur = connect.cursor()
|
|
135
|
-
cur.execute(sql)
|
|
136
|
-
cur.close()
|
|
137
|
-
return
|
|
138
|
-
|
|
139
|
-
@hku_catch()
|
|
140
|
-
def collect(self, stk_list):
|
|
141
|
-
record_list = get_spot(stk_list, source='sina', use_proxy=self._use_zhima_proxy)
|
|
142
|
-
hku_info("{} 网络获取数量:{}".format(self.market, len(record_list)))
|
|
143
|
-
connect = self.get_connect()
|
|
144
|
-
if self.marketid == None:
|
|
145
|
-
self.marketid = get_marketid(connect, self.market)
|
|
146
|
-
update_count = 0
|
|
147
|
-
for record in record_list:
|
|
148
|
-
if not self.working:
|
|
149
|
-
break
|
|
150
|
-
if self.process_one_record(record):
|
|
151
|
-
update_count += 1
|
|
152
|
-
connect.commit()
|
|
153
|
-
hku_info("{} 数据库更新记录数:{}".format(self.market, update_count))
|
|
154
|
-
|
|
155
|
-
def get_connect(self):
|
|
156
|
-
if self._connect:
|
|
157
|
-
return self._connect
|
|
158
|
-
try:
|
|
159
|
-
self._connect = mysql.connector.connect(**self._db_config)
|
|
160
|
-
except mysql.connector.Error as err:
|
|
161
|
-
if err.errno == errorcode.ER_ACCESS_DENIED_ERROR:
|
|
162
|
-
self.logger.error("MYSQL密码或用户名错误!")
|
|
163
|
-
elif err.errno == errorcode.ER_BAD_DB_ERROR:
|
|
164
|
-
self.logger.error("MySQL数据库不存在!")
|
|
165
|
-
else:
|
|
166
|
-
self.logger.error("连接数据库失败,{}".format(err.msg))
|
|
167
|
-
except:
|
|
168
|
-
self.logger.error("未知原因导致无法连接数据库!")
|
|
169
|
-
return self._connect
|
|
170
|
-
|
|
171
|
-
@hku_catch(retry=2, ret=[])
|
|
172
|
-
def get_stock_list(self):
|
|
173
|
-
connect = self.get_connect()
|
|
174
|
-
stk_list = get_stock_list(connect, self.market, self.quotations)
|
|
175
|
-
return ["{}{}".format(self.market.lower(), item[2]) for item in stk_list if item[3] == 1]
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
class_logger(CollectToMySQLThread)
|