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.
- QuantNodes/__init__.py +15 -0
- QuantNodes/__main__.py +14 -0
- QuantNodes/agent/__init__.py +158 -0
- QuantNodes/agent/agents/__init__.py +13 -0
- QuantNodes/agent/agents/definition.py +180 -0
- QuantNodes/agent/agents/manager.py +73 -0
- QuantNodes/agent/config/__init__.py +34 -0
- QuantNodes/agent/config/executor.py +958 -0
- QuantNodes/agent/config/loader.py +427 -0
- QuantNodes/agent/config/templates/bollinger_bands.yaml +84 -0
- QuantNodes/agent/config/templates/dual_ma.yaml +72 -0
- QuantNodes/agent/config/templates/empty.yaml +56 -0
- QuantNodes/agent/config/templates/mean_reversion.yaml +47 -0
- QuantNodes/agent/config/templates/mean_reversion_zscore.yaml +90 -0
- QuantNodes/agent/config/templates/momentum.yaml +81 -0
- QuantNodes/agent/config/templates/momentum_breakout.yaml +84 -0
- QuantNodes/agent/config/templates/rsi_strategy.yaml +72 -0
- QuantNodes/agent/config/templates/volume_price.yaml +86 -0
- QuantNodes/agent/config/types.py +156 -0
- QuantNodes/agent/config_mapper.py +293 -0
- QuantNodes/agent/core/__init__.py +19 -0
- QuantNodes/agent/core/dream.py +47 -0
- QuantNodes/agent/core/quant_dream.py +274 -0
- QuantNodes/agent/cron_jobs.py +314 -0
- QuantNodes/agent/nanobot_bridge.py +242 -0
- QuantNodes/agent/permission/__init__.py +30 -0
- QuantNodes/agent/permission/defaults.py +36 -0
- QuantNodes/agent/permission/evaluate.py +41 -0
- QuantNodes/agent/permission/models.py +59 -0
- QuantNodes/agent/permission/service.py +133 -0
- QuantNodes/agent/providers/__init__.py +11 -0
- QuantNodes/agent/providers/base.py +102 -0
- QuantNodes/agent/providers/quantnodes.py +610 -0
- QuantNodes/agent/providers/rate_limiter.py +326 -0
- QuantNodes/agent/providers/registry.py +163 -0
- QuantNodes/agent/skills/__init__.py +20 -0
- QuantNodes/agent/skills/base.py +118 -0
- QuantNodes/agent/skills/bridge.py +73 -0
- QuantNodes/agent/skills/factor/__init__.py +14 -0
- QuantNodes/agent/skills/factor/correlation.py +99 -0
- QuantNodes/agent/skills/factor/group_backtest.py +114 -0
- QuantNodes/agent/skills/factor/ic_analysis.py +106 -0
- QuantNodes/agent/skills/loader.py +107 -0
- QuantNodes/agent/skills/registry.py +105 -0
- QuantNodes/agent/skills/strategy/__init__.py +16 -0
- QuantNodes/agent/skills/strategy/bollinger.py +86 -0
- QuantNodes/agent/skills/strategy/dual_ma.py +82 -0
- QuantNodes/agent/skills/strategy/momentum.py +74 -0
- QuantNodes/agent/skills/strategy/rsi_reversal.py +99 -0
- QuantNodes/agent/skills_quant/__init__.py +14 -0
- QuantNodes/agent/skills_quant/backtest-analyze/SKILL.md +42 -0
- QuantNodes/agent/skills_quant/config-driven/SKILL.md +72 -0
- QuantNodes/agent/skills_quant/factor-research/SKILL.md +40 -0
- QuantNodes/agent/skills_quant/quant-dream/SKILL.md +55 -0
- QuantNodes/agent/skills_quant/risk-management/SKILL.md +45 -0
- QuantNodes/agent/skills_quant/strategy-design/SKILL.md +43 -0
- QuantNodes/agent/templates/__init__.py +4 -0
- QuantNodes/agent/tools/__init__.py +173 -0
- QuantNodes/agent/tools/_workspace.py +51 -0
- QuantNodes/agent/tools/alpha_backtest.py +328 -0
- QuantNodes/agent/tools/alpha_evaluate.py +493 -0
- QuantNodes/agent/tools/backtest.py +226 -0
- QuantNodes/agent/tools/base.py +133 -0
- QuantNodes/agent/tools/code_search.py +207 -0
- QuantNodes/agent/tools/config_backtest.py +401 -0
- QuantNodes/agent/tools/context.py +97 -0
- QuantNodes/agent/tools/dream_skill.py +77 -0
- QuantNodes/agent/tools/echo.py +38 -0
- QuantNodes/agent/tools/factor.py +231 -0
- QuantNodes/agent/tools/file_ops.py +201 -0
- QuantNodes/agent/tools/git_ops.py +190 -0
- QuantNodes/agent/tools/operator_lookup.py +218 -0
- QuantNodes/agent/tools/output_truncation.py +77 -0
- QuantNodes/agent/tools/path_check.py +43 -0
- QuantNodes/agent/tools/pipeline.py +62 -0
- QuantNodes/agent/tools/registry.py +150 -0
- QuantNodes/agent/tools/sandbox.py +62 -0
- QuantNodes/agent/tools/shell_safety.py +63 -0
- QuantNodes/agent/tools/strategy.py +106 -0
- QuantNodes/agent/tools/task.py +171 -0
- QuantNodes/agent/tools/web_fetch.py +142 -0
- QuantNodes/agent/tools/web_search.py +114 -0
- QuantNodes/agent/tools/wiki.py +370 -0
- QuantNodes/agent/utils/__init__.py +11 -0
- QuantNodes/agent/utils/helpers.py +43 -0
- QuantNodes/agent/utils/prompt_templates.py +30 -0
- QuantNodes/agent/workflows/__init__.py +20 -0
- QuantNodes/agent/workflows/implementations/__init__.py +8 -0
- QuantNodes/agent/workflows/implementations/alpha_gpt.py +508 -0
- QuantNodes/agent/workflows/implementations/mcts.py +442 -0
- QuantNodes/agent/workflows/parsers.py +44 -0
- QuantNodes/agent/workflows/registry.py +119 -0
- QuantNodes/agent/workflows/step_agent.py +219 -0
- QuantNodes/agent/workflows/tool.py +198 -0
- QuantNodes/ai/__init__.py +93 -0
- QuantNodes/ai/llm/__init__.py +75 -0
- QuantNodes/ai/llm/base.py +233 -0
- QuantNodes/ai/llm/decorators.py +281 -0
- QuantNodes/ai/llm/gateway.py +571 -0
- QuantNodes/ai/llm/null.py +76 -0
- QuantNodes/ai/llm/openai.py +435 -0
- QuantNodes/ai/optimizer.py +405 -0
- QuantNodes/ai/prompts/__init__.py +229 -0
- QuantNodes/ai/sandbox.py +371 -0
- QuantNodes/ai/sandbox_pandas_bridge.py +150 -0
- QuantNodes/ai/strategy_gen.py +396 -0
- QuantNodes/backtest/__init__.py +64 -0
- QuantNodes/backtest/backtest_node.py +188 -0
- QuantNodes/backtest/broker_node.py +378 -0
- QuantNodes/backtest/config_runner.py +397 -0
- QuantNodes/backtest/config_strategy.py +64 -0
- QuantNodes/backtest/risk_node.py +360 -0
- QuantNodes/backtest/strategy_node.py +268 -0
- QuantNodes/cache_node/__init__.py +19 -0
- QuantNodes/cache_node/base.py +244 -0
- QuantNodes/cache_node/cache_store.py +99 -0
- QuantNodes/cache_node/metadata.py +100 -0
- QuantNodes/cli/__init__.py +109 -0
- QuantNodes/cli/_helpers.py +511 -0
- QuantNodes/cli/command.py +110 -0
- QuantNodes/cli/commands/__init__.py +69 -0
- QuantNodes/cli/commands/agent.py +158 -0
- QuantNodes/cli/commands/alpha.py +951 -0
- QuantNodes/cli/commands/chat.py +38 -0
- QuantNodes/cli/commands/evolve.py +120 -0
- QuantNodes/cli/commands/factor.py +569 -0
- QuantNodes/cli/commands/init.py +190 -0
- QuantNodes/cli/commands/run.py +259 -0
- QuantNodes/cli/commands/serve.py +398 -0
- QuantNodes/cli/commands/version.py +120 -0
- QuantNodes/cli/enhanced.py +146 -0
- QuantNodes/conf_node/__init__.py +37 -0
- QuantNodes/conf_node/base.py +120 -0
- QuantNodes/conf_node/env_config.py +132 -0
- QuantNodes/conf_node/ini_config.py +70 -0
- QuantNodes/conf_node/json_config.py +69 -0
- QuantNodes/conf_node/yaml_config.py +78 -0
- QuantNodes/constants.py +17 -0
- QuantNodes/core/__init__.py +196 -0
- QuantNodes/core/_lookback_helpers.py +49 -0
- QuantNodes/core/ast_parser.py +198 -0
- QuantNodes/core/base.py +61 -0
- QuantNodes/core/cache_manager.py +344 -0
- QuantNodes/core/cache_utils.py +150 -0
- QuantNodes/core/cond_builder.py +53 -0
- QuantNodes/core/config.py +170 -0
- QuantNodes/core/constants.py +48 -0
- QuantNodes/core/control.py +412 -0
- QuantNodes/core/data_preprocessing.py +453 -0
- QuantNodes/core/data_source.py +46 -0
- QuantNodes/core/events.py +178 -0
- QuantNodes/core/evolution/__init__.py +22 -0
- QuantNodes/core/evolution/loop.py +583 -0
- QuantNodes/core/evolution/operators.py +289 -0
- QuantNodes/core/evolution/settings.py +44 -0
- QuantNodes/core/expression.py +841 -0
- QuantNodes/core/feedback/__init__.py +38 -0
- QuantNodes/core/feedback/channels.py +182 -0
- QuantNodes/core/feedback/collector.py +91 -0
- QuantNodes/core/feedback/dataclass.py +239 -0
- QuantNodes/core/feedback/llm_judge.py +138 -0
- QuantNodes/core/knowledge/__init__.py +69 -0
- QuantNodes/core/knowledge/knowledge_base.py +217 -0
- QuantNodes/core/knowledge/lineage_compress.py +196 -0
- QuantNodes/core/knowledge/lineage_expand.py +123 -0
- QuantNodes/core/knowledge/metrics/__init__.py +43 -0
- QuantNodes/core/knowledge/metrics/evaluator.py +176 -0
- QuantNodes/core/knowledge/metrics/metrics.py +220 -0
- QuantNodes/core/knowledge/rag_prompt.py +196 -0
- QuantNodes/core/knowledge/retriever.py +209 -0
- QuantNodes/core/lambda_node.py +81 -0
- QuantNodes/core/monitoring/__init__.py +22 -0
- QuantNodes/core/monitoring/collector.py +292 -0
- QuantNodes/core/monitoring/dashboard.py +365 -0
- QuantNodes/core/node.py +375 -0
- QuantNodes/core/pandas_utils.py +504 -0
- QuantNodes/core/parallel/__init__.py +15 -0
- QuantNodes/core/parallel/worker.py +140 -0
- QuantNodes/core/parallel/worker_process.py +265 -0
- QuantNodes/core/path_utils.py +73 -0
- QuantNodes/core/pipeline.py +328 -0
- QuantNodes/core/plugin.py +135 -0
- QuantNodes/core/quality_gate/__init__.py +32 -0
- QuantNodes/core/quality_gate/complexity.py +94 -0
- QuantNodes/core/quality_gate/consistency.py +26 -0
- QuantNodes/core/quality_gate/node.py +97 -0
- QuantNodes/core/quality_gate/redundancy.py +51 -0
- QuantNodes/core/quality_gate/settings.py +43 -0
- QuantNodes/core/quality_gate/zoo.py +98 -0
- QuantNodes/core/serializable.py +116 -0
- QuantNodes/core/serialization.py +673 -0
- QuantNodes/core/tools.py +333 -0
- QuantNodes/core/trajectory/__init__.py +25 -0
- QuantNodes/core/trajectory/entry.py +116 -0
- QuantNodes/core/trajectory/lineage.py +67 -0
- QuantNodes/core/trajectory/pool.py +211 -0
- QuantNodes/core/trajectory/selector.py +140 -0
- QuantNodes/core/visualization/__init__.py +33 -0
- QuantNodes/core/visualization/builder.py +233 -0
- QuantNodes/core/visualization/gate_breakdown.py +140 -0
- QuantNodes/core/visualization/lineage_dag.py +203 -0
- QuantNodes/core/visualization/metric_distribution.py +125 -0
- QuantNodes/core/visualization/report.py +68 -0
- QuantNodes/database_node/__init__.py +69 -0
- QuantNodes/database_node/base.py +135 -0
- QuantNodes/database_node/clickhouse_node.py +272 -0
- QuantNodes/database_node/csv_node.py +83 -0
- QuantNodes/database_node/duckdb_node.py +86 -0
- QuantNodes/database_node/factory.py +83 -0
- QuantNodes/database_node/mysql_node.py +100 -0
- QuantNodes/database_node/parquet_node.py +75 -0
- QuantNodes/database_node/sqlite_node.py +67 -0
- QuantNodes/factor_node/__init__.py +50 -0
- QuantNodes/factor_node/factor.py +563 -0
- QuantNodes/factor_node/factor_db.py +421 -0
- QuantNodes/factor_node/factor_functions/__init__.py +252 -0
- QuantNodes/factor_node/factor_functions/_helpers.py +358 -0
- QuantNodes/factor_node/factor_functions/_helpers_debug.py +317 -0
- QuantNodes/factor_node/factor_functions/composite_ops.py +136 -0
- QuantNodes/factor_node/factor_functions/math_ops.py +433 -0
- QuantNodes/factor_node/factor_functions/section_ops.py +290 -0
- QuantNodes/factor_node/factor_functions/talib_ops.py +1293 -0
- QuantNodes/factor_node/factor_functions/time_ops.py +535 -0
- QuantNodes/factor_node/factor_operation.py +1115 -0
- QuantNodes/factor_node/factor_table.py +1073 -0
- QuantNodes/factor_node/quant_nodes_object.py +60 -0
- QuantNodes/mcp_server/__init__.py +27 -0
- QuantNodes/mcp_server/__main__.py +4 -0
- QuantNodes/mcp_server/server.py +272 -0
- QuantNodes/methods/__init__.py +28 -0
- QuantNodes/methods/pipeline.py +100 -0
- QuantNodes/methods/sandbox.py +102 -0
- QuantNodes/monitor/__init__.py +27 -0
- QuantNodes/monitor/agent_tools/__init__.py +5 -0
- QuantNodes/monitor/agent_tools/monitor_tool.py +98 -0
- QuantNodes/monitor/agent_tools/schedule_tool.py +98 -0
- QuantNodes/monitor/agent_tools/version_tool.py +133 -0
- QuantNodes/monitor/monitor/__init__.py +6 -0
- QuantNodes/monitor/monitor/alerter.py +60 -0
- QuantNodes/monitor/monitor/collector.py +164 -0
- QuantNodes/monitor/monitor/dashboard.py +115 -0
- QuantNodes/monitor/monitor/drift.py +190 -0
- QuantNodes/monitor/scheduler/__init__.py +4 -0
- QuantNodes/monitor/scheduler/runner.py +133 -0
- QuantNodes/monitor/scheduler/scheduler.py +184 -0
- QuantNodes/monitor/storage/__init__.py +16 -0
- QuantNodes/monitor/storage/models.py +70 -0
- QuantNodes/monitor/storage/repository.py +407 -0
- QuantNodes/monitor/version/__init__.py +4 -0
- QuantNodes/monitor/version/diff.py +81 -0
- QuantNodes/monitor/version/version_manager.py +182 -0
- QuantNodes/operator_node/__init__.py +28 -0
- QuantNodes/operator_node/base.py +97 -0
- QuantNodes/operator_node/query_node.py +129 -0
- QuantNodes/operator_node/sql_builder.py +125 -0
- QuantNodes/operator_node/sql_utils.py +172 -0
- QuantNodes/operator_node/transform.py +130 -0
- QuantNodes/operators/__init__.py +90 -0
- QuantNodes/operators/_engine.py +108 -0
- QuantNodes/operators/composite.py +161 -0
- QuantNodes/operators/composite_dag.py +667 -0
- QuantNodes/operators/composite_dag_ops.py +343 -0
- QuantNodes/operators/composite_dag_pandas_ops.py +382 -0
- QuantNodes/operators/custom.py +408 -0
- QuantNodes/operators/facade.py +164 -0
- QuantNodes/operators/math.py +163 -0
- QuantNodes/operators/proxy.py +29 -0
- QuantNodes/operators/registry.py +144 -0
- QuantNodes/operators/section.py +99 -0
- QuantNodes/operators/talib.py +757 -0
- QuantNodes/operators/templates.py +95 -0
- QuantNodes/operators/time_series.py +136 -0
- QuantNodes/prompts/__init__.py +20 -0
- QuantNodes/prompts/backtest/__init__.py +12 -0
- QuantNodes/prompts/backtest/factor_based.py +86 -0
- QuantNodes/prompts/backtest/standard.py +73 -0
- QuantNodes/prompts/factor/__init__.py +14 -0
- QuantNodes/prompts/factor/correlation.py +77 -0
- QuantNodes/prompts/factor/group_backtest.py +86 -0
- QuantNodes/prompts/factor/ic_analysis.py +91 -0
- QuantNodes/prompts/strategy/__init__.py +18 -0
- QuantNodes/prompts/strategy/market_neutral.py +96 -0
- QuantNodes/prompts/strategy/mean_reversion.py +107 -0
- QuantNodes/prompts/strategy/momentum.py +160 -0
- QuantNodes/prompts/strategy/pairs_trading.py +107 -0
- QuantNodes/prompts/strategy/trend_following.py +96 -0
- QuantNodes/research/README.md +106 -0
- QuantNodes/research/__init__.py +154 -0
- QuantNodes/research/_legacy_3c/__init__.py +61 -0
- QuantNodes/research/_legacy_3c/auto_researcher.py +289 -0
- QuantNodes/research/_legacy_3c/factor_evaluator.py +560 -0
- QuantNodes/research/_legacy_3c/factor_miner.py +318 -0
- QuantNodes/research/_legacy_3c/mcts_search.py +324 -0
- QuantNodes/research/factor_test/__init__.py +25 -0
- QuantNodes/research/factor_test/config.py +184 -0
- QuantNodes/research/factor_test/config_builder.py +276 -0
- QuantNodes/research/factor_test/e2e/data_prep.py +163 -0
- QuantNodes/research/factor_test/e2e/run_evolution_e2e.py +309 -0
- QuantNodes/research/factor_test/evolution_adapter.py +231 -0
- QuantNodes/research/factor_test/feedback_wrapper.py +102 -0
- QuantNodes/research/factor_test/ifind_db/__init__.py +7 -0
- QuantNodes/research/factor_test/ifind_db/fetcher.py +224 -0
- QuantNodes/research/factor_test/ifind_db/ifind_database.py +689 -0
- QuantNodes/research/factor_test/nodes/__init__.py +1 -0
- QuantNodes/research/factor_test/nodes/_base.py +91 -0
- QuantNodes/research/factor_test/nodes/adjust_date_node.py +48 -0
- QuantNodes/research/factor_test/nodes/configs.py +240 -0
- QuantNodes/research/factor_test/nodes/factor_neutralize_node.py +87 -0
- QuantNodes/research/factor_test/nodes/factor_preprocess_node.py +222 -0
- QuantNodes/research/factor_test/nodes/factor_score_node.py +141 -0
- QuantNodes/research/factor_test/nodes/factor_test_report_node.py +153 -0
- QuantNodes/research/factor_test/nodes/group_analyzer_node.py +317 -0
- QuantNodes/research/factor_test/nodes/ic_analyzer_node.py +112 -0
- QuantNodes/research/factor_test/nodes/load_data_node.py +100 -0
- QuantNodes/research/factor_test/nodes/long_short_node.py +93 -0
- QuantNodes/research/factor_test/nodes/neutralizers.py +222 -0
- QuantNodes/research/factor_test/nodes/preprocess_strategies.py +277 -0
- QuantNodes/research/factor_test/nodes/risk_correlation_node.py +112 -0
- QuantNodes/research/factor_test/nodes/sample_pool_filter_node.py +110 -0
- QuantNodes/research/factor_test/nodes/tradability_filter_node.py +92 -0
- QuantNodes/research/factor_test/pipeline_runner.py +305 -0
- QuantNodes/research/factor_test/pipeline_spec.py +216 -0
- QuantNodes/research/factor_test/utils/__init__.py +26 -0
- QuantNodes/research/factor_test/utils/constants.py +86 -0
- QuantNodes/research/factor_test/utils/data_loader.py +141 -0
- QuantNodes/research/factor_test/utils/date_utils.py +232 -0
- QuantNodes/research/factor_test/utils/file_loaders.py +150 -0
- QuantNodes/research/factor_test/utils/labels.py +37 -0
- QuantNodes/research/factor_test/utils/metrics_extractor.py +55 -0
- QuantNodes/research/factor_test/utils/performance_metrics.py +175 -0
- QuantNodes/research/factor_test/utils/safe_load.py +106 -0
- QuantNodes/research/quant_alpha/CHANGELOG.md +80 -0
- QuantNodes/research/quant_alpha/README.md +142 -0
- QuantNodes/research/quant_alpha/__init__.py +45 -0
- QuantNodes/research/quant_alpha/adapters/__init__.py +99 -0
- QuantNodes/research/quant_alpha/adapters/calculator.py +503 -0
- QuantNodes/research/quant_alpha/adapters/expression.py +387 -0
- QuantNodes/research/quant_alpha/alpha101_design/__init__.py +50 -0
- QuantNodes/research/quant_alpha/alpha101_design/few_shot_examples.py +243 -0
- QuantNodes/research/quant_alpha/alpha101_design/philosophy.py +474 -0
- QuantNodes/research/quant_alpha/alpha158_design/__init__.py +63 -0
- QuantNodes/research/quant_alpha/alpha158_design/few_shot_examples.py +219 -0
- QuantNodes/research/quant_alpha/alpha158_design/philosophy.py +240 -0
- QuantNodes/research/quant_alpha/evaluation/__init__.py +47 -0
- QuantNodes/research/quant_alpha/evaluation/baselines/__init__.py +8 -0
- QuantNodes/research/quant_alpha/evaluation/baselines/g1_handcrafted.py +135 -0
- QuantNodes/research/quant_alpha/evaluation/baselines/g2_llm_only.py +269 -0
- QuantNodes/research/quant_alpha/evaluation/baselines/g3_alpha_gpt.py +152 -0
- QuantNodes/research/quant_alpha/evaluation/clickhouse_data_loader.py +227 -0
- QuantNodes/research/quant_alpha/evaluation/contracts.py +376 -0
- QuantNodes/research/quant_alpha/evaluation/evaluators/__init__.py +6 -0
- QuantNodes/research/quant_alpha/evaluation/evaluators/polars_evaluator.py +545 -0
- QuantNodes/research/quant_alpha/evaluation/mock_data_loader.py +226 -0
- QuantNodes/research/quant_alpha/evaluation/runner.py +243 -0
- QuantNodes/research/quant_alpha/llm/__init__.py +38 -0
- QuantNodes/research/quant_alpha/llm/parser.py +681 -0
- QuantNodes/research/quant_alpha/logic_driven_pipeline.py +411 -0
- QuantNodes/research/quant_alpha/logic_mining/__init__.py +74 -0
- QuantNodes/research/quant_alpha/logic_mining/compiler.py +457 -0
- QuantNodes/research/quant_alpha/logic_mining/generator.py +366 -0
- QuantNodes/research/quant_alpha/logic_mining/models.py +252 -0
- QuantNodes/research/quant_alpha/logic_mining/parser.py +287 -0
- QuantNodes/research/quant_alpha/logic_mining/pipelines.py +297 -0
- QuantNodes/research/quant_alpha/logic_mining/sources.py +149 -0
- QuantNodes/research/quant_alpha/mcts/__init__.py +66 -0
- QuantNodes/research/quant_alpha/mcts/cache.py +262 -0
- QuantNodes/research/quant_alpha/mcts/extension_ops.py +320 -0
- QuantNodes/research/quant_alpha/mcts/feedback.py +825 -0
- QuantNodes/research/quant_alpha/mcts/op_prior.py +180 -0
- QuantNodes/research/quant_alpha/mcts/search.py +540 -0
- QuantNodes/research/quant_alpha/mcts/tree.py +201 -0
- QuantNodes/research/quant_alpha/operator_vocab/__init__.py +50 -0
- QuantNodes/research/quant_alpha/operator_vocab/config.py +54 -0
- QuantNodes/research/quant_alpha/operator_vocab/metadata.py +263 -0
- QuantNodes/research/quant_alpha/operator_vocab/vocabulary.py +481 -0
- QuantNodes/research/quant_alpha/pipeline.py +1027 -0
- QuantNodes/research/quant_alpha/types/__init__.py +27 -0
- QuantNodes/research/quant_alpha/types/constants.py +28 -0
- QuantNodes/research/quant_alpha/types/state.py +205 -0
- QuantNodes/research/quant_alpha/workflow/__init__.py +32 -0
- QuantNodes/research/quant_alpha/workflow/alpha_gpt.py +911 -0
- QuantNodes/research/quant_alpha/workflow/alpha_logics.py +416 -0
- QuantNodes/research/quant_alpha/workflow/state.py +27 -0
- QuantNodes/research/report_reproducer.py +485 -0
- QuantNodes/research/wiki.py +1155 -0
- QuantNodes/symbolic/__init__.py +51 -0
- QuantNodes/symbolic/compiler.py +113 -0
- QuantNodes/symbolic/dialect.py +260 -0
- QuantNodes/symbolic/executor.py +147 -0
- QuantNodes/symbolic/expression.py +234 -0
- QuantNodes/symbolic/functions.py +433 -0
- QuantNodes/symbolic/optimizer.py +165 -0
- QuantNodes/ui_node/__init__.py +30 -0
- QuantNodes/ui_node/base.py +222 -0
- quantnodes-3.0.0.dist-info/METADATA +463 -0
- quantnodes-3.0.0.dist-info/RECORD +399 -0
- quantnodes-3.0.0.dist-info/WHEEL +5 -0
- quantnodes-3.0.0.dist-info/entry_points.txt +24 -0
- quantnodes-3.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
"""
|
|
3
|
+
Pipeline 优化器
|
|
4
|
+
|
|
5
|
+
提供 Pipeline 自动优化功能。
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import re
|
|
10
|
+
import ast
|
|
11
|
+
import logging
|
|
12
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
13
|
+
from dataclasses import dataclass, field
|
|
14
|
+
from abc import ABC, abstractmethod
|
|
15
|
+
|
|
16
|
+
from QuantNodes.ai.llm.base import LLMClientBase, Message, MessageRole
|
|
17
|
+
from QuantNodes.ai.prompts import PromptLibrary
|
|
18
|
+
from QuantNodes.ai.sandbox import CodeSandbox
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class OptimizationResult:
|
|
23
|
+
"""优化结果"""
|
|
24
|
+
original_code: str
|
|
25
|
+
optimized_code: str
|
|
26
|
+
improvements: List[str] = field(default_factory=list)
|
|
27
|
+
is_valid: bool = True
|
|
28
|
+
error_message: Optional[str] = None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class NodeAnalysis:
|
|
33
|
+
"""节点分析"""
|
|
34
|
+
node_type: str
|
|
35
|
+
config: Dict[str, Any]
|
|
36
|
+
dependencies: List[str]
|
|
37
|
+
estimated_cost: float = 1.0
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class PipelineAnalyzer:
|
|
41
|
+
"""
|
|
42
|
+
Pipeline 分析器
|
|
43
|
+
|
|
44
|
+
分析 Pipeline 结构并识别优化机会。
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def __init__(self):
|
|
48
|
+
self.logger = logging.getLogger(f"optimizer.{self.__class__.__name__}")
|
|
49
|
+
|
|
50
|
+
def analyze(self, code: str) -> List[NodeAnalysis]:
|
|
51
|
+
"""
|
|
52
|
+
分析 Pipeline 代码
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
code: Pipeline 代码
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
List[NodeAnalysis] 节点分析列表
|
|
59
|
+
"""
|
|
60
|
+
analyses = []
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
tree = ast.parse(code)
|
|
64
|
+
analyses = self._walk_ast(tree)
|
|
65
|
+
except SyntaxError as e:
|
|
66
|
+
self.logger.error(f"Syntax error: {e}")
|
|
67
|
+
|
|
68
|
+
return analyses
|
|
69
|
+
|
|
70
|
+
def _walk_ast(self, tree: ast.AST) -> List[NodeAnalysis]:
|
|
71
|
+
"""遍历 AST"""
|
|
72
|
+
analyses = []
|
|
73
|
+
|
|
74
|
+
for node in ast.walk(tree):
|
|
75
|
+
if isinstance(node, ast.Call):
|
|
76
|
+
analysis = self._analyze_call(node)
|
|
77
|
+
if analysis:
|
|
78
|
+
analyses.append(analysis)
|
|
79
|
+
|
|
80
|
+
return analyses
|
|
81
|
+
|
|
82
|
+
def _analyze_call(self, node: ast.Call) -> Optional[NodeAnalysis]:
|
|
83
|
+
"""分析函数调用"""
|
|
84
|
+
if not isinstance(node.func, ast.Name):
|
|
85
|
+
return None
|
|
86
|
+
|
|
87
|
+
node_name = node.func.id
|
|
88
|
+
|
|
89
|
+
if 'Node' in node_name or 'Node' in str(node.func):
|
|
90
|
+
config = self._extract_config(node)
|
|
91
|
+
deps = self._extract_dependencies(node)
|
|
92
|
+
|
|
93
|
+
return NodeAnalysis(
|
|
94
|
+
node_type=node_name,
|
|
95
|
+
config=config,
|
|
96
|
+
dependencies=deps,
|
|
97
|
+
estimated_cost=self._estimate_cost(node_name, config)
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
return None
|
|
101
|
+
|
|
102
|
+
def _extract_config(self, node: ast.Call) -> Dict[str, Any]:
|
|
103
|
+
"""提取配置"""
|
|
104
|
+
config = {}
|
|
105
|
+
|
|
106
|
+
for keyword in node.keywords:
|
|
107
|
+
if isinstance(keyword.value, ast.Dict):
|
|
108
|
+
for k, v in zip(keyword.value.keys, keyword.value.values):
|
|
109
|
+
if isinstance(k, ast.Constant):
|
|
110
|
+
if isinstance(v, ast.Constant):
|
|
111
|
+
config[k.value] = v.value
|
|
112
|
+
elif isinstance(v, ast.Name):
|
|
113
|
+
config[k.value] = v.id
|
|
114
|
+
elif isinstance(keyword.value, ast.Constant):
|
|
115
|
+
config[keyword.arg] = keyword.value.value
|
|
116
|
+
|
|
117
|
+
return config
|
|
118
|
+
|
|
119
|
+
def _extract_dependencies(self, node: ast.Call) -> List[str]:
|
|
120
|
+
"""提取依赖"""
|
|
121
|
+
deps = []
|
|
122
|
+
|
|
123
|
+
for arg in node.args:
|
|
124
|
+
if isinstance(arg, ast.Name):
|
|
125
|
+
deps.append(arg.id)
|
|
126
|
+
elif isinstance(arg, ast.BinOp) and isinstance(arg.op, ast.RShift):
|
|
127
|
+
if isinstance(arg.left, ast.Name):
|
|
128
|
+
deps.append(arg.left.id)
|
|
129
|
+
if isinstance(arg.right, ast.Name):
|
|
130
|
+
deps.append(arg.right.id)
|
|
131
|
+
|
|
132
|
+
return deps
|
|
133
|
+
|
|
134
|
+
def _estimate_cost(self, node_type: str, config: Dict[str, Any]) -> float:
|
|
135
|
+
"""估算节点成本"""
|
|
136
|
+
base_cost = 1.0
|
|
137
|
+
|
|
138
|
+
if 'database' in node_type.lower():
|
|
139
|
+
base_cost = 10.0
|
|
140
|
+
elif 'backtest' in node_type.lower():
|
|
141
|
+
base_cost = 50.0
|
|
142
|
+
elif 'factor' in node_type.lower():
|
|
143
|
+
base_cost = 5.0
|
|
144
|
+
|
|
145
|
+
if 'limit' in config:
|
|
146
|
+
limit = config.get('limit', 1000)
|
|
147
|
+
base_cost *= (limit / 1000)
|
|
148
|
+
|
|
149
|
+
return base_cost
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class RuleBasedOptimizer(ABC):
|
|
153
|
+
"""基于规则的优化器基类"""
|
|
154
|
+
|
|
155
|
+
@abstractmethod
|
|
156
|
+
def can_apply(self, code: str) -> bool:
|
|
157
|
+
"""检查是否可以应用"""
|
|
158
|
+
pass
|
|
159
|
+
|
|
160
|
+
@abstractmethod
|
|
161
|
+
def apply(self, code: str) -> Tuple[str, List[str]]:
|
|
162
|
+
"""应用优化"""
|
|
163
|
+
pass
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class CacheReadOptimizer(RuleBasedOptimizer):
|
|
167
|
+
"""缓存读取优化"""
|
|
168
|
+
|
|
169
|
+
def can_apply(self, code: str) -> bool:
|
|
170
|
+
return 'DatabaseNode' in code and '.read(' in code
|
|
171
|
+
|
|
172
|
+
def apply(self, code: str) -> Tuple[str, List[str]]:
|
|
173
|
+
improvements = []
|
|
174
|
+
|
|
175
|
+
optimized = re.sub(
|
|
176
|
+
r'(\w+)\s*=\s*DatabaseNode\([^)]*\)\s*\n\s*\1\.read\(',
|
|
177
|
+
r'\1 = DatabaseNode(cache=True, ...)\n\1.read(',
|
|
178
|
+
code
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
if optimized != code:
|
|
182
|
+
improvements.append("Added caching to DatabaseNode reads")
|
|
183
|
+
|
|
184
|
+
return optimized, improvements
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
class LimitPushdownOptimizer(RuleBasedOptimizer):
|
|
188
|
+
"""LIMIT 下推优化"""
|
|
189
|
+
|
|
190
|
+
def can_apply(self, code: str) -> bool:
|
|
191
|
+
return '.limit(' in code and 'DatabaseNode' in code
|
|
192
|
+
|
|
193
|
+
def apply(self, code: str) -> Tuple[str, List[str]]:
|
|
194
|
+
improvements = []
|
|
195
|
+
|
|
196
|
+
limit_match = re.search(r'\.limit\((\d+)\)', code)
|
|
197
|
+
if limit_match:
|
|
198
|
+
limit_value = limit_match.group(1)
|
|
199
|
+
improvements.append(f"Pushed down limit={limit_value} to DatabaseNode")
|
|
200
|
+
|
|
201
|
+
return code, improvements
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class ParallelFetchOptimizer(RuleBasedOptimizer):
|
|
205
|
+
"""并行获取优化"""
|
|
206
|
+
|
|
207
|
+
def can_apply(self, code: str) -> bool:
|
|
208
|
+
patterns = [
|
|
209
|
+
r'DatabaseNode\([^)]*engine\s*=\s*["\']duckdb["\']',
|
|
210
|
+
r'DatabaseNode\([^)]*engine\s*=\s*["\']clickhouse["\']',
|
|
211
|
+
]
|
|
212
|
+
return any(re.search(p, code) for p in patterns)
|
|
213
|
+
|
|
214
|
+
def apply(self, code: str) -> Tuple[str, List[str]]:
|
|
215
|
+
improvements = ["Enabled parallel data fetching"]
|
|
216
|
+
|
|
217
|
+
optimized = re.sub(
|
|
218
|
+
r'DatabaseNode\(',
|
|
219
|
+
'DatabaseNode(parallel=True, ',
|
|
220
|
+
code
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
return optimized, improvements
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
class PipelineOptimizer:
|
|
227
|
+
"""
|
|
228
|
+
Pipeline 优化器
|
|
229
|
+
|
|
230
|
+
提供 Pipeline 自动优化功能。
|
|
231
|
+
|
|
232
|
+
Examples:
|
|
233
|
+
>>> optimizer = PipelineOptimizer(llm_client)
|
|
234
|
+
>>> result = optimizer.optimize(code)
|
|
235
|
+
>>> print(result.optimized_code)
|
|
236
|
+
"""
|
|
237
|
+
|
|
238
|
+
def __init__(
|
|
239
|
+
self,
|
|
240
|
+
llm_client=None,
|
|
241
|
+
code_sandbox: Optional[CodeSandbox] = None,
|
|
242
|
+
enable_ai_optimization: bool = True,
|
|
243
|
+
**kwargs
|
|
244
|
+
):
|
|
245
|
+
"""
|
|
246
|
+
初始化优化器
|
|
247
|
+
|
|
248
|
+
Args:
|
|
249
|
+
llm_client: LLM 客户端(可选,默认使用 LLMGateway)
|
|
250
|
+
code_sandbox: 代码沙箱
|
|
251
|
+
enable_ai_optimization: 是否启用 AI 优化
|
|
252
|
+
"""
|
|
253
|
+
if llm_client is None:
|
|
254
|
+
from QuantNodes.ai.llm.gateway import get_llm_gateway
|
|
255
|
+
llm_client = get_llm_gateway()
|
|
256
|
+
self.llm = llm_client
|
|
257
|
+
self.sandbox = code_sandbox or CodeSandbox()
|
|
258
|
+
self.enable_ai_optimization = enable_ai_optimization and self.llm is not None
|
|
259
|
+
self.analyzer = PipelineAnalyzer()
|
|
260
|
+
self.rule_optimizers: List[RuleBasedOptimizer] = [
|
|
261
|
+
CacheReadOptimizer(),
|
|
262
|
+
LimitPushdownOptimizer(),
|
|
263
|
+
ParallelFetchOptimizer(),
|
|
264
|
+
]
|
|
265
|
+
self.logger = logging.getLogger(f"optimizer.{self.__class__.__name__}")
|
|
266
|
+
|
|
267
|
+
def optimize(
|
|
268
|
+
self,
|
|
269
|
+
code: str,
|
|
270
|
+
goal: str = "performance",
|
|
271
|
+
validate: bool = True,
|
|
272
|
+
**kwargs
|
|
273
|
+
) -> OptimizationResult:
|
|
274
|
+
"""
|
|
275
|
+
优化 Pipeline 代码
|
|
276
|
+
|
|
277
|
+
Args:
|
|
278
|
+
code: Pipeline 代码
|
|
279
|
+
goal: 优化目标 ("performance", "memory", "readability")
|
|
280
|
+
validate: 是否验证优化后的代码
|
|
281
|
+
**kwargs: 额外参数
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
OptimizationResult 优化结果
|
|
285
|
+
"""
|
|
286
|
+
original_code = code
|
|
287
|
+
all_improvements: List[str] = []
|
|
288
|
+
|
|
289
|
+
analyses = self.analyzer.analyze(code)
|
|
290
|
+
if analyses:
|
|
291
|
+
estimated_cost = sum(a.estimated_cost for a in analyses)
|
|
292
|
+
all_improvements.append(
|
|
293
|
+
f"Analyzed {len(analyses)} nodes, estimated cost: {estimated_cost:.2f}"
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
for optimizer in self.rule_optimizers:
|
|
297
|
+
if optimizer.can_apply(code):
|
|
298
|
+
optimized, improvements = optimizer.apply(code)
|
|
299
|
+
if optimized != code:
|
|
300
|
+
code = optimized
|
|
301
|
+
all_improvements.extend(improvements)
|
|
302
|
+
|
|
303
|
+
if self.enable_ai_optimization and self.llm:
|
|
304
|
+
code, ai_improvements = self._ai_optimize(code, goal, **kwargs)
|
|
305
|
+
all_improvements.extend(ai_improvements)
|
|
306
|
+
|
|
307
|
+
if validate:
|
|
308
|
+
validation_result = self.sandbox.validate(code)
|
|
309
|
+
is_valid = validation_result.is_safe
|
|
310
|
+
error_message = None if is_valid else f"Validation failed: {validation_result.errors}"
|
|
311
|
+
else:
|
|
312
|
+
is_valid = True
|
|
313
|
+
error_message = None
|
|
314
|
+
|
|
315
|
+
return OptimizationResult(
|
|
316
|
+
original_code=original_code,
|
|
317
|
+
optimized_code=code,
|
|
318
|
+
improvements=all_improvements,
|
|
319
|
+
is_valid=is_valid,
|
|
320
|
+
error_message=error_message
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
def _ai_optimize(
|
|
324
|
+
self,
|
|
325
|
+
code: str,
|
|
326
|
+
goal: str,
|
|
327
|
+
**kwargs
|
|
328
|
+
) -> Tuple[str, List[str]]:
|
|
329
|
+
"""AI 优化"""
|
|
330
|
+
improvements = []
|
|
331
|
+
|
|
332
|
+
system_prompt, user_prompt = PromptLibrary.format(
|
|
333
|
+
"optimization",
|
|
334
|
+
code=code
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
goal_instruction = ""
|
|
338
|
+
if goal == "performance":
|
|
339
|
+
goal_instruction = "Focus on reducing execution time and minimizing API calls."
|
|
340
|
+
elif goal == "memory":
|
|
341
|
+
goal_instruction = (
|
|
342
|
+
"Focus on reducing memory usage and avoiding unnecessary data copies."
|
|
343
|
+
)
|
|
344
|
+
elif goal == "readability":
|
|
345
|
+
goal_instruction = "Focus on improving code clarity and maintainability."
|
|
346
|
+
|
|
347
|
+
messages = [
|
|
348
|
+
Message(role=MessageRole.SYSTEM, content=system_prompt),
|
|
349
|
+
Message(role=MessageRole.USER, content=user_prompt + "\n\n" + goal_instruction),
|
|
350
|
+
]
|
|
351
|
+
|
|
352
|
+
try:
|
|
353
|
+
response = self.llm.chat(
|
|
354
|
+
messages=messages,
|
|
355
|
+
temperature=0.3,
|
|
356
|
+
max_tokens=kwargs.get('max_tokens'),
|
|
357
|
+
**kwargs
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
if response and response.content:
|
|
361
|
+
optimized_code = self._extract_code(response.content)
|
|
362
|
+
if optimized_code and optimized_code != code:
|
|
363
|
+
improvements.append("Applied AI-based optimization")
|
|
364
|
+
return optimized_code, improvements
|
|
365
|
+
|
|
366
|
+
except Exception as e:
|
|
367
|
+
self.logger.error(f"AI optimization failed: {e}")
|
|
368
|
+
|
|
369
|
+
return code, improvements
|
|
370
|
+
|
|
371
|
+
def _extract_code(self, content: str) -> str:
|
|
372
|
+
"""从响应中提取代码"""
|
|
373
|
+
pattern = re.compile(r'```(?:python)?\s*(.*?)```', re.DOTALL)
|
|
374
|
+
matches = pattern.findall(content)
|
|
375
|
+
if matches:
|
|
376
|
+
return matches[0].strip()
|
|
377
|
+
return content.strip()
|
|
378
|
+
|
|
379
|
+
def suggest_optimizations(self, code: str) -> List[str]:
|
|
380
|
+
"""
|
|
381
|
+
建议优化项
|
|
382
|
+
|
|
383
|
+
Args:
|
|
384
|
+
code: Pipeline 代码
|
|
385
|
+
|
|
386
|
+
Returns:
|
|
387
|
+
List[str] 建议列表
|
|
388
|
+
"""
|
|
389
|
+
suggestions = []
|
|
390
|
+
analyses = self.analyzer.analyze(code)
|
|
391
|
+
|
|
392
|
+
for analysis in analyses:
|
|
393
|
+
if analysis.estimated_cost > 10:
|
|
394
|
+
suggestions.append(
|
|
395
|
+
f"High cost node ({analysis.node_type}, cost={analysis.estimated_cost:.2f}): "
|
|
396
|
+
"Consider optimizing or caching"
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
for optimizer in self.rule_optimizers:
|
|
400
|
+
if optimizer.can_apply(code):
|
|
401
|
+
suggestions.append(
|
|
402
|
+
f"Rule-based optimization available: {optimizer.__class__.__name__}"
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
return suggestions
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
"""
|
|
3
|
+
提示词模板库
|
|
4
|
+
|
|
5
|
+
提供用于生成和优化 Pipeline 的提示词模板。
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Dict, List
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class PromptTemplate:
|
|
15
|
+
"""提示词模板"""
|
|
16
|
+
system: str
|
|
17
|
+
user: str
|
|
18
|
+
description: str = ""
|
|
19
|
+
|
|
20
|
+
def format(self, **kwargs) -> tuple[str, str]:
|
|
21
|
+
"""格式化模板"""
|
|
22
|
+
return (
|
|
23
|
+
self.system.format(**kwargs),
|
|
24
|
+
self.user.format(**kwargs)
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
SYSTEM_PROMPT = (
|
|
29
|
+
"You are a quantitative trading strategy expert specializing in"
|
|
30
|
+
" designing and implementing trading systems using the QuantNodes"
|
|
31
|
+
" framework.\n\n"
|
|
32
|
+
"QuantNodes Framework Overview:\n"
|
|
33
|
+
"- BaseNode: Unified node base class with execute() method\n"
|
|
34
|
+
"- Pipeline: Chain nodes together using >> operator\n"
|
|
35
|
+
"- DatabaseNode: Query data from various databases (SQLite, DuckDB, MySQL,"
|
|
36
|
+
" ClickHouse)\n"
|
|
37
|
+
"- factor_functions: 140+ Polars-based operators (rolling_mean, zscore,"
|
|
38
|
+
" rank, etc.)\n"
|
|
39
|
+
"- BacktestNode: Run backtesting simulations\n"
|
|
40
|
+
"- OperatorNode: SQL operations and data transformations\n\n"
|
|
41
|
+
"Key Conventions:\n"
|
|
42
|
+
"- All nodes inherit from BaseNode\n"
|
|
43
|
+
"- Use >> to chain nodes in a pipeline\n"
|
|
44
|
+
"- Configuration passed via config dict in constructor\n"
|
|
45
|
+
"- Input/output data is typically pandas DataFrame\n"
|
|
46
|
+
"- Factor computation uses factor_functions (ff) module\n\n"
|
|
47
|
+
"Your task is to generate valid Python code that creates QuantNodes"
|
|
48
|
+
" pipelines based on user requests.\n"
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
STRATEGY_GENERATION_PROMPT = PromptTemplate(
|
|
52
|
+
system=SYSTEM_PROMPT,
|
|
53
|
+
user=(
|
|
54
|
+
"Generate a QuantNodes trading strategy pipeline based on the following"
|
|
55
|
+
" description:\n\n{trading_description}\n\nRequirements:\n"
|
|
56
|
+
"- Use Python code\n"
|
|
57
|
+
"- Create appropriate nodes (DatabaseNode, BacktestNode, etc.) and"
|
|
58
|
+
" use factor_functions for factor computation\n"
|
|
59
|
+
"- Use the >> operator to chain nodes\n"
|
|
60
|
+
"- Include necessary configuration\n\n"
|
|
61
|
+
"Available Data:\n"
|
|
62
|
+
"The database contains stock OHLCV data with columns: date, code,"
|
|
63
|
+
" open, high, low, close, volume\n\n"
|
|
64
|
+
"Generate the Python code:"
|
|
65
|
+
),
|
|
66
|
+
description="Generate trading strategy pipeline from natural language",
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
CODE_REVIEW_PROMPT = PromptTemplate(
|
|
70
|
+
system=SYSTEM_PROMPT,
|
|
71
|
+
user="""Review the following QuantNodes pipeline code for issues:
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
{code}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Check for:
|
|
78
|
+
1. Correct node usage and configuration
|
|
79
|
+
2. Proper pipeline chaining
|
|
80
|
+
3. Data flow correctness
|
|
81
|
+
4. Performance concerns
|
|
82
|
+
5. Potential bugs
|
|
83
|
+
|
|
84
|
+
Provide your review:""",
|
|
85
|
+
description="Review generated code for issues"
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
OPTIMIZATION_PROMPT = PromptTemplate(
|
|
89
|
+
system=SYSTEM_PROMPT,
|
|
90
|
+
user="""Optimize the following QuantNodes pipeline for better performance:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
{code}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Optimization goals:
|
|
97
|
+
- Reduce execution time
|
|
98
|
+
- Minimize memory usage
|
|
99
|
+
- Improve readability
|
|
100
|
+
|
|
101
|
+
Provide the optimized code:""",
|
|
102
|
+
description="Optimize pipeline for performance"
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
FACTOR_EXPLANATION_PROMPT = PromptTemplate(
|
|
106
|
+
system="You are a financial factor research expert.",
|
|
107
|
+
user="""Explain the following trading factor in detail:
|
|
108
|
+
|
|
109
|
+
{factor_description}
|
|
110
|
+
|
|
111
|
+
Include:
|
|
112
|
+
1. What the factor measures
|
|
113
|
+
2. How to calculate it
|
|
114
|
+
3. Practical usage tips
|
|
115
|
+
4. Potential issues or limitations
|
|
116
|
+
|
|
117
|
+
Provide a comprehensive explanation:""",
|
|
118
|
+
description="Explain trading factors"
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
BACKTEST_CONFIG_PROMPT = PromptTemplate(
|
|
122
|
+
system=SYSTEM_PROMPT,
|
|
123
|
+
user="""Suggest appropriate backtest configuration for the following strategy:
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
{strategy_code}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Consider:
|
|
130
|
+
- Initial capital
|
|
131
|
+
- Commission rates
|
|
132
|
+
- Position sizing
|
|
133
|
+
- Risk management
|
|
134
|
+
|
|
135
|
+
Provide configuration dict:""",
|
|
136
|
+
description="Suggest backtest configuration"
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class PromptLibrary:
|
|
141
|
+
"""
|
|
142
|
+
提示词模板库
|
|
143
|
+
|
|
144
|
+
提供各种任务场景的提示词模板。
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
_templates: Dict[str, PromptTemplate] = {
|
|
148
|
+
"strategy_generation": STRATEGY_GENERATION_PROMPT,
|
|
149
|
+
"code_review": CODE_REVIEW_PROMPT,
|
|
150
|
+
"optimization": OPTIMIZATION_PROMPT,
|
|
151
|
+
"factor_explanation": FACTOR_EXPLANATION_PROMPT,
|
|
152
|
+
"backtest_config": BACKTEST_CONFIG_PROMPT,
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
@classmethod
|
|
156
|
+
def get(cls, name: str) -> PromptTemplate:
|
|
157
|
+
"""获取模板"""
|
|
158
|
+
if name not in cls._templates:
|
|
159
|
+
raise ValueError(f"Unknown template: {name}. Available: {list(cls._templates.keys())}")
|
|
160
|
+
return cls._templates[name]
|
|
161
|
+
|
|
162
|
+
@classmethod
|
|
163
|
+
def list_templates(cls) -> List[str]:
|
|
164
|
+
"""列出所有模板"""
|
|
165
|
+
return list(cls._templates.keys())
|
|
166
|
+
|
|
167
|
+
@classmethod
|
|
168
|
+
def register(cls, name: str, template: PromptTemplate) -> None:
|
|
169
|
+
"""注册新模板"""
|
|
170
|
+
cls._templates[name] = template
|
|
171
|
+
|
|
172
|
+
@classmethod
|
|
173
|
+
def format(
|
|
174
|
+
cls,
|
|
175
|
+
name: str,
|
|
176
|
+
**kwargs
|
|
177
|
+
) -> tuple[str, str]:
|
|
178
|
+
"""格式化模板"""
|
|
179
|
+
template = cls.get(name)
|
|
180
|
+
return template.format(**kwargs)
|
|
181
|
+
|
|
182
|
+
@classmethod
|
|
183
|
+
def get_system_prompt(cls) -> str:
|
|
184
|
+
"""获取系统提示词"""
|
|
185
|
+
return SYSTEM_PROMPT
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class PromptBuilder:
|
|
189
|
+
"""提示词构建器"""
|
|
190
|
+
|
|
191
|
+
def __init__(self):
|
|
192
|
+
self._parts: List[str] = []
|
|
193
|
+
|
|
194
|
+
def add_system(self, text: str) -> 'PromptBuilder':
|
|
195
|
+
"""添加系统提示"""
|
|
196
|
+
self._parts.append(f"[SYSTEM] {text}")
|
|
197
|
+
return self
|
|
198
|
+
|
|
199
|
+
def add_user(self, text: str) -> 'PromptBuilder':
|
|
200
|
+
"""添加用户提示"""
|
|
201
|
+
self._parts.append(f"[USER] {text}")
|
|
202
|
+
return self
|
|
203
|
+
|
|
204
|
+
def add_assistant(self, text: str) -> 'PromptBuilder':
|
|
205
|
+
"""添加助手提示"""
|
|
206
|
+
self._parts.append(f"[ASSISTANT] {text}")
|
|
207
|
+
return self
|
|
208
|
+
|
|
209
|
+
def add_example(self, user: str, assistant: str) -> 'PromptBuilder':
|
|
210
|
+
"""添加示例"""
|
|
211
|
+
self._parts.append(f"[EXAMPLE]\nUser: {user}\nAssistant: {assistant}")
|
|
212
|
+
return self
|
|
213
|
+
|
|
214
|
+
def build(self) -> tuple[str, str]:
|
|
215
|
+
"""构建最终提示词"""
|
|
216
|
+
system_parts = []
|
|
217
|
+
user_parts = []
|
|
218
|
+
|
|
219
|
+
for part in self._parts:
|
|
220
|
+
if part.startswith("[SYSTEM]"):
|
|
221
|
+
system_parts.append(part[9:])
|
|
222
|
+
elif part.startswith("[USER]"):
|
|
223
|
+
user_parts.append(part[7:])
|
|
224
|
+
elif part.startswith("[ASSISTANT]"):
|
|
225
|
+
system_parts.append(f"Assistant: {part[11:]}")
|
|
226
|
+
elif part.startswith("[EXAMPLE]"):
|
|
227
|
+
user_parts.append(part[10:])
|
|
228
|
+
|
|
229
|
+
return "\n".join(system_parts), "\n".join(user_parts)
|