Commit Graph
9 Commits
Author SHA1 Message Date
shadowinlife 8c2fd3e127 fix: complete env-var migration — CI gate exit 0, 9 schema fields, noqa mechanism
- Add 9 missing env vars to EnvConfig schema (QVERIS_API_KEY,
  VIBE_TRADING_API_URL, OPENAI_MODEL, FUTU_TRADE_PWD_MD5, etc.)
- Migrate 26 os.getenv calls to get_env_config() accessor across 17 files
- Add # noqa: env-gate inline suppression to ci_env_var_gate.py (21 lines)
- Refactor security.py _env_flag_enabled to direct schema access
- Wire CI gate into .github/workflows/test.yml
- Fix api_server.py import of deleted constants
- Restore _legacy.py timeout positive-value validation
- Add reset_env_config() to test_security_auth_api.py for singleton freshness

CI gate: exit 0 (was exit 1 with 54 violations)
Tests: 4953 passed, 4 pre-existing tushare failures, 0 regressions

Co-Authored-By: OpenCode <noreply@opencode.ai>
AI-Model: qwen3.7-max
Co-Authored-By: opencode <noreply@ai-tool.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
AI-Contributed/Feature: 188/188
AI-Contributed/UT: 39/39
2026-07-08 22:42:14 +08:00
shadowinlife 8234058562 refactor: centralize environment variable management with Pydantic schema + CI gate
- Add agent/src/config/env_schema.py: Pydantic models for ~50 env vars across 6 sub-models (LLMConfig, DataConfig, APIConfig, SwarmConfig, AgentTuningConfig, PathConfig)
- Add agent/src/config/accessor.py: thread-safe lazy singleton get_env_config() + unified _parse_bool() + reset_env_config() for test isolation
- Fix TIMEOUT_SECONDS CLI display default (2400 -> 120, matching runtime)
- Fix MAX_RETRIES CLI display default ('(not set)' -> 2, matching runtime)
- Fix VIBE_TRADING_API_KEY server-side alias (security.py now resolves it via get_env_config().api.api_auth_key)
- Fix VIBE_TRADING_CHANNELS_AUTO_START=on silently ignored (unified _parse_bool accepts 'on')
- Migrate 207 scattered os.getenv/os.environ.get calls across 50+ files to centralized accessor
- Convert 12 module-level import-time fixations to lazy accessor pattern (loop.py, swarm_tool.py, _backend.py, worker.py, security.py)
- Add reset_env_config() calls after settings_routes.py env mutations (13 mutation points)
- Replace print('[WARN]...') with logger.warning() in tushare/okx/yfinance loaders
- Add tools/ci_env_var_gate.py: AST-based CI gate preventing new os.getenv calls outside src/config/
- Add tools/test_ci_env_var_gate.py: 18 test cases for the CI gate
- Update tools/ci_grep_gates.sh to call the new env var gate
- Add agent/tests/test_env_schema.py: 81 test cases covering defaults, type coercion, singleton, thread safety, bool parser
- Update agent/.env.example with schema cross-references
- Update agent/tests/conftest.py with reset_env_config autouse fixture

Closes HKUDS/Vibe-Trading#438

Co-Authored-By: OpenCode <noreply@opencode.ai>
AI-Model: alibaba-cn/glm-5.2

