quantnodes 3.0.0__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 (399) hide show
  1. QuantNodes/__init__.py +15 -0
  2. QuantNodes/__main__.py +14 -0
  3. QuantNodes/agent/__init__.py +158 -0
  4. QuantNodes/agent/agents/__init__.py +13 -0
  5. QuantNodes/agent/agents/definition.py +180 -0
  6. QuantNodes/agent/agents/manager.py +73 -0
  7. QuantNodes/agent/config/__init__.py +34 -0
  8. QuantNodes/agent/config/executor.py +958 -0
  9. QuantNodes/agent/config/loader.py +427 -0
  10. QuantNodes/agent/config/templates/bollinger_bands.yaml +84 -0
  11. QuantNodes/agent/config/templates/dual_ma.yaml +72 -0
  12. QuantNodes/agent/config/templates/empty.yaml +56 -0
  13. QuantNodes/agent/config/templates/mean_reversion.yaml +47 -0
  14. QuantNodes/agent/config/templates/mean_reversion_zscore.yaml +90 -0
  15. QuantNodes/agent/config/templates/momentum.yaml +81 -0
  16. QuantNodes/agent/config/templates/momentum_breakout.yaml +84 -0
  17. QuantNodes/agent/config/templates/rsi_strategy.yaml +72 -0
  18. QuantNodes/agent/config/templates/volume_price.yaml +86 -0
  19. QuantNodes/agent/config/types.py +156 -0
  20. QuantNodes/agent/config_mapper.py +293 -0
  21. QuantNodes/agent/core/__init__.py +19 -0
  22. QuantNodes/agent/core/dream.py +47 -0
  23. QuantNodes/agent/core/quant_dream.py +274 -0
  24. QuantNodes/agent/cron_jobs.py +314 -0
  25. QuantNodes/agent/nanobot_bridge.py +242 -0
  26. QuantNodes/agent/permission/__init__.py +30 -0
  27. QuantNodes/agent/permission/defaults.py +36 -0
  28. QuantNodes/agent/permission/evaluate.py +41 -0
  29. QuantNodes/agent/permission/models.py +59 -0
  30. QuantNodes/agent/permission/service.py +133 -0
  31. QuantNodes/agent/providers/__init__.py +11 -0
  32. QuantNodes/agent/providers/base.py +102 -0
  33. QuantNodes/agent/providers/quantnodes.py +610 -0
  34. QuantNodes/agent/providers/rate_limiter.py +326 -0
  35. QuantNodes/agent/providers/registry.py +163 -0
  36. QuantNodes/agent/skills/__init__.py +20 -0
  37. QuantNodes/agent/skills/base.py +118 -0
  38. QuantNodes/agent/skills/bridge.py +73 -0
  39. QuantNodes/agent/skills/factor/__init__.py +14 -0
  40. QuantNodes/agent/skills/factor/correlation.py +99 -0
  41. QuantNodes/agent/skills/factor/group_backtest.py +114 -0
  42. QuantNodes/agent/skills/factor/ic_analysis.py +106 -0
  43. QuantNodes/agent/skills/loader.py +107 -0
  44. QuantNodes/agent/skills/registry.py +105 -0
  45. QuantNodes/agent/skills/strategy/__init__.py +16 -0
  46. QuantNodes/agent/skills/strategy/bollinger.py +86 -0
  47. QuantNodes/agent/skills/strategy/dual_ma.py +82 -0
  48. QuantNodes/agent/skills/strategy/momentum.py +74 -0
  49. QuantNodes/agent/skills/strategy/rsi_reversal.py +99 -0
  50. QuantNodes/agent/skills_quant/__init__.py +14 -0
  51. QuantNodes/agent/skills_quant/backtest-analyze/SKILL.md +42 -0
  52. QuantNodes/agent/skills_quant/config-driven/SKILL.md +72 -0
  53. QuantNodes/agent/skills_quant/factor-research/SKILL.md +40 -0
  54. QuantNodes/agent/skills_quant/quant-dream/SKILL.md +55 -0
  55. QuantNodes/agent/skills_quant/risk-management/SKILL.md +45 -0
  56. QuantNodes/agent/skills_quant/strategy-design/SKILL.md +43 -0
  57. QuantNodes/agent/templates/__init__.py +4 -0
  58. QuantNodes/agent/tools/__init__.py +173 -0
  59. QuantNodes/agent/tools/_workspace.py +51 -0
  60. QuantNodes/agent/tools/alpha_backtest.py +328 -0
  61. QuantNodes/agent/tools/alpha_evaluate.py +493 -0
  62. QuantNodes/agent/tools/backtest.py +226 -0
  63. QuantNodes/agent/tools/base.py +133 -0
  64. QuantNodes/agent/tools/code_search.py +207 -0
  65. QuantNodes/agent/tools/config_backtest.py +401 -0
  66. QuantNodes/agent/tools/context.py +97 -0
  67. QuantNodes/agent/tools/dream_skill.py +77 -0
  68. QuantNodes/agent/tools/echo.py +38 -0
  69. QuantNodes/agent/tools/factor.py +231 -0
  70. QuantNodes/agent/tools/file_ops.py +201 -0
  71. QuantNodes/agent/tools/git_ops.py +190 -0
  72. QuantNodes/agent/tools/operator_lookup.py +218 -0
  73. QuantNodes/agent/tools/output_truncation.py +77 -0
  74. QuantNodes/agent/tools/path_check.py +43 -0
  75. QuantNodes/agent/tools/pipeline.py +62 -0
  76. QuantNodes/agent/tools/registry.py +150 -0
  77. QuantNodes/agent/tools/sandbox.py +62 -0
  78. QuantNodes/agent/tools/shell_safety.py +63 -0
  79. QuantNodes/agent/tools/strategy.py +106 -0
  80. QuantNodes/agent/tools/task.py +171 -0
  81. QuantNodes/agent/tools/web_fetch.py +142 -0
  82. QuantNodes/agent/tools/web_search.py +114 -0
  83. QuantNodes/agent/tools/wiki.py +370 -0
  84. QuantNodes/agent/utils/__init__.py +11 -0
  85. QuantNodes/agent/utils/helpers.py +43 -0
  86. QuantNodes/agent/utils/prompt_templates.py +30 -0
  87. QuantNodes/agent/workflows/__init__.py +20 -0
  88. QuantNodes/agent/workflows/implementations/__init__.py +8 -0
  89. QuantNodes/agent/workflows/implementations/alpha_gpt.py +508 -0
  90. QuantNodes/agent/workflows/implementations/mcts.py +442 -0
  91. QuantNodes/agent/workflows/parsers.py +44 -0
  92. QuantNodes/agent/workflows/registry.py +119 -0
  93. QuantNodes/agent/workflows/step_agent.py +219 -0
  94. QuantNodes/agent/workflows/tool.py +198 -0
  95. QuantNodes/ai/__init__.py +93 -0
  96. QuantNodes/ai/llm/__init__.py +75 -0
  97. QuantNodes/ai/llm/base.py +233 -0
  98. QuantNodes/ai/llm/decorators.py +281 -0
  99. QuantNodes/ai/llm/gateway.py +571 -0
  100. QuantNodes/ai/llm/null.py +76 -0
  101. QuantNodes/ai/llm/openai.py +435 -0
  102. QuantNodes/ai/optimizer.py +405 -0
  103. QuantNodes/ai/prompts/__init__.py +229 -0
  104. QuantNodes/ai/sandbox.py +371 -0
  105. QuantNodes/ai/sandbox_pandas_bridge.py +150 -0
  106. QuantNodes/ai/strategy_gen.py +396 -0
  107. QuantNodes/backtest/__init__.py +64 -0
  108. QuantNodes/backtest/backtest_node.py +188 -0
  109. QuantNodes/backtest/broker_node.py +378 -0
  110. QuantNodes/backtest/config_runner.py +397 -0
  111. QuantNodes/backtest/config_strategy.py +64 -0
  112. QuantNodes/backtest/risk_node.py +360 -0
  113. QuantNodes/backtest/strategy_node.py +268 -0
  114. QuantNodes/cache_node/__init__.py +19 -0
  115. QuantNodes/cache_node/base.py +244 -0
  116. QuantNodes/cache_node/cache_store.py +99 -0
  117. QuantNodes/cache_node/metadata.py +100 -0
  118. QuantNodes/cli/__init__.py +109 -0
  119. QuantNodes/cli/_helpers.py +511 -0
  120. QuantNodes/cli/command.py +110 -0
  121. QuantNodes/cli/commands/__init__.py +69 -0
  122. QuantNodes/cli/commands/agent.py +158 -0
  123. QuantNodes/cli/commands/alpha.py +951 -0
  124. QuantNodes/cli/commands/chat.py +38 -0
  125. QuantNodes/cli/commands/evolve.py +120 -0
  126. QuantNodes/cli/commands/factor.py +569 -0
  127. QuantNodes/cli/commands/init.py +190 -0
  128. QuantNodes/cli/commands/run.py +259 -0
  129. QuantNodes/cli/commands/serve.py +398 -0
  130. QuantNodes/cli/commands/version.py +120 -0
  131. QuantNodes/cli/enhanced.py +146 -0
  132. QuantNodes/conf_node/__init__.py +37 -0
  133. QuantNodes/conf_node/base.py +120 -0
  134. QuantNodes/conf_node/env_config.py +132 -0
  135. QuantNodes/conf_node/ini_config.py +70 -0
  136. QuantNodes/conf_node/json_config.py +69 -0
  137. QuantNodes/conf_node/yaml_config.py +78 -0
  138. QuantNodes/constants.py +17 -0
  139. QuantNodes/core/__init__.py +196 -0
  140. QuantNodes/core/_lookback_helpers.py +49 -0
  141. QuantNodes/core/ast_parser.py +198 -0
  142. QuantNodes/core/base.py +61 -0
  143. QuantNodes/core/cache_manager.py +344 -0
  144. QuantNodes/core/cache_utils.py +150 -0
  145. QuantNodes/core/cond_builder.py +53 -0
  146. QuantNodes/core/config.py +170 -0
  147. QuantNodes/core/constants.py +48 -0
  148. QuantNodes/core/control.py +412 -0
  149. QuantNodes/core/data_preprocessing.py +453 -0
  150. QuantNodes/core/data_source.py +46 -0
  151. QuantNodes/core/events.py +178 -0
  152. QuantNodes/core/evolution/__init__.py +22 -0
  153. QuantNodes/core/evolution/loop.py +583 -0
  154. QuantNodes/core/evolution/operators.py +289 -0
  155. QuantNodes/core/evolution/settings.py +44 -0
  156. QuantNodes/core/expression.py +841 -0
  157. QuantNodes/core/feedback/__init__.py +38 -0
  158. QuantNodes/core/feedback/channels.py +182 -0
  159. QuantNodes/core/feedback/collector.py +91 -0
  160. QuantNodes/core/feedback/dataclass.py +239 -0
  161. QuantNodes/core/feedback/llm_judge.py +138 -0
  162. QuantNodes/core/knowledge/__init__.py +69 -0
  163. QuantNodes/core/knowledge/knowledge_base.py +217 -0
  164. QuantNodes/core/knowledge/lineage_compress.py +196 -0
  165. QuantNodes/core/knowledge/lineage_expand.py +123 -0
  166. QuantNodes/core/knowledge/metrics/__init__.py +43 -0
  167. QuantNodes/core/knowledge/metrics/evaluator.py +176 -0
  168. QuantNodes/core/knowledge/metrics/metrics.py +220 -0
  169. QuantNodes/core/knowledge/rag_prompt.py +196 -0
  170. QuantNodes/core/knowledge/retriever.py +209 -0
  171. QuantNodes/core/lambda_node.py +81 -0
  172. QuantNodes/core/monitoring/__init__.py +22 -0
  173. QuantNodes/core/monitoring/collector.py +292 -0
  174. QuantNodes/core/monitoring/dashboard.py +365 -0
  175. QuantNodes/core/node.py +375 -0
  176. QuantNodes/core/pandas_utils.py +504 -0
  177. QuantNodes/core/parallel/__init__.py +15 -0
  178. QuantNodes/core/parallel/worker.py +140 -0
  179. QuantNodes/core/parallel/worker_process.py +265 -0
  180. QuantNodes/core/path_utils.py +73 -0
  181. QuantNodes/core/pipeline.py +328 -0
  182. QuantNodes/core/plugin.py +135 -0
  183. QuantNodes/core/quality_gate/__init__.py +32 -0
  184. QuantNodes/core/quality_gate/complexity.py +94 -0
  185. QuantNodes/core/quality_gate/consistency.py +26 -0
  186. QuantNodes/core/quality_gate/node.py +97 -0
  187. QuantNodes/core/quality_gate/redundancy.py +51 -0
  188. QuantNodes/core/quality_gate/settings.py +43 -0
  189. QuantNodes/core/quality_gate/zoo.py +98 -0
  190. QuantNodes/core/serializable.py +116 -0
  191. QuantNodes/core/serialization.py +673 -0
  192. QuantNodes/core/tools.py +333 -0
  193. QuantNodes/core/trajectory/__init__.py +25 -0
  194. QuantNodes/core/trajectory/entry.py +116 -0
  195. QuantNodes/core/trajectory/lineage.py +67 -0
  196. QuantNodes/core/trajectory/pool.py +211 -0
  197. QuantNodes/core/trajectory/selector.py +140 -0
  198. QuantNodes/core/visualization/__init__.py +33 -0
  199. QuantNodes/core/visualization/builder.py +233 -0
  200. QuantNodes/core/visualization/gate_breakdown.py +140 -0
  201. QuantNodes/core/visualization/lineage_dag.py +203 -0
  202. QuantNodes/core/visualization/metric_distribution.py +125 -0
  203. QuantNodes/core/visualization/report.py +68 -0
  204. QuantNodes/database_node/__init__.py +69 -0
  205. QuantNodes/database_node/base.py +135 -0
  206. QuantNodes/database_node/clickhouse_node.py +272 -0
  207. QuantNodes/database_node/csv_node.py +83 -0
  208. QuantNodes/database_node/duckdb_node.py +86 -0
  209. QuantNodes/database_node/factory.py +83 -0
  210. QuantNodes/database_node/mysql_node.py +100 -0
  211. QuantNodes/database_node/parquet_node.py +75 -0
  212. QuantNodes/database_node/sqlite_node.py +67 -0
  213. QuantNodes/factor_node/__init__.py +50 -0
  214. QuantNodes/factor_node/factor.py +563 -0
  215. QuantNodes/factor_node/factor_db.py +421 -0
  216. QuantNodes/factor_node/factor_functions/__init__.py +252 -0
  217. QuantNodes/factor_node/factor_functions/_helpers.py +358 -0
  218. QuantNodes/factor_node/factor_functions/_helpers_debug.py +317 -0
  219. QuantNodes/factor_node/factor_functions/composite_ops.py +136 -0
  220. QuantNodes/factor_node/factor_functions/math_ops.py +433 -0
  221. QuantNodes/factor_node/factor_functions/section_ops.py +290 -0
  222. QuantNodes/factor_node/factor_functions/talib_ops.py +1293 -0
  223. QuantNodes/factor_node/factor_functions/time_ops.py +535 -0
  224. QuantNodes/factor_node/factor_operation.py +1115 -0
  225. QuantNodes/factor_node/factor_table.py +1073 -0
  226. QuantNodes/factor_node/quant_nodes_object.py +60 -0
  227. QuantNodes/mcp_server/__init__.py +27 -0
  228. QuantNodes/mcp_server/__main__.py +4 -0
  229. QuantNodes/mcp_server/server.py +272 -0
  230. QuantNodes/methods/__init__.py +28 -0
  231. QuantNodes/methods/pipeline.py +100 -0
  232. QuantNodes/methods/sandbox.py +102 -0
  233. QuantNodes/monitor/__init__.py +27 -0
  234. QuantNodes/monitor/agent_tools/__init__.py +5 -0
  235. QuantNodes/monitor/agent_tools/monitor_tool.py +98 -0
  236. QuantNodes/monitor/agent_tools/schedule_tool.py +98 -0
  237. QuantNodes/monitor/agent_tools/version_tool.py +133 -0
  238. QuantNodes/monitor/monitor/__init__.py +6 -0
  239. QuantNodes/monitor/monitor/alerter.py +60 -0
  240. QuantNodes/monitor/monitor/collector.py +164 -0
  241. QuantNodes/monitor/monitor/dashboard.py +115 -0
  242. QuantNodes/monitor/monitor/drift.py +190 -0
  243. QuantNodes/monitor/scheduler/__init__.py +4 -0
  244. QuantNodes/monitor/scheduler/runner.py +133 -0
  245. QuantNodes/monitor/scheduler/scheduler.py +184 -0
  246. QuantNodes/monitor/storage/__init__.py +16 -0
  247. QuantNodes/monitor/storage/models.py +70 -0
  248. QuantNodes/monitor/storage/repository.py +407 -0
  249. QuantNodes/monitor/version/__init__.py +4 -0
  250. QuantNodes/monitor/version/diff.py +81 -0
  251. QuantNodes/monitor/version/version_manager.py +182 -0
  252. QuantNodes/operator_node/__init__.py +28 -0
  253. QuantNodes/operator_node/base.py +97 -0
  254. QuantNodes/operator_node/query_node.py +129 -0
  255. QuantNodes/operator_node/sql_builder.py +125 -0
  256. QuantNodes/operator_node/sql_utils.py +172 -0
  257. QuantNodes/operator_node/transform.py +130 -0
  258. QuantNodes/operators/__init__.py +90 -0
  259. QuantNodes/operators/_engine.py +108 -0
  260. QuantNodes/operators/composite.py +161 -0
  261. QuantNodes/operators/composite_dag.py +667 -0
  262. QuantNodes/operators/composite_dag_ops.py +343 -0
  263. QuantNodes/operators/composite_dag_pandas_ops.py +382 -0
  264. QuantNodes/operators/custom.py +408 -0
  265. QuantNodes/operators/facade.py +164 -0
  266. QuantNodes/operators/math.py +163 -0
  267. QuantNodes/operators/proxy.py +29 -0
  268. QuantNodes/operators/registry.py +144 -0
  269. QuantNodes/operators/section.py +99 -0
  270. QuantNodes/operators/talib.py +757 -0
  271. QuantNodes/operators/templates.py +95 -0
  272. QuantNodes/operators/time_series.py +136 -0
  273. QuantNodes/prompts/__init__.py +20 -0
  274. QuantNodes/prompts/backtest/__init__.py +12 -0
  275. QuantNodes/prompts/backtest/factor_based.py +86 -0
  276. QuantNodes/prompts/backtest/standard.py +73 -0
  277. QuantNodes/prompts/factor/__init__.py +14 -0
  278. QuantNodes/prompts/factor/correlation.py +77 -0
  279. QuantNodes/prompts/factor/group_backtest.py +86 -0
  280. QuantNodes/prompts/factor/ic_analysis.py +91 -0
  281. QuantNodes/prompts/strategy/__init__.py +18 -0
  282. QuantNodes/prompts/strategy/market_neutral.py +96 -0
  283. QuantNodes/prompts/strategy/mean_reversion.py +107 -0
  284. QuantNodes/prompts/strategy/momentum.py +160 -0
  285. QuantNodes/prompts/strategy/pairs_trading.py +107 -0
  286. QuantNodes/prompts/strategy/trend_following.py +96 -0
  287. QuantNodes/research/README.md +106 -0
  288. QuantNodes/research/__init__.py +154 -0
  289. QuantNodes/research/_legacy_3c/__init__.py +61 -0
  290. QuantNodes/research/_legacy_3c/auto_researcher.py +289 -0
  291. QuantNodes/research/_legacy_3c/factor_evaluator.py +560 -0
  292. QuantNodes/research/_legacy_3c/factor_miner.py +318 -0
  293. QuantNodes/research/_legacy_3c/mcts_search.py +324 -0
  294. QuantNodes/research/factor_test/__init__.py +25 -0
  295. QuantNodes/research/factor_test/config.py +184 -0
  296. QuantNodes/research/factor_test/config_builder.py +276 -0
  297. QuantNodes/research/factor_test/e2e/data_prep.py +163 -0
  298. QuantNodes/research/factor_test/e2e/run_evolution_e2e.py +309 -0
  299. QuantNodes/research/factor_test/evolution_adapter.py +231 -0
  300. QuantNodes/research/factor_test/feedback_wrapper.py +102 -0
  301. QuantNodes/research/factor_test/ifind_db/__init__.py +7 -0
  302. QuantNodes/research/factor_test/ifind_db/fetcher.py +224 -0
  303. QuantNodes/research/factor_test/ifind_db/ifind_database.py +689 -0
  304. QuantNodes/research/factor_test/nodes/__init__.py +1 -0
  305. QuantNodes/research/factor_test/nodes/_base.py +91 -0
  306. QuantNodes/research/factor_test/nodes/adjust_date_node.py +48 -0
  307. QuantNodes/research/factor_test/nodes/configs.py +240 -0
  308. QuantNodes/research/factor_test/nodes/factor_neutralize_node.py +87 -0
  309. QuantNodes/research/factor_test/nodes/factor_preprocess_node.py +222 -0
  310. QuantNodes/research/factor_test/nodes/factor_score_node.py +141 -0
  311. QuantNodes/research/factor_test/nodes/factor_test_report_node.py +153 -0
  312. QuantNodes/research/factor_test/nodes/group_analyzer_node.py +317 -0
  313. QuantNodes/research/factor_test/nodes/ic_analyzer_node.py +112 -0
  314. QuantNodes/research/factor_test/nodes/load_data_node.py +100 -0
  315. QuantNodes/research/factor_test/nodes/long_short_node.py +93 -0
  316. QuantNodes/research/factor_test/nodes/neutralizers.py +222 -0
  317. QuantNodes/research/factor_test/nodes/preprocess_strategies.py +277 -0
  318. QuantNodes/research/factor_test/nodes/risk_correlation_node.py +112 -0
  319. QuantNodes/research/factor_test/nodes/sample_pool_filter_node.py +110 -0
  320. QuantNodes/research/factor_test/nodes/tradability_filter_node.py +92 -0
  321. QuantNodes/research/factor_test/pipeline_runner.py +305 -0
  322. QuantNodes/research/factor_test/pipeline_spec.py +216 -0
  323. QuantNodes/research/factor_test/utils/__init__.py +26 -0
  324. QuantNodes/research/factor_test/utils/constants.py +86 -0
  325. QuantNodes/research/factor_test/utils/data_loader.py +141 -0
  326. QuantNodes/research/factor_test/utils/date_utils.py +232 -0
  327. QuantNodes/research/factor_test/utils/file_loaders.py +150 -0
  328. QuantNodes/research/factor_test/utils/labels.py +37 -0
  329. QuantNodes/research/factor_test/utils/metrics_extractor.py +55 -0
  330. QuantNodes/research/factor_test/utils/performance_metrics.py +175 -0
  331. QuantNodes/research/factor_test/utils/safe_load.py +106 -0
  332. QuantNodes/research/quant_alpha/CHANGELOG.md +80 -0
  333. QuantNodes/research/quant_alpha/README.md +142 -0
  334. QuantNodes/research/quant_alpha/__init__.py +45 -0
  335. QuantNodes/research/quant_alpha/adapters/__init__.py +99 -0
  336. QuantNodes/research/quant_alpha/adapters/calculator.py +503 -0
  337. QuantNodes/research/quant_alpha/adapters/expression.py +387 -0
  338. QuantNodes/research/quant_alpha/alpha101_design/__init__.py +50 -0
  339. QuantNodes/research/quant_alpha/alpha101_design/few_shot_examples.py +243 -0
  340. QuantNodes/research/quant_alpha/alpha101_design/philosophy.py +474 -0
  341. QuantNodes/research/quant_alpha/alpha158_design/__init__.py +63 -0
  342. QuantNodes/research/quant_alpha/alpha158_design/few_shot_examples.py +219 -0
  343. QuantNodes/research/quant_alpha/alpha158_design/philosophy.py +240 -0
  344. QuantNodes/research/quant_alpha/evaluation/__init__.py +47 -0
  345. QuantNodes/research/quant_alpha/evaluation/baselines/__init__.py +8 -0
  346. QuantNodes/research/quant_alpha/evaluation/baselines/g1_handcrafted.py +135 -0
  347. QuantNodes/research/quant_alpha/evaluation/baselines/g2_llm_only.py +269 -0
  348. QuantNodes/research/quant_alpha/evaluation/baselines/g3_alpha_gpt.py +152 -0
  349. QuantNodes/research/quant_alpha/evaluation/clickhouse_data_loader.py +227 -0
  350. QuantNodes/research/quant_alpha/evaluation/contracts.py +376 -0
  351. QuantNodes/research/quant_alpha/evaluation/evaluators/__init__.py +6 -0
  352. QuantNodes/research/quant_alpha/evaluation/evaluators/polars_evaluator.py +545 -0
  353. QuantNodes/research/quant_alpha/evaluation/mock_data_loader.py +226 -0
  354. QuantNodes/research/quant_alpha/evaluation/runner.py +243 -0
  355. QuantNodes/research/quant_alpha/llm/__init__.py +38 -0
  356. QuantNodes/research/quant_alpha/llm/parser.py +681 -0
  357. QuantNodes/research/quant_alpha/logic_driven_pipeline.py +411 -0
  358. QuantNodes/research/quant_alpha/logic_mining/__init__.py +74 -0
  359. QuantNodes/research/quant_alpha/logic_mining/compiler.py +457 -0
  360. QuantNodes/research/quant_alpha/logic_mining/generator.py +366 -0
  361. QuantNodes/research/quant_alpha/logic_mining/models.py +252 -0
  362. QuantNodes/research/quant_alpha/logic_mining/parser.py +287 -0
  363. QuantNodes/research/quant_alpha/logic_mining/pipelines.py +297 -0
  364. QuantNodes/research/quant_alpha/logic_mining/sources.py +149 -0
  365. QuantNodes/research/quant_alpha/mcts/__init__.py +66 -0
  366. QuantNodes/research/quant_alpha/mcts/cache.py +262 -0
  367. QuantNodes/research/quant_alpha/mcts/extension_ops.py +320 -0
  368. QuantNodes/research/quant_alpha/mcts/feedback.py +825 -0
  369. QuantNodes/research/quant_alpha/mcts/op_prior.py +180 -0
  370. QuantNodes/research/quant_alpha/mcts/search.py +540 -0
  371. QuantNodes/research/quant_alpha/mcts/tree.py +201 -0
  372. QuantNodes/research/quant_alpha/operator_vocab/__init__.py +50 -0
  373. QuantNodes/research/quant_alpha/operator_vocab/config.py +54 -0
  374. QuantNodes/research/quant_alpha/operator_vocab/metadata.py +263 -0
  375. QuantNodes/research/quant_alpha/operator_vocab/vocabulary.py +481 -0
  376. QuantNodes/research/quant_alpha/pipeline.py +1027 -0
  377. QuantNodes/research/quant_alpha/types/__init__.py +27 -0
  378. QuantNodes/research/quant_alpha/types/constants.py +28 -0
  379. QuantNodes/research/quant_alpha/types/state.py +205 -0
  380. QuantNodes/research/quant_alpha/workflow/__init__.py +32 -0
  381. QuantNodes/research/quant_alpha/workflow/alpha_gpt.py +911 -0
  382. QuantNodes/research/quant_alpha/workflow/alpha_logics.py +416 -0
  383. QuantNodes/research/quant_alpha/workflow/state.py +27 -0
  384. QuantNodes/research/report_reproducer.py +485 -0
  385. QuantNodes/research/wiki.py +1155 -0
  386. QuantNodes/symbolic/__init__.py +51 -0
  387. QuantNodes/symbolic/compiler.py +113 -0
  388. QuantNodes/symbolic/dialect.py +260 -0
  389. QuantNodes/symbolic/executor.py +147 -0
  390. QuantNodes/symbolic/expression.py +234 -0
  391. QuantNodes/symbolic/functions.py +433 -0
  392. QuantNodes/symbolic/optimizer.py +165 -0
  393. QuantNodes/ui_node/__init__.py +30 -0
  394. QuantNodes/ui_node/base.py +222 -0
  395. quantnodes-3.0.0.dist-info/METADATA +463 -0
  396. quantnodes-3.0.0.dist-info/RECORD +399 -0
  397. quantnodes-3.0.0.dist-info/WHEEL +5 -0
  398. quantnodes-3.0.0.dist-info/entry_points.txt +24 -0
  399. quantnodes-3.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,563 @@
