powerquant-cli 0.2.6__tar.gz → 0.2.7__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.
Files changed (420) hide show
  1. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/.gitignore +0 -2
  2. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/PKG-INFO +34 -6
  3. powerquant_cli-0.2.7/README.md +69 -0
  4. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/pyproject.toml +1 -1
  5. powerquant_cli-0.2.7/src/quant_cli/app/config/__init__.py +1 -0
  6. powerquant_cli-0.2.7/src/quant_cli/app/config/config_cli.py +71 -0
  7. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/data/data_dependency.py +6 -6
  8. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/quant_cli.py +2 -0
  9. powerquant_cli-0.2.7/src/quant_cli/config/__init__.py +1 -0
  10. powerquant_cli-0.2.7/src/quant_cli/config/connection_config.py +133 -0
  11. powerquant_cli-0.2.7/tests/unit/test_connection_config.py +169 -0
  12. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/uv.lock +1 -1
  13. powerquant_cli-0.2.6/README.md +0 -41
  14. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/.env.example +0 -0
  15. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/LICENSE +0 -0
  16. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/pqdata/__init__.py +0 -0
  17. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/pqdata/client.py +0 -0
  18. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/pqdata/download.py +0 -0
  19. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/pqdata/exceptions.py +0 -0
  20. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/pqdata/schema/__init__.py +0 -0
  21. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/pqdata/schema/adjustment_schema.py +0 -0
  22. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/pqdata/schema/bar_content_schema.py +0 -0
  23. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/pqdata/schema/bar_schema.py +0 -0
  24. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/pqdata/schema/corporate_action_schema.py +0 -0
  25. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/pqdata/schema/history_schema.py +0 -0
  26. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/pqdata/schema/pit_daily_window.py +0 -0
  27. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/pqdata/schema/query_schema.py +0 -0
  28. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/pqdata/schema/quote_schema.py +0 -0
  29. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/pqdata/schema/reference_schema.py +0 -0
  30. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/pqdata/schema/reliability_schema.py +0 -0
  31. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/__init__.py +0 -0
  32. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/SPEC.md +0 -0
  33. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/__init__.py +0 -0
  34. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/backtest/SPEC.md +0 -0
  35. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/backtest/__init__.py +0 -0
  36. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/backtest/backtest_input_schema.py +0 -0
  37. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/backtest/backtest_run.py +0 -0
  38. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/backtest/data_guard.py +0 -0
  39. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/backtest/historical_clock.py +0 -0
  40. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/backtest/legacy_result_schema.py +0 -0
  41. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/backtest/metrics.py +0 -0
  42. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/backtest/performance_report.py +0 -0
  43. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/backtest/report_schema.py +0 -0
  44. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/backtest/schema.py +0 -0
  45. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/backtest/service/__init__.py +0 -0
  46. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/backtest/service/backtest_execution_service.py +0 -0
  47. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/__init__.py +0 -0
  48. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/constants.py +0 -0
  49. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/domain/__init__.py +0 -0
  50. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/domain/trading_quantity_value.py +0 -0
  51. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/exceptions.py +0 -0
  52. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/interface/__init__.py +0 -0
  53. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/interface/adjustment_factor_query.py +0 -0
  54. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/interface/market_data_query.py +0 -0
  55. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/interface/market_data_verification.py +0 -0
  56. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/interface/market_event_source.py +0 -0
  57. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/interface/market_revision_query.py +0 -0
  58. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/interface/market_runtime_repository.py +0 -0
  59. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/interface/market_time_slice_source.py +0 -0
  60. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/repository/__init__.py +0 -0
  61. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/schema/__init__.py +0 -0
  62. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/schema/adjustment_schema.py +0 -0
  63. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/schema/corporate_action_schema.py +0 -0
  64. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/schema/event_schema.py +0 -0
  65. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/schema/exchange_operating_state.py +0 -0
  66. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/schema/exchange_state_schema.py +0 -0
  67. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/schema/history_schema.py +0 -0
  68. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/schema/instrument_identity.py +0 -0
  69. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/schema/market_schema.py +0 -0
  70. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/schema/pit_daily_window.py +0 -0
  71. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/schema/quote_schema.py +0 -0
  72. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/schema/reliability_schema.py +0 -0
  73. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/schema/snapshot_schema.py +0 -0
  74. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/schema/trading_state_schema.py +0 -0
  75. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/service/__init__.py +0 -0
  76. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/service/calendar_coverage_service.py +0 -0
  77. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/service/prepared_data_verification_service.py +0 -0
  78. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/service/prepared_market_service.py +0 -0
  79. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/data/service/price_adjustment_service.py +0 -0
  80. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/LICENSE.vnpy +0 -0
  81. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/__init__.py +0 -0
  82. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/builtin/__init__.py +0 -0
  83. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/builtin/alpha101_recipe.py +0 -0
  84. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/builtin/alpha158_recipe.py +0 -0
  85. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/builtin/factor_recipe_catalog.py +0 -0
  86. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/computation/__init__.py +0 -0
  87. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/computation/factor_batch_evaluator.py +0 -0
  88. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/computation/factor_expression.py +0 -0
  89. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/computation/factor_source_loader.py +0 -0
  90. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/computation/operators/__init__.py +0 -0
  91. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/computation/operators/arithmetic_operator.py +0 -0
  92. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/computation/operators/cross_section_operator.py +0 -0
  93. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/computation/operators/time_series_operator.py +0 -0
  94. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/computation/panel_evaluator.py +0 -0
  95. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/computation/panel_expression.py +0 -0
  96. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/computation/python_factor_executor.py +0 -0
  97. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/computation/universe_filter.py +0 -0
  98. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/constants.py +0 -0
  99. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/exceptions.py +0 -0
  100. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/factor_dependency.py +0 -0
  101. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/interface/__init__.py +0 -0
  102. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/interface/factor_compute.py +0 -0
  103. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/interface/factor_execution.py +0 -0
  104. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/interface/factor_local_data.py +0 -0
  105. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/interface/factor_panel_compute.py +0 -0
  106. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/interface/factor_panel_input.py +0 -0
  107. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/interface/factor_query_store.py +0 -0
  108. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/interface/public/__init__.py +0 -0
  109. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/interface/public/factor_diagnostics.py +0 -0
  110. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/interface/public/factor_exposure_query.py +0 -0
  111. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/interface/public/factor_local.py +0 -0
  112. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/interface/public/factor_query.py +0 -0
  113. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/interface/public/factor_selection.py +0 -0
  114. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/model/__init__.py +0 -0
  115. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/repository/__init__.py +0 -0
  116. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/schema/__init__.py +0 -0
  117. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/schema/diagnostic_types.py +0 -0
  118. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/schema/factor_artifact_schema.py +0 -0
  119. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/schema/factor_computation_schema.py +0 -0
  120. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/schema/factor_compute_request.py +0 -0
  121. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/schema/factor_contract.py +0 -0
  122. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/schema/factor_input_schema.py +0 -0
  123. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/schema/factor_panel.py +0 -0
  124. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/schema/factor_publication_schema.py +0 -0
  125. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/schema/factor_query_result_schema.py +0 -0
  126. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/schema/factor_result_schema.py +0 -0
  127. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/schema/local_factor_schema.py +0 -0
  128. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/schema/panel_policy.py +0 -0
  129. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/schema/selection_report.py +0 -0
  130. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/schema/selection_types.py +0 -0
  131. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/service/__init__.py +0 -0
  132. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/service/factor_compute_service.py +0 -0
  133. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/service/factor_diagnostic_runner.py +0 -0
  134. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/service/factor_diagnostics_service.py +0 -0
  135. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/service/factor_exposure_service.py +0 -0
  136. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/service/factor_input_service.py +0 -0
  137. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/service/factor_local_execution_service.py +0 -0
  138. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/service/factor_panel_service.py +0 -0
  139. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/service/factor_runtime_service.py +0 -0
  140. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/service/factor_selection_runner.py +0 -0
  141. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/service/published_factor_execution_service.py +0 -0
  142. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/service/selection_service.py +0 -0
  143. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/factor/visibility.py +0 -0
  144. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/opportunity/SPEC.md +0 -0
  145. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/opportunity/__init__.py +0 -0
  146. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/SPEC.md +0 -0
  147. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/__init__.py +0 -0
  148. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/bar_matcher.py +0 -0
  149. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/constants.py +0 -0
  150. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/domain/__init__.py +0 -0
  151. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/domain/execution_batch.py +0 -0
  152. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/domain/order_entity.py +0 -0
  153. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/domain/order_event.py +0 -0
  154. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/domain/order_policy.py +0 -0
  155. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/domain/order_value.py +0 -0
  156. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/fee_model.py +0 -0
  157. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/interface/__init__.py +0 -0
  158. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/interface/order_account.py +0 -0
  159. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/interface/order_trading_rules.py +0 -0
  160. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/interface/public/__init__.py +0 -0
  161. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/interface/public/execution_account.py +0 -0
  162. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/interface/public/order_events.py +0 -0
  163. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/interface/public/order_execution.py +0 -0
  164. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/interface/public/order_runtime.py +0 -0
  165. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/interface/public/order_submission.py +0 -0
  166. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/order_event_bus.py +0 -0
  167. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/order_execution_dependency.py +0 -0
  168. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/order_submission_service.py +0 -0
  169. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/schema/__init__.py +0 -0
  170. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/schema/order_request_schema.py +0 -0
  171. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/simulation_broker.py +0 -0
  172. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/slippage_model.py +0 -0
  173. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/tradability_policy.py +0 -0
  174. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/order_execution/validators.py +0 -0
  175. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/SPEC.md +0 -0
  176. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/__init__.py +0 -0
  177. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/domain/__init__.py +0 -0
  178. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/domain/entitlement_entity.py +0 -0
  179. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/domain/portfolio_entity.py +0 -0
  180. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/domain/portfolio_event.py +0 -0
  181. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/domain/portfolio_value.py +0 -0
  182. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/domain/position_entity.py +0 -0
  183. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/domain/reservation_entity.py +0 -0
  184. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/interface/__init__.py +0 -0
  185. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/interface/public/__init__.py +0 -0
  186. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/interface/public/portfolio.py +0 -0
  187. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/interface/public/simulation_account.py +0 -0
  188. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/ledger_schema.py +0 -0
  189. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/order_account_listener.py +0 -0
  190. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/portfolio_dependency.py +0 -0
  191. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/portfolio_schema.py +0 -0
  192. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/portfolio/simulated_portfolio.py +0 -0
  193. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/research/SPEC.md +0 -0
  194. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/research/__init__.py +0 -0
  195. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/research/adapter/__init__.py +0 -0
  196. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/research/adapter/market_label_query.py +0 -0
  197. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/research/interface/__init__.py +0 -0
  198. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/research/interface/research_dataset.py +0 -0
  199. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/research/interface/research_evaluation.py +0 -0
  200. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/research/schema/__init__.py +0 -0
  201. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/research/schema/comparison_schema.py +0 -0
  202. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/research/schema/dataset_schema.py +0 -0
  203. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/research/schema/research_schema.py +0 -0
  204. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/research/service/__init__.py +0 -0
  205. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/research/service/research_dataset_service.py +0 -0
  206. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/research/service/research_evaluation_service.py +0 -0
  207. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/research/service/research_service.py +0 -0
  208. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/SPEC.md +0 -0
  209. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/__init__.py +0 -0
  210. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/constants.py +0 -0
  211. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/exceptions.py +0 -0
  212. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/interface/__init__.py +0 -0
  213. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/interface/public/__init__.py +0 -0
  214. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/interface/public/portfolio_construction.py +0 -0
  215. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/interface/public/strategy.py +0 -0
  216. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/interface/public/strategy_market_query.py +0 -0
  217. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/interface/public/strategy_portfolio_reader.py +0 -0
  218. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/interface/strategy_factor_reader.py +0 -0
  219. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/interface/strategy_order_reader.py +0 -0
  220. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/schema/__init__.py +0 -0
  221. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/schema/portfolio_schema.py +0 -0
  222. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/schema/portfolio_target.py +0 -0
  223. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/schema/python_strategy_schema.py +0 -0
  224. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/schema/screener_schema.py +0 -0
  225. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/schema/signal_schema.py +0 -0
  226. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/schema/strategy_publication_schema.py +0 -0
  227. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/schema/strategy_schema.py +0 -0
  228. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/service/__init__.py +0 -0
  229. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/service/factor_top_n_strategy.py +0 -0
  230. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/service/portfolio_construction_service.py +0 -0
  231. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/service/python_strategy_service.py +0 -0
  232. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/service/screener_service.py +0 -0
  233. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/service/store_factor_reader.py +0 -0
  234. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/service/strategy_market_view.py +0 -0
  235. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/service/strategy_runtime_service.py +0 -0
  236. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/service/strategy_scheduler.py +0 -0
  237. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/strategies/__init__.py +0 -0
  238. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/strategies/momentum_volume_breakout.py +0 -0
  239. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/strategy_context.py +0 -0
  240. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/strategy/strategy_dependency.py +0 -0
  241. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/trading_runtime/SPEC.md +0 -0
  242. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/trading_runtime/__init__.py +0 -0
  243. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/trading_runtime/domain/__init__.py +0 -0
  244. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/trading_runtime/replay/__init__.py +0 -0
  245. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/trading_runtime/replay/daily_state_expand.py +0 -0
  246. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/trading_runtime/replay/exchange_state_resolver.py +0 -0
  247. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/trading_runtime/replay/market_runtime_service.py +0 -0
  248. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/trading_runtime/replay/market_state_resolver.py +0 -0
  249. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/trading_runtime/runtime_ports.py +0 -0
  250. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/trading_runtime/runtime_schema.py +0 -0
  251. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/trading_runtime/runtime_session.py +0 -0
  252. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/trading_runtime/strategy_portfolio_adapter.py +0 -0
  253. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/trading_runtime/trading_rule_book.py +0 -0
  254. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/app/trading_runtime/trading_rule_query.py +0 -0
  255. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/common/__init__.py +0 -0
  256. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/common/exceptions/__init__.py +0 -0
  257. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/common/exceptions/base.py +0 -0
  258. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/bundled/quant_core/common/local_run.py +0 -0
  259. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/cached_factor_screen.py +0 -0
  260. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/factors/ma_close_10.py +0 -0
  261. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/factors/max_drawdown_20d.py +0 -0
  262. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/factors/momentum_20d.py +0 -0
  263. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/factors/multi_intraday_screen.py +0 -0
  264. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/factors/risk_adjusted_momentum_20d.py +0 -0
  265. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/factors/volume_ratio_5d.py +0 -0
  266. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/factors/volume_weighted_close_pressure.py +0 -0
  267. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/full_market_screen.py +0 -0
  268. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/local_quant_validation.py +0 -0
  269. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/published_definition_validation.py +0 -0
  270. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/research/factor_pit_coverage.py +0 -0
  271. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/research/ipo_first_day.py +0 -0
  272. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/selection/README.md +0 -0
  273. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/selection/backtest.json +0 -0
  274. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/selection/buy_hold.py +0 -0
  275. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/selection/compute.json +0 -0
  276. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/selection/prepare.json +0 -0
  277. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/selection/select.json +0 -0
  278. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/strategies/bar_roundtrip.py +0 -0
  279. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/strategies/buy_and_hold.py +0 -0
  280. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/strategies/contrarian_timing.py +0 -0
  281. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/strategies/factor_gate_vwap.py +0 -0
  282. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/strategies/ipo_next_day_vwap.py +0 -0
  283. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/strategies/momentum_timing.py +0 -0
  284. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/strategies/monthly_equal_weight.py +0 -0
  285. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/strategies/session_roundtrip.py +0 -0
  286. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/strategies/trend_drawdown_guard.py +0 -0
  287. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/strategies/weekly_risk_adjusted_rotation.py +0 -0
  288. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/examples/unified_snapshot_validation.py +0 -0
  289. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/hatch_build.py +0 -0
  290. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/licenses/LICENSE.vnpy +0 -0
  291. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/__init__.py +0 -0
  292. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/api.py +0 -0
  293. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/__init__.py +0 -0
  294. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/backtest/__init__.py +0 -0
  295. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/backtest/cli/__init__.py +0 -0
  296. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/backtest/cli/local_backtest_cli.py +0 -0
  297. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/backtest/local_backtest_dependency.py +0 -0
  298. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/backtest/local_backtest_schema.py +0 -0
  299. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/backtest/repository/__init__.py +0 -0
  300. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/backtest/repository/backtest_local_repository.py +0 -0
  301. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/backtest/service/__init__.py +0 -0
  302. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/backtest/service/local_backtest_service.py +0 -0
  303. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/data/__init__.py +0 -0
  304. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/data/cli/__init__.py +0 -0
  305. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/data/cli/data_cli.py +0 -0
  306. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/data/repository/__init__.py +0 -0
  307. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/data/repository/parquet_repository.py +0 -0
  308. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/data/schema/__init__.py +0 -0
  309. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/data/schema/dataset_audit_schema.py +0 -0
  310. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/data/schema/dataset_request_schema.py +0 -0
  311. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/data/schema/parquet_file_schema.py +0 -0
  312. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/data/service/__init__.py +0 -0
  313. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/data/service/bar_cache_service.py +0 -0
  314. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/data/service/dataset_audit_service.py +0 -0
  315. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/data/service/dataset_load_service.py +0 -0
  316. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/data/service/dataset_prepare_service.py +0 -0
  317. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/factor/__init__.py +0 -0
  318. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/factor/cli/__init__.py +0 -0
  319. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/factor/cli/factor_definition_cli.py +0 -0
  320. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/factor/cli/local_factor_cli.py +0 -0
  321. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/factor/cli/local_selection_cli.py +0 -0
  322. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/factor/interface/__init__.py +0 -0
  323. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/factor/interface/local_selection_store.py +0 -0
  324. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/factor/local_factor_dependency.py +0 -0
  325. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/factor/repository/__init__.py +0 -0
  326. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/factor/repository/factor_local_repository.py +0 -0
  327. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/factor/repository/selection_local_repository.py +0 -0
  328. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/factor/schema/local_selection_schema.py +0 -0
  329. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/factor/service/__init__.py +0 -0
  330. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/factor/service/factor_data_prepare_service.py +0 -0
  331. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/factor/service/local_factor_query_service.py +0 -0
  332. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/factor/service/local_factor_service.py +0 -0
  333. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/factor/service/local_selection_service.py +0 -0
  334. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/job/__init__.py +0 -0
  335. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/job/cli/__init__.py +0 -0
  336. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/job/cli/local_job_cli.py +0 -0
  337. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/job/schema/__init__.py +0 -0
  338. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/job/schema/local_job_schema.py +0 -0
  339. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/job/service/__init__.py +0 -0
  340. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/job/service/local_job_service.py +0 -0
  341. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/research/__init__.py +0 -0
  342. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/research/cli/__init__.py +0 -0
  343. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/research/cli/local_research_cli.py +0 -0
  344. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/research/local_research_dependency.py +0 -0
  345. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/research/repository/__init__.py +0 -0
  346. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/research/repository/research_local_repository.py +0 -0
  347. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/research/schema/__init__.py +0 -0
  348. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/research/schema/local_research_schema.py +0 -0
  349. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/research/service/__init__.py +0 -0
  350. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/research/service/local_research_execution_service.py +0 -0
  351. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/research/service/local_research_service.py +0 -0
  352. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/strategy/__init__.py +0 -0
  353. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/strategy/cli/__init__.py +0 -0
  354. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/app/strategy/cli/strategy_cli.py +0 -0
  355. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/common/__init__.py +0 -0
  356. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/common/constants.py +0 -0
  357. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/common/database/__init__.py +0 -0
  358. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/common/database/duckdb_connection.py +0 -0
  359. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/common/http/__init__.py +0 -0
  360. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/common/http/definition_client.py +0 -0
  361. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/common/utils/__init__.py +0 -0
  362. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/common/utils/cli_utils.py +0 -0
  363. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/common/utils/platform_utils.py +0 -0
  364. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/src/quant_cli/common/utils/runtime_environment.py +0 -0
  365. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/__init__.py +0 -0
  366. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/conftest.py +0 -0
  367. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/factor_fixtures.py +0 -0
  368. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/integration/__init__.py +0 -0
  369. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/integration/test_local_quant_storage.py +0 -0
  370. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/integration/test_local_selection.py +0 -0
  371. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/__init__.py +0 -0
  372. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_alpha_backtest_reports.py +0 -0
  373. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_alpha_identity.py +0 -0
  374. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_alpha_market_input.py +0 -0
  375. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_alpha_research.py +0 -0
  376. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_alpha_top_n.py +0 -0
  377. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_backtest_run_result.py +0 -0
  378. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_bar_cache.py +0 -0
  379. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_coarse_execution_capability.py +0 -0
  380. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_corporate_action_replay.py +0 -0
  381. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_d1_replay_execution_chain.py +0 -0
  382. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_daily_state_expand.py +0 -0
  383. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_daily_state_snapshot.py +0 -0
  384. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_daily_vwap_execution.py +0 -0
  385. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_data_guard.py +0 -0
  386. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_dataset_audit.py +0 -0
  387. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_domain_dependency_boundaries.py +0 -0
  388. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_domain_interface_boundary.py +0 -0
  389. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_exchange_state_execution.py +0 -0
  390. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_exchange_state_replay.py +0 -0
  391. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_exchange_state_resolver.py +0 -0
  392. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_exchange_state_schema.py +0 -0
  393. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_factor_contract.py +0 -0
  394. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_factor_diagnostic_runner.py +0 -0
  395. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_factor_diagnostics.py +0 -0
  396. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_factor_expression.py +0 -0
  397. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_factor_local_runner.py +0 -0
  398. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_factor_runtime_service.py +0 -0
  399. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_factor_selection.py +0 -0
  400. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_factor_selection_runner.py +0 -0
  401. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_ipo_vwap_study.py +0 -0
  402. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_local_quant_boundary.py +0 -0
  403. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_market_replay.py +0 -0
  404. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_market_trading_state.py +0 -0
  405. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_order_domain.py +0 -0
  406. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_order_submission.py +0 -0
  407. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_portfolio_construction.py +0 -0
  408. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_portfolio_contracts.py +0 -0
  409. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_python_strategy_runtime.py +0 -0
  410. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_replay_state_boundaries.py +0 -0
  411. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_risk_adjusted_strategy_example.py +0 -0
  412. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_simulated_order_execution.py +0 -0
  413. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_simulated_portfolio.py +0 -0
  414. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_store_factor_reader.py +0 -0
  415. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_strategy_adjusted_view.py +0 -0
  416. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_strategy_domain.py +0 -0
  417. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_strategy_lifecycle.py +0 -0
  418. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_tradability_policy.py +0 -0
  419. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_trading_runtime_contracts.py +0 -0
  420. {powerquant_cli-0.2.6 → powerquant_cli-0.2.7}/tests/unit/test_trading_runtime_session.py +0 -0
