HKUDS/Vibe-TradingPublic

"Vibe-Trading: Your Personal Trading Agent"

AI summary: A multimodal AI agent framework that interprets visual charts and market news for financial trading.

Stars
34.5K
+102 today
Forks
5.6K
Watchers
179
Open issues
13
Open PRs
47
Contributors
~180
Commits
2.7K
Branches
10

PythonMITCreated Apr 1, 2026Last push 1d agoLatest release v0.1.16+477 stars this week+2.1K this month

Quick answers

What is Vibe-Trading?
A multimodal AI agent framework that interprets visual charts and market news for financial trading.
What does Vibe-Trading do?
Vibe-Trading introduces a novel multimodal trading framework that leverages Large Multimodal Models (LMMs) to make complex financial decisions. It moves beyond traditional quantitative analysis by allowing AI agents to visually interpret financial charts, read breaking market news, and analyze social media sentiment—capturing the 'vibe' of the market. The system integrates real-time data feeds and employs specialized agents for distinct tasks, such as technical chart analysis and fundamental news summarization. By synthesizing these diverse inputs, the framework aims to execute more nuanced and context-aware algorithmic trading strategies.
Who is Vibe-Trading for?
Quantitative researchers, algorithmic traders, and AI engineers interested in applying multimodal models to financial markets.
How do I get started with Vibe-Trading?
git clone https://github.com/HKUDS/Vibe-Trading.git
How popular is Vibe-Trading on GitHub?
HKUDS/Vibe-Trading has 34,494 stars and 5,606 forks on GitHub, and gained 477 stars in the last 7 days.
What license does Vibe-Trading use?
HKUDS/Vibe-Trading is released under the MIT license.

Star history

since Jul 27, 2026
010K20K30KJul 2026Aug 2026Sep 2026Oct 2026
34.5K stars as of Oct 3, 2026. Measured daily since Jul 27, 2026; GitHub no longer exposes earlier star timestamps.

Contribution activity

commits per day, last 52 weeks
OctNovDecJanFebMarAprMayJunJulAugSepMonWedFri2025-10-05: 0 commits2025-10-06: 0 commits2025-10-07: 0 commits2025-10-08: 0 commits2025-10-09: 0 commits2025-10-10: 0 commits2025-10-11: 0 commits2025-10-12: 0 commits2025-10-13: 0 commits2025-10-14: 0 commits2025-10-15: 0 commits2025-10-16: 0 commits2025-10-17: 0 commits2025-10-18: 0 commits2025-10-19: 0 commits2025-10-20: 0 commits2025-10-21: 0 commits2025-10-22: 0 commits2025-10-23: 0 commits2025-10-24: 0 commits2025-10-25: 0 commits2025-10-26: 0 commits2025-10-27: 0 commits2025-10-28: 0 commits2025-10-29: 0 commits2025-10-30: 0 commits2025-10-31: 0 commits2025-11-01: 0 commits2025-11-02: 0 commits2025-11-03: 0 commits2025-11-04: 0 commits2025-11-05: 0 commits2025-11-06: 0 commits2025-11-07: 0 commits2025-11-08: 0 commits2025-11-09: 0 commits2025-11-10: 0 commits2025-11-11: 0 commits2025-11-12: 0 commits2025-11-13: 0 commits2025-11-14: 0 commits2025-11-15: 0 commits2025-11-16: 0 commits2025-11-17: 0 commits2025-11-18: 0 commits2025-11-19: 0 commits2025-11-20: 0 commits2025-11-21: 0 commits2025-11-22: 0 commits2025-11-23: 0 commits2025-11-24: 0 commits2025-11-25: 0 commits2025-11-26: 0 commits2025-11-27: 0 commits2025-11-28: 0 commits2025-11-29: 0 commits2025-11-30: 0 commits2025-12-01: 0 commits2025-12-02: 0 commits2025-12-03: 0 commits2025-12-04: 0 commits2025-12-05: 0 commits2025-12-06: 0 commits2025-12-07: 0 commits2025-12-08: 0 commits2025-12-09: 0 commits2025-12-10: 0 commits2025-12-11: 0 commits2025-12-12: 0 commits2025-12-13: 0 commits2025-12-14: 0 commits2025-12-15: 0 commits2025-12-16: 0 commits2025-12-17: 0 commits2025-12-18: 0 commits2025-12-19: 0 commits2025-12-20: 0 commits2025-12-21: 0 commits2025-12-22: 0 commits2025-12-23: 0 commits2025-12-24: 0 commits2025-12-25: 0 commits2025-12-26: 0 commits2025-12-27: 0 commits2025-12-28: 0 commits2025-12-29: 0 commits2025-12-30: 0 commits2025-12-31: 0 commits2026-01-01: 0 commits2026-01-02: 0 commits2026-01-03: 0 commits2026-01-04: 0 commits2026-01-05: 0 commits2026-01-06: 0 commits2026-01-07: 0 commits2026-01-08: 0 commits2026-01-09: 0 commits2026-01-10: 0 commits2026-01-11: 0 commits2026-01-12: 0 commits2026-01-13: 0 commits2026-01-14: 0 commits2026-01-15: 0 commits2026-01-16: 0 commits2026-01-17: 0 commits2026-01-18: 0 commits2026-01-19: 0 commits2026-01-20: 0 commits2026-01-21: 0 commits2026-01-22: 0 commits2026-01-23: 0 commits2026-01-24: 0 commits2026-01-25: 0 commits2026-01-26: 0 commits2026-01-27: 0 commits2026-01-28: 0 commits2026-01-29: 0 commits2026-01-30: 0 commits2026-01-31: 0 commits2026-02-01: 0 commits2026-02-02: 0 commits2026-02-03: 0 commits2026-02-04: 0 commits2026-02-05: 0 commits2026-02-06: 0 commits2026-02-07: 0 commits2026-02-08: 0 commits2026-02-09: 0 commits2026-02-10: 0 commits2026-02-11: 0 commits2026-02-12: 0 commits2026-02-13: 0 commits2026-02-14: 0 commits2026-02-15: 0 commits2026-02-16: 0 commits2026-02-17: 0 commits2026-02-18: 0 commits2026-02-19: 0 commits2026-02-20: 0 commits2026-02-21: 0 commits2026-02-22: 0 commits2026-02-23: 0 commits2026-02-24: 0 commits2026-02-25: 0 commits2026-02-26: 0 commits2026-02-27: 0 commits2026-02-28: 0 commits2026-03-01: 0 commits2026-03-02: 0 commits2026-03-03: 0 commits2026-03-04: 0 commits2026-03-05: 0 commits2026-03-06: 0 commits2026-03-07: 0 commits2026-03-08: 0 commits2026-03-09: 0 commits2026-03-10: 0 commits2026-03-11: 0 commits2026-03-12: 0 commits2026-03-13: 0 commits2026-03-14: 0 commits2026-03-15: 0 commits2026-03-16: 0 commits2026-03-17: 0 commits2026-03-18: 0 commits2026-03-19: 0 commits2026-03-20: 0 commits2026-03-21: 0 commits2026-03-22: 0 commits2026-03-23: 0 commits2026-03-24: 0 commits2026-03-25: 0 commits2026-03-26: 0 commits2026-03-27: 0 commits2026-03-28: 0 commits2026-03-29: 0 commits2026-03-30: 0 commits2026-03-31: 0 commits2026-04-01: 3 commits2026-04-02: 0 commits2026-04-03: 0 commits2026-04-04: 0 commits2026-04-05: 0 commits2026-04-06: 0 commits2026-04-07: 0 commits2026-04-08: 1 commit2026-04-09: 3 commits2026-04-10: 9 commits2026-04-11: 9 commits2026-04-12: 4 commits2026-04-13: 3 commits2026-04-14: 2 commits2026-04-15: 4 commits2026-04-16: 1 commit2026-04-17: 5 commits2026-04-18: 2 commits2026-04-19: 13 commits2026-04-20: 3 commits2026-04-21: 7 commits2026-04-22: 1 commit2026-04-23: 0 commits2026-04-24: 0 commits2026-04-25: 0 commits2026-04-26: 0 commits2026-04-27: 6 commits2026-04-28: 1 commit2026-04-29: 0 commits2026-04-30: 9 commits2026-05-01: 3 commits2026-05-02: 3 commits2026-05-03: 1 commit2026-05-04: 3 commits2026-05-05: 1 commit2026-05-06: 5 commits2026-05-07: 4 commits2026-05-08: 4 commits2026-05-09: 8 commits2026-05-10: 6 commits2026-05-11: 4 commits2026-05-12: 1 commit2026-05-13: 7 commits2026-05-14: 8 commits2026-05-15: 2 commits2026-05-16: 10 commits2026-05-17: 11 commits2026-05-18: 3 commits2026-05-19: 3 commits2026-05-20: 3 commits2026-05-21: 0 commits2026-05-22: 5 commits2026-05-23: 0 commits2026-05-24: 4 commits2026-05-25: 2 commits2026-05-26: 3 commits2026-05-27: 5 commits2026-05-28: 5 commits2026-05-29: 1 commit2026-05-30: 7 commits2026-05-31: 0 commits2026-06-01: 10 commits2026-06-02: 5 commits2026-06-03: 4 commits2026-06-04: 4 commits2026-06-05: 11 commits2026-06-06: 0 commits2026-06-07: 4 commits2026-06-08: 5 commits2026-06-09: 4 commits2026-06-10: 4 commits2026-06-11: 4 commits2026-06-12: 3 commits2026-06-13: 3 commits2026-06-14: 9 commits2026-06-15: 6 commits2026-06-16: 9 commits2026-06-17: 4 commits2026-06-18: 14 commits2026-06-19: 4 commits2026-06-20: 8 commits2026-06-21: 4 commits2026-06-22: 5 commits2026-06-23: 6 commits2026-06-24: 3 commits2026-06-25: 6 commits2026-06-26: 5 commits2026-06-27: 6 commits2026-06-28: 6 commits2026-06-29: 12 commits2026-06-30: 5 commits2026-07-01: 7 commits2026-07-02: 8 commits2026-07-03: 4 commits2026-07-04: 7 commits2026-07-05: 10 commits2026-07-06: 28 commits2026-07-07: 8 commits2026-07-08: 8 commits2026-07-09: 3 commits2026-07-10: 8 commits2026-07-11: 13 commits2026-07-12: 9 commits2026-07-13: 44 commits2026-07-14: 14 commits2026-07-15: 21 commits2026-07-16: 69 commits2026-07-17: 25 commits2026-07-18: 26 commits2026-07-19: 24 commits2026-07-20: 17 commits2026-07-21: 36 commits2026-07-22: 15 commits2026-07-23: 3 commits2026-07-24: 25 commits2026-07-25: 27 commits2026-07-26: 4 commits2026-07-27: 9 commits2026-07-28: 11 commits2026-07-29: 9 commits2026-07-30: 21 commits2026-07-31: 15 commits2026-08-01: 8 commits2026-08-02: 6 commits2026-08-03: 6 commits2026-08-04: 18 commits2026-08-05: 19 commits2026-08-06: 10 commits2026-08-07: 30 commits2026-08-08: 34 commits2026-08-09: 31 commits2026-08-10: 20 commits2026-08-11: 17 commits2026-08-12: 16 commits2026-08-13: 17 commits2026-08-14: 19 commits2026-08-15: 21 commits2026-08-16: 9 commits2026-08-17: 10 commits2026-08-18: 37 commits2026-08-19: 11 commits2026-08-20: 49 commits2026-08-21: 12 commits2026-08-22: 16 commits2026-08-23: 18 commits2026-08-24: 26 commits2026-08-25: 16 commits2026-08-26: 8 commits2026-08-27: 8 commits2026-08-28: 17 commits2026-08-29: 19 commits2026-08-30: 19 commits2026-08-31: 21 commits2026-09-01: 28 commits2026-09-02: 14 commits2026-09-03: 2 commits2026-09-04: 12 commits2026-09-05: 25 commits2026-09-06: 17 commits2026-09-07: 13 commits2026-09-08: 17 commits2026-09-09: 13 commits2026-09-10: 9 commits2026-09-11: 19 commits2026-09-12: 5 commits2026-09-13: 9 commits2026-09-14: 7 commits2026-09-15: 33 commits2026-09-16: 6 commits2026-09-17: 5 commits2026-09-18: 54 commits2026-09-19: 15 commits2026-09-20: 24 commits2026-09-21: 55 commits2026-09-22: 25 commits2026-09-23: 16 commits2026-09-24: 36 commits2026-09-25: 20 commits2026-09-26: 18 commits2026-09-27: 5 commits2026-09-28: 9 commits2026-09-29: 21 commits2026-09-30: 10 commits2026-10-01: 7 commits2026-10-02: 12 commits2026-10-03: 5 commits
2,043 commits in the last yearLessMore

