lib-x17-fintech 2.1.3__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.
Files changed (282) hide show
  1. lib_x17_fintech-2.1.3.dist-info/METADATA +633 -0
  2. lib_x17_fintech-2.1.3.dist-info/RECORD +282 -0
  3. lib_x17_fintech-2.1.3.dist-info/WHEEL +5 -0
  4. lib_x17_fintech-2.1.3.dist-info/licenses/LICENSE +1 -0
  5. lib_x17_fintech-2.1.3.dist-info/top_level.txt +1 -0
  6. xfintech/__init__.py +0 -0
  7. xfintech/connect/__init__.py +18 -0
  8. xfintech/connect/artifact/__init__.py +5 -0
  9. xfintech/connect/artifact/artifact.py +168 -0
  10. xfintech/connect/artifact/tests/__init__.py +3 -0
  11. xfintech/connect/artifact/tests/test_class_artifact_all.py +564 -0
  12. xfintech/connect/common/__init__.py +12 -0
  13. xfintech/connect/common/connect.py +49 -0
  14. xfintech/connect/common/connectref.py +119 -0
  15. xfintech/connect/common/error.py +62 -0
  16. xfintech/connect/common/tests/__init__.py +1 -0
  17. xfintech/connect/common/tests/test_class_connectlike_all.py +544 -0
  18. xfintech/connect/common/tests/test_class_connectref_all.py +586 -0
  19. xfintech/connect/common/tests/test_class_errors_all.py +524 -0
  20. xfintech/connect/instance/__init__.py +7 -0
  21. xfintech/connect/instance/macos.py +121 -0
  22. xfintech/connect/instance/s3.py +176 -0
  23. xfintech/connect/instance/tests/__init__.py +1 -0
  24. xfintech/connect/instance/tests/test_class_macosconnect_all.py +692 -0
  25. xfintech/connect/instance/tests/test_class_s3connect_all.py +603 -0
  26. xfintech/data/__init__.py +20 -0
  27. xfintech/data/common/__init__.py +15 -0
  28. xfintech/data/common/cache.py +186 -0
  29. xfintech/data/common/coolant.py +171 -0
  30. xfintech/data/common/metric.py +138 -0
  31. xfintech/data/common/paginate.py +132 -0
  32. xfintech/data/common/params.py +162 -0
  33. xfintech/data/common/retry.py +201 -0
  34. xfintech/data/common/tests/__init__.py +1 -0
  35. xfintech/data/common/tests/test_class_cache_all.py +681 -0
  36. xfintech/data/common/tests/test_class_coolant_all.py +534 -0
  37. xfintech/data/common/tests/test_class_metric_all.py +705 -0
  38. xfintech/data/common/tests/test_class_paginate_all.py +508 -0
  39. xfintech/data/common/tests/test_class_params_all.py +891 -0
  40. xfintech/data/common/tests/test_class_retry_all.py +714 -0
  41. xfintech/data/job/__init__.py +17 -0
  42. xfintech/data/job/errors.py +112 -0
  43. xfintech/data/job/house.py +156 -0
  44. xfintech/data/job/job.py +247 -0
  45. xfintech/data/job/joblike.py +47 -0
  46. xfintech/data/job/tests/__init__.py +1 -0
  47. xfintech/data/job/tests/test_class_errors_all.py +275 -0
  48. xfintech/data/job/tests/test_class_house_all.py +801 -0
  49. xfintech/data/job/tests/test_class_job_all.py +684 -0
  50. xfintech/data/job/tests/test_class_joblike_all.py +482 -0
  51. xfintech/data/relay/__init__.py +7 -0
  52. xfintech/data/relay/client.py +114 -0
  53. xfintech/data/relay/clientlike.py +45 -0
  54. xfintech/data/relay/tests/test_class_relayclient_all.py +484 -0
  55. xfintech/data/relay/tests/test_class_relayclientlike_all.py +500 -0
  56. xfintech/data/source/__init__.py +7 -0
  57. xfintech/data/source/baostock/__init__.py +21 -0
  58. xfintech/data/source/baostock/job/__init__.py +5 -0
  59. xfintech/data/source/baostock/job/job.py +217 -0
  60. xfintech/data/source/baostock/job/tests/__init__.py +0 -0
  61. xfintech/data/source/baostock/job/tests/test_class_baostockjob_all.py +547 -0
  62. xfintech/data/source/baostock/session/__init__.py +8 -0
  63. xfintech/data/source/baostock/session/relay.py +223 -0
  64. xfintech/data/source/baostock/session/session.py +241 -0
  65. xfintech/data/source/baostock/session/tests/__init__.py +0 -0
  66. xfintech/data/source/baostock/session/tests/test_class_relay_all.py +694 -0
  67. xfintech/data/source/baostock/session/tests/test_class_session_all.py +505 -0
  68. xfintech/data/source/baostock/stock/__init__.py +0 -0
  69. xfintech/data/source/baostock/stock/hs300stock/__init__.py +3 -0
  70. xfintech/data/source/baostock/stock/hs300stock/constant.py +49 -0
  71. xfintech/data/source/baostock/stock/hs300stock/hs300stock.py +133 -0
  72. xfintech/data/source/baostock/stock/hs300stock/tests/__init__.py +1 -0
  73. xfintech/data/source/baostock/stock/hs300stock/tests/test_class_hs300index_all.py +413 -0
  74. xfintech/data/source/baostock/stock/minuteline/__init__.py +19 -0
  75. xfintech/data/source/baostock/stock/minuteline/constant.py +89 -0
  76. xfintech/data/source/baostock/stock/minuteline/minuteline.py +163 -0
  77. xfintech/data/source/baostock/stock/minuteline/tests/__init__.py +0 -0
  78. xfintech/data/source/baostock/stock/minuteline/tests/test_class_minuteline_all.py +582 -0
  79. xfintech/data/source/baostock/stock/stock/__init__.py +19 -0
  80. xfintech/data/source/baostock/stock/stock/constant.py +55 -0
  81. xfintech/data/source/baostock/stock/stock/stock.py +149 -0
  82. xfintech/data/source/baostock/stock/stock/tests/__init__.py +0 -0
  83. xfintech/data/source/baostock/stock/stock/tests/test_class_stock_all.py +508 -0
  84. xfintech/data/source/baostock/stock/stockinfo/__init__.py +5 -0
  85. xfintech/data/source/baostock/stock/stockinfo/constant.py +66 -0
  86. xfintech/data/source/baostock/stock/stockinfo/stockinfo.py +176 -0
  87. xfintech/data/source/baostock/stock/stockinfo/tests/__init__.py +1 -0
  88. xfintech/data/source/baostock/stock/stockinfo/tests/test_class_stockinfo_all.py +617 -0
  89. xfintech/data/source/baostock/stock/sz50stock/__init__.py +3 -0
  90. xfintech/data/source/baostock/stock/sz50stock/constant.py +49 -0
  91. xfintech/data/source/baostock/stock/sz50stock/sz50stock.py +133 -0
  92. xfintech/data/source/baostock/stock/sz50stock/tests/__init__.py +1 -0
  93. xfintech/data/source/baostock/stock/sz50stock/tests/test_class_sz50stock_all.py +397 -0
  94. xfintech/data/source/baostock/stock/tradedate/__init__.py +19 -0
  95. xfintech/data/source/baostock/stock/tradedate/constant.py +72 -0
  96. xfintech/data/source/baostock/stock/tradedate/tests/__init__.py +0 -0
  97. xfintech/data/source/baostock/stock/tradedate/tests/test_class_tradedate_all.py +695 -0
  98. xfintech/data/source/baostock/stock/tradedate/tradedate.py +208 -0
  99. xfintech/data/source/baostock/stock/zz500stock/__init__.py +3 -0
  100. xfintech/data/source/baostock/stock/zz500stock/constant.py +55 -0
  101. xfintech/data/source/baostock/stock/zz500stock/tests/__init__.py +1 -0
  102. xfintech/data/source/baostock/stock/zz500stock/tests/test_class_zz500stock_all.py +421 -0
  103. xfintech/data/source/baostock/stock/zz500stock/zz500stock.py +133 -0
  104. xfintech/data/source/tushare/__init__.py +61 -0
  105. xfintech/data/source/tushare/job/__init__.py +5 -0
  106. xfintech/data/source/tushare/job/job.py +257 -0
  107. xfintech/data/source/tushare/job/tests/test_class_tusharejob_all.py +589 -0
  108. xfintech/data/source/tushare/session/__init__.py +5 -0
  109. xfintech/data/source/tushare/session/relay.py +231 -0
  110. xfintech/data/source/tushare/session/session.py +239 -0
  111. xfintech/data/source/tushare/session/tests/test_class_relay_all.py +719 -0
  112. xfintech/data/source/tushare/session/tests/test_class_session_all.py +705 -0
  113. xfintech/data/source/tushare/stock/__init__.py +55 -0
  114. xfintech/data/source/tushare/stock/adjfactor/__init__.py +19 -0
  115. xfintech/data/source/tushare/stock/adjfactor/adjfactor.py +150 -0
  116. xfintech/data/source/tushare/stock/adjfactor/constant.py +71 -0
  117. xfintech/data/source/tushare/stock/adjfactor/tests/__init__.py +0 -0
  118. xfintech/data/source/tushare/stock/adjfactor/tests/test_class_adjfactor_all.py +372 -0
  119. xfintech/data/source/tushare/stock/capflow/__init__.py +19 -0
  120. xfintech/data/source/tushare/stock/capflow/capflow.py +171 -0
  121. xfintech/data/source/tushare/stock/capflow/constant.py +105 -0
  122. xfintech/data/source/tushare/stock/capflow/tests/__init__.py +0 -0
  123. xfintech/data/source/tushare/stock/capflow/tests/test_class_capflow_all.py +589 -0
  124. xfintech/data/source/tushare/stock/capflowdc/__init__.py +19 -0
  125. xfintech/data/source/tushare/stock/capflowdc/capflowdc.py +167 -0
  126. xfintech/data/source/tushare/stock/capflowdc/constant.py +95 -0
  127. xfintech/data/source/tushare/stock/capflowdc/tests/__init__.py +0 -0
  128. xfintech/data/source/tushare/stock/capflowdc/tests/test_class_capflowdc_all.py +814 -0
  129. xfintech/data/source/tushare/stock/capflowths/__init__.py +19 -0
  130. xfintech/data/source/tushare/stock/capflowths/capflowths.py +173 -0
  131. xfintech/data/source/tushare/stock/capflowths/constant.py +92 -0
  132. xfintech/data/source/tushare/stock/capflowths/tests/__init__.py +0 -0
  133. xfintech/data/source/tushare/stock/capflowths/tests/test_class_capflowths_all.py +551 -0
  134. xfintech/data/source/tushare/stock/company/__init__.py +19 -0
  135. xfintech/data/source/tushare/stock/company/company.py +188 -0
  136. xfintech/data/source/tushare/stock/company/constant.py +92 -0
  137. xfintech/data/source/tushare/stock/company/tests/__init__.py +1 -0
  138. xfintech/data/source/tushare/stock/company/tests/test_class_company_all.py +829 -0
  139. xfintech/data/source/tushare/stock/companybusiness/__init__.py +21 -0
  140. xfintech/data/source/tushare/stock/companybusiness/companybusiness.py +183 -0
  141. xfintech/data/source/tushare/stock/companybusiness/constant.py +91 -0
  142. xfintech/data/source/tushare/stock/companybusiness/tests/__init__.py +0 -0
  143. xfintech/data/source/tushare/stock/companybusiness/tests/test_class_companybusiness_all.py +633 -0
  144. xfintech/data/source/tushare/stock/companycashflow/__init__.py +21 -0
  145. xfintech/data/source/tushare/stock/companycashflow/companycashflow.py +277 -0
  146. xfintech/data/source/tushare/stock/companycashflow/constant.py +293 -0
  147. xfintech/data/source/tushare/stock/companycashflow/tests/__init__.py +0 -0
  148. xfintech/data/source/tushare/stock/companycashflow/tests/test_class_companycashflow_all.py +619 -0
  149. xfintech/data/source/tushare/stock/companydebt/__init__.py +19 -0
  150. xfintech/data/source/tushare/stock/companydebt/companydebt.py +339 -0
  151. xfintech/data/source/tushare/stock/companydebt/constant.py +403 -0
  152. xfintech/data/source/tushare/stock/companydebt/tests/__init__.py +0 -0
  153. xfintech/data/source/tushare/stock/companydebt/tests/test_class_companydebt_all.py +655 -0
  154. xfintech/data/source/tushare/stock/companyoverview/__init__.py +21 -0
  155. xfintech/data/source/tushare/stock/companyoverview/companyoverview.py +214 -0
  156. xfintech/data/source/tushare/stock/companyoverview/constant.py +152 -0
  157. xfintech/data/source/tushare/stock/companyoverview/tests/__init__.py +0 -0
  158. xfintech/data/source/tushare/stock/companyoverview/tests/test_class_companyoverview_all.py +647 -0
  159. xfintech/data/source/tushare/stock/companyprofit/__init__.py +21 -0
  160. xfintech/data/source/tushare/stock/companyprofit/companyprofit.py +272 -0
  161. xfintech/data/source/tushare/stock/companyprofit/constant.py +259 -0
  162. xfintech/data/source/tushare/stock/companyprofit/tests/__init__.py +0 -0
  163. xfintech/data/source/tushare/stock/companyprofit/tests/test_class_companyprofit_all.py +635 -0
  164. xfintech/data/source/tushare/stock/conceptcapflowdc/__init__.py +21 -0
  165. xfintech/data/source/tushare/stock/conceptcapflowdc/conceptcapflowdc.py +175 -0
  166. xfintech/data/source/tushare/stock/conceptcapflowdc/constant.py +106 -0
  167. xfintech/data/source/tushare/stock/conceptcapflowdc/tests/__init__.py +0 -0
  168. xfintech/data/source/tushare/stock/conceptcapflowdc/tests/test_class_conceptcapflowdc_all.py +568 -0
  169. xfintech/data/source/tushare/stock/conceptcapflowths/__init__.py +21 -0
  170. xfintech/data/source/tushare/stock/conceptcapflowths/conceptcapflowths.py +188 -0
  171. xfintech/data/source/tushare/stock/conceptcapflowths/constant.py +89 -0
  172. xfintech/data/source/tushare/stock/conceptcapflowths/tests/__init__.py +0 -0
  173. xfintech/data/source/tushare/stock/conceptcapflowths/tests/test_class_conceptcapflowths_all.py +516 -0
  174. xfintech/data/source/tushare/stock/dayline/__init__.py +19 -0
  175. xfintech/data/source/tushare/stock/dayline/constant.py +87 -0
  176. xfintech/data/source/tushare/stock/dayline/dayline.py +177 -0
  177. xfintech/data/source/tushare/stock/dayline/tests/__init__.py +0 -0
  178. xfintech/data/source/tushare/stock/dayline/tests/test_class_dayline_all.py +585 -0
  179. xfintech/data/source/tushare/stock/industrycapflowths/__init__.py +21 -0
  180. xfintech/data/source/tushare/stock/industrycapflowths/constant.py +89 -0
  181. xfintech/data/source/tushare/stock/industrycapflowths/industrycapflowths.py +192 -0
  182. xfintech/data/source/tushare/stock/industrycapflowths/tests/__init__.py +0 -0
  183. xfintech/data/source/tushare/stock/industrycapflowths/tests/test_class_industrycapflowths_all.py +683 -0
  184. xfintech/data/source/tushare/stock/marketindexcapflowdc/__init__.py +21 -0
  185. xfintech/data/source/tushare/stock/marketindexcapflowdc/constant.py +90 -0
  186. xfintech/data/source/tushare/stock/marketindexcapflowdc/marketindexcapflowdc.py +173 -0
  187. xfintech/data/source/tushare/stock/marketindexcapflowdc/tests/__init__.py +0 -0
  188. xfintech/data/source/tushare/stock/marketindexcapflowdc/tests/test_class_marketindexcapflowdc_all.py +793 -0
  189. xfintech/data/source/tushare/stock/monthline/__init__.py +19 -0
  190. xfintech/data/source/tushare/stock/monthline/constant.py +87 -0
  191. xfintech/data/source/tushare/stock/monthline/monthline.py +180 -0
  192. xfintech/data/source/tushare/stock/monthline/tests/__init__.py +0 -0
  193. xfintech/data/source/tushare/stock/monthline/tests/test_class_monthline_all.py +574 -0
  194. xfintech/data/source/tushare/stock/stock/__init__.py +19 -0
  195. xfintech/data/source/tushare/stock/stock/constant.py +105 -0
  196. xfintech/data/source/tushare/stock/stock/stock.py +193 -0
  197. xfintech/data/source/tushare/stock/stock/tests/__init__.py +0 -0
  198. xfintech/data/source/tushare/stock/stock/tests/test_class_stock_all.py +788 -0
  199. xfintech/data/source/tushare/stock/stockdividend/__init__.py +21 -0
  200. xfintech/data/source/tushare/stock/stockdividend/constant.py +111 -0
  201. xfintech/data/source/tushare/stock/stockdividend/stockdividend.py +180 -0
  202. xfintech/data/source/tushare/stock/stockdividend/tests/__init__.py +0 -0
  203. xfintech/data/source/tushare/stock/stockdividend/tests/test_class_stockdividend_all.py +725 -0
  204. xfintech/data/source/tushare/stock/stockinfo/__init__.py +19 -0
  205. xfintech/data/source/tushare/stock/stockinfo/constant.py +104 -0
  206. xfintech/data/source/tushare/stock/stockinfo/stockinfo.py +208 -0
  207. xfintech/data/source/tushare/stock/stockinfo/tests/__init__.py +0 -0
  208. xfintech/data/source/tushare/stock/stockinfo/tests/test_class_stockinfo_all.py +881 -0
  209. xfintech/data/source/tushare/stock/stockipo/__init__.py +19 -0
  210. xfintech/data/source/tushare/stock/stockipo/constant.py +90 -0
  211. xfintech/data/source/tushare/stock/stockipo/stockipo.py +234 -0
  212. xfintech/data/source/tushare/stock/stockipo/tests/__init__.py +1 -0
  213. xfintech/data/source/tushare/stock/stockipo/tests/test_class_stockipo_all.py +750 -0
  214. xfintech/data/source/tushare/stock/stockpledge/__init__.py +19 -0
  215. xfintech/data/source/tushare/stock/stockpledge/constant.py +72 -0
  216. xfintech/data/source/tushare/stock/stockpledge/stockpledge.py +158 -0
  217. xfintech/data/source/tushare/stock/stockpledge/tests/__init__.py +0 -0
  218. xfintech/data/source/tushare/stock/stockpledge/tests/test_class_stockpledge_all.py +664 -0
  219. xfintech/data/source/tushare/stock/stockpledgedetail/__init__.py +21 -0
  220. xfintech/data/source/tushare/stock/stockpledgedetail/constant.py +85 -0
  221. xfintech/data/source/tushare/stock/stockpledgedetail/stockpledgedetail.py +171 -0
  222. xfintech/data/source/tushare/stock/stockpledgedetail/tests/__init__.py +0 -0
  223. xfintech/data/source/tushare/stock/stockpledgedetail/tests/test_class_stockpledgedetail_all.py +112 -0
  224. xfintech/data/source/tushare/stock/stockst/__init__.py +19 -0
  225. xfintech/data/source/tushare/stock/stockst/constant.py +80 -0
  226. xfintech/data/source/tushare/stock/stockst/stockst.py +189 -0
  227. xfintech/data/source/tushare/stock/stockst/tests/__init__.py +0 -0
  228. xfintech/data/source/tushare/stock/stockst/tests/test_class_stockst_all.py +693 -0
  229. xfintech/data/source/tushare/stock/stocksuspend/__init__.py +21 -0
  230. xfintech/data/source/tushare/stock/stocksuspend/constant.py +75 -0
  231. xfintech/data/source/tushare/stock/stocksuspend/stocksuspend.py +151 -0
  232. xfintech/data/source/tushare/stock/stocksuspend/tests/__init__.py +0 -0
  233. xfintech/data/source/tushare/stock/stocksuspend/tests/test_class_stocksuspend_all.py +626 -0
  234. xfintech/data/source/tushare/stock/techindex/__init__.py +19 -0
  235. xfintech/data/source/tushare/stock/techindex/constant.py +600 -0
  236. xfintech/data/source/tushare/stock/techindex/techindex.py +314 -0
  237. xfintech/data/source/tushare/stock/techindex/tests/__init__.py +0 -0
  238. xfintech/data/source/tushare/stock/techindex/tests/test_class_techindex_all.py +576 -0
  239. xfintech/data/source/tushare/stock/tradedate/__init__.py +19 -0
  240. xfintech/data/source/tushare/stock/tradedate/constant.py +93 -0
  241. xfintech/data/source/tushare/stock/tradedate/tests/__init__.py +0 -0
  242. xfintech/data/source/tushare/stock/tradedate/tests/test_class_tradedate_all.py +947 -0
  243. xfintech/data/source/tushare/stock/tradedate/tradedate.py +234 -0
  244. xfintech/data/source/tushare/stock/weekline/__init__.py +19 -0
  245. xfintech/data/source/tushare/stock/weekline/constant.py +87 -0
  246. xfintech/data/source/tushare/stock/weekline/tests/__init__.py +0 -0
  247. xfintech/data/source/tushare/stock/weekline/tests/test_class_weekline_all.py +575 -0
  248. xfintech/data/source/tushare/stock/weekline/weekline.py +182 -0
  249. xfintech/fabric/__init__.py +18 -0
  250. xfintech/fabric/column/__init__.py +7 -0
  251. xfintech/fabric/column/info.py +202 -0
  252. xfintech/fabric/column/kind.py +102 -0
  253. xfintech/fabric/column/tests/__init__.py +0 -0
  254. xfintech/fabric/column/tests/test_class_info_all.py +207 -0
  255. xfintech/fabric/column/tests/test_class_kind_all.py +80 -0
  256. xfintech/fabric/table/__init__.py +5 -0
  257. xfintech/fabric/table/info.py +263 -0
  258. xfintech/fabric/table/tests/__init__.py +0 -0
  259. xfintech/fabric/table/tests/test_class_info_all.py +547 -0
  260. xfintech/serde/__init__.py +35 -0
  261. xfintech/serde/common/__init__.py +9 -0
  262. xfintech/serde/common/dataformat.py +78 -0
  263. xfintech/serde/common/deserialiserlike.py +38 -0
  264. xfintech/serde/common/error.py +182 -0
  265. xfintech/serde/common/serialiserlike.py +38 -0
  266. xfintech/serde/common/tests/__init__.py +1 -0
  267. xfintech/serde/common/tests/test_class_dataformat_all.py +694 -0
  268. xfintech/serde/common/tests/test_class_deserialiserlike_all.py +500 -0
  269. xfintech/serde/common/tests/test_class_errors_all.py +518 -0
  270. xfintech/serde/common/tests/test_class_serialiserlike_all.py +401 -0
  271. xfintech/serde/deserialiser/__init__.py +7 -0
  272. xfintech/serde/deserialiser/pandas.py +113 -0
  273. xfintech/serde/deserialiser/python.py +68 -0
  274. xfintech/serde/deserialiser/tests/__init__.py +1 -0
  275. xfintech/serde/deserialiser/tests/test_class_pandasdeserialiser_all.py +503 -0
  276. xfintech/serde/deserialiser/tests/test_class_pythondeserialiser_all.py +570 -0
  277. xfintech/serde/serialiser/__init__.py +7 -0
  278. xfintech/serde/serialiser/pandas.py +116 -0
  279. xfintech/serde/serialiser/python.py +71 -0
  280. xfintech/serde/serialiser/tests/__init__.py +1 -0
  281. xfintech/serde/serialiser/tests/test_class_pandasserialiser_all.py +474 -0
  282. xfintech/serde/serialiser/tests/test_class_pythonserialiser_all.py +508 -0