@@ -15,8 +15,6 @@ __pycache__/
15
15
  .venv/
16
16
  dist/
17
17
  build/
18
- tasks/draft/TASK-20260906-1704-akshare-minute-ingestion/samples/
19
- tasks/approved/TASK-20260906-2119-real-market-integration-review-fixes/samples/
20
18
 
21
19
  node_modules/
22
20
  apps/quant_frontend/public/data-dictionary.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: powerquant-cli
3
- Version: 0.2.6
3
+ Version: 0.2.7
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
@@ -37,18 +37,46 @@ uv tool upgrade powerquant-cli
37
37
 
38
38
  ## 接入行情
39
39
 
40
- 向管理员获取行情读取密钥,无需注册账户。服务当前仅在 LAN/WireGuard 内可达。
40
+ 向管理员申请账户及具备 `market:read` 权限的平台 API Token。登录 JWT 不用于行情请求。
41
+
42
+ 首次配置一次,之后新开终端、切换目录仍可使用:
43
+
44
+ ```sh
45
+ pq config set --market-url 'https://powerquant.cn/market/api/v1'
46
+ pq config token
47
+ pq config show
48
+ ```
49
+
50
+ `token` 命令隐藏输入密钥,不加 `Bearer`,避免写入命令历史。`show` 显示地址、配置来源和是否已配置 Token,不显示密钥原文或前缀。
51
+
52
+ 家庭 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
+ 配置保存在当前系统用户的 `~/.powerquant/config.json`,与工作目录无关,不自动加载 `.env`。这是本地明文配置:POSIX 新目录权限 700、文件权限 600;Windows 依赖用户目录 ACL,不声称加密存储。不要提交或分享该文件。
55
+
56
+ 每项配置按环境变量 > 用户文件 > 默认值解析。默认地址为 `http://localhost:8002/api/v1`,默认 Token 为空。环境变量只影响当前终端及其启动的子进程,不改文件;显式空 Token 环境变量会覆盖已保存密钥。
57
+
58
+ PowerShell 临时覆盖示例:
59
+
60
+ ```powershell
61
+ $env:MARKET_BASE_URL="http://192.168.8.142:18026/market/api/v1"
62
+ $env:MARKET_API_TOKEN="管理员签发的完整平台Token"
63
+ ```
64
+
65
+ 删除已保存的配置:
66
+
67
+ ```sh
68
+ pq config unset market-token
69
+ pq config unset market-url
70
+ ```
71
+
72
+ 随后准备本地行情快照:
41
73
 
