Releases: furic/richfolio
v1.7.0 — Multi-AI Mode (Gemini + Claude) & 3 More Languages
What's New
Multi-AI Mode — Gemini + Claude Side by Side
Richfolio is no longer Gemini-only. The analysis layer was refactored into a pluggable provider architecture, and Anthropic Claude is now a first-class second provider.
- Set one key (
GEMINI_API_KEYorANTHROPIC_API_KEY) → identical behaviour to v1.6, single-AI rendering, no surprises. - Set both keys → multi-AI mode auto-engages: providers run concurrently, scores aggregate per ticker, every email and Telegram message shows a per-AI breakdown beneath each consensus recommendation.
How aggregation works
- Consensus action via mode-of-votes with confidence-sum tiebreaker (see
src/aiAggregation.ts) - STRONG BUY requires unanimous agreement — if any provider dissents, the consensus caps at BUY. Preserves STRONG BUY's "rare, high-conviction" semantics.
- Averaged confidence drives within-tier sort, displayed prominently with an
avgtag - Agreement badge (
unanimous/majority/split) shown next to the action - Suggested buy value / limit price inherited from the highest-confidence provider that voted consensus — deterministic, no muddled averages
Graceful degradation
- If a provider throws mid-run (rate-limited, network blip, quota hit), surviving providers continue.
- If exactly one provider survives, that run renders as single-AI mode.
- If all providers fail, falls back to gap-based recommendations (today's behaviour with no AI key).
Reasoning history is now per-provider
Each AI sees only its own past convictions in the "HISTORICAL CONTEXT" prompt section. Storage schema bumped v1 → v2; existing history is dropped on first load (7 days isn't precious data).
Pluggable detailed analysis (STRONG BUY page)
The dedicated "More Details" analysis page for STRONG BUY tickers can now be generated by either provider. Default: first available. Override:
| Env var | Effect |
|---|---|
AI_DETAILED_PROVIDER=gemini |
Force Gemini |
AI_DETAILED_PROVIDER=claude |
Force Claude |
CLAUDE_MODEL=claude-haiku-4-5-20251001 |
Use Haiku for cheaper Claude calls |
New Architecture (Extensible)
Adding a third provider (OpenAI, Mistral, whatever) is now ~50 lines: implement the AIProvider interface in src/providers/, register it in src/providers/index.ts, done. The orchestrator, guard pipeline, aggregation, reasoning history, and renderers all flow through automatically — no consumer changes needed.
src/providers/
├── types.ts # AIProvider interface + canonical AIBuyRecommendation
├── prompts.ts # SDK-agnostic prompt builders
├── gemini.ts # GeminiProvider (Google @google/genai)
├── claude.ts # ClaudeProvider (Anthropic @anthropic-ai/sdk, tool-use)
└── index.ts # Provider registry — buildActiveProviders()
src/aiOrchestrator.ts # Runs active providers, applies guards, sorts
src/aiAggregation.ts # Consensus action, average, unanimity rule
3 More Languages: Japanese, Korean, Spanish
The docs site now ships in 6 languages total:
- English (default)
- 简体中文 (Simplified Chinese)
- 繁體中文 (Traditional Chinese)
- 日本語 (Japanese) — new
- 한국어 (Korean) — new
- Español (Spanish, neutral / Latin-American) — new
Language picker in the docs header was converted from inline links to a compact dropdown <select> to scale cleanly as more locales are added.
Bug Fixes
- fix(docs): removed
//comments from the language switcher inline script — Jekyll's HTML compression collapsed the script onto a single line, turning//into a runaway comment that broke the parser with "Unexpected end of input". Dropdown navigation now works in production.
Docs
- docs/api-keys.md restructured around the multi-AI mode (single/multi comparison table at top, dedicated Anthropic Claude section, removed obsolete "Using a different AI model" sub-section)
- docs/deployment.md "Add Secrets & Variables" table now lists
ANTHROPIC_API_KEY,CLAUDE_MODEL,AI_DETAILED_PROVIDER - docs/troubleshooting.md Gemini quota fix now notes Claude continues alone when both keys are set; "empty email" bullet expanded into 4 combinations
- All of the above translated to the 5 non-English locales
Upgrading
If you already had GEMINI_API_KEY set: nothing breaks, nothing changes. v1.7 is fully backward compatible with single-AI configurations.
To opt into multi-AI mode:
- Sign up at console.anthropic.com and create an API key
- Add
ANTHROPIC_API_KEYas a GitHub Secret (and to your local.env) - Optionally set
CLAUDE_MODEL=claude-haiku-4-5-20251001as a GitHub Variable for cheaper Claude calls - Optionally set
AI_DETAILED_PROVIDER=geminiorclaudeto pin who generates the STRONG BUY analysis page - Next scheduled run picks up the new env automatically — no code deploy needed
Full Changelog: v1.6.0...v1.7.0
v1.6.0 — Bond ETF Timing Signals & i18n Docs
What's New
Bond ETF Timing Signals — No More Flatline 75% BUY for BSV
The short-duration bond ETF framework (BSV, SHY, VGSH, SCHO, BIL, SHV, SGOV, ...) was previously gap-capped: any meaningful allocation gap returned a fixed 75% BUY every single day, regardless of whether today was actually a good entry. This release replaces that with a base + timing-modifiers scoring system so BSV's daily conviction reflects real entry-quality signals.
- 90-day price percentile (new on
TechnicalData.pricePercentile90d) — where today's price sits in its rolling 90-day window. Bottom 20% gets +12pts (cheap entry), top 20% gets −15pts (poor entry). - 10-year treasury 20-day change (new on
MacroIndicators.treasury10yChange20d) — bonds get cheaper when rates rise. Rising fast (>+0.15%) adds +6pts; falling fast (<−0.15%) subtracts 12pts to discourage chasing rallies. - Distribution yield (new on
QuoteData.distributionYield, from YahoosummaryDetail.yield) — high SEC yield (>4.5%) adds +3pts, low yield (<3%) subtracts 2pts. - Per-tier confidence ceilings: gap≥5% can reach 95, gap 3-5% reaches 85, gap 1-3% reaches 72. Gap<1% stays HOLD.
- No more limit-price clutter: short-duration bonds never get a
suggestedLimitPrice— the daily range is too tight for the suggestion to mean anything. - AI reason field now frames bond recommendations around percentile + rate direction, never RSI/MACD (which are noise for rate-driven instruments).
Net effect: BSV will swing from ~35% (poor entry day) up to 90%+ (great entry day — near 90-day low, rates spiking, high yield, big gap) instead of flatlining at 75% every day.
Action-Tier Sort
AI recommendations are now sorted STRONG BUY → BUY → HOLD → WAIT (with confidence descending within each tier), applied as a final pass in aiAnalyze after the guard pipeline. Previously the email/Telegram render order was confidence-only, which meant a high-confidence bond BUY could rank above a genuine equity STRONG BUY. Now equity STRONG BUYs always appear at the top.
Documentation: i18n Site
- Jekyll polyglot scaffolding for the docs site, supporting English (default), Simplified Chinese, and Traditional Chinese
- Full translations of
how-it-works.md,features.md, andreferences.mdfor both Chinese variants hreflangand canonical<link>tags emitted for each language to improve SEO- Language switcher in the header (vertically centered fix)
References
- OpenAlice promoted to #2 in the inspiration credits
- hvkshetry Medium article added
Guards
- Absolute confidence ceiling for short-duration bond ETFs raised 88 → 95 to match the equity confidence cap (
guardConfidenceSanity). The action-tier sort prevents visual displacement of equity STRONG BUYs. - Bond-cap guard now strips
suggestedLimitPrice/limitPriceReasonfor short-duration bonds (safety net in case the AI suggests one anyway). - Gap-based confidence ceiling for bonds removed — driven by the new timing modifiers instead.
Chore
- Claude Code project settings added (
.claude/settings.json) with Playwright MCP andpython3permissions
Full Changelog: v1.5.0...v1.6.0
v1.5.0 — International Currency Support
What's New
International Currency Support
- Portfolio now supports non-USD tickers (LSE, Frankfurt, and other exchanges) — configure
defaultCurrencyinconfig.jsonand holdings are automatically converted - FX rates fetched live from Yahoo Finance (
GBPUSD=Xconvention) in a single batch per run — no extra API key needed - Sub-unit fix for exchanges quoting in fractional units: GBp/GBX (LSE pence → GBP), ILA (TASE agorot), ZAc (JSE cents) automatically divided by 100
- All prices, limit orders, dividends, suggested buy values, and portfolio stats displayed in your default currency
- Multi-currency caveat shown in emails and Telegram when the portfolio spans currencies
totalPortfolioValueUSDdeprecated in favour oftotalPortfolioValue+defaultCurrencyin config
Ticker Name Tooltips
- Company full names shown as hover tooltips on ticker symbols in all emails (daily, intraday, weekly, refresh)
- Names sourced from Yahoo Finance
longNamefield
CI & Code Quality
- GitHub Actions CI now runs on all pull requests — catches type errors and formatting drift before merge
- Prettier formatting enforced across
src/andtest/ - Unit tests (63 tests via
node:test, zero dependencies) coveringformatMoney,applyFxRate, andSUB_UNIT_FIX npm test— unit tests;npm run smoke— live API smoke tests (manual)
Bug Fixes & Improvements
- Two-stage AI analysis (Observe → Decide) improves STRONG BUY consistency by separating data parsing from decision-making
- Earnings calendar guard: hard HOLD if earnings ≤3 days, cap at BUY if ≤7 days
- Guard pipeline (
guards.ts) programmatically enforces STRONG BUY criteria as a post-AI safety net - ATR (Average True Range), Stochastic %K/%D, and OBV trend added to technical indicators
- News sentiment scoring: each headline rated bullish/bearish/neutral + impact with overall per-ticker sentiment fed to AI
- Reasoning persistence: 7-day rolling history of AI conviction trends shown to Gemini each run
- Fixed STRONG BUY over-strictness and bond ETF confidence constant
Full Changelog: v1.4.0...v1.5.0
v1.4.0 — Macro Indicators & Smarter STRONG BUY
What's New
Macro Environment Context
- AI now receives real-time macro indicators (VIX, 10Y Treasury yield, S&P 500, Oil/WTI, USD/DXY) from Yahoo Finance — no extra API key needed
- Gemini writes macro-aware risk assessments instead of generic boilerplate (e.g. "elevated VIX + high yields suggest caution")
- Fed to both daily analysis and detailed STRONG BUY analysis prompts
Smarter STRONG BUY Criteria
- Price below 200-day MA added as a price-level signal — ETFs (which lack P/E data) now have a viable path to STRONG BUY without requiring near-52w-low
- Entry signals now require at least 1 price-level signal (P/E below avg, 52w position <30%, or below 200MA) — momentum signals alone no longer sufficient
- Golden cross correctly ignored when price is below 200MA (lagging artifact, not bullish)
Bond ETF Framework
- Two-tier framework: short-duration (BSV, SHY, etc.) hard-capped at BUY ≤65%; long-duration (TLT, BND, etc.) eligible for STRONG BUY at rate cycle peaks
- RSI/MACD/momentum explicitly excluded as buy signals for all bond ETFs
Bug Fixes
- Fixed 52-week position misinterpretation in detailed analysis — Gemini no longer confuses "% of annual range" with "% of 52w high"
- Fixed golden cross framing in detailed analysis when price is below both MAs
- Three-layer news filtering (financial phrases → language filter → Gemini relevance) reduces false positive headlines
Technical Indicators
- MACD (12/26/9) with bullish/bearish crossover detection
- Bollinger Bands with %B, bandwidth, and squeeze detection
- Explicit conflict resolution hierarchy (MACD for trending, Bollinger for range-bound)
- Bottom-fishing model: stricter threshold for stocks/ETFs (3+ indicators) vs crypto (2+)
Other
- Intraday alerts refocused on STRONG BUY signals only
- Baseline updated after intraday alert to prevent duplicate notifications
- Auto-generated news search terms from Yahoo Finance company names
- Docs rewritten as GitHub-first for non-technical users
Full Changelog: v1.3.0...v1.4.0
v1.3.0 — Refresh Analysis & Smarter Intraday Alerts
What's New
Refresh Analysis Mode
Re-analyze a single ticker with the latest price (including after-hours/pre-market) to get an updated limit order and analysis URL.
npm run refresh -- SMHAlso available via GitHub Actions: Run workflow → mode: refresh → ticker: SMH
- Uses Yahoo Finance
postMarketPrice/preMarketPrice(zero extra API calls) - Sends email + Telegram with updated analysis URL
- Useful when you see a STRONG BUY alert after market close and the price has moved
Smarter Intraday Alerts
Intraday alerts now focus exclusively on STRONG BUY signals:
- Upgraded to STRONG BUY — any action → STRONG BUY
- Downgraded from STRONG BUY — STRONG BUY → any other action
- Confidence changed ≥10 — while staying at STRONG BUY
Other Changes
- Fix: TradingView chart now renders correctly on the analysis page
- Fix: Detailed analysis uses Gemini Flash instead of Pro (avoids quota issues)
- Docs: Added "Who Should Use This" section to README
- Docs: Gemini free-tier quota gotcha and model swap guide
- UI: Repo icon and Google Gemini badge
Full Changelog: v1.2.0...v1.3.0
v1.2.0 — STRONG BUY Analysis Page
What's New
STRONG BUY Analysis Page
STRONG BUY tickers now include a "More Details" link in emails and Telegram messages. Clicking it opens a dedicated analysis page on GitHub Pages featuring:
- Interactive TradingView chart — 6-month candlestick with SMA50, SMA200, and RSI overlays
- Detailed buy thesis — 3-4 paragraph analysis generated by Gemini 2.5 Pro
- Risk analysis — specific risk factors to watch
- Key metrics grid — price, P/E, 52-week position, RSI, moving averages, momentum
- Fundamentals — ROE, debt/equity, margins, growth, analyst target
- Action summary — suggested investment amount, limit order price with reasoning
All data is compressed and embedded in the URL hash — no server-side logic needed. The page works offline once loaded.
Other Changes
- Fix intraday baseline — use age check instead of date string comparison
- CONFIG_JSON moved from Actions Secret to Variable for easier editing
- RECIPIENT_EMAIL moved from Actions Secret to Variable
- Cleaned up duplicate
setup.md(content already split across doc pages) - Updated screenshots, mockups, and documentation
New Files
src/detailedAnalysis.ts— Gemini 2.5 Pro call for detailed buy thesis + risk analysissrc/analysisUrl.ts— zlib compression + base64url encoding into URL hashdocs/analysis/index.html— Static analysis page (decodes URL hash client-side)
Full Changelog: v1.1.0...v1.2.0
v1.1.0 — Value Investing & Crypto Bottom-Fishing
What's New in v1.1.0
Two new AI analytical frameworks embedded into the Gemini prompt — zero additional API calls, stays within free tier. Inspired by @xingpt's AI agent skills article on BlockTempo.
New Features
- Value Investing Framework — AI rates individual stocks A–D based on five fundamental criteria: ROE > 15%, debt/equity < 50%, FCF/operating CF > 80%, positive earnings growth, and price below analyst target. Displayed as colored badges in email and Telegram
- Crypto Bottom-Fishing Model — AI detects BTC/ETH accumulation zones using four indicators: RSI < 30, volume contraction > 20%, price below 200-day MA, and death cross. 2+ triggers a bottom signal, 3+ strongly considers STRONG BUY with DCA recommendation
How It Works
Both features are prompt-only enhancements — structured analytical frameworks injected into the single Gemini call:
- Fundamental data (ROE, debt/equity, FCF, margins, growth, analyst targets) comes from Yahoo Finance's
financialDatamodule, added to the existingquoteSummarycall — zero extra API overhead - Volume change (7-day avg vs prior 30-day avg) computed from existing chart data for selling exhaustion detection
- Value ratings adjust AI confidence: A boosts ~10 points, D reduces ~10 points
- Bottom signals shown in daily email, intraday alerts, and Telegram messages
Screenshots
| Daily Brief | Intraday Alert | Weekly Rebalance |
|---|---|---|
![]() |
![]() |
![]() |
Files Changed
| File | Change |
|---|---|
src/fetchPrices.ts |
Added financialData module + 9 new QuoteData fields |
src/fetchTechnicals.ts |
Added volumeChange7d computation |
src/aiAnalysis.ts |
Extended schema, prompt with 2 frameworks |
src/email.ts |
Value rating badges + bottom signal rendering |
src/telegram.ts |
Value rating + bottom signal inline |
src/intradayCompare.ts |
Propagated new fields |
src/intradayEmail.ts |
Rendered new fields in alerts |
Upgrading
No config changes needed. Just pull the latest code — the new features activate automatically when Gemini is configured. Existing config.json and .env files work as-is.
Full Changelog: v1.0.0...v1.1.0
v1.0.0 — Technical Momentum & Limit Orders
What's New
Richfolio v1.0.0 — a zero-maintenance portfolio monitoring system with AI-powered buy signals, delivered daily via email and Telegram.
Features
- AI Buy Recommendations — Gemini 2.5 Flash analyzes valuation, allocation gaps, news sentiment, technicals, and risk
- Technical Momentum Signals — SMA50, SMA200, RSI(14), golden/death cross, momentum classification for every ticker
- Limit Order Prices — AI-suggested limit prices based on nearby support (moving averages, recent lows, round numbers)
- Allocation Gap Analysis — current vs target %, with suggested buy amounts
- Dynamic P/E Signals — trailing P/E compared against historical averages from Yahoo Finance
- ETF Overlap Detection — reduces buy priority when you hold overlapping stocks
- 52-Week Range Signals — highlights tickers near their 52w low or high
- News Digest — top headlines per ticker from NewsAPI
- Portfolio Health — weighted beta, estimated annual dividend income
- Intraday Alerts — periodic checks that alert only when buy signals strengthen vs morning brief
- Weekly Rebalancing Report — drift analysis with BUY/TRIM/OK actions
- Dual Delivery — dark-themed HTML email + condensed Telegram message
Stack
All free-tier services — $0/month to run:
| Component | Service |
|---|---|
| Prices & Fundamentals | Yahoo Finance (yahoo-finance2) |
| News | NewsAPI.org (100 req/day) |
| AI Analysis | Google Gemini 2.5 Flash (250 req/day) |
| Resend.com (3,000/month) | |
| Telegram | Telegram Bot API |
| Scheduler | GitHub Actions (cron) |
Getting Started
- Fork this repo
- Add secrets (
CONFIG_JSON,RESEND_API_KEY,RECIPIENT_EMAIL) - Run manually or wait for the daily cron (8am AEST)
See the full documentation for setup details.



