LLM 驱动的多市场股票智能分析系统:多源行情、实时新闻、决策看板与自动推送,支持零成本定时运行。 LLM-powered multi-market stock analysis system with multi-source market data, real-time news, decision dashboard, automated notifications, and cost-free scheduled runs.
This report presents the forensic synthetic code analysis of ZhuLinsen/daily_stock_analysis, a Python project with 57,120 GitHub stars. SynthScan v2.0 examined 371,512 lines of code across 898 source files, recording 7516 pattern matches distributed across 21 syntactic categories. The overall adjusted score of 21.3 places this repository in the Moderate AI signal band.
The scanner applied 160+ deterministic lexical heuristics, multi-line block detectors, abstract syntax tree depth profilers, and a cross-file Jaccard similarity matrix to construct a statistically normalised synthetic code estimate. All matches are individually weighted by severity coefficient and contextual multiplier before summation, and the resulting headline score is temporally discounted to account for the repository's development history relative to the commercial emergence of large language model coding tooling (November 2022 onward).
This chart maps the temporal evolution of the adjusted synthetic code score across successive scan runs. An upward trajectory indicates ongoing incorporation of AI-generated code or expanding LLM-assisted scaffolding; a stable or declining trajectory may reflect active human refactoring, code removal, or the adoption of stricter authorship policies. The dashed secondary line (right axis) independently tracks total raw pattern hit count, which can diverge from the normalised score when codebase size changes significantly between scans.
Classifies detected patterns by their diagnostic confidence and structural impact. CRITICAL patterns (coefficient 10) represent definitive synthetic signatures — hallucinated imports, explicit LLM attribution metadata — virtually never produced by human authors. HIGH (5) indicates strong structural tells such as cross-file repetition or cross-linguistic idioms. MEDIUM (2) covers recognisable conversational padding and AI-specific vocabulary. LOW (1) captures subtle indicators like tautological comments and generic boilerplate that require density to carry independent signal.
This horizontal bar chart decomposes the repository's raw synthetic code score by top-level directory, allowing you to pinpoint precisely which modules or components carry the highest AI authorship density. Directories with disproportionately high scores relative to their size warrant targeted manual review: concentrated AI signatures often trace back to mass-generated configuration layers, auto-ported test suites, LLM-scaffolded boilerplate classes, or entire subsystems authored under heavy copilot assistance. Use this view to prioritise your human code-review effort.
The scanner identified 7516 distinct pattern matches across 21 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a statistically significant AI authorship indicator. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.
Reading the findings table: The Severity column indicates the diagnostic confidence level (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — comment-context matches receive a ×1.5 weight because LLMs systematically over-annotate. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier as dense clusters constitute far stronger evidence of synthetic authorship than isolated hits.
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | main.py | 95 | def _warn_if_public_webui_without_auth(host: str) -> None: | CODE |
| LOW | main.py | 111 | def _resolve_web_service_bind(args: argparse.Namespace, config: Config) -> Tuple[str, int]: | CODE |
| LOW | main.py | 208 | def _get_stock_analysis_pipeline(): | CODE |
| LOW | main.py | 247 | def _reload_env_file_values_preserving_overrides() -> None: | CODE |
| LOW⚡ | main.py | 587 | def _can_reuse_market_context_for_review(summary: str, region: str) -> bool: | STRING |
| LOW⚡ | main.py | 597 | def _resolve_daily_market_context_market(market: str, normalized_region: str) -> str: | STRING |
| LOW⚡ | main.py | 606 | def _resolve_daily_market_context_target_date( | STRING |
| LOW | main.py | 435 | def _compute_trading_day_filter( | STRING |
| LOW | main.py | 477 | def _run_market_review_with_shared_lock( | STRING |
| LOW | main.py | 510 | def _refresh_stock_index_cache_for_analysis(config: Config) -> None: | STRING |
| LOW | main.py | 527 | def _prime_daily_market_context( | STRING |
| LOW | main.py | 621 | def _market_review_report_text(review_result: Any) -> str: | STRING |
| LOW | main.py | 630 | def _save_reused_market_review_report( | STRING |
| LOW | main.py | 1012 | def _run_analysis_with_runtime_scheduler_lock( | STRING |
| LOW | main.py | 1165 | def _resolve_scheduled_stock_codes(stock_codes: Optional[List[str]]) -> Optional[List[str]]: | STRING |
| LOW | main.py | 1181 | def _build_schedule_time_provider(default_schedule_time: str): | STRING |
| LOW | main.py | 1208 | def _build_schedule_times_provider(default_schedule_time: str): | STRING |
| LOW | tests/test_backtest_service.py | 223 | def test_run_backtest_accepts_dotted_exchange_prefix_and_filters_analysis_date_range(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 253 | def test_run_backtest_keeps_dotted_cn_code_match_when_analysis_history_is_dotted(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 291 | def test_run_backtest_matches_compact_prefixed_analysis_history_with_canonical_query(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 345 | def test_run_backtest_matches_compact_ss_alias_after_request_normalization(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 379 | def test_run_backtest_uses_bare_daily_bars_and_summary_for_compact_ss_history(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 443 | def test_run_backtest_uses_compact_forward_bars_when_analysis_history_is_bare_code(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 495 | def test_run_backtest_matches_compact_bj_code_shape_with_no_prefix_query(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 549 | def test_build_market_code_variants_includes_compact_prefix_and_bj_forms(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 564 | def test_daily_refill_codes_normalize_legacy_ss_aliases_once(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 580 | def test_try_fill_daily_data_uses_normalized_a_share_code_for_legacy_ss_alias(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 627 | def test_build_market_code_variants_rejects_wrong_explicit_exchange_for_bse_code(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 637 | def test_get_candidates_does_not_match_invalid_a_share_hk_cross_input(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 650 | def test_get_candidates_does_not_match_explicit_wrong_a_share_market(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 664 | def test_run_backtest_rejects_invalid_market_suffix_length_input(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 677 | def test_run_backtest_rejects_explicit_wrong_a_share_market(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 692 | def test_get_recent_evaluations_rejects_explicit_wrong_a_share_market(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 706 | def test_get_summary_rejects_explicit_wrong_a_share_market(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 719 | def test_run_backtest_bare_code_query_matches_dotted_history_records(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 763 | def test_run_backtest_uses_bare_daily_bars_for_dotted_history_record(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 818 | def test_run_backtest_uses_forward_bars_from_other_code_shape_when_start_daily_shape_differs(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 876 | def test_run_backtest_supports_us_suffix_code_shape_when_run_with_suffix(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 908 | def test_run_backtest_us_suffix_query_matches_bare_history_and_summary(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 954 | def test_run_backtest_bare_us_query_matches_us_suffix_history_and_summary(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1000 | def test_us_code_queries_match_legacy_results_without_rerun(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1117 | def test_run_backtest_matches_hk_different_code_shapes_in_analysis_history_and_daily(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1177 | def test_run_backtest_matches_hk_daily_shape_variants_for_prefixed_history(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1237 | def test_run_backtest_supports_dotted_hk_prefix_query_shape(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1312 | def test_run_backtest_filters_by_snapshot_analysis_date_not_created_at(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1359 | def test_run_backtest_persists_snapshot_date_when_start_daily_falls_back(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1428 | def test_date_filtered_rerun_aligns_legacy_result_date_to_snapshot_date(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1498 | def test_date_filtered_rerun_aligns_legacy_result_date_when_new_candidates_process(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1599 | def test_run_backtest_pages_candidates_before_analysis_date_filter(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1639 | def test_run_backtest_reports_no_matching_candidates(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1657 | def test_run_backtest_reports_insufficient_daily_data(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1698 | def test_result_fields_correct(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1731 | def test_summaries_created_after_run(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1759 | def test_get_summary_overall_returns_sentinel_as_none(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1770 | def test_agent_learning_summary_helpers_keep_skill_rollups_neutral_until_supported(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1792 | def test_get_recent_evaluations(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1809 | def test_get_recent_evaluations_aligns_neutral_advice_with_score(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1838 | def test_get_recent_evaluations_prefers_persisted_raw_action(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1877 | def test_get_recent_evaluations_supports_tracking_fields_and_analysis_date_filters(self) -> None: | CODE |
| LOW | tests/test_backtest_service.py | 1909 | def test_get_summary_supports_analysis_date_range(self) -> None: | CODE |
| 5035 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | requirements.txt | 1 | # =================================== | COMMENT |
| MEDIUM | requirements.txt | 3 | # =================================== | COMMENT |
| MEDIUM | docker/docker-compose.yml | 1 | # =================================== | COMMENT |
| MEDIUM | docker/docker-compose.yml | 3 | # =================================== | COMMENT |
| MEDIUM⚡ | tests/test_notification_sender.py | 373 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM⚡ | tests/test_notification_sender.py | 375 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM⚡ | tests/test_notification_sender.py | 681 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM⚡ | tests/test_notification_sender.py | 683 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM⚡ | tests/test_multi_agent.py | 43 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_multi_agent.py | 45 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_multi_agent.py | 199 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_multi_agent.py | 201 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_multi_agent.py | 516 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_multi_agent.py | 518 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_multi_agent.py | 605 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_multi_agent.py | 607 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_multi_agent.py | 2296 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_multi_agent.py | 2298 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_multi_agent.py | 2606 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_multi_agent.py | 2608 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_multi_agent.py | 2694 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_multi_agent.py | 2696 | # ============================================================ | COMMENT |
| MEDIUM | tests/test_multi_agent.py | 439 | # ============================================================ | COMMENT |
| MEDIUM | tests/test_multi_agent.py | 441 | # ============================================================ | COMMENT |
| MEDIUM | tests/test_multi_agent.py | 642 | # ============================================================ | COMMENT |
| MEDIUM | tests/test_multi_agent.py | 644 | # ============================================================ | COMMENT |
| MEDIUM | tests/test_multi_agent.py | 730 | # ============================================================ | COMMENT |
| MEDIUM | tests/test_multi_agent.py | 732 | # ============================================================ | COMMENT |
| MEDIUM | tests/test_multi_agent.py | 1975 | # ============================================================ | COMMENT |
| MEDIUM | tests/test_multi_agent.py | 1977 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_image_stock_extractor_litellm.py | 78 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_image_stock_extractor_litellm.py | 80 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_image_stock_extractor_litellm.py | 126 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_image_stock_extractor_litellm.py | 128 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_image_stock_extractor_litellm.py | 153 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_image_stock_extractor_litellm.py | 155 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_image_stock_extractor_litellm.py | 289 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_image_stock_extractor_litellm.py | 291 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_image_stock_extractor_litellm.py | 362 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_image_stock_extractor_litellm.py | 364 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_image_stock_extractor_litellm.py | 37 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM | tests/test_image_stock_extractor_litellm.py | 39 | # --------------------------------------------------------------------------- | COMMENT |
| MEDIUM⚡ | tests/test_agent_pipeline.py | 36 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_agent_pipeline.py | 38 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_agent_pipeline.py | 1462 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_agent_pipeline.py | 1464 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_agent_pipeline.py | 1493 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_agent_pipeline.py | 1495 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_agent_pipeline.py | 2066 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_agent_pipeline.py | 2068 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_agent_pipeline.py | 2756 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_agent_pipeline.py | 2758 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_agent_pipeline.py | 2832 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_agent_pipeline.py | 2834 | # ============================================================ | COMMENT |
| MEDIUM | tests/test_agent_pipeline.py | 552 | # ============================================================ | COMMENT |
| MEDIUM | tests/test_agent_pipeline.py | 554 | # ============================================================ | COMMENT |
| MEDIUM⚡ | tests/test_history_loader.py | 15 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM⚡ | tests/test_history_loader.py | 17 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM⚡ | tests/test_history_loader.py | 32 | # ------------------------------------------------------------------ | COMMENT |
| MEDIUM⚡ | tests/test_history_loader.py | 34 | # ------------------------------------------------------------------ | COMMENT |
| 317 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | main.py | 1092 | def run_server(): | CODE |
| LOW | main.py | 55 | except Exception as exc: | CODE |
| LOW | main.py | 125 | except Exception as exc: # pragma: no cover - defensive branch | CODE |
| LOW | main.py | 523 | except Exception as exc: # noqa: BLE001 - stock index freshness must not block analysis. | STRING |
| LOW | main.py | 659 | except Exception as exc: | STRING |
| LOW | main.py | 971 | except Exception as e: | STRING |
| LOW | main.py | 991 | except Exception as e: | STRING |
| LOW | main.py | 996 | except Exception as e: | STRING |
| LOW | main.py | 1095 | except Exception as exc: # noqa: BLE001 - surface startup issues to caller promptly | STRING |
| LOW | main.py | 1146 | except Exception as exc: | STRING |
| LOW | main.py | 1161 | except Exception as exc: | STRING |
| LOW | main.py | 1251 | except Exception as exc: | STRING |
| LOW | main.py | 1262 | except Exception as exc: | STRING |
| LOW | main.py | 1269 | except Exception as exc: | STRING |
| LOW | main.py | 1368 | except Exception as e: | STRING |
| LOW | main.py | 1536 | except Exception as e: | STRING |
| LOW | tests/test_portfolio_service.py | 1162 | except Exception as exc: # pragma: no cover - asserted below | CODE |
| LOW | tests/test_portfolio_service.py | 1217 | except Exception as exc: # pragma: no cover - asserted below | CODE |
| LOW⚡ | tests/longbridge_live_smoke.py | 106 | except Exception as e: | CODE |
| LOW | tests/test_anspire_search.py | 466 | except Exception: | CODE |
| LOW | tests/test_social_sentiment_service.py | 129 | except Exception as exc: # pragma: no cover - thread collection | CODE |
| MEDIUM | tests/test_social_sentiment_service.py | 125 | def worker(): | CODE |
| LOW | tests/test_llm_usage.py | 1764 | except Exception as exc: | CODE |
| LOW | tests/test_conversation_manager.py | 22 | except Exception as exc: # pragma: no cover - failures are asserted below | CODE |
| LOW | tests/test_search_service_concurrency.py | 114 | except Exception as exc: # pragma: no cover - thread collection | CODE |
| LOW | tests/test_search_service_concurrency.py | 171 | except Exception as exc: # pragma: no cover - thread collection | CODE |
| LOW | tests/test_search_service_concurrency.py | 265 | except Exception as exc: # pragma: no cover - thread collection | CODE |
| MEDIUM | tests/test_search_service_concurrency.py | 110 | def worker(): | CODE |
| MEDIUM | tests/test_search_service_concurrency.py | 167 | def worker(): | CODE |
| MEDIUM | tests/test_search_service_concurrency.py | 261 | def worker(): | CODE |
| MEDIUM | tests/test_storage.py | 454 | def ensure_record() -> None: | CODE |
| MEDIUM | tests/test_storage.py | 835 | def initialize_manager() -> None: | CODE |
| MEDIUM | tests/test_storage.py | 844 | def use_manager() -> None: | CODE |
| MEDIUM | tests/test_storage.py | 927 | def construct_directly() -> None: | CODE |
| MEDIUM | tests/test_storage.py | 936 | def use_get_instance() -> None: | CODE |
| LOW | tests/test_storage.py | 458 | except Exception as exc: | CODE |
| LOW | tests/test_storage.py | 840 | except Exception as exc: | CODE |
| LOW | tests/test_storage.py | 856 | except Exception as exc: | CODE |
| LOW | tests/test_storage.py | 932 | except Exception as exc: | CODE |
| LOW | tests/test_storage.py | 948 | except Exception as exc: | CODE |
| LOW | tests/test_data_fetcher_prefetch_stock_names.py | 291 | except Exception as exc: # pragma: no cover - thread collection | CODE |
| MEDIUM | tests/test_data_fetcher_prefetch_stock_names.py | 286 | def worker(): | CODE |
| LOW | tests/test_agent_sse_cleanup.py | 50 | except Exception as exc: | CODE |
| LOW | tests/test_main_schedule_mode.py | 75 | except Exception: | CODE |
| LOW | tests/test_main_schedule_mode.py | 2092 | except Exception: | CODE |
| LOW | tests/tw_institutional_live_smoke.py | 42 | except Exception: # noqa: BLE001 - cosmetic only; never block the smoke on console encoding | CODE |
| LOW | tests/test_run_diagnostics_p1.py | 106 | except Exception as exc: # pragma: no cover - exercised by queue behavior | CODE |
| LOW | tests/test_analysis_api_contract.py | 37 | except Exception: # pragma: no cover - optional dependency environments | CODE |
| LOW | tests/test_analysis_api_contract.py | 1016 | except Exception as exc: # pragma: no cover - exercised via assert below | CODE |
| LOW | tests/test_analysis_api_contract.py | 3376 | except Exception: # pragma: no cover - optional dependency environments | CODE |
| LOW | tests/test_stooq_fallback.py | 12 | except Exception: | CODE |
| LOW | tests/test_realtime_types.py | 64 | except Exception as exc: # pragma: no cover - thread collection | CODE |
| LOW | tests/test_realtime_types.py | 91 | except Exception as exc: # pragma: no cover - thread collection | CODE |
| LOW | tests/test_realtime_types.py | 99 | except Exception as exc: # pragma: no cover - thread collection | CODE |
| MEDIUM | tests/test_realtime_types.py | 60 | def worker(): | CODE |
| MEDIUM | tests/test_realtime_types.py | 86 | def record_success(): | CODE |
| MEDIUM | tests/test_realtime_types.py | 94 | def record_failure(): | CODE |
| LOW⚡ | tests/test_api_schema_pydantic.py | 138 | except Exception as exc: | CODE |
| MEDIUM | tests/test_api_schema_pydantic.py | 132 | def test_analyze_request_rejects_invalid_analysis_phase() -> None: | CODE |
| LOW | data_provider/alphavantage_fetcher.py | 60 | except Exception as e: | CODE |
| 818 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | server.py | 40 | CODE | |
| LOW | webui.py | 18 | CODE | |
| LOW | main.py | 24 | CODE | |
| LOW | tests/test_portfolio_service.py | 4 | CODE | |
| LOW | tests/test_analysis_context_pack_prompt.py | 4 | CODE | |
| LOW | tests/test_generate_index_from_csv.py | 11 | CODE | |
| LOW | tests/test_generate_index_from_csv.py | 11 | CODE | |
| LOW | tests/test_generate_index_from_csv.py | 17 | CODE | |
| LOW | tests/test_analysis_context_builder.py | 4 | CODE | |
| LOW | tests/test_analysis_context_pack_overview.py | 4 | CODE | |
| LOW | tests/test_market_light_service.py | 4 | CODE | |
| LOW | tests/test_fetch_tushare_stock_list.py | 4 | CODE | |
| LOW | tests/test_multi_agent.py | 25 | CODE | |
| LOW | tests/conftest.py | 4 | CODE | |
| LOW | tests/test_decision_signal_repo.py | 4 | CODE | |
| LOW | tests/test_run_diagnostics_p2.py | 4 | CODE | |
| LOW | tests/test_runtime_scheduler_service.py | 4 | CODE | |
| LOW | tests/test_agent_pipeline.py | 20 | CODE | |
| LOW | tests/test_agent_pipeline.py | 21 | CODE | |
| LOW | tests/test_agent_pipeline.py | 21 | CODE | |
| LOW | tests/test_agent_pipeline.py | 22 | CODE | |
| LOW | tests/test_agent_pipeline.py | 22 | CODE | |
| LOW | tests/test_report_integrity.py | 16 | CODE | |
| LOW | tests/test_anspire_search.py | 27 | CODE | |
| LOW | tests/test_anspire_search.py | 27 | CODE | |
| LOW | tests/test_anspire_search.py | 28 | CODE | |
| LOW | tests/test_anspire_search.py | 29 | CODE | |
| LOW | tests/test_decision_signal_api.py | 4 | CODE | |
| LOW | tests/test_decision_signal_api.py | 19 | CODE | |
| LOW | tests/test_local_cli_backend.py | 4 | CODE | |
| LOW | tests/test_analysis_context_pack_schema.py | 4 | CODE | |
| LOW | tests/test_daily_analysis_workflow_llm_env.py | 4 | CODE | |
| LOW | tests/test_alert_api.py | 4 | CODE | |
| LOW | tests/test_alert_api.py | 29 | CODE | |
| LOW | tests/test_alert_api.py | 21 | CODE | |
| LOW | tests/test_stock_index_remote_service.py | 4 | CODE | |
| LOW | tests/test_analysis_integration.py | 18 | CODE | |
| LOW | tests/test_analysis_integration.py | 19 | CODE | |
| LOW | tests/test_history_loader.py | 3 | CODE | |
| LOW | tests/test_market_light_alerts.py | 4 | CODE | |
| LOW | tests/test_decision_signal_service.py | 4 | CODE | |
| LOW | tests/test_build_release_notes.py | 1 | CODE | |
| LOW | tests/test_agent_frozen_context.py | 3 | CODE | |
| LOW | tests/test_realtime_quote_fallback_logging.py | 11 | CODE | |
| LOW | tests/test_ask_command.py | 10 | CODE | |
| LOW | tests/test_decision_profile_policy.py | 1 | CODE | |
| LOW | tests/test_market_structure_service.py | 4 | CODE | |
| LOW | tests/test_desktop_packaging_assets.py | 4 | CODE | |
| LOW | tests/test_intelligence_service.py | 4 | CODE | |
| LOW | tests/test_signal_attribution_supplement.py | 15 | CODE | |
| LOW | tests/test_report_renderer.py | 15 | CODE | |
| LOW | tests/test_tencent_fetcher.py | 4 | CODE | |
| LOW | tests/test_daily_market_context_guardrail.py | 4 | CODE | |
| LOW | tests/test_agent_executor.py | 27 | CODE | |
| LOW | tests/test_signal_attribution_real_paths.py | 13 | CODE | |
| LOW | tests/test_signal_attribution_real_paths.py | 13 | CODE | |
| LOW | tests/test_yfinance_fundamental_adapter.py | 9 | CODE | |
| LOW | tests/test_fetcher_logging.py | 1 | CODE | |
| LOW | tests/test_alert_worker.py | 4 | CODE | |
| LOW | tests/test_auth_api.py | 19 | CODE | |
| 469 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | server.py | 43 | __all__ = ['app'] | CODE |
| LOW | webui.py | 23 | logger = logging.getLogger(__name__) | CODE |
| LOW | main.py | 79 | logger = logging.getLogger(__name__) | CODE |
| LOW | main.py | 170 | def _setup_bootstrap_logging(debug: bool = False) -> None: | CODE |
| LOW | tests/test_runtime_scheduler_service.py | 337 | def set_daily_task(self, task, run_immediately: bool) -> None: | CODE |
| LOW | tests/test_runtime_scheduler_service.py | 418 | def set_daily_task(self, task, run_immediately: bool) -> None: | CODE |
| LOW | tests/test_signal_attribution_supplement.py | 23 | logger = logging.getLogger(__name__) | CODE |
| LOW⚡ | tests/test_run_flow.py | 222 | def update_analysis_history_diagnostics(self, *, query_id: str, code: str, diagnostics: dict) -> None: | CODE |
| LOW⚡ | data_provider/realtime_types.py | 24 | logger = logging.getLogger(__name__) | CODE |
| LOW | data_provider/alphavantage_fetcher.py | 22 | logger = logging.getLogger(__name__) | CODE |
| LOW | data_provider/yfinance_fetcher.py | 54 | logger = logging.getLogger(__name__) | CODE |
| LOW | data_provider/fundamental_adapter.py | 18 | logger = logging.getLogger(__name__) | CODE |
| LOW | data_provider/tickflow_fetcher.py | 44 | logger = logging.getLogger(__name__) | CODE |
| LOW | data_provider/tickflow_fetcher.py | 552 | def _set_daily_cache(self, cache_key: Tuple[str, str, str, str], df: pd.DataFrame) -> None: | CODE |
| LOW | data_provider/yfinance_fundamental_adapter.py | 36 | logger = logging.getLogger(__name__) | CODE |
| LOW | data_provider/akshare_fetcher.py | 60 | logger = logging.getLogger(__name__) | CODE |
| LOW | data_provider/akshare_fetcher.py | 406 | def _set_random_user_agent(self) -> None: | CODE |
| LOW | data_provider/efinance_fetcher.py | 118 | logger = logging.getLogger(__name__) | CODE |
| LOW | data_provider/efinance_fetcher.py | 317 | def _set_random_user_agent(self) -> None: | CODE |
| LOW | data_provider/longbridge_fetcher.py | 40 | logger = logging.getLogger(__name__) | CODE |
| LOW | data_provider/finnhub_fetcher.py | 22 | logger = logging.getLogger(__name__) | CODE |
| LOW | data_provider/__init__.py | 46 | __all__ = [ | CODE |
| LOW | data_provider/tushare_fetcher.py | 40 | logger = logging.getLogger(__name__) | CODE |
| LOW | data_provider/tw_institutional_fetcher.py | 37 | logger = logging.getLogger(__name__) | CODE |
| LOW | data_provider/baostock_fetcher.py | 42 | logger = logging.getLogger(__name__) | CODE |
| LOW | data_provider/pytdx_fetcher.py | 43 | logger = logging.getLogger(__name__) | CODE |
| LOW | data_provider/tencent_fetcher.py | 20 | logger = logging.getLogger(__name__) | CODE |
| LOW | data_provider/base.py | 36 | logger = logging.getLogger(__name__) | CODE |
| LOW | scripts/check_env.py | 73 | logger = logging.getLogger(__name__) | CODE |
| LOW | api/app.py | 36 | logger = logging.getLogger(__name__) | CODE |
| LOW | api/v1/__init__.py | 13 | __all__ = ["api_v1_router"] | CODE |
| LOW | api/v1/endpoints/alerts.py | 29 | logger = logging.getLogger(__name__) | CODE |
| LOW | api/v1/endpoints/auth.py | 37 | logger = logging.getLogger(__name__) | CODE |
| LOW | api/v1/endpoints/auth.py | 143 | def _set_session_cookie(response: Response, session_value: str, request: Request) -> None: | CODE |
| LOW | api/v1/endpoints/stocks.py | 46 | logger = logging.getLogger(__name__) | CODE |
| LOW | api/v1/endpoints/analysis.py | 97 | logger = logging.getLogger(__name__) | CODE |
| LOW | api/v1/endpoints/__init__.py | 26 | __all__ = [ | CODE |
| LOW | api/v1/endpoints/intelligence.py | 27 | logger = logging.getLogger(__name__) | CODE |
| LOW | api/v1/endpoints/decision_signals.py | 45 | logger = logging.getLogger(__name__) | CODE |
| LOW | api/v1/endpoints/agent.py | 39 | logger = logging.getLogger(__name__) | CODE |
| LOW | api/v1/endpoints/system_config.py | 44 | logger = logging.getLogger(__name__) | CODE |
| LOW | api/v1/endpoints/backtest.py | 24 | logger = logging.getLogger(__name__) | CODE |
| LOW | api/v1/endpoints/portfolio.py | 48 | logger = logging.getLogger(__name__) | CODE |
| LOW | api/v1/endpoints/usage.py | 16 | logger = logging.getLogger(__name__) | CODE |
| LOW | api/v1/endpoints/history.py | 60 | logger = logging.getLogger(__name__) | CODE |
| LOW | api/v1/schemas/__init__.py | 129 | __all__ = [ | CODE |
| LOW | api/middlewares/auth.py | 17 | logger = logging.getLogger(__name__) | CODE |
| LOW | api/middlewares/__init__.py | 13 | __all__ = ["ErrorHandlerMiddleware"] | CODE |
| LOW | api/middlewares/error_handler.py | 21 | logger = logging.getLogger(__name__) | CODE |
| LOW | bot/dispatcher.py | 21 | logger = logging.getLogger(__name__) | CODE |
| LOW | bot/dispatcher.py | 363 | def set_help_command_getter(self, getter: Callable) -> None: | CODE |
| LOW | bot/handler.py | 23 | logger = logging.getLogger(__name__) | CODE |
| LOW | bot/__init__.py | 37 | __all__ = [ | CODE |
| LOW | bot/platforms/dingtalk.py | 25 | logger = logging.getLogger(__name__) | CODE |
| LOW | bot/platforms/discord.py | 26 | logger = logging.getLogger(__name__) | CODE |
| LOW | bot/platforms/__init__.py | 56 | __all__ = [ | CODE |
| LOW | bot/platforms/feishu_stream.py | 33 | logger = logging.getLogger(__name__) | CODE |
| LOW | bot/platforms/dingtalk_stream.py | 28 | logger = logging.getLogger(__name__) | CODE |
| LOW | bot/commands/strategies.py | 14 | logger = logging.getLogger(__name__) | CODE |
| LOW | bot/commands/research.py | 20 | logger = logging.getLogger(__name__) | CODE |
| 128 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | main.py | 663 | CODE | |
| LOW | main.py | 1132 | CODE | |
| LOW | main.py | 1238 | CODE | |
| LOW | tests/test_portfolio_service.py | 1381 | CODE | |
| LOW | tests/test_multi_agent.py | 1212 | CODE | |
| LOW | tests/test_multi_agent.py | 1581 | CODE | |
| LOW | tests/test_multi_agent.py | 1603 | CODE | |
| LOW | tests/test_multi_agent.py | 1618 | CODE | |
| LOW | tests/test_multi_agent.py | 1649 | CODE | |
| LOW | tests/test_anspire_search.py | 446 | CODE | |
| LOW | tests/test_ask_command.py | 281 | CODE | |
| LOW | tests/test_market_review.py | 17 | CODE | |
| LOW | tests/test_agent_executor.py | 227 | CODE | |
| LOW | tests/test_agent_executor.py | 270 | CODE | |
| LOW | tests/test_agent_executor.py | 312 | CODE | |
| LOW | tests/test_agent_executor.py | 989 | CODE | |
| LOW | tests/test_fetcher_logging.py | 127 | CODE | |
| LOW | tests/test_storage.py | 39 | CODE | |
| LOW | tests/test_storage.py | 417 | CODE | |
| LOW | tests/test_storage.py | 992 | CODE | |
| LOW | tests/test_auth_status_setup_state.py | 103 | CODE | |
| LOW | tests/test_analysis_api_contract.py | 315 | CODE | |
| LOW | tests/test_analysis_api_contract.py | 3045 | CODE | |
| LOW | data_provider/realtime_types.py | 233 | CODE | |
| LOW | data_provider/realtime_types.py | 404 | CODE | |
| LOW | data_provider/yfinance_fetcher.py | 225 | CODE | |
| LOW | data_provider/yfinance_fetcher.py | 340 | CODE | |
| LOW | data_provider/yfinance_fetcher.py | 390 | CODE | |
| LOW | data_provider/yfinance_fetcher.py | 417 | CODE | |
| LOW | data_provider/yfinance_fetcher.py | 449 | CODE | |
| LOW | data_provider/yfinance_fetcher.py | 472 | CODE | |
| LOW | data_provider/yfinance_fetcher.py | 495 | CODE | |
| LOW | data_provider/yfinance_fetcher.py | 783 | CODE | |
| LOW | data_provider/fundamental_adapter.py | 240 | CODE | |
| LOW | data_provider/tickflow_fetcher.py | 396 | CODE | |
| LOW | data_provider/yfinance_fundamental_adapter.py | 146 | CODE | |
| LOW | data_provider/akshare_fetcher.py | 605 | CODE | |
| LOW | data_provider/akshare_fetcher.py | 908 | CODE | |
| LOW | data_provider/akshare_fetcher.py | 952 | CODE | |
| LOW | data_provider/akshare_fetcher.py | 1357 | CODE | |
| LOW | data_provider/akshare_fetcher.py | 1686 | CODE | |
| LOW | data_provider/akshare_fetcher.py | 1824 | CODE | |
| LOW | data_provider/efinance_fetcher.py | 836 | CODE | |
| LOW | data_provider/efinance_fetcher.py | 974 | CODE | |
| LOW | data_provider/efinance_fetcher.py | 1102 | CODE | |
| LOW | data_provider/longbridge_fetcher.py | 145 | CODE | |
| LOW | data_provider/longbridge_fetcher.py | 489 | CODE | |
| LOW | data_provider/longbridge_fetcher.py | 626 | CODE | |
| LOW | data_provider/tushare_fetcher.py | 778 | CODE | |
| LOW | data_provider/tushare_fetcher.py | 849 | CODE | |
| LOW | data_provider/tushare_fetcher.py | 930 | CODE | |
| LOW | data_provider/baostock_fetcher.py | 290 | CODE | |
| LOW | data_provider/baostock_fetcher.py | 337 | CODE | |
| LOW | data_provider/pytdx_fetcher.py | 48 | CODE | |
| LOW | data_provider/pytdx_fetcher.py | 185 | CODE | |
| LOW | data_provider/pytdx_fetcher.py | 283 | CODE | |
| LOW | data_provider/base.py | 847 | CODE | |
| LOW | data_provider/base.py | 1029 | CODE | |
| LOW | data_provider/base.py | 1242 | CODE | |
| LOW | data_provider/base.py | 1721 | CODE | |
| 186 more matches not shown… | ||||
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | data_provider/yfinance_fetcher.py | 97 | 转换股票代码为 Yahoo Finance 格式 Yahoo Finance 代码格式: - A股沪市:600519.SS (Shanghai Stock Exchange) | STRING |
| HIGH | data_provider/us_index_mapping.py | 47 | 判断代码是否为美股指数符号。 Args: code: 股票/指数代码,如 'SPX', 'DJI' Returns: True 表示是已知美股指数符号,否则 False | STRING |
| HIGH | data_provider/us_index_mapping.py | 66 | 判断代码是否为美股股票符号(排除美股指数)。 美股股票代码为 1-5 个大写字母,可选 .X 后缀如 BRK.B。 美股指数(SPX、DJI 等)明确排除。 Args: code: 股票 | STRING |
| HIGH | data_provider/us_index_mapping.py | 98 | 获取美股指数的 Yahoo Finance 符号与中文名称。 Args: code: 用户输入,如 'SPX', '^GSPC', 'DJI' Returns: (yf_symb | STRING |
| HIGH | data_provider/akshare_fetcher.py | 210 | 判断代码是否为美股股票(不包括美股指数)。 委托给 us_index_mapping 模块的 is_us_stock_code()。 Args: stock_code: 股票代码 Re | STRING |
| HIGH | data_provider/base.py | 1249 | 获取日线数据(自动切换数据源) 故障切换策略: 1. 美股指数/美股股票直接路由到 YfinanceFetcher 2. 其他代码从最高优先级数据源开始尝试 | STRING |
| HIGH | api/v1/endpoints/stocks.py | 420 | 获取股票实时行情 获取指定股票的最新行情数据 Args: stock_code: 股票代码(如 600519、00700、AAPL) Returns: | STRING |
| HIGH | api/v1/endpoints/analysis.py | 280 | 触发股票分析 启动 AI 智能分析任务,支持单只或多只股票批量分析 流程: 1. 校验请求参数 2. 异步模式:检查重复 -> 提交任务队列 -> 返回 202 3. 同 | STRING |
| HIGH | api/v1/endpoints/analysis.py | 1031 | 查询分析任务状态 优先从任务队列查询,如果不存在则从数据库查询历史记录 Args: task_id: 任务 ID Returns: Ta | STRING |
| HIGH | api/v1/endpoints/history.py | 450 | 获取历史报告详情 根据分析历史记录主键 ID 或 query_id 获取完整的历史分析报告。 优先尝试按主键 ID(整数)查询,若参数不是合法整数则按 query_id 查询。 Args | STRING |
| HIGH | api/v1/endpoints/history.py | 763 | 获取历史报告的 Markdown 格式内容 根据分析历史记录 ID 或 query_id 生成与推送通知格式一致的 Markdown 报告。 Args: record_id: 分析历史记录主键 | STRING |
| HIGH | src/agent/skills/base.py | 141 | Load a single Skill from a YAML file. The YAML file must contain at minimum: ``name``, ``display_name``, ``desc | STRING |
| HIGH | src/services/stock_service.py | 94 | 获取股票历史行情 Args: stock_code: 股票代码 period: K 线周期 (daily/weekly/monthly) | STRING |
| HIGH | src/services/task_queue.py | 336 | Submit a single analysis task. Args: stock_code: Stock code stock_name: Option | STRING |
| HIGH | src/services/image_stock_extractor.py | 290 | 从图片中提取股票代码及名称(使用 Vision LLM)。 优先级:Gemini -> Anthropic -> OpenAI(首个可用)。 支持多 Key 轮询与重试(最多 3 次,指数退避)。 Ar | STRING |
| HIGH | src/services/history_service.py | 612 | Delete specified analysis history records. Args: record_ids: List of history record primar | STRING |
| HIGH | src/services/history_service.py | 763 | Generate a Markdown report for a single analysis history record. This method reconstructs an AnalysisR | STRING |
| HIGH | src/services/import_parser.py | 129 | Parse file bytes (CSV/Excel) into items. Args: data: File content bytes. filename: Optional fi | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/test_notification_sender.py | 1551 | # Step 2: upload must send raw bytes (not multipart) to match declared length | COMMENT |
| LOW⚡ | tests/longbridge_live_smoke.py | 100 | # Step 1: yfinance only | COMMENT |
| LOW | tests/longbridge_live_smoke.py | 126 | # Step 2: Supplement from Longbridge | COMMENT |
| LOW⚡ | tests/test_agent_executor.py | 1115 | # Step 1: LLM requests tool call | COMMENT |
| LOW⚡ | tests/test_agent_executor.py | 1124 | # Step 2: LLM returns final text | COMMENT |
| LOW | .claude/skills/analyze-pr/SKILL.md | 17 | ### Step 1: 同步最新代码基线 | COMMENT |
| LOW | .claude/skills/analyze-pr/SKILL.md | 32 | ### Step 2: 拉取 PR 基本信息 | COMMENT |
| LOW | .claude/skills/analyze-pr/SKILL.md | 47 | ### Step 3: 检查标题与描述完整性 | COMMENT |
| LOW | .claude/skills/analyze-pr/SKILL.md | 77 | ### Step 4: 优先使用 CI / Diff 证据 | COMMENT |
| LOW | .claude/skills/analyze-pr/SKILL.md | 89 | ### Step 5: 评估正确性与风险 | COMMENT |
| LOW | .claude/skills/analyze-pr/SKILL.md | 98 | ### Step 6: 生成评审文档 | COMMENT |
| LOW | .claude/skills/analyze-issue/SKILL.md | 17 | ### Step 1: 同步最新代码基线 | COMMENT |
| LOW | .claude/skills/analyze-issue/SKILL.md | 32 | ### Step 2: 拉取 Issue 信息 | COMMENT |
| LOW⚡ | .claude/skills/analyze-issue/SKILL.md | 46 | ### Step 3: 回答 4 个核心问题 | COMMENT |
| LOW⚡ | .claude/skills/analyze-issue/SKILL.md | 53 | ### Step 4: 结合仓库现状做证据检查 | COMMENT |
| LOW⚡ | .claude/skills/analyze-issue/SKILL.md | 60 | ### Step 5: 形成结论 | COMMENT |
| LOW | .claude/skills/analyze-issue/SKILL.md | 74 | ### Step 6: 生成分析文档 | COMMENT |
| LOW | .claude/skills/fix-issue/SKILL.md | 19 | ### Step 1: 确认分析基线 | COMMENT |
| LOW | .claude/skills/fix-issue/SKILL.md | 23 | ### Step 2: 同步最新代码基线并选择安全的工作方式 | COMMENT |
| LOW | .claude/skills/fix-issue/SKILL.md | 41 | ### Step 3: 实施修复 | COMMENT |
| LOW | .claude/skills/fix-issue/SKILL.md | 51 | ### Step 4: 按改动面验证 | COMMENT |
| LOW | .claude/skills/fix-issue/SKILL.md | 62 | ### Step 5: 更新 issue 分析文档 | COMMENT |
| LOW | .claude/skills/fix-issue/SKILL.md | 89 | ### Step 6: 需要确认的后续动作 | COMMENT |
| LOW⚡ | data_provider/base.py | 502 | # Step 2: 标准化列名 | COMMENT |
| LOW⚡ | data_provider/base.py | 505 | # Step 3: 数据清洗 | COMMENT |
| LOW⚡ | data_provider/base.py | 508 | # Step 4: 计算技术指标 | COMMENT |
| LOW | data_provider/base.py | 487 | # Step 1: 获取原始数据 | COMMENT |
| LOW⚡ | src/core/pipeline.py | 456 | # Step 2: 获取筹码分布 - 使用统一入口,带熔断保护 | COMMENT |
| LOW⚡ | src/core/pipeline.py | 529 | # Step 3: 趋势分析(基于交易理念)— 在 Agent 分支之前执行,供两条路径共用 | COMMENT |
| LOW⚡ | src/core/pipeline.py | 635 | # Step 5: 获取分析上下文(技术面数据) | COMMENT |
| LOW | src/core/pipeline.py | 430 | # Step 1: 获取实时行情(量比、换手率等)- 使用统一入口,自动故障切换 | COMMENT |
| LOW | src/core/pipeline.py | 568 | # Step 4: 多维度情报搜索(最新消息+风险排查+业绩预期) | COMMENT |
| LOW | src/core/pipeline.py | 653 | # Step 6: 增强上下文数据(添加实时行情、筹码、趋势分析结果、股票名称) | COMMENT |
| LOW | src/core/pipeline.py | 675 | # Step 7: 调用 AI 分析(传入增强的上下文和新闻) | COMMENT |
| LOW | src/core/pipeline.py | 804 | # Step 8: 保存分析历史记录 | COMMENT |
| LOW | src/core/pipeline.py | 2888 | # Step 1: 获取并保存数据 | COMMENT |
| LOW | src/core/pipeline.py | 2899 | # Step 2: AI 分析 | COMMENT |
| LOW⚡ | src/notification_sender/telegram_sender.py | 379 | # Step 1: temporarily protect markdown links | COMMENT |
| LOW⚡ | src/notification_sender/telegram_sender.py | 388 | # Step 2: escape remaining special chars | COMMENT |
| LOW⚡ | src/notification_sender/telegram_sender.py | 392 | # Step 3: restore links | COMMENT |
| LOW | src/notification_sender/slack_sender.py | 186 | # Step 1: 获取上传 URL | COMMENT |
| LOW | src/notification_sender/slack_sender.py | 204 | # Step 2: 上传文件内容(raw body,不能用 multipart) | COMMENT |
| LOW | src/notification_sender/slack_sender.py | 215 | # Step 3: 完成上传并分享到频道 | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH⚡ | tests/test_searxng_env_docs.py | 26 | "SEARXNG_BASE_URLS: ${{ vars.SEARXNG_BASE_URLS || secrets.SEARXNG_BASE_URLS }}" | CODE |
| HIGH | tests/test_storage.py | 280 | ("600519", "cn", "analysis", 12, "trace-12", "buy", "3d", "intraday", "2026-01-01", '{"decision_ | CODE |
| HIGH⚡ | tests/test_chip_structure_fallback.py | 218 | """When LLM returns data_perspective: null, fill should still work.""" | STRING |
| HIGH | tests/test_bot_dispatcher_async.py | 96 | content='{"intent":"analysis","codes":["600519"],"strategy":null}', | CODE |
| HIGH | data_provider/longbridge_fetcher.py | 85 | GitHub Actions sets ``LONGBRIDGE_HTTP_URL: ${{ vars.X || secrets.X }}`` | STRING |
| HIGH | scripts/check_static_assets.py | 84 | "`cd apps/dsa-web && npm install && npm run build`.", | CODE |
| HIGH⚡ | bot/dispatcher.py | 396 | {"intent":"analysis","codes":["600519","000858"],"strategy":null} | CODE |
| HIGH⚡ | bot/dispatcher.py | 402 | {"intent":"chat","codes":[],"strategy":null} | CODE |
| HIGH⚡ | bot/dispatcher.py | 405 | {"intent":"none","codes":[],"strategy":null} | CODE |
| HIGH⚡ | bot/dispatcher.py | 408 | {"intent":"analysis","codes":["600519"],"strategy":null} | CODE |
| HIGH⚡ | bot/dispatcher.py | 411 | {"intent":"analysis","codes":[],"strategy":null} | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| CRITICAL | tests/test_notification_sender.py | 765 | dummy_client.im.v1.file.create.assert_called_once() | CODE |
| CRITICAL | bot/platforms/feishu_stream.py | 135 | response = self._client.im.v1.message.reply(request) | CODE |
| CRITICAL | bot/platforms/feishu_stream.py | 148 | response = self._client.im.v1.message.create(request) | CODE |
| CRITICAL | src/feishu_doc.py | 55 | response = self.client.docx.v1.document.create(create_request) | CODE |
| CRITICAL | src/feishu_doc.py | 87 | write_resp = self.client.docx.v1.document_block_children.create(batch_add_request) | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | tests/test_notification_sender.py | 1551 | # Step 2: upload must send raw bytes (not multipart) to match declared length | COMMENT |
| LOW⚡ | tests/longbridge_live_smoke.py | 100 | # Step 1: yfinance only | COMMENT |
| LOW | tests/longbridge_live_smoke.py | 126 | # Step 2: Supplement from Longbridge | COMMENT |
| LOW⚡ | tests/test_agent_executor.py | 1115 | # Step 1: LLM requests tool call | COMMENT |
| LOW⚡ | tests/test_agent_executor.py | 1124 | # Step 2: LLM returns final text | COMMENT |
| LOW⚡ | data_provider/base.py | 502 | # Step 2: 标准化列名 | COMMENT |
| LOW⚡ | data_provider/base.py | 505 | # Step 3: 数据清洗 | COMMENT |
| LOW⚡ | data_provider/base.py | 508 | # Step 4: 计算技术指标 | COMMENT |
| LOW | data_provider/base.py | 487 | # Step 1: 获取原始数据 | COMMENT |
| LOW⚡ | src/core/pipeline.py | 456 | # Step 2: 获取筹码分布 - 使用统一入口,带熔断保护 | COMMENT |
| LOW⚡ | src/core/pipeline.py | 529 | # Step 3: 趋势分析(基于交易理念)— 在 Agent 分支之前执行,供两条路径共用 | COMMENT |
| LOW⚡ | src/core/pipeline.py | 635 | # Step 5: 获取分析上下文(技术面数据) | COMMENT |
| LOW | src/core/pipeline.py | 430 | # Step 1: 获取实时行情(量比、换手率等)- 使用统一入口,自动故障切换 | COMMENT |
| LOW | src/core/pipeline.py | 568 | # Step 4: 多维度情报搜索(最新消息+风险排查+业绩预期) | COMMENT |
| LOW | src/core/pipeline.py | 653 | # Step 6: 增强上下文数据(添加实时行情、筹码、趋势分析结果、股票名称) | COMMENT |
| LOW | src/core/pipeline.py | 675 | # Step 7: 调用 AI 分析(传入增强的上下文和新闻) | COMMENT |
| LOW | src/core/pipeline.py | 804 | # Step 8: 保存分析历史记录 | COMMENT |
| LOW | src/core/pipeline.py | 2888 | # Step 1: 获取并保存数据 | COMMENT |
| LOW | src/core/pipeline.py | 2899 | # Step 2: AI 分析 | COMMENT |
| LOW⚡ | src/notification_sender/telegram_sender.py | 379 | # Step 1: temporarily protect markdown links | COMMENT |
| LOW⚡ | src/notification_sender/telegram_sender.py | 388 | # Step 2: escape remaining special chars | COMMENT |
| LOW⚡ | src/notification_sender/telegram_sender.py | 392 | # Step 3: restore links | COMMENT |
| LOW | src/notification_sender/slack_sender.py | 186 | # Step 1: 获取上传 URL | COMMENT |
| LOW | src/notification_sender/slack_sender.py | 204 | # Step 2: 上传文件内容(raw body,不能用 multipart) | COMMENT |
| LOW | src/notification_sender/slack_sender.py | 215 | # Step 3: 完成上传并分享到频道 | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_config_env_compat.py | 990 | "EMAIL_GROUP_1": "user@example.com", | CODE |
| LOW | tests/test_config_env_compat.py | 998 | self.assertEqual(emails, ["user@example.com"]) | CODE |
| LOW | tests/test_search_news_freshness.py | 64 | bocha_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_news_freshness.py | 144 | bocha_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_news_freshness.py | 173 | bocha_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_news_freshness.py | 215 | bocha_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_news_freshness.py | 249 | bocha_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_news_freshness.py | 280 | bocha_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_news_freshness.py | 314 | bocha_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_news_freshness.py | 352 | bocha_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_news_freshness.py | 402 | bocha_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_news_freshness.py | 429 | bocha_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_news_freshness.py | 481 | bocha_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_news_freshness.py | 1459 | bocha_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_news_freshness.py | 1508 | bocha_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_news_freshness.py | 1561 | bocha_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_news_freshness.py | 1685 | bocha_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_news_freshness.py | 1733 | bocha_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_news_freshness.py | 1781 | bocha_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_news_freshness.py | 1869 | brave_keys=["dummy_key"], | CODE |
| LOW⚡ | tests/test_search_serpapi_provider.py | 307 | provider = SerpAPISearchProvider(["dummy_key"]) | CODE |
| LOW | tests/test_search_serpapi_provider.py | 52 | provider = SerpAPISearchProvider(["dummy_key"]) | CODE |
| LOW | tests/test_search_serpapi_provider.py | 78 | provider = SerpAPISearchProvider(["dummy_key"]) | CODE |
| LOW | tests/test_search_serpapi_provider.py | 113 | provider = SerpAPISearchProvider(["dummy_key"]) | CODE |
| LOW | tests/test_search_serpapi_provider.py | 151 | provider = SerpAPISearchProvider(["dummy_key"]) | CODE |
| LOW | tests/test_search_serpapi_provider.py | 187 | provider = SerpAPISearchProvider(["dummy_key"]) | CODE |
| LOW | tests/test_search_serpapi_provider.py | 221 | provider = SerpAPISearchProvider(["dummy_key"]) | CODE |
| LOW | tests/test_search_serpapi_provider.py | 248 | provider = SerpAPISearchProvider(["dummy_key"]) | CODE |
| LOW | tests/test_search_serpapi_provider.py | 349 | provider = SerpAPISearchProvider(["dummy_key"]) | CODE |
| LOW | tests/test_search_serpapi_provider.py | 391 | provider = SerpAPISearchProvider(["dummy_key"]) | CODE |
| LOW | tests/test_search_serpapi_provider.py | 433 | provider = SerpAPISearchProvider(["dummy_key"]) | CODE |
| LOW | tests/test_search_serpapi_provider.py | 468 | provider = SerpAPISearchProvider(["dummy_key"]) | CODE |
| LOW | tests/test_search_serpapi_provider.py | 503 | provider = SerpAPISearchProvider(["dummy_key"]) | CODE |
| LOW | tests/test_search_tavily_provider.py | 57 | provider = TavilySearchProvider(["dummy_key"]) | CODE |
| LOW | tests/test_search_tavily_provider.py | 74 | self.assertEqual(_FakeTavilyClient.init_api_keys, ["dummy_key"]) | CODE |
| LOW | tests/test_search_tavily_provider.py | 85 | provider = TavilySearchProvider(["dummy_key"]) | CODE |
| LOW | tests/test_search_tavily_provider.py | 106 | provider = TavilySearchProvider(["dummy_key"]) | CODE |
| LOW | tests/test_search_tavily_provider.py | 145 | tavily_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_tavily_provider.py | 170 | tavily_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_tavily_provider.py | 196 | tavily_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_tavily_provider.py | 226 | tavily_keys=["dummy_key"], | CODE |
| LOW | tests/test_search_tavily_provider.py | 258 | tavily_keys=["dummy_key"], | CODE |
| LOW | bot/commands/ask.py | 217 | skill_id = self._parse_skill(["placeholder"] + remaining_args) if remaining_args else self._get_default_skill_id | CODE |
| LOW | src/core/config_registry.py | 164 | "placeholder": "optional provider/model override", | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | data_provider/efinance_fetcher.py | 0 | 判断代码是否为美股 美股代码规则: - 1-5个大写字母,如 'aapl', 'tsla' - 可能包含 '.',如 'brk.b' | STRING |
| HIGH | data_provider/tushare_fetcher.py | 0 | 判断代码是否为美股 美股代码规则: - 1-5个大写字母,如 'aapl', 'tsla' - 可能包含 '.',如 'brk.b' | STRING |
| HIGH | data_provider/baostock_fetcher.py | 0 | 判断代码是否为美股 美股代码规则: - 1-5个大写字母,如 'aapl', 'tsla' - 可能包含 '.',如 'brk.b' | STRING |
| HIGH | data_provider/pytdx_fetcher.py | 0 | 判断代码是否为美股 美股代码规则: - 1-5个大写字母,如 'aapl', 'tsla' - 可能包含 '.',如 'brk.b' | STRING |
| HIGH | src/agent/memory.py | 0 | compatibility wrapper for legacy strategy-based callers. | STRING |
| HIGH | src/agent/skills/router.py | 0 | compatibility wrapper for legacy strategy-based callers. | STRING |
| HIGH | src/services/backtest_service.py | 0 | compatibility wrapper for legacy strategy-based callers. | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_decision_signal_api.py | 1318 | CODE | |
| LOW | tests/test_stock_analyzer_bias.py | 22 | CODE | |
| LOW | tests/test_report_renderer.py | 23 | CODE | |
| LOW | tests/test_tickflow_fetcher.py | 147 | CODE | |
| LOW | api/v1/endpoints/decision_signals.py | 142 | CODE | |
| LOW | api/v1/endpoints/backtest.py | 99 | CODE | |
| LOW | api/v1/endpoints/portfolio.py | 492 | CODE | |
| LOW | src/search_service.py | 2258 | CODE | |
| LOW | src/llm/provider_cache.py | 167 | CODE | |
| LOW | src/core/market_review.py | 174 | CODE | |
| LOW | src/core/pipeline.py | 177 | CODE | |
| LOW | src/repositories/decision_signal_repo.py | 159 | CODE | |
| LOW | src/repositories/decision_signal_outcome_repo.py | 25 | CODE | |
| LOW | src/repositories/intelligence_repo.py | 152 | CODE | |
| LOW | src/services/run_diagnostics.py | 868 | CODE | |
| LOW | src/services/run_diagnostics.py | 931 | CODE | |
| LOW | src/services/task_queue.py | 322 | CODE | |
| LOW | src/services/task_queue.py | 375 | CODE | |
| LOW | src/services/decision_signal_service.py | 109 | CODE | |
| LOW | src/services/daily_market_context.py | 103 | CODE | |
| LOW | src/services/alert_indicators.py | 210 | CODE | |
| LOW | src/services/run_flow.py | 1245 | CODE | |
| LOW | src/services/alert_service.py | 309 | CODE | |
| LOW | src/services/analyzer_service.py | 68 | CODE | |
| LOW | src/services/decision_signal_outcome_service.py | 73 | CODE | |
| LOW | src/services/analysis_service.py | 50 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| HIGH | tests/test_anspire_search.py | 560 | print(" Windows PowerShell: $env:ANSPIRE_API_KEYS=\"your_api_key\"") | CODE |
| HIGH | tests/test_anspire_search.py | 561 | print(" Linux/Mac: export ANSPIRE_API_KEYS=\"your_api_key\"") | CODE |
| HIGH | tests/test_anspire_search.py | 631 | print(" Windows PowerShell: $env:ANSPIRE_API_KEYS=\"your_api_key\"") | CODE |
| HIGH | tests/test_anspire_search.py | 632 | print(" Linux/Mac: export ANSPIRE_API_KEYS=\"your_api_key\"") | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/test_phase_decision_guardrail.py | 2 | """Tests for Issue #1386 P5 phase decision guardrails.""" | STRING |
| MEDIUM | src/config.py | 850 | agent_orchestrator_timeout_s: int = 600 # Cooperative timeout budget for the whole multi-agent pipeline | CODE |
| MEDIUM | src/config.py | 867 | agent_event_monitor_enabled: bool = False # Enable periodic event-driven alert checks in schedule mode | CODE |
| MEDIUM | src/market_analyzer.py | 164 | # Structural/template language. Korean reuses the English scaffolding; | COMMENT |
| MEDIUM | src/agent/agents/base_agent.py | 227 | # Cap per-field size to avoid overwhelming the context window | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM⚡ | tests/test_agent_pipeline.py | 2844 | # Create a fresh Skill with default enabled=False | COMMENT |
| MEDIUM | tests/test_agent_registry.py | 852 | # Create a custom directory with an overriding strategy | COMMENT |
| MEDIUM | tests/test_agent_registry.py | 725 | # Create an invalid YAML file (should be skipped) | STRING |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW | tests/test_stock_analyzer_bias.py | 161 | mock_get_config.return_value.bias_threshold = 5.0 | COMMENT |
| LOW | docs/examples/litellm_config.example.yaml | 1 | # =================================== | COMMENT |
| LOW | docs/examples/litellm_config.example.yaml | 61 | - model_name: gemini/gemini-2.5-flash | COMMENT |
| LOW | docs/examples/litellm_config.example.yaml | 81 | # litellm_params: | COMMENT |
| LOW | scripts/test.sh | 1 | #!/bin/bash | COMMENT |
| LOW | src/config.py | 1041 | enable_realtime_technical_indicators: bool = True | COMMENT |
| LOW | src/market_analyzer.py | 581 | # # 取最新一条数据 | COMMENT |
| LOW | src/agent/llm_adapter.py | 101 | _OPT_IN_THINKING_MODELS: Dict[str, dict] = { | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM | tests/test_market_analyzer_generate_text.py | 936 | CODE | |
| MEDIUM | tests/test_llm_param_recovery.py | 169 | CODE |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| LOW⚡ | src/config.py | 443 | # Check if the prefix is a known LiteLLM provider; if so, keep it. | COMMENT |
| Severity | File | Line | Snippet | Context |
|---|---|---|---|---|
| MEDIUM⚡ | tests/test_agent_pipeline.py | 2761 | """Test the _safe_int helper for robust sentiment_score parsing.""" | STRING |