42
74
  ```sh
43
- export MARKET_BASE_URL='http://服务器地址/market/api/v1'
44
- export MARKET_API_TOKEN='管理员提供的行情密钥'
45
75
  pq examples --directory powerquant-examples
46
76
  cd powerquant-examples/selection
47
77
  pq data prepare --config prepare.json
48
78
  ```
49
79
 
50
- PowerShell 使用 `$env:MARKET_BASE_URL="..."` 与 `$env:MARKET_API_TOKEN="..."`。
51
-
52
80
  按实际覆盖调整 prepare.json 的股票和日期,将返回 manifest_path 写入 compute.json、select.json;按示例 README 执行 compute、select 和 backtest。不同使用目的的快照须分别通过完整性检查。
53
81
 
54
82
  密钥到期或撤销后在线准备会失败,已下载快照仍可离线使用。行情密钥不用于定义发布;发布定义另使用 PQ_QUANT_URL/PQ_QUANT_TOKEN。默认本地目录为 ~/.powerquant。
@@ -0,0 +1,69 @@
1
+ # Power Quant CLI
2
+
3
+ 本地行情准备、因子计算、选股、研究及策略回测;结果保存在本地 DuckDB 和文件。
4
+
5
+ ## 安装
6
+
7
+ 推荐通过 uv 安装独立工具环境:
8
+
9
+ ```sh
10
+ uv tool install --python 3.12 powerquant-cli
11
+ pq --help
12
+ uv tool upgrade powerquant-cli
13
+ ```
14
+
15
+ 也支持在 Python 3.12+ 环境通过 `pip install powerquant-cli` 安装。
16
+
17
+ ## 接入行情
18
+
19
+ 向管理员申请账户及具备 `market:read` 权限的平台 API Token。登录 JWT 不用于行情请求。
20
+
21
+ 首次配置一次,之后新开终端、切换目录仍可使用:
22
+
23
+ ```sh
24
+ pq config set --market-url 'https://powerquant.cn/market/api/v1'
25
+ pq config token
26
+ pq config show
27
+ ```
28
+
29
+ `token` 命令隐藏输入密钥,不加 `Bearer`,避免写入命令历史。`show` 显示地址、配置来源和是否已配置 Token,不显示密钥原文或前缀。
30
+
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
+
33
+ 配置保存在当前系统用户的 `~/.powerquant/config.json`,与工作目录无关,不自动加载 `.env`。这是本地明文配置:POSIX 新目录权限 700、文件权限 600;Windows 依赖用户目录 ACL,不声称加密存储。不要提交或分享该文件。
34
+
35
+ 每项配置按环境变量 > 用户文件 > 默认值解析。默认地址为 `http://localhost:8002/api/v1`,默认 Token 为空。环境变量只影响当前终端及其启动的子进程,不改文件;显式空 Token 环境变量会覆盖已保存密钥。
36
+
37
+ PowerShell 临时覆盖示例:
38
+
39
+ ```powershell
40
+ $env:MARKET_BASE_URL="http://192.168.8.142:18026/market/api/v1"
41
+ $env:MARKET_API_TOKEN="管理员签发的完整平台Token"
42
+ ```
43
+
44
+ 删除已保存的配置:
45
+
46
+ ```sh
47
+ pq config unset market-token
48
+ pq config unset market-url
49
+ ```
50
+
51
+ 随后准备本地行情快照:
52
+
53
+ ```sh
54
+ pq examples --directory powerquant-examples
55
+ cd powerquant-examples/selection
56
+ pq data prepare --config prepare.json
57
+ ```
58
+
59
+ 按实际覆盖调整 prepare.json 的股票和日期,将返回 manifest_path 写入 compute.json、select.json;按示例 README 执行 compute、select 和 backtest。不同使用目的的快照须分别通过完整性检查。
60
+
61
+ 密钥到期或撤销后在线准备会失败,已下载快照仍可离线使用。行情密钥不用于定义发布;发布定义另使用 PQ_QUANT_URL/PQ_QUANT_TOKEN。默认本地目录为 ~/.powerquant。
62
+
63
+ ## Python
64
+
65
+ 公开请求模型与调用入口位于 quant_cli.api,与 CLI 使用同一应用服务。
66
+
67
+ ## 使用许可
68
+
69
+ 自有代码采用随包附带的专有许可证:允许安装、查看源码、为自用进行修改,以及商业使用;未经书面授权不得再分发或转售本软件及其修改版本。第三方组件保留各自许可证。行情访问仍需要有效 Token;本许可证不授予行情数据的使用或再分发权。
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "powerquant-cli"
3
- version = "0.2.6"
3
+ version = "0.2.7"
4
4
  description = "Power Quant local research CLI"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -0,0 +1 @@