@@ -0,0 +1,576 @@
1
+ from __future__ import annotations
2
+
3
+ from datetime import date, datetime
4
+ from unittest.mock import MagicMock, patch
5
+
6
+ import pandas as pd
7
+ import pytest
8
+
9
+ from xfintech.data.source.tushare.stock.techindex import (
10
+ KEY,
11
+ NAME,
12
+ PAGINATE,
13
+ SOURCE,
14
+ TARGET,
15
+ TechIndex,
16
+ )
17
+ from xfintech.data.source.tushare.stock.techindex.constant import (
18
+ _IN_BFQ_COLS,
19
+ _IN_HFQ_COLS,
20
+ _IN_MAIN_COLS,
21
+ _IN_QFQ_COLS,
22
+ _OUT_BA_COLS,
23
+ _OUT_FA_COLS,
24
+ _OUT_MAIN_COLS,
25
+ _OUT_NA_COLS,
26
+ )
27
+
28
+
29
+ # ================= Fixtures =================
30
+ @pytest.fixture
31
+ def mock_session():
32
+ """创建模拟的Tushare会话对象"""
33
+ session = MagicMock()
34
+
35
+ # Mock the connection object
36
+ mock_connection = MagicMock()
37
+ mock_connection.stk_factor_pro = MagicMock()
38
+ session.connection = mock_connection
39
+
40
+ return session
41
+
42
+
43
+ @pytest.fixture
44
+ def sample_tushare_data():
45
+ """创建样本Tushare格式数据"""
46
+ return pd.DataFrame(
47
+ {
48
+ "ts_code": ["000001.SZ", "000002.SZ"],
49
+ "trade_date": ["20240101", "20240101"],
50
+ "open": [10.5, 20.3],
51
+ "high": [11.0, 21.0],
52
+ "low": [10.2, 20.0],
53
+ "close": [10.8, 20.8],
54
+ "change": [0.3, 0.5],
55
+ "pct_chg": [2.86, 2.46],
56
+ "vol": [100000.0, 200000.0],
57
+ "amount": [108000.0, 416000.0],
58
+ "turnover_rate": [1.5, 2.3],
59
+ "turnover_rate_f": [1.2, 2.0],
60
+ "volume_ratio": [1.1, 1.3],
61
+ "pe": [15.5, 18.2],
62
+ "pe_ttm": [16.0, 18.5],
63
+ "pb": [2.5, 3.2],
64
+ "ps": [3.5, 4.2],
65
+ "ps_ttm": [3.8, 4.5],
66
+ "dv_ratio": [2.5, 3.0],
67
+ "dv_ttm": [2.8, 3.2],
68
+ "total_share": [1000000.0, 2000000.0],
69
+ "float_share": [800000.0, 1600000.0],
70
+ "free_share": [700000.0, 1400000.0],
71
+ "total_mv": [10800000.0, 41600000.0],
72
+ "circ_mv": [8640000.0, 33280000.0],
73
+ "adj_factor": [1.0, 1.0],
74
+ "downdays": [0.0, 1.0],
75
+ "updays": [3.0, 2.0],
76
+ "lowdays": [5.0, 10.0],
77
+ "topdays": [15.0, 20.0],
78
+ # BFQ columns
79
+ "macd_bfq": [0.05, 0.08],
80
+ "macd_dif_bfq": [0.03, 0.05],
81
+ "macd_dea_bfq": [0.02, 0.03],
82
+ # HFQ columns
83
+ "macd_hfq": [0.06, 0.09],
84
+ "macd_dif_hfq": [0.04, 0.06],
85
+ "macd_dea_hfq": [0.02, 0.03],
86
+ # QFQ columns
87
+ "macd_qfq": [0.055, 0.085],
88
+ "macd_dif_qfq": [0.035, 0.055],
89
+ "macd_dea_qfq": [0.02, 0.03],
90
+ }
91
+ )
92
+
93
+
94
+ @pytest.fixture
95
+ def sample_transformed_data():
96
+ """创建样本转换后数据"""
97
+ return pd.DataFrame(
98
+ {
99
+ "code": ["000001.SZ", "000002.SZ"],
100
+ "date": ["2024-01-01", "2024-01-01"],
101
+ "datecode": ["20240101", "20240101"],
102
+ "open": [10.5, 20.3],
103
+ "high": [11.0, 21.0],
104
+ "low": [10.2, 20.0],
105
+ "close": [10.8, 20.8],
106
+ "change": [0.3, 0.5],
107
+ "percent_change": [2.86, 2.46],
108
+ "volume": [100000.0, 200000.0],
109
+ "amount": [108000.0, 416000.0],
110
+ }
111
+ )
112
+
113
+
114
+ # ================= 初始化测试 =================
115
+ class TestTechIndexInitialization:
116
+ """测试TechIndex类的初始化"""
117
+
118
+ def test_init_with_minimal_params(self, mock_session):
119
+ """测试使用最少参数初始化"""
120
+ job = TechIndex(session=mock_session)
121
+ assert job.name == NAME
122
+ assert job.key == KEY
123
+ assert job.source == SOURCE
124
+ assert job.target == TARGET
125
+
126
+ def test_init_with_params_dict(self, mock_session):
127
+ """测试使用字典参数初始化"""
128
+ params = {"ts_code": "000001.SZ"}
129
+ job = TechIndex(session=mock_session, params=params)
130
+ assert job.params.get("ts_code") == "000001.SZ"
131
+
132
+ def test_init_with_date_params(self, mock_session):
133
+ """测试使用日期参数初始化"""
134
+ params = {
135
+ "ts_code": "000001.SZ",
136
+ "start_date": "20240101",
137
+ "end_date": "20240131",
138
+ }
139
+ job = TechIndex(session=mock_session, params=params)
140
+ assert job.params.get("start_date") == "20240101"
141
+ assert job.params.get("end_date") == "20240131"
142
+
143
+ def test_init_with_cache_enabled(self, mock_session):
144
+ """测试启用缓存初始化"""
145
+ job = TechIndex(session=mock_session, cache=True)
146
+ assert job.cache is not None
147
+
148
+ def test_init_with_cache_disabled(self, mock_session):
149
+ """测试禁用缓存初始化"""
150
+ job = TechIndex(session=mock_session, cache=False)
151
+ assert job.cache is None
152
+
153
+ def test_paginate_settings(self, mock_session):
154
+ """测试分页设置"""
155
+ job = TechIndex(session=mock_session)
156
+ assert job.paginate.pagesize == PAGINATE.pagesize
157
+ assert job.paginate.pagelimit == PAGINATE.pagelimit
158
+
159
+
160
+ # ================= 转换测试 =================
161
+ class TestTechIndexTransform:
162
+ """测试TechIndex的数据转换功能"""
163
+
164
+ def test_transform_main_with_valid_data(self, mock_session, sample_tushare_data):
165
+ """测试主数据转换"""
166
+ job = TechIndex(session=mock_session)
167
+ result = job._transform_main(sample_tushare_data)
168
+
169
+ assert not result.empty
170
+ assert len(result) == 2
171
+ assert "code" in result.columns
172
+ assert "date" in result.columns
173
+ assert "datecode" in result.columns
174
+ assert result["code"].iloc[0] == "000001.SZ"
175
+ assert result["date"].iloc[0] == "2024-01-01"
176
+ assert result["datecode"].iloc[0] == "20240101"
177
+
178
+ def test_transform_main_with_empty_data(self, mock_session):
179
+ """测试空数据的主数据转换"""
180
+ job = TechIndex(session=mock_session)
181
+ result = job._transform_main(pd.DataFrame())
182
+
183
+ assert result.empty
184
+ assert len(result.columns) == len(_OUT_MAIN_COLS)
185
+
186
+ def test_transform_na_with_valid_data(self, mock_session, sample_tushare_data):
187
+ """测试不复权因子转换"""
188
+ job = TechIndex(session=mock_session)
189
+ result = job._transform_na(sample_tushare_data)
190
+
191
+ assert not result.empty
192
+ assert len(result) == 2
193
+ assert "open" in result.columns
194
+ assert "macd" in result.columns
195
+ assert result["macd"].iloc[0] == 0.05
196
+
197
+ def test_transform_na_with_empty_data(self, mock_session):
198
+ """测试空数据的不复权因子转换"""
199
+ job = TechIndex(session=mock_session)
200
+ result = job._transform_na(pd.DataFrame())
201
+
202
+ assert result.empty
203
+ assert len(result.columns) == len(_OUT_NA_COLS)
204
+
205
+ def test_transform_ba_with_valid_data(self, mock_session, sample_tushare_data):
206
+ """测试后复权因子转换"""
207
+ job = TechIndex(session=mock_session)
208
+ result = job._transform_ba(sample_tushare_data)
209
+
210
+ assert not result.empty
211
+ assert len(result) == 2
212
+ # BA transform adds ba_ prefix
213
+ assert "ba_macd" in result.columns
214
+ assert result["ba_macd"].iloc[0] == 0.06
215
+
216
+ def test_transform_ba_with_empty_data(self, mock_session):
217
+ """测试空数据的后复权因子转换"""
218
+ job = TechIndex(session=mock_session)
219
+ result = job._transform_ba(pd.DataFrame())
220
+
221
+ assert result.empty
222
+ assert len(result.columns) == len(_OUT_BA_COLS)
223
+
224
+ def test_transform_fa_with_valid_data(self, mock_session, sample_tushare_data):
225
+ """测试前复权因子转换"""
226
+ job = TechIndex(session=mock_session)
227
+ result = job._transform_fa(sample_tushare_data)
228
+
229
+ assert not result.empty
230
+ assert len(result) == 2
231
+ # FA transform adds fa_ prefix
232
+ assert "fa_macd" in result.columns
233
+ assert result["fa_macd"].iloc[0] == 0.055
234
+
235
+ def test_transform_fa_with_empty_data(self, mock_session):
236
+ """测试空数据的前复权因子转换"""
237
+ job = TechIndex(session=mock_session)
238
+ result = job._transform_fa(pd.DataFrame())
239
+
240
+ assert result.empty
241
+ assert len(result.columns) == len(_OUT_FA_COLS)
242
+
243
+ def test_transform_complete_with_valid_data(self, mock_session, sample_tushare_data):
244
+ """测试完整数据转换"""
245
+ job = TechIndex(session=mock_session)
246
+ result = job.transform(sample_tushare_data)
247
+
248
+ assert not result.empty
249
+ assert len(result) == 2
250
+ # Check all column groups are present
251
+ assert "code" in result.columns # main
252
+ assert "open" in result.columns # na
253
+ assert "ba_macd" in result.columns # ba (with prefix)
254
+ assert "fa_macd" in result.columns # fa (with prefix)
255
+ # Total columns should match target
256
+ assert len(result.columns) == len(TARGET.list_column_names())
257
+
258
+ def test_transform_complete_with_empty_data(self, mock_session):
259
+ """测试空数据的完整转换"""
260
+ job = TechIndex(session=mock_session)
261
+ result = job.transform(pd.DataFrame())
262
+
263
+ assert result.empty
264
+ assert len(result.columns) == len(TARGET.list_column_names())
265
+
266
+ def test_transform_preserves_column_order(self, mock_session, sample_tushare_data):
267
+ """测试转换保持列顺序"""
268
+ job = TechIndex(session=mock_session)
269
+ result = job.transform(sample_tushare_data)
270
+
271
+ expected_columns = TARGET.list_column_names()
272
+ assert list(result.columns) == expected_columns
273
+
274
+
275
+ # ================= Run方法测试 =================
276
+ class TestTechIndexRun:
277
+ """测试TechIndex的run方法"""
278
+
279
+ def test_run_with_ts_code(self, mock_session, sample_tushare_data):
280
+ """测试使用股票代码运行"""
281
+ job = TechIndex(session=mock_session, params={"ts_code": "000001.SZ"}, cache=False)
282
+
283
+ with patch.object(job, "_fetchall", return_value=sample_tushare_data):
284
+ result = job.run()
285
+ assert isinstance(result, pd.DataFrame)
286
+ assert not result.empty
287
+
288
+ def test_run_with_trade_date_string(self, mock_session, sample_tushare_data):
289
+ """测试使用字符串交易日期运行"""
290
+ job = TechIndex(session=mock_session, params={"trade_date": "20240101"}, cache=False)
291
+
292
+ with patch.object(job, "_fetchall", return_value=sample_tushare_data):
293
+ result = job.run()
294
+ assert isinstance(result, pd.DataFrame)
295
+
296
+ def test_run_with_trade_date_datetime(self, mock_session, sample_tushare_data):
297
+ """测试使用datetime交易日期运行"""
298
+ job = TechIndex(
299
+ session=mock_session,
300
+ params={"trade_date": datetime(2024, 1, 1)},
301
+ cache=False,
302
+ )
303
+
304
+ with patch.object(job, "_fetchall", return_value=sample_tushare_data):
305
+ result = job.run()
306
+ assert isinstance(result, pd.DataFrame)
307
+
308
+ def test_run_with_trade_date_date(self, mock_session, sample_tushare_data):
309
+ """测试使用date交易日期运行"""
310
+ job = TechIndex(session=mock_session, params={"trade_date": date(2024, 1, 1)}, cache=False)
311
+
312
+ with patch.object(job, "_fetchall", return_value=sample_tushare_data):
313
+ result = job.run()
314
+ assert isinstance(result, pd.DataFrame)
315
+
316
+ def test_run_with_date_range_string(self, mock_session, sample_tushare_data):
317
+ """测试使用字符串日期范围运行"""
318
+ job = TechIndex(
319
+ session=mock_session,
320
+ params={"start_date": "20240101", "end_date": "20240131"},
321
+ cache=False,
322
+ )
323
+
324
+ with patch.object(job, "_fetchall", return_value=sample_tushare_data):
325
+ result = job.run()
326
+ assert isinstance(result, pd.DataFrame)
327
+
328
+ def test_run_with_date_range_datetime(self, mock_session, sample_tushare_data):
329
+ """测试使用datetime日期范围运行"""
330
+ job = TechIndex(
331
+ session=mock_session,
332
+ params={
333
+ "start_date": datetime(2024, 1, 1),
334
+ "end_date": datetime(2024, 1, 31),
335
+ },
336
+ cache=False,
337
+ )
338
+
339
+ with patch.object(job, "_fetchall", return_value=sample_tushare_data):
340
+ result = job.run()
341
+ assert isinstance(result, pd.DataFrame)
342
+
343
+ def test_run_with_date_range_date(self, mock_session, sample_tushare_data):
344
+ """测试使用date日期范围运行"""
345
+ job = TechIndex(
346
+ session=mock_session,
347
+ params={"start_date": date(2024, 1, 1), "end_date": date(2024, 1, 31)},
348
+ cache=False,
349
+ )
350
+
351
+ with patch.object(job, "_fetchall", return_value=sample_tushare_data):
352
+ result = job.run()
353
+ assert isinstance(result, pd.DataFrame)
354
+
355
+ def test_run_with_mixed_date_formats(self, mock_session, sample_tushare_data):
356
+ """测试使用混合日期格式运行"""
357
+ job = TechIndex(
358
+ session=mock_session,
359
+ params={"start_date": date(2024, 1, 1), "end_date": "20240131"},
360
+ cache=False,
361
+ )
362
+
363
+ with patch.object(job, "_fetchall", return_value=sample_tushare_data):
364
+ result = job.run()
365
+ assert isinstance(result, pd.DataFrame)
366
+
367
+ def test_run_returns_dataframe(self, mock_session, sample_tushare_data):
368
+ """测试run方法返回DataFrame类型"""
369
+ job = TechIndex(session=mock_session, cache=False)
370
+
371
+ with patch.object(job, "_fetchall", return_value=sample_tushare_data):
372
+ result = job.run()
373
+ assert isinstance(result, pd.DataFrame)
374
+ assert len(result) > 0
375
+
376
+
377
+ # ================= 缓存测试 =================
378
+ class TestTechIndexCache:
379
+ """测试TechIndex的缓存功能"""
380
+
381
+ def test_cache_disabled_by_default(self, mock_session):
382
+ """测试默认不启用缓存"""
383
+ job = TechIndex(session=mock_session, cache=False)
384
+ assert job.cache is None
385
+
386
+ def test_cache_load_returns_none_when_disabled(self, mock_session):
387
+ """测试禁用缓存时_load_cache返回None"""
388
+ job = TechIndex(session=mock_session, cache=False)
389
+ result = job._load_cache()
390
+ assert result is None
391
+
392
+ def test_cache_save_does_nothing_when_disabled(self, mock_session, sample_transformed_data):
393
+ """测试禁用缓存时_save_cache不执行操作"""
394
+ job = TechIndex(session=mock_session, cache=False)
395
+ # Should not raise any errors
396
+ job._save_cache(sample_transformed_data)
397
+
398
+ def test_run_with_cache_enabled(self, mock_session, sample_tushare_data):
399
+ """测试启用缓存运行"""
400
+ job = TechIndex(
401
+ session=mock_session,
402
+ params={"ts_code": "000001.SZ"},
403
+ cache={"store": "memory"},
404
+ )
405
+
406
+ with (
407
+ patch.object(job, "_fetchall", return_value=sample_tushare_data),
408
+ patch.object(job, "_load_cache", return_value=None),
409
+ patch.object(job, "_save_cache") as mock_save,
410
+ ):
411
+ result = job.run()
412
+ assert isinstance(result, pd.DataFrame)
413
+ mock_save.assert_called_once()
414
+
415
+
416
+ # ================= Slice方法测试 =================
417
+ class TestTechIndexSlice:
418
+ """测试TechIndex的slice方法"""
419
+
420
+ def test_slice_main_without_data(self, mock_session, sample_tushare_data):
421
+ """测试slice_main方法不传入数据"""
422
+ job = TechIndex(session=mock_session, cache=False)
423
+
424
+ with patch.object(job, "_fetchall", return_value=sample_tushare_data):
425
+ result = job.slice_main()
426
+ assert isinstance(result, pd.DataFrame)
427
+ assert not result.empty
428
+ assert len(result.columns) == len(_OUT_MAIN_COLS)
429
+ assert "code" in result.columns
430
+ assert "date" in result.columns
431
+
432
+ def test_slice_main_with_data(self, mock_session, sample_tushare_data):
433
+ """测试slice_main方法传入数据"""
434
+ job = TechIndex(session=mock_session, cache=False)
435
+ full_data = job.transform(sample_tushare_data)
436
+ result = job.slice_main(data=full_data)
437
+
438
+ assert isinstance(result, pd.DataFrame)
439
+ assert not result.empty
440
+ assert len(result.columns) == len(_OUT_MAIN_COLS)
441
+
442
+ def test_slice_na_without_data(self, mock_session, sample_tushare_data):
443
+ """测试slice_na方法不传入数据"""
444
+ job = TechIndex(session=mock_session, cache=False)
445
+
446
+ with patch.object(job, "_fetchall", return_value=sample_tushare_data):
447
+ result = job.slice_na()
448
+ assert isinstance(result, pd.DataFrame)
449
+ assert not result.empty
450
+ assert len(result.columns) == len(_OUT_MAIN_COLS + _OUT_NA_COLS)
451
+ assert "open" in result.columns
452
+ assert "macd" in result.columns
453
+
454
+ def test_slice_na_with_data(self, mock_session, sample_tushare_data):
455
+ """测试slice_na方法传入数据"""
456
+ job = TechIndex(session=mock_session, cache=False)
457
+ full_data = job.transform(sample_tushare_data)
458
+ result = job.slice_na(data=full_data)
459
+
460
+ assert isinstance(result, pd.DataFrame)
461
+ assert not result.empty
462
+ assert len(result.columns) == len(_OUT_MAIN_COLS + _OUT_NA_COLS)
463
+
464
+ def test_slice_ba_without_data(self, mock_session, sample_tushare_data):
465
+ """测试slice_ba方法不传入数据"""
466
+ job = TechIndex(session=mock_session, cache=False)
467
+
468
+ with patch.object(job, "_fetchall", return_value=sample_tushare_data):
469
+ result = job.slice_ba()
470
+ assert isinstance(result, pd.DataFrame)
471
+ assert not result.empty
472
+ assert len(result.columns) == len(_OUT_MAIN_COLS + _OUT_BA_COLS)
473
+ assert "ba_macd" in result.columns
474
+
475
+ def test_slice_ba_with_data(self, mock_session, sample_tushare_data):
476
+ """测试slice_ba方法传入数据"""
477
+ job = TechIndex(session=mock_session, cache=False)
478
+ full_data = job.transform(sample_tushare_data)
479
+ result = job.slice_ba(data=full_data)
480
+
481
+ assert isinstance(result, pd.DataFrame)
482
+ assert not result.empty
483
+ assert len(result.columns) == len(_OUT_MAIN_COLS + _OUT_BA_COLS)
484
+
485
+ def test_slice_fa_without_data(self, mock_session, sample_tushare_data):
486
+ """测试slice_fa方法不传入数据"""
487
+ job = TechIndex(session=mock_session, cache=False)
488
+
489
+ with patch.object(job, "_fetchall", return_value=sample_tushare_data):
490
+ result = job.slice_fa()
491
+ assert isinstance(result, pd.DataFrame)
492
+ assert not result.empty
493
+ assert len(result.columns) == len(_OUT_MAIN_COLS + _OUT_FA_COLS)
494
+ assert "fa_macd" in result.columns
495
+
496
+ def test_slice_fa_with_data(self, mock_session, sample_tushare_data):
497
+ """测试slice_fa方法传入数据"""
498
+ job = TechIndex(session=mock_session, cache=False)
499
+ full_data = job.transform(sample_tushare_data)
500
+ result = job.slice_fa(data=full_data)
501
+
502
+ assert isinstance(result, pd.DataFrame)
503
+ assert not result.empty
504
+ assert len(result.columns) == len(_OUT_MAIN_COLS + _OUT_FA_COLS)
505
+
506
+ def test_slice_with_empty_data(self, mock_session):
507
+ """测试slice方法处理空数据"""
508
+ job = TechIndex(session=mock_session, cache=False)
509
+ empty_data = job.transform(pd.DataFrame())
510
+
511
+ result_main = job.slice_main(data=empty_data)
512
+ result_na = job.slice_na(data=empty_data)
513
+ result_ba = job.slice_ba(data=empty_data)
514
+ result_fa = job.slice_fa(data=empty_data)
515
+
516
+ assert result_main.empty
517
+ assert result_na.empty
518
+ assert result_ba.empty
519
+ assert result_fa.empty
520
+
521
+
522
+ # ================= 集成测试 =================
523
+ class TestTechIndexIntegration:
524
+ """TechIndex的集成测试"""
525
+
526
+ def test_complete_workflow(self, mock_session, sample_tushare_data):
527
+ """测试完整工作流程"""
528
+ job = TechIndex(
529
+ session=mock_session,
530
+ params={"ts_code": "000001.SZ", "start_date": "20240101", "end_date": "20240131"},
531
+ cache=False,
532
+ )
533
+
534
+ with patch.object(job, "_fetchall", return_value=sample_tushare_data):
535
+ # 运行并获取完整数据
536
+ full_result = job.run()
537
+ assert isinstance(full_result, pd.DataFrame)
538
+ assert not full_result.empty
539
+
540
+ # 获取各部分数据
541
+ main_result = job.slice_main(data=full_result)
542
+ na_result = job.slice_na(data=full_result)
543
+ ba_result = job.slice_ba(data=full_result)
544
+ fa_result = job.slice_fa(data=full_result)
545
+
546
+ # 验证各部分
547
+ assert not main_result.empty
548
+ assert not na_result.empty
549
+ assert not ba_result.empty
550
+ assert not fa_result.empty
551
+
552
+ # 验证行数一致
553
+ assert len(main_result) == len(na_result) == len(ba_result) == len(fa_result)
554
+
555
+ def test_module_constants(self):
556
+ """测试模块常量"""
557
+ assert NAME == "techindex"
558
+ assert KEY == "/tushare/techindex"
559
+ assert PAGINATE.pagesize == 10000
560
+ assert PAGINATE.pagelimit == 1000
561
+
562
+ def test_source_table_structure(self):
563
+ """测试源表结构"""
564
+ assert SOURCE.desc == "A股股票技术面因子数据(Tushare格式)"
565
+ assert SOURCE.meta["provider"] == "tushare"
566
+ assert SOURCE.meta["source"] == "stk_factor_pro"
567
+ total_cols = len(_IN_MAIN_COLS) + len(_IN_BFQ_COLS) + len(_IN_HFQ_COLS) + len(_IN_QFQ_COLS)
568
+ assert len(SOURCE.columns) == total_cols
569
+
570
+ def test_target_table_structure(self):
571
+ """测试目标表结构"""
572
+ assert TARGET.desc == "A股股票技术面因子数据(xfintech格式)"
573
+ assert TARGET.meta["key"] == KEY
574
+ assert TARGET.meta["name"] == NAME
575
+ total_cols = len(_OUT_MAIN_COLS) + len(_OUT_NA_COLS) + len(_OUT_BA_COLS) + len(_OUT_FA_COLS)
576
+ assert len(TARGET.columns) == total_cols
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+
3
+ from xfintech.data.source.tushare.stock.tradedate.constant import (
4
+ KEY,
5
+ NAME,
6
+ PAGINATE,
7
+ SOURCE,
8
+ TARGET,
9
+ )
10
+ from xfintech.data.source.tushare.stock.tradedate.tradedate import TradeDate
11
+
12
+ __all__ = [
13
+ "TradeDate",
14
+ "KEY",
15
+ "NAME",
16
+ "PAGINATE",
17
+ "SOURCE",
18
+ "TARGET",
19
+ ]
@@ -0,0 +1,93 @@
1
+ from __future__ import annotations
2
+
3
+ from xfintech.data.common.paginate import Paginate
4
+ from xfintech.fabric.column.info import ColumnInfo
5
+ from xfintech.fabric.column.kind import ColumnKind
6
+ from xfintech.fabric.table.info import TableInfo
7
+
8
+ PROVIDER = "tushare"
9
+ SOURCE_NAME = "trade_cal"
10
+ URL = "https://tushare.pro/document/2?doc_id=26"
11
+ EXCHANGES = [
12
+ "SSE",
13
+ "SZSE",
14
+ "CFFEX",
15
+ "SHFE",
16
+ "CZCE",
17
+ "DCE",
18
+ "INE",
19
+ ]
20
+ ARGS = {
21
+ "exchange": {
22
+ "type": ColumnKind.STRING,
23
+ "required": "N",
24
+ "desc": f"交易所: {EXCHANGES}",
25
+ },
26
+ "start_date": {
27
+ "type": ColumnKind.STRING,
28
+ "required": "N",
29
+ "desc": "开始日期: YYYYMMDD",
30
+ },
31
+ "end_date": {
32
+ "type": ColumnKind.STRING,
33
+ "required": "N",
34
+ "desc": "结束日期: YYYYMMDD",
35
+ },
36
+ "is_open": {
37
+ "type": ColumnKind.STRING,
38
+ "required": "N",
39
+ "desc": "是否交易: 0=休市, 1=交易",
40
+ },
41
+ "year": {
42
+ "type": ColumnKind.STRING,
43
+ "required": "N",
44
+ "desc": "年份(YYYY)",
45
+ },
46
+ }
47
+
48
+ # Exported constants
49
+ NAME = "tradedate"
50
+ KEY = "/tushare/tradedate"
51
+ PAGINATE = Paginate(
52
+ pagesize=1000,
53
+ pagelimit=1000,
54
+ )
55
+ SOURCE = TableInfo(
56
+ desc="交易日历数据,包括交易所的交易日期和非交易日期",
57
+ meta={
58
+ "provider": PROVIDER,
59
+ "source": SOURCE_NAME,
60
+ "url": URL,
61
+ "args": ARGS,
62
+ "type": "static",
63
+ "scale": "crosssection",
64
+ },
65
+ columns=[
66
+ ColumnInfo(name="exchange", kind=ColumnKind.STRING, desc="交易所"),
67
+ ColumnInfo(name="cal_date", kind=ColumnKind.STRING, desc="日历日期"),
68
+ ColumnInfo(name="is_open", kind=ColumnKind.INTEGER, desc="是否交易"),
69
+ ColumnInfo(name="pretrade_date", kind=ColumnKind.STRING, desc="上一个交易日"),
70
+ ],
71
+ )
72
+ TARGET = TableInfo(
73
+ desc="交易日历数据,包括日期信息和交易状态",
74
+ meta={
75
+ "key": KEY,
76
+ "name": NAME,
77
+ "type": "static",
78
+ "scale": "crosssection",
79
+ },
80
+ columns=[
81
+ ColumnInfo(name="datecode", kind=ColumnKind.STRING, desc="日期代码:YYYYMMDD"),
82
+ ColumnInfo(name="date", kind=ColumnKind.STRING, desc="日期:YYYY-MM-DD"),
83
+ ColumnInfo(name="exchange", kind=ColumnKind.STRING, desc="交易所"),
84
+ ColumnInfo(name="previous", kind=ColumnKind.STRING, desc="前一个交易日"),
85
+ ColumnInfo(name="is_open", kind=ColumnKind.BOOLEAN, desc="是否交易日"),
86
+ ColumnInfo(name="year", kind=ColumnKind.INTEGER, desc="年份"),
87
+ ColumnInfo(name="month", kind=ColumnKind.INTEGER, desc="月份"),
88
+ ColumnInfo(name="day", kind=ColumnKind.INTEGER, desc="日"),
89
+ ColumnInfo(name="week", kind=ColumnKind.INTEGER, desc="周数"),
90
+ ColumnInfo(name="weekday", kind=ColumnKind.STRING, desc="星期几"),
91
+ ColumnInfo(name="quarter", kind=ColumnKind.INTEGER, desc="季度"),
92
+ ],
93
+ )