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,516 @@
1
+ from unittest.mock import MagicMock, patch
2
+
3
+ import pandas as pd
4
+ import pytest
5
+
6
+ from xfintech.data.common.cache import Cache
7
+ from xfintech.data.common.coolant import Coolant
8
+ from xfintech.data.common.retry import Retry
9
+ from xfintech.data.source.tushare.session.session import Session
10
+ from xfintech.data.source.tushare.stock.conceptcapflowths.conceptcapflowths import (
11
+ ConceptCapflowTHS,
12
+ )
13
+ from xfintech.data.source.tushare.stock.conceptcapflowths.constant import (
14
+ KEY,
15
+ NAME,
16
+ SOURCE,
17
+ TARGET,
18
+ )
19
+
20
+ # ============================================================================
21
+ # Fixtures
22
+ # ============================================================================
23
+
24
+
25
+ @pytest.fixture
26
+ def mock_session():
27
+ """Create a mock Tushare session"""
28
+ session = MagicMock(spec=Session)
29
+ session._credential = "test_token"
30
+ session.id = "test1234"
31
+ session.mode = "direct"
32
+ session.relay_url = None
33
+ session.relay_secret = None
34
+ session.connected = True
35
+
36
+ # Mock the connection object
37
+ mock_connection = MagicMock()
38
+ mock_connection.moneyflow_cnt_ths = MagicMock()
39
+ session.connection = mock_connection
40
+
41
+ return session
42
+
43
+
44
+ @pytest.fixture
45
+ def sample_source_data():
46
+ """Create sample source data in Tushare format"""
47
+ return pd.DataFrame(
48
+ {
49
+ "trade_date": ["20241201", "20241201", "20241129"],
50
+ "ts_code": ["885748.TI", "886008.TI", "885426.TI"],
51
+ "name": ["可燃冰", "减速器", "海工装备"],
52
+ "lead_stock": ["海默科技", "大叶股份", "天海防务"],
53
+ "close_price": [7.99, 21.22, 6.97],
54
+ "pct_change": [4.76, 2.60, 2.56],
55
+ "industry_index": [1307.56, 1862.58, 2711.31],
56
+ "company_num": [12, 103, 85],
57
+ "pct_change_stock": [4.76, 2.60, 2.56],
58
+ "net_buy_amount": [21.00, 227.00, 171.00],
59
+ "net_sell_amount": [19.00, 235.00, 148.00],
60
+ "net_amount": [1.00, -8.00, 23.00],
61
+ }
62
+ )
63
+
64
+
65
+ # ============================================================================
66
+ # Initialization Tests
67
+ # ============================================================================
68
+
69
+
70
+ class TestInitialization:
71
+ """Test initialization and configuration"""
72
+
73
+ def test_init_basic(self, mock_session):
74
+ """Test basic initialization"""
75
+ job = ConceptCapflowTHS(session=mock_session)
76
+
77
+ assert job.name == NAME
78
+ assert job.key == KEY
79
+ assert job.source == SOURCE
80
+ assert job.target == TARGET
81
+ assert job.paginate.pagesize == 5000
82
+
83
+ def test_init_with_params(self, mock_session):
84
+ """Test initialization with params"""
85
+ params = {"ts_code": "885748.TI", "start_date": "20240101"}
86
+ job = ConceptCapflowTHS(session=mock_session, params=params)
87
+
88
+ assert job.params.ts_code == "885748.TI"
89
+ assert job.params.start_date == "20240101"
90
+
91
+ def test_init_with_all_components(self, mock_session):
92
+ """Test initialization with all components"""
93
+ params = {"ts_code": "885748.TI"}
94
+ coolant = Coolant(interval=0.2)
95
+ retry = Retry(retry=3)
96
+ cache = Cache(path="/tmp/test_cache")
97
+
98
+ job = ConceptCapflowTHS(
99
+ session=mock_session,
100
+ params=params,
101
+ coolant=coolant,
102
+ retry=retry,
103
+ cache=cache,
104
+ )
105
+
106
+ assert job.params.ts_code == "885748.TI"
107
+ assert job.coolant.interval == 0.2
108
+ assert job.retry.retry == 3
109
+ assert job.cache is not None
110
+ assert isinstance(job.cache, Cache)
111
+
112
+ def test_name_constant(self):
113
+ """Test name constant"""
114
+ assert NAME == "conceptcapflowths"
115
+
116
+ def test_key_constant(self):
117
+ """Test key constant"""
118
+ assert KEY == "/tushare/conceptcapflowths"
119
+
120
+ def test_source_schema(self):
121
+ """Test source schema has all required columns"""
122
+ assert SOURCE is not None
123
+ assert SOURCE.desc == "同花顺概念板块资金流向数据(Tushare格式)"
124
+
125
+ column_names = SOURCE.columns
126
+ assert "ts_code" in column_names
127
+ assert "trade_date" in column_names
128
+ assert "name" in column_names
129
+ assert "lead_stock" in column_names
130
+ assert "close_price" in column_names
131
+ assert "pct_change" in column_names
132
+ assert "net_buy_amount" in column_names
133
+ assert "net_sell_amount" in column_names
134
+ assert "net_amount" in column_names
135
+
136
+ def test_target_schema(self):
137
+ """Test target schema has all required columns"""
138
+ assert TARGET is not None
139
+ assert TARGET.desc == "同花顺概念板块资金流向数据(xfintech标准格式)"
140
+
141
+ column_names = TARGET.columns
142
+ assert "code" in column_names
143
+ assert "date" in column_names
144
+ assert "datecode" in column_names
145
+ assert "name" in column_names
146
+ assert "lead_stock" in column_names
147
+ assert "close" in column_names
148
+ assert "percent_change" in column_names
149
+ assert "net_buy_amount" in column_names
150
+ assert "net_sell_amount" in column_names
151
+ assert "net_amount" in column_names
152
+
153
+
154
+ # ============================================================================
155
+ # Transform Tests
156
+ # ============================================================================
157
+
158
+
159
+ class TestTransform:
160
+ """Test data transformation"""
161
+
162
+ def test_transform_basic(self, mock_session, sample_source_data):
163
+ """Test basic data transformation"""
164
+ job = ConceptCapflowTHS(session=mock_session)
165
+ result = job.transform(sample_source_data)
166
+
167
+ assert len(result) == 3
168
+ assert "code" in result.columns
169
+ assert "date" in result.columns
170
+ assert "datecode" in result.columns
171
+ # Data is sorted by code, so first row is 885426.TI
172
+ assert result.iloc[0]["code"] == "885426.TI"
173
+ assert result.iloc[2]["datecode"] == "20241201"
174
+
175
+ def test_transform_date_conversion(self, mock_session, sample_source_data):
176
+ """Test date field conversions"""
177
+ job = ConceptCapflowTHS(session=mock_session)
178
+ result = job.transform(sample_source_data)
179
+
180
+ # Check date format (YYYY-MM-DD) - sorted by code
181
+ assert result.iloc[0]["date"] == "2024-11-29" # 885426.TI
182
+ assert result.iloc[1]["date"] == "2024-12-01" # 885748.TI
183
+ assert result.iloc[2]["date"] == "2024-12-01" # 886008.TI
184
+
185
+ # Check datecode format (YYYYMMDD)
186
+ assert result.iloc[1]["datecode"] == "20241201"
187
+
188
+ def test_transform_field_mappings(self, mock_session, sample_source_data):
189
+ """Test field mapping transformations"""
190
+ job = ConceptCapflowTHS(session=mock_session)
191
+ result = job.transform(sample_source_data)
192
+
193
+ # Use second row (index 1) which is 885748.TI after sorting
194
+ row = result.iloc[1]
195
+ assert row["code"] == "885748.TI"
196
+ assert row["name"] == "可燃冰"
197
+ assert row["lead_stock"] == "海默科技"
198
+ assert row["close"] == 7.99
199
+ assert row["percent_change"] == 4.76
200
+
201
+ def test_transform_numeric_fields(self, mock_session, sample_source_data):
202
+ """Test numeric field transformations"""
203
+ job = ConceptCapflowTHS(session=mock_session)
204
+ result = job.transform(sample_source_data)
205
+
206
+ row = result.iloc[0]
207
+ # Check all numeric fields are properly converted
208
+ assert isinstance(row["close"], (int, float)) or pd.notna(row["close"])
209
+ assert isinstance(row["percent_change"], (int, float)) or pd.notna(row["percent_change"])
210
+ assert isinstance(row["industry_index"], (int, float)) or pd.notna(row["industry_index"])
211
+ # company_num should be numeric
212
+ assert pd.notna(row["company_num"])
213
+ assert isinstance(row["net_buy_amount"], (int, float)) or pd.notna(row["net_buy_amount"])
214
+ assert isinstance(row["net_sell_amount"], (int, float)) or pd.notna(row["net_sell_amount"])
215
+ assert isinstance(row["net_amount"], (int, float)) or pd.notna(row["net_amount"])
216
+
217
+ def test_transform_empty_data(self, mock_session):
218
+ """Test transform with empty data"""
219
+ job = ConceptCapflowTHS(session=mock_session)
220
+
221
+ # Test with None
222
+ result = job.transform(None)
223
+ assert result.empty
224
+ assert len(result.columns) == len(TARGET.columns)
225
+
226
+ # Test with empty DataFrame
227
+ empty_df = pd.DataFrame()
228
+ result = job.transform(empty_df)
229
+ assert result.empty
230
+ assert len(result.columns) == len(TARGET.columns)
231
+
232
+ def test_transform_none_data(self, mock_session):
233
+ """Test transform with None data"""
234
+ job = ConceptCapflowTHS(session=mock_session)
235
+ result = job.transform(None)
236
+
237
+ assert result.empty
238
+ assert list(result.columns) == TARGET.list_column_names()
239
+
240
+ def test_transform_invalid_data(self, mock_session):
241
+ """Test transform with invalid numeric values"""
242
+ data = pd.DataFrame(
243
+ {
244
+ "trade_date": ["20241201", "invalid_date"],
245
+ "ts_code": ["885748.TI", "886008.TI"],
246
+ "name": ["可燃冰", "减速器"],
247
+ "lead_stock": ["海默科技", "大叶股份"],
248
+ "close_price": [7.99, "invalid"],
249
+ "pct_change": [4.76, 2.60],
250
+ "industry_index": [1307.56, 1862.58],
251
+ "company_num": [12, 103],
252
+ "pct_change_stock": [4.76, 2.60],
253
+ "net_buy_amount": [21.00, 227.00],
254
+ "net_sell_amount": [19.00, 235.00],
255
+ "net_amount": [1.00, -8.00],
256
+ }
257
+ )
258
+ job = ConceptCapflowTHS(session=mock_session)
259
+ result = job.transform(data)
260
+
261
+ # Should handle invalid data gracefully
262
+ assert len(result) == 2
263
+ assert pd.isna(result.iloc[1]["date"]) # Invalid date
264
+ assert pd.isna(result.iloc[1]["close"]) # Invalid numeric
265
+
266
+ def test_transform_duplicates_removed(self, mock_session):
267
+ """Test that duplicates are removed"""
268
+ data = pd.DataFrame(
269
+ {
270
+ "trade_date": ["20241201", "20241201", "20241201"],
271
+ "ts_code": ["885748.TI", "885748.TI", "886008.TI"],
272
+ "name": ["可燃冰", "可燃冰", "减速器"],
273
+ "lead_stock": ["海默科技", "海默科技", "大叶股份"],
274
+ "close_price": [7.99, 7.99, 21.22],
275
+ "pct_change": [4.76, 4.76, 2.60],
276
+ "industry_index": [1307.56, 1307.56, 1862.58],
277
+ "company_num": [12, 12, 103],
278
+ "pct_change_stock": [4.76, 4.76, 2.60],
279
+ "net_buy_amount": [21.00, 21.00, 227.00],
280
+ "net_sell_amount": [19.00, 19.00, 235.00],
281
+ "net_amount": [1.00, 1.00, -8.00],
282
+ }
283
+ )
284
+ job = ConceptCapflowTHS(session=mock_session)
285
+ result = job.transform(data)
286
+
287
+ # Duplicates should be removed
288
+ assert len(result) == 2
289
+
290
+ def test_transform_sorting(self, mock_session):
291
+ """Test that result is sorted by code and date"""
292
+ data = pd.DataFrame(
293
+ {
294
+ "trade_date": ["20241115", "20241201", "20241129"],
295
+ "ts_code": ["885426.TI", "885748.TI", "886008.TI"],
296
+ "name": ["海工装备", "可燃冰", "减速器"],
297
+ "lead_stock": ["天海防务", "海默科技", "大叶股份"],
298
+ "close_price": [6.97, 7.99, 21.22],
299
+ "pct_change": [2.56, 4.76, 2.60],
300
+ "industry_index": [2711.31, 1307.56, 1862.58],
301
+ "company_num": [85, 12, 103],
302
+ "pct_change_stock": [2.56, 4.76, 2.60],
303
+ "net_buy_amount": [171.00, 21.00, 227.00],
304
+ "net_sell_amount": [148.00, 19.00, 235.00],
305
+ "net_amount": [23.00, 1.00, -8.00],
306
+ }
307
+ )
308
+ job = ConceptCapflowTHS(session=mock_session)
309
+ result = job.transform(data)
310
+
311
+ # Should be sorted by code, then date
312
+ expected_order = ["885426.TI", "885748.TI", "886008.TI"]
313
+ actual_order = result["code"].tolist()
314
+ assert actual_order == expected_order
315
+
316
+
317
+ # ============================================================================
318
+ # Run Tests
319
+ # ============================================================================
320
+
321
+
322
+ class TestRun:
323
+ """Test execution logic"""
324
+
325
+ def test_run_basic(self, mock_session, sample_source_data):
326
+ """Test basic run method"""
327
+ job = ConceptCapflowTHS(session=mock_session)
328
+
329
+ with patch.object(job, "_fetchall", return_value=sample_source_data):
330
+ result = job.run()
331
+
332
+ assert isinstance(result, pd.DataFrame)
333
+ assert len(result) == 3
334
+ assert "code" in result.columns
335
+ assert "date" in result.columns
336
+
337
+ def test_run_with_params(self, mock_session, sample_source_data):
338
+ """Test run with ts_code parameter"""
339
+ filtered_data = sample_source_data[sample_source_data["ts_code"] == "885748.TI"]
340
+
341
+ job = ConceptCapflowTHS(session=mock_session, params={"ts_code": "885748.TI"})
342
+
343
+ with patch.object(job, "_fetchall", return_value=filtered_data):
344
+ result = job.run()
345
+
346
+ assert len(result) == 1
347
+ assert result["code"].iloc[0] == "885748.TI"
348
+
349
+ def test_run_with_date_string(self, mock_session, sample_source_data):
350
+ """Test run with trade_date as string"""
351
+ job = ConceptCapflowTHS(session=mock_session, params={"trade_date": "20241201"})
352
+
353
+ with patch.object(job, "_fetchall", return_value=sample_source_data) as mock_fetchall:
354
+ job.run()
355
+
356
+ call_kwargs = mock_fetchall.call_args[1]
357
+ assert call_kwargs["trade_date"] == "20241201"
358
+
359
+ def test_run_with_date_range_string(self, mock_session, sample_source_data):
360
+ """Test run with start_date and end_date as strings"""
361
+ job = ConceptCapflowTHS(
362
+ session=mock_session,
363
+ params={"start_date": "20241101", "end_date": "20241231"},
364
+ )
365
+
366
+ with patch.object(job, "_fetchall", return_value=sample_source_data) as mock_fetchall:
367
+ job.run()
368
+
369
+ call_kwargs = mock_fetchall.call_args[1]
370
+ assert call_kwargs["start_date"] == "20241101"
371
+ assert call_kwargs["end_date"] == "20241231"
372
+
373
+ def test_run_calls_transform(self, mock_session, sample_source_data):
374
+ """Test that run calls transform"""
375
+ job = ConceptCapflowTHS(session=mock_session)
376
+
377
+ with patch.object(job, "_fetchall", return_value=sample_source_data):
378
+ with patch.object(job, "transform", wraps=job.transform) as mock_transform:
379
+ job.run()
380
+
381
+ mock_transform.assert_called_once()
382
+
383
+ def test_run_with_multiple_ts_codes(self, mock_session, sample_source_data):
384
+ """Test run with multiple ts_code parameter"""
385
+ job = ConceptCapflowTHS(session=mock_session, params={"ts_code": "885748.TI,886008.TI"})
386
+
387
+ with patch.object(job, "_fetchall", return_value=sample_source_data) as mock_fetchall:
388
+ job.run()
389
+ call_kwargs = mock_fetchall.call_args[1]
390
+ assert call_kwargs["ts_code"] == "885748.TI,886008.TI"
391
+
392
+
393
+ # ============================================================================
394
+ # Cache Tests
395
+ # ============================================================================
396
+
397
+
398
+ class TestCache:
399
+ """Test caching behavior"""
400
+
401
+ def test_cache_persistence(self, mock_session, sample_source_data):
402
+ """Test that cache persists across runs"""
403
+ job = ConceptCapflowTHS(session=mock_session, cache=True)
404
+
405
+ with patch.object(job, "_load_cache", return_value=None) as mock_load:
406
+ with patch.object(job, "_fetchall", return_value=sample_source_data) as mock_fetchall:
407
+ # First run - fetches data and caches it
408
+ result1 = job.run()
409
+ assert mock_fetchall.call_count == 1
410
+ assert mock_load.call_count == 1
411
+
412
+ # Second run - _load_cache still returns None, so _fetchall called again
413
+ result2 = job.run()
414
+ assert mock_fetchall.call_count == 2
415
+ assert mock_load.call_count == 2
416
+
417
+ pd.testing.assert_frame_equal(result1, result2)
418
+
419
+ def test_run_without_cache(self, mock_session, sample_source_data):
420
+ """Test that conceptcapflow works correctly without cache"""
421
+ job = ConceptCapflowTHS(session=mock_session, cache=False)
422
+
423
+ with patch.object(job, "_fetchall", return_value=sample_source_data) as mock_fetchall:
424
+ job.run()
425
+ job.run()
426
+
427
+ # Should fetch twice (no caching)
428
+ assert mock_fetchall.call_count == 2
429
+
430
+ def test_params_identifier_uniqueness(self, mock_session):
431
+ """Test that different params create different cache keys"""
432
+ job1 = ConceptCapflowTHS(session=mock_session, params={"trade_date": "20241201"}, cache=True)
433
+ job2 = ConceptCapflowTHS(session=mock_session, params={"trade_date": "20241129"}, cache=True)
434
+
435
+ assert job1.params.identifier != job2.params.identifier
436
+
437
+
438
+ # ============================================================================
439
+ # Integration Tests
440
+ # ============================================================================
441
+
442
+
443
+ class TestIntegration:
444
+ """Test end-to-end workflows"""
445
+
446
+ def test_full_workflow(self, mock_session, sample_source_data):
447
+ """Test complete workflow from initialization to data retrieval"""
448
+ job = ConceptCapflowTHS(
449
+ session=mock_session,
450
+ params={
451
+ "ts_code": "885748.TI",
452
+ "start_date": "20241101",
453
+ "end_date": "20241231",
454
+ },
455
+ cache=False,
456
+ )
457
+
458
+ with patch.object(job, "_fetchall", return_value=sample_source_data):
459
+ result = job.run()
460
+
461
+ assert len(result) > 0
462
+
463
+ def test_large_dataset_handling(self, mock_session):
464
+ """Test handling of large datasets"""
465
+ # Create large dataset
466
+ large_data = pd.DataFrame(
467
+ {
468
+ "trade_date": ["20241201"] * 1000,
469
+ "ts_code": [f"88{str(i).zfill(4)}.TI" for i in range(1000)],
470
+ "name": ["概念板块"] * 1000,
471
+ "lead_stock": ["领涨股"] * 1000,
472
+ "close_price": [10.50] * 1000,
473
+ "pct_change": [2.50] * 1000,
474
+ "industry_index": [1500.00] * 1000,
475
+ "company_num": [50] * 1000,
476
+ "pct_change_stock": [3.00] * 1000,
477
+ "net_buy_amount": [100.00] * 1000,
478
+ "net_sell_amount": [90.00] * 1000,
479
+ "net_amount": [10.00] * 1000,
480
+ }
481
+ )
482
+
483
+ job = ConceptCapflowTHS(session=mock_session, cache=False)
484
+
485
+ with patch.object(job, "_fetchall", return_value=large_data):
486
+ result = job.run()
487
+
488
+ assert len(result) == 1000
489
+
490
+ def test_missing_fields_handling(self, mock_session):
491
+ """Test handling of data with some missing fields"""
492
+ data = pd.DataFrame(
493
+ {
494
+ "trade_date": ["20241201"],
495
+ "ts_code": ["885748.TI"],
496
+ "name": ["可燃冰"],
497
+ "lead_stock": ["海默科技"],
498
+ "close_price": [None], # Missing price
499
+ "pct_change": [4.76],
500
+ "industry_index": [1307.56],
501
+ "company_num": [12],
502
+ "pct_change_stock": [None], # Missing data
503
+ "net_buy_amount": [21.00],
504
+ "net_sell_amount": [19.00],
505
+ "net_amount": [1.00],
506
+ }
507
+ )
508
+
509
+ job = ConceptCapflowTHS(session=mock_session, cache=False)
510
+
511
+ with patch.object(job, "_fetchall", return_value=data):
512
+ result = job.run()
513
+
514
+ assert len(result) == 1
515
+ assert pd.isna(result.iloc[0]["close"])
516
+ assert pd.isna(result.iloc[0]["pct_change_stock"])
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+
3
+ from xfintech.data.source.tushare.stock.dayline.constant import (
4
+ KEY,
5
+ NAME,
6
+ PAGINATE,
7
+ SOURCE,
8
+ TARGET,
9
+ )
10
+ from xfintech.data.source.tushare.stock.dayline.dayline import Dayline
11
+
12
+ __all__ = [
13
+ "Dayline",
14
+ "KEY",
15
+ "NAME",
16
+ "PAGINATE",
17
+ "SOURCE",
18
+ "TARGET",
19
+ ]
@@ -0,0 +1,87 @@
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 = "daily"
10
+ URL = "https://tushare.pro/document/2?doc_id=27"
11
+ ARGS = {
12
+ "ts_code": {
13
+ "type": ColumnKind.STRING,
14
+ "required": "N",
15
+ "desc": "股票代码(支持多个股票同时提取,逗号分隔)",
16
+ },
17
+ "trade_date": {
18
+ "type": ColumnKind.STRING,
19
+ "required": "N",
20
+ "desc": "交易日期(YYYYMMDD)",
21
+ },
22
+ "start_date": {
23
+ "type": ColumnKind.STRING,
24
+ "required": "N",
25
+ "desc": "开始日期(YYYYMMDD)",
26
+ },
27
+ "end_date": {
28
+ "type": ColumnKind.STRING,
29
+ "required": "N",
30
+ "desc": "结束日期(YYYYMMDD)",
31
+ },
32
+ }
33
+
34
+ # Exported constants
35
+ NAME = "dayline"
36
+ KEY = "/tushare/dayline"
37
+ PAGINATE = Paginate(
38
+ pagesize=6000,
39
+ pagelimit=1000,
40
+ )
41
+ SOURCE = TableInfo(
42
+ desc="A股日线行情数据(Tushare格式)",
43
+ meta={
44
+ "provider": PROVIDER,
45
+ "source": SOURCE_NAME,
46
+ "url": URL,
47
+ "args": ARGS,
48
+ "type": "partitioned",
49
+ "scale": "crosssection",
50
+ },
51
+ columns=[
52
+ ColumnInfo(name="ts_code", kind=ColumnKind.STRING, desc="股票代码"),
53
+ ColumnInfo(name="trade_date", kind=ColumnKind.STRING, desc="交易日期"),
54
+ ColumnInfo(name="open", kind=ColumnKind.FLOAT, desc="开盘价"),
55
+ ColumnInfo(name="high", kind=ColumnKind.FLOAT, desc="最高价"),
56
+ ColumnInfo(name="low", kind=ColumnKind.FLOAT, desc="最低价"),
57
+ ColumnInfo(name="close", kind=ColumnKind.FLOAT, desc="收盘价"),
58
+ ColumnInfo(name="pre_close", kind=ColumnKind.FLOAT, desc="昨收价(除权价,前复权)"),
59
+ ColumnInfo(name="change", kind=ColumnKind.FLOAT, desc="涨跌额"),
60
+ ColumnInfo(name="pct_chg", kind=ColumnKind.FLOAT, desc="涨跌幅(基于除权后昨收计算)"),
61
+ ColumnInfo(name="vol", kind=ColumnKind.FLOAT, desc="成交量(手)"),
62
+ ColumnInfo(name="amount", kind=ColumnKind.FLOAT, desc="成交额(千元)"),
63
+ ],
64
+ )
65
+ TARGET = TableInfo(
66
+ desc="A股日线行情数据(xfintech格式)",
67
+ meta={
68
+ "key": KEY,
69
+ "name": NAME,
70
+ "type": "partitioned",
71
+ "scale": "crosssection",
72
+ },
73
+ columns=[
74
+ ColumnInfo(name="code", kind=ColumnKind.STRING, desc="股票代码"),
75
+ ColumnInfo(name="date", kind=ColumnKind.STRING, desc="交易日期"),
76
+ ColumnInfo(name="datecode", kind=ColumnKind.STRING, desc="交易日期代码(YYYYMMDD)"),
77
+ ColumnInfo(name="open", kind=ColumnKind.FLOAT, desc="开盘价(元)"),
78
+ ColumnInfo(name="high", kind=ColumnKind.FLOAT, desc="最高价(元)"),
79
+ ColumnInfo(name="low", kind=ColumnKind.FLOAT, desc="最低价(元)"),
80
+ ColumnInfo(name="close", kind=ColumnKind.FLOAT, desc="收盘价(元)"),
81
+ ColumnInfo(name="pre_close", kind=ColumnKind.FLOAT, desc="昨收价(元)"),
82
+ ColumnInfo(name="change", kind=ColumnKind.FLOAT, desc="涨跌额(元)"),
83
+ ColumnInfo(name="percent_change", kind=ColumnKind.FLOAT, desc="涨跌幅(%)"),
84
+ ColumnInfo(name="volume", kind=ColumnKind.FLOAT, desc="成交量(手)"),
85
+ ColumnInfo(name="amount", kind=ColumnKind.FLOAT, desc="成交额(千元)"),
86
+ ],
87
+ )