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,589 @@
1
+ from datetime import date, datetime
2
+ from unittest.mock import MagicMock, patch
3
+
4
+ import pandas as pd
5
+ import pytest
6
+
7
+ from xfintech.data.common.cache import Cache
8
+ from xfintech.data.common.coolant import Coolant
9
+ from xfintech.data.common.retry import Retry
10
+ from xfintech.data.source.tushare.session.session import Session
11
+ from xfintech.data.source.tushare.stock.capflow.capflow import Capflow
12
+ from xfintech.data.source.tushare.stock.capflow.constant import (
13
+ KEY,
14
+ NAME,
15
+ PAGINATE,
16
+ SOURCE,
17
+ TARGET,
18
+ )
19
+
20
+ # Fixtures
21
+
22
+
23
+ @pytest.fixture
24
+ def mock_session():
25
+ """Create a mock Tushare session"""
26
+ session = MagicMock(spec=Session)
27
+ session._credential = "test_token"
28
+ session.id = "test1234"
29
+ session.mode = "direct"
30
+ session.relay_url = None
31
+ session.relay_secret = None
32
+ session.connected = True
33
+
34
+ # Mock the connection object
35
+ mock_connection = MagicMock()
36
+ mock_connection.moneyflow = MagicMock()
37
+ session.connection = mock_connection
38
+
39
+ return session
40
+
41
+
42
+ @pytest.fixture
43
+ def sample_source_data():
44
+ """Create sample source data in Tushare format"""
45
+ return pd.DataFrame(
46
+ {
47
+ "ts_code": ["000001.SZ", "000002.SZ", "600000.SH"],
48
+ "trade_date": ["20241201", "20241201", "20241129"],
49
+ "buy_sm_vol": [1000.0, 800.0, 1200.0],
50
+ "buy_sm_amount": [105.5, 84.2, 126.3],
51
+ "sell_sm_vol": [900.0, 750.0, 1100.0],
52
+ "sell_sm_amount": [94.7, 78.9, 115.8],
53
+ "buy_md_vol": [2000.0, 1600.0, 2400.0],
54
+ "buy_md_amount": [211.0, 168.4, 252.6],
55
+ "sell_md_vol": [1800.0, 1500.0, 2200.0],
56
+ "sell_md_amount": [189.4, 157.8, 231.6],
57
+ "buy_lg_vol": [3000.0, 2400.0, 3600.0],
58
+ "buy_lg_amount": [316.5, 252.6, 378.9],
59
+ "sell_lg_vol": [2700.0, 2250.0, 3300.0],
60
+ "sell_lg_amount": [284.1, 236.7, 347.4],
61
+ "buy_elg_vol": [5000.0, 4000.0, 6000.0],
62
+ "buy_elg_amount": [527.5, 421.0, 631.5],
63
+ "sell_elg_vol": [4500.0, 3750.0, 5500.0],
64
+ "sell_elg_amount": [474.8, 394.9, 579.2],
65
+ "net_mf_vol": [1000.0, 800.0, 1200.0],
66
+ "net_mf_amount": [105.5, 84.2, 126.3],
67
+ }
68
+ )
69
+
70
+
71
+ # Initialization Tests
72
+
73
+
74
+ class TestInitialization:
75
+ """Test initialization and configuration"""
76
+
77
+ def test_init_basic(self, mock_session):
78
+ """Test basic initialization"""
79
+ job = Capflow(session=mock_session)
80
+
81
+ assert job.name == NAME
82
+ assert job.key == KEY
83
+ assert job.source == SOURCE
84
+ assert job.target == TARGET
85
+ assert job.paginate.pagesize == 6000
86
+
87
+ def test_init_with_params(self, mock_session):
88
+ """Test initialization with params"""
89
+ params = {"ts_code": "000001.SZ", "start_date": "20240101"}
90
+ job = Capflow(session=mock_session, params=params)
91
+
92
+ assert job.params.ts_code == "000001.SZ"
93
+ assert job.params.start_date == "20240101"
94
+
95
+ def test_init_with_all_components(self, mock_session):
96
+ """Test initialization with all components"""
97
+ params = {"ts_code": "000001.SZ"}
98
+ coolant = Coolant(interval=0.2)
99
+ retry = Retry(retry=3)
100
+ cache = Cache(path="/tmp/test_cache")
101
+
102
+ job = Capflow(
103
+ session=mock_session,
104
+ params=params,
105
+ coolant=coolant,
106
+ retry=retry,
107
+ cache=cache,
108
+ )
109
+
110
+ assert job.params.ts_code == "000001.SZ"
111
+ assert job.coolant.interval == 0.2
112
+ assert job.retry.retry == 3
113
+ assert job.cache is not None
114
+ assert isinstance(job.cache, Cache)
115
+
116
+ def test_name_constant(self):
117
+ """Test name constant"""
118
+ assert NAME == "capflow"
119
+
120
+ def test_key_constant(self):
121
+ """Test key constant"""
122
+ assert KEY == "/tushare/capflow"
123
+
124
+ def test_paginate_constant(self):
125
+ """Test paginate configuration"""
126
+ assert PAGINATE.pagesize
127
+ assert PAGINATE.pagelimit
128
+
129
+ def test_source_schema(self):
130
+ """Test source schema has all required columns"""
131
+ assert SOURCE is not None
132
+ assert SOURCE.desc
133
+
134
+ column_names = SOURCE.columns
135
+ assert "ts_code" in column_names
136
+ assert "trade_date" in column_names
137
+ assert "buy_sm_vol" in column_names
138
+ assert "buy_sm_amount" in column_names
139
+ assert "sell_sm_vol" in column_names
140
+ assert "sell_sm_amount" in column_names
141
+ assert "net_mf_vol" in column_names
142
+ assert "net_mf_amount" in column_names
143
+
144
+ def test_target_schema(self):
145
+ """Test target schema has all required columns"""
146
+ assert TARGET is not None
147
+ assert TARGET.desc
148
+
149
+ column_names = TARGET.columns
150
+ assert "code" in column_names
151
+ assert "date" in column_names
152
+ assert "datecode" in column_names
153
+ assert "buy_sm_vol" in column_names
154
+ assert "buy_sm_amount" in column_names
155
+ assert "net_mf_vol" in column_names
156
+ assert "net_mf_amount" in column_names
157
+
158
+
159
+ # Transform Tests
160
+
161
+
162
+ class TestTransform:
163
+ """Test data transformation"""
164
+
165
+ def test_transform_basic(self, mock_session, sample_source_data):
166
+ """Test basic data transformation"""
167
+ job = Capflow(session=mock_session)
168
+ result = job.transform(sample_source_data)
169
+
170
+ assert len(result) == 3
171
+ assert "code" in result.columns
172
+ assert "date" in result.columns
173
+ assert "datecode" in result.columns
174
+ assert result.iloc[0]["code"] == "000001.SZ"
175
+ assert result.iloc[0]["datecode"] == "20241201"
176
+
177
+ def test_transform_date_conversion(self, mock_session, sample_source_data):
178
+ """Test date field conversions"""
179
+ job = Capflow(session=mock_session)
180
+ result = job.transform(sample_source_data)
181
+
182
+ # Check date format (YYYY-MM-DD)
183
+ assert result.iloc[0]["date"] == "2024-12-01"
184
+ assert result.iloc[1]["date"] == "2024-12-01"
185
+ assert result.iloc[2]["date"] == "2024-11-29"
186
+
187
+ # Check datecode format (YYYYMMDD)
188
+ assert result.iloc[0]["datecode"] == "20241201"
189
+
190
+ def test_transform_field_mappings(self, mock_session, sample_source_data):
191
+ """Test field mapping transformations"""
192
+ job = Capflow(session=mock_session)
193
+ result = job.transform(sample_source_data)
194
+
195
+ row = result.iloc[0]
196
+ assert row["buy_sm_vol"] == 1000.0
197
+ assert row["buy_sm_amount"] == 105.5
198
+ assert row["sell_sm_vol"] == 900.0
199
+ assert row["sell_sm_amount"] == 94.7
200
+ assert row["net_mf_vol"] == 1000.0
201
+ assert row["net_mf_amount"] == 105.5
202
+
203
+ def test_transform_numeric_fields(self, mock_session, sample_source_data):
204
+ """Test numeric field transformations"""
205
+ job = Capflow(session=mock_session)
206
+ result = job.transform(sample_source_data)
207
+
208
+ row = result.iloc[0]
209
+ # Check all numeric fields are properly converted
210
+ assert isinstance(row["buy_sm_vol"], (int, float))
211
+ assert isinstance(row["buy_sm_amount"], (int, float))
212
+ assert isinstance(row["buy_md_vol"], (int, float))
213
+ assert isinstance(row["buy_lg_vol"], (int, float))
214
+ assert isinstance(row["buy_elg_vol"], (int, float))
215
+
216
+ def test_transform_empty_data(self, mock_session):
217
+ """Test transform with empty data"""
218
+ job = Capflow(session=mock_session)
219
+
220
+ # Test with None
221
+ result = job.transform(None)
222
+ assert result.empty
223
+ assert len(result.columns) == len(TARGET.columns)
224
+
225
+ # Test with empty DataFrame
226
+ empty_df = pd.DataFrame()
227
+ result = job.transform(empty_df)
228
+ assert result.empty
229
+ assert len(result.columns) == len(TARGET.columns)
230
+
231
+ def test_transform_none_data(self, mock_session):
232
+ """Test transform with None data"""
233
+ job = Capflow(session=mock_session)
234
+ result = job.transform(None)
235
+
236
+ assert result.empty
237
+ assert list(result.columns) == TARGET.list_column_names()
238
+
239
+ def test_transform_invalid_data(self, mock_session):
240
+ """Test transform with invalid numeric values"""
241
+ data = pd.DataFrame(
242
+ {
243
+ "ts_code": ["000001.SZ", "000002.SZ"],
244
+ "trade_date": ["20241201", "invalid_date"],
245
+ "buy_sm_vol": [1000.0, "invalid"],
246
+ "buy_sm_amount": [105.5, 84.2],
247
+ "sell_sm_vol": [900.0, 750.0],
248
+ "sell_sm_amount": [94.7, 78.9],
249
+ "buy_md_vol": [2000.0, 1600.0],
250
+ "buy_md_amount": [211.0, 168.4],
251
+ "sell_md_vol": [1800.0, 1500.0],
252
+ "sell_md_amount": [189.4, 157.8],
253
+ "buy_lg_vol": [3000.0, 2400.0],
254
+ "buy_lg_amount": [316.5, 252.6],
255
+ "sell_lg_vol": [2700.0, 2250.0],
256
+ "sell_lg_amount": [284.1, 236.7],
257
+ "buy_elg_vol": [5000.0, 4000.0],
258
+ "buy_elg_amount": [527.5, 421.0],
259
+ "sell_elg_vol": [4500.0, 3750.0],
260
+ "sell_elg_amount": [474.8, 394.9],
261
+ "net_mf_vol": [1000.0, 800.0],
262
+ "net_mf_amount": [105.5, 84.2],
263
+ }
264
+ )
265
+ job = Capflow(session=mock_session)
266
+ result = job.transform(data)
267
+
268
+ # Should handle invalid data gracefully
269
+ assert len(result) == 2
270
+ assert pd.isna(result.iloc[1]["date"]) # Invalid date
271
+ assert pd.isna(result.iloc[1]["buy_sm_vol"]) # Invalid numeric
272
+
273
+ def test_transform_duplicates_removed(self, mock_session):
274
+ """Test that duplicates are removed"""
275
+ data = pd.DataFrame(
276
+ {
277
+ "ts_code": ["000001.SZ", "000001.SZ", "000002.SZ"],
278
+ "trade_date": ["20241201", "20241201", "20241201"],
279
+ "buy_sm_vol": [1000.0, 1000.0, 800.0],
280
+ "buy_sm_amount": [105.5, 105.5, 84.2],
281
+ "sell_sm_vol": [900.0, 900.0, 750.0],
282
+ "sell_sm_amount": [94.7, 94.7, 78.9],
283
+ "buy_md_vol": [2000.0, 2000.0, 1600.0],
284
+ "buy_md_amount": [211.0, 211.0, 168.4],
285
+ "sell_md_vol": [1800.0, 1800.0, 1500.0],
286
+ "sell_md_amount": [189.4, 189.4, 157.8],
287
+ "buy_lg_vol": [3000.0, 3000.0, 2400.0],
288
+ "buy_lg_amount": [316.5, 316.5, 252.6],
289
+ "sell_lg_vol": [2700.0, 2700.0, 2250.0],
290
+ "sell_lg_amount": [284.1, 284.1, 236.7],
291
+ "buy_elg_vol": [5000.0, 5000.0, 4000.0],
292
+ "buy_elg_amount": [527.5, 527.5, 421.0],
293
+ "sell_elg_vol": [4500.0, 4500.0, 3750.0],
294
+ "sell_elg_amount": [474.8, 474.8, 394.9],
295
+ "net_mf_vol": [1000.0, 1000.0, 800.0],
296
+ "net_mf_amount": [105.5, 105.5, 84.2],
297
+ }
298
+ )
299
+ job = Capflow(session=mock_session)
300
+ result = job.transform(data)
301
+
302
+ # Duplicates should be removed
303
+ assert len(result) == 2
304
+
305
+ def test_transform_sorting(self, mock_session):
306
+ """Test that result is sorted by code and date"""
307
+ data = pd.DataFrame(
308
+ {
309
+ "ts_code": ["600000.SH", "000001.SZ", "000002.SZ"],
310
+ "trade_date": ["20241115", "20241201", "20241129"],
311
+ "buy_sm_vol": [1200.0, 1000.0, 800.0],
312
+ "buy_sm_amount": [126.3, 105.5, 84.2],
313
+ "sell_sm_vol": [1100.0, 900.0, 750.0],
314
+ "sell_sm_amount": [115.8, 94.7, 78.9],
315
+ "buy_md_vol": [2400.0, 2000.0, 1600.0],
316
+ "buy_md_amount": [252.6, 211.0, 168.4],
317
+ "sell_md_vol": [2200.0, 1800.0, 1500.0],
318
+ "sell_md_amount": [231.6, 189.4, 157.8],
319
+ "buy_lg_vol": [3600.0, 3000.0, 2400.0],
320
+ "buy_lg_amount": [378.9, 316.5, 252.6],
321
+ "sell_lg_vol": [3300.0, 2700.0, 2250.0],
322
+ "sell_lg_amount": [347.4, 284.1, 236.7],
323
+ "buy_elg_vol": [6000.0, 5000.0, 4000.0],
324
+ "buy_elg_amount": [631.5, 527.5, 421.0],
325
+ "sell_elg_vol": [5500.0, 4500.0, 3750.0],
326
+ "sell_elg_amount": [579.2, 474.8, 394.9],
327
+ "net_mf_vol": [1200.0, 1000.0, 800.0],
328
+ "net_mf_amount": [126.3, 105.5, 84.2],
329
+ }
330
+ )
331
+ job = Capflow(session=mock_session)
332
+ result = job.transform(data)
333
+
334
+ # Should be sorted by code, then date
335
+ expected_order = ["000001.SZ", "000002.SZ", "600000.SH"]
336
+ actual_order = result["code"].tolist()
337
+ assert actual_order == expected_order
338
+
339
+
340
+ # Run Tests
341
+
342
+
343
+ class TestRun:
344
+ """Test execution logic"""
345
+
346
+ def test_run_basic(self, mock_session, sample_source_data):
347
+ """Test basic run method"""
348
+ job = Capflow(session=mock_session)
349
+
350
+ with patch.object(job, "_fetchall", return_value=sample_source_data):
351
+ result = job.run()
352
+
353
+ assert isinstance(result, pd.DataFrame)
354
+ assert len(result) == 3
355
+ assert "code" in result.columns
356
+ assert "date" in result.columns
357
+
358
+ def test_run_with_params(self, mock_session, sample_source_data):
359
+ """Test run with ts_code parameter"""
360
+ filtered_data = sample_source_data[sample_source_data["ts_code"] == "000001.SZ"]
361
+
362
+ job = Capflow(session=mock_session, params={"ts_code": "000001.SZ"})
363
+
364
+ with patch.object(job, "_fetchall", return_value=filtered_data):
365
+ result = job.run()
366
+
367
+ assert len(result) == 1
368
+ assert result["code"].iloc[0] == "000001.SZ"
369
+
370
+ def test_run_with_date_string(self, mock_session, sample_source_data):
371
+ """Test run with trade_date as string"""
372
+ job = Capflow(session=mock_session, params={"trade_date": "20241201"})
373
+
374
+ with patch.object(job, "_fetchall", return_value=sample_source_data) as mock_fetchall:
375
+ job.run()
376
+
377
+ call_kwargs = mock_fetchall.call_args[1]
378
+ assert call_kwargs["trade_date"] == "20241201"
379
+
380
+ def test_run_with_date_datetime(self, mock_session, sample_source_data):
381
+ """Test run with trade_date as datetime object"""
382
+ trade_date = datetime(2024, 12, 1)
383
+ job = Capflow(session=mock_session, params={"trade_date": trade_date})
384
+
385
+ with patch.object(job, "_fetchall", return_value=sample_source_data) as mock_fetchall:
386
+ job.run()
387
+
388
+ call_kwargs = mock_fetchall.call_args[1]
389
+ assert call_kwargs["trade_date"] == "20241201"
390
+
391
+ def test_run_with_date_date(self, mock_session, sample_source_data):
392
+ """Test run with trade_date as date object (not datetime)"""
393
+ trade_date = date(2024, 12, 1)
394
+ job = Capflow(session=mock_session, params={"trade_date": trade_date})
395
+
396
+ with patch.object(job, "_fetchall", return_value=sample_source_data) as mock_fetchall:
397
+ job.run()
398
+
399
+ call_kwargs = mock_fetchall.call_args[1]
400
+ assert call_kwargs["trade_date"] == "20241201"
401
+
402
+ def test_run_with_date_range_string(self, mock_session, sample_source_data):
403
+ """Test run with start_date and end_date as strings"""
404
+ job = Capflow(
405
+ session=mock_session,
406
+ params={"start_date": "20241101", "end_date": "20241231"},
407
+ )
408
+
409
+ with patch.object(job, "_fetchall", return_value=sample_source_data) as mock_fetchall:
410
+ job.run()
411
+
412
+ call_kwargs = mock_fetchall.call_args[1]
413
+ assert call_kwargs["start_date"] == "20241101"
414
+ assert call_kwargs["end_date"] == "20241231"
415
+
416
+ def test_run_with_date_range_datetime(self, mock_session, sample_source_data):
417
+ """Test run with start_date and end_date as datetime objects"""
418
+ job = Capflow(
419
+ session=mock_session,
420
+ params={
421
+ "start_date": datetime(2024, 11, 1),
422
+ "end_date": datetime(2024, 12, 31),
423
+ },
424
+ )
425
+
426
+ with patch.object(job, "_fetchall", return_value=sample_source_data) as mock_fetchall:
427
+ job.run()
428
+
429
+ call_kwargs = mock_fetchall.call_args[1]
430
+ assert call_kwargs["start_date"] == "20241101"
431
+ assert call_kwargs["end_date"] == "20241231"
432
+
433
+ def test_run_calls_transform(self, mock_session, sample_source_data):
434
+ """Test that run calls transform"""
435
+ job = Capflow(session=mock_session)
436
+
437
+ with patch.object(job, "_fetchall", return_value=sample_source_data):
438
+ with patch.object(job, "transform", wraps=job.transform) as mock_transform:
439
+ job.run()
440
+
441
+ mock_transform.assert_called_once()
442
+
443
+ def test_run_with_multiple_ts_codes(self, mock_session, sample_source_data):
444
+ """Test run with multiple ts_code parameter"""
445
+ job = Capflow(session=mock_session, params={"ts_code": "000001.SZ,000002.SZ"})
446
+
447
+ with patch.object(job, "_fetchall", return_value=sample_source_data) as mock_fetchall:
448
+ job.run()
449
+ call_kwargs = mock_fetchall.call_args[1]
450
+ assert call_kwargs["ts_code"] == "000001.SZ,000002.SZ"
451
+
452
+
453
+ # Cache Tests
454
+
455
+
456
+ class TestCache:
457
+ """Test caching behavior"""
458
+
459
+ def test_cache_persistence(self, mock_session, sample_source_data):
460
+ """Test that cache persists across runs"""
461
+ job = Capflow(session=mock_session, cache=True)
462
+
463
+ with patch.object(job, "_load_cache", return_value=None) as mock_load:
464
+ with patch.object(job, "_fetchall", return_value=sample_source_data) as mock_fetchall:
465
+ # First run - fetches data and caches it
466
+ result1 = job.run()
467
+ assert mock_fetchall.call_count == 1
468
+ assert mock_load.call_count == 1
469
+
470
+ # Second run - _load_cache still returns None, so _fetchall called again
471
+ result2 = job.run()
472
+ assert mock_fetchall.call_count == 2
473
+ assert mock_load.call_count == 2
474
+
475
+ pd.testing.assert_frame_equal(result1, result2)
476
+
477
+ def test_run_without_cache(self, mock_session, sample_source_data):
478
+ """Test that capflow works correctly without cache"""
479
+ job = Capflow(session=mock_session, cache=False)
480
+
481
+ with patch.object(job, "_fetchall", return_value=sample_source_data) as mock_fetchall:
482
+ job.run()
483
+ job.run()
484
+
485
+ # Should fetch twice (no caching)
486
+ assert mock_fetchall.call_count == 2
487
+
488
+ def test_params_identifier_uniqueness(self, mock_session):
489
+ """Test that different params create different cache keys"""
490
+ job1 = Capflow(session=mock_session, params={"trade_date": "20241201"}, cache=True)
491
+ job2 = Capflow(session=mock_session, params={"trade_date": "20241129"}, cache=True)
492
+
493
+ assert job1.params.identifier != job2.params.identifier
494
+
495
+
496
+ # List Methods Tests
497
+
498
+
499
+ # Integration Tests
500
+
501
+
502
+ class TestIntegration:
503
+ """Test end-to-end workflows"""
504
+
505
+ def test_full_workflow(self, mock_session, sample_source_data):
506
+ """Test complete workflow from initialization to data retrieval"""
507
+ job = Capflow(
508
+ session=mock_session,
509
+ params={"ts_code": "000001.SZ", "start_date": "20241101", "end_date": "20241231"},
510
+ cache=False,
511
+ )
512
+
513
+ with patch.object(job, "_fetchall", return_value=sample_source_data):
514
+ result = job.run()
515
+
516
+ assert len(result) > 0
517
+ assert "code" in result.columns
518
+ assert "date" in result.columns
519
+
520
+ def test_large_dataset_handling(self, mock_session):
521
+ """Test handling of large datasets"""
522
+ # Create large dataset
523
+ large_data = pd.DataFrame(
524
+ {
525
+ "ts_code": [f"{str(i).zfill(6)}.SZ" for i in range(1000)],
526
+ "trade_date": ["20241201"] * 1000,
527
+ "buy_sm_vol": [1000.0] * 1000,
528
+ "buy_sm_amount": [105.5] * 1000,
529
+ "sell_sm_vol": [900.0] * 1000,
530
+ "sell_sm_amount": [94.7] * 1000,
531
+ "buy_md_vol": [2000.0] * 1000,
532
+ "buy_md_amount": [211.0] * 1000,
533
+ "sell_md_vol": [1800.0] * 1000,
534
+ "sell_md_amount": [189.4] * 1000,
535
+ "buy_lg_vol": [3000.0] * 1000,
536
+ "buy_lg_amount": [316.5] * 1000,
537
+ "sell_lg_vol": [2700.0] * 1000,
538
+ "sell_lg_amount": [284.1] * 1000,
539
+ "buy_elg_vol": [5000.0] * 1000,
540
+ "buy_elg_amount": [527.5] * 1000,
541
+ "sell_elg_vol": [4500.0] * 1000,
542
+ "sell_elg_amount": [474.8] * 1000,
543
+ "net_mf_vol": [1000.0] * 1000,
544
+ "net_mf_amount": [105.5] * 1000,
545
+ }
546
+ )
547
+
548
+ job = Capflow(session=mock_session, cache=False)
549
+
550
+ with patch.object(job, "_fetchall", return_value=large_data):
551
+ result = job.run()
552
+
553
+ assert len(result) == 1000
554
+
555
+ def test_missing_fields_handling(self, mock_session):
556
+ """Test handling of data with some missing fields"""
557
+ data = pd.DataFrame(
558
+ {
559
+ "ts_code": ["000001.SZ"],
560
+ "trade_date": ["20241201"],
561
+ "buy_sm_vol": [1000.0],
562
+ "buy_sm_amount": [None], # Missing amount
563
+ "sell_sm_vol": [900.0],
564
+ "sell_sm_amount": [94.7],
565
+ "buy_md_vol": [2000.0],
566
+ "buy_md_amount": [211.0],
567
+ "sell_md_vol": [None], # Missing volume
568
+ "sell_md_amount": [189.4],
569
+ "buy_lg_vol": [3000.0],
570
+ "buy_lg_amount": [316.5],
571
+ "sell_lg_vol": [2700.0],
572
+ "sell_lg_amount": [284.1],
573
+ "buy_elg_vol": [5000.0],
574
+ "buy_elg_amount": [527.5],
575
+ "sell_elg_vol": [4500.0],
576
+ "sell_elg_amount": [474.8],
577
+ "net_mf_vol": [1000.0],
578
+ "net_mf_amount": [105.5],
579
+ }
580
+ )
581
+
582
+ job = Capflow(session=mock_session, cache=False)
583
+
584
+ with patch.object(job, "_fetchall", return_value=data):
585
+ result = job.run()
586
+
587
+ assert len(result) == 1
588
+ assert pd.isna(result.iloc[0]["buy_sm_amount"])
589
+ assert pd.isna(result.iloc[0]["sell_md_vol"])
@@ -0,0 +1,19 @@
1
+ from __future__ import annotations
2
+
3
+ from xfintech.data.source.tushare.stock.capflowdc.capflowdc import CapflowDC
4
+ from xfintech.data.source.tushare.stock.capflowdc.constant import (
5
+ KEY,
6
+ NAME,
7
+ PAGINATE,
8
+ SOURCE,
9
+ TARGET,
10
+ )
11
+
12
+ __all__ = [
13
+ "CapflowDC",
14
+ "KEY",
15
+ "NAME",
16
+ "PAGINATE",
17
+ "SOURCE",
18
+ "TARGET",
19
+ ]