Signed-off-by: shadowinlife <shadowinlife@gmail.com>
Co-Authored-By: opencode <noreply@ai-tool.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
AI-Contributed/Feature: 1383/1383
AI-Contributed/UT: 735/735
2026-07-08 19:36:24 +08:00
Miranda 3be0738f1e fix(tests): isolate loader cache root on Windows 2026-07-05 21:02:17 +08:00
Lanre Shittu 9addc95a4b feat(loaders): validate OHLC invariants at the loader boundary (#274)
* feat(loaders): validate OHLC invariants at the loader boundary

Loaders only dropped NaN rows, so structurally invalid bars (high<low, a
non-positive price, or a high/low that fails to bracket open/close) passed
straight into the backtest and surfaced downstream as NaN/inf metrics that
break the strict allow_nan=False JSON serializers.

Add a shared validate_ohlc() helper in loaders/base.py and call it after the
existing dropna in the yfinance and local loaders. The default drops offending
rows and logs a count, matching the loaders' existing silent-clean convention;
"warn" and "raise" strategies are available for stricter callers.

Signed-off-by: Lanre Shittu <136805224+Shizoqua@users.noreply.github.com>

* feat(loaders): apply OHLC validation centrally for every source

Wire validate_ohlc into the runner's single fetch-convergence point so
auto, single-source, runtime-fallback, and any future loader are guarded
uniformly — not just the two loaders wired at source. Adds
_sanitize_data_map(data_map) in runner.py, applied right after the data
map is assembled and before the empty-data check, plus a test that a dirty
bar from an unwired loader is dropped before it reaches the backtest.

---------

Signed-off-by: Lanre Shittu <136805224+Shizoqua@users.noreply.github.com>
2026-06-20 18:00:35 +08:00
gyx09212214-prog 9f5b8afe7b fix(loaders): tolerate malformed crypto timeout env vars (#227)
Malformed values like CCXT_TIMEOUT_MS=abc / OKX_TIMEOUT_S=abc raised ValueError at import time and could block startup. Add shared positive_env_int/float helpers in loaders/base.py; invalid/blank/non-positive timeout/budget values now warn and fall back to defaults. Valid values still honored.

Closes #227.
2026-06-14 22:25:29 +08:00
Matt Van Horn ff56134b91 feat(loaders): opt-in local data cache for all backtest data sources (#177)
Add an opt-in local market-data cache (VIBE_TRADING_DATA_CACHE) for the backtest
loaders. When enabled, every data source — tushare, okx, ccxt, akshare, mootdx,
yfinance, futu — caches settled historical bars under ~/.vibe-trading/cache
(user home, never the repo tree) so repeated and long-horizon / cross-market
backtests skip the network and avoid provider rate limits.

- Generic loader_cache_get / loader_cache_put / cached_loader_fetch helpers in
  the loader base; batch/connection loaders (yfinance, futu) skip the bulk
  download / FutuOpenD connection entirely on a full cache hit.
- Staleness guard: ranges ending today or in the future are never cached, since
  the key is content-addressed on end_date, not fetch time.
- Cached frames round-trip byte-identical to freshly fetched ones (columns name
  and per-level index dtype preserved across the duckdb parquet round-trip).
- pid + uuid tmp filenames for concurrency-safe atomic writes; cache version 2.
- Documented in .env.example; staleness, real-duckdb, and batch-loader tests.

Closes #171.

Signed-off-by: Haozhe Wu <haozhe_wu@connect.hku.hk>
2026-06-04 23:14:32 +08:00
Haozhe Wu 6d7d365892 refactor(loaders): extract bounded retry/budget pattern into base.py
ccxt_loader and okx each carried their own copy of the same 25-line
retry+budget loop introduced in #121. Hoist the pattern into two
helpers — check_budget() and retry_with_budget() — so any future loader
(yfinance, akshare, tushare) inherits the same guarantees: per-call
transient retries, a wall-clock budget, non-transient exceptions left
unwrapped, original exception preserved as __cause__.

ccxt_loader / okx now declare only what is loader-specific (the
exception class for transient errors and the budget env var); the
scheduling, sleep math, and TimeoutError wrapping live in base.py.

Adds 11 helper-level tests + the 11 pre-existing integration tests
still pass against the refactored loaders.

Follow-up to #121.
2026-05-17 00:13:28 +08:00
warren618 2772ecb688 fix: harden backtest engine with data validation and error isolation
- ffill(limit=5) replaces unlimited ffill to prevent stale prices from
  masking long suspensions; all-NaN symbols auto-dropped with warning
- try/except per symbol in _execute_bars so one symbol failure doesn't
  crash the entire backtest
- pydantic BacktestConfigSchema validates config.json before execution
  (codes non-empty, date format, start<=end, valid interval/engine/source)
- validate_date_range() shared helper called from all 5 loaders
- 25 regression tests covering all four fixes
2026-04-11 13:39:36 +08:00
warren618 27354eb008 feat: data source expansion with auto-fallback + web search + skill categorization
- Add DataLoader Protocol + Registry with market-level fallback chains
- New data sources: AKShare (A-shares/US/HK/futures, free) and CCXT (100+ crypto exchanges)
- Auto-fallback: tushare unavailable -> akshare; OKX unavailable -> CCXT
- Zero-config: all markets work without any API keys
- New web_search tool (DuckDuckGo) for web information retrieval
- Skill categorization: 68 skills organized into 7 categories (data-source, strategy, analysis, asset-class, crypto, flow, tool)
- New data-routing meta-skill for intelligent data source selection
- Registry self-initializes via _ensure_registered() — no manual imports needed
- Pattern detection returns market type instead of source name (decoupled)
- runner.py loads .env via dotenv for reliable token access
2026-04-09 13:43:13 +08:00