Signals and awards

derived from tracked data
  • Widely adopted

    34,494 stars

  • Very active

    2,043 commits in 52 weeks

  • Community-driven

    ~180 contributors

  • Well documented

    High community health score

  • Permissive license

    MIT

  • Continuous integration

    Automated checks passing

  • Repeat trending

    23 trending appearances

What Vibe-Trading does

Vibe-Trading introduces a novel multimodal trading framework that leverages Large Multimodal Models (LMMs) to make complex financial decisions. It moves beyond traditional quantitative analysis by allowing AI agents to visually interpret financial charts, read breaking market news, and analyze social media sentiment—capturing the 'vibe' of the market. The system integrates real-time data feeds and employs specialized agents for distinct tasks, such as technical chart analysis and fundamental news summarization. By synthesizing these diverse inputs, the framework aims to execute more nuanced and context-aware algorithmic trading strategies.

Quantitative researchers, algorithmic traders, and AI engineers interested in applying multimodal models to financial markets.

  • Multimodal Analysis: Natively processes visual candlestick charts alongside textual market news and social sentiment.
  • Multi-Agent Architecture: Utilizes distinct, specialized LLM agents for technical analysis, fundamental analysis, and final trade execution.
  • Real-Time Data Integration: Connects to live financial APIs to fetch the latest price action and breaking market updates.
  • Explainable Decisions: Generates detailed, human-readable reasoning logs explaining the rationale behind every trading signal.
  • Backtesting Engine: Includes tools to simulate trading strategies against historical market data to validate performance.

Where teams use it

Algorithmic Trading

Deploy autonomous trading bots that react to both technical chart patterns and qualitative news events.

Market Sentiment Analysis

Aggregate and analyze complex social media and news data to gauge overall market fear or greed.

Trading Signal Generation

Provide human traders with synthesized, actionable insights derived from vast amounts of multimodal data.

Financial Research

Automate the arduous process of correlating visual chart anomalies with corresponding historical news events.

Getting started: git clone https://github.com/HKUDS/Vibe-Trading.git

README

main branch

English | 中文 | 日本語 | 한국어 | العربية | Español | Bahasa Indonesia

Vibe-Trading Logo

Vibe-Trading: Your Personal Trading Agent

One Command to Empower Your Agent with Comprehensive Trading Capabilities

HKUDS%2FVibe-Trading | Trendshift

Python FastAPI React PyPI License
Feishu WeChat Discord

Website  ·  Docs  ·  News  ·  Features  ·  Shadow Account  ·  Demo  ·  Quick Start  ·  Examples  ·  API / MCP  ·  Roadmap  ·  Contributing

pip install vibe-trading-ai


📰 News

