173 Commits

Author SHA1 Message Date
mumu
9bca31304c fix: harden agent runtime and config handling (#776)
* fix: harden agent runtime and config handling

* fix: restore cors test import and update review status

* fix: close remaining agent timeout gaps

* fix: align agent timeout defaults and fallback budget
2026-03-19 22:25:03 +08:00
Alfred
3eabeda06c feat: 支持 SearXNG 公共实例自动发现与受控轮询 (#752) (#769)
* feat: support SearXNG public instance discovery (#752)

* fix: back off cold-start failures for public searxng (#752)
2026-03-19 12:40:21 +08:00
Alfred
38d7ab5b5a docs: add Ollama local model configuration guide (Fixes #690) (#744)
* docs: add Ollama local model configuration guide (Fixes #690)

- Add Example 4 and channel mode example in LLM_CONFIG_GUIDE
- Add OLLAMA_API_BASE to .env.example and full-guide
- Add Ollama entry to litellm_config.example.yaml
- Add Q12b to FAQ (CN/EN)
- Add troubleshooting row for Ollama 404 / api/generate/api/show
- Update CHANGELOG

Made-with: Cursor

* docs: sync README with Ollama config per AGENTS.md (address review)

- Add Ollama to AI models list in README.md
- Add OLLAMA_API_BASE to Secrets table with link to config guide
- Add pitfall note: do not use OPENAI_BASE_URL for Ollama
- Sync docs/README_EN.md with same changes
- Update CHANGELOG to mention README sync

Made-with: Cursor

* docs: add OLLAMA_API_BASE to full-guide env table and note (address review)

* docs: remove duplicate OLLAMA_API_BASE entries in full-guide (address review)
2026-03-18 22:37:52 +08:00
Alfred
905b366ef1 feat: integrate TickFlow market review enhancement (#632) (#745)
Co-authored-by: mumu <42829555+ZhuLinsen@users.noreply.github.com>
2026-03-18 19:19:08 +08:00
Alfred
216a77f6a2 fix: decouple agent and analysis primary models (#692) (#741)
* fix #692: decouple agent and analysis primary model selection

* fix #692: preserve yaml alias for agent primary model

* docs #692: sync agent primary model in EN/CHT readmes
2026-03-18 19:08:36 +08:00
mumu
a5a0d8e264 fix: restore schedule immediate-run compatibility (#735)
* fix: restore schedule immediate-run compatibility

* test: move config compatibility coverage

* fix: preserve blank immediate-run semantics
2026-03-17 23:03:06 +08:00
Alfred
eaa25f8a26 [#697] fix: 新闻时效硬过滤与策略分窗 (#707)
* fix: enforce strict news freshness windows (#697)

* fix: normalize timezone-aware publish date parsing (#697)

* fix: align analyzer news window with runtime pipeline config (#697)
2026-03-16 22:40:45 +08:00
Alexander Schneider
2b5a640ffe feat: add social sentiment intelligence for US stocks (Reddit/X/Polymarket) (#705)
Integrate real-time social media sentiment data from api.adanos.org as an
additional intelligence source for US stock analysis. When configured, the
system fetches Reddit community sentiment, X/Twitter buzz, and Polymarket
prediction market data — and injects it alongside news context into the
LLM analysis prompt.

- New SocialSentimentService with retry, TTL caching, and graceful fallback
- Only activates for US stock tickers (A-shares/HK stocks are unaffected)
- Fully optional: requires SOCIAL_SENTIMENT_API_KEY env var
- Works in both standard and Agent analysis pipelines (via news_context)
- 22 unit tests covering all code paths including zero-value edge cases
- Updated README.md and docs/CHANGELOG.md

Co-authored-by: mumu <42829555+ZhuLinsen@users.noreply.github.com>
2026-03-16 22:05:24 +08:00
Alfred
e861ea4d31 [docs] 云服务器 Web 界面访问指南 Issue #686 (#702)
* docs: add cloud server WebUI deployment guide (Fixes #686)

* docs: fix --webui schedule claim per Codex review (P1)
2026-03-16 22:03:11 +08:00
Alfred
631bc820c5 [#627][PR4] 持仓管理P0:补全功能漏洞与缺失 (#677)
* feat(portfolio): implement P0 PR1 core ledger and snapshot

* feat(portfolio): implement PR2 import and risk loop

* feat(portfolio): deliver PR3 web and agent consumption loop

* fix(portfolio): finalize PR3 follow-up adjustments

* docs: clarify portfolio env section as P0

* feat(portfolio): close PR4 gaps for account workflow

* fix(portfolio): preserve csv code zeros and dry-run dedup

* fix(portfolio): align account contract and shared parser registry

* fix(portfolio): refine import dedup and local date defaults

---------

Co-authored-by: zhulinsen <zhuls97@163.com>
2026-03-15 20:19:11 +08:00
Xavier Zhou
7b7eff7187 fix: support legacy Discord channel env alias and align docs (#659) 2026-03-15 19:09:14 +08:00
mumu
f6bcb8d383 fix: runtime robustness — efinance timeout, type-safe integrity, report save decoupling (#660)
* fix: runtime robustness — efinance timeout, type-safe integrity, report save decoupling

- efinance_fetcher: wrap all efinance API calls with _ef_call_with_timeout()
  to prevent indefinite hangs when eastmoney hosts are unreachable (was 81min+)
- analyzer: make check_content_integrity() type-safe when LLM returns dict
  for operation_advice or string for core_conclusion/intelligence/battle_plan
- pipeline: decouple report saving from notification flag (--no-notify no longer
  skips local report generation); normalize operation_advice dict to string
- backtest_engine: handle operation_advice as dict in _compute_advice_breakdown
- runner: guard response.usage against None to prevent AttributeError
- orchestrator: log non-critical stage failures (intel/risk) instead of silent skip

* fix: address PR #660 review — timeout shutdown, env guard, decision_type normalize, non-str advice

- efinance_fetcher: _ef_call_with_timeout() now uses explicit executor.shutdown(
  wait=False) to avoid re-blocking on hung thread after FuturesTimeoutError
- efinance_fetcher: guard _EF_CALL_TIMEOUT parsing with try/except to prevent
  module load failure on invalid EFINANCE_CALL_TIMEOUT env value
- pipeline: normalize decision_type with strip/lower before operation_advice
  dict lookup so 'BUY'/'Buy' variants map correctly instead of falling to default
- analyzer: treat non-str operation_advice/analysis_summary as missing to
  prevent downstream TypeError (e.g. get_emoji() with unhashable dict)
- .env.example: add EFINANCE_CALL_TIMEOUT config entry
2026-03-14 21:39:27 +08:00
mumu
d1ec2c8b5f feat: multi-agent architecture — core orchestrator, specialised agents, strategy system (#647)
* feat: multi-agent architecture — core orchestrator, specialised agents, strategy system

Phase 0-7 core agent infrastructure:
- AgentContext/AgentOpinion/StageResult protocols
- run_agent_loop() shared runner extracted from AgentExecutor
- AgentOrchestrator with 4 modes (quick/standard/full/strategy)
- BaseAgent ABC + Technical/Intel/Risk/Decision/Portfolio agents
- StrategyRouter (regime detection), StrategyAggregator (weighted consensus)
- AgentMemory with prediction tracking and confidence calibration
- Backtest summary tools registered as read-only Agent tools
- AGENT_ARCH switch (single/multi), config registry + WebUI entries
- is_agent_available() auto-detection from LITELLM_MODEL
- Config __post_init__ validation for AGENT_ARCH/ORCHESTRATOR_MODE/STRATEGY_ROUTING

* fix: address PR #647 review comments

- base_agent: propagate tool_calls_log in result.meta for orchestrator aggregation
- risk_agent: fix docstring — AGENT_RISK_OVERRIDE is bool, not string
- __init__: remove ResearchAgent from lazy imports (research.py not on this branch)
- router: cast trend_score to float to handle LLM string responses
- config_registry: fix duplicate display_order 65 — bump AGENT_MEMORY_ENABLED to 66 and cascade
- test_system_config_service: add missing assertions to validate test
- agent.py: clarify user_id must include platform prefix in docstring

* feat(multi-agent): strategy mode, data perspective fix, review fixes

- Multi-agent orchestrator: add strategy mode with consensus voting
- Fix data perspective MA N/A: compute trend before agent branch, read
  from trend_result instead of LLM output
- Fix risk override double-apply: make _apply_risk_override idempotent
  so normal runs don't over-downgrade signals
- Fix timeout error suppression: preserve error_message on agent result
  regardless of success flag
- Fix notification float subscript: wrap dashboard values in str()
- Add skills->strategies backward compat on ChatRequest model
- Fix zero-value falsy bug in price_position dict construction
- Add fill_price_position_if_needed post-processing for single-agent
- Add _bias_label helper for computed bias status display
- Increase orchestrator timeout default to 600s
- Web: skills->strategies rename, i18n updates
- Python 3.9 compat: add future annotations to stock_mapping.py

* fix: update pipeline routing test for trend_result param, fix risk docstring

- test_agent_mode_routes_to_agent: assert 8 positional args (trend_result added)
- risk_agent.py: fix docstring to match actual boolean config behavior

* fix typeerror
2026-03-14 13:45:35 +08:00
mumu
a97f41637b feat(llm): multi-channel LLM config with WebUI channel editor (#641)
* feat(llm): multi-channel LLM config with WebUI editor, protocol/model normalization, and connectivity test

- Add env-based multi-channel LLM configuration (LLM_CHANNELS, per-channel
  PROTOCOL/BASE_URL/API_KEY/MODELS/ENABLED) with automatic protocol inference
  and model name normalization for LiteLLM Router
- Add full-featured LLM Channel Editor in WebUI with inline channel
  management, model selection, temperature control, and one-click
  connectivity testing per channel
- Add POST /api/v1/system-config/test-llm-channel endpoint for real-time
  LLM channel validation with latency reporting
- Add comprehensive validation for channel definitions, model references,
  and runtime selection in SystemConfigService
- Add unified LLM_TEMPERATURE with backward-compatible fallback to legacy
  provider-specific temperature vars (GEMINI/OPENAI/ANTHROPIC_TEMPERATURE)
- Default localhost channels to openai protocol (not ollama) for
  compatibility with vLLM/LM Studio/LocalAI; Ollama requires explicit
  PROTOCOL=ollama
- Allow direct-env LiteLLM providers (groq/*, bedrock/*, etc.) to bypass
  channel-only model validation on both backend and frontend
- Skip channel validation when LITELLM_CONFIG YAML is the active model source
- Normalize slash-prefixed model IDs (e.g. Qwen/Qwen3-8B on SiliconFlow)
  consistently between frontend and backend
- Prevent WebUI from resetting unsaved channel edits when unrelated AI
  settings in the same category are modified
- Protect against invalid temperature env values with try/except fallback
- Add regression tests for channel parsing, temperature fallback, protocol
  inference, YAML priority, and direct-env provider passthrough

Refs #544, Refs #507

* fix: resolve CI test failures and address PR review feedback

- Fix 3 failing validate_structured tests by aligning litellm_model with model lists
- Add direct-env provider bypass for primary and fallback model validation
- Add ValueError/TypeError -> 422 handling in test-llm-channel endpoint
- Add Space key preventDefault for accessible channel header toggle
- Canonicalize alias prefixes in normalizeModelForRuntime to prevent double-prefixing

* fix(ui): align temperature resolver and API_KEYS priority with backend

- Replace hard-coded temperature fallback chain with resolveTemperatureFromItems()
  that mirrors backend resolve_unified_llm_temperature: reads LLM_TEMPERATURE first,
  then the active model's provider-specific env, then any legacy *_TEMPERATURE
- Swap LLM_{NAME}_API_KEYS / LLM_{NAME}_API_KEY hydration order so multi-key
  configs (rotation/load-balancing) are not silently dropped on save

* fix(security): SSRF guard on base_url + validate parsed API key segments

- Add _is_safe_base_url() to block link-local/cloud metadata addresses
  (169.254.0.0/16, metadata.google.internal, 100.100.100.200) while
  preserving legitimate localhost/LAN endpoints like Ollama
- Apply ssrf_blocked validation error in _validate_llm_channel_definition
- Replace api_key_value truthy-string check with parsed-segment check so
  ',' / ' , ' inputs are caught as missing_api_key instead of silently
  producing zero-key channels at runtime
- Add regression tests: rejects_comma_only_api_key (3 subtests),
  rejects_ssrf_metadata_base_url (3 subtests), allows_localhost_base_url

* fix: direct-env models bypass Router when channel mode is active

In channel/YAML mode, Router.completion() is called for all models but
the Router model_list only contains channel/YAML-declared entries. Direct-
env providers (groq/, bedrock/, etc.) are never added to it, so they caused
'model not found' errors at inference time even though validate_structured()
correctly exempted them from membership checks.

Fix: before dispatching to the Router, check whether the model is actually
in the Router model_list (via get_configured_llm_models). Models absent from
the list fall through to litellm.completion() with env-based credentials,
matching the existing legacy-path behavior. Applied consistently in both
src/analyzer.py and src/agent/llm_adapter.py.

* fix: add missing get_configured_llm_models import in analyzer.py
2026-03-13 22:57:58 +08:00
Alfred
8cfcf7f6ef [Feature] [P0] 基本面数据管道程序化改造 Issue #614 (#626)
* fix: stabilize P0 fundamental context pipeline (#614)

* test: mock fundamental bundle for ETF context stability

* fix: preserve remaining budget and lock fundamental cache

* fix: harden adapter row matching and bound timeout workers

* fix: refine fundamental status semantics and dragon tiger completion

* test: cover get_stock_info board semantics contract

* docs: clarify board field contract in fundamental outputs

* fix: normalize belong board metadata keys across payload shapes

* fix: harden valuation status and scope fundamental cache keys

* fix: align belong board dict aliases with dataframe normalization

---------

Co-authored-by: mumu <42829555+ZhuLinsen@users.noreply.github.com>
2026-03-13 16:36:52 +08:00
Alfred
4608f8f3a6 [feat] 增加 SearXNG支持 Issue #550 (#588)
* feat(search): add SearXNG support as quota-free fallback (Fixes #550)

Made-with: Cursor

* fix(pr-588): address Copilot review - test robustness, config urlparse, doc typo

- tests: fix flaky published_date assertion; add sleep patch to 3 retry tests; remove unused SearchResult import
- config: replace double urlparse with single-pass loop for SEARXNG_BASE_URLS
- docs: correct SERPAPI_KEYS to SERPAPI_API_KEYS in zeabur-deployment.md

Made-with: Cursor
2026-03-11 13:36:09 +08:00
Alfred
53e3d2dead [Feature] 报告引擎 P0:Schema、模板、完整性校验、Brief 模式、历史对比 (#560) (#561)
* chore(config): add report engine feature flags and template settings

* feat(analyzer): add pydantic schema validation for llm report json

* feat(report): report engine P0 - schema, templates, integrity, brief mode, history comparison

- Pydantic AnalysisReportSchema for LLM JSON validation
- Jinja2 templates (markdown, wechat, brief) with configurable dir
- Content integrity check with retry and placeholder fallback
- Brief mode (REPORT_TYPE=brief) for 3-5 sentence summary
- History comparison service for signal changes across runs
- generate_aggregate_report unified entry, ReportType.from_str(detailed)
- Config: REPORT_TEMPLATES_DIR, REPORT_RENDERER_ENABLED, etc.

Fixes #560
2026-03-09 21:35:55 +08:00
Haode Du
049e7e8f59 feat: add MiniMax Coding Plan web search provider (#493)
* feat: add MiniMax Coding Plan web search provider

- Add MiniMaxSearchProvider class with POST API to api.minimaxi.com
- Priority: Bocha > MiniMax > Tavily > Brave > SerpAPI
- Dual time-filtering: query augmentation + client-side date filtering
- Circuit breaker: 3 consecutive failures -> 300s cooldown
- New MINIMAX_API_KEY env var (supports multiple keys, comma-separated)
- Update config.py, search_service.py, .env.example

* docs: add MiniMax search provider to all documentation

- .env.example: add MINIMAX_API_KEY and BOCHA_API_KEYS with priority note
- README.md: update tech stack table and secrets table
- docs/full-guide.md: add MiniMax to config tables and search service section
- docs/full-guide_EN.md: add MiniMax to config tables and search service section
- docs/README_EN.md: update tech stack and secrets tables
- docs/README_CHT.md: update tech stack and secrets tables
- docs/DEPLOY.md: add MiniMax to env var tables
- docs/DEPLOY_EN.md: add MiniMax to env var tables
- docs/docker/zeabur-deployment.md: add MiniMax to analysis config table
- docs/CHANGELOG.md: add MiniMax provider to Unreleased section

* update doc

* refactor(search_service): 调整搜索提供者初始化顺序及参数位置

将MiniMax搜索提供者的参数位置和初始化顺序调整到最后,保持代码逻辑清晰

* 添加其他多处minimax_api_keys支持并调整参数顺序

* 增加 Bocha 和 Minimax 的前端配置

* fix: 将MINIMAX_API_KEYS改为单数形式

* docs(CHANGELOG): 调整MiniMax搜索提供商的优先级顺序

更新CHANGELOG.md中MiniMax搜索提供商的优先级描述,从Bocha > MiniMax > Tavily > Brave > SerpAPI调整为Bocha > Tavily > Brave > SerpAPI > MiniMax

* fix: 统一 MINIMAX_API_KEY 为 MINIMAX_API_KEYS 以保持命名一致性

---------

Co-authored-by: mumu <42829555+ZhuLinsen@users.noreply.github.com>
2026-03-09 21:29:56 +08:00
Alfred
9153a83c34 docs: 新增 LLM 配置指南,系统讲解三层配置、渠道模式、Vision、Agent、排错 (#545)
- 新增 docs/LLM_CONFIG_GUIDE.md(中文)与 docs/LLM_CONFIG_GUIDE_EN.md(英文)
- 更新 README、full-guide、.env.example、litellm_config.example.yaml 增加指南链接
- full-guide 环境变量表补充 LITELLM_MODEL、LITELLM_FALLBACK_MODELS、LLM_CHANNELS、LITELLM_CONFIG
- full-guide_EN 同步 LiteLLM 直接集成章节与 AI 表
- FAQ 与 FAQ_EN 增加 LLM 配置常见问题
- CHANGELOG 记录本次文档更新
2026-03-08 16:18:33 +08:00
Alfred
076b0fe718 [feat] 配置中 markdown 转图片支持个股日报汇总 Issue #455 (#535)
* feat(#455): Markdown-to-image for dashboard, m2f engine, prefetch controls

- Dashboard report supports markdown-to-image (Telegram/WeChat/Custom/Email)
- MD2IMG_ENGINE=markdown-to-file for better emoji support
- PREFETCH_REALTIME_QUOTES to disable full-market quote prefetch
- Stock name prefetch with allow_realtime=False to reduce network overhead
- Email groups and Custom webhook image routing
- Enhanced failure hint (wkhtmltopdf or m2f)
- Docs: README, full-guide, CHANGELOG, .env.example
- Tests: prefetch_stock_names, pipeline notification routing, prefetch dry_run

Fixes #455

* chore: trigger CI and AI review refresh

---------

Co-authored-by: mumu <42829555+ZhuLinsen@users.noreply.github.com>
2026-03-07 20:31:16 +08:00
mumu
e642f776c8 feat: multi-channel LLM support with visual channel editor (#494)
* feat: multi-channel LLM support with visual channel editor

- Add three-tier LLM config: LITELLM_CONFIG (YAML) > LLM_CHANNELS (env) > legacy keys
- Each channel gets independent base_url / api_key / models (no OPENAI_BASE_URL conflict)
- Support DEEPSEEK_API_KEY as standalone provider (auto-infers deepseek-chat model)
- Add LLMChannelEditor component with 9 presets (AIHubmix/DeepSeek/Dashscope/GLM/Moonshot/SiliconFlow/OpenRouter/Gemini/Custom)
- Expand config_registry with ~50 new fields for web settings coverage
- Rewrite .env.example AI section with clear quick-start guide (Scenario A vs B)
- Add litellm_config.example.yaml template
- Add PyYAML dependency for YAML config support
- Full backward compatibility: existing single-key configs work unchanged

* chore: replace placeholder key values with empty defaults in .env.example

* fix: resolve ESLint errors in LLMChannelEditor and HomePage

* refactor: use native litellm deepseek/ provider and extract shared LLM helpers

- Replace openai/deepseek-* + manual api_base with deepseek/ prefix (litellm
  natively resolves DEEPSEEK_API_KEY and base_url)
- Extract duplicated _get_api_keys_for_model and _extra_litellm_params from
  analyzer.py and llm_adapter.py into shared functions in config.py
- Update litellm_config.example.yaml to use deepseek/ prefix
- Thinking mode (deepseek-chat opt-in, deepseek-reasoner auto) unaffected:
  get_thinking_extra_body uses model short name stripped of provider prefix
2026-03-06 21:14:34 +08:00
Alfred
c644e0144e docs: add ENABLE_EASTMONEY_PATCH guidance for Issue #453 (#456)
- FAQ Q4: add ENABLE_EASTMONEY_PATCH and MAX_WORKERS suggestions
- full-guide: add ENABLE_EASTMONEY_PATCH to config table, add 东财接口频繁失败时的处理 section
- .env.example: expand ENABLE_EASTMONEY_PATCH comment

Refs #453
2026-02-28 16:37:29 +08:00
Alfred
0154992e18 [feat] LiteLLM 直接集成 + 多 API Key 支持 (Fixes #421 #428, Refs #440) (#454) #minor
* fix: migrate _call_gemini to google-genai SDK for thought_signature support (Fixes #440, Refs #421)

- Replace deprecated google-generativeai with google-genai in llm_adapter.py
- Add base64 round-trip for thought_signature (bytes <-> str) for Gemini 3 multi-turn tool calls
- Fix to_gemini_declaration() to use JSON Schema lowercase types (object/string) for parameters_json_schema
- Add base64 decode error handling for robustness
- Add google-genai>=1.0.0 to requirements.txt; keep google-generativeai for analyzer/image_stock_extractor

* test: update test_gemini_declaration for JSON Schema lowercase types

* fix: use role="tool" for function response per Gemini API docs (review feedback)

* feat: LiteLLM 直接集成 + 多 API Key 支持 (Fixes #421, Refs #440)

- 移除 google-generativeai、google-genai、anthropic 原生 SDK,统一通过 litellm 调用
- 新增 LITELLM_MODEL、LITELLM_FALLBACK_MODELS 配置
- 新增 GEMINI_API_KEYS、ANTHROPIC_API_KEYS、OPENAI_API_KEYS 多 Key 解析
- 多 Key 时自动构建 LiteLLM Router(simple-shuffle)
- 删除 LITELLM_PROXY_SETUP.md、litellm_config.yaml.example
- image_stock_extractor、analyzer、market_analyzer 改用 litellm
- registry 移除 to_gemini_declarations/to_anthropic_tools,统一 OpenAI 格式
- 修复 review 发现:删除 _is_key_valid 死代码,更新错误信息与模块 docstring

* docs: restore AIHubmix recommendation section in .env.example

* docs: expand LITELLM_FALLBACK_MODELS example and add vision model config

* fix: correct _run_loop type hint for tool_decls (Dict -> List)

* style: move inline imports to top of file per PEP 8

- litellm and Router imports moved to module top in llm_adapter.py,
  analyzer.py, image_stock_extractor.py
- Also fixes _run_loop tool_decls type hint (Dict -> List)

* fix: add Config type hints and clarify LLM failure exception (review feedback)

* docs: restore original Chinese comments in config (review feedback)

* fix: deprecation hint for legacy config; fallback to gemini_model_fallback when LITELLM_FALLBACK_MODELS empty (review feedback)

* docs: improve .env.example LLM config clarity (review feedback)

- Consolidate LITELLM_MODEL/FALLBACK explanation at top
- Clarify single primary vs comma-separated fallback
- Rename scheme 3 to OpenAI/DeepSeek/OpenRouter (AIHubmix has own section)
- Add note: AIHUBMIX_KEY requires no OPENAI_BASE_URL
- Add OpenRouter URL in OPENAI_BASE_URL comment
- Clarify openai prefix required for third-party/OpenAI-compatible APIs

* chore: Router log models list; add openai dependency note in full-guide (AI review)
2026-02-28 16:36:34 +08:00
zhulinsen
2349ac90c7 feat: auto-build frontend assets on WebUI startup and show guide page when not built
- Add prepare_webui_frontend_assets() to main.py: auto-runs npm install && npm
      run build in apps/dsa-web before starting FastAPI server
    - New env var WEBUI_AUTO_BUILD (default: true) to control auto-build behavior
    - Replace bare JSON root response with styled HTML guide page when frontend
      static files are not present (api/app.py)
    - Remove unused RootResponse import from api/app.py
    - Update README.md startup instructions and .env.example documentation
    - Add changelog entry in docs/CHANGELOG.md

    #patch
2026-02-27 20:13:22 +08:00
Alfred
29a22af1f3 fix: Agent Reasoning 400 & LiteLLM Proxy integration (fixes #409) (#427)
- Parse and propagate thought_signature in OpenAI-compatible tool calls
- Add LiteLLM Proxy setup guide and config example
- Relax OpenAI API key length validation to >= 8 for proxy compatibility
- Update CHANGELOG, full-guide, README
2026-02-26 21:13:04 +08:00
Mark
75896f6d05 fix(agent): include framework category in skill rendering + Docker strategies missing (#406)
* fix(agent): include framework category in skill instructions rendering

`get_skill_instructions()` only iterated over ["trend", "pattern",
"reversal"] categories, silently dropping all strategies with
`category: framework` (box_oscillation, chan_theory, wave_theory,
emotion_cycle). Add "framework" to the category map and use a
dynamic fallback so future custom categories are never lost.

Also:
- Document `AGENT_SKILLS=all` shorthand in .env.example
- Add `AGENT_SKILLS` config to README
- Add CHANGELOG entry
- Update strategies/README.md and Skill docstring with framework category

Fixes #403

* fix(docker): include strategies directory in Docker image and compose

Dockerfile was missing `COPY strategies/ ./strategies/`, and
docker-compose.yml did not mount the strategies directory, causing
all 11 built-in strategies to fail loading in containerized deployments.

---------

Co-authored-by: ma_k <ma_k@ctrip.com>
2026-02-26 20:44:24 +08:00
Alfred
c66fd3cf13 [feature] 盘中实时分析 Issue #234 (#397)
* feat: intraday realtime technical indicators (MA5/10/20, bullish alignment)

- Use realtime price for MA and alignment in intraday analysis
- Add enable_realtime_technical_indicators config
- Add _augment_historical_with_realtime and _compute_ma_status in pipeline
- Fix today context overwrite when trend_result.ma5 is 0
- Add tests for realtime indicator logic

Fixes #234

* refactor: avoid mutating input df in _augment_historical_with_realtime
2026-02-25 22:32:43 +08:00
Alfred
4e030c3958 [fix] 支持 DeepSeek 思考模式 Issue #379 (#386)
* fix: support DeepSeek thinking mode for tool-calling (Fixes #379)

- Add reasoning_content to LLMResponse and pass it in multi-turn assistant messages
- Add OPENAI_THINKING_ENABLED config for deepseek-chat explicit enable
- Parse reasoning_content from DeepSeek API response via getattr
- Update config_registry, .env.example, and docs (CHANGELOG, README, full-guide, FAQ)

* refactor(issue-379): auto-detect thinking models, remove OPENAI_THINKING_ENABLED

- _AUTO_THINKING_MODELS: deepseek-reasoner, deepseek-r1, qwq (no extra_body)
- _OPT_IN_THINKING_MODELS: deepseek-chat -> payload (decoupled for Qwen3 etc.)
- Remove env/config/registry/i18n for OPENAI_THINKING_ENABLED
- User transparent, no manual config required

* docs: address PR review - clarify reasoning_content, add path comment

- LLMResponse.reasoning_content: expand comment (CoT, multi-turn pass-back)
- analyzer _build_base_request_kwargs: add OpenAI-compatible path comment

* docs: address PR review - explicit impl, README note, docstring

- PR body: add 实现方案 section, clarify no openai_thinking_enabled
- README: add DeepSeek thinking mode auto-detect note
- get_thinking_extra_body: expand docstring for _AUTO_THINKING_MODELS
2026-02-25 22:16:22 +08:00
Mark
8090715035 feat: PushPlus group push support (PUSHPLUS_TOPIC) (#402)
Add PUSHPLUS_TOPIC config for PushPlus one-to-many group push.

- src/config.py: add pushplus_topic field
- src/notification.py: include topic param in PushPlus API call
- .env.example / README.md / CHANGELOG.md: document new config
2026-02-25 22:03:54 +08:00
Alfred
0e2e111545 feat: add trading day check (Issue #373) (#375)
- Add trading_calendar module with exchange-calendars for A/HK/US markets
- Per-stock filtering: analyze only stocks whose markets are open today
- Add TRADING_DAY_CHECK_ENABLED config and --force-run CLI override
- Add is_hk_stock_code to data_provider public API
- Update CHANGELOG, full-guide, README, .env.example
2026-02-24 20:12:18 +08:00
zhulinsen
39848b80a1 chore: add aihubmix 2026-02-23 21:05:00 +08:00
mumu
cddb6baeda feat: add agent strategy chat across API, bot, and web UI #minor (#367)
* feat: add agent strategy chat across API, bot, and web UI #minor
- add /api/v1/agent endpoints for strategies and streaming chat
- route pipeline to agent mode when specific skills are configured
- persist multi-turn conversation history in database
- add web chat page, bot /ask command, built-in strategies, and tests

* fix(agent): improve session handling, progress messaging, and chat type safety #patch

Generate UUID session IDs for stream chat requests and use running loop API.

Persist user messages even on failed runs, and store assistant error notes for context continuity.

Add contextual thinking messages after tool calls in agent executor.

Fix strategy display name lookup in bot ask command.

Refine ChatPage TypeScript types and error handling for SSE parsing.

Use SQLAlchemy select+execute for conversation history query.

* docs: add Agent strategy chat to README and CHANGELOG #skip

* fix(tests): update strategy count assertions 6->11; clean up CHANGELOG [Unreleased] section #patch

* chore: update readme and fix unitest

* feat: optimize tools

* fix: Fix hard-coded test values and resolve nested mapping in Dashboard

* update changelog

* refactor(agent): extract shared factory, cache ToolRegistry/SkillManager, fix Gemini model name

* - CRITICAL: fix 4 wrong tool names in AGENT_SYSTEM_PROMPT and
  CHAT_SYSTEM_PROMPT (get_k_history→get_daily_history,
  get_technical_analysis→analyze_trend, get_chip_analysis→
  get_chip_distribution, search_news→search_stock_news)
- fix _THINKING_TOOL_LABELS: update 7 stale keys, add calculate_ma
  and get_analysis_context (13 tools now fully mapped)
- add isinstance(dict) guard in _parse_dashboard to reject non-dict
  JSON (arrays, scalars) that would crash downstream dict access
- use getattr() for config.agent_skills in pipeline.py (AttributeError safety)
- move  to top-level, remove unused imports (get_config,
  Callable, Any/Dict/Optional)
- add phased workflow directives to both system prompts to enforce
  sequential tool calling across analysis stages
- expand .env.example AGENT_SKILLS with all 11 built-in strategies
  and usage examples
- fix factory.py docstring referencing non-existent comprehensive_analysis
2026-02-23 13:24:01 +08:00
zhulinsen
e780f840a3 feat: add RUN_IMMEDIATELY config, fix web UI centering and settings 500 error 2026-02-22 22:24:09 +08:00
Alfred
32162ff745 feat: Web 页面密码验证 (Issue #320, #349) (#351)
* feat(auth): Web 登录认证与 Settings 保护 (Issue #320, #349)

- 新增 ADMIN_AUTH_ENABLED 开关,启用后需登录才能访问 Web UI 和 API
- 首次访问时在网页设置初始密码,凭证存储于 data/.admin_password_hash
- Settings 页面及 /api/v1/* 在启用认证后需登录访问,保护 API 密钥等敏感配置
- 系统设置中可修改密码,密码输入框支持眼睛图标显示/隐藏
- CLI: python -m src.auth reset_password 可重置密码
- 错误提示统一为中文
- 更新 README、full-guide、CHANGELOG

* fix: 凭证文件权限 + ESLint 修复

- src/auth.py: .session_secret 创建后显式 chmod(0o600)
- Pagination.tsx: PageButton 移至组件外,避免 render 内创建组件
- useTaskStream.ts: connectRef 解决闭包引用;isConnected 改用 useState;disconnect setState 延后执行
- HomePage.tsx: 初始加载 useEffect 添加 exhaustive-deps 注释

* test(auth): add unit and integration tests for auth (Issue #320, #349)

- tests/test_auth.py: password validation, hash verification, session, rate limit, set/change/overwrite password
- tests/test_auth_api.py: login, logout, change-password, API protection (401 without session)
- scripts/ci_gate.sh: add src/auth.py to py_compile

* fix(test): disable auth in system_config_api tests to fix 401

* fix: remove duplicate PageButton declaration in Pagination.tsx

Fixes #320
Fixes #349
2026-02-20 21:47:19 +08:00
Alfred
88fdaf7933 feat: 大盘复盘可选除 A 股外的其它大盘(Issue #299) (#348)
* feat: 大盘复盘可选 A 股/美股区域 (Issue #299)

- 新增 MARKET_REVIEW_REGION 配置:cn/us/both
- 新增 market_profile 抽象,按 region 切换新闻搜索、Prompt、模板
- 数据层 get_main_indices(region):yfinance 支持 us 返回 SPX/IXIC/DJI/VIX
- MarketAnalyzer 支持 region 参数,美股时跳过涨跌统计与板块
- region=both 时顺序执行 A 股+美股复盘并合并报告
- 更新 .env.example、full-guide、README、CHANGELOG

* Issue #299: 审查建议修复与优化

- bot: 透传 market_review_region 到 MarketAnalyzer
- yfinance: 提取 _fetch_yf_ticker_data 公共方法,消除 cn/us 重复逻辑
- market_analyzer: 修正 mood_index 匹配逻辑,美股搜索 stock_name 为 US market
- market_analyzer: region=us 时 LLM 提示语改为英文模板
- market_review: both 模式增加 A股/美股生成进度日志
- tests: 新增 _get_us_main_indices 单元测试(mock yfinance)

* Issue #299: 落实审查建议

- config: _parse_market_review_region 解析到非法值时打印 warning 日志
- market_review: both 模式报告分隔符增加描述性说明
- market_analyzer: 指数表格中 amount=0.0 时显示 N/A,避免用户误解

* docs: 优化 MARKET_REVIEW_REGION 描述措辞,避免歧义

- 移除「仅炒美股用户可设为 us」表述
- 明确 both 模式可同时复盘 A 股与美股
- 更新 full-guide、README、CHANGELOG、config 注释、env.example

* style: 移除 bot market 命令中冗余的 or 'cn' 回退
2026-02-19 11:45:47 +08:00
Alfred
7cf1925179 增加 PE 指标、新闻时效性筛查与强势趋势股乖离率放宽 (fix #296) (#340)
* feat: add PE valuation guidance, news freshness, and strong-trend bias relief (Issue #296)

- NEWS_MAX_AGE_DAYS: configurable news max age (default 3 days)
- BIAS_THRESHOLD: configurable MA5 bias threshold (default 5.0%)
- Strong trend compensation: relax bias threshold 1.5x for STRONG_BULL with strength>=70
- AI system prompt: add PE valuation focus and strong-trend relief guidance
- SearchService: pass days param to search_comprehensive_intel
- Config/pipeline robustness: boundary clamping, NaN defense

* test: add unit tests for Issue #296 (bias relief, news freshness)
2026-02-16 20:16:35 +08:00
Gustin Lau
b8ca520f19 feat: 添加东财接口补丁可配置开关 (#335) 2026-02-16 10:32:50 +08:00
Alfred
5414a6de80 feat: add REPORT_SUMMARY_ONLY option for analysis summary only (Fixes #262) (#331)
- Add report_summary_only config (env: REPORT_SUMMARY_ONLY, default false)
- When true, notification shows only summary block without per-stock details
- Applies to generate_dashboard_report, generate_wechat_dashboard, generate_daily_report
- Update README, full-guide, CHANGELOG, .env.example
- Register in Web UI config (config_registry, systemConfigI18n)
- No workflow change: GitHub Actions users can add REPORT_SUMMARY_ONLY via repo vars when needed
2026-02-15 19:13:36 +08:00
Alfred
542c8e4314 feat: merge stock and market report into one notification (Issue #190) (#330)
- Add MERGE_EMAIL_NOTIFICATION env var (default false) to control merged push
- When enabled, combine个股分析 and 大盘复盘 into single notification
- Reduces email count and spam detection risk
- Incompatible with SINGLE_STOCK_NOTIFY, merge disabled in single-stock mode
- Update README, .env.example, full-guide, CHANGELOG

Fixes #190
2026-02-15 19:11:58 +08:00
Alfred
b19a4d0df9 feat: 支持图片识别股票代码、Anthropic Claude API 及通达信手动配置 (fix #257) (#329)
* feat: Add image stock code extraction, Anthropic API, and Pytdx config (Fixes #257)

- Add POST /api/v1/stocks/extract-from-image with Vision LLM (Gemini/Anthropic/OpenAI)
- Add image_stock_extractor service with 60s timeout, rate limit (10/min), X-Forwarded-For support
- Add ImageStockExtractor UI in Settings for upload and merge-to-watchlist
- Add ANTHROPIC_API_KEY, ANTHROPIC_MODEL to config and analyzer fallback chain
- Add PYTDX_HOST, PYTDX_PORT, PYTDX_SERVERS for custom Pytdx server
- Add OPENAI_VISION_MODEL for image-only models
- Handle 409 conflict in merge flow with user-friendly message

* fix: resolve TypeScript build error in stocks.ts (avoid Record<> generic parsing)

* feat: Redis rate limiter, API field unification, anthropic_max_tokens

- Add rate_limiter.py: Memory + Redis implementations for extract-from-image
- Integrate get_extract_rate_limiter() in stocks.py; remove image param, keep file only
- Add anthropic_max_tokens config for analyzer
- Update .env.example, config_registry, full-guide, CHANGELOG
- Add redis>=5.0 as optional dependency

* refactor: rename GeminiAnalyzer to LLMAnalyzer for multi-backend clarity

* revert: restore GeminiAnalyzer naming (keep original upstream convention)

* docs: add image extraction and from-image-add usage to README

* fix: Anthropic runtime fallback to OpenAI; remove Redis rate limiter

- Init both Anthropic and OpenAI at startup so Anthropic 429/network glitch can fall back to OpenAI
- Check Anthropic before OpenAI in _call_api_with_retry to preserve priority
- Remove Redis rate limiter per review; keep in-memory only

* remove rate limiter for extract-from-image per review

- Delete rate_limiter.py; extract-from-image has no rate limiting
- Remove Request param and 429 response from stocks endpoint
- Update docs to drop rate limit mentions
2026-02-15 19:10:42 +08:00
mumu
2692b20c2d feat: add schedule immediate run config and fix docker build (#333) fixes #332
* feat: add schedule immediate run config and fix docker build

1. Fix Docker build failure by adding missing `patch/` directory copy.
2. Add comprehensive module import smoke tests in CI to prevent future regressions.
3. Add `SCHEDULE_RUN_IMMEDIATELY` config and `--no-run-immediately` arg to control whether scheduled tasks run on startup.
4. Update documentation for scheduled task configuration.

* fix import error
2026-02-15 14:57:27 +08:00
Alfred
84a3da9953 feat: add WEBHOOK_VERIFY_SSL for self-signed cert support (#265) (#319)
- Add webhook_verify_ssl config (default true), parse WEBHOOK_VERIFY_SSL env
- Pass verify param to all Webhook requests (WeChat, Feishu, Discord, Custom, AstrBot)
- Add WEBHOOK_VERIFY_SSL to config_registry with security warning
- Update .env.example, README, full-guide, CHANGELOG

Closes #265
2026-02-14 22:00:55 +08:00
Alfred
5883dc41bd feat: add Markdown-to-image for notification channels (Fixes #289) (#315)
* feat: add Markdown-to-image for notification channels (Fixes #289)

- Add MARKDOWN_TO_IMAGE_CHANNELS config for telegram, wechat, custom, email
- New src/md2img.py: markdown_to_image() via imgkit/wkhtmltoimage
- Extract markdown_to_html_document to src/formatters.py for reuse
- Implement image sending: Telegram sendPhoto, WeChat base64+md5,
  Discord webhook multipart, email inline attachment
- Add imgkit to requirements, wkhtmltopdf to Dockerfile
- Graceful fallback to text when imgkit/wkhtmltopdf unavailable

* fix(docker): pin to bookworm for wkhtmltopdf, add runtime deps

wkhtmltopdf was removed from Debian testing (2025). Pin base image to
python:3.11-slim-bookworm. Add fontconfig, libjpeg62-turbo, libxrender1,
libxext6 for headless wkhtmltopdf.

* docs(md2img): add security note on command injection and XSS

* refactor(md2img): extract _should_use_image_for_channel, document Fallback rules

* docs: add Markdown-to-image dependency install guide (imgkit, wkhtmltopdf)
2026-02-13 21:16:22 +08:00
Alfred
184084e415 feat: stock-to-email group routing (Fix #268) (#313)
- Add STOCK_GROUP_N + EMAIL_GROUP_N config for routing reports to different emails
- Market review sends to all configured email receivers
- Minimal changes: optional params on send_to_email and send(), new helpers
2026-02-12 22:26:05 +08:00
mumu
8f30f9093d fix: report signal accuracy, data source reliability, and market revi… (#275)
* fix: report signal accuracy, data source reliability, and market review quality #patch

- Fix signal emoji mismatch for compound advice and *ST markdown escaping
- Inject structured data (indices/stats/sectors) into market review
- Fix tushare return type and API endpoint; auto-inject realtime priority
- Add search cache (500-cap FIFO), limit supplement requests to 1
- Fix analysis API report=None and ReportStrategy type inconsistency
- Update CHANGELOG for v3.0.1 ~ v3.0.5

* fix:  F821 undefined name 'UnifiedRealtimeQuote'
2026-02-08 18:21:33 +08:00
[ZE]
dbe1cd7cae feat(backtest): add backtest engine with evaluation pipeline and WebUI (#269)
Add a complete backtest/evaluation system that measures the accuracy of
AI-generated stock analysis recommendations against actual market outcomes.

Backend:
- Backtest engine (src/core/backtest_engine.py) with direction inference,
  stop-loss/take-profit simulation, and outcome classification (win/loss/neutral)
- Repository layer (src/repositories/backtest_repo.py) with SQLite persistence
  for backtest_results and backtest_summaries tables
- Service layer (src/services/backtest_service.py) orchestrating evaluation runs
  with configurable window days, neutral band, and min-age filters
- REST API endpoints: POST /run, GET /results, GET /performance, GET /performance/{code}
- Pydantic schemas for request/response validation

Frontend (apps/dsa-web):
- New Backtest page with performance dashboard sidebar showing direction
  accuracy, win rate, simulated returns, SL/TP trigger rates, and W/L/N counts
- Paginated results table with outcome badges, direction indicators, and
  color-coded return percentages
- Stock code filter and one-click "Run Backtest" trigger
- Full TypeScript types and API client matching backend schemas

Direction mapping fix:
- "Wait/observe" (观望) advice now maps to direction_expected="down" instead
  of "flat", correctly reflecting that "wait" means "stay out due to downside
  risk" rather than predicting a flat market

Tests:
- 21 unit tests covering engine logic, service orchestration, and summary
  aggregation (all passing)

Docs:
- Updated README, full-guide, and translations with backtest feature docs
2026-02-08 14:49:50 +08:00
[ZE]
13b556e79e feat(search): add Brave Search API support (#255)
* feat(search): add Brave Search API support

- Add BraveSearchProvider class with multi-key load balancing
- Support time-based filtering (freshness: pd/pw/pm/py)
- Priority order: Bocha > Tavily > Brave > SerpAPI
- Configure via BRAVE_API_KEYS environment variable
- US stock optimized (English language, US region)

* docs: add Brave Search API to documentation

- Update README.md (CN)
- Update docs/full-guide.md
- Update docs/README_EN.md
- Update docs/README_CHT.md
2026-02-05 20:40:46 +08:00
Hopeless
b0c6825ed9 feat: 增加ServerChan³(Server酱³)推送通道 (已更新文档) (#238)
* update serverchan3 config

* update serverchan3 config

* Add Server酱3 notification channel support

* Add support for SERVERCHAN3 notification channel

* Add SERVERCHAN3_SENDKEY to configuration options

* Add SERVERCHAN3_SENDKEY to deployment documentation

* Add SERVERCHAN3_SENDKEY to notification options

* Fix formatting for SERVERCHAN3_SENDKEY entry

* Add SERVERCHAN3_SENDKEY to README_CHT.md

* Add SERVERCHAN3_SENDKEY to daily_analysis.yml

* Add SERVERCHAN3_SENDKEY to README_EN.md

* Fix typo in SERVERCHAN3_SENDKEY description
2026-02-04 20:09:58 +08:00
Baojunjie
3bab8b0a26 feat(telegram): 支持发送消息到子话题 (#235)
新增 TELEGRAM_MESSAGE_THREAD_ID 配置选项,允许将通知发送到 Telegram 群组中的特定子话题(Topic)。更新了配置文件、文档和 GitHub Actions 工作流以支持此功能。
2026-02-03 21:23:23 +08:00
zhulinsen
1e63e65ce0 fix(#155): resolve missing volume ratio and improve real-time data sources
- akshare_fetcher: Parse volume_ratio (49), PE (39), PB (46), and market cap (44/45) from Tencent API.
- efinance_fetcher: Add parsing for volume_ratio, PE, and market capitalization.
- base.py: Integrated Tushare Pro as an optional real-time quote source.
- config: Reordered default priority to prioritize Tencent (tencent > akshare_sina > efinance > akshare_em).
- documentation: Updated .env.example and GitHub Actions workflow with real-time source priority instructions.

This fix ensures critical indicators like volume ratio (量比) and turnover rate are correctly fetched and displayed across different data sources.

Closes #155
2026-02-01 12:36:46 +08:00