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,574 @@
1
+ """
2
+ Test suite for Monthline class
3
+ Tests cover initialization, data fetching, transformation, date handling, and utility methods
4
+ """
5
+
6
+ from unittest.mock import MagicMock, patch
7
+
8
+ import pandas as pd
9
+ import pytest
10
+
11
+ from xfintech.data.common.cache import Cache
12
+ from xfintech.data.common.coolant import Coolant
13
+ from xfintech.data.common.retry import Retry
14
+ from xfintech.data.source.tushare.session.session import Session
15
+ from xfintech.data.source.tushare.stock.monthline.constant import (
16
+ KEY,
17
+ NAME,
18
+ SOURCE,
19
+ TARGET,
20
+ )
21
+ from xfintech.data.source.tushare.stock.monthline.monthline import Monthline
22
+
23
+ # ============================================================================
24
+ # Fixtures
25
+ # ============================================================================
26
+
27
+
28
+ @pytest.fixture
29
+ def mock_session():
30
+ """Create a mock Tushare session"""
31
+ session = MagicMock(spec=Session)
32
+ session._credential = "test_token"
33
+ session.id = "test1234"
34
+ session.mode = "direct"
35
+ session.relay_url = None
36
+ session.relay_secret = None
37
+ session.connected = True
38
+
39
+ # Mock the connection object
40
+ mock_connection = MagicMock()
41
+ mock_connection.monthly = MagicMock()
42
+ session.connection = mock_connection
43
+
44
+ return session
45
+
46
+
47
+ @pytest.fixture
48
+ def sample_source_data():
49
+ """Create sample source data in Tushare format"""
50
+ return pd.DataFrame(
51
+ {
52
+ "ts_code": ["000001.SZ", "000002.SZ", "600000.SH"],
53
+ "trade_date": ["20241031", "20241031", "20240930"],
54
+ "open": [10.50, 8.20, 15.30],
55
+ "high": [10.80, 8.45, 15.60],
56
+ "low": [10.30, 8.00, 15.10],
57
+ "close": [10.75, 8.35, 15.45],
58
+ "pre_close": [10.50, 8.20, 15.20],
59
+ "change": [0.25, 0.15, 0.25],
60
+ "pct_chg": [2.38, 1.83, 1.64],
61
+ "vol": [1250000.0, 980000.0, 2100000.0],
62
+ "amount": [134500.0, 81200.0, 324500.0],
63
+ }
64
+ )
65
+
66
+
67
+ # ============================================================================
68
+ # Initialization Tests
69
+ # ============================================================================
70
+
71
+
72
+ def test_monthline_initialization_basic(mock_session):
73
+ """Test basic initialization"""
74
+ job = Monthline(session=mock_session)
75
+ assert job.name == NAME
76
+ assert job.key == KEY
77
+ assert job.source == SOURCE
78
+ assert job.target == TARGET
79
+ assert job.paginate.pagesize == 4500
80
+
81
+
82
+ def test_monthline_initialization_with_params(mock_session):
83
+ """Test initialization with params"""
84
+ params = {"ts_code": "000001.SZ", "start_date": "20240101"}
85
+ job = Monthline(session=mock_session, params=params)
86
+
87
+ assert job.params.ts_code == "000001.SZ"
88
+ assert job.params.start_date == "20240101"
89
+
90
+
91
+ def test_monthline_initialization_with_all_components(mock_session):
92
+ """Test initialization with all components"""
93
+ params = {"ts_code": "000001.SZ"}
94
+ coolant = Coolant(interval=0.2)
95
+ retry = Retry(retry=3)
96
+ cache = Cache(path="/tmp/test_cache")
97
+
98
+ job = Monthline(
99
+ session=mock_session,
100
+ params=params,
101
+ coolant=coolant,
102
+ retry=retry,
103
+ cache=cache,
104
+ )
105
+
106
+ assert job.params.ts_code == "000001.SZ"
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
+
113
+ def test_monthline_name_and_key():
114
+ """Test name and key constants"""
115
+ assert NAME == "monthline"
116
+ assert KEY == "/tushare/monthline"
117
+
118
+
119
+ def test_monthline_source_schema():
120
+ """Test source schema has all required columns"""
121
+ assert SOURCE is not None
122
+ assert SOURCE.desc == "A股月线行情数据(Tushare格式)"
123
+
124
+ column_names = SOURCE.columns
125
+ assert "ts_code" in column_names
126
+ assert "trade_date" in column_names
127
+ assert "open" in column_names
128
+ assert "high" in column_names
129
+ assert "low" in column_names
130
+ assert "close" in column_names
131
+ assert "vol" in column_names
132
+ assert "amount" in column_names
133
+
134
+
135
+ def test_monthline_target_schema():
136
+ """Test target schema has all required columns"""
137
+ assert TARGET is not None
138
+ assert TARGET.desc == "A股月线行情数据(xfintech格式)"
139
+
140
+ column_names = TARGET.columns
141
+ assert "code" in column_names
142
+ assert "date" in column_names
143
+ assert "datecode" in column_names
144
+ assert "open" in column_names
145
+ assert "close" in column_names
146
+ assert "percent_change" in column_names
147
+ assert "volume" in column_names
148
+ assert "amount" in column_names
149
+
150
+
151
+ # ============================================================================
152
+ # Transform Tests
153
+ # ============================================================================
154
+
155
+
156
+ def test_monthline_transform_basic(mock_session, sample_source_data):
157
+ """Test basic data transformation"""
158
+ job = Monthline(session=mock_session)
159
+ result = job.transform(sample_source_data)
160
+
161
+ assert len(result) == 3
162
+ assert "code" in result.columns
163
+ assert "date" in result.columns
164
+ assert "datecode" in result.columns
165
+ assert result.iloc[0]["code"] == "000001.SZ"
166
+ assert result.iloc[0]["datecode"] == "20241031"
167
+
168
+
169
+ def test_monthline_transform_date_conversion(mock_session, sample_source_data):
170
+ """Test date field conversions"""
171
+ job = Monthline(session=mock_session)
172
+ result = job.transform(sample_source_data)
173
+
174
+ # Check date format (YYYY-MM-DD)
175
+ assert result.iloc[0]["date"] == "2024-10-31"
176
+ assert result.iloc[1]["date"] == "2024-10-31"
177
+ assert result.iloc[2]["date"] == "2024-09-30"
178
+
179
+ # Check datecode format (YYYYMMDD)
180
+ assert result.iloc[0]["datecode"] == "20241031"
181
+
182
+
183
+ def test_monthline_transform_price_fields(mock_session, sample_source_data):
184
+ """Test price field transformations"""
185
+ job = Monthline(session=mock_session)
186
+ result = job.transform(sample_source_data)
187
+
188
+ row = result.iloc[0]
189
+ assert row["open"] == 10.50
190
+ assert row["high"] == 10.80
191
+ assert row["low"] == 10.30
192
+ assert row["close"] == 10.75
193
+ assert row["pre_close"] == 10.50
194
+ assert row["change"] == 0.25
195
+ assert row["percent_change"] == 2.38
196
+
197
+
198
+ def test_monthline_transform_volume_fields(mock_session, sample_source_data):
199
+ """Test volume field transformations"""
200
+ job = Monthline(session=mock_session)
201
+ result = job.transform(sample_source_data)
202
+
203
+ row = result.iloc[0]
204
+ assert row["volume"] == 1250000.0
205
+ assert row["amount"] == 134500.0
206
+
207
+
208
+ def test_monthline_transform_empty_data(mock_session):
209
+ """Test transform with empty data"""
210
+ job = Monthline(session=mock_session)
211
+
212
+ # Test with None
213
+ result = job.transform(None)
214
+ assert result.empty
215
+ assert len(result.columns) == len(TARGET.columns)
216
+
217
+ # Test with empty DataFrame
218
+ empty_df = pd.DataFrame()
219
+ result = job.transform(empty_df)
220
+ assert result.empty
221
+ assert len(result.columns) == len(TARGET.columns)
222
+
223
+
224
+ def test_monthline_transform_invalid_data(mock_session):
225
+ """Test transform with invalid numeric values"""
226
+ data = pd.DataFrame(
227
+ {
228
+ "ts_code": ["000001.SZ", "000002.SZ"],
229
+ "trade_date": ["20241031", "invalid_date"],
230
+ "open": [10.50, "invalid"],
231
+ "high": [10.80, 8.45],
232
+ "low": [10.30, 8.00],
233
+ "close": [10.75, 8.35],
234
+ "pre_close": [10.50, 8.20],
235
+ "change": [0.25, 0.15],
236
+ "pct_chg": [2.38, 1.83],
237
+ "vol": [1250000.0, 980000.0],
238
+ "amount": [134500.0, 81200.0],
239
+ }
240
+ )
241
+ job = Monthline(session=mock_session)
242
+ result = job.transform(data)
243
+
244
+ # Should handle invalid data gracefully
245
+ assert len(result) == 2
246
+ assert pd.isna(result.iloc[1]["date"]) # Invalid date
247
+ assert pd.isna(result.iloc[1]["open"]) # Invalid numeric
248
+
249
+
250
+ def test_monthline_transform_duplicate_removal(mock_session):
251
+ """Test that duplicates are removed"""
252
+ data = pd.DataFrame(
253
+ {
254
+ "ts_code": ["000001.SZ", "000001.SZ", "000002.SZ"],
255
+ "trade_date": ["20241031", "20241031", "20241031"],
256
+ "open": [10.50, 10.50, 8.20],
257
+ "high": [10.80, 10.80, 8.45],
258
+ "low": [10.30, 10.30, 8.00],
259
+ "close": [10.75, 10.75, 8.35],
260
+ "pre_close": [10.50, 10.50, 8.20],
261
+ "change": [0.25, 0.25, 0.15],
262
+ "pct_chg": [2.38, 2.38, 1.83],
263
+ "vol": [1250000.0, 1250000.0, 980000.0],
264
+ "amount": [134500.0, 134500.0, 81200.0],
265
+ }
266
+ )
267
+ job = Monthline(session=mock_session)
268
+ result = job.transform(data)
269
+
270
+ # Duplicates should be removed
271
+ assert len(result) == 2
272
+
273
+
274
+ def test_monthline_transform_sorting(mock_session):
275
+ """Test that result is sorted by code and date"""
276
+ data = pd.DataFrame(
277
+ {
278
+ "ts_code": ["600000.SH", "000001.SZ", "000002.SZ"],
279
+ "trade_date": ["20240831", "20241031", "20240930"],
280
+ "open": [15.30, 10.50, 8.20],
281
+ "high": [15.60, 10.80, 8.45],
282
+ "low": [15.10, 10.30, 8.00],
283
+ "close": [15.45, 10.75, 8.35],
284
+ "pre_close": [15.20, 10.50, 8.20],
285
+ "change": [0.25, 0.25, 0.15],
286
+ "pct_chg": [1.64, 2.38, 1.83],
287
+ "vol": [2100000.0, 1250000.0, 980000.0],
288
+ "amount": [324500.0, 134500.0, 81200.0],
289
+ }
290
+ )
291
+ job = Monthline(session=mock_session)
292
+ result = job.transform(data)
293
+
294
+ # Should be sorted by code, then date
295
+ expected_order = ["000001.SZ", "000002.SZ", "600000.SH"]
296
+ actual_order = result["code"].tolist()
297
+ assert actual_order == expected_order
298
+
299
+
300
+ # ============================================================================
301
+ # Run Tests
302
+ # ============================================================================
303
+
304
+
305
+ def test_monthline_run_basic(mock_session, sample_source_data):
306
+ """Test basic run method"""
307
+ job = Monthline(session=mock_session)
308
+
309
+ with patch.object(job, "_fetchall", return_value=sample_source_data):
310
+ result = job.run()
311
+
312
+ assert isinstance(result, pd.DataFrame)
313
+ assert len(result) == 3
314
+ assert "code" in result.columns
315
+ assert "date" in result.columns
316
+
317
+
318
+ def test_monthline_run_with_ts_code(mock_session, sample_source_data):
319
+ """Test run with ts_code parameter"""
320
+ filtered_data = sample_source_data[sample_source_data["ts_code"] == "000001.SZ"]
321
+
322
+ job = Monthline(session=mock_session, params={"ts_code": "000001.SZ"})
323
+
324
+ with patch.object(job, "_fetchall", return_value=filtered_data):
325
+ result = job.run()
326
+
327
+ assert len(result) == 1
328
+ assert result["code"].iloc[0] == "000001.SZ"
329
+
330
+
331
+ def test_monthline_run_with_trade_date_string(mock_session, sample_source_data):
332
+ """Test run with trade_date as string"""
333
+ job = Monthline(session=mock_session, params={"trade_date": "20241031"})
334
+
335
+ with patch.object(job, "_fetchall", return_value=sample_source_data) as mock_fetchall:
336
+ job.run()
337
+
338
+ call_kwargs = mock_fetchall.call_args[1]
339
+ assert call_kwargs["trade_date"] == "20241031"
340
+
341
+
342
+ def test_monthline_run_with_date_range_string(mock_session, sample_source_data):
343
+ """Test run with start_date and end_date as strings"""
344
+ job = Monthline(
345
+ session=mock_session,
346
+ params={"start_date": "20240101", "end_date": "20241231"},
347
+ )
348
+
349
+ with patch.object(job, "_fetchall", return_value=sample_source_data) as mock_fetchall:
350
+ job.run()
351
+
352
+ call_kwargs = mock_fetchall.call_args[1]
353
+ assert call_kwargs["start_date"] == "20240101"
354
+ assert call_kwargs["end_date"] == "20241231"
355
+
356
+
357
+ def test_monthline_run_calls_transform(mock_session, sample_source_data):
358
+ """Test that run calls transform"""
359
+ job = Monthline(session=mock_session)
360
+
361
+ with patch.object(job, "_fetchall", return_value=sample_source_data):
362
+ with patch.object(job, "transform", wraps=job.transform) as mock_transform:
363
+ job.run()
364
+
365
+ mock_transform.assert_called_once()
366
+
367
+
368
+ # ============================================================================
369
+ # Cache Tests
370
+ # ============================================================================
371
+
372
+
373
+ def test_monthline_cache_persistence(mock_session, sample_source_data):
374
+ """Test that cache persists across runs"""
375
+ job = Monthline(session=mock_session, cache=True)
376
+
377
+ with patch.object(job, "_load_cache", return_value=None) as mock_load:
378
+ with patch.object(job, "_fetchall", return_value=sample_source_data) as mock_fetchall:
379
+ # First run - fetches data and caches it
380
+ result1 = job.run()
381
+ assert mock_fetchall.call_count == 1
382
+ assert mock_load.call_count == 1
383
+
384
+ # Second run - _load_cache still returns None, so _fetchall called again
385
+ result2 = job.run()
386
+ assert mock_fetchall.call_count == 2
387
+ assert mock_load.call_count == 2
388
+
389
+ pd.testing.assert_frame_equal(result1, result2)
390
+
391
+
392
+ def test_monthline_params_identifier_uniqueness(mock_session):
393
+ """Test that different params create different cache keys"""
394
+ job1 = Monthline(session=mock_session, params={"trade_date": "20241031"}, cache=True)
395
+ job2 = Monthline(session=mock_session, params={"trade_date": "20240930"}, cache=True)
396
+
397
+ assert job1.params.identifier != job2.params.identifier
398
+
399
+
400
+ def test_monthline_without_cache(mock_session, sample_source_data):
401
+ """Test that monthline works correctly without cache"""
402
+ job = Monthline(session=mock_session, cache=False)
403
+
404
+ with patch.object(job, "_fetchall", return_value=sample_source_data) as mock_fetchall:
405
+ job.run()
406
+ job.run()
407
+
408
+ # Should fetch twice (no caching)
409
+ assert mock_fetchall.call_count == 2
410
+
411
+
412
+ # ============================================================================
413
+ # List Methods Tests
414
+ # ============================================================================
415
+
416
+
417
+ def test_monthline_list_codes(mock_session, sample_source_data):
418
+ """Test list_codes method"""
419
+ job = Monthline(session=mock_session, cache=False)
420
+
421
+ with patch.object(job, "_fetchall", return_value=sample_source_data):
422
+ codes = job.list_codes()
423
+
424
+ assert isinstance(codes, list)
425
+ assert len(codes) == 3
426
+ assert "000001.SZ" in codes
427
+ assert "000002.SZ" in codes
428
+ assert "600000.SH" in codes
429
+ assert codes == sorted(codes) # Should be sorted
430
+
431
+
432
+ def test_monthline_list_dates(mock_session, sample_source_data):
433
+ """Test list_dates method"""
434
+ job = Monthline(session=mock_session, cache=False)
435
+
436
+ with patch.object(job, "_fetchall", return_value=sample_source_data):
437
+ dates = job.list_dates()
438
+
439
+ assert isinstance(dates, list)
440
+ assert len(dates) == 2 # Two unique dates
441
+ assert "2024-09-30" in dates
442
+ assert "2024-10-31" in dates
443
+ assert dates == sorted(dates) # Should be sorted
444
+
445
+
446
+ def test_monthline_list_codes_unique(mock_session):
447
+ """Test that list_codes returns unique codes"""
448
+ data = pd.DataFrame(
449
+ {
450
+ "ts_code": ["000001.SZ", "000001.SZ", "000002.SZ"],
451
+ "trade_date": ["20241031", "20240930", "20241031"],
452
+ "open": [10.50, 10.60, 8.20],
453
+ "high": [10.80, 10.90, 8.45],
454
+ "low": [10.30, 10.40, 8.00],
455
+ "close": [10.75, 10.85, 8.35],
456
+ "pre_close": [10.50, 10.60, 8.20],
457
+ "change": [0.25, 0.25, 0.15],
458
+ "pct_chg": [2.38, 2.36, 1.83],
459
+ "vol": [1250000.0, 1300000.0, 980000.0],
460
+ "amount": [134500.0, 140500.0, 81200.0],
461
+ }
462
+ )
463
+
464
+ job = Monthline(session=mock_session, cache=False)
465
+
466
+ with patch.object(job, "_fetchall", return_value=data):
467
+ codes = job.list_codes()
468
+
469
+ assert len(codes) == 2 # Should be unique
470
+
471
+
472
+ def test_monthline_list_dates_sorted(mock_session):
473
+ """Test that list_dates returns sorted dates"""
474
+ data = pd.DataFrame(
475
+ {
476
+ "ts_code": ["000001.SZ", "000002.SZ", "600000.SH"],
477
+ "trade_date": ["20241231", "20240131", "20240630"],
478
+ "open": [10.50, 8.20, 15.30],
479
+ "high": [10.80, 8.45, 15.60],
480
+ "low": [10.30, 8.00, 15.10],
481
+ "close": [10.75, 8.35, 15.45],
482
+ "pre_close": [10.50, 8.20, 15.20],
483
+ "change": [0.25, 0.15, 0.25],
484
+ "pct_chg": [2.38, 1.83, 1.64],
485
+ "vol": [1250000.0, 980000.0, 2100000.0],
486
+ "amount": [134500.0, 81200.0, 324500.0],
487
+ }
488
+ )
489
+
490
+ job = Monthline(session=mock_session, cache=False)
491
+
492
+ with patch.object(job, "_fetchall", return_value=data):
493
+ dates = job.list_dates()
494
+
495
+ expected_dates = ["2024-01-31", "2024-06-30", "2024-12-31"]
496
+ assert dates == expected_dates
497
+
498
+
499
+ # ============================================================================
500
+ # Integration Tests
501
+ # ============================================================================
502
+
503
+
504
+ def test_monthline_full_workflow(mock_session, sample_source_data):
505
+ """Test complete workflow from initialization to data retrieval"""
506
+ job = Monthline(
507
+ session=mock_session,
508
+ params={"ts_code": "000001.SZ", "start_date": "20240101", "end_date": "20241231"},
509
+ cache=False,
510
+ )
511
+
512
+ with patch.object(job, "_fetchall", return_value=sample_source_data):
513
+ result = job.run()
514
+ codes = job.list_codes()
515
+ dates = job.list_dates()
516
+
517
+ assert len(result) > 0
518
+ assert len(codes) > 0
519
+ assert len(dates) > 0
520
+
521
+
522
+ def test_monthline_large_dataset_handling(mock_session):
523
+ """Test handling of large datasets"""
524
+ # Create large dataset
525
+ large_data = pd.DataFrame(
526
+ {
527
+ "ts_code": [f"{str(i).zfill(6)}.SZ" for i in range(1000)],
528
+ "trade_date": ["20241031"] * 1000,
529
+ "open": [10.50] * 1000,
530
+ "high": [10.80] * 1000,
531
+ "low": [10.30] * 1000,
532
+ "close": [10.75] * 1000,
533
+ "pre_close": [10.50] * 1000,
534
+ "change": [0.25] * 1000,
535
+ "pct_chg": [2.38] * 1000,
536
+ "vol": [1250000.0] * 1000,
537
+ "amount": [134500.0] * 1000,
538
+ }
539
+ )
540
+
541
+ job = Monthline(session=mock_session, cache=False)
542
+
543
+ with patch.object(job, "_fetchall", return_value=large_data):
544
+ result = job.run()
545
+
546
+ assert len(result) == 1000
547
+
548
+
549
+ def test_monthline_handles_missing_fields(mock_session):
550
+ """Test handling of data with some missing fields"""
551
+ data = pd.DataFrame(
552
+ {
553
+ "ts_code": ["000001.SZ"],
554
+ "trade_date": ["20241031"],
555
+ "open": [10.50],
556
+ "high": [10.80],
557
+ "low": [10.30],
558
+ "close": [10.75],
559
+ "pre_close": [10.50],
560
+ "change": [0.25],
561
+ "pct_chg": [2.38],
562
+ "vol": [None], # Missing volume
563
+ "amount": [None], # Missing amount
564
+ }
565
+ )
566
+
567
+ job = Monthline(session=mock_session, cache=False)
568
+
569
+ with patch.object(job, "_fetchall", return_value=data):
570
+ result = job.run()
571
+
572
+ assert len(result) == 1
573
+ assert pd.isna(result.iloc[0]["volume"])
574
+ assert pd.isna(result.iloc[0]["amount"])
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+
3
+ from xfintech.data.source.tushare.stock.stock.constant import (
4
+ KEY,
5
+ NAME,
6
+ PAGINATE,
7
+ SOURCE,
8
+ TARGET,
9
+ )
10
+ from xfintech.data.source.tushare.stock.stock.stock import Stock
11
+
12
+ __all__ = [
13
+ "Stock",
14
+ "KEY",
15
+ "NAME",
16
+ "PAGINATE",
17
+ "SOURCE",
18
+ "TARGET",
19
+ ]
@@ -0,0 +1,105 @@
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 = "stock_basic"
10
+ URL = "https://tushare.pro/document/2?doc_id=25"
11
+ EXCHANGES = ["SSE", "SZSE", "BSE"]
12
+ STATUSES = ["L", "D", "P"]
13
+ ARGS = {
14
+ "ts_code": {
15
+ "type": ColumnKind.STRING,
16
+ "required": "N",
17
+ "desc": "TS股票代码",
18
+ },
19
+ "name": {
20
+ "type": ColumnKind.STRING,
21
+ "required": "N",
22
+ "desc": "股票名称",
23
+ },
24
+ "list_status": {
25
+ "type": ColumnKind.STRING,
26
+ "required": "N",
27
+ "desc": f"上市状态{STATUSES}",
28
+ },
29
+ "exchange": {
30
+ "type": ColumnKind.STRING,
31
+ "required": "N",
32
+ "desc": f"交易所{EXCHANGES}",
33
+ },
34
+ "market": {
35
+ "type": ColumnKind.STRING,
36
+ "required": "N",
37
+ "desc": "市场类型",
38
+ },
39
+ }
40
+
41
+ # Exported constants
42
+ NAME = "stock"
43
+ KEY = "/tushare/stock"
44
+ PAGINATE = Paginate(
45
+ pagesize=4000,
46
+ pagelimit=1000,
47
+ )
48
+ SOURCE = TableInfo(
49
+ desc="上市股票基本信息(Tushare格式)",
50
+ meta={
51
+ "provider": PROVIDER,
52
+ "source": SOURCE_NAME,
53
+ "url": URL,
54
+ "args": ARGS,
55
+ "type": "static",
56
+ "scale": "crosssection",
57
+ },
58
+ columns=[
59
+ ColumnInfo(name="ts_code", kind=ColumnKind.STRING, desc="TS代码"),
60
+ ColumnInfo(name="symbol", kind=ColumnKind.STRING, desc="股票代码"),
61
+ ColumnInfo(name="name", kind=ColumnKind.STRING, desc="股票名称"),
62
+ ColumnInfo(name="area", kind=ColumnKind.STRING, desc="地域"),
63
+ ColumnInfo(name="industry", kind=ColumnKind.STRING, desc="所属行业"),
64
+ ColumnInfo(name="fullname", kind=ColumnKind.STRING, desc="股票全称"),
65
+ ColumnInfo(name="enname", kind=ColumnKind.STRING, desc="英文全称"),
66
+ ColumnInfo(name="cnspell", kind=ColumnKind.STRING, desc="拼音缩写"),
67
+ ColumnInfo(name="market", kind=ColumnKind.STRING, desc="市场类型(主板/创业板/科创板/CDR)"),
68
+ ColumnInfo(name="exchange", kind=ColumnKind.STRING, desc="交易所代码"),
69
+ ColumnInfo(name="curr_type", kind=ColumnKind.STRING, desc="交易货币"),
70
+ ColumnInfo(name="list_status", kind=ColumnKind.STRING, desc="上市状态 L上市 D退市 P暂停上市"),
71
+ ColumnInfo(name="list_date", kind=ColumnKind.STRING, desc="上市日期"),
72
+ ColumnInfo(name="delist_date", kind=ColumnKind.STRING, desc="退市日期"),
73
+ ColumnInfo(name="is_hs", kind=ColumnKind.STRING, desc="是否沪深港通标"),
74
+ ColumnInfo(name="act_name", kind=ColumnKind.STRING, desc="实控人名称"),
75
+ ColumnInfo(name="act_ent_type", kind=ColumnKind.STRING, desc="实控人企业性质"),
76
+ ],
77
+ )
78
+ TARGET = TableInfo(
79
+ desc="上市公司基本信息(xfintech格式)",
80
+ meta={
81
+ "key": KEY,
82
+ "name": NAME,
83
+ "type": "static",
84
+ "scale": "crosssection",
85
+ },
86
+ columns=[
87
+ ColumnInfo(name="code", kind=ColumnKind.STRING, desc="TS代码"),
88
+ ColumnInfo(name="symbol", kind=ColumnKind.STRING, desc="股票代码"),
89
+ ColumnInfo(name="name", kind=ColumnKind.STRING, desc="股票名称"),
90
+ ColumnInfo(name="area", kind=ColumnKind.STRING, desc="地域"),
91
+ ColumnInfo(name="industry", kind=ColumnKind.STRING, desc="所属行业"),
92
+ ColumnInfo(name="fullname", kind=ColumnKind.STRING, desc="股票全称"),
93
+ ColumnInfo(name="enname", kind=ColumnKind.STRING, desc="英文全称"),
94
+ ColumnInfo(name="cnspell", kind=ColumnKind.STRING, desc="拼音缩写"),
95
+ ColumnInfo(name="market", kind=ColumnKind.STRING, desc="市场类型(主板/创业板/科创板/CDR)"),
96
+ ColumnInfo(name="exchange", kind=ColumnKind.STRING, desc="交易所代码"),
97
+ ColumnInfo(name="currency", kind=ColumnKind.STRING, desc="交易货币"),
98
+ ColumnInfo(name="list_status", kind=ColumnKind.STRING, desc="上市状态 L上市 D退市 P暂停上市"),
99
+ ColumnInfo(name="list_date", kind=ColumnKind.STRING, desc="上市日期"),
100
+ ColumnInfo(name="delist_date", kind=ColumnKind.STRING, desc="退市日期"),
101
+ ColumnInfo(name="is_hs", kind=ColumnKind.STRING, desc="是否沪深港通标"),
102
+ ColumnInfo(name="ace_name", kind=ColumnKind.STRING, desc="实控人名称"),
103
+ ColumnInfo(name="ace_type", kind=ColumnKind.STRING, desc="实控人企业性质"),
104
+ ],
105
+ )