⚠️ Security warning: The X account VibeTrading_HKU, Virtuals project 101845, and token contract 0x640BDBF77b6447E8b7DB7894cED84BD1c40571f4 are not official Vibe-Trading assets. We have never launched or endorsed any token or memecoin. Do not buy, connect a wallet, or sign anything. Details.

  • 2026-10-03 🛠️ Research, reports and data reliability: CJK session search, channel setup, broker exposure pricing and file writes now handle cases that blocked everyday use. PDF delivery embeds CJK fonts, Swarm validates preset inputs and separates task artifacts, and replayed tool results survive context compaction (#1683, #1455, #1635). Backtests keep one adjustment basis, local caches distinguish sources, single-asset caps and weekly/monthly risk use the declared settings, audits retain loss signs, grounding checks the current engine output and exact list references, and Stooq retries after a denial cooldown (#1684, #1650, #1685, #1640).

  • 2026-10-02 🛠️ Backtests and report checks: strategy-file writes retain model provenance without crashing (#1673), and Monte Carlo drawdown and Sharpe include starting capital (#1664). Report audits preserve accounting negatives and units (#1663); grounding artifacts record fired declared checks (#1661); public loader-health reports include sanitized failure reasons (#1643). Indonesian tool documentation matches the registry (#1671).

  • 2026-10-01 ✅ Data correctness and reproducible backtests: A-share adjustment conversion now refuses ambiguous one-bar edge cases (#1551); Southbound Eastmoney amounts are scaled from million HKD and rejected responses no longer look empty (#1486); Northbound fallback data distinguishes post-2024-08-19 turnover from net flow (#1484); Binance-only unpriced positions are marked incomplete without penalising other brokers (#1505); and backtest run cards record model provenance and warn when the training cutoff is unknown or outside the test window (#1618, closes #1613).

Earlier news
  • 2026-09-30 🛠️ Feishu in the Web UI, a momentum factor that read today's price, and a profit factor for runs that never lost: Feishu joins the guided channel setup, with a standalone connection test and a hot reload that closes the old WebSocket (#1572). academic_carhart_mom subtracted the 1-month return from the 12-month one, so it moved with today's close; it is now the return from 12 months ago to 1 month ago (#1578). A run with no losing trade reports its profit factor as undefined instead of 0.0, which ranked it last (#1602). Stooq's anti-bot page now stops every later request in the process, not just the log line (#1637); MCP tool results reach the agent once instead of up to four times (#1634); and the first piece of loop.py moves into its own module (#1636).

  • 2026-09-29 🚀 v0.1.16 released (Release notes, pip install -U vibe-trading-ai): 492 commits and 116 merged pull requests since 0.1.15, from 16 contributors. The theme of this cycle is a number that can show where it came from. The grounding gate no longer guesses what a number is from the words around it: the model declares each figure's role (observed, derived, proposed, cited or count), the gate checks it against the session's tool evidence, and a figure that fails is cut instead of the whole answer being refused. A backtest's own output — Sortino, turnover, weights and Monte Carlo p-values, not only Sharpe — now grounds the report written about it, and run cards cite a metric only where the saved CSV agrees. Long research runs keep what they fetched: compaction follows each model's real context window instead of a fixed 40K estimate. The missing-data sweep reached 59 more alphas. Fixed in this release, from a user's report: failed runs keep their steps and the stop message names the call that produced nothing; read_file says where it may read instead of letting the model guess paths until the no-progress stop; on Codex, mid-run instructions no longer replace the system prompt, reasoning carries between turns and the default model is gpt-6-sol; and get_market_data asks for AAPL.US rather than returning empty data for a bare US ticker. New: Argentina (BYMA), weekly and monthly bars, Bahasa Indonesia, Gildata, OpenCode, Email and WebSocket channels, IM channel setup in the Web UI, and KIS, Upbit, Toss Securities and Scalable Capital connectors, 18 brokers in all. Thanks @Shizoqua, @zeus229, @cgycorey, @shadowinlife, @lorenzozanee, @he-yufeng, @chiww, @as950118, @woshi77777stars, @Yoruxyv, @sambazhu, @0xouzm, @tingkk, @tonydo, @alanwilhelm and @modelpath-dev!

  • 2026-09-28 🛠️ Source health and connector transparency: scheduled public-source canaries report outages and data drift with bounded, credential-free probes (#1627); BaoStock socket requests now have deadlines and serialize concurrent sessions (#1615). Copilot credential lookups refresh after a short cache TTL (#1619). A generated broker matrix preserves each profile’s paper/live permissions and labels declared capabilities separately from runtime verification (#1629). Grounding and MT5 follow-up: explicit evidence symbols and exact field references are preserved; localized grouped figures retain the existing numeric tolerance (#1584, #1586, #1588). Text-only correction attempts are bounded (#1600). MT5 search uses the selected terminal and refuses ambiguous broker aliases; backtest sandboxes receive only validated attachment settings (#1597, #1598).

  • 2026-09-27 🛠️ Verifiable run cards and safer research: Run cards now show hashed backtest execution records and verified metric-to-CSV references in JSON, Markdown and Run Detail (#1612). GTJA high/low recency factors use the correct day count and consistent tie handling (#1604); India short covers check the buy-side circuit band (#1608). Token usage remains readable without exempting arbitrary credential strings (#1606), malformed MCP schemas retain their object properties (#1607), and immediate-order goal checks preserve research questions (#1605). Setup documentation now correctly identifies OpenRouter as the shipped default (#1609).

  • 2026-09-26 🛠️ More reliable indicators and trading limits: Technical indicators retain their observation date and can reuse results lost during conversation compaction (#1590, #1601). All five Qlib158 WVMA windows now use absolute returns in the numerator (#1594); Benford checks preserve the correct leading digit at numeric boundaries (#1591). An explicitly zero exposure limit stays zero (#1593), and Dhan paper orders reject fractional or invalid quantities without rounding away input precision (#1595). Invalid optional numeric environment variables fall back to defaults while explicit configuration constraints remain enforced (#1592). Runtime triggers keep the correct field defaults and subclass factory behavior (#1599).

  • 2026-09-25 🛠️ More reliable research sessions and channel diagnostics: A text column in a backtest CSV no longer discards the numeric metrics (#1579), and conversation compaction now counts reasoning content in its retained-message budget (#1582). Failed channel loads now log the actual exception (#1580); the Telegram guide clarifies that CLI and Web controls share the same API runtime (#1583). Robinhood portfolio reads reject malformed buying-power objects while keeping omitted or null values unknown (#1526). Leaving a chat also cancels pending history-scroll timers. Thanks @Shizoqua and @lorenzozanee!

  • 2026-09-24 💱 A dollar line priced as pesos, Email and WebSocket in the Web UI, and a CI break from an SDK update: BYMA and the TSX list US-dollar lines beside their home-currency ones (GGALD.BA, DLR-U.TO), and an Argentine or Canadian backtest priced them in its single peso or Canadian-dollar pool. The loaders now admit a line only in its market's currency, as LSE lines already were, and every other declared quote currency travels with the data, so an answer names the right one (#1576). Hong Kong's RMB and USD counters (80700.HK, 9834.HK), which HKEX numbers in their own code ranges, are refused in a Hong Kong backtest for the same reason and quoted in their own currency. Stock profiles carry the listing's own venue and currency beside the issuer's fundamentals (#1577), grounding and symbol search know every market the data layer routes (#1575), and technical_indicators reports volume with the unit its source declares — board lots or shares, 100× apart (#1571). Email and WebSocket join the guided channel setup, with mail-server certificates now verified and settings writes closed to cross-site pages, and a plain IMAP login is upgraded with STARTTLS before the password goes out (#1544). Fixed: an explicit provider header lost to an ambient twin under openai 3.19.2, which had turned every PR's CI red (#1568); a backtest from a microsecond-resolution source was dated 1970 (#1560); a research goal that is plainly an order is refused again (#1562); a strict-bench OOS split could leave one side empty (#1559); HRP label alignment, cross-validation label order and non-finite quant inputs (#1555, #1556, #1557, #1558); the shadow-account overtrading window (#1563); and asset growth was read day over day (#1564). Thanks @Shizoqua, @zeus229 and @shadowinlife!

  • 2026-09-23 🇦🇷 Argentine listings, a short book sized upside down, and the last half of the tail-risk gate: .BA symbols — BYMA equities and CEDEARs — route to Yahoo as their own ARS market, and the Web UI groups and labels them like any other; an Argentine backtest still fails closed until BYMA execution rules are modelled (#1543). The mean-variance and turnover-aware optimizers scored every position as if it were held long, so the strongest shorts got the least capital. Both now size on position returns, where a long and a short of two correlated names hedge each other instead of reading as correlated — on a +0.92 correlated pair the old objective put the whole book on the long, the new one splits it 0.51 / -0.49 (#1548). And a tail-risk figure now has to name its own field once a session holds more than one measure or confidence level, so an ES 95% can no longer quote the VaR 95% value under a call id (#1425). Fixed: Monte-Carlo validation annualises at the venue's bars per year instead of a hardcoded 252, so its Sharpe agrees with the rest of the same report (#1546); a futures order on a negative-price bar is no longer rejected outright (#1547); a factor's IC ratio is left unset for a negative baseline instead of reading real decay as healthy improvement (#1549); and two memories sharing a title under different types keep their own index rows and link targets (#1545). Thanks @zeus229, @Shizoqua and @he-yufeng!

  • 2026-09-22 📅 Weekly and monthly bars, and a compaction replay that could lose evidence: get_market_data and backtests take 1W and 1M (rejected since 09-20 so 1M would not fetch minute bars). Every source still serves daily bars and the period bar is built from them, dated on the last trading day of its week or month, so a 21-month review is one call of 21 bars (#1479). A price index is stamped unadjusted instead of by what its source does to a stock (#1541). A read-only tool result that context compaction removed is restored from the run's own memory instead of fetched again, capped per run, and a write empties that memory so a regenerated file is read afresh (#1488). A tail-risk figure declared with a field ref is checked against that field, so a VaR 99% quoting the 95% value is caught (#1444). QVeris refuses stock and ETF bars, whose adjustment its search-ranked pick cannot state, and quotes priced per result (#1494). Thanks @sambazhu, @zeus229, @he-yufeng, @jw232 and @cgycorey!

  • 2026-09-22 💸 A backtest that died when funding pushed cash below zero, and three more tools that read a rejected query as no data: a crypto funding debit can leave free cash below zero, and the next position the strategy wanted then found no size that fit, not even zero, so the run aborted with "planned order … exceeds available capital" (or "insufficient capital for position rebalance"). That open is now skipped and reported once as insufficient_capital, the bar's reductions still run, and a close whose loss exceeds its margin still aborts the bar as before (#1542). Block trades, margin trading and financial statements now tell Eastmoney rejecting a stale query apart from a genuinely empty answer, through the same check shareholder count, dragon-tiger and lockup expiry use. Answers in Spanish, German and other decimal-comma locales now ground 17,93 % or 1.410,00 CNY against the tool results, while two unspaced numbers like 1400,1777 stay two numbers, and a figure has to match its evidence to the precision it is written at (#1517). Thanks @turtle696966969696 for a trace reconciled to the cent, and @zeus229!

  • 2026-09-21 🔌 IM channels configured from the Web UI, and 24 alphas that emitted a value computed from a missing bar: Settings now edits each IM channel with masked secrets, a connection test on the unsaved form, and a per-channel hot apply with no restart; DingTalk and QQ get guided setups (#1520, #1529), and every adapter logs through stdlib again, so diagnostics that a {} placeholder used to swallow reach the log (#1533). In the Alpha Zoo, a comparison whose operand is NaN because its window holds a missing bar reads False and emits a constant; the #1463 sweep, which nudged the bar by a tick, could not see it. A gap-versus-gap-free check found 24 more alphas, which now mask on their inputs' reach while a correlation undefined on complete data keeps its old verdict (#1523, #1534, #1463). Data: a lockup's free_shares is the unlocking quantity, not the float it was read from (#1513); dragon-tiger seats are ranked within each listing reason (#1512); shareholder-count history returns real periods (#1518); Tencent, Eastmoney and AKShare A-share prices are labelled dividend-additive (#1497); Gildata joins the A-share chain as a token-gated source (#1474); portfolios value any ISO-4217 currency and fail one source, not the snapshot, on a missing rate (#1510); connector account shows Binance, Futu and Trading 212 balances (#1539). New: Bahasa Indonesia UI and README (#1482). Removed: the Requesty provider — point openrouter at its base URL instead. Thanks @shadowinlife, @he-yufeng, @Shizoqua, @lorenzozanee, @cgycorey, @zeus229, @sambazhu, @Yoruxyv and @jastincheis!

  • 2026-09-20 🛠️ Clearer data requests and everyday fixes: monthly 1M requests are now explicitly rejected instead of silently fetching one-minute bars (#1487); weekly/monthly support remains tracked in #1479. Welcome quick actions highlight the selected chip (#1500), DingTalk sanitizes downloaded filenames (#1506), Signal preserves text around mentions after emoji (#1478), and credit-spread tables merge equivalent 5 / 5.0 tenor columns (#1507).

  • 2026-09-19 🛠️ Data errors that looked like missing disclosures or the wrong provider: A-share shareholder counts work again after an upstream column rename; rejected queries now report the provider's error instead of claiming the stock has no disclosure (#1490). Market-data provenance now names the loader that actually served each symbol, with the matching fallback flag and adjustment label, even when the requested SDK is unavailable (#1491). QVeris no longer overwrites indicators with an end date (#1496); adjustment selection, adjusted-response parsing and billing remain tracked in #1494. Thanks @cgycorey and @lorenzozanee!

  • 2026-09-18 ✂️ A redacted answer that lost its row numbers, and one starved order counted as twenty-six: when the grounding gate released an answer with its unverified figures cut, a ranked table came back with (omitted※) where 1, 2, 3, the 12m in its headers and "3 names" in the prose had been. Every integer in a table cell counted as a measurement, and each cut figure's digits were then swept off the rest of the page. A column that numbers its rows is now structure, a plain integer beside words in a cell is read as it would be in a sentence, and the sweep never keys on a single digit; invented returns and multiples are still cut (#1471). In hold mode, the search that scales a basket down to the available cash booked a zero_size rejection on every step, so one contract the cash could not hold read as 26 lot-rounding failures; it is now one insufficient_capital (#1470). Fixed: a local: code in a backtest is served from your own dataset or refused, never filled from a network source (#1467); the event-study CAR standard error now includes the covariance between daily forecasts that share estimated parameters — with a 30-day estimation window the standardised CAR's variance on null events was 1.41–1.46 and is now 1.07–1.08 (#1466); a real historical_var / parametric_var result grounds the VaR it returned (#1464); and twenty alphas no longer fill a missing bar with a constant, while recursive smoothers skip the gap and continue under a rule that is now written down and tested (#1463). Later the same day: a plain LANGCHAIN_PROVIDER=openai setup with gpt-5.6-terra failed on its first tool call, because Chat Completions refuses function tools for the gpt-5.6 models unless the reasoning effort is none. The adapter now retries such a request once on /v1/responses, where the reasoning is kept, and remembers that route for the model (#1473). New: OpenCode Go / Zen as a built-in opencode provider that sends the x-opencode-session id the relay requires, in the compaction thread too (#1416, closes #1415). Merged: an entry memory GC archived is no longer handed to compression as well (#1450); the Patell z uses each normal-return model's own degrees of freedom (#1449); the microstructure estimators reject NaN and infinite inputs instead of returning a zero spread (#1451); a source that must never fall back to the network keeps that promise per symbol too (#1441); and a backtest checks the declared interval against the served bar spacing before annualising, so a daily file declared 1H is no longer annualised at the hourly rate and a weekly file annualises at 52 (#1432). Thanks @5gaLbt and @turtle696966969696 for the reports, and @tonydo, @Shizoqua and @chiww for the fixes!

  • 2026-09-17 🔐 A Robinhood login that reaches several accounts, and a live gate that refused every real order while its tests passed: Robinhood can now be a read-only portfolio source that reads exactly one account, picked from Robinhood's own list with nothing preselected (#1428), and live trading binds each mandate to one account the same way (#1442). The runner and the pre-trade gate had been calling Robinhood with no account and reading its replies one level too shallow, so every reconciliation aborted and every order was refused, while the tests stayed green because their fixtures used a reply shape Robinhood never sends. Positions show unpriced until the quote reply is mapped. Fixed: a swarm worker saves its message log on every exit path that writes a summary (#1439); qlib158's up- and down-day counts no longer count a missing close as a flat day (#1459); a strategy's decay check no longer reads an infinite Sharpe as healthy (#1447); and a custom alpha-zoo root no longer replaces a bundled alpha of the same name process-wide (#1468). Thanks @balu1866 for the reply shapes, and @cgycorey and @0xouzm!

  • 2026-09-16 🧪 Four numerical slips that each returned a plausible number: "low" sat in the sentiment lexicon as both a bullish and a bearish word, cancelling itself out (#1448); head-and-shoulders detection divided by a signed shoulder average, so lopsided shoulders on a negative-valued series passed the symmetry check (#1456); the options engine annualised over one bar fewer than the shared metrics, exaggerating short runs (#1458); and copula pseudo-observations ranked a missing value as the largest and gave ties arbitrary distinct ranks (#1453). Thanks @Shizoqua.

  • 2026-09-15 🧮 A grounding gate that decided what a number was from the words around it: the check every market answer passes before release used to infer whether a figure was a price, a target or a metric from a catalogue of phrasings — 65 regular expressions that grew a fix commit per wording and could give a sentence and its translation different verdicts. The model now declares what each figure is in a figures block the reader never sees (observed, derived, proposed, cited, count); the gate reads only a number's shape and checks every declaration against the session's tool results. A rejected answer gets one correction that names each failing figure with the nearest observed prints, and if it still fails it is released with only those figures cut ((略※) / (omitted※)) instead of being replaced wholesale by a canned refusal, which remains only for an identity problem or a run that observed no price. While it waits, the chat shows "Checking the figures in this answer" in all eight languages. Before release it went through three rounds of adversarial review and real model runs, which added decimal commas, year-shaped prices, untagged code fences, integer prices of instruments quoted in the thousands, prices declared as counts and unchecked numbers reaching the stream. Metadata counts and metric-name tokens no longer ground a metric, and a sentence with several metrics is no longer rejected (#1418, #1420, #1421, #1426, #1433). Thanks @zeus229, @he-yufeng and @5gaLbt!

  • 2026-09-14 🇰🇷 A-shares backtested as perpetual futures, and a swarm argument the model could set but never change: every branchless data source that serves A-shares — local, tencent, eastmoney, baostock, mootdx, sina — routed a pure A-share basket to the crypto engine, which applies none of the A-share rules (stamp tax, T+1, price limits, 100-share lots) and does charge an 8-hourly perpetual funding fee against the position. The run succeeded and its metrics were internally consistent, which is what made it dangerous; a pure A-share basket now reaches ChinaAEngine from every source (#1431). Separately, the swarm worker overwrote every tool call's run_dir with the agent workspace, so for the tools that declare it — backtest above all — the model could pass any directory and read none of it, while the error named no path. A declared run_dir is now honoured inside the workspace and refused outside it with the boundary named, and the backtest tool says which directory it checked (#1430, #1429). New: four connectors land together and the count reaches 18 — KIS (한국투자증권; a genuine 모의투자 paper sandbox on its own host, plus read-only live), Upbit (KRW crypto; paper + read-only live, capped because the exchange exposes no paper/live discriminator), Toss Securities (read-only live; the closed-order history is paged to completion and refused rather than truncated past the cap; read paths validated against a real account) and Scalable Capital's Agentic MCP as a fully read-only profile with an explicit tool allowlist and no order capability (#1407, #1408, #1409, #1417). Fixed: the shared SDK diagnostics told every broker's user to check Longbridge; they now name the affected broker's SDK or gateway in all eight languages (#1436). Thanks @chiww, @cgycorey, @as950118, @dudco and @tingkk!

  • 2026-09-13 🗂️ A broker reply in the wrong shape that counted as an empty account, and run-card diagnostics that never reached the card: the portfolio layer read positions with an empty list as the default, so a reply that never carried a positions list — an MCP response with no mapping yet, or IBKR's official MCP answering without structured positions — became a source holding nothing, and the snapshot was stored as complete. That is exactly the quietly smaller portfolio the aggregation exists to rule out, so a read without a positions list is now refused: the source shows as an error and the snapshot is marked incomplete, while a genuinely empty account ("positions": []) still reads as empty. It surfaced while reviewing a new MCP connector whose holdings are not mapped yet. Separately, the run card kept only scalar metrics, so every dict- or list-shaped diagnostic the engine writes for card readers was dropped — a reader could see how many plans were rejected, but not for which symbol or why. Those metrics now travel in a structured_metrics block, capped at 4 KiB of UTF-8 JSON per metric with anything larger named under _omitted, and render in the Run Card tab in all eight languages (#1424). Thanks @cgycorey!

  • 2026-09-12 📥 A dividend row that looks like a holding, and a number format where one misplaced separator is a thousandfold error: extraETF's CSV exports can now be read into the portfolio layer's position shape — read-only, standard library only, and failing closed on anything it cannot read without guessing (#1406, toward #1170). The Investments export becomes positions and the Transaktionen export becomes typed movements, so a Dividende row, which carries a quantity and a price of its own, is never read as a position, and a transactions file cannot pose as an empty portfolio. Numbers follow the export's German grammar exactly: 1.386,608 is 1386.608, a US-ordered 1,234.56 is refused rather than read a thousandfold off, and a value the eight-decimal wire format cannot hold is refused rather than rounded — 0,000000004 shares would otherwise have become zero. An unknown header (the error names both known column sets), an unknown transaction label, a movement with no instrument, and one instrument listed twice under a single portfolio ID are all refused, while the same ISIN under two portfolio IDs — the export's normal multi-portfolio case — stays two positions. The export carries no snapshot date, so the file's modification time is reported as source_mtime and no position claims an observation time. Nothing calls the reader yet; wiring it into the portfolio container is next. Thanks @cgycorey and @KaiLuettmann!

  • 2026-09-11 📉 Eight years of Tencent history that came back as the last two, and an evidence gate that turned away every backtest the agent ran itself: Tencent's fqkline endpoint serves the last 500 bars of a window, not the first — a CSI 300 request for 2018-01-01..2026-06-30 returns 2024-06-06..2026-06-30 — while the loader paginated forward, stepped past the window after one page and returned a tail-only series with exit code 0 and no warning. It now walks backward from the end date, re-requests an empty page once before believing it, treats an error-shaped reply as a failure, and bumps the loader cache version so series cached by the old walk are never served again (#1411, closes #1410). refresh_strategy_evidence rejected every run produced by the backtest tool, because only the agent runtime wrote the state.json its ingestion gate reads; the tool now records success, failure and timeout itself, and the gate stays fail-closed for runs nobody vouches for (#1413, closes #1412). Concurrent cold-start data requests could come back _unresolved for symbols that were perfectly available: the loader registry marked itself initialised before its imports ran, so simultaneous first callers saw it empty — seven of eight in the reporter's run (#1405, closes #1403). A swarm worker's skills: list, documented as its allowlist, is now enforced by load_skill instead of only by the prompt (#1414), and the correlation skill's Engle-Granger example, which crashed on an unnamed series, now calls the tested quantlib functions instead of its own OLS fit (#1404). One more was ours: thirteen broker config files that hold API keys — alpaca.json, zerodha.json and the rest — were missing from .gitignore though its comment claimed them, so anyone whose VIBE_TRADING_HOME is the checkout was one git add -A away from committing credentials; a test now derives the list from the code. So was a paper cancel that answered for orders it never placed: the Zerodha, Dhan and Shoonya paper connectors simulate orders locally but read the real account, and acknowledged a cancel for any order id — a live one included, which would have kept working; they now accept only the ids their simulator issued. Thanks @shadowinlife, @alanwilhelm and @Shizoqua!

  • 2026-09-10 🧾 A remediation message that named a variable nothing reads, and an adapted strategy that wore its parent's sign-off: when stooq answers with its anti-bot challenge page, the loader tells the operator how to route around it — and both halves of that advice were unreachable as printed. VIBE_TRADING_MARKET_DATA_ORDER_* is read nowhere: the registry builds MARKET_DATA_ORDER_<MARKET> and the config layer passes it to a bare os.getenv, so exporting the name as printed was a silent no-op and stooq stayed at position 2 of the US-equity chain. The other half, "drop stooq from it", is rejected outright — an override must be a permutation of the default chain, so a source can be reordered but not removed. The message now names the variable the registry actually reads and states the constraint, pinned to the registry rather than to a literal so it cannot drift again (#1402). Separately, the first half of description-driven strategy adaptation landed: an adapted strategy is a new artifact pointing at its parent through derived_from, the description may change universe, name and position sizing while the signal is copied verbatim, and the child starts with empty evidence so its numbers come from its own backtest instead of inheriting the parent's (#1391, refs #1149). Two gaps were closed on the way in, both one field over from the rule that PR was written to enforce. dataclasses.replace copies every field the call does not name, so the child came out UNVALIDATED while still carrying the parent's validator and approver — an independent sign-off worn by something that never earned it — along with an artifact_version and a model_version for code no model had generated yet. And the parent-evidence gate was reachable only from tests: register_adaptation never consulted it, so a stale or insufficient parent was written anyway, against what the substrate advertised. Its inputs are keyword-only and required now, so the check cannot be skipped by forgetting it. Thanks @chiww and @modelpath-dev!

  • 2026-09-09 🚀 v0.1.15 released (Release notes, pip install -U vibe-trading-ai): 551 commits and 162 merged pull requests since 0.1.14, from 35 contributors. The theme of this cycle is data that says what it is — and three of the biggest fixes turned out to be the same bug wearing different clothes: a default that quietly substitutes a plausible value for a missing one, which is indistinguishable downstream from a real observation. The Alpha Zoo's NaN contract moved out of the individual alphas and into the registry: an alpha that branches on an np.where comparison never sees a NaN — the comparison is False — so blanking every declared input on one bar left 84 of 462 alphas returning a number anyway, each consumed as a real signal because dropna() is what keeps a gap out of an IC. The registry now masks output wherever a declared dependency is missing on that bar, and the same sweep afterwards finds none (#1377, closes #1376). The warmup half stays open and stated rather than quietly carried: 52 alphas still emit a value inside their own declared min_warmup_bars, and a registry-level warmup mask would also blank rows for alphas that merely over-declare, so that half needs a direction call rather than 52 PRs. Same class, second instance: pandas still defaults pct_change() to forward-filling, so a missing close becomes a 0.0% return that never happened; four PRs fixed one call site each, and an exhaustive sweep found 24 sites across 10 files — two of them inside the very files those PRs were editing. Third instance: the futures loader chain named tushare and akshare, and neither implemented a futures endpoint at all, so every contract fell through to the A-share equity endpoint. AKShare now serves Chinese contracts off the keyless Sina daily endpoints — dated and main-continuous, verified live across SHFE, CFFEX, GFEX and ZCE — while a global contract returns empty and reaches local instead of being priced as an equity (#1395). Prices themselves now carry the adjustment caliber they were served under, and a source whose caliber was never measured against a live payload reports unknown rather than guessing one (#1317). Live trading fails closed in five more places: a broker position read returning an API error, error envelopes arriving mid halt-sweep, the flatten latch across runner restarts, unresolved Alpaca submissions recovered by exact client ID across a restart, and buy-limit orders sized at the worse of quote and limit on both transports. In the backtest: options signals fill on the next bar rather than the date they were computed from, short option legs hold margin and gate opens on buying power, perpetual funding settles by bar span on 8h+ intervals, an over-committed rebalance basket scales instead of aborting, and a halted position marks at the last traded close instead of entry cost. In the agent loop: a session that had already fetched fundamentals, fund flow, margin and research data had those results cleared to free context, and the de-duplication ledger went on refusing to re-fetch them — 44 blocked retries in one run, ending in "fundamental data not retrieved" for data the model had already received; results reconcile by exact call identity now, and the no-progress budget counts observations rather than activity. The final batch to land before the tag is those same three themes in miniature. CL2412.NYMEX matched no symbol pattern — the bare dated form (CL2412) matched and the venue form (ES.CME) matched, but the way a contract is actually written matched neither — so a US crude contract ran under T+1, with no shorting, settled in CNY; Tushare's own exchange spellings had the mirror-image problem on the China side, and both halves classify now (#1396, closes #1394). The pct_change() call sites were being fixed one at a time (#1397, #1398) before the exhaustive sweep found the rest, and the same default sat behind TopN selection ranking assets that had no factor observations (#1399) and sentiment orthogonalization regressing on zeros it had filled in itself (#1400). China-futures runs now state which products were priced on a generic default instead of a table entry — rb's real margin rate is 0.10, the same number as the default, and "looked up" must not read like "assumed" (closes #1393). And the ML walk-forward example purges future labels (#1392). New this cycle: UK equities (LSE .L/.IL, with SDRT modelled as a purchase-side-only duty, because charging both sides overstated every round trip by half), Zerodha Kite Connect as the fourteenth broker (capped at paper plus read-only, since Kite exposes no runtime live discriminator), a read-only multi-broker portfolio across Web, REST, CLI and agent tool where a source that fails to refresh is an error excluded from the totals rather than a stale cache, fifteen Quant Library additions (Heston, Hierarchical Risk Parity, copulas, VPIN/Roll/Amihud/Kyle microstructure, barrier options with finite-difference Greeks, ISDA CDS, Key Rate Duration, Vasicek, factor IC, Ornstein-Uhlenbeck, Ulcer/Pain, event-study tests, group-purged CV), Brazilian Portuguese as the eighth locale, read-only Nobitex and Wallex, calendar-triggered partial rebalancing, swarm replay and retry, and an offline evals harness that emits NOT_EVALUABLE rather than passing when the instrumentation it needs is absent. Thanks to all 35 contributors of this cycle!

  • 2026-09-08 🧪 An alpha that printed a number for a bar whose inputs were blank, and a spot-gold search that answered with a Swedish Bitcoin ETP: the Alpha Zoo contract preserves NaN through warmup and missing data, but an alpha that branches on an np.where comparison never sees a NaN — the comparison is False, so the ternary falls through to its constant. Blanking every declared input on one bar of a 462-alpha sweep, 84 alphas returned a number anyway, and since dropna() is what keeps a gap out of an IC, each of those constants was consumed as a real signal. The guard now sits in the registry rather than in each alpha — the output is masked to NaN wherever a declared dependency is missing on that bar — and the same sweep afterwards finds none (#1377, closes #1376). Eleven alphas were fixed for the other half of the contract, the warmup window (#1379, #1380, #1381, #1382, #1383) — and measuring that half the same way leaves 52 alphas still emitting a value inside their own declared min_warmup_bars. A registry-level warmup mask would also blank rows for alphas whose declaration is merely conservative, so that half stays open and stated rather than quietly carried. Separately, search_symbol("XAUUSD") returned exactly one candidate — VALOUR-BTC-0-SEK.ST, a Swedish Bitcoin ETP — which then locked the run's instrument identity; a metal or FX pair query is an exact instrument assertion now, keeping only candidates that name the same two legs in any spelling (#1282). Fixed: an announcement date carries no time of day, so on an intraday frame a filing became visible from the first bar of its own announcement day — a full session of lookahead. Sub-daily frames are refused now, with fundamental_subdaily="next_day" as the explicit opt-in (closes #1387). A metric claim formatted as a generic | Metric | Value | table escaped the analysis gate that rejects the same claim in prose (#1375), while the mirror-image error rejected a price word used as a formula variable — close/SMA50 > 1 was read as an asserted price (#1378, closes #1354). A pasted broker code (HK.00700, US.AAPL, SH.600519) scanned as no symbol at all, so every market tool answered identity_required (#1384). The three Archimedean copula CDFs returned wrong extreme values under strong dependence — Clayton 0.0, Gumbel 1.0, Frank inf — and are computed in log space now, verified against a 2500-digit reference across θ ∈ [-5000, 5000] (#1386, closes #1385). An MT5 order above the symbol's volume cap was silently clamped and sent, an eToro limit order with no limit price rested untriggered while reading as accepted, futu K-lines inherited an undeclared adjustment caliber, and BTCUSDT was routed through A-share rules — T+1 and no shorting, on a perpetual (#1388). Thanks @cgycorey, @Shizoqua, @he-yufeng, @Robin1987China, @laiyierjiangsu, @aminak58, and @nandofmike!

  • 2026-09-07 🪙 A 50-ounce gold order rounded down to nothing, and a currency future priced at 1/2500th of its contract size: in a cross-market backtest the composite engine dispatches every symbol through one shared sub-engine per market, but only apply_slippage refreshed that sub-engine's own active symbol — so round_size and calc_commission used whichever symbol had synced it last. A 50 oz gold position sized against FX's 1,000-unit micro lot rounded to 0, gold futures were charged the index future's rate-based fee (6.90) instead of their own flat one (20.00), and swap used the 100,000-unit standard lot rather than the 100 oz metal lot (#1370). Separately, _extract_product could not read a symbol whose product code contains a digit or ends in a letter that doubles as a month code: 6EZ4, 6JH25, M2K, MYM2503 and FESX2503 all fell through to the default multiplier of 50 — for 6E the true figure is 125,000 (#1369). Symbols now resolve against the multiplier table itself, longest match first, which also covers the dated forms (M2KZ4) and prefix collisions (SILZ4 vs SI). Fixed: four Alpha Zoo factors printed a hard ±1 or 0 through a trading halt and inside their own declared warmup, because a NaN comparison is False rather than NaN and the ternary fell through to its constant. min_warmup_bars is metadata that nothing trims, and what keeps a gap out of an IC is dropna() — so those constants were consumed as real signals (#1371, #1372, #1373, #1374). Measuring the whole zoo the same way puts 82 more alphas in the same shape; rather than one PR per alpha, that is now tracked as a registry-level guard in #1376. Strategy-discovery evidence also resolved position size once for the whole run instead of per regime, and a single unparseable benchmark cell could erase every evidence row that run produced (#1368). New: a run that keeps issuing tool calls without gaining information now stops after eight iterations with a visible recovery request, instead of spending its whole budget on path discovery — the reported case burned ~35 iterations re-guessing the same rejected paths. An identical call is refused from its second failure rather than its first, so one honest retry after a rate limit or a timeout still runs (#1363, closes #1353). Thanks @Shizoqua, @be-student, and @nandofmike!

  • 2026-09-06 🛡️ A buy limit sized at a price it would never fill at, and an audit that returned PASS having verified nothing: the MCP order gate priced a quantity order from the live quote alone, so a limit at twice the market cleared a cap sized for the quote and could fill at twice the authorized notional. It is sized at the worse of quote and limit now — the rule the direct-SDK path already used — and an unparseable limit price is denied rather than waved through (#1361). The report auditor skipped every point with no fetched value and then reported PASS because nothing had failed, certifying a report backed by no evidence at all; that fails closed now (#1362). Fixed: metrics survived a failed analysis tool, and the new exemption for attributed figures — right for a paper's Sharpe, wrong for a price this run is meant to observe — would have passed Analysts say TSLA.US last traded at 412.35 USD. with no tool call behind it (#1338, closes #1336); a cash-dividend row killed the whole trade-journal parse (#1356); compaction re-opened the de-duplication ledger by tool name, so clearing one argument variant left the rest gated (#1358); the compliance ledger refused its first append on Windows (#1261). New: Zerodha Kite Connect makes 14 brokers — read and paper only, since Kite exposes no runtime paper/live discriminator ((README truncated)

Recent activity

commits and pull requests

Recent open issues

view all

Discussions

all 23

Releases and announcements

13 total
  1. Rolls up 492 commits / 116 merged pull requests since 0.1.15, from 16 contributors. The theme of this cycle is a number that can show where it came from. The final-answer grounding gate stopped guessing what a number is from the words around it: the model declares each figure's role — observed, derived, proposed, cited or count — the gate checks that declaration against the session's tool evidence, and a figure that fails is cut from the answer instead of the whole answer being refused. A backtest's own output (its Sortino, turnover, weights and Monte Carlo p-values, not only its Sharpe) now grounds the report written about it, run cards cite a metric only where the saved CSV agrees, and the generated broker matrix states each profile's permissions as declarations rather than as runtime verification. Research runs stopped losing what they fetched: compaction follows the model's real context window instead of a fixed 40K estimate that began clearing tool results from the third step. The missing-data sweep reached 59 more alphas: 15 qlib158 count factors, 20 that filled a missing input with a constant and 24 comparison gates. Argentina (BYMA), weekly and monthly bars, Bahasa Indones

  2. Rolls up 551 commits / 162 merged pull requests since 0.1.14, from 35 contributors. The theme of this cycle is data that says what it is. A price frame now carries the adjustment caliber it was served under. A factor propagates the gaps in its inputs instead of filling them. A loader that cannot serve a market no longer claims it, and a source that fails to refresh is an error rather than a smaller portfolio. Three of those were the same bug wearing different clothes: a default that silently substitutes a plausible value for a missing one, which is indistinguishable downstream from a real observation. Three new markets, a fourteenth broker and fifteen Quant Library additions land alongside. ### Added - **UK equity market** (#1206, thanks @cgycorey) — LSE `.L` and `.IL` symbols end to end: market data, Yahoo-backed financial statements and indicators, trade-journal inference into `uk_equity`, and its own engine path. SDRT is modelled as what it actually is — a 0.5% duty on the **purchase** side only, not a symmetric round-trip cost. Charging both sides overstated the cost of every round trip by half, which is exactly the size of edge a mean-reversion strategy lives on

  3. Rolls up 272 commits / 74 merged pull requests since 0.1.13. ### Added - **Options Lab** (#1096, closes #1095, thanks @shadowinlife) — a Web UI page with four surfaces: expiry payoff diagram, spot×IV scenario P&L matrix, portfolio Greeks cards, and a live US options chain. The math is not new: two read-only HTTP endpoints wrap the existing `options_payoff` / `get_options_chain` tools, so the page and the MCP surface compute from the same test-pinned `src/quantlib/options.py`. Research only — it places no orders. - **Factor Research tab** in Run Detail (#1099, thanks @shadowinlife) — IC statistics cards, the daily IC series with its mean line, quantile-group equity curves, and an IC correlation heatmap, all rendered from the `factor_analysis` artifacts a run already writes. The new read-only `GET /runs/{run_id}/factor` endpoint scans the run's `artifacts/` tree and computes the pairwise IC time-series correlation matrix, which existed nowhere before; a `has_factor_artifacts` flag gates the tab so runs without factor output do not show an empty panel. - **Positions tab** in Run Detail (#1097, closes #1098, thanks @shadowinlife) — portfolio-book structur

  4. # v0.1.13 — The grounding repair, a finance-math layer, and institutional research `pip install -U vibe-trading-ai` **408 commits and 162 merged pull requests since [v0.1.12](https://github.com/HKUDS/Vibe-Trading/releases/tag/v0.1.12) (2026-07-22)** — the largest release to date, from 35 contributors. Full detail in [CHANGELOG.md](https://github.com/HKUDS/Vibe-Trading/blob/main/CHANGELOG.md). --- ## 🛡 The headline is a fix, not a feature The single most user-visible defect in the 0.1.12 line: a **well-formed question would spend minutes on real tool calls and then refuse to answer**, returning > 当前无法安全确认标的身份或价格证据,因此没有生成交易结论。请确认候选证券代码和交易所后再继续。 > *(cannot safely confirm instrument identity or price evidence)* The identity/grounding gate was rejecting answers it already had the evidence for. Seven independent root causes, each now fixed and covered by two-sided guard tests (healthy samples must pass; bad samples must still be blocked) plus mutation tests: | # | Root cause | Effect | |---|-----------|--------| | 1 | `.SS` and `.SH` treated as different instruments | **Every Shanghai ticker was permanently `ambiguous`** | | 2 | A+H dual listings and bare HK codes collapsed to `

  5. ## 🌀 v0.1.12 — Correlation regime timeline, three new providers, MetaTrader 5 + a reliability wave `v0.1.12` rolls up nearly two weeks of work since 0.1.11 (2026-07-10) — the headlines: a **correlation regime timeline** that answers *"when did the market fuse into one bloc, and are we in that state now?"*, **three new LLM providers** plus catalog-based endpoint resolution that makes every provider work with just a key, the **MetaTrader 5 (Exness) broker connector** (12 brokers), the **Strategy Development Manager** skill, **Binance USD-M perpetuals** with historical funding, and a broad **reliability wave** — strict-JSON/finite hardening, session/journal robustness, an 80× vectorization, and the native `zai` streaming fix. This release is available on **PyPI**, **ClawHub**, and GitHub Releases. ```bash pip install -U vibe-trading-ai # or uv tool install --reinstall vibe-trading-ai ``` ## Highlights ### 🌀 Correlation regime timeline A new additive `GET /correlation/regime` endpoint and an opt-in **"Regime timeline"** strip on the Correlation tab (#756, closes #719, thanks @ebujinovch). It reuses the same price data `/correlation` already fetches: rolling pairwise correlation

Code frequency

additions and deletions
+87.1K-87.1KWeek of 2026-03-29: +72,440 linesWeek of 2026-03-29: -3 linesWeek of 2026-04-05: +11,485 linesWeek of 2026-04-05: -893 linesWeek of 2026-04-12: +10,575 linesWeek of 2026-04-12: -1,370 linesWeek of 2026-04-19: +2,518 linesWeek of 2026-04-19: -375 linesWeek of 2026-04-26: +12,659 linesWeek of 2026-04-26: -6,497 linesWeek of 2026-05-03: +3,699 linesWeek of 2026-05-03: -439 linesWeek of 2026-05-10: +14,454 linesWeek of 2026-05-10: -1,997 linesWeek of 2026-05-17: +47,158 linesWeek of 2026-05-17: -5,360 linesWeek of 2026-05-24: +28,024 linesWeek of 2026-05-24: -1,256 linesWeek of 2026-05-31: +22,067 linesWeek of 2026-05-31: -1,969 linesWeek of 2026-06-07: +6,537 linesWeek of 2026-06-07: -608 linesWeek of 2026-06-14: +27,705 linesWeek of 2026-06-14: -990 linesWeek of 2026-06-21: +15,061 linesWeek of 2026-06-21: -6,695 linesWeek of 2026-06-28: +30,854 linesWeek of 2026-06-28: -1,859 linesWeek of 2026-07-05: +37,346 linesWeek of 2026-07-05: -17,761 linesWeek of 2026-07-12: +30,799 linesWeek of 2026-07-12: -4,556 linesWeek of 2026-07-19: +18,944 linesWeek of 2026-07-19: -3,573 linesWeek of 2026-07-26: +41,309 linesWeek of 2026-07-26: -5,857 linesWeek of 2026-08-02: +87,113 linesWeek of 2026-08-02: -3,185 linesWeek of 2026-08-09: +44,848 linesWeek of 2026-08-09: -5,119 linesWeek of 2026-08-16: +21,882 linesWeek of 2026-08-16: -2,580 linesWeek of 2026-08-23: +21,785 linesWeek of 2026-08-23: -2,118 linesWeek of 2026-08-30: +18,884 linesWeek of 2026-08-30: -2,198 linesWeek of 2026-09-06: +13,791 linesWeek of 2026-09-06: -1,215 linesWeek of 2026-09-13: +33,916 linesWeek of 2026-09-13: -12,271 linesWeek of 2026-09-20: +26,237 linesWeek of 2026-09-20: -3,690 linesWeek of 2026-09-27: +23,273 linesWeek of 2026-09-27: -4,126 linesMar 29, 2026Sep 27, 2026
+725.4K lines added, -98.6K removed over the last year.

Commits per week

last 52 weeks
2080Week of 2025-10-05: 0 commitsWeek of 2025-10-12: 0 commitsWeek of 2025-10-19: 0 commitsWeek of 2025-10-26: 0 commitsWeek of 2025-11-02: 0 commitsWeek of 2025-11-09: 0 commitsWeek of 2025-11-16: 0 commitsWeek of 2025-11-23: 0 commitsWeek of 2025-11-30: 0 commitsWeek of 2025-12-07: 0 commitsWeek of 2025-12-14: 0 commitsWeek of 2025-12-21: 0 commitsWeek of 2025-12-28: 0 commitsWeek of 2026-01-04: 0 commitsWeek of 2026-01-11: 0 commitsWeek of 2026-01-18: 0 commitsWeek of 2026-01-25: 0 commitsWeek of 2026-02-01: 0 commitsWeek of 2026-02-08: 0 commitsWeek of 2026-02-15: 0 commitsWeek of 2026-02-22: 0 commitsWeek of 2026-03-01: 0 commitsWeek of 2026-03-08: 0 commitsWeek of 2026-03-15: 0 commitsWeek of 2026-03-22: 0 commitsWeek of 2026-03-29: 3 commitsWeek of 2026-04-05: 22 commitsWeek of 2026-04-12: 21 commitsWeek of 2026-04-19: 24 commitsWeek of 2026-04-26: 22 commitsWeek of 2026-05-03: 26 commitsWeek of 2026-05-10: 38 commitsWeek of 2026-05-17: 25 commitsWeek of 2026-05-24: 27 commitsWeek of 2026-05-31: 34 commitsWeek of 2026-06-07: 27 commitsWeek of 2026-06-14: 54 commitsWeek of 2026-06-21: 35 commitsWeek of 2026-06-28: 49 commitsWeek of 2026-07-05: 78 commitsWeek of 2026-07-12: 208 commitsWeek of 2026-07-19: 147 commitsWeek of 2026-07-26: 77 commitsWeek of 2026-08-02: 123 commitsWeek of 2026-08-09: 141 commitsWeek of 2026-08-16: 144 commitsWeek of 2026-08-23: 112 commitsWeek of 2026-08-30: 121 commitsWeek of 2026-09-06: 93 commitsWeek of 2026-09-13: 129 commitsWeek of 2026-09-20: 194 commitsWeek of 2026-09-27: 69 commitsOct 5, 2025Sep 27, 2026
2K commits in the last 52 weeks.

When work happens

weekday and hour
SunMonTueWedThuFriSat036912151821Sun 0:00 — 10 commitsSun 1:00 — 13 commitsSun 2:00 — 2 commitsSun 3:00 — 3 commitsSun 4:00 — 2 commitsSun 5:00 — 3 commitsSun 6:00 — 4 commitsSun 7:00 — 1 commitsSun 8:00 — 5 commitsSun 9:00 — 2 commitsSun 10:00 — 6 commitsSun 11:00 — 20 commitsSun 12:00 — 8 commitsSun 13:00 — 10 commitsSun 14:00 — 10 commitsSun 15:00 — 19 commitsSun 16:00 — 18 commitsSun 17:00 — 6 commitsSun 18:00 — 9 commitsSun 19:00 — 17 commitsSun 20:00 — 22 commitsSun 21:00 — 17 commitsSun 22:00 — 22 commitsSun 23:00 — 18 commitsMon 0:00 — 16 commitsMon 1:00 — 5 commitsMon 2:00 — 8 commitsMon 3:00 — 8 commitsMon 4:00 — 2 commitsMon 5:00 — 4 commitsMon 6:00 — 2 commitsMon 7:00 — 3 commitsMon 8:00 — 9 commitsMon 9:00 — 11 commitsMon 10:00 — 9 commitsMon 11:00 — 14 commitsMon 12:00 — 36 commitsMon 13:00 — 10 commitsMon 14:00 — 9 commitsMon 15:00 — 27 commitsMon 16:00 — 29 commitsMon 17:00 — 26 commitsMon 18:00 — 11 commitsMon 19:00 — 15 commitsMon 20:00 — 29 commitsMon 21:00 — 9 commitsMon 22:00 — 25 commitsMon 23:00 — 11 commitsTue 0:00 — 38 commitsTue 1:00 — 16 commitsTue 2:00 — 15 commitsTue 3:00 — 3 commitsTue 4:00 — 4 commitsTue 5:00 — 4 commitsTue 6:00 — 6 commitsTue 7:00 — 2 commitsTue 8:00 — 1 commitsTue 9:00 — 12 commitsTue 10:00 — 7 commitsTue 11:00 — 24 commitsTue 12:00 — 15 commitsTue 13:00 — 10 commitsTue 14:00 — 28 commitsTue 15:00 — 30 commitsTue 16:00 — 10 commitsTue 17:00 — 21 commitsTue 18:00 — 21 commitsTue 19:00 — 6 commitsTue 20:00 — 10 commitsTue 21:00 — 33 commitsTue 22:00 — 2 commitsTue 23:00 — 10 commitsWed 0:00 — 4 commitsWed 1:00 — 12 commitsWed 2:00 — 6 commitsWed 3:00 — 2 commitsWed 4:00 — 1 commitsWed 5:00 — 0 commitsWed 6:00 — 0 commitsWed 7:00 — 3 commitsWed 8:00 — 1 commitsWed 9:00 — 1 commitsWed 10:00 — 11 commitsWed 11:00 — 17 commitsWed 12:00 — 20 commitsWed 13:00 — 7 commitsWed 14:00 — 8 commitsWed 15:00 — 31 commitsWed 16:00 — 20 commitsWed 17:00 — 11 commitsWed 18:00 — 7 commitsWed 19:00 — 7 commitsWed 20:00 — 12 commitsWed 21:00 — 19 commitsWed 22:00 — 10 commitsWed 23:00 — 7 commitsThu 0:00 — 4 commitsThu 1:00 — 6 commitsThu 2:00 — 6 commitsThu 3:00 — 4 commitsThu 4:00 — 0 commitsThu 5:00 — 1 commitsThu 6:00 — 0 commitsThu 7:00 — 5 commitsThu 8:00 — 7 commitsThu 9:00 — 3 commitsThu 10:00 — 1 commitsThu 11:00 — 37 commitsThu 12:00 — 10 commitsThu 13:00 — 64 commitsThu 14:00 — 10 commitsThu 15:00 — 17 commitsThu 16:00 — 10 commitsThu 17:00 — 14 commitsThu 18:00 — 19 commitsThu 19:00 — 42 commitsThu 20:00 — 10 commitsThu 21:00 — 15 commitsThu 22:00 — 15 commitsThu 23:00 — 8 commitsFri 0:00 — 10 commitsFri 1:00 — 10 commitsFri 2:00 — 5 commitsFri 3:00 — 9 commitsFri 4:00 — 1 commitsFri 5:00 — 1 commitsFri 6:00 — 11 commitsFri 7:00 — 26 commitsFri 8:00 — 5 commitsFri 9:00 — 5 commitsFri 10:00 — 19 commitsFri 11:00 — 8 commitsFri 12:00 — 16 commitsFri 13:00 — 16 commitsFri 14:00 — 14 commitsFri 15:00 — 28 commitsFri 16:00 — 17 commitsFri 17:00 — 14 commitsFri 18:00 — 12 commitsFri 19:00 — 5 commitsFri 20:00 — 11 commitsFri 21:00 — 41 commitsFri 22:00 — 30 commitsFri 23:00 — 12 commitsSat 0:00 — 15 commitsSat 1:00 — 13 commitsSat 2:00 — 3 commitsSat 3:00 — 4 commitsSat 4:00 — 4 commitsSat 5:00 — 1 commitsSat 6:00 — 1 commitsSat 7:00 — 12 commitsSat 8:00 — 2 commitsSat 9:00 — 18 commitsSat 10:00 — 14 commitsSat 11:00 — 22 commitsSat 12:00 — 17 commitsSat 13:00 — 15 commitsSat 14:00 — 16 commitsSat 15:00 — 14 commitsSat 16:00 — 18 commitsSat 17:00 — 29 commitsSat 18:00 — 12 commitsSat 19:00 — 9 commitsSat 20:00 — 4 commitsSat 21:00 — 21 commitsSat 22:00 — 24 commitsSat 23:00 — 7 commits
Commit volume by weekday and hour (UTC). Larger dots mean more commits.
DateListRankStars gained
Aug 9, 2026monthly#16+12,068
Aug 8, 2026monthly#16+12,068
Aug 7, 2026monthly#16+12,134
Aug 6, 2026monthly#15+12,165
Aug 5, 2026monthly#15+12,089
Aug 3, 2026monthly#13+13,093
Aug 2, 2026monthly#13+13,093
Aug 1, 2026monthly#11+13,643
Jul 31, 2026monthly#10+14,101
Jul 30, 2026monthly#11+13,918
Jul 29, 2026monthly#14+14,460
Jul 28, 2026monthly#13+14,723
Jul 27, 2026monthly#11+14,550
Jul 24, 2026daily#21+4
Jul 17, 2026daily#12+6
  • public-apis/public-apis

    A collective list of free APIs

    486.1K stars · Python

  • donnemartin/system-design-primer

    Learn how to design large-scale systems. Prep for the system design interview. Includes Anki flashcards.

    373.2K stars · Python

  • practical-tutorials/project-based-learning

    Curated list of project-based tutorials

    285.8K stars · Python

  • affaan-m/ECC

    The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.

    272.8K stars · JavaScript

  • NousResearch/hermes-agent

    The agent that grows with you

    251.2K stars · Python

  • n8n-io/n8n

    Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.

    206.7K stars · TypeScript