shepherdpp / qteasy

a python-based fast quantitative investment module
BSD 3-Clause "New" or "Revised" License
73 stars 28 forks source link

从tushare下载数据的2个问题,tushare接口访问频次限制 #144

Closed roc138 closed 6 months ago

roc138 commented 6 months ago

第1个问题是个告警,应该不影响什么吧? C:\ProgramData\anaconda3\envs\qteasy-env-p311\Lib\site-packages\qteasy\database.py:5085: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation. dnld_data = pd.concat([dnld_data, df])

第2个问题,换了2个5000分以上tushare token,都还是报错。估计是tushare 每分钟读取频率限制的问题,请问大佬哪里可以调整tusahre数据的读取频率?

运行的脚本: qt.refill_data_source(tables='events', start_date='20230101', end_date='20240403',reversed_par_seq=True) 把refill_data_source函数中的parallel=True,merge_type='update'参数去掉了也还是不行。

报错日志: [##############--------------------------]6000/16923-35.5% 37107wrtn/about 19 minleftC:\ProgramData\anaconda3\envs\qteasy-env-p311\Lib\site-packages\qteasy**database.py:5134: UserWarning: 抱歉,您每分钟最多访问该接口600次,权限的具体详情访问:https://tushare.pro/document/1?doc_id=108。: download process interrupted at [fund_share]:<F180003.OF>-<016408.OF> 37107 rows downloaded, will proceed with next table! warnings.warn(msg) [#######################-----------------]10000/16923-59.1% 1264483wrtn/about 15 minleftC:\ProgramData\anaconda3\envs\qteasy-env-p311\Lib\site-packages\qteasy\database.py:5134: UserWarning: 抱歉,您每分钟最多访问该接口500次,权限的具体详情访问:https://tushare.pro/document/1?doc_id=108。:** download process interrupted at [fund_manager]:<F180003.OF>-<012278.OF> 1264483 rows downloaded, will proceed with next table! warnings.warn(msg) image

有没有这种类似的参数可以设置的?

self.params.rows_limit = 5000 # 该接口限制每次调用,最大获取数据量

    # self.params.times_limit = 800  # 该接口限制,每分钟最多调用次数
    # self.params.sleep_time = 61  # 一分钟内到了最多调用次数上线后,休眠多少秒
shepherdpp commented 6 months ago

请尝试修改qteasy的下面几个配置,调整下载数据时的重试次数和延时设置,这几个参数是专门为了应对tushare的读取频率限制设置的:

QT_CONFIG.hist_dnld_retry_cnt - 下载数据时失败重试的次数,默认为7次 QT_CONFIG.hist_dnld_retry_wait - 第一次下载失败时的等待时长,单位为秒,默认为1秒 QT_CONFIG.hist_dnld_backoff - 等待后仍然失败时等待时间的倍增乘数,默认为2倍

qteasy在调用所有的tushare函数时,会自动retry,每两次retry之间会逐渐延长间隔。比如,第一次下载不成功时,会暂停一秒重试,如果重试仍然有问题,会等待2秒重试,下一次等待4秒、再等待8秒。。。依此类推,一直到重试次数用光,这时才会raise。

正常来讲,重试7次后的延时会倍增到32秒,加上前面延时的长度,已经超过1分钟了,正常是不会触发频率错误的,但如果您的网速过快,或者同时启用的线程太多,可能会有上面的问题。

可以尝试将重试次数改成10次或更多(这样会显著延长下载时间),或者增加等待初始时长:

qt.configure(hist_dnld_retry_cnt=10, hist_dnld_retry_wait=2.)

如果您做了上面的修改仍然会报错,那么有可能是我最近在1.1.7以后版本的retry函数中增加的“逃逸”信息引起的,因为我考虑到有的情况下如果tushare报错说用户没有权限,那么就没必要一直重试了,因此设置了一些逃逸条件。如果是这个情况,请告诉我,我来仔细检查。

roc138 commented 6 months ago

使用qt.configure(hist_dnld_retry_cnt=10, hist_dnld_retry_wait=2.)后还是报错。

我又增加了几个参数,也还是会报错。 qt.configure(hist_dnld_retry_cnt=10, hist_dnld_retry_wait=5.,hist_dnld_delay=2.,hist_dnld_delay_evy=2,hist_dnld_backoff=3.) qt.refill_data_source(tables='events', start_date='20230101', end_date='20240403', reversed_par_seq=True)

[#################-----------------------]7551/16923-44.6% 543612wrtn/about 20 minleftC:\ProgramData\anaconda3\envs\qteasy-env-p311\Lib\site-packages\qteasy\database.py:5085: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation. dnld_data = pd.concat([dnld_data, df]) [#################-----------------------]7560/16923-44.7% 547716wrtn/about 20 minleftC:\ProgramData\anaconda3\envs\qteasy-env-p311\Lib\site-packages\qteasy\database.py:5085: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation. dnld_data = pd.concat([dnld_data, df]) [##################----------------------]7800/16923-46.1% 659410wrtn/about 19 minleftC:\ProgramData\anaconda3\envs\qteasy-env-p311\Lib\site-packages\qteasy\database.py:5134: UserWarning: 抱歉,您每分钟最多访问该接口600次,权限的具体详情访问:https://tushare.pro/document/1?doc_id=108。: download process interrupted at [fund_share]:<F180003.OF>-<014544.OF> 659410 rows downloaded, will proceed with next table! warnings.warn(msg) [###############-------------------------]6500/16923-38.4% 538854wrtn/about 24 minleftC:\ProgramData\anaconda3\envs\qteasy-env-p311\Lib\site-packages\qteasy\database.py:5134: UserWarning: 抱歉,您每分钟最多访问该接口500次,权限的具体详情访问:https://tushare.pro/document/1?doc_id=108。: download process interrupted at [fund_manager]:<F180003.OF>-<015894.OF> 538854 rows downloaded, will proceed with next table! warnings.warn(msg)

进程已结束,退出代码为 0

shepherdpp commented 6 months ago

经检查,问题的原因在于我使用了静态decorator来实现tushare api的重试。重试的参数是在程序读取的时候就确定了,后面即使修改config参数,实际重试的次数也不会改变。所以,尽管已经将重试次数改为10次,但实际上程序运行时仍然只重试7次。

抱歉造成上面的问题,现在已经有了解决方案。

解决方案是使用动态decorator,每次调用tushare api的时候系统会读取config参数并重新生成decorated_func,经测试,修改config参数后,重试的参数已经能按照config改变了。

另外,为了方便,对于tushare实施了频率限制的api,现在他们的retry次数会被特殊处理。qteasy在使用这些api获取数据时,会在config设置的基础上多3次重试。用户不再需要手动修改。会自动额外重试的API包括:

如果完整的测试都能通过,上面的改变将在1.1.10版本中发布,敬请期待!

shepherdpp commented 6 months ago

修正bug之后的qteasy v1.1.10 版本已经发布到pypi!请升级最新版qteasy

$ pip install qteasy -U

更新后的版本改变了retry装饰器的使用方式,使得QT_CONFIG变化后能立即影响retry的参数。因此,在从tushare下载数据时如果积分不够导致频率受限,可以通过修改以下参数增加重试次数和等待时间,规避因频率受限导致的下载失败。

QT_CONFIG.hist_dnld_retry_cnt - 下载数据时失败重试的次数,默认为7次 QT_CONFIG.hist_dnld_retry_wait - 第一次下载失败时的等待时长,单位为秒,默认为1秒 QT_CONFIG.hist_dnld_backoff - 等待后仍然失败时等待时间的倍增乘数,默认为2倍

麻烦再测试一下,如果问题得到解决,请关闭此Issue,如果还有其他问题,请跟我联系!

roc138 commented 6 months ago

程序运行过程中尝试次1次失败后,再进行第2次尝试,成功了。 C:\ProgramData\anaconda3\envs\qteasy-env-p311\Lib\site-packages\qteasy\database.py:5085: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation. dnld_data = pd.concat([dnld_data, df]) [#########################---------------]10800/16923-63.8% 0wrtn/about 11 minleftC:\ProgramData\anaconda3\envs\qteasy-env-p311\Lib\site-packages\qteasy\database.py:5134: UserWarning: 抱歉,您每分钟最多访问该接口600次,权限的具体详情访问:https://tushare.pro/document/1?doc_id=108。: download process interrupted at [fund_share]:<F180003.OF>-<011439.OF> 0 rows downloaded, will proceed with next table! warnings.warn(msg) [########################################]16923/16923-100.0% 2287650wrtn in ~37' 进程已结束,退出代码为 0