axdata 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- axdata/__init__.py +16 -0
- axdata/cache.py +19 -0
- axdata/client.py +1223 -0
- axdata-0.1.0.dist-info/METADATA +238 -0
- axdata-0.1.0.dist-info/RECORD +427 -0
- axdata-0.1.0.dist-info/WHEEL +5 -0
- axdata-0.1.0.dist-info/entry_points.txt +8 -0
- axdata-0.1.0.dist-info/licenses/LICENSE +162 -0
- axdata-0.1.0.dist-info/top_level.txt +6 -0
- axdata_core/__init__.py +221 -0
- axdata_core/_tdx_wire/__init__.py +35 -0
- axdata_core/_tdx_wire/_shim.py +140 -0
- axdata_core/_tdx_wire/api/__init__.py +51 -0
- axdata_core/_tdx_wire/api/auction.py +24 -0
- axdata_core/_tdx_wire/api/bars.py +24 -0
- axdata_core/_tdx_wire/api/base.py +26 -0
- axdata_core/_tdx_wire/api/codes.py +25 -0
- axdata_core/_tdx_wire/api/corporate.py +24 -0
- axdata_core/_tdx_wire/api/finance.py +24 -0
- axdata_core/_tdx_wire/api/intraday.py +24 -0
- axdata_core/_tdx_wire/api/quotes.py +26 -0
- axdata_core/_tdx_wire/api/resources.py +25 -0
- axdata_core/_tdx_wire/api/session.py +24 -0
- axdata_core/_tdx_wire/api/trades.py +24 -0
- axdata_core/_tdx_wire/client.py +33 -0
- axdata_core/_tdx_wire/exceptions.py +27 -0
- axdata_core/_tdx_wire/hosts.py +106 -0
- axdata_core/_tdx_wire/models/__init__.py +93 -0
- axdata_core/_tdx_wire/models/auction.py +26 -0
- axdata_core/_tdx_wire/models/corporate.py +27 -0
- axdata_core/_tdx_wire/models/finance.py +26 -0
- axdata_core/_tdx_wire/models/intraday.py +31 -0
- axdata_core/_tdx_wire/models/kline.py +27 -0
- axdata_core/_tdx_wire/models/quote.py +32 -0
- axdata_core/_tdx_wire/models/resource.py +24 -0
- axdata_core/_tdx_wire/models/security.py +24 -0
- axdata_core/_tdx_wire/models/session.py +27 -0
- axdata_core/_tdx_wire/models/subchart.py +25 -0
- axdata_core/_tdx_wire/models/trade.py +28 -0
- axdata_core/_tdx_wire/protocol/__init__.py +49 -0
- axdata_core/_tdx_wire/protocol/commands/__init__.py +43 -0
- axdata_core/_tdx_wire/protocol/commands/auction.py +110 -0
- axdata_core/_tdx_wire/protocol/commands/codec.py +43 -0
- axdata_core/_tdx_wire/protocol/commands/corporate.py +98 -0
- axdata_core/_tdx_wire/protocol/commands/finance.py +96 -0
- axdata_core/_tdx_wire/protocol/commands/intraday.py +122 -0
- axdata_core/_tdx_wire/protocol/commands/klines.py +102 -0
- axdata_core/_tdx_wire/protocol/commands/lookup.py +36 -0
- axdata_core/_tdx_wire/protocol/commands/price_limits.py +89 -0
- axdata_core/_tdx_wire/protocol/commands/quotes.py +102 -0
- axdata_core/_tdx_wire/protocol/commands/registry.py +36 -0
- axdata_core/_tdx_wire/protocol/commands/resources.py +99 -0
- axdata_core/_tdx_wire/protocol/commands/security.py +103 -0
- axdata_core/_tdx_wire/protocol/commands/session.py +82 -0
- axdata_core/_tdx_wire/protocol/commands/subchart.py +97 -0
- axdata_core/_tdx_wire/protocol/commands/trades.py +107 -0
- axdata_core/_tdx_wire/protocol/constants.py +124 -0
- axdata_core/_tdx_wire/protocol/frame.py +68 -0
- axdata_core/_tdx_wire/protocol/unit.py +85 -0
- axdata_core/_tdx_wire/py.typed +1 -0
- axdata_core/_tdx_wire/transport/__init__.py +34 -0
- axdata_core/_tdx_wire/transport/base.py +25 -0
- axdata_core/_tdx_wire/transport/memory.py +24 -0
- axdata_core/_tdx_wire/transport/pool.py +32 -0
- axdata_core/_tdx_wire/transport/socket.py +39 -0
- axdata_core/adapters/__init__.py +0 -0
- axdata_core/adapters/cls/__init__.py +17 -0
- axdata_core/adapters/cls/provider_bridge.py +23 -0
- axdata_core/adapters/cls/request.py +632 -0
- axdata_core/adapters/cls/source_adapter_registry.py +31 -0
- axdata_core/adapters/cninfo/__init__.py +17 -0
- axdata_core/adapters/cninfo/provider_bridge.py +25 -0
- axdata_core/adapters/cninfo/request.py +2425 -0
- axdata_core/adapters/cninfo/source_adapter_registry.py +42 -0
- axdata_core/adapters/eastmoney/__init__.py +17 -0
- axdata_core/adapters/eastmoney/provider_bridge.py +25 -0
- axdata_core/adapters/eastmoney/request.py +1128 -0
- axdata_core/adapters/eastmoney/source_adapter_registry.py +42 -0
- axdata_core/adapters/exchange/__init__.py +17 -0
- axdata_core/adapters/exchange/provider_bridge.py +25 -0
- axdata_core/adapters/exchange/request.py +1214 -0
- axdata_core/adapters/exchange/source_adapter_registry.py +42 -0
- axdata_core/adapters/kph/__init__.py +17 -0
- axdata_core/adapters/kph/provider_bridge.py +23 -0
- axdata_core/adapters/kph/request.py +509 -0
- axdata_core/adapters/kph/source_adapter_registry.py +31 -0
- axdata_core/adapters/sina/__init__.py +17 -0
- axdata_core/adapters/sina/provider_bridge.py +25 -0
- axdata_core/adapters/sina/request.py +5155 -0
- axdata_core/adapters/sina/source_adapter_registry.py +42 -0
- axdata_core/adapters/tdx/__init__.py +32 -0
- axdata_core/adapters/tdx/adjustment.py +50 -0
- axdata_core/adapters/tdx/adjustment_fetch.py +51 -0
- axdata_core/adapters/tdx/auction_fetch.py +51 -0
- axdata_core/adapters/tdx/client_factory.py +110 -0
- axdata_core/adapters/tdx/code_fetch.py +62 -0
- axdata_core/adapters/tdx/codes.py +54 -0
- axdata_core/adapters/tdx/derived_rows.py +69 -0
- axdata_core/adapters/tdx/downloader.py +193 -0
- axdata_core/adapters/tdx/downloader_interface_sets.py +50 -0
- axdata_core/adapters/tdx/downloader_profiles.py +43 -0
- axdata_core/adapters/tdx/downloader_registry.py +115 -0
- axdata_core/adapters/tdx/execution_utils.py +55 -0
- axdata_core/adapters/tdx/f10_executor.py +57 -0
- axdata_core/adapters/tdx/f10_normalize.py +61 -0
- axdata_core/adapters/tdx/f10_params.py +57 -0
- axdata_core/adapters/tdx/f10_postprocess.py +67 -0
- axdata_core/adapters/tdx/f10_render.py +48 -0
- axdata_core/adapters/tdx/f10_request.py +62 -0
- axdata_core/adapters/tdx/finance_fetch.py +61 -0
- axdata_core/adapters/tdx/finance_maps.py +54 -0
- axdata_core/adapters/tdx/finance_normalize.py +57 -0
- axdata_core/adapters/tdx/host_config.py +115 -0
- axdata_core/adapters/tdx/interface_sets.py +50 -0
- axdata_core/adapters/tdx/intraday_fetch.py +68 -0
- axdata_core/adapters/tdx/kline_helpers.py +58 -0
- axdata_core/adapters/tdx/limit_ladder_fetch.py +60 -0
- axdata_core/adapters/tdx/limit_ladder_topics.py +53 -0
- axdata_core/adapters/tdx/normalize_utils.py +75 -0
- axdata_core/adapters/tdx/options.py +61 -0
- axdata_core/adapters/tdx/price_limit_calendar.py +49 -0
- axdata_core/adapters/tdx/price_limit_fetch.py +53 -0
- axdata_core/adapters/tdx/price_limit_history.py +50 -0
- axdata_core/adapters/tdx/price_limits.py +58 -0
- axdata_core/adapters/tdx/provider_bridge.py +68 -0
- axdata_core/adapters/tdx/quote_fetch.py +61 -0
- axdata_core/adapters/tdx/quote_identity.py +49 -0
- axdata_core/adapters/tdx/rank_fetch.py +55 -0
- axdata_core/adapters/tdx/rank_params.py +52 -0
- axdata_core/adapters/tdx/realtime_refresh.py +45 -0
- axdata_core/adapters/tdx/request.py +11 -0
- axdata_core/adapters/tdx/request_adapter_runtime.py +41 -0
- axdata_core/adapters/tdx/request_client.py +51 -0
- axdata_core/adapters/tdx/request_compat.py +89 -0
- axdata_core/adapters/tdx/request_dispatch.py +50 -0
- axdata_core/adapters/tdx/request_filters.py +60 -0
- axdata_core/adapters/tdx/request_host_config.py +110 -0
- axdata_core/adapters/tdx/request_limits.py +59 -0
- axdata_core/adapters/tdx/request_methods.py +41 -0
- axdata_core/adapters/tdx/request_params.py +62 -0
- axdata_core/adapters/tdx/request_seams.py +41 -0
- axdata_core/adapters/tdx/resources/__init__.py +0 -0
- axdata_core/adapters/tdx/resources/finance_maps/__init__.py +0 -0
- axdata_core/adapters/tdx/resources/finance_maps/incon.dat +3702 -0
- axdata_core/adapters/tdx/resources/finance_maps/tdxhy.cfg +5620 -0
- axdata_core/adapters/tdx/resources/finance_maps/tdxzs.cfg +605 -0
- axdata_core/adapters/tdx/security_codes.py +54 -0
- axdata_core/adapters/tdx/series_history.py +57 -0
- axdata_core/adapters/tdx/server_cache.py +58 -0
- axdata_core/adapters/tdx/snapshot_normalize.py +56 -0
- axdata_core/adapters/tdx/source_adapter_registry.py +69 -0
- axdata_core/adapters/tdx/source_execution.py +44 -0
- axdata_core/adapters/tdx/source_execution_registry.py +70 -0
- axdata_core/adapters/tdx/stats_cache.py +184 -0
- axdata_core/adapters/tdx/stats_models.py +159 -0
- axdata_core/adapters/tdx/stats_resource.py +304 -0
- axdata_core/adapters/tdx/status_fetch.py +55 -0
- axdata_core/adapters/tdx/time_series_normalize.py +67 -0
- axdata_core/adapters/tdx/tqlex.py +50 -0
- axdata_core/adapters/tdx/wire_requests.py +60 -0
- axdata_core/adapters/tdx_ext/__init__.py +66 -0
- axdata_core/adapters/tdx_ext/client.py +688 -0
- axdata_core/adapters/tdx_ext/exceptions.py +51 -0
- axdata_core/adapters/tdx_ext/host_config.py +40 -0
- axdata_core/adapters/tdx_ext/interface_sets.py +65 -0
- axdata_core/adapters/tdx_ext/local_cache.py +649 -0
- axdata_core/adapters/tdx_ext/models.py +96 -0
- axdata_core/adapters/tdx_ext/options.py +36 -0
- axdata_core/adapters/tdx_ext/pool.py +153 -0
- axdata_core/adapters/tdx_ext/provider_bridge.py +35 -0
- axdata_core/adapters/tdx_ext/request.py +498 -0
- axdata_core/adapters/tdx_ext/request_execution.py +118 -0
- axdata_core/adapters/tdx_ext/request_instruments.py +221 -0
- axdata_core/adapters/tdx_ext/request_normalize.py +356 -0
- axdata_core/adapters/tdx_ext/request_params.py +157 -0
- axdata_core/adapters/tdx_ext/request_series.py +98 -0
- axdata_core/adapters/tdx_ext/server_cache.py +13 -0
- axdata_core/adapters/tdx_ext/servers.py +35 -0
- axdata_core/adapters/tdx_ext/source_adapter_registry.py +42 -0
- axdata_core/adapters/tdx_ext/source_execution.py +19 -0
- axdata_core/adapters/tdx_ext/source_execution_registry.py +43 -0
- axdata_core/adapters/tencent/__init__.py +17 -0
- axdata_core/adapters/tencent/provider_bridge.py +25 -0
- axdata_core/adapters/tencent/request.py +729 -0
- axdata_core/adapters/tencent/source_adapter_registry.py +42 -0
- axdata_core/axp.py +1843 -0
- axdata_core/builtin_providers.py +586 -0
- axdata_core/builtin_source_declarations.py +156 -0
- axdata_core/cli.py +1818 -0
- axdata_core/collector_registry.py +227 -0
- axdata_core/collector_runner.py +1016 -0
- axdata_core/collector_scheduler.py +3155 -0
- axdata_core/collector_templates.py +339 -0
- axdata_core/data_browser.py +1696 -0
- axdata_core/diagnostics.py +734 -0
- axdata_core/downloader_engine.py +1480 -0
- axdata_core/downloader_registry.py +62 -0
- axdata_core/downloaders.py +1619 -0
- axdata_core/legacy_provider_adapter.py +68 -0
- axdata_core/paths.py +51 -0
- axdata_core/plugin_config.py +272 -0
- axdata_core/plugin_status.py +419 -0
- axdata_core/plugins.py +1363 -0
- axdata_core/provider_catalog.py +462 -0
- axdata_core/provider_registry.py +833 -0
- axdata_core/quality.py +86 -0
- axdata_core/query.py +242 -0
- axdata_core/resources/__init__.py +2 -0
- axdata_core/resources/tdx_extended_servers.json +22 -0
- axdata_core/resources/tdx_quote_servers.json +49 -0
- axdata_core/sample_collectors.py +42 -0
- axdata_core/schema.py +385 -0
- axdata_core/source_adapter_factory.py +95 -0
- axdata_core/source_adapter_options.py +18 -0
- axdata_core/source_errors.py +43 -0
- axdata_core/source_execution_options.py +37 -0
- axdata_core/source_execution_registry.py +27 -0
- axdata_core/source_projection.py +21 -0
- axdata_core/source_request.py +441 -0
- axdata_core/source_session.py +355 -0
- axdata_core/sources/__init__.py +40 -0
- axdata_core/sources/base.py +112 -0
- axdata_core/sources/catalog.py +60 -0
- axdata_core/sources/cls/__init__.py +5 -0
- axdata_core/sources/cls/catalog.py +231 -0
- axdata_core/sources/cninfo/__init__.py +5 -0
- axdata_core/sources/cninfo/catalog.py +1994 -0
- axdata_core/sources/display_docs.py +139 -0
- axdata_core/sources/eastmoney/__init__.py +5 -0
- axdata_core/sources/eastmoney/catalog.py +509 -0
- axdata_core/sources/exchange/__init__.py +5 -0
- axdata_core/sources/exchange/catalog.py +361 -0
- axdata_core/sources/kph/__init__.py +5 -0
- axdata_core/sources/kph/catalog.py +255 -0
- axdata_core/sources/sina/__init__.py +5 -0
- axdata_core/sources/sina/catalog.py +2951 -0
- axdata_core/sources/tdx/__init__.py +5 -0
- axdata_core/sources/tdx/catalog.py +4546 -0
- axdata_core/sources/tdx_ext/__init__.py +5 -0
- axdata_core/sources/tdx_ext/catalog.py +1518 -0
- axdata_core/sources/tencent/__init__.py +5 -0
- axdata_core/sources/tencent/catalog.py +370 -0
- axdata_core/storage.py +186 -0
- axdata_core/tdx_f10_catalog.py +52 -0
- axdata_core/tdx_f10_models.py +50 -0
- axdata_core/tdx_f10_names.py +47 -0
- axdata_core/tdx_f10_specs.py +56 -0
- axdata_core/tdx_plugin_required.py +43 -0
- axdata_core/tdx_server_config.py +65 -0
- axdata_core/trade_calendar_cache.py +397 -0
- axdata_source_cninfo/__init__.py +15 -0
- axdata_source_cninfo/adapter.py +31 -0
- axdata_source_cninfo/axdata-provider.json +384 -0
- axdata_source_cninfo/catalog.py +209 -0
- axdata_source_cninfo/metadata.py +8 -0
- axdata_source_cninfo/provider.py +41 -0
- axdata_source_tdx/__init__.py +15 -0
- axdata_source_tdx/_tdx_wire/__init__.py +26 -0
- axdata_source_tdx/_tdx_wire/_binary.py +218 -0
- axdata_source_tdx/_tdx_wire/_code_utils.py +42 -0
- axdata_source_tdx/_tdx_wire/_command_codec.py +186 -0
- axdata_source_tdx/_tdx_wire/_command_codes.py +74 -0
- axdata_source_tdx/_tdx_wire/_command_defaults.py +15 -0
- axdata_source_tdx/_tdx_wire/_command_dispatch.py +96 -0
- axdata_source_tdx/_tdx_wire/_command_layouts.py +96 -0
- axdata_source_tdx/_tdx_wire/_command_lookup.py +25 -0
- axdata_source_tdx/_tdx_wire/_command_metadata.py +32 -0
- axdata_source_tdx/_tdx_wire/_command_registry.py +61 -0
- axdata_source_tdx/_tdx_wire/_connection_defaults.py +13 -0
- axdata_source_tdx/_tdx_wire/_host_defaults.py +51 -0
- axdata_source_tdx/_tdx_wire/_host_probe.py +81 -0
- axdata_source_tdx/_tdx_wire/_host_resource.py +70 -0
- axdata_source_tdx/_tdx_wire/_host_utils.py +31 -0
- axdata_source_tdx/_tdx_wire/_market.py +66 -0
- axdata_source_tdx/_tdx_wire/_request_defaults.py +11 -0
- axdata_source_tdx/_tdx_wire/_security_classification.py +61 -0
- axdata_source_tdx/_tdx_wire/_time_utils.py +7 -0
- axdata_source_tdx/_tdx_wire/api/__init__.py +45 -0
- axdata_source_tdx/_tdx_wire/api/auction.py +25 -0
- axdata_source_tdx/_tdx_wire/api/bars.py +31 -0
- axdata_source_tdx/_tdx_wire/api/base.py +39 -0
- axdata_source_tdx/_tdx_wire/api/codes.py +25 -0
- axdata_source_tdx/_tdx_wire/api/corporate.py +11 -0
- axdata_source_tdx/_tdx_wire/api/finance.py +10 -0
- axdata_source_tdx/_tdx_wire/api/intraday.py +38 -0
- axdata_source_tdx/_tdx_wire/api/quotes.py +78 -0
- axdata_source_tdx/_tdx_wire/api/resources.py +34 -0
- axdata_source_tdx/_tdx_wire/api/session.py +16 -0
- axdata_source_tdx/_tdx_wire/api/trades.py +34 -0
- axdata_source_tdx/_tdx_wire/client.py +470 -0
- axdata_source_tdx/_tdx_wire/exceptions.py +25 -0
- axdata_source_tdx/_tdx_wire/hosts.py +27 -0
- axdata_source_tdx/_tdx_wire/models/__init__.py +87 -0
- axdata_source_tdx/_tdx_wire/models/auction.py +58 -0
- axdata_source_tdx/_tdx_wire/models/corporate.py +59 -0
- axdata_source_tdx/_tdx_wire/models/finance.py +80 -0
- axdata_source_tdx/_tdx_wire/models/intraday.py +112 -0
- axdata_source_tdx/_tdx_wire/models/kline.py +58 -0
- axdata_source_tdx/_tdx_wire/models/quote.py +262 -0
- axdata_source_tdx/_tdx_wire/models/resource.py +18 -0
- axdata_source_tdx/_tdx_wire/models/security.py +28 -0
- axdata_source_tdx/_tdx_wire/models/session.py +30 -0
- axdata_source_tdx/_tdx_wire/models/subchart.py +39 -0
- axdata_source_tdx/_tdx_wire/models/trade.py +46 -0
- axdata_source_tdx/_tdx_wire/protocol/__init__.py +43 -0
- axdata_source_tdx/_tdx_wire/protocol/_frame_constants.py +5 -0
- axdata_source_tdx/_tdx_wire/protocol/commands/__init__.py +37 -0
- axdata_source_tdx/_tdx_wire/protocol/commands/auction.py +165 -0
- axdata_source_tdx/_tdx_wire/protocol/commands/codec.py +37 -0
- axdata_source_tdx/_tdx_wire/protocol/commands/corporate.py +163 -0
- axdata_source_tdx/_tdx_wire/protocol/commands/finance.py +180 -0
- axdata_source_tdx/_tdx_wire/protocol/commands/intraday.py +382 -0
- axdata_source_tdx/_tdx_wire/protocol/commands/klines.py +396 -0
- axdata_source_tdx/_tdx_wire/protocol/commands/lookup.py +31 -0
- axdata_source_tdx/_tdx_wire/protocol/commands/price_limits.py +110 -0
- axdata_source_tdx/_tdx_wire/protocol/commands/quotes.py +804 -0
- axdata_source_tdx/_tdx_wire/protocol/commands/registry.py +30 -0
- axdata_source_tdx/_tdx_wire/protocol/commands/resources.py +107 -0
- axdata_source_tdx/_tdx_wire/protocol/commands/security.py +163 -0
- axdata_source_tdx/_tdx_wire/protocol/commands/session.py +129 -0
- axdata_source_tdx/_tdx_wire/protocol/commands/subchart.py +182 -0
- axdata_source_tdx/_tdx_wire/protocol/commands/trades.py +275 -0
- axdata_source_tdx/_tdx_wire/protocol/constants.py +70 -0
- axdata_source_tdx/_tdx_wire/protocol/frame.py +141 -0
- axdata_source_tdx/_tdx_wire/protocol/unit.py +98 -0
- axdata_source_tdx/_tdx_wire/py.typed +1 -0
- axdata_source_tdx/_tdx_wire/transport/__init__.py +28 -0
- axdata_source_tdx/_tdx_wire/transport/base.py +21 -0
- axdata_source_tdx/_tdx_wire/transport/memory.py +42 -0
- axdata_source_tdx/_tdx_wire/transport/pool.py +148 -0
- axdata_source_tdx/_tdx_wire/transport/socket.py +373 -0
- axdata_source_tdx/adapter.py +31 -0
- axdata_source_tdx/adjustment.py +163 -0
- axdata_source_tdx/adjustment_fetch.py +148 -0
- axdata_source_tdx/auction_fetch.py +162 -0
- axdata_source_tdx/axdata-provider.json +23680 -0
- axdata_source_tdx/catalog.py +39 -0
- axdata_source_tdx/client_factory.py +61 -0
- axdata_source_tdx/code_fetch.py +579 -0
- axdata_source_tdx/codes.py +69 -0
- axdata_source_tdx/collectors.py +525 -0
- axdata_source_tdx/derived_rows.py +500 -0
- axdata_source_tdx/downloader.py +139 -0
- axdata_source_tdx/downloader_interface_sets.py +29 -0
- axdata_source_tdx/downloader_profiles.py +731 -0
- axdata_source_tdx/downloader_registry.py +85 -0
- axdata_source_tdx/execution_utils.py +141 -0
- axdata_source_tdx/f10_executor.py +414 -0
- axdata_source_tdx/f10_normalize.py +169 -0
- axdata_source_tdx/f10_params.py +221 -0
- axdata_source_tdx/f10_postprocess.py +405 -0
- axdata_source_tdx/f10_render.py +29 -0
- axdata_source_tdx/f10_request.py +365 -0
- axdata_source_tdx/finance_fetch.py +514 -0
- axdata_source_tdx/finance_maps.py +377 -0
- axdata_source_tdx/finance_normalize.py +273 -0
- axdata_source_tdx/host_config.py +51 -0
- axdata_source_tdx/interface_sets.py +180 -0
- axdata_source_tdx/intraday_fetch.py +600 -0
- axdata_source_tdx/kline_helpers.py +333 -0
- axdata_source_tdx/limit_ladder_fetch.py +614 -0
- axdata_source_tdx/limit_ladder_topics.py +280 -0
- axdata_source_tdx/metadata.py +8 -0
- axdata_source_tdx/normalize_utils.py +264 -0
- axdata_source_tdx/options.py +195 -0
- axdata_source_tdx/price_limit_calendar.py +106 -0
- axdata_source_tdx/price_limit_fetch.py +264 -0
- axdata_source_tdx/price_limit_history.py +100 -0
- axdata_source_tdx/price_limits.py +142 -0
- axdata_source_tdx/provider.py +44 -0
- axdata_source_tdx/provider_bridge.py +43 -0
- axdata_source_tdx/quote_fetch.py +485 -0
- axdata_source_tdx/quote_identity.py +50 -0
- axdata_source_tdx/rank_fetch.py +316 -0
- axdata_source_tdx/rank_params.py +181 -0
- axdata_source_tdx/realtime_refresh.py +51 -0
- axdata_source_tdx/request_adapter.py +533 -0
- axdata_source_tdx/request_adapter_runtime.py +302 -0
- axdata_source_tdx/request_client.py +98 -0
- axdata_source_tdx/request_compat.py +432 -0
- axdata_source_tdx/request_dispatch.py +138 -0
- axdata_source_tdx/request_entrypoints.py +146 -0
- axdata_source_tdx/request_filters.py +154 -0
- axdata_source_tdx/request_host_config.py +103 -0
- axdata_source_tdx/request_limits.py +15 -0
- axdata_source_tdx/request_methods.py +1910 -0
- axdata_source_tdx/request_params.py +225 -0
- axdata_source_tdx/request_seams.py +534 -0
- axdata_source_tdx/resources/__init__.py +0 -0
- axdata_source_tdx/resources/finance_maps/__init__.py +1 -0
- axdata_source_tdx/resources/finance_maps/incon.dat +3702 -0
- axdata_source_tdx/resources/finance_maps/tdxhy.cfg +5620 -0
- axdata_source_tdx/resources/finance_maps/tdxzs.cfg +605 -0
- axdata_source_tdx/resources/tdx_extended_servers.json +22 -0
- axdata_source_tdx/resources/tdx_quote_servers.json +49 -0
- axdata_source_tdx/security_codes.py +127 -0
- axdata_source_tdx/series_history.py +348 -0
- axdata_source_tdx/server_cache.py +21 -0
- axdata_source_tdx/snapshot_normalize.py +232 -0
- axdata_source_tdx/source_adapter_registry.py +42 -0
- axdata_source_tdx/source_execution.py +22 -0
- axdata_source_tdx/source_execution_registry.py +43 -0
- axdata_source_tdx/stats_cache.py +150 -0
- axdata_source_tdx/stats_models.py +161 -0
- axdata_source_tdx/stats_resource.py +242 -0
- axdata_source_tdx/status_fetch.py +209 -0
- axdata_source_tdx/tdx_f10_catalog.py +957 -0
- axdata_source_tdx/tdx_f10_models.py +47 -0
- axdata_source_tdx/tdx_f10_names.py +48 -0
- axdata_source_tdx/tdx_f10_specs.py +1142 -0
- axdata_source_tdx/tdx_server_config.py +389 -0
- axdata_source_tdx/time_series_normalize.py +370 -0
- axdata_source_tdx/tqlex.py +138 -0
- axdata_source_tdx/wire.py +32 -0
- axdata_source_tdx/wire_requests.py +190 -0
- axdata_source_tdx_ext/__init__.py +15 -0
- axdata_source_tdx_ext/adapter.py +31 -0
- axdata_source_tdx_ext/axdata-provider.json +9424 -0
- axdata_source_tdx_ext/catalog.py +33 -0
- axdata_source_tdx_ext/metadata.py +8 -0
- axdata_source_tdx_ext/provider.py +44 -0
- axdata_source_tencent/__init__.py +15 -0
- axdata_source_tencent/adapter.py +31 -0
- axdata_source_tencent/axdata-provider.json +291 -0
- axdata_source_tencent/catalog.py +190 -0
- axdata_source_tencent/metadata.py +8 -0
- axdata_source_tencent/provider.py +41 -0
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
"""Built-in Provider wrappers for the current source request catalog.
|
|
2
|
+
|
|
3
|
+
The existing AxData source catalog remains the behavioral source of truth in
|
|
4
|
+
this phase. This module only projects it into the new Provider protocol so the
|
|
5
|
+
registry can represent today's built-in sources before routing is migrated.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from importlib import import_module
|
|
12
|
+
from typing import Any, Mapping, Sequence
|
|
13
|
+
|
|
14
|
+
from .plugins import (
|
|
15
|
+
AssetClass,
|
|
16
|
+
CollectorSpec,
|
|
17
|
+
DownloaderMode,
|
|
18
|
+
DownloaderProfile as PluginDownloaderProfile,
|
|
19
|
+
FieldSpec,
|
|
20
|
+
FieldType,
|
|
21
|
+
InterfaceCollectionSpec,
|
|
22
|
+
InterfaceSpec,
|
|
23
|
+
ParameterSpec,
|
|
24
|
+
ParameterType,
|
|
25
|
+
RequestExample as PluginRequestExample,
|
|
26
|
+
RequestMode,
|
|
27
|
+
SourceResult,
|
|
28
|
+
)
|
|
29
|
+
from .sources import SourceRequestInterface
|
|
30
|
+
from .sources.display_docs import display_doc_for_interface
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
BUILTIN_SOURCE_CATALOG_MODULES: tuple[tuple[str, str], ...] = (
|
|
34
|
+
("exchange", "axdata_core.sources.exchange.catalog"),
|
|
35
|
+
("cninfo", "axdata_core.sources.cninfo.catalog"),
|
|
36
|
+
("tencent", "axdata_core.sources.tencent.catalog"),
|
|
37
|
+
("eastmoney", "axdata_core.sources.eastmoney.catalog"),
|
|
38
|
+
("cls", "axdata_core.sources.cls.catalog"),
|
|
39
|
+
("kph", "axdata_core.sources.kph.catalog"),
|
|
40
|
+
("sina", "axdata_core.sources.sina.catalog"),
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
BUILTIN_PROVIDER_PREFIX = "axdata.source"
|
|
44
|
+
BUILTIN_SOURCE_NAMES_ZH: Mapping[str, str] = {}
|
|
45
|
+
_PROJECTION_DOWNLOADER_PROFILES_CACHE: tuple[Any, ...] | None = None
|
|
46
|
+
|
|
47
|
+
_BUILTIN_INTERFACE_DOWNLOADER_CONFIG: Mapping[str, Mapping[str, Any]] = {
|
|
48
|
+
"stock_trade_calendar_exchange": {
|
|
49
|
+
"primary_key": ("cal_date",),
|
|
50
|
+
"params": {"year": "2026"},
|
|
51
|
+
"fields": ("cal_date", "is_open", "pretrade_date"),
|
|
52
|
+
"output_layer": "core",
|
|
53
|
+
"required_columns": ("cal_date", "is_open"),
|
|
54
|
+
"date_field": "cal_date",
|
|
55
|
+
},
|
|
56
|
+
"stock_historical_list_exchange": {
|
|
57
|
+
"primary_key": ("trade_date", "instrument_id"),
|
|
58
|
+
"params": {"trade_date": "20260102"},
|
|
59
|
+
"output_layer": "snapshot",
|
|
60
|
+
"required_columns": ("trade_date", "instrument_id"),
|
|
61
|
+
"date_field": "trade_date",
|
|
62
|
+
},
|
|
63
|
+
"stock_basic_info_exchange": {
|
|
64
|
+
"primary_key": ("instrument_id",),
|
|
65
|
+
"params": {},
|
|
66
|
+
"output_layer": "core",
|
|
67
|
+
"required_columns": ("instrument_id", "symbol", "exchange", "asset_type", "name"),
|
|
68
|
+
"date_field": "list_date",
|
|
69
|
+
"numeric_positive_columns": ("total_share", "float_share"),
|
|
70
|
+
},
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@dataclass(frozen=True)
|
|
75
|
+
class BuiltinSourceProvider:
|
|
76
|
+
"""Provider wrapper for one current built-in source catalog group."""
|
|
77
|
+
|
|
78
|
+
source_code: str
|
|
79
|
+
source_name_zh: str
|
|
80
|
+
interfaces_: tuple[InterfaceSpec, ...]
|
|
81
|
+
version: str = "0.1.0"
|
|
82
|
+
plugin_api_version: str = "1.0"
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def provider_id(self) -> str:
|
|
86
|
+
return f"{BUILTIN_PROVIDER_PREFIX}.{self.source_code}"
|
|
87
|
+
|
|
88
|
+
def interfaces(self) -> Sequence[InterfaceSpec]:
|
|
89
|
+
return self.interfaces_
|
|
90
|
+
|
|
91
|
+
def create_adapter(self, options: Mapping[str, object] | None = None) -> "BuiltinSourceAdapter":
|
|
92
|
+
return BuiltinSourceAdapter(
|
|
93
|
+
source_code=self.source_code,
|
|
94
|
+
provider_id=self.provider_id,
|
|
95
|
+
options=options,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def downloader_profiles(self) -> Sequence[PluginDownloaderProfile]:
|
|
99
|
+
if self.source_code != "tdx":
|
|
100
|
+
return tuple(
|
|
101
|
+
_generic_builtin_downloader_profile(interface)
|
|
102
|
+
for interface in self.interfaces_
|
|
103
|
+
if interface.name in _BUILTIN_INTERFACE_DOWNLOADER_CONFIG
|
|
104
|
+
)
|
|
105
|
+
interface_names = {interface.name for interface in self.interfaces_}
|
|
106
|
+
return tuple(
|
|
107
|
+
_convert_downloader_profile(profile)
|
|
108
|
+
for profile in _current_downloader_profiles()
|
|
109
|
+
if profile.interface_name in interface_names
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
def collectors(self) -> Sequence[CollectorSpec]:
|
|
113
|
+
return ()
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@dataclass(frozen=True)
|
|
117
|
+
class BuiltinSourceAdapter:
|
|
118
|
+
"""Adapter shim that delegates to the existing source request adapters."""
|
|
119
|
+
|
|
120
|
+
source_code: str
|
|
121
|
+
provider_id: str | None = None
|
|
122
|
+
options: Mapping[str, object] | None = None
|
|
123
|
+
|
|
124
|
+
def call(
|
|
125
|
+
self,
|
|
126
|
+
interface_name: str,
|
|
127
|
+
params: Mapping[str, object] | None = None,
|
|
128
|
+
fields: Sequence[str] | None = None,
|
|
129
|
+
options: Mapping[str, object] | None = None,
|
|
130
|
+
) -> SourceResult:
|
|
131
|
+
# Import lazily to keep provider catalog projection side-effect free.
|
|
132
|
+
from .source_projection import select_fields
|
|
133
|
+
|
|
134
|
+
request_options = {**dict(self.options or {}), **dict(options or {})}
|
|
135
|
+
adapter = _adapter_for_builtin_source(
|
|
136
|
+
provider_id=self.provider_id,
|
|
137
|
+
source_code=self.source_code,
|
|
138
|
+
options=request_options,
|
|
139
|
+
)
|
|
140
|
+
records = adapter.request(interface_name, dict(params or {}))
|
|
141
|
+
if fields:
|
|
142
|
+
records = select_fields(records, fields)
|
|
143
|
+
meta = {
|
|
144
|
+
"interface_name": interface_name,
|
|
145
|
+
"source": adapter.source,
|
|
146
|
+
"requested_fields": list(fields or []),
|
|
147
|
+
}
|
|
148
|
+
adapter_meta = getattr(adapter, "last_meta", None)
|
|
149
|
+
if isinstance(adapter_meta, Mapping):
|
|
150
|
+
meta.update(adapter_meta)
|
|
151
|
+
return SourceResult(
|
|
152
|
+
data=tuple(records),
|
|
153
|
+
meta=meta,
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class _ProjectionObject:
|
|
158
|
+
"""Small shape-compatible object for Provider metadata projection."""
|
|
159
|
+
|
|
160
|
+
def __init__(self, **values: Any) -> None:
|
|
161
|
+
for name, value in values.items():
|
|
162
|
+
setattr(self, name, value)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class _ProjectionConcurrencyProfile(_ProjectionObject):
|
|
166
|
+
"""Downloader concurrency shape without importing the runtime downloader."""
|
|
167
|
+
|
|
168
|
+
def __init__(self, **values: Any) -> None:
|
|
169
|
+
defaults = {
|
|
170
|
+
"mode": "fixed",
|
|
171
|
+
"mode_editable": False,
|
|
172
|
+
"default_source_server_count": 1,
|
|
173
|
+
"source_server_count_editable": False,
|
|
174
|
+
"max_source_server_count": 1,
|
|
175
|
+
"default_connections_per_server": 1,
|
|
176
|
+
"connections_per_server_editable": False,
|
|
177
|
+
"max_connections_per_server": 1,
|
|
178
|
+
"default_max_concurrent_tasks": 1,
|
|
179
|
+
"max_concurrent_tasks_editable": False,
|
|
180
|
+
"max_max_concurrent_tasks": 1,
|
|
181
|
+
"default_batch_size": 1,
|
|
182
|
+
"batch_size_editable": False,
|
|
183
|
+
"max_batch_size": 1,
|
|
184
|
+
"default_request_interval_ms": 0,
|
|
185
|
+
"request_interval_ms_editable": False,
|
|
186
|
+
"min_request_interval_ms": 0,
|
|
187
|
+
"max_request_interval_ms": 0,
|
|
188
|
+
"default_retry_count": 0,
|
|
189
|
+
"retry_count_editable": False,
|
|
190
|
+
"max_retry_count": 0,
|
|
191
|
+
"default_timeout_ms": 30000,
|
|
192
|
+
"timeout_ms_editable": False,
|
|
193
|
+
"min_timeout_ms": 30000,
|
|
194
|
+
"max_timeout_ms": 30000,
|
|
195
|
+
"description": "",
|
|
196
|
+
}
|
|
197
|
+
defaults.update(values)
|
|
198
|
+
super().__init__(**defaults)
|
|
199
|
+
|
|
200
|
+
@property
|
|
201
|
+
def default_connection_count(self) -> int:
|
|
202
|
+
return min(
|
|
203
|
+
self.default_source_server_count * self.default_connections_per_server,
|
|
204
|
+
self.default_max_concurrent_tasks,
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
@property
|
|
208
|
+
def max_connection_count(self) -> int:
|
|
209
|
+
return min(
|
|
210
|
+
self.max_source_server_count * self.max_connections_per_server,
|
|
211
|
+
self.max_max_concurrent_tasks,
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
class _ProjectionDownloaderProfile(_ProjectionObject):
|
|
216
|
+
"""Downloader profile shape used only for built-in Provider manifests."""
|
|
217
|
+
|
|
218
|
+
pass
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def list_builtin_providers() -> tuple[BuiltinSourceProvider, ...]:
|
|
222
|
+
"""Return built-in providers projected from the current catalog."""
|
|
223
|
+
|
|
224
|
+
return tuple(
|
|
225
|
+
_builtin_provider_from_interfaces(source_code, _source_interfaces(source_code))
|
|
226
|
+
for source_code, _module_name in BUILTIN_SOURCE_CATALOG_MODULES
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def get_builtin_provider(source_code: str) -> BuiltinSourceProvider:
|
|
231
|
+
"""Return one built-in provider by source code."""
|
|
232
|
+
|
|
233
|
+
normalized = source_code.strip()
|
|
234
|
+
known_source_codes = [known_source_code for known_source_code, _module_name in BUILTIN_SOURCE_CATALOG_MODULES]
|
|
235
|
+
if normalized in known_source_codes:
|
|
236
|
+
return _builtin_provider_from_interfaces(normalized, _source_interfaces(normalized))
|
|
237
|
+
known = ", ".join(known_source_codes)
|
|
238
|
+
raise KeyError(f"Unknown built-in provider {source_code!r}. Known providers: {known}.")
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def _source_interfaces(source_code: str) -> tuple[SourceRequestInterface, ...]:
|
|
242
|
+
module_name = dict(BUILTIN_SOURCE_CATALOG_MODULES)[source_code]
|
|
243
|
+
module = import_module(module_name)
|
|
244
|
+
interfaces = getattr(module, "INTERFACES")
|
|
245
|
+
return tuple(interfaces.values())
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def _builtin_provider_from_interfaces(
|
|
249
|
+
source_code: str,
|
|
250
|
+
interfaces: tuple[SourceRequestInterface, ...],
|
|
251
|
+
) -> BuiltinSourceProvider:
|
|
252
|
+
if not interfaces:
|
|
253
|
+
raise KeyError(f"Built-in provider {source_code!r} has no interfaces.")
|
|
254
|
+
source_name_zh = _builtin_source_name_zh(source_code, interfaces[0].source_name_zh)
|
|
255
|
+
return BuiltinSourceProvider(
|
|
256
|
+
source_code=source_code,
|
|
257
|
+
source_name_zh=source_name_zh,
|
|
258
|
+
interfaces_=tuple(_convert_interface(interface) for interface in interfaces),
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def _adapter_for_builtin_source(
|
|
263
|
+
source_code: str,
|
|
264
|
+
*,
|
|
265
|
+
provider_id: str | None = None,
|
|
266
|
+
options: Mapping[str, object] | None = None,
|
|
267
|
+
) -> Any:
|
|
268
|
+
"""Create the adapter for one known built-in Provider/source."""
|
|
269
|
+
|
|
270
|
+
from .source_adapter_factory import adapter_for_source_identity
|
|
271
|
+
|
|
272
|
+
return adapter_for_source_identity(
|
|
273
|
+
provider_id=provider_id,
|
|
274
|
+
source_code=source_code,
|
|
275
|
+
options=options,
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def _convert_interface(interface: SourceRequestInterface) -> InterfaceSpec:
|
|
280
|
+
source_name_zh = _builtin_source_name_zh(interface.source_code, interface.source_name_zh)
|
|
281
|
+
display_doc = display_doc_for_interface(interface.name)
|
|
282
|
+
summary_zh = display_doc.summary_zh or interface.summary_zh or _default_summary_zh(interface, source_name_zh)
|
|
283
|
+
description_zh = (
|
|
284
|
+
display_doc.description_zh
|
|
285
|
+
or interface.description_zh
|
|
286
|
+
or _default_description_zh(interface, summary_zh)
|
|
287
|
+
)
|
|
288
|
+
downloader_profile_name = (
|
|
289
|
+
_downloader_profile_name(interface.name)
|
|
290
|
+
if interface.source_code == "tdx"
|
|
291
|
+
else _generic_builtin_downloader_name(interface.name)
|
|
292
|
+
)
|
|
293
|
+
return InterfaceSpec(
|
|
294
|
+
name=interface.name,
|
|
295
|
+
display_name_zh=interface.display_name_zh,
|
|
296
|
+
source_code=interface.source_code,
|
|
297
|
+
source_name_zh=source_name_zh,
|
|
298
|
+
category=interface.category,
|
|
299
|
+
menu_path=(source_name_zh, interface.category),
|
|
300
|
+
asset_class=_infer_asset_class(interface),
|
|
301
|
+
request_mode=_convert_request_mode(interface.request_mode),
|
|
302
|
+
collection=InterfaceCollectionSpec(
|
|
303
|
+
supported=downloader_profile_name is not None,
|
|
304
|
+
default_profile=downloader_profile_name,
|
|
305
|
+
),
|
|
306
|
+
parameters=tuple(_convert_parameter(parameter) for parameter in interface.parameters),
|
|
307
|
+
fields=tuple(_convert_field(field) for field in interface.fields),
|
|
308
|
+
examples=(_convert_example(interface),),
|
|
309
|
+
summary_zh=summary_zh,
|
|
310
|
+
description_zh=description_zh,
|
|
311
|
+
params_note_zh=display_doc.params_note_zh or interface.params_note_zh,
|
|
312
|
+
params_example_zh=display_doc.params_example_zh or interface.params_example_zh,
|
|
313
|
+
notes=interface.description,
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def _builtin_source_name_zh(source_code: str, fallback: str) -> str:
|
|
318
|
+
return BUILTIN_SOURCE_NAMES_ZH.get(source_code, fallback)
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def _default_summary_zh(interface: SourceRequestInterface, source_name_zh: str) -> str:
|
|
322
|
+
title = interface.display_name_zh or interface.name
|
|
323
|
+
return f"临时获取{source_name_zh}{title}数据,默认不入库。"
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def _default_description_zh(interface: SourceRequestInterface, summary_zh: str) -> str:
|
|
327
|
+
if _contains_cjk(interface.first_stage_strategy):
|
|
328
|
+
return interface.first_stage_strategy
|
|
329
|
+
return summary_zh
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def _contains_cjk(value: str) -> bool:
|
|
333
|
+
return any("\u4e00" <= char <= "\u9fff" for char in value)
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def _current_downloader_profiles() -> tuple[Any, ...]:
|
|
337
|
+
"""Return current built-in downloader profiles without making them catalog truth."""
|
|
338
|
+
|
|
339
|
+
global _PROJECTION_DOWNLOADER_PROFILES_CACHE
|
|
340
|
+
if _PROJECTION_DOWNLOADER_PROFILES_CACHE is not None:
|
|
341
|
+
return _PROJECTION_DOWNLOADER_PROFILES_CACHE
|
|
342
|
+
|
|
343
|
+
from .downloader_registry import load_builtin_downloader_profiles
|
|
344
|
+
|
|
345
|
+
_PROJECTION_DOWNLOADER_PROFILES_CACHE = tuple(
|
|
346
|
+
load_builtin_downloader_profiles(
|
|
347
|
+
_ProjectionConcurrencyProfile,
|
|
348
|
+
_ProjectionDownloaderProfile,
|
|
349
|
+
).values()
|
|
350
|
+
)
|
|
351
|
+
return _PROJECTION_DOWNLOADER_PROFILES_CACHE
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def _downloader_profile_name(interface_name: str) -> str | None:
|
|
355
|
+
for profile in _current_downloader_profiles():
|
|
356
|
+
if profile.interface_name == interface_name:
|
|
357
|
+
return _plugin_downloader_name(profile)
|
|
358
|
+
return None
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def _convert_downloader_profile(profile: Any) -> PluginDownloaderProfile:
|
|
362
|
+
concurrency = profile.concurrency
|
|
363
|
+
return PluginDownloaderProfile(
|
|
364
|
+
name=_plugin_downloader_name(profile),
|
|
365
|
+
interface_name=profile.interface_name,
|
|
366
|
+
display_name_zh=profile.display_name,
|
|
367
|
+
resource_group=str(getattr(profile, "resource_group", None) or f"{profile.interface_name}.source"),
|
|
368
|
+
mode=DownloaderMode.SNAPSHOT.value,
|
|
369
|
+
default_options={
|
|
370
|
+
"params": dict(profile.default_params),
|
|
371
|
+
"fields": list(profile.default_fields) if profile.default_fields is not None else None,
|
|
372
|
+
"formats": [profile.output_format],
|
|
373
|
+
"connection_mode": profile.default_connection_mode,
|
|
374
|
+
"source_server_count": concurrency.default_source_server_count,
|
|
375
|
+
"connections_per_server": concurrency.default_connections_per_server,
|
|
376
|
+
"max_concurrent_tasks": concurrency.default_max_concurrent_tasks,
|
|
377
|
+
"batch_size": concurrency.default_batch_size,
|
|
378
|
+
"request_interval_ms": concurrency.default_request_interval_ms,
|
|
379
|
+
"retry_count": concurrency.default_retry_count,
|
|
380
|
+
"timeout_ms": concurrency.default_timeout_ms,
|
|
381
|
+
},
|
|
382
|
+
default_limits={
|
|
383
|
+
"max_active_jobs": 1,
|
|
384
|
+
"max_connections_total": concurrency.max_connection_count,
|
|
385
|
+
"request_interval_ms": concurrency.default_request_interval_ms,
|
|
386
|
+
"max_retries": concurrency.max_retry_count,
|
|
387
|
+
},
|
|
388
|
+
output={
|
|
389
|
+
"default_dir_name": profile.interface_name,
|
|
390
|
+
"file_name_template": "{interface_name}_{data_date}_{run_time}",
|
|
391
|
+
"supported_formats": list(profile.supported_formats),
|
|
392
|
+
"output_layer": profile.output_layer,
|
|
393
|
+
"write_mode": getattr(profile, "write_mode", "snapshot"),
|
|
394
|
+
"primary_key": list(profile.primary_key) if isinstance(profile.primary_key, tuple) else profile.primary_key,
|
|
395
|
+
"partition_by": list(getattr(profile, "partition_by", ()) or ()),
|
|
396
|
+
"required_columns": list(getattr(profile, "required_columns", ()) or ()),
|
|
397
|
+
"expected_columns": list(getattr(profile, "expected_columns", ()) or ()),
|
|
398
|
+
"date_field": getattr(profile, "date_field", None),
|
|
399
|
+
"datetime_field": getattr(profile, "datetime_field", None),
|
|
400
|
+
"numeric_positive_columns": list(getattr(profile, "numeric_positive_columns", ()) or ()),
|
|
401
|
+
"field_mappings": dict(getattr(profile, "field_mappings", {}) or {}),
|
|
402
|
+
},
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
def _generic_builtin_downloader_name(interface_name: str) -> str | None:
|
|
407
|
+
if interface_name not in _BUILTIN_INTERFACE_DOWNLOADER_CONFIG:
|
|
408
|
+
return None
|
|
409
|
+
return f"{interface_name}.snapshot"
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
def _generic_builtin_downloader_profile(interface: InterfaceSpec) -> PluginDownloaderProfile:
|
|
413
|
+
config = dict(_BUILTIN_INTERFACE_DOWNLOADER_CONFIG[interface.name])
|
|
414
|
+
default_fields = config.get("fields")
|
|
415
|
+
if default_fields is None:
|
|
416
|
+
default_fields = tuple(field.name for field in interface.fields)
|
|
417
|
+
return PluginDownloaderProfile(
|
|
418
|
+
name=f"{interface.name}.snapshot",
|
|
419
|
+
interface_name=interface.name,
|
|
420
|
+
display_name_zh=f"{interface.display_name_zh}采集",
|
|
421
|
+
resource_group=f"{interface.source_code}.http",
|
|
422
|
+
mode=DownloaderMode.SNAPSHOT.value,
|
|
423
|
+
default_options={
|
|
424
|
+
"params": dict(config.get("params") or {}),
|
|
425
|
+
"fields": list(default_fields),
|
|
426
|
+
"formats": ["parquet"],
|
|
427
|
+
"source_server_count": 1,
|
|
428
|
+
"connections_per_server": 1,
|
|
429
|
+
"max_concurrent_tasks": 1,
|
|
430
|
+
"batch_size": 1,
|
|
431
|
+
"request_interval_ms": 0,
|
|
432
|
+
"retry_count": 0,
|
|
433
|
+
"timeout_ms": 30000,
|
|
434
|
+
},
|
|
435
|
+
default_limits={
|
|
436
|
+
"max_active_jobs": 1,
|
|
437
|
+
"max_connections_total": 1,
|
|
438
|
+
"request_interval_ms": 0,
|
|
439
|
+
"max_retries": 0,
|
|
440
|
+
},
|
|
441
|
+
output={
|
|
442
|
+
"default_dir_name": interface.name,
|
|
443
|
+
"file_name_template": "{interface_name}_{data_date}_{run_time}",
|
|
444
|
+
"supported_formats": ["parquet", "csv", "jsonl"],
|
|
445
|
+
"output_layer": str(config.get("output_layer") or "snapshot"),
|
|
446
|
+
"write_mode": str(config.get("write_mode") or "snapshot"),
|
|
447
|
+
"primary_key": list(config.get("primary_key") or ()),
|
|
448
|
+
"partition_by": list(config.get("partition_by") or ()),
|
|
449
|
+
"required_columns": list(config.get("required_columns") or config.get("primary_key") or ()),
|
|
450
|
+
"expected_columns": list(default_fields),
|
|
451
|
+
"date_field": config.get("date_field"),
|
|
452
|
+
"datetime_field": config.get("datetime_field"),
|
|
453
|
+
"numeric_positive_columns": list(config.get("numeric_positive_columns") or ()),
|
|
454
|
+
},
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
def _generic_builtin_collector_spec(interface: InterfaceSpec) -> CollectorSpec:
|
|
459
|
+
config = dict(_BUILTIN_INTERFACE_DOWNLOADER_CONFIG[interface.name])
|
|
460
|
+
output_layer = str(config.get("output_layer") or "snapshot")
|
|
461
|
+
return CollectorSpec(
|
|
462
|
+
name=f"{interface.source_code}.{interface.name}.snapshot",
|
|
463
|
+
display_name_zh=f"{interface.display_name_zh}采集",
|
|
464
|
+
description=f"通过 {interface.source_name_zh} 源端接口 {interface.name} 采集小批量快照。",
|
|
465
|
+
interfaces=(interface.name,),
|
|
466
|
+
downloader_profile=f"{interface.name}.snapshot",
|
|
467
|
+
resource_group=f"{interface.source_code}.http",
|
|
468
|
+
default_params=dict(config.get("params") or {}),
|
|
469
|
+
required_interfaces=(interface.name,),
|
|
470
|
+
output={"layer": output_layer, "formats": ["parquet", "csv", "jsonl"]},
|
|
471
|
+
)
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
def _plugin_downloader_name(profile: Any) -> str:
|
|
475
|
+
return f"{profile.interface_name}.snapshot"
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
def _convert_parameter(parameter: Any) -> ParameterSpec:
|
|
479
|
+
return ParameterSpec(
|
|
480
|
+
name=parameter.name,
|
|
481
|
+
display_name_zh=parameter.description_zh or parameter.name,
|
|
482
|
+
type=_convert_parameter_type(parameter.dtype),
|
|
483
|
+
required=parameter.required,
|
|
484
|
+
multiple="list" in parameter.dtype,
|
|
485
|
+
default=parameter.default,
|
|
486
|
+
description=parameter.description_zh or parameter.description,
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
def _convert_field(field: Any) -> FieldSpec:
|
|
491
|
+
return FieldSpec(
|
|
492
|
+
name=field.name,
|
|
493
|
+
display_name_zh=field.description_zh or field.name,
|
|
494
|
+
type=_convert_field_type(field.dtype),
|
|
495
|
+
required=False,
|
|
496
|
+
description=field.description_zh or field.description,
|
|
497
|
+
)
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
def _convert_example(interface: SourceRequestInterface) -> PluginRequestExample:
|
|
501
|
+
return PluginRequestExample(
|
|
502
|
+
title=interface.display_name_zh,
|
|
503
|
+
request={
|
|
504
|
+
"interface_name": interface.name,
|
|
505
|
+
"params": dict(interface.example.request.get("params", interface.example.request)),
|
|
506
|
+
},
|
|
507
|
+
response={
|
|
508
|
+
"data": [dict(row) for row in interface.example.response],
|
|
509
|
+
"schema": [{"name": field.name, "type": _convert_field_type(field.dtype)} for field in interface.fields],
|
|
510
|
+
"meta": {"count": len(interface.example.response)},
|
|
511
|
+
},
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
|
|
515
|
+
def _convert_request_mode(value: str) -> str:
|
|
516
|
+
if value in {mode.value for mode in RequestMode}:
|
|
517
|
+
return value
|
|
518
|
+
return RequestMode.SOURCE_REQUEST.value
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
def _convert_parameter_type(dtype: str) -> str:
|
|
522
|
+
normalized = dtype.lower()
|
|
523
|
+
if "boolean" in normalized:
|
|
524
|
+
return ParameterType.BOOLEAN.value
|
|
525
|
+
if "date" in normalized and "datetime" not in normalized:
|
|
526
|
+
return ParameterType.DATE.value
|
|
527
|
+
if "datetime" in normalized:
|
|
528
|
+
return ParameterType.DATETIME.value
|
|
529
|
+
if "integer" in normalized and "string" not in normalized and "list" not in normalized:
|
|
530
|
+
return ParameterType.INTEGER.value
|
|
531
|
+
if ("number" in normalized or "float" in normalized) and "string" not in normalized:
|
|
532
|
+
return ParameterType.NUMBER.value
|
|
533
|
+
return ParameterType.STRING.value
|
|
534
|
+
|
|
535
|
+
|
|
536
|
+
def _convert_field_type(dtype: str) -> str:
|
|
537
|
+
normalized = dtype.lower()
|
|
538
|
+
if "boolean" in normalized:
|
|
539
|
+
return FieldType.BOOLEAN.value
|
|
540
|
+
if "datetime" in normalized:
|
|
541
|
+
return FieldType.DATETIME.value
|
|
542
|
+
if normalized.startswith("date"):
|
|
543
|
+
return FieldType.DATE.value
|
|
544
|
+
if normalized.startswith("time"):
|
|
545
|
+
return FieldType.STRING.value
|
|
546
|
+
if "integer" in normalized:
|
|
547
|
+
return FieldType.INTEGER.value
|
|
548
|
+
if "number" in normalized or "float" in normalized:
|
|
549
|
+
return FieldType.NUMBER.value
|
|
550
|
+
return FieldType.STRING.value
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
def _infer_asset_class(interface: SourceRequestInterface) -> str:
|
|
554
|
+
name = interface.name
|
|
555
|
+
category = interface.category
|
|
556
|
+
if name.startswith("index_"):
|
|
557
|
+
return AssetClass.INDEX.value
|
|
558
|
+
if name.startswith("etf_"):
|
|
559
|
+
return AssetClass.ETF.value
|
|
560
|
+
if name.startswith("fund_"):
|
|
561
|
+
return AssetClass.FUND.value
|
|
562
|
+
if name.startswith("bond_"):
|
|
563
|
+
return AssetClass.BOND.value
|
|
564
|
+
if name.startswith("futures_"):
|
|
565
|
+
return AssetClass.FUTURE.value
|
|
566
|
+
if name.startswith("option_"):
|
|
567
|
+
return AssetClass.OPTION.value
|
|
568
|
+
if name.startswith("fx_"):
|
|
569
|
+
return AssetClass.FX.value
|
|
570
|
+
if name.startswith("macro_"):
|
|
571
|
+
return AssetClass.MACRO.value
|
|
572
|
+
if category in {"指数数据"}:
|
|
573
|
+
return AssetClass.INDEX.value
|
|
574
|
+
if category in {"基金数据"}:
|
|
575
|
+
return AssetClass.FUND.value
|
|
576
|
+
if category in {"债券数据"}:
|
|
577
|
+
return AssetClass.BOND.value
|
|
578
|
+
if category in {"期货数据"}:
|
|
579
|
+
return AssetClass.FUTURE.value
|
|
580
|
+
if category in {"期权数据"}:
|
|
581
|
+
return AssetClass.OPTION.value
|
|
582
|
+
if category in {"外汇数据"}:
|
|
583
|
+
return AssetClass.FX.value
|
|
584
|
+
if category in {"宏观数据"}:
|
|
585
|
+
return AssetClass.MACRO.value
|
|
586
|
+
return AssetClass.STOCK.value
|