1
+ # coding=utf-8
2
+ """因子类
3
+
4
+ 包含 Factor(因子基类实现)和 DataFactor(数据因子)
5
+ 以及因子运算符辅助函数。
6
+
7
+ v2.0: 移除 traits 依赖,使用 dataclass 和 Enum
8
+ """
9
+ import gc
10
+ import os
11
+ import shelve
12
+ from enum import Enum
13
+ from typing import Dict
14
+
15
+ import numpy as np
16
+ import pandas as pd
17
+
18
+ from QuantNodes.factor_node.quant_nodes_object import QuantNodesObject
19
+ from QuantNodes.core.base import FactorError
20
+ from QuantNodes.core.tools import (
21
+ partition_list_moving_sampling,
22
+ fill_na_by_lookback as fillNaByLookback,
23
+ )
24
+
25
+
26
+ class DataType(Enum):
27
+ """数据类型枚举"""
28
+ DOUBLE = "double"
29
+ STRING = "string"
30
+ OBJECT = "object"
31
+
32
+
33
+ def Factorize(factor_object, factor_name, args=None, **kwargs):
34
+ """将运算结果转换成真正的可以存储的因子"""
35
+ if args is None:
36
+ args = {}
37
+ factor_object.Name = factor_name
38
+ for iArg, iVal in args.items():
39
+ factor_object[iArg] = iVal
40
+ if "logger" in kwargs:
41
+ factor_object._QN_Logger = kwargs.logger
42
+ return factor_object
43
+
44
+
45
+ def _UnitaryOperator(f, idt, iid, x, args):
46
+ """一元运算符"""
47
+ Fun = args.get("Fun", None)
48
+ if Fun is not None:
49
+ Data = Fun(f, idt, iid, x, args["Arg"])
50
+ else:
51
+ Data = x[0]
52
+ OperatorType = args.get("OperatorType", "neg")
53
+ if OperatorType == "neg":
54
+ return -Data
55
+ elif OperatorType == "abs":
56
+ return np.abs(Data)
57
+ elif OperatorType == "not":
58
+ return (~Data)
59
+ else:
60
+ raise FactorError("尚不支持的单因子运算符: %s" % OperatorType)
61
+
62
+
63
+ def _BinaryOperator(f, idt, iid, x, args):
64
+ """二元运算符"""
65
+ Fun1 = args.get("Fun1", None)
66
+ if Fun1 is not None:
67
+ Data1 = Fun1(f, idt, iid, x[:args["SepInd"]], args["Arg1"])
68
+ else:
69
+ Data1 = args.get("Data1", None)
70
+ if Data1 is None:
71
+ Data1 = x[0]
72
+ Fun2 = args.get("Fun2", None)
73
+ if Fun2 is not None:
74
+ Data2 = Fun2(f, idt, iid, x[args["SepInd"]:], args["Arg2"])
75
+ else:
76
+ Data2 = args.get("Data2", None)
77
+ if Data2 is None:
78
+ Data2 = x[args["SepInd"]]
79
+ OperatorType = args.get("OperatorType", "add")
80
+ if OperatorType == "add":
81
+ return Data1 + Data2
82
+ elif OperatorType == "sub":
83
+ return Data1 - Data2
84
+ elif OperatorType == "mul":
85
+ return Data1 * Data2
86
+ elif OperatorType == "div":
87
+ if np.isscalar(Data2):
88
+ return (Data1 / Data2 if Data2 != 0 else np.empty(Data1.shape) + np.nan)
89
+ Data2[Data2 == 0] = np.nan
90
+ return Data1 / Data2
91
+ elif OperatorType == "floordiv":
92
+ return Data1 // Data2
93
+ elif OperatorType == "mod":
94
+ return Data1 % Data2
95
+ elif OperatorType == "pow":
96
+ if np.isscalar(Data2):
97
+ if Data2 < 0:
98
+ Data1[Data1 == 0] = np.nan
99
+ return Data1 ** Data2
100
+ if np.isscalar(Data1):
101
+ if Data1 == 0:
102
+ Data2[Data2 < 0] = np.nan
103
+ return Data1 ** Data2
104
+ Data1[(Data1 == 0) & (Data2 < 0)] = np.nan
105
+ return Data1 ** Data2
106
+ elif OperatorType == "and":
107
+ return (Data1 & Data2)
108
+ elif OperatorType == "or":
109
+ return (Data1 | Data2)
110
+ elif OperatorType == "xor":
111
+ return (Data1 ^ Data2)
112
+ elif OperatorType == "<":
113
+ return (Data1 < Data2)
114
+ elif OperatorType == "<=":
115
+ return (Data1 <= Data2)
116
+ elif OperatorType == ">":
117
+ return (Data1 > Data2)
118
+ elif OperatorType == ">=":
119
+ return (Data1 >= Data2)
120
+ elif OperatorType == "==":
121
+ return (Data1 == Data2)
122
+ elif OperatorType == "!=":
123
+ return (Data1 != Data2)
124
+ else:
125
+ raise FactorError("尚不支持的多因子运算符: %s" % OperatorType)
126
+
127
+
128
+ class Factor(QuantNodesObject):
129
+ """因子
130
+
131
+ 因子可看做一个 DataFrame(index=[时间点], columns=[ID])。
132
+ 时间点数据类型是 datetime.datetime,ID 的数据类型是 str。
133
+ """
134
+ data_type: DataType = DataType.DOUBLE
135
+
136
+ def __init__(self, name: str, ft=None, sys_args: dict = None, config_file: str = None, **kwargs):
137
+ self._FactorTable = ft
138
+ self._NameInFT = name
139
+ self.name = name
140
+ self._isStarted = False
141
+ self._CacheData = None
142
+ self._OperationMode = None
143
+ self._RawDataFile = ""
144
+ self._isCacheDataOK = False
145
+ self.UserData = {}
146
+ self._Args = sys_args or {}
147
+ super().__init__(name=name, config=sys_args or {})
148
+
149
+ @property
150
+ def Args(self) -> Dict:
151
+ """获取参数"""
152
+ return self.get_config('args', {})
153
+
154
+ @property
155
+ def FactorTable(self):
156
+ return self._FactorTable
157
+
158
+ @property
159
+ def Descriptors(self):
160
+ return []
161
+
162
+ def getMetaData(self, key=None, args=None):
163
+ if args is None:
164
+ args = {}
165
+ Args = self.Args
166
+ Args.update(args)
167
+ return self._FactorTable.getFactorMetaData(factor_names=[self._NameInFT], key=key, args=Args).loc[
168
+ self._NameInFT]
169
+
170
+ def getID(self, idt=None):
171
+ if (self._OperationMode is not None) and (self._OperationMode._isStarted):
172
+ return self._OperationMode.IDs
173
+ if self._FactorTable is not None:
174
+ return self._FactorTable.getID(ifactor_name=self._NameInFT, idt=idt, args=self.Args)
175
+ return []
176
+
177
+ def getDateTime(self, iid=None, start_dt=None, end_dt=None):
178
+ if (self._OperationMode is not None) and (self._OperationMode._isStarted):
179
+ return self._OperationMode.DateTimes
180
+ if self._FactorTable is not None:
181
+ return self._FactorTable.getDateTime(ifactor_name=self._NameInFT, iid=iid,
182
+ start_dt=start_dt, end_dt=end_dt, args=self.Args)
183
+ return []
184
+
185
+ def readData(self, ids, dts, **kwargs):
186
+ if not self._isStarted:
187
+ return self._FactorTable.readData(
188
+ factor_names=[self._NameInFT], ids=ids, dts=dts, args=self.Args
189
+ ).loc[self._NameInFT]
190
+ if self._CacheData is None:
191
+ self._CacheData = self._FactorTable.readData(
192
+ factor_names=[self._NameInFT], ids=ids, dts=dts, args=self.Args
193
+ ).loc[self._NameInFT]
194
+ return self._CacheData
195
+ NewDTs = sorted(set(dts).difference(self._CacheData.index))
196
+ if NewDTs:
197
+ NewCacheData = self._FactorTable.readData(
198
+ factor_names=[self._NameInFT],
199
+ ids=self._CacheData.columns.tolist(),
200
+ dts=NewDTs,
201
+ args=self.Args,
202
+ ).loc[self._NameInFT]
203
+ self._CacheData = pd.concat([self._CacheData, NewCacheData]).loc[dts]
204
+ NewIDs = sorted(set(ids).difference(self._CacheData.columns))
205
+ if NewIDs:
206
+ NewCacheData = self._FactorTable.readData(
207
+ factor_names=[self._NameInFT],
208
+ ids=NewIDs,
209
+ dts=self._CacheData.index.tolist(),
210
+ args=self.Args,
211
+ ).loc[self._NameInFT]
212
+ self._CacheData = pd.merge(self._CacheData, NewCacheData, left_index=True, right_index=True)
213
+ return self._CacheData.loc[dts, ids]
214
+
215
+ def _QN_init_operation(self, start_dt, dt_dict, prepare_ids, id_dict):
216
+ OldStartDT = dt_dict.get(self.Name, start_dt)
217
+ dt_dict[self.Name] = start_dt if start_dt < OldStartDT else OldStartDT
218
+ PrepareIDs = id_dict.setdefault(self.Name, prepare_ids)
219
+ if prepare_ids != PrepareIDs:
220
+ raise FactorError("因子 %s 指定了不同的截面!" % self.Name)
221
+
222
+ def __QN_prepare_cache_data__(self, ids=None):
223
+ StartDT = self._OperationMode._FactorStartDT[self.Name]
224
+ EndDT = self._OperationMode.DateTimes[-1]
225
+ StartInd, EndInd = self._OperationMode.DTRuler.index(StartDT), self._OperationMode.DTRuler.index(EndDT)
226
+ DTs = self._OperationMode.DTRuler[StartInd:EndInd + 1]
227
+ RawDataFilePath = self._OperationMode._RawDataDir + os.sep + self._OperationMode._iPID + os.sep + self._RawDataFile
228
+ if os.path.isfile(RawDataFilePath + self._OperationMode._FileSuffix):
229
+ with shelve.open(RawDataFilePath, "r") as File:
230
+ PrepareIDs = File["_QN_IDs"]
231
+ if self._NameInFT in File:
232
+ RawData = File[self._NameInFT]
233
+ elif "RawData" in File:
234
+ RawData = File["RawData"]
235
+ else:
236
+ RawData = None
237
+ if PrepareIDs is None:
238
+ PrepareIDs = self._OperationMode._PID_IDs[self._OperationMode._iPID]
239
+ if RawData is not None:
240
+ StdData = self._FactorTable.__QN_calc_data__(
241
+ RawData, factor_names=[self._NameInFT], ids=PrepareIDs, dts=DTs, args=self.Args
242
+ ).iloc[0]
243
+ else:
244
+ StdData = self._FactorTable.readData(
245
+ factor_names=[self._NameInFT], ids=PrepareIDs, dts=DTs, args=self.Args
246
+ ).iloc[0]
247
+ else:
248
+ PrepareIDs = self._OperationMode._FactorPrepareIDs[self.Name]
249
+ if PrepareIDs is None:
250
+ PrepareIDs = self._OperationMode._PID_IDs[self._OperationMode._iPID]
251
+ else:
252
+ PrepareIDs = partition_list_moving_sampling(PrepareIDs, len(self._OperationMode._PID_IDs))[
253
+ self._OperationMode._PIDs.index(self._OperationMode._iPID)]
254
+ StdData = self._FactorTable.readData(
255
+ factor_names=[self._NameInFT], ids=PrepareIDs, dts=DTs, args=self.Args
256
+ ).iloc[0]
257
+ with self._OperationMode._PID_Lock[self._OperationMode._iPID]:
258
+ with shelve.open(
259
+ self._OperationMode._CacheDataDir + os.sep + self._OperationMode._iPID + os.sep + self.Name + str(
260
+ self._OperationMode._FactorID[self.Name])) as CacheFile:
261
+ CacheFile["StdData"] = StdData
262
+ CacheFile["_QN_IDs"] = PrepareIDs
263
+ self._isCacheDataOK = True
264
+ return StdData
265
+
266
+ def _QN_get_data(self, dts, pids=None, **kwargs):
267
+ if pids is None:
268
+ pids = set(self._OperationMode._PID_IDs)
269
+ AllPID = True
270
+ else:
271
+ pids = set(pids)
272
+ AllPID = False
273
+ if not self._isCacheDataOK:
274
+ StdData = self.__QN_prepare_cache_data__()
275
+ if (StdData is not None) and (self._OperationMode._iPID in pids):
276
+ pids.remove(self._OperationMode._iPID)
277
+ else:
278
+ StdData = None
279
+ else:
280
+ StdData = None
281
+ while len(pids) > 0:
282
+ iPID = pids.pop()
283
+ iFilePath = self._OperationMode._CacheDataDir + os.sep + iPID + os.sep + self.Name + str(
284
+ self._OperationMode._FactorID[self.Name])
285
+ if not os.path.isfile(iFilePath + self._OperationMode._FileSuffix):
286
+ pids.add(iPID)
287
+ continue
288
+ with self._OperationMode._PID_Lock[iPID]:
289
+ with shelve.open(iFilePath, 'r') as CacheFile:
290
+ iStdData = CacheFile["StdData"]
291
+ if StdData is None:
292
+ StdData = iStdData
293
+ else:
294
+ StdData = pd.merge(StdData, iStdData, how='inner', left_index=True, right_index=True)
295
+ if not AllPID:
296
+ StdData = StdData.loc[list(dts), :]
297
+ elif self._OperationMode._FactorPrepareIDs[self.Name] is None:
298
+ StdData = StdData.loc[list(dts), self._OperationMode.IDs]
299
+ else:
300
+ StdData = StdData.loc[list(dts), self._OperationMode._FactorPrepareIDs[self.Name]]
301
+ gc.collect()
302
+ return StdData
303
+
304
+ def _exit(self):
305
+ self._OperationMode = None
306
+ self._RawDataFile = ""
307
+ self._isCacheDataOK = False
308
+
309
+ def start(self, dts, **kwargs):
310
+ self._isStarted = True
311
+ return 0
312
+
313
+ def end(self):
314
+ self._CacheData = None
315
+ self._isStarted = False
316
+ return 0
317
+
318
+ def _genUnitaryOperatorInfo(self):
319
+ if self.Name == "":
320
+ Args = {"Fun": self.Operator, "Arg": self.ModelArgs}
321
+ return (self.Descriptors, Args)
322
+ else:
323
+ return ([self], {})
324
+
325
+ def _genBinaryOperatorInfo(self, other):
326
+ if isinstance(other, Factor):
327
+ if (self.Name == "") and (other.Name == ""):
328
+ Args = {"Fun1": self.Operator, "Fun2": other.Operator, "SepInd": len(self.Descriptors),
329
+ "Arg1": self.ModelArgs, "Arg2": other.ModelArgs}
330
+ return (self.Descriptors + other.Descriptors, Args)
331
+ elif self.Name == "":
332
+ Args = {"Fun1": self.Operator, "SepInd": len(self.Descriptors), "Arg1": self.ModelArgs}
333
+ return (self.Descriptors + [other], Args)
334
+ elif other.Name == "":
335
+ Args = {"Fun2": other.Operator, "SepInd": 1, "Arg2": other.ModelArgs}
336
+ return ([self] + other.Descriptors, Args)
337
+ else:
338
+ Args = {"SepInd": 1}
339
+ return ([self, other], Args)
340
+ elif self.Name == "":
341
+ Args = {"Fun1": self.Operator, "SepInd": len(self.Descriptors), "Data2": other, "Arg1": self.ModelArgs}
342
+ return (self.Descriptors, Args)
343
+ else:
344
+ Args = {"SepInd": 1, "Data2": other}
345
+ return ([self], Args)
346
+
347
+ def _genRBinaryOperatorInfo(self, other):
348
+ if self.Name == "":
349
+ Args = {"Fun2": self.Operator, "SepInd": 0, "Data1": other, "Arg2": self.ModelArgs}
350
+ return (self.Descriptors, Args)
351
+ else:
352
+ Args = {"SepInd": 0, "Data1": other}
353
+ return ([self], Args)
354
+
355
+ def _binary_op(self, other, op_type, is_reverse=False):
356
+ from QuantNodes.factor_node.factor_operation import PointOperation
357
+ if is_reverse:
358
+ Descriptors, Args = self._genRBinaryOperatorInfo(other)
359
+ else:
360
+ Descriptors, Args = self._genBinaryOperatorInfo(other)
361
+ Args["OperatorType"] = op_type
362
+ return PointOperation("", Descriptors,
363
+ {"算子": _BinaryOperator, "参数": Args, "运算时点": "多时点", "运算ID": "多ID"},
364
+ logger=self._QN_Logger)
365
+
366
+ def __add__(self, other):
367
+ return self._binary_op(other, "add", is_reverse=False)
368
+
369
+ def __radd__(self, other):
370
+ return self._binary_op(other, "add", is_reverse=True)
371
+
372
+ def __sub__(self, other):
373
+ return self._binary_op(other, "sub", is_reverse=False)
374
+
375
+ def __rsub__(self, other):
376
+ return self._binary_op(other, "sub", is_reverse=True)
377
+
378
+ def __mul__(self, other):
379
+ return self._binary_op(other, "mul", is_reverse=False)
380
+
381
+ def __rmul__(self, other):
382
+ return self._binary_op(other, "mul", is_reverse=True)
383
+
384
+ def __pow__(self, other):
385
+ return self._binary_op(other, "pow", is_reverse=False)
386
+
387
+ def __rpow__(self, other):
388
+ return self._binary_op(other, "pow", is_reverse=True)
389
+
390
+ def __truediv__(self, other):
391
+ return self._binary_op(other, "div", is_reverse=False)
392
+
393
+ def __rtruediv__(self, other):
394
+ return self._binary_op(other, "div", is_reverse=True)
395
+
396
+ def __floordiv__(self, other):
397
+ return self._binary_op(other, "floordiv", is_reverse=False)
398
+
399
+ def __rfloordiv__(self, other):
400
+ return self._binary_op(other, "floordiv", is_reverse=True)
401
+
402
+ def __mod__(self, other):
403
+ return self._binary_op(other, "mod", is_reverse=False)
404
+
405
+ def __rmod__(self, other):
406
+ return self._binary_op(other, "mod", is_reverse=True)
407
+
408
+ def __and__(self, other):
409
+ return self._binary_op(other, "and", is_reverse=False)
410
+
411
+ def __rand__(self, other):
412
+ return self._binary_op(other, "and", is_reverse=True)
413
+
414
+ def __or__(self, other):
415
+ return self._binary_op(other, "or", is_reverse=False)
416
+
417
+ def __ror__(self, other):
418
+ return self._binary_op(other, "or", is_reverse=True)
419
+
420
+ def __xor__(self, other):
421
+ return self._binary_op(other, "xor", is_reverse=False)
422
+
423
+ def __rxor__(self, other):
424
+ return self._binary_op(other, "xor", is_reverse=True)
425
+
426
+ def __lt__(self, other):
427
+ return self._binary_op(other, "<", is_reverse=False)
428
+
429
+ def __le__(self, other):
430
+ return self._binary_op(other, "<=", is_reverse=False)
431
+
432
+ def __eq__(self, other):
433
+ return self._binary_op(other, "==", is_reverse=False)
434
+
435
+ def __ne__(self, other):
436
+ return self._binary_op(other, "!=", is_reverse=False)
437
+
438
+ def __gt__(self, other):
439
+ return self._binary_op(other, ">", is_reverse=False)
440
+
441
+ def __ge__(self, other):
442
+ return self._binary_op(other, ">=", is_reverse=False)
443
+
444
+ def _unary_op(self, op_type):
445
+ from QuantNodes.factor_node.factor_operation import PointOperation
446
+ Descriptors, Args = self._genUnitaryOperatorInfo()
447
+ Args["OperatorType"] = op_type
448
+ return PointOperation("", Descriptors,
449
+ {"算子": _UnitaryOperator, "参数": Args, "运算时点": "多时点", "运算ID": "多ID"},
450
+ logger=self._QN_Logger)
451
+
452
+ def __neg__(self):
453
+ return self._unary_op("neg")
454
+
455
+ def __pos__(self):
456
+ return self
457
+
458
+ def __abs__(self):
459
+ return self._unary_op("abs")
460
+
461
+ def __invert__(self):
462
+ return self._unary_op("not")
463
+
464
+
465
+ class DataFactor(Factor):
466
+ """直接赋予数据产生的因子"""
467
+ LookBack: int = 0
468
+
469
+ def __init__(self, name: str, data, sys_args: dict = None, config_file: str = None, **kwargs):
470
+ if sys_args is None:
471
+ sys_args = {}
472
+
473
+ def _detect_dtype(val):
474
+ """Detect if value can be cast to float, set '数据类型' accordingly."""
475
+ try:
476
+ float(val)
477
+ except (ValueError, TypeError):
478
+ sys_args["数据类型"] = "object"
479
+ else:
480
+ sys_args["数据类型"] = "double"
481
+
482
+ if isinstance(data, pd.Series):
483
+ if data.index.is_all_dates:
484
+ self._DataContent = "DateTime"
485
+ else:
486
+ self._DataContent = "ID"
487
+ if "数据类型" not in sys_args:
488
+ _detect_dtype(data)
489
+ elif isinstance(data, pd.DataFrame):
490
+ self._DataContent = "Factor"
491
+ if "数据类型" not in sys_args:
492
+ _detect_dtype(data)
493
+ else:
494
+ self._DataContent = "Value"
495
+ if "数据类型" not in sys_args:
496
+ if isinstance(data, str):
497
+ sys_args["数据类型"] = "string"
498
+ else:
499
+ _detect_dtype(data)
500
+ self._Data = data
501
+ return super().__init__(name=name, ft=None, sys_args=sys_args, config_file=None, **kwargs)
502
+
503
+ def getMetaData(self, key=None, args=None):
504
+ if args is None:
505
+ args = {}
506
+ DataType = args.get("数据类型", self.DataType)
507
+ if key is None:
508
+ return pd.Series({"DataType": DataType})
509
+ elif key == "DataType":
510
+ return DataType
511
+ return None
512
+
513
+ def getID(self, idt=None):
514
+ if (self._OperationMode is not None) and (self._OperationMode._isStarted):
515
+ return self._OperationMode.IDs
516
+ if self._DataContent == "Factor":
517
+ return self._Data.columns.tolist()
518
+ elif self._DataContent == "ID":
519
+ return self._Data.index.tolist()
520
+ else:
521
+ return []
522
+
523
+ def getDateTime(self, iid=None, start_dt=None, end_dt=None):
524
+ if (self._OperationMode is not None) and (self._OperationMode._isStarted):
525
+ return self._OperationMode.DateTimes
526
+ if self._DataContent in ("DateTime", "Factor"):
527
+ return self._Data.index.tolist()
528
+ else:
529
+ return []
530
+
531
+ def readData(self, ids, dts, **kwargs):
532
+ if self._DataContent == "Value":
533
+ return pd.DataFrame([(self._Data,) * len(ids)] * len(dts), index=dts, columns=ids)
534
+ elif self._DataContent == "ID":
535
+ Data = pd.DataFrame(self._Data.values.reshape((1, self._Data.shape[0])).repeat(len(dts), axis=0), index=dts,
536
+ columns=self._Data.index)
537
+ elif self._DataContent == "DateTime":
538
+ Data = pd.DataFrame(self._Data.values.reshape((self._Data.shape[0], 1)).repeat(len(ids), axis=1),
539
+ index=self._Data.index, columns=ids)
540
+ else:
541
+ Data = self._Data
542
+ if (Data.columns.intersection(ids).shape[0] == 0) or (Data.index.intersection(dts).shape[0] == 0):
543
+ return pd.DataFrame(index=dts, columns=ids, dtype=("O" if self.DataType != "double" else float))
544
+ if self.LookBack == 0:
545
+ return Data.loc[dts, ids]
546
+ else:
547
+ return fillNaByLookback(Data.loc[sorted(Data.index.union(dts)), ids],
548
+ lookback=self.LookBack * 24.0 * 3600).loc[dts, :]
549
+
550
+ def __QN_prepare_cache_data__(self, ids=None):
551
+ return self._Data
552
+
553
+ def _QN_get_data(self, dts, pids=None, **kwargs):
554
+ IDs = kwargs.get("ids", None)
555
+ if IDs is None:
556
+ if pids is None:
557
+ IDs = list(self._OperationMode.IDs)
558
+ else:
559
+ IDs = []
560
+ for iPID in pids:
561
+ IDs.extend(self._OperationMode._PID_IDs[iPID])
562
+ dts = list(dts)
563
+ return self.readData(sorted(IDs), dts)