1
+ """用户连接配置命令。"""
@@ -0,0 +1,71 @@
1
+ """持久化行情连接配置;Token 通过隐藏交互录入,输出始终脱敏。"""
2
+
3
+ from enum import StrEnum
4
+ from typing import Annotated
5
+
6
+ import typer
7
+
8
+ from quant_cli.common.utils.cli_utils import cli_errors, output
9
+ from quant_cli.config.connection_config import (
10
+ get_config_path,
11
+ load_saved_config,
12
+ resolve_market_connection,
13
+ update_saved_config,
14
+ )
15
+
16
+ app = typer.Typer(help="保存和查看当前用户的行情连接配置", no_args_is_help=True)
17
+
18
+
19
+ class ConfigKey(StrEnum):
20
+ MARKET_URL = "market-url"
21
+ MARKET_TOKEN = "market-token"
22
+
23
+
24
+ @app.command("set")
25
+ @cli_errors
26
+ def set_config(
27
+ market_url: Annotated[str, typer.Option("--market-url", "--url", help="行情 API 基础地址")],
28
+ ) -> None:
29
+ """保存行情服务 URL;不会修改当前进程的环境变量。"""
30
+ update_saved_config("market_url", market_url)
31
+ output({"status": "saved", "path": str(get_config_path()), "key": "market_url"})
32
+
33
+
34
+ @app.command("token")
35
+ @cli_errors
36
+ def set_token() -> None:
37
+ """隐藏输入平台 Token,避免写入命令历史与进程参数。"""
38
+ value = typer.prompt("平台 Token(不加 Bearer)", hide_input=True, err=True)
39
+ update_saved_config("market_token", value)
40
+ output({"status": "saved", "path": str(get_config_path()), "key": "market_token"})
41
+
42
+
43
+ @app.command("show")
44
+ @cli_errors
45
+ def show_config() -> None:
46
+ """展示已保存和当前生效的配置、来源;不输出密钥原文或前缀。"""
47
+ saved = load_saved_config()
48
+ effective = resolve_market_connection()
49
+ output(
50
+ {
51
+ "path": str(get_config_path()),
52
+ "saved": {
53
+ "market_url": saved.get("market_url"),
54
+ "token_configured": bool(saved.get("market_token")),
55
+ },
56
+ "effective": {
57
+ "market_url": effective.url,
58
+ "token_configured": bool(effective.token),
59
+ "url_source": effective.url_source,
60
+ "token_source": effective.token_source,
61
+ },
62
+ }
63
+ )
64
+
65
+
66
+ @app.command("unset")
67
+ @cli_errors
68
+ def unset_config(key: ConfigKey) -> None:
69
+ """删除一项已保存配置,环境变量覆盖仍然有效。"""
70
+ update_saved_config(key.value.replace("-", "_"), None)
71
+ output({"status": "removed", "key": key.value})
@@ -1,14 +1,15 @@
1
- from pqdata import MarketClient
2
-
3
1
  """量化数据组装;数据库会话不再参与行情读取。"""
