powerquant-cli 0.2.7__tar.gz → 0.2.10__tar.gz
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.
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/PKG-INFO +26 -3
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/README.md +24 -2
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/pqdata/client.py +63 -13
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/pqdata/exceptions.py +6 -2
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/pqdata/schema/query_schema.py +1 -0
- powerquant_cli-0.2.10/bundled/pqdata/schema/snapshot_schema.py +50 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/full_market_screen.py +4 -4
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/pyproject.toml +3 -3
- powerquant_cli-0.2.10/src/quant_cli/app/agent_resources/cli/agent_resource_cli.py +70 -0
- powerquant_cli-0.2.10/src/quant_cli/app/agent_resources/interface/public/agent_resource_sync.py +14 -0
- powerquant_cli-0.2.10/src/quant_cli/app/agent_resources/repository/agent_resource_repository.py +57 -0
- powerquant_cli-0.2.10/src/quant_cli/app/agent_resources/schema/agent_resource_schema.py +89 -0
- powerquant_cli-0.2.10/src/quant_cli/app/agent_resources/service/agent_resource_service.py +279 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/backtest/cli/local_backtest_cli.py +17 -13
- powerquant_cli-0.2.10/src/quant_cli/app/backtest/service/backtest_application_service.py +29 -0
- powerquant_cli-0.2.10/src/quant_cli/app/cli_dependency.py +11 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/data/cli/data_cli.py +8 -6
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/data/data_dependency.py +1 -4
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/data/service/bar_cache_service.py +50 -97
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/data/service/dataset_load_service.py +7 -9
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/data/service/dataset_prepare_service.py +23 -6
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/factor/cli/factor_definition_cli.py +6 -4
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/factor/cli/local_factor_cli.py +18 -13
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/factor/cli/local_selection_cli.py +10 -19
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/factor/local_factor_dependency.py +1 -1
- powerquant_cli-0.2.10/src/quant_cli/app/factor/service/factor_application_service.py +41 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/job/cli/local_job_cli.py +9 -9
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/quant_cli.py +33 -4
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/research/cli/local_research_cli.py +20 -17
- powerquant_cli-0.2.10/src/quant_cli/app/research/service/research_application_service.py +34 -0
- powerquant_cli-0.2.10/src/quant_cli/app/strategy/cli/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/strategy/cli/strategy_cli.py +11 -10
- powerquant_cli-0.2.10/src/quant_cli/app/system/__init__.py +0 -0
- powerquant_cli-0.2.10/src/quant_cli/app/system/cli/__init__.py +0 -0
- powerquant_cli-0.2.10/src/quant_cli/app/system/cli/config_cli.py +50 -0
- powerquant_cli-0.2.10/src/quant_cli/app/system/cli/system_cli.py +66 -0
- powerquant_cli-0.2.10/src/quant_cli/app/system/interface/__init__.py +0 -0
- powerquant_cli-0.2.10/src/quant_cli/app/system/interface/package_updater.py +9 -0
- powerquant_cli-0.2.10/src/quant_cli/app/system/service/__init__.py +0 -0
- powerquant_cli-0.2.10/src/quant_cli/app/system/service/bootstrap_service.py +57 -0
- powerquant_cli-0.2.10/src/quant_cli/app/system/service/connection_service.py +39 -0
- powerquant_cli-0.2.10/src/quant_cli/app/system/service/upgrade_service.py +41 -0
- powerquant_cli-0.2.10/src/quant_cli/application_container.py +63 -0
- powerquant_cli-0.2.10/src/quant_cli/application_settings.py +19 -0
- powerquant_cli-0.2.10/src/quant_cli/common/__init__.py +0 -0
- powerquant_cli-0.2.10/src/quant_cli/common/application_errors.py +8 -0
- powerquant_cli-0.2.10/src/quant_cli/common/command_error_handler.py +53 -0
- powerquant_cli-0.2.10/src/quant_cli/common/command_help.py +45 -0
- powerquant_cli-0.2.10/src/quant_cli/common/database/__init__.py +0 -0
- powerquant_cli-0.2.10/src/quant_cli/common/filesystem.py +73 -0
- powerquant_cli-0.2.10/src/quant_cli/common/hashing.py +5 -0
- powerquant_cli-0.2.10/src/quant_cli/common/http/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/common/http/definition_client.py +27 -1
- powerquant_cli-0.2.10/src/quant_cli/common/operation_error.py +10 -0
- powerquant_cli-0.2.10/src/quant_cli/common/package_update_worker.py +145 -0
- powerquant_cli-0.2.10/src/quant_cli/common/package_updater.py +211 -0
- powerquant_cli-0.2.10/src/quant_cli/common/utils/__init__.py +0 -0
- powerquant_cli-0.2.10/src/quant_cli/common/utils/cli_utils.py +88 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/config/connection_config.py +6 -7
- powerquant_cli-0.2.10/src/quant_cli/resources/agent_hint.md +7 -0
- powerquant_cli-0.2.10/src/quant_cli/resources/skills/pq-bootstrap/SKILL.md +49 -0
- powerquant_cli-0.2.10/src/quant_cli/resources/skills/pq-bootstrap/references/resources.md +9 -0
- powerquant_cli-0.2.10/src/quant_cli/resources/skills/pq-data-operations/SKILL.md +37 -0
- powerquant_cli-0.2.10/src/quant_cli/resources/skills/pq-research/SKILL.md +47 -0
- powerquant_cli-0.2.10/tests/__init__.py +0 -0
- powerquant_cli-0.2.10/tests/integration/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/integration/test_local_quant_storage.py +1 -1
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/integration/test_local_selection.py +4 -4
- powerquant_cli-0.2.10/tests/unit/test_agent_install.py +131 -0
- powerquant_cli-0.2.10/tests/unit/test_agent_json.py +26 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_bar_cache.py +12 -8
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_connection_config.py +13 -1
- powerquant_cli-0.2.10/tests/unit/test_definition_errors.py +59 -0
- powerquant_cli-0.2.10/tests/unit/test_package_upgrade.py +260 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/uv.lock +50 -2
- powerquant_cli-0.2.7/src/quant_cli/app/config/__init__.py +0 -1
- powerquant_cli-0.2.7/src/quant_cli/app/config/config_cli.py +0 -71
- powerquant_cli-0.2.7/src/quant_cli/common/utils/cli_utils.py +0 -37
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/.env.example +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/.gitignore +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/LICENSE +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/pqdata/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/pqdata/download.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/pqdata/schema/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/pqdata/schema/adjustment_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/pqdata/schema/bar_content_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/pqdata/schema/bar_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/pqdata/schema/corporate_action_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/pqdata/schema/history_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/pqdata/schema/pit_daily_window.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/pqdata/schema/quote_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/pqdata/schema/reference_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/pqdata/schema/reliability_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/SPEC.md +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/backtest/SPEC.md +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/backtest/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/backtest/backtest_input_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/backtest/backtest_run.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/backtest/data_guard.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/backtest/historical_clock.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/backtest/legacy_result_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/backtest/metrics.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/backtest/performance_report.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/backtest/report_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/backtest/schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/backtest/service/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/backtest/service/backtest_execution_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/constants.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/domain/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/domain/trading_quantity_value.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/exceptions.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/interface/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/interface/adjustment_factor_query.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/interface/market_data_query.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/interface/market_data_verification.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/interface/market_event_source.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/interface/market_revision_query.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/interface/market_runtime_repository.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/interface/market_time_slice_source.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/repository/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/schema/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/schema/adjustment_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/schema/corporate_action_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/schema/event_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/schema/exchange_operating_state.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/schema/exchange_state_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/schema/history_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/schema/instrument_identity.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/schema/market_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/schema/pit_daily_window.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/schema/quote_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/schema/reliability_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/schema/snapshot_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/schema/trading_state_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/service/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/service/calendar_coverage_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/service/prepared_data_verification_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/service/prepared_market_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/data/service/price_adjustment_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/LICENSE.vnpy +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/builtin/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/builtin/alpha101_recipe.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/builtin/alpha158_recipe.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/builtin/factor_recipe_catalog.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/computation/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/computation/factor_batch_evaluator.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/computation/factor_expression.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/computation/factor_source_loader.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/computation/operators/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/computation/operators/arithmetic_operator.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/computation/operators/cross_section_operator.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/computation/operators/time_series_operator.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/computation/panel_evaluator.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/computation/panel_expression.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/computation/python_factor_executor.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/computation/universe_filter.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/constants.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/exceptions.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/factor_dependency.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/interface/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/interface/factor_compute.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/interface/factor_execution.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/interface/factor_local_data.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/interface/factor_panel_compute.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/interface/factor_panel_input.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/interface/factor_query_store.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/interface/public/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/interface/public/factor_diagnostics.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/interface/public/factor_exposure_query.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/interface/public/factor_local.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/interface/public/factor_query.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/interface/public/factor_selection.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/model/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/repository/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/schema/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/schema/diagnostic_types.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/schema/factor_artifact_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/schema/factor_computation_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/schema/factor_compute_request.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/schema/factor_contract.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/schema/factor_input_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/schema/factor_panel.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/schema/factor_publication_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/schema/factor_query_result_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/schema/factor_result_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/schema/local_factor_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/schema/panel_policy.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/schema/selection_report.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/schema/selection_types.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/service/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/service/factor_compute_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/service/factor_diagnostic_runner.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/service/factor_diagnostics_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/service/factor_exposure_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/service/factor_input_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/service/factor_local_execution_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/service/factor_panel_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/service/factor_runtime_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/service/factor_selection_runner.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/service/published_factor_execution_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/service/selection_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/factor/visibility.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/opportunity/SPEC.md +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/opportunity/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/SPEC.md +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/bar_matcher.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/constants.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/domain/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/domain/execution_batch.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/domain/order_entity.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/domain/order_event.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/domain/order_policy.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/domain/order_value.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/fee_model.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/interface/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/interface/order_account.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/interface/order_trading_rules.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/interface/public/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/interface/public/execution_account.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/interface/public/order_events.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/interface/public/order_execution.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/interface/public/order_runtime.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/interface/public/order_submission.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/order_event_bus.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/order_execution_dependency.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/order_submission_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/schema/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/schema/order_request_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/simulation_broker.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/slippage_model.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/tradability_policy.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/order_execution/validators.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/SPEC.md +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/domain/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/domain/entitlement_entity.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/domain/portfolio_entity.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/domain/portfolio_event.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/domain/portfolio_value.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/domain/position_entity.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/domain/reservation_entity.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/interface/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/interface/public/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/interface/public/portfolio.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/interface/public/simulation_account.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/ledger_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/order_account_listener.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/portfolio_dependency.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/portfolio_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/portfolio/simulated_portfolio.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/research/SPEC.md +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/research/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/research/adapter/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/research/adapter/market_label_query.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/research/interface/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/research/interface/research_dataset.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/research/interface/research_evaluation.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/research/schema/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/research/schema/comparison_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/research/schema/dataset_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/research/schema/research_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/research/service/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/research/service/research_dataset_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/research/service/research_evaluation_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/research/service/research_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/SPEC.md +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/constants.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/exceptions.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/interface/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/interface/public/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/interface/public/portfolio_construction.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/interface/public/strategy.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/interface/public/strategy_market_query.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/interface/public/strategy_portfolio_reader.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/interface/strategy_factor_reader.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/interface/strategy_order_reader.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/schema/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/schema/portfolio_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/schema/portfolio_target.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/schema/python_strategy_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/schema/screener_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/schema/signal_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/schema/strategy_publication_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/schema/strategy_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/service/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/service/factor_top_n_strategy.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/service/portfolio_construction_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/service/python_strategy_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/service/screener_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/service/store_factor_reader.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/service/strategy_market_view.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/service/strategy_runtime_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/service/strategy_scheduler.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/strategies/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/strategies/momentum_volume_breakout.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/strategy_context.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/strategy/strategy_dependency.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/trading_runtime/SPEC.md +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/trading_runtime/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/trading_runtime/domain/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/trading_runtime/replay/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/trading_runtime/replay/daily_state_expand.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/trading_runtime/replay/exchange_state_resolver.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/trading_runtime/replay/market_runtime_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/trading_runtime/replay/market_state_resolver.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/trading_runtime/runtime_ports.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/trading_runtime/runtime_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/trading_runtime/runtime_session.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/trading_runtime/strategy_portfolio_adapter.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/trading_runtime/trading_rule_book.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/app/trading_runtime/trading_rule_query.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/common/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/common/exceptions/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/common/exceptions/base.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/bundled/quant_core/common/local_run.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/cached_factor_screen.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/factors/ma_close_10.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/factors/max_drawdown_20d.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/factors/momentum_20d.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/factors/multi_intraday_screen.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/factors/risk_adjusted_momentum_20d.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/factors/volume_ratio_5d.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/factors/volume_weighted_close_pressure.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/local_quant_validation.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/published_definition_validation.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/research/factor_pit_coverage.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/research/ipo_first_day.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/selection/README.md +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/selection/backtest.json +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/selection/buy_hold.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/selection/compute.json +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/selection/prepare.json +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/selection/select.json +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/strategies/bar_roundtrip.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/strategies/buy_and_hold.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/strategies/contrarian_timing.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/strategies/factor_gate_vwap.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/strategies/ipo_next_day_vwap.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/strategies/momentum_timing.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/strategies/monthly_equal_weight.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/strategies/session_roundtrip.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/strategies/trend_drawdown_guard.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/strategies/weekly_risk_adjusted_rotation.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/examples/unified_snapshot_validation.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/hatch_build.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/licenses/LICENSE.vnpy +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/api.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/__init__.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/backtest → powerquant_cli-0.2.10/src/quant_cli/app/agent_resources}/__init__.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/backtest → powerquant_cli-0.2.10/src/quant_cli/app/agent_resources}/cli/__init__.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/backtest/repository → powerquant_cli-0.2.10/src/quant_cli/app/agent_resources/interface}/__init__.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/backtest/service → powerquant_cli-0.2.10/src/quant_cli/app/agent_resources/interface/public}/__init__.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/data → powerquant_cli-0.2.10/src/quant_cli/app/agent_resources/repository}/__init__.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/data/cli → powerquant_cli-0.2.10/src/quant_cli/app/agent_resources/schema}/__init__.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/data/repository → powerquant_cli-0.2.10/src/quant_cli/app/agent_resources/service}/__init__.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/data/schema → powerquant_cli-0.2.10/src/quant_cli/app/backtest}/__init__.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/data/service → powerquant_cli-0.2.10/src/quant_cli/app/backtest/cli}/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/backtest/local_backtest_dependency.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/backtest/local_backtest_schema.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/factor → powerquant_cli-0.2.10/src/quant_cli/app/backtest/repository}/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/backtest/repository/backtest_local_repository.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/factor/cli → powerquant_cli-0.2.10/src/quant_cli/app/backtest/service}/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/backtest/service/local_backtest_service.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/factor/interface → powerquant_cli-0.2.10/src/quant_cli/app/data}/__init__.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/factor/repository → powerquant_cli-0.2.10/src/quant_cli/app/data/cli}/__init__.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/factor/service → powerquant_cli-0.2.10/src/quant_cli/app/data/repository}/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/data/repository/parquet_repository.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/job → powerquant_cli-0.2.10/src/quant_cli/app/data/schema}/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/data/schema/dataset_audit_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/data/schema/dataset_request_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/data/schema/parquet_file_schema.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/job/cli → powerquant_cli-0.2.10/src/quant_cli/app/data/service}/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/data/service/dataset_audit_service.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/job/schema → powerquant_cli-0.2.10/src/quant_cli/app/factor}/__init__.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/job/service → powerquant_cli-0.2.10/src/quant_cli/app/factor/cli}/__init__.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/research → powerquant_cli-0.2.10/src/quant_cli/app/factor/interface}/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/factor/interface/local_selection_store.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/research/cli → powerquant_cli-0.2.10/src/quant_cli/app/factor/repository}/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/factor/repository/factor_local_repository.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/factor/repository/selection_local_repository.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/factor/schema/local_selection_schema.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/research/repository → powerquant_cli-0.2.10/src/quant_cli/app/factor/service}/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/factor/service/factor_data_prepare_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/factor/service/local_factor_query_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/factor/service/local_factor_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/factor/service/local_selection_service.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/research/schema → powerquant_cli-0.2.10/src/quant_cli/app/job}/__init__.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/research/service → powerquant_cli-0.2.10/src/quant_cli/app/job/cli}/__init__.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/strategy → powerquant_cli-0.2.10/src/quant_cli/app/job/schema}/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/job/schema/local_job_schema.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/app/strategy/cli → powerquant_cli-0.2.10/src/quant_cli/app/job/service}/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/job/service/local_job_service.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/common → powerquant_cli-0.2.10/src/quant_cli/app/research}/__init__.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/common/database → powerquant_cli-0.2.10/src/quant_cli/app/research/cli}/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/research/local_research_dependency.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/common/http → powerquant_cli-0.2.10/src/quant_cli/app/research/repository}/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/research/repository/research_local_repository.py +0 -0
- {powerquant_cli-0.2.7/src/quant_cli/common/utils → powerquant_cli-0.2.10/src/quant_cli/app/research/schema}/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/research/schema/local_research_schema.py +0 -0
- {powerquant_cli-0.2.7/tests → powerquant_cli-0.2.10/src/quant_cli/app/research/service}/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/research/service/local_research_execution_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/app/research/service/local_research_service.py +0 -0
- {powerquant_cli-0.2.7/tests/integration → powerquant_cli-0.2.10/src/quant_cli/app/strategy}/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/common/constants.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/common/database/duckdb_connection.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/common/utils/platform_utils.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/common/utils/runtime_environment.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/src/quant_cli/config/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/conftest.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/factor_fixtures.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/__init__.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_alpha_backtest_reports.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_alpha_identity.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_alpha_market_input.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_alpha_research.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_alpha_top_n.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_backtest_run_result.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_coarse_execution_capability.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_corporate_action_replay.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_d1_replay_execution_chain.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_daily_state_expand.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_daily_state_snapshot.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_daily_vwap_execution.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_data_guard.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_dataset_audit.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_domain_dependency_boundaries.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_domain_interface_boundary.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_exchange_state_execution.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_exchange_state_replay.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_exchange_state_resolver.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_exchange_state_schema.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_factor_contract.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_factor_diagnostic_runner.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_factor_diagnostics.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_factor_expression.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_factor_local_runner.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_factor_runtime_service.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_factor_selection.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_factor_selection_runner.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_ipo_vwap_study.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_local_quant_boundary.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_market_replay.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_market_trading_state.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_order_domain.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_order_submission.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_portfolio_construction.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_portfolio_contracts.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_python_strategy_runtime.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_replay_state_boundaries.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_risk_adjusted_strategy_example.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_simulated_order_execution.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_simulated_portfolio.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_store_factor_reader.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_strategy_adjusted_view.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_strategy_domain.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_strategy_lifecycle.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_tradability_policy.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_trading_runtime_contracts.py +0 -0
- {powerquant_cli-0.2.7 → powerquant_cli-0.2.10}/tests/unit/test_trading_runtime_session.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: powerquant-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.10
|
|
4
4
|
Summary: Power Quant local research CLI
|
|
5
5
|
Project-URL: Repository, https://github.com/Kepler452Byte/power-quant
|
|
6
6
|
License-Expression: LicenseRef-PowerQuant-Proprietary AND MIT
|
|
@@ -14,6 +14,7 @@ Requires-Dist: numpy<3,>=2
|
|
|
14
14
|
Requires-Dist: pandas<4,>=3
|
|
15
15
|
Requires-Dist: polars<2,>=1.36
|
|
16
16
|
Requires-Dist: pydantic<3,>=2.5
|
|
17
|
+
Requires-Dist: pyyaml<7,>=6
|
|
17
18
|
Requires-Dist: scipy<2,>=1.17
|
|
18
19
|
Requires-Dist: typer>=0.27.2
|
|
19
20
|
Requires-Dist: tzdata>=2026.3
|
|
@@ -51,7 +52,7 @@ pq config show
|
|
|
51
52
|
|
|
52
53
|
家庭 LAN 可配置 `http://192.168.8.142:18026/market/api/v1`;公网 IP 临时入口为 `http://82.157.167.33/market/api/v1`。公网 HTTP 会明文传输 Token,只适合已明确接受风险的临时接入;长期公网访问使用可信 HTTPS 或 SSH/WireGuard 加密链路。直接使用 `https://82.157.167.33` 与现有域名证书不匹配。
|
|
53
54
|
|
|
54
|
-
配置保存在当前系统用户的 `~/.powerquant/config.
|
|
55
|
+
配置保存在当前系统用户的 `~/.powerquant/config.yml`,与工作目录无关,不自动加载 `.env`。这是本地明文配置:POSIX 新目录权限 700、文件权限 600;Windows 依赖用户目录 ACL,不声称加密存储。不要提交或分享该文件。
|
|
55
56
|
|
|
56
57
|
每项配置按环境变量 > 用户文件 > 默认值解析。默认地址为 `http://localhost:8002/api/v1`,默认 Token 为空。环境变量只影响当前终端及其启动的子进程,不改文件;显式空 Token 环境变量会覆盖已保存密钥。
|
|
57
58
|
|
|
@@ -77,10 +78,32 @@ cd powerquant-examples/selection
|
|
|
77
78
|
pq data prepare --config prepare.json
|
|
78
79
|
```
|
|
79
80
|
|
|
80
|
-
按实际覆盖调整 prepare.json
|
|
81
|
+
按实际覆盖调整 prepare.json 的股票和日期,将返回的 data.manifest_path 写入 compute.json、select.json;按示例 README 执行 compute、select 和 backtest。不同使用目的的快照须分别通过完整性检查。
|
|
81
82
|
|
|
82
83
|
密钥到期或撤销后在线准备会失败,已下载快照仍可离线使用。行情密钥不用于定义发布;发布定义另使用 PQ_QUANT_URL/PQ_QUANT_TOKEN。默认本地目录为 ~/.powerquant。
|
|
83
84
|
|
|
85
|
+
## Agent 使用
|
|
86
|
+
|
|
87
|
+
命令结果统一输出 JSON `{status,data}`;错误以 JSON 写入 stderr,保留业务错误码、消息和 request_id,并返回非零退出码。
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
pq --version
|
|
91
|
+
pq skill list
|
|
92
|
+
pq skill show pq-bootstrap
|
|
93
|
+
pq skill check
|
|
94
|
+
pq init
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`pq init` 先返回安装计划。使用返回的 `data.expected_plan` 执行 `pq init --confirm --expected-plan <expected_plan>`,默认安装到 Codex 的 `~/.agents/skills` 和 Claude Code 的 `~/.claude/skills`。可用 `--agent codex|claude|both` 选择客户端,或用 `--skills-dir` 指定项目目录。Hint 仅写入显式提供的 `--hint-file`,保留受管块外的内容。
|
|
98
|
+
|
|
99
|
+
没有 Token 也可以初始化;需要连接行情时,按 bootstrap Skill 申请权限并通过 `pq config token` 安全录入。行情运维通过 PQData API/MCP 提交任务。
|
|
100
|
+
|
|
101
|
+
`pq upgrade` 先预览,再用 `--confirm --expected-plan <expected_plan>` 启动后台升级;通过 `pq agent upgrade-status <operation_id>` 查询结果。升级沿用 uv tool 或 pipx 安装渠道,并同步已登记的资源目录。`pq upgrade --skip-package` 仅同步资源。独立资源同步使用 `pq agent sync`,同样先预览再确认。
|
|
102
|
+
|
|
103
|
+
## 依赖生命周期
|
|
104
|
+
|
|
105
|
+
ApplicationContainer 接收 ApplicationSettings,按需组装明确的因子、回测、研究应用 Service,CLI 从 ctx.obj 获取。Service 依赖由构造函数显式传入;不维护通用 Repository 缓存、不查询全局容器、不在缺少上下文时静默创建容器。MarketClient 按需创建并由调用方 async with 关闭,本地 Repository 使用短事务。配置、帮助和资源查看不初始化数据库或联网。
|
|
106
|
+
|
|
84
107
|
## Python
|
|
85
108
|
|
|
86
109
|
公开请求模型与调用入口位于 quant_cli.api,与 CLI 使用同一应用服务。
|
|
@@ -30,7 +30,7 @@ pq config show
|
|
|
30
30
|
|
|
31
31
|
家庭 LAN 可配置 `http://192.168.8.142:18026/market/api/v1`;公网 IP 临时入口为 `http://82.157.167.33/market/api/v1`。公网 HTTP 会明文传输 Token,只适合已明确接受风险的临时接入;长期公网访问使用可信 HTTPS 或 SSH/WireGuard 加密链路。直接使用 `https://82.157.167.33` 与现有域名证书不匹配。
|
|
32
32
|
|
|
33
|
-
配置保存在当前系统用户的 `~/.powerquant/config.
|
|
33
|
+
配置保存在当前系统用户的 `~/.powerquant/config.yml`,与工作目录无关,不自动加载 `.env`。这是本地明文配置:POSIX 新目录权限 700、文件权限 600;Windows 依赖用户目录 ACL,不声称加密存储。不要提交或分享该文件。
|
|
34
34
|
|
|
35
35
|
每项配置按环境变量 > 用户文件 > 默认值解析。默认地址为 `http://localhost:8002/api/v1`,默认 Token 为空。环境变量只影响当前终端及其启动的子进程,不改文件;显式空 Token 环境变量会覆盖已保存密钥。
|
|
36
36
|
|
|
@@ -56,10 +56,32 @@ cd powerquant-examples/selection
|
|
|
56
56
|
pq data prepare --config prepare.json
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
按实际覆盖调整 prepare.json
|
|
59
|
+
按实际覆盖调整 prepare.json 的股票和日期,将返回的 data.manifest_path 写入 compute.json、select.json;按示例 README 执行 compute、select 和 backtest。不同使用目的的快照须分别通过完整性检查。
|
|
60
60
|
|
|
61
61
|
密钥到期或撤销后在线准备会失败,已下载快照仍可离线使用。行情密钥不用于定义发布;发布定义另使用 PQ_QUANT_URL/PQ_QUANT_TOKEN。默认本地目录为 ~/.powerquant。
|
|
62
62
|
|
|
63
|
+
## Agent 使用
|
|
64
|
+
|
|
65
|
+
命令结果统一输出 JSON `{status,data}`;错误以 JSON 写入 stderr,保留业务错误码、消息和 request_id,并返回非零退出码。
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
pq --version
|
|
69
|
+
pq skill list
|
|
70
|
+
pq skill show pq-bootstrap
|
|
71
|
+
pq skill check
|
|
72
|
+
pq init
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`pq init` 先返回安装计划。使用返回的 `data.expected_plan` 执行 `pq init --confirm --expected-plan <expected_plan>`,默认安装到 Codex 的 `~/.agents/skills` 和 Claude Code 的 `~/.claude/skills`。可用 `--agent codex|claude|both` 选择客户端,或用 `--skills-dir` 指定项目目录。Hint 仅写入显式提供的 `--hint-file`,保留受管块外的内容。
|
|
76
|
+
|
|
77
|
+
没有 Token 也可以初始化;需要连接行情时,按 bootstrap Skill 申请权限并通过 `pq config token` 安全录入。行情运维通过 PQData API/MCP 提交任务。
|
|
78
|
+
|
|
79
|
+
`pq upgrade` 先预览,再用 `--confirm --expected-plan <expected_plan>` 启动后台升级;通过 `pq agent upgrade-status <operation_id>` 查询结果。升级沿用 uv tool 或 pipx 安装渠道,并同步已登记的资源目录。`pq upgrade --skip-package` 仅同步资源。独立资源同步使用 `pq agent sync`,同样先预览再确认。
|
|
80
|
+
|
|
81
|
+
## 依赖生命周期
|
|
82
|
+
|
|
83
|
+
ApplicationContainer 接收 ApplicationSettings,按需组装明确的因子、回测、研究应用 Service,CLI 从 ctx.obj 获取。Service 依赖由构造函数显式传入;不维护通用 Repository 缓存、不查询全局容器、不在缺少上下文时静默创建容器。MarketClient 按需创建并由调用方 async with 关闭,本地 Repository 使用短事务。配置、帮助和资源查看不初始化数据库或联网。
|
|
84
|
+
|
|
63
85
|
## Python
|
|
64
86
|
|
|
65
87
|
公开请求模型与调用入口位于 quant_cli.api,与 CLI 使用同一应用服务。
|
|
@@ -30,6 +30,7 @@ from pqdata.schema.reference_schema import (
|
|
|
30
30
|
TradingRuleResponse,
|
|
31
31
|
)
|
|
32
32
|
from pqdata.schema.reliability_schema import DatasetHealthResult
|
|
33
|
+
from pqdata.schema.snapshot_schema import PREPARATION_DATASETS, DatasetSnapshot, SnapshotQuery
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
class MarketClient:
|
|
@@ -101,12 +102,50 @@ class MarketClient:
|
|
|
101
102
|
await response.aclose()
|
|
102
103
|
await asyncio.sleep(delay)
|
|
103
104
|
if not response.is_success:
|
|
104
|
-
|
|
105
|
+
code: str | int | None = None
|
|
106
|
+
message: str | None = None
|
|
107
|
+
request_id = response.headers.get("x-request-id")
|
|
108
|
+
if "application/json" in response.headers.get("content-type", ""):
|
|
109
|
+
try:
|
|
110
|
+
error = response.json()
|
|
111
|
+
except ValueError:
|
|
112
|
+
error = None
|
|
113
|
+
if isinstance(error, dict):
|
|
114
|
+
candidate = error.get("error_code", error.get("code"))
|
|
115
|
+
if isinstance(candidate, (str, int)) and not isinstance(candidate, bool):
|
|
116
|
+
code = candidate
|
|
117
|
+
candidate = error.get("message")
|
|
118
|
+
if isinstance(candidate, str) and 0 < len(candidate) <= 512:
|
|
119
|
+
message = candidate
|
|
120
|
+
candidate = error.get("request_id")
|
|
121
|
+
if isinstance(candidate, str) and len(candidate) <= 128:
|
|
122
|
+
request_id = request_id or candidate
|
|
123
|
+
raise MarketAPIError(response.status_code, request_id, code=code, message=message)
|
|
105
124
|
try:
|
|
106
125
|
return TypeAdapter(response_type).validate_json(response.content)
|
|
107
126
|
except ValidationError as error:
|
|
108
127
|
raise MarketProtocolError("Invalid market response") from error
|
|
109
128
|
|
|
129
|
+
async def resolve_snapshot(
|
|
130
|
+
self,
|
|
131
|
+
datasets: list[str],
|
|
132
|
+
*,
|
|
133
|
+
instrument_ids: list[str] | None = None,
|
|
134
|
+
start: date | None = None,
|
|
135
|
+
end: date | None = None,
|
|
136
|
+
) -> DatasetSnapshot:
|
|
137
|
+
query = SnapshotQuery(
|
|
138
|
+
datasets=datasets, instrument_ids=instrument_ids or [], start=start, end=end
|
|
139
|
+
)
|
|
140
|
+
return await self._request(
|
|
141
|
+
"POST", "snapshots/resolve", DatasetSnapshot, body=query.model_dump(mode="json")
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
async def inspect_snapshot(self, snapshot_id: str) -> DatasetSnapshot:
|
|
145
|
+
return await self._request(
|
|
146
|
+
"GET", f"snapshots/{quote(snapshot_id, safe='')}", DatasetSnapshot
|
|
147
|
+
)
|
|
148
|
+
|
|
110
149
|
async def get_instrument(self, instrument_id: str) -> InstrumentResponse:
|
|
111
150
|
return await self._request(
|
|
112
151
|
"GET",
|
|
@@ -115,6 +154,9 @@ class MarketClient:
|
|
|
115
154
|
)
|
|
116
155
|
|
|
117
156
|
async def get_history_facts(self, query: HistoryFactsQuery) -> HistoryFacts:
|
|
157
|
+
if query.revision is None:
|
|
158
|
+
snapshot = await self.resolve_snapshot(PREPARATION_DATASETS)
|
|
159
|
+
query = query.model_copy(update={"revision": snapshot.snapshot_id})
|
|
118
160
|
result = await self._request(
|
|
119
161
|
"POST", "history/facts", HistoryFacts, body=query.model_dump(mode="json")
|
|
120
162
|
)
|
|
@@ -170,8 +212,11 @@ class MarketClient:
|
|
|
170
212
|
frequency: str,
|
|
171
213
|
start: datetime,
|
|
172
214
|
end: datetime,
|
|
215
|
+
*,
|
|
216
|
+
revision: str,
|
|
173
217
|
) -> DatasetHealthResult:
|
|
174
218
|
query = DataHealthQuery(
|
|
219
|
+
revision=revision,
|
|
175
220
|
instrument_id=instrument_id,
|
|
176
221
|
frequency=TypeAdapter(BarFrequency).validate_python(frequency),
|
|
177
222
|
start=start,
|
|
@@ -187,8 +232,11 @@ class MarketClient:
|
|
|
187
232
|
frequency: str,
|
|
188
233
|
start: datetime,
|
|
189
234
|
end: datetime,
|
|
235
|
+
*,
|
|
236
|
+
revision: str,
|
|
190
237
|
) -> DatasetHealthResult:
|
|
191
238
|
query = DataHealthQuery(
|
|
239
|
+
revision=revision,
|
|
192
240
|
instrument_id=instrument_id,
|
|
193
241
|
frequency=TypeAdapter(BarFrequency).validate_python(frequency),
|
|
194
242
|
start=start,
|
|
@@ -206,8 +254,12 @@ class MarketClient:
|
|
|
206
254
|
instrument_id: str,
|
|
207
255
|
start: datetime,
|
|
208
256
|
end: datetime,
|
|
257
|
+
*,
|
|
258
|
+
revision: str,
|
|
209
259
|
) -> DatasetHealthResult:
|
|
210
|
-
query = DataHealthQuery(
|
|
260
|
+
query = DataHealthQuery(
|
|
261
|
+
revision=revision, instrument_id=instrument_id, start=start, end=end
|
|
262
|
+
)
|
|
211
263
|
return await self._request(
|
|
212
264
|
"POST",
|
|
213
265
|
"verify/corporate-actions",
|
|
@@ -215,23 +267,13 @@ class MarketClient:
|
|
|
215
267
|
body=query.model_dump(mode="json"),
|
|
216
268
|
)
|
|
217
269
|
|
|
218
|
-
async def snapshot(self, start: date, end: date) -> dict[str, str]:
|
|
219
|
-
return await self._request(
|
|
220
|
-
"GET",
|
|
221
|
-
"revisions",
|
|
222
|
-
dict[str, str],
|
|
223
|
-
params={
|
|
224
|
-
"start": start.isoformat(),
|
|
225
|
-
"end": end.isoformat(),
|
|
226
|
-
},
|
|
227
|
-
)
|
|
228
|
-
|
|
229
270
|
async def search_instruments(
|
|
230
271
|
self,
|
|
231
272
|
keyword: str | None = None,
|
|
232
273
|
instrument_type: str | None = None,
|
|
233
274
|
exchange: str | None = None,
|
|
234
275
|
limit: int = 100,
|
|
276
|
+
revision: str | None = None,
|
|
235
277
|
) -> list[InstrumentResponse]:
|
|
236
278
|
params = {
|
|
237
279
|
key: value
|
|
@@ -243,6 +285,8 @@ class MarketClient:
|
|
|
243
285
|
}.items()
|
|
244
286
|
if value is not None
|
|
245
287
|
}
|
|
288
|
+
if revision is not None:
|
|
289
|
+
params["revision"] = revision
|
|
246
290
|
return await self._request("GET", "instruments", list[InstrumentResponse], params=params)
|
|
247
291
|
|
|
248
292
|
async def list_instruments_on(
|
|
@@ -337,6 +381,9 @@ class MarketClient:
|
|
|
337
381
|
|
|
338
382
|
async def query_bars(self, query: BarQuery) -> BarPage:
|
|
339
383
|
"""读取一页数据;错误内容不混入行情结果。"""
|
|
384
|
+
if query.revision is None:
|
|
385
|
+
snapshot = await self.resolve_snapshot(["bar"])
|
|
386
|
+
query = query.model_copy(update={"revision": snapshot.snapshot_id})
|
|
340
387
|
page = await self._request(
|
|
341
388
|
"POST", "bars/query", BarPage, body=query.model_dump(mode="json")
|
|
342
389
|
)
|
|
@@ -359,6 +406,9 @@ class MarketClient:
|
|
|
359
406
|
|
|
360
407
|
async def describe_bars(self, query: BarQuery) -> BarContent:
|
|
361
408
|
"""只传输范围摘要;服务端仍需扫描数据,不能视为常数成本的查询。"""
|
|
409
|
+
if query.revision is None:
|
|
410
|
+
snapshot = await self.resolve_snapshot(["bar"])
|
|
411
|
+
query = query.model_copy(update={"revision": snapshot.snapshot_id})
|
|
362
412
|
if query.cursor is not None:
|
|
363
413
|
raise ValueError("Content queries must start at the first page")
|
|
364
414
|
result = await self._request(
|
|
@@ -4,10 +4,14 @@
|
|
|
4
4
|
class MarketAPIError(Exception):
|
|
5
5
|
"""服务拒绝请求;保留状态码和可追踪的请求 ID,不暴露凭据。"""
|
|
6
6
|
|
|
7
|
-
def __init__(self, status_code: int, request_id: str | None = None
|
|
7
|
+
def __init__(self, status_code: int, request_id: str | None = None,
|
|
8
|
+
*, code: str | int | None = None, message: str | None = None) -> None:
|
|
8
9
|
self.status_code = status_code
|
|
9
10
|
self.request_id = request_id
|
|
10
|
-
|
|
11
|
+
self.code = code if code is not None else f"HTTP_{status_code}"
|
|
12
|
+
self.message = message or f"行情请求失败(HTTP {status_code})"
|
|
13
|
+
super().__init__(self.message)
|
|
14
|
+
|
|
11
15
|
|
|
12
16
|
|
|
13
17
|
class MarketProtocolError(Exception):
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""固定的数据集版本组合;内容身份和覆盖凭证独立表达。"""
|
|
2
|
+
|
|
3
|
+
from datetime import date
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
|
6
|
+
|
|
7
|
+
PREPARATION_DATASETS = [
|
|
8
|
+
"bar",
|
|
9
|
+
"instrument",
|
|
10
|
+
"trading_calendar",
|
|
11
|
+
"trading_rule",
|
|
12
|
+
"instrument_daily_fact",
|
|
13
|
+
"adjustment_factor",
|
|
14
|
+
"corporate_action",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class SnapshotQuery(BaseModel):
|
|
19
|
+
model_config = ConfigDict(extra="forbid")
|
|
20
|
+
datasets: list[str] = Field(min_length=1, max_length=9)
|
|
21
|
+
instrument_ids: list[str] = Field(default_factory=list, max_length=10000)
|
|
22
|
+
start: date | None = None
|
|
23
|
+
end: date | None = None
|
|
24
|
+
|
|
25
|
+
@model_validator(mode="after")
|
|
26
|
+
def scoped(self) -> "SnapshotQuery":
|
|
27
|
+
if (self.start is None) != (self.end is None):
|
|
28
|
+
raise ValueError("start 和 end 必须同时提供")
|
|
29
|
+
if self.start is not None and self.end is not None:
|
|
30
|
+
if not self.instrument_ids or not 0 <= (self.end - self.start).days <= 3660:
|
|
31
|
+
raise ValueError("范围解析需要标的及不超过十年的有效日期区间")
|
|
32
|
+
if not {"instrument", "trading_calendar"}.issubset(self.datasets):
|
|
33
|
+
raise ValueError("范围解析需要标的和交易日历数据集")
|
|
34
|
+
elif self.instrument_ids:
|
|
35
|
+
raise ValueError("标的范围需要日期区间")
|
|
36
|
+
return self
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class DatasetVersionInfo(BaseModel):
|
|
40
|
+
rules_version: int = Field(ge=1)
|
|
41
|
+
contract_version: int = Field(ge=1)
|
|
42
|
+
version_id: str
|
|
43
|
+
root_hash: str
|
|
44
|
+
coverage: dict
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class DatasetSnapshot(BaseModel):
|
|
48
|
+
snapshot_id: str
|
|
49
|
+
root_hash: str
|
|
50
|
+
datasets: dict[str, DatasetVersionInfo]
|
|
@@ -43,8 +43,10 @@ async def run(day: date, output: Path, minimum_amount: Decimal, top: int) -> dic
|
|
|
43
43
|
if observed_at <= end:
|
|
44
44
|
raise ValueError("只支持已结束的历史交易日")
|
|
45
45
|
async with build_market_query() as client:
|
|
46
|
-
revision = (
|
|
47
|
-
|
|
46
|
+
revision = (
|
|
47
|
+
await client.resolve_snapshot(["bar", "instrument", "trading_calendar"])
|
|
48
|
+
).snapshot_id
|
|
49
|
+
catalog = await client.search_instruments(limit=10000, revision=revision)
|
|
48
50
|
if len(catalog) >= 10000:
|
|
49
51
|
raise ValueError("标的目录可能截断,拒绝冒充全市场")
|
|
50
52
|
stocks = [i for i in catalog if i.instrument_type == "stock"]
|
|
@@ -72,8 +74,6 @@ async def run(day: date, output: Path, minimum_amount: Decimal, top: int) -> dic
|
|
|
72
74
|
raise ValueError("同一证券出现重复日线")
|
|
73
75
|
bars[bar.instrument_id] = bar
|
|
74
76
|
print(f"已读取 {min(offset + 1000, len(ids))}/{len(ids)} 只候选", flush=True)
|
|
75
|
-
if (await client.snapshot(day, day))["canonical"] != revision:
|
|
76
|
-
raise ValueError("读取期间数据修订变化,请重新运行")
|
|
77
77
|
if not bars:
|
|
78
78
|
raise ValueError("当日无日线数据")
|
|
79
79
|
reasons = dict.fromkeys(unknown_listing, "unknown_listing_date")
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "powerquant-cli"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.10"
|
|
4
4
|
description = "Power Quant local research CLI"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
7
7
|
license = "LicenseRef-PowerQuant-Proprietary AND MIT"
|
|
8
8
|
license-files = ["LICENSE", "licenses/LICENSE.vnpy"]
|
|
9
|
-
dependencies = ["pydantic>=2.5,<3", "polars>=1.36,<2", "numpy>=2,<3", "scipy>=1.17,<2", "pandas>=3,<4", "tzdata>=2026.3", "typer>=0.27.2", "httpx>=0.28,<1", "duckdb>=1.4,<2", "filelock>=3.20,<4"]
|
|
9
|
+
dependencies = ["pydantic>=2.5,<3", "polars>=1.36,<2", "numpy>=2,<3", "scipy>=1.17,<2", "pandas>=3,<4", "tzdata>=2026.3", "typer>=0.27.2", "httpx>=0.28,<1", "duckdb>=1.4,<2", "filelock>=3.20,<4", "pyyaml>=6,<7"]
|
|
10
10
|
|
|
11
11
|
[project.urls]
|
|
12
12
|
Repository = "https://github.com/Kepler452Byte/power-quant"
|
|
@@ -19,7 +19,7 @@ build-backend = "hatchling.build"
|
|
|
19
19
|
packages = ["src/quant_cli"]
|
|
20
20
|
|
|
21
21
|
[dependency-groups]
|
|
22
|
-
dev = ["powerquant-core==0.2.6", "powerquant-market==0.
|
|
22
|
+
dev = ["powerquant-core==0.2.6", "powerquant-market==0.3.0", "pytest>=8", "pytest-asyncio>=0.24", "ruff>=0.6", "pyright>=1.1.380"]
|
|
23
23
|
[tool.ruff]
|
|
24
24
|
line-length = 100
|
|
25
25
|
target-version = "py312"
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""Agent 资源命令:发现随包内容、预览安装与同步。"""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Annotated
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
|
|
8
|
+
from quant_cli.app.agent_resources.schema.agent_resource_schema import AgentTarget
|
|
9
|
+
from quant_cli.app.cli_dependency import container
|
|
10
|
+
from quant_cli.common.command_error_handler import CommandGroup
|
|
11
|
+
from quant_cli.common.command_help import Command
|
|
12
|
+
from quant_cli.common.utils.cli_utils import cli_errors, output
|
|
13
|
+
|
|
14
|
+
app = typer.Typer(cls=CommandGroup, no_args_is_help=True, help="安装和同步受管 Agent 资源")
|
|
15
|
+
skill_app = typer.Typer(cls=CommandGroup, no_args_is_help=True, help="查看并校验随包 Skill")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@skill_app.command("list", cls=Command)
|
|
19
|
+
@cli_errors
|
|
20
|
+
def list_skills(ctx: typer.Context) -> None:
|
|
21
|
+
output(container(ctx).agent_resource_service.list_skills())
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@skill_app.command("show", cls=Command)
|
|
25
|
+
@cli_errors
|
|
26
|
+
def show_skill(ctx: typer.Context, name: str, file: str = typer.Option("SKILL.md")) -> None:
|
|
27
|
+
output(container(ctx).agent_resource_service.show(name, file))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@skill_app.command("check", cls=Command)
|
|
31
|
+
@cli_errors
|
|
32
|
+
def check_skills(ctx: typer.Context) -> None:
|
|
33
|
+
output(container(ctx).agent_resource_service.check())
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@app.command("install", cls=Command)
|
|
37
|
+
@cli_errors
|
|
38
|
+
def install_agent(
|
|
39
|
+
ctx: typer.Context,
|
|
40
|
+
agent: Annotated[AgentTarget, typer.Option()] = AgentTarget.BOTH,
|
|
41
|
+
skills_dir: Annotated[
|
|
42
|
+
Path | None, typer.Option(help="自定义 Skill 目录,替代客户端默认目录")
|
|
43
|
+
] = None,
|
|
44
|
+
hint_file: Annotated[list[Path] | None, typer.Option(help="显式 Hint 目标,可重复")] = None,
|
|
45
|
+
confirm: bool = typer.Option(False),
|
|
46
|
+
expected_plan: str | None = typer.Option(None),
|
|
47
|
+
) -> None:
|
|
48
|
+
result = container(ctx).bootstrap_service.install(
|
|
49
|
+
agent.value, skills_dir, tuple(hint_file or ()), confirm, expected_plan
|
|
50
|
+
)
|
|
51
|
+
output(result, status="applied" if confirm else "planned")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@app.command("sync", cls=Command)
|
|
55
|
+
@cli_errors
|
|
56
|
+
def sync_agent(
|
|
57
|
+
ctx: typer.Context,
|
|
58
|
+
confirm: bool = typer.Option(False),
|
|
59
|
+
expected_plan: str | None = typer.Option(None),
|
|
60
|
+
) -> None:
|
|
61
|
+
output(
|
|
62
|
+
container(ctx).agent_resource_service.sync(confirm, expected_plan),
|
|
63
|
+
status="applied" if confirm else "planned",
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def register_agent_commands(root: typer.Typer) -> typer.Typer:
|
|
68
|
+
root.add_typer(skill_app, name="skill")
|
|
69
|
+
root.add_typer(app, name="agent")
|
|
70
|
+
return app
|
powerquant_cli-0.2.10/src/quant_cli/app/agent_resources/interface/public/agent_resource_sync.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Public resource alignment port used by system upgrade."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Protocol
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class IAgentResourceSync(Protocol):
|
|
8
|
+
def sync(
|
|
9
|
+
self,
|
|
10
|
+
confirm: bool = False,
|
|
11
|
+
expected_plan: str | None = None,
|
|
12
|
+
skills_dirs: tuple[Path, ...] = (),
|
|
13
|
+
hint_files: tuple[Path, ...] = (),
|
|
14
|
+
) -> dict[str, object]: ...
|
powerquant_cli-0.2.10/src/quant_cli/app/agent_resources/repository/agent_resource_repository.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Read packaged assets and persist explicitly addressed files."""
|
|
2
|
+
|
|
3
|
+
from contextlib import AbstractContextManager
|
|
4
|
+
from importlib import metadata, resources
|
|
5
|
+
from importlib.resources.abc import Traversable
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from quant_cli.common.filesystem import atomic_write, read_bytes, safe_path, write_lock
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AgentResourceRepository:
|
|
12
|
+
def __init__(
|
|
13
|
+
self, distribution: str, command: str, state_root: Path, package: str = "quant_cli"
|
|
14
|
+
):
|
|
15
|
+
self.distribution = distribution
|
|
16
|
+
self.command = command
|
|
17
|
+
self.state_root = state_root.expanduser().absolute()
|
|
18
|
+
self.package = package
|
|
19
|
+
self.registry_path = self.state_root / "resources.json"
|
|
20
|
+
|
|
21
|
+
def assets(self) -> dict[str, bytes]:
|
|
22
|
+
root = resources.files(self.package).joinpath("resources", "skills")
|
|
23
|
+
assets: dict[str, bytes] = {}
|
|
24
|
+
|
|
25
|
+
def visit(node: Traversable, prefix: str) -> None:
|
|
26
|
+
for child in sorted(node.iterdir(), key=lambda item: item.name):
|
|
27
|
+
relative = prefix + child.name
|
|
28
|
+
if child.is_dir():
|
|
29
|
+
visit(child, relative + "/")
|
|
30
|
+
else:
|
|
31
|
+
assets[relative] = child.read_bytes()
|
|
32
|
+
|
|
33
|
+
if root.is_dir():
|
|
34
|
+
visit(root, "")
|
|
35
|
+
return assets
|
|
36
|
+
|
|
37
|
+
def version(self) -> str:
|
|
38
|
+
return metadata.version(self.distribution)
|
|
39
|
+
|
|
40
|
+
def hint(self) -> bytes:
|
|
41
|
+
path = resources.files(self.package).joinpath("resources", "agent_hint.md")
|
|
42
|
+
return path.read_bytes() if path.is_file() else b""
|
|
43
|
+
|
|
44
|
+
def resolve(self, path: Path) -> Path:
|
|
45
|
+
return safe_path(path)
|
|
46
|
+
|
|
47
|
+
def read(self, path: Path) -> bytes | None:
|
|
48
|
+
return read_bytes(path)
|
|
49
|
+
|
|
50
|
+
def write(self, path: Path, content: bytes) -> None:
|
|
51
|
+
atomic_write(path, content)
|
|
52
|
+
|
|
53
|
+
def remove(self, path: Path) -> None:
|
|
54
|
+
safe_path(path).unlink(missing_ok=True)
|
|
55
|
+
|
|
56
|
+
def lock(self, targets: list[Path]) -> AbstractContextManager[None]:
|
|
57
|
+
return write_lock(self.state_root, targets)
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""Resource ownership records and explicit synchronization plans."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from dataclasses import asdict, dataclass
|
|
7
|
+
from enum import StrEnum
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from quant_cli.common.hashing import digest
|
|
11
|
+
from quant_cli.common.operation_error import OperationError
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class AgentTarget(StrEnum):
|
|
15
|
+
CODEX = "codex"
|
|
16
|
+
CLAUDE = "claude"
|
|
17
|
+
BOTH = "both"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass(frozen=True)
|
|
21
|
+
class OwnedFile:
|
|
22
|
+
path: str
|
|
23
|
+
kind: str
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class Registry:
|
|
28
|
+
distribution: str
|
|
29
|
+
skills: list[str]
|
|
30
|
+
hints: list[str]
|
|
31
|
+
files: list[OwnedFile]
|
|
32
|
+
|
|
33
|
+
@classmethod
|
|
34
|
+
def load(cls, raw: bytes, distribution: str) -> Registry:
|
|
35
|
+
try:
|
|
36
|
+
data = json.loads(raw)
|
|
37
|
+
if (
|
|
38
|
+
not isinstance(data, dict)
|
|
39
|
+
or set(data) != {"distribution", "skills", "hints", "files"}
|
|
40
|
+
or data.get("distribution") != distribution
|
|
41
|
+
):
|
|
42
|
+
raise ValueError("identity")
|
|
43
|
+
skills, hints, files = data["skills"], data["hints"], data["files"]
|
|
44
|
+
if not all(isinstance(items, list) for items in (skills, hints, files)):
|
|
45
|
+
raise ValueError("lists")
|
|
46
|
+
if not all(isinstance(item, str) for item in [*skills, *hints]):
|
|
47
|
+
raise ValueError("paths")
|
|
48
|
+
if not all(Path(item).is_absolute() for item in [*skills, *hints]):
|
|
49
|
+
raise ValueError("absolute paths")
|
|
50
|
+
owned: list[OwnedFile] = []
|
|
51
|
+
for item in files:
|
|
52
|
+
if (
|
|
53
|
+
not isinstance(item, dict)
|
|
54
|
+
or set(item) != {"path", "kind"}
|
|
55
|
+
or not all(isinstance(item.get(key), str) for key in ("path", "kind"))
|
|
56
|
+
):
|
|
57
|
+
raise ValueError("files")
|
|
58
|
+
if item["kind"] not in {"skill", "hint"}:
|
|
59
|
+
raise ValueError("kind")
|
|
60
|
+
owned.append(OwnedFile(item["path"], item["kind"]))
|
|
61
|
+
if len({item.path for item in owned}) != len(owned):
|
|
62
|
+
raise ValueError("duplicate paths")
|
|
63
|
+
return cls(distribution, skills, hints, owned)
|
|
64
|
+
except (ValueError, KeyError, TypeError) as exc:
|
|
65
|
+
raise OperationError(
|
|
66
|
+
"Resource registry is invalid; preserve it and repair explicitly",
|
|
67
|
+
"invalid-registry",
|
|
68
|
+
) from exc
|
|
69
|
+
|
|
70
|
+
def encode(self) -> bytes:
|
|
71
|
+
return (
|
|
72
|
+
json.dumps(asdict(self), sort_keys=True, ensure_ascii=False, indent=2) + "\n"
|
|
73
|
+
).encode()
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass(frozen=True)
|
|
77
|
+
class Change:
|
|
78
|
+
path: Path
|
|
79
|
+
before: str
|
|
80
|
+
content: bytes | None
|
|
81
|
+
action: str
|
|
82
|
+
|
|
83
|
+
def describe(self) -> dict[str, str]:
|
|
84
|
+
return {
|
|
85
|
+
"path": str(self.path),
|
|
86
|
+
"action": self.action,
|
|
87
|
+
"expected_hash": self.before,
|
|
88
|
+
"new_hash": digest(self.content),
|
|
89
|
+
}
|