4
2
 
5
3
  from pathlib import Path
6
4
 
5
+ from pqdata import MarketClient
7
6
  from quant_core.app.backtest.backtest_input_schema import BacktestMarketComponents
8
7
  from quant_core.app.trading_runtime.replay.exchange_state_resolver import ExchangeStateResolver
9
8
  from quant_core.app.trading_runtime.replay.market_runtime_service import ReplayMarketEventSource
10
9
  from quant_core.app.trading_runtime.replay.market_state_resolver import MarketStateResolver
11
10
 
11
+ from quant_cli.config.connection_config import resolve_market_connection
12
+
12
13
 
13
14
  def load_backtest_market(manifest_path: Path, max_rows: int) -> BacktestMarketComponents:
14
15
  """从已校验本地快照组装回放输入,不访问 SDK 或数据库。"""
@@ -27,9 +28,8 @@ def load_backtest_market(manifest_path: Path, max_rows: int) -> BacktestMarketCo
27
28
 
28
29
  def build_market_query() -> MarketClient:
29
30
  """显式在线准备入口,配置仅为服务地址与令牌。"""
30
- import os
31
-
31
+ connection = resolve_market_connection()
32
32
  return MarketClient(
33
- os.getenv("MARKET_BASE_URL", "http://localhost:8002/api/v1"),
34
- token=os.getenv("MARKET_API_TOKEN", ""),
33
+ connection.url,
34
+ token=connection.token,
35
35
  )
@@ -8,6 +8,7 @@ from typing import Annotated
8
8
  import typer
9
9
 
10
10
  from quant_cli.app.backtest.cli.local_backtest_cli import app as backtest
11
+ from quant_cli.app.config.config_cli import app as config
11
12
  from quant_cli.app.data.cli.data_cli import app as data
12
13
  from quant_cli.app.factor.cli.local_factor_cli import app as factor
13
14
  from quant_cli.app.job.cli.local_job_cli import app as job
@@ -22,6 +23,7 @@ app.add_typer(factor, name="factor")
22
23
  app.add_typer(research, name="research")
23
24
  app.add_typer(backtest, name="backtest")
24
25
  app.add_typer(strategy, name="strategy")
26
+ app.add_typer(config, name="config")
25
27
 
26
28
 
27
29
  @app.command()
@@ -0,0 +1 @@
1
+ """CLI 用户连接配置,不读取服务端环境文件。"""
@@ -0,0 +1,133 @@
1
+ """行情连接配置:环境变量覆盖用户文件,密钥不参与展示与错误输出。"""
2
+
3
+ import json
4
+ import os
5
+ import tempfile
6
+ from dataclasses import dataclass, field
7
+ from pathlib import Path
8
+ from urllib.parse import urlsplit
9
+
10
+ from filelock import FileLock
11
+
12
+ DEFAULT_MARKET_URL = "http://localhost:8002/api/v1"
13
+ CONFIG_KEYS = {"market_url", "market_token"}
14
+
15
+
16
+ @dataclass(frozen=True)
17
+ class MarketConnection:
18
+ url: str
19
+ token: str = field(repr=False)
20
+ url_source: str
21
+ token_source: str
22
+
23
+
24
+ def get_config_path() -> Path:
25
+ """当前系统用户的配置路径,独立于终端和工作目录。"""
26
+ return Path.home() / ".powerquant" / "config.json"
27
+
28
+
29
+ def validate_market_url(value: str) -> str:
30
+ """拒绝凭据、查询参数、片段和非 HTTP(S) 地址,不回显输入。"""
31
+ try:
32
+ url = urlsplit(value)
33
+ port = url.port
34
+ valid = (
35
+ url.scheme in {"http", "https"}
36
+ and bool(url.hostname)
37
+ and not url.username
38
+ and not url.password
39
+ and not url.query
40
+ and not url.fragment
41
+ and not any(character.isspace() for character in value)
42
+ and (port is None or port > 0)
43
+ )
44
+ except ValueError:
45
+ valid = False
46
+ if not valid:
47
+ raise ValueError("行情地址必须是无凭据、查询参数和片段的 HTTP(S) 基础 URL")
48
+ return value.rstrip("/")
49
+
50
+
51
+ def _validate_token(value: str) -> None:
52
+ if any(character.isspace() for character in value):
53
+ raise ValueError("Token 不能包含空白字符,请输入完整密钥,不加 Bearer 前缀")
54
+
55
+
56
+ def load_saved_config() -> dict[str, str]:
57
+ """加载已保存配置;损坏时明确失败,不静默回退到其他服务器。"""
58
+ path = get_config_path()
59
+ if not path.exists():
60
+ return {}
61
+ try:
62
+ document = json.loads(path.read_text(encoding="utf-8"))
63
+ except (OSError, ValueError) as exc:
64
+ raise ValueError("无法读取用户连接配置,请检查 ~/.powerquant/config.json") from exc
65
+ if (
66
+ not isinstance(document, dict)
67
+ or set(document) - CONFIG_KEYS
68
+ or any(not isinstance(value, str) for value in document.values())
69
+ ):
70
+ raise ValueError("用户连接配置格式不合法")
71
+ if "market_url" in document:
72
+ validate_market_url(document["market_url"])
73
+ if "market_token" in document:
74
+ _validate_token(document["market_token"])
75
+ return document
76
+
77
+
78
+ def update_saved_config(key: str, value: str | None) -> None:
79
+ """加锁修改并原子替换文件;POSIX 新目录 700、配置文件 600。"""
80
+ if key not in CONFIG_KEYS:
81
+ raise ValueError("不支持的配置项")
82
+ if value is not None:
83
+ if key == "market_url":
84
+ value = validate_market_url(value)
85
+ else:
86
+ if not value:
87
+ raise ValueError("Token 不能为空;删除配置请使用 pq config unset")
88
+ _validate_token(value)
89
+ path = get_config_path()
90
+ path.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
91
+ with FileLock(str(path) + ".lock"):
92
+ document = load_saved_config()
93
+ if value is None:
94
+ document.pop(key, None)
95
+ else:
96
+ document[key] = value
97
+ temporary: Path | None = None
98
+ try:
99
+ descriptor, name = tempfile.mkstemp(prefix=".config-", dir=path.parent)
100
+ temporary = Path(name)
101
+ with os.fdopen(descriptor, "w", encoding="utf-8") as stream:
102
+ json.dump(document, stream, ensure_ascii=False, indent=2)
103
+ stream.write("\n")
104
+ stream.flush()
105
+ os.fsync(stream.fileno())
106
+ temporary.chmod(0o600)
107
+ os.replace(temporary, path)
108
+ except OSError as exc:
109
+ raise ValueError("无法保存用户连接配置,请检查用户目录权限") from exc
110
+ finally:
111
+ if temporary is not None:
112
+ temporary.unlink(missing_ok=True)
113
+
114
+
115
+ def resolve_market_connection() -> MarketConnection:
116
+ """按环境变量、用户文件、默认值分别解析 URL 和 Token。"""
117
+ saved = (
118
+ {} if {"MARKET_BASE_URL", "MARKET_API_TOKEN"} <= os.environ.keys() else load_saved_config()
119
+ )
120
+ url = os.environ.get("MARKET_BASE_URL", saved.get("market_url", DEFAULT_MARKET_URL))
121
+ token = os.environ.get("MARKET_API_TOKEN", saved.get("market_token", ""))
122
+ url = validate_market_url(url)
123
+ _validate_token(token)
124
+ return MarketConnection(
125
+ url=url,
126
+ token=token,
127
+ url_source="environment"
128
+ if "MARKET_BASE_URL" in os.environ
129
+ else ("file" if "market_url" in saved else "default"),
130
+ token_source="environment"
131
+ if "MARKET_API_TOKEN" in os.environ
132
+ else ("file" if "market_token" in saved else "default"),
133
+ )
@@ -0,0 +1,169 @@
1
+ """真实用户文件、配置命令与行情客户端的连接配置回归。"""
2
+
3
+ import json
4
+ import os
5
+ import subprocess
6
+ import sys
7
+ from pathlib import Path
8
+
9
+ import pytest
10
+ from typer.testing import CliRunner
11
+
12
+ from quant_cli.app.quant_cli import app
13
+ from quant_cli.config.connection_config import (
14
+ DEFAULT_MARKET_URL,
15
+ get_config_path,
16
+ load_saved_config,
17
+ resolve_market_connection,
18
+ update_saved_config,
19
+ validate_market_url,
20
+ )
21
+
22
+
23
+ @pytest.fixture(autouse=True)
24
+ def isolated_config(monkeypatch, tmp_path):
25
+ monkeypatch.setattr(Path, "home", lambda: tmp_path)
26
+ monkeypatch.delenv("MARKET_BASE_URL", raising=False)
27
+ monkeypatch.delenv("MARKET_API_TOKEN", raising=False)
28
+
29
+
30
+ def test_default_connection():
31
+ connection = resolve_market_connection()
32
+ assert connection.url == DEFAULT_MARKET_URL
33
+ assert connection.token == ""
34
+ assert connection.url_source == connection.token_source == "default"
35
+ assert not get_config_path().exists()
36
+
37
+
38
+ def test_saved_connection_survives_a_new_process(tmp_path):
39
+ update_saved_config("market_url", "http://82.157.167.33/market/api/v1/")
40
+ update_saved_config("market_token", "test-platform-secret")
41
+ script = """
42
+ import json, sys
43
+ from pathlib import Path
44
+ Path.home = classmethod(lambda cls: Path(sys.argv[1]))
45
+ from quant_cli.config.connection_config import resolve_market_connection
46
+ c = resolve_market_connection()
47
+ print(json.dumps({'url': c.url, 'token_matches': c.token == 'test-platform-secret'}))
48
+ """
49
+ result = subprocess.run(
50
+ [sys.executable, "-c", script, str(tmp_path)], capture_output=True, text=True, check=True
51
+ )
52
+ assert json.loads(result.stdout) == {
53
+ "url": "http://82.157.167.33/market/api/v1",
54
+ "token_matches": True,
55
+ }
56
+ if os.name == "posix":
57
+ assert get_config_path().stat().st_mode & 0o777 == 0o600
58
+ assert get_config_path().parent.stat().st_mode & 0o777 == 0o700
59
+
60
+
61
+ def test_environment_overrides_each_field_without_changing_file(monkeypatch):
62
+ update_saved_config("market_url", "https://example.com/market/api/v1")
63
+ update_saved_config("market_token", "saved-secret")
64
+ original = get_config_path().read_bytes()
65
+ monkeypatch.setenv("MARKET_API_TOKEN", "environment-secret")
66
+ connection = resolve_market_connection()
67
+ assert connection.url == "https://example.com/market/api/v1"
68
+ assert connection.token == "environment-secret"
69
+ assert connection.url_source == "file"
70
+ assert connection.token_source == "environment"
71
+ monkeypatch.setenv("MARKET_BASE_URL", "http://localhost:9000/api/v1")
72
+ assert resolve_market_connection().url == "http://localhost:9000/api/v1"
73
+ assert get_config_path().read_bytes() == original
74
+
75
+
76
+ def test_empty_environment_token_does_not_reuse_saved_secret(monkeypatch):
77
+ update_saved_config("market_token", "saved-secret")
78
+ monkeypatch.setenv("MARKET_API_TOKEN", "")
79
+ assert resolve_market_connection().token == ""
80
+
81
+
82
+ def test_cli_hidden_token_and_show_never_output_secret():
83
+ runner = CliRunner()
84
+ assert (
85
+ runner.invoke(app, ["config", "set", "--url", "http://localhost:9000/api/v1"]).exit_code
86
+ == 0
87
+ )
88
+ token = runner.invoke(app, ["config", "token"], input="test-hidden-secret\n")
89
+ assert token.exit_code == 0, token.output
90
+ assert "test-hidden-secret" not in token.output
91
+ shown = runner.invoke(app, ["config", "show"])
92
+ assert shown.exit_code == 0
93
+ assert "test-hidden-secret" not in shown.output
94
+ assert json.loads(shown.stdout)["effective"]["token_configured"]
95
+ assert "test-hidden-secret" not in repr(resolve_market_connection())
96
+ assert runner.invoke(app, ["config", "unset", "market-token"]).exit_code == 0
97
+ assert load_saved_config() == {"market_url": "http://localhost:9000/api/v1"}
98
+
99
+
100
+ @pytest.mark.parametrize(
101
+ "url",
102
+ [
103
+ "[http://example.com](http://example.com)",
104
+ "ftp://example.com",
105
+ "https://u:secret@example.com",
106
+ "https://example.com?token=secret",
107
+ "https://example.com#token",
108
+ "https://example.com:99999",
109
+ "https://",
110
+ "",
111
+ "http://example.com/ white space",
112
+ ],
113
+ )
114
+ def test_invalid_url_does_not_echo_credentials(url):
115
+ with pytest.raises(ValueError) as error:
116
+ validate_market_url(url)
117
+ assert "secret" not in str(error.value)
118
+ assert not get_config_path().exists()
119
+
120
+
121
+ def test_corrupted_file_fails_without_exposing_content(monkeypatch):
122
+ path = get_config_path()
123
+ path.parent.mkdir()
124
+ path.write_text('{"market_token": "hidden-secret"', encoding="utf-8")
125
+ result = CliRunner().invoke(app, ["config", "show"])
126
+ assert result.exit_code == 1
127
+ assert "hidden-secret" not in result.output
128
+ monkeypatch.setenv("MARKET_BASE_URL", "https://example.com/api/v1")
129
+ monkeypatch.setenv("MARKET_API_TOKEN", "override-secret")
130
+ assert resolve_market_connection().token == "override-secret"
131
+
132
+
133
+ def test_market_client_uses_saved_connection(monkeypatch):
134
+ from quant_cli.app.data import data_dependency
135
+
136
+ update_saved_config("market_url", "https://example.com/market/api/v1")
137
+ update_saved_config("market_token", "test-secret")
138
+ observed = {}
139
+
140
+ def fake_client(url, *, token):
141
+ observed.update(url=url, token=token)
142
+ return observed
143
+
144
+ monkeypatch.setattr(data_dependency, "MarketClient", fake_client)
145
+ assert data_dependency.build_market_query() == {
146
+ "url": "https://example.com/market/api/v1",
147
+ "token": "test-secret",
148
+ }
149
+
150
+
151
+ def test_invalid_token_is_not_saved_or_echoed():
152
+ result = CliRunner().invoke(app, ["config", "token"], input="Bearer hidden-secret\n")
153
+ assert result.exit_code == 1
154
+ assert "hidden-secret" not in result.output
155
+ assert not get_config_path().exists()
156
+
157
+
158
+ def test_failed_atomic_replace_preserves_previous_config(monkeypatch):
159
+ update_saved_config("market_token", "old-secret")
160
+ original = get_config_path().read_bytes()
161
+
162
+ def fail_replace(*args):
163
+ raise OSError("test write failure")
164
+
165
+ monkeypatch.setattr(os, "replace", fail_replace)
166
+ with pytest.raises(ValueError, match="无法保存"):
167
+ update_saved_config("market_token", "new-secret")
168
+ assert get_config_path().read_bytes() == original
169
+ assert not list(get_config_path().parent.glob(".config-*"))
@@ -365,7 +365,7 @@ wheels = [
365
365
 
366
366
  [[package]]
367
367
  name = "powerquant-cli"
368
- version = "0.2.6"
368
+ version = "0.2.7"
369
369
  source = { editable = "." }
370
370
  dependencies = [
371
371
  { name = "duckdb" },
@@ -1,41 +0,0 @@
1
- # Power Quant CLI
2
-
3
- 本地行情准备、因子计算、选股、研究及策略回测;结果保存在本地 DuckDB 和文件。
4
-
5
- ## 安装
6
-
7
- 推荐通过 uv 安装独立工具环境:
8
-
9
- ```sh
10
- uv tool install --python 3.12 powerquant-cli
11
- pq --help
12
- uv tool upgrade powerquant-cli
13
- ```
14
-
15
- 也支持在 Python 3.12+ 环境通过 `pip install powerquant-cli` 安装。
16
-
17
- ## 接入行情
18
-
19
- 向管理员获取行情读取密钥,无需注册账户。服务当前仅在 LAN/WireGuard 内可达。
20
-
21
- ```sh
22
- export MARKET_BASE_URL='http://服务器地址/market/api/v1'
23
- export MARKET_API_TOKEN='管理员提供的行情密钥'
24
- pq examples --directory powerquant-examples
25
- cd powerquant-examples/selection
26
- pq data prepare --config prepare.json
27
- ```
28
-
29
- PowerShell 使用 `$env:MARKET_BASE_URL="..."` 与 `$env:MARKET_API_TOKEN="..."`。
30
-
31
- 按实际覆盖调整 prepare.json 的股票和日期,将返回 manifest_path 写入 compute.json、select.json;按示例 README 执行 compute、select 和 backtest。不同使用目的的快照须分别通过完整性检查。
32
-
33
- 密钥到期或撤销后在线准备会失败,已下载快照仍可离线使用。行情密钥不用于定义发布;发布定义另使用 PQ_QUANT_URL/PQ_QUANT_TOKEN。默认本地目录为 ~/.powerquant。
34
-
35
- ## Python
36
-
37
- 公开请求模型与调用入口位于 quant_cli.api,与 CLI 使用同一应用服务。
38
-
39
- ## 使用许可
40
-
41
- 自有代码采用随包附带的专有许可证:允许安装、查看源码、为自用进行修改,以及商业使用;未经书面授权不得再分发或转售本软件及其修改版本。第三方组件保留各自许可证。行情访问仍需要有效 Token;本许可证不授予行情数据的使用或再分发权。
File without changes