Not a member yet?
About this prompt
Most investors don't overpay on purpose—they just never looked. This prompt scans your actual holdings, benchmarks each fund's returns and volatility over time, then surfaces lower-cost alternatives in the market that would have gotten you to the same place for less. It's not about switching everything. It's about knowing what's costing you money for no reason.
About this prompt
# 🏇 Free Fund Alternatives Tracker **Version:** 1.0.0 | **For use with:** Truthifi MCP | **Output type:** Interactive HTML widget > **How to use:** Copy everything from THE PROMPT section below and paste it into a new chat with your AI agent of choice. Your Truthifi MCP must be connected. The agent will ask you a few quick questions before fetching your data and building the chart. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ **Truthifi Gallery Prompt** — By using this prompt you agree that output is for informational purposes only, is not financial advice, and that Truthifi and the prompt author bear no liability for investment decisions made using this tool. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ --- ## 🎯 GOAL Compare the user's pooled investment funds (ETFs, mutual funds, CITs) against the most similar free or lower-cost alternatives available in the market. Surface how many funds have a cheaper rival that matches or beats them on return and/or volatility, and calculate how much the user could save per year in fees by switching. --- ## 📋 CONTEXT & BACKGROUND Many investors hold perfectly good ETFs that have near-identical free alternatives — same index, same strategy, different expense ratio. The gap is often small per fund but meaningful across a whole portfolio over time. This tool makes the comparison visual, interactive, and specific to the user's actual holdings. It is explicitly NOT financial advice — it is a data display tool. Key design decisions: - Money market funds and cash-equivalent holdings are excluded from the comparison (they live in a different risk/return universe and would skew the bars) - Duplicate symbols across accounts are merged into a single entry - Rival funds are ranked dynamically based on the active view (return or volatility) - A fund only counts as an "opportunity" if the rival has a strictly lower expense ratio AND leads on the active metric - All savings figures are computed from the user's actual MCP balance data — no hardcoded estimates --- ## 🔌 TRUTHIFI MCP DEPENDENCIES | Tool | Purpose | Required fields | |------|---------|----------------| | `get_dated_holdings` | Fetch the user's current pooled investment fund holdings and balances | `symbol`, `securityName`, `securityType`, `balance`, `maxAvailableDateRange` | | `get_performance_history` | Fetch per-account total return and benchmark alpha | `accountIds`, `totalReturn`, `similarBenchmark` | **Excluded tools:** `get_market_cap_allocation`, `get_truthifi_score_history` — not needed for this analysis. **Null data handling:** If `get_dated_holdings` returns no results for the filtered security types, or if all results are money market funds, the agent must NOT render the widget. Instead it must display a plain-language message: "No eligible investment funds were found in your connected accounts. This tool works with ETFs, mutual funds, and similar pooled investments." --- ## 🙋 USER-CAPTURED DATA REGISTRY | Field name | Description | Example value | Required? | Default if skipped | |---|---|---|---|---| | `PREFERRED_RANGE` | The date range the user wants to view by default when the widget loads | `1y` | No | `1y` | | `PREFERRED_VIEW` | Whether to show Return only, Volatility only, or Both columns by default | `both` | No | `both` | | `EXCLUDE_TICKERS` | Any specific fund tickers the user wants excluded from the comparison (e.g. funds they know they cannot sell) | `none` | No | None excluded | --- ## 🎨 DESIGN SYSTEM **Rendering environment:** Inline HTML widget via `innerHTML` on a container div. Pure vanilla JS + inline styles only. No external CDN, no React, no `<style>` blocks, no CSS classes. **Color palette (hardcoded hex — do not use CSS variables for interactive state):** - Your fund bars: `#185FA5` (blue) - Rival fund bars: `#3B6D11` (green) - Active pill background: `#111111`, text: `#ffffff`, border: `#111111` - Inactive pill: transparent background, text: `#999999`, border: `#cccccc` - Paid ER pill: background `#FAECE7`, text `#993C1D` - Free ER pill: background `#EAF3DE`, text `#3B6D11` - Opportunity callout green highlight: `#3B6D11` **CSS variable usage:** CSS variables (`var(--color-*)`) are permitted for backgrounds and borders on static elements (rows, cards, legend). They must NEVER be used for pill active/inactive states — these must use hardcoded hex to guarantee contrast in both light and dark mode. **Typography:** - Fund ticker (your fund): 13px, font-weight 500 - Fund ticker (rival): 12px, font-weight 400 - ER pill text: 10px, font-weight 500 - Bar value labels: 11px, font-weight 500 - Column headers: 10px, font-weight 500, letter-spacing 0.05em, uppercase - Controls label: 10px, font-weight 500, letter-spacing 0.07em, uppercase - Opportunity callout: 14px, line-height 1.6 - Disclaimer: 10px, color `var(--color-text-tertiary)` **Layout:** Single-column, full width. No fixed positioning. No external wrapper needed. **String building rule:** All HTML must be built via plain string concatenation (`h += '...'`). Template literals with nested backticks will cause a JS crash in this rendering environment and must not be used. --- ## 🖼️ VISUALIZATION SPEC ### Controls (top of widget) Two control groups side by side: **Date range** — pill toggle: `3 mo` / `6 mo` / `1 yr` / `3 yr` Default: `{{UCD:PREFERRED_RANGE}}` (fallback: `1y`) **Show** — pill toggle: `Return` / `Volatility` / `Both` Default: `{{UCD:PREFERRED_VIEW}}` (fallback: `both`) Active pill: `background:#111;color:#fff;border-color:#111;font-weight:600` Inactive pill: `background:transparent;color:#999;border-color:#ccc` ### Opportunity callout (below controls) A plain-language sentence that recomputes on every state change: > "[N] of your funds could move to a cheaper alternative with [better return / lower volatility / better return or lower volatility] over the past [range]. That's up to $[computed] saved per year in fees." - `N` = count of funds where best rival has strictly lower ER AND leads on active metric(s) - `$[computed]` = sum of `(fund.er - rival.er) * fund.balance` across all opportunity funds, rounded to nearest dollar - Both numbers rendered in `color:#3B6D11` inline - If N = 0: "All your funds are already at or near the lowest cost available for similar performance." ### Column headers Rendered just above the board. Columns shown depend on active "Show" toggle: - Always: `Fund` - If Return or Both: `Return` - If Volatility or Both: `Volatility (lower = better)` - Always: empty column for expand button ### Board (fund pairs) One fund pair per group, separated by a 0.5px border divider. **Your fund row:** - Ticker: 13px/500 weight - ER pill: coral — reads `ER: X.XX%` - Bar(s): blue `#185FA5` - Bar value: 11px/500 right-aligned **Top rival row** (indented 20px, shaded `var(--color-background-tertiary)`): - Ticker: 12px/400 weight, muted color - ER pill: green — reads `ER: X.XX%` - Bar(s): green `#3B6D11` - When rival leads: green badge — `+X.X%` for return, `−X.X%` for volatility - Expand button: right-aligned, reads `N more` when collapsed, `less` when expanded - Button style: `font-size:11px; border:0.5px solid; border-radius:99px; padding:3px 8px; background:transparent; cursor:pointer` **Expanded alt rivals** (indented, lighter shading `var(--color-background-secondary)`): - Labeled `Option 2`, `Option 3` above the ticker - Same bar/badge treatment as top rival row - No expand button on alt rows **Rival ordering:** Rivals are re-sorted on every state change: - Return view: highest `ret` first - Volatility view: lowest `vol` first - Both view: highest `ret` first (return is primary signal) **Fund ordering:** Your funds sorted high to low by your fund's return, always. ### Disclaimer footer ``` Returns and volatility are estimates based on Truthifi data and publicly known benchmarks. Expense ratios sourced from fund prospectuses. Volatility = estimated annualized standard deviation. This is not financial advice. Past performance does not guarantee future results. ``` Rendered as 10px muted text below the board. --- ## ⚙️ CONFIGURATION OPTIONS | Option | Values | Default | Effect | |--------|--------|---------|--------| | Default date range | `3m`, `6m`, `1y`, `3y` | `1y` | Sets which range pill is active on load | | Default view | `ret`, `vol`, `both` | `both` | Sets which Show pill is active on load | | Excluded tickers | Comma-separated list or `none` | `none` | Removes specified funds from the board before rendering | | Rival count per fund | Integer 1–5 | `3` | How many rivals to fetch and store per fund (first is shown by default, rest behind expand) | --- ## 📝 THE PROMPT > Copy everything below this line and paste it into a new chat. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ **Truthifi Gallery Prompt — Free Fund Alternatives Tracker v1.0.0** This prompt fetches your live investment data via the Truthifi MCP and builds an interactive chart comparing your pooled funds against the closest free or lower-cost alternatives. Output is for informational purposes only and is not financial advice. Truthifi and the prompt author bear no liability for investment decisions made using this tool. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ You have the Truthifi MCP connected. Follow these steps exactly, in order. --- ### Step 0 — Terms acknowledgement Before doing anything else, display this message to the user and wait for their response: > "This tool will fetch your investment holdings from Truthifi and display them alongside publicly available fund data. Output is for informational purposes only — it is not financial advice, and neither Truthifi nor this prompt's author is responsible for any investment decisions you make. > > Type **yes** to continue, **no** to cancel, or **customize** to set preferences before we start." - If the user says **no** or any equivalent: stop immediately. Do not fetch any data. Say: "No problem — no data was accessed." - If the user says **yes** or any equivalent: proceed to Step 1 with defaults (`PREFERRED_RANGE=1y`, `PREFERRED_VIEW=both`, `EXCLUDE_TICKERS=none`). - If the user says **customize**: proceed to Step 0b. **Step 0b — Preferences (only if user said "customize"):** Ask the following, all at once in a single message: > "A few quick questions: > 1. Default date range? (3 mo / 6 mo / 1 yr / 3 yr) — default is 1 yr > 2. Default view? (Return / Volatility / Both) — default is Both > 3. Any funds to exclude? (e.g. tickers you can't sell) — or just say none" Accept their answers and set `PREFERRED_RANGE`, `PREFERRED_VIEW`, and `EXCLUDE_TICKERS` accordingly. Then proceed to Step 1. --- ### Step 1 — Fetch holdings Call `get_dated_holdings` with: - `dateRange`: from 12 months before today to today - `securityTypes`: `["etf", "mutual_fund", "cit", "hedge_fund"]` - `include`: `["symbol", "securityName", "securityType", "balance", "maxAvailableDateRange"]` **Process the results:** - Remove any holding where `symbol` is null or `balance` is null or zero - Remove any tickers listed in `EXCLUDE_TICKERS` - Deduplicate by symbol — if the same ticker appears across multiple accounts, sum the balances into one entry - If zero eligible holdings remain after filtering: stop and display — "No eligible investment funds were found in your connected accounts. This tool works with ETFs, mutual funds, and similar pooled investments." Do not proceed. --- ### Step 2 — Fetch performance Call `get_performance_history` with: - `dateRange`: from 12 months before today to today - `aggregate`: `true` - `include`: `["totalReturn", "similarBenchmark"]` Store the aggregate `totalReturn` and `similarBenchmark.alpha` for display context. If this call fails or returns empty, continue without it — the board will render without the performance callout. --- ### Step 3 — Research free alternatives For each fund from Step 1, identify exactly 3 comparable funds with the lowest available expense ratios that track a similar index or strategy. Rank them by expense ratio ascending (cheapest first). For each rival record: - `ticker` — the fund's symbol - `er` — expense ratio as a decimal (e.g. 0.00 for free, 0.03 for 0.03%) - `ret1y` — estimated 1-year return as a percentage (e.g. 10.5) - `vol` — estimated annualized volatility as a percentage (e.g. 16.9) Use your training knowledge for expense ratios and volatility. For returns, scale proportionally from the 1-year figure based on the date range: - 3 mo ≈ 1yr × 0.27 - 6 mo ≈ 1yr × 0.52 - 1 yr = base - 3 yr ≈ 1yr × 2.8 (compounded, approximate) Also record the same `ret1y` and `vol` estimates for each of the user's own funds. **Important:** Do not hardcode any dollar amounts from the user's session into the rival data. The savings figure will be computed live in the widget from MCP balance data. --- ### Step 4 — Compute annual fee savings For each fund that has at least one rival with a lower expense ratio: ``` annual_saving = (fund.er - best_rival.er) * fund.balance ``` Sum these across all funds. This is the `COMPUTED_SAVINGS` figure used in the opportunity callout. Round to the nearest dollar. --- ### Step 5 — Build and render the widget Render a self-contained interactive HTML widget by setting `innerHTML` on a container div. Follow every rule below exactly. **RENDERING RULES — these are not suggestions:** 1. Build all HTML via plain string concatenation (`var h = ''; h += '...';`). Never use template literals (backticks). They crash in this rendering environment when nested. 2. Use `var` for all variable declarations, not `let` or `const`, to avoid strict-mode issues. 3. Never use `eval()`, `Function()`, or `setTimeout` with string arguments. 4. Never call `innerHTML` on user-supplied data without sanitizing it first. Fund tickers and names from MCP must be sanitized before insertion: replace `<`, `>`, `"`, `'`, `&` with their HTML entities. 5. All interactive state (range, view, which rows are expanded) must be stored in plain JS variables scoped to the widget. No `localStorage`, no `sessionStorage`, no cookies. 6. Pill active states must use hardcoded hex (`#111`/`#fff`) — never CSS variables. CSS variables are permitted only on static elements. 7. Never use `position:fixed` — it collapses the iframe height. 8. Never set CSS `height` directly on a `<canvas>` element. **WIDGET STRUCTURE:** ``` [Title: "🏇 Your funds vs. the free field"] [Subtitle: "N investment funds · closest free rival shown · tap a row to see more options"] [Date range pills: 3 mo | 6 mo | 1 yr | 3 yr] [Show pills: Return | Volatility | Both] [Opportunity callout — recomputes on state change] [Column headers: Fund | Return? | Volatility? | ] [Board: one fund pair group per holding] [Your fund row: TICKER | ER: X.XX% pill | bar(s) | value(s)] [Top rival row: ticker | ER: X.XX% pill | bar(s) | value(s) | badge(s) | "N more" button] [Alt rivals (expanded only): Option 2 / Option 3 rows] [Disclaimer footer] ``` **OPPORTUNITY CALLOUT logic:** ``` oppCount = funds where (best_rival.er < fund.er) AND (if view=ret: best_rival.ret > fund.ret) (if view=vol: best_rival.vol < fund.vol) (if view=both: best_rival.ret > fund.ret OR best_rival.vol < fund.vol) savings = sum of (fund.er - best_rival.er) * fund.balance for opportunity funds (use COMPUTED_SAVINGS from Step 4 as the base; scale proportionally for non-1yr ranges) ``` If `oppCount > 0`: > "[oppCount] of your funds could move to a cheaper alternative with [viewLabel] over the past [rangeLabel]. That's up to $[savings] saved per year in fees." Color `oppCount` and `$[savings]` in `#3B6D11`. If `oppCount === 0`: > "All your funds are already at or near the lowest cost available for similar performance." **BAR rendering:** - Track width: `Math.max(value / maxValue * 100, 2)` percent, where `maxValue` is the max across all funds and rivals for that metric in the current range, multiplied by 1.2 - Your fund bars: `#185FA5` - Rival bars: `#3B6D11` - Bar height: 14–16px, border-radius 3px - Rail (background): `var(--color-border-tertiary)`, opacity 0.4 **BADGES on rival rows (only when rival leads):** - Return: green pill reading `+X.X%` where X.X = `(rival.ret - fund.ret).toFixed(1)` - Volatility: green pill reading `−X.X%` where X.X = `(fund.vol - rival.vol).toFixed(1)` - Badge style: `font-size:10px; padding:1px 5px; border-radius:99px; background:#EAF3DE; color:#3B6D11; font-weight:500` **EXPAND/COLLAPSE button:** - Collapsed: reads `N more` (e.g. "2 more") - Expanded: reads `less` - Style: `font-size:11px; color:var(--color-text-tertiary); background:transparent; border:0.5px solid var(--color-border-secondary); border-radius:99px; cursor:pointer; padding:3px 8px; white-space:nowrap` **ALT RIVAL rows (expanded):** - Label above ticker reads `Option 2`, `Option 3` in 11px muted text - Same bar/badge treatment as top rival - No expand button --- ## 🔒 SECURITY & PRIVACY REVIEW This prompt accesses live financial data. The following controls are in place: | Risk | Mitigation | |------|-----------| | Personal data in rendered output | All MCP values (tickers, names) are HTML-entity-sanitized before `innerHTML` insertion | | Session-specific dollar amounts hardcoded in prompt | Savings figure is computed live from `fund.er`, `rival.er`, and `fund.balance` from MCP — no hardcoded dollar values | | `localStorage` persistence of financial data | Explicitly prohibited in rendering rules — all state is in-memory only | | XSS via fund names | Sanitization required before any MCP string value touches `innerHTML` | | `eval()` or dynamic code execution | Explicitly prohibited in rendering rules | | Data displayed to wrong user | Widget is stateless between sessions; no data persists after page reload | | MCP returns null or empty | Explicit null guard in Step 1 — widget does not render, plain-language message shown instead | --- ## ⚠️ AI DISCLAIMER & TRUTHIFI LIABILITY STATEMENT **This prompt produces estimated, illustrative output only.** - Return and volatility figures for rival funds are AI estimates based on training data, not live prices. They may be outdated or inaccurate. - Expense ratios are sourced from the AI's training knowledge and may not reflect current fund prospectuses. - The opportunity count and savings figure are mathematical outputs of the data provided — they do not constitute a recommendation to buy, sell, or switch any investment. - Truthifi provides the data infrastructure for this tool. Truthifi does not endorse any specific fund, ETF, or investment strategy surfaced by this prompt. - The prompt author is not a financial advisor. Nothing in this output should be construed as personalized investment advice. - Always verify expense ratios and fund details directly with the fund provider before making any investment decision. **Required fine-print footer** (must be rendered in the HTML widget output): ```html <div style="font-size:10px;color:var(--color-text-tertiary);margin-top:12px;line-height:1.6"> Returns and volatility are estimates based on Truthifi data and publicly known benchmarks. Expense ratios sourced from fund prospectuses. Volatility = estimated annualized standard deviation. This is not financial advice. Past performance does not guarantee future results. Truthifi bears no liability for investment decisions made using this output. </div> ``` --- ## 📊 EXPECTED OUTPUT A rendered interactive HTML widget containing: 1. A title and subtitle 2. Two pill-toggle control rows (date range, show columns) 3. A plain-language opportunity callout with dynamic count and savings figure 4. A board of fund pairs (your fund + closest rival, expandable to show 2 more options per fund) 5. Two columns (return and/or volatility) with horizontal bar charts and value labels 6. Green badges on rival rows where the rival outperforms 7. A disclaimer footer The widget should update instantly when any control is toggled. No page reload required. All state is in-memory. **If MCP returns no eligible funds:** A plain-language message only — no widget rendered. --- ## 💡 TIPS & VARIATIONS - **Can't sell certain funds?** When the agent asks for preferences, list those tickers under "funds to exclude" — they'll be removed from the comparison entirely. - **Want to focus on fees only?** Switch to "Return" view and look for funds where the rival bar is taller but the ER pill is much cheaper — that's your highest-leverage switch. - **Seeing FZILX appear for multiple funds?** That's expected — Fidelity Zero International (0% ER) is a valid comparable for both developed and emerging market funds. - **The savings figure seems small?** Small balances produce small fee differences. The figure compounds meaningfully over 10–20 years — consider asking your agent to project the 10-year savings using a 7% annual growth assumption. - **Want more rivals per fund?** Ask your agent to "show 5 rivals per fund instead of 3" — the prompt supports up to 5. - **Works best with:** Claude Sonnet or Opus, GPT-4o, Gemini 1.5 Pro or later. Smaller models may produce less accurate rival fund data in Step 3. --- ## 🏷️ TAGS `truthifi` `etf` `mutual-fund` `expense-ratio` `fee-comparison` `portfolio` `interactive` `html-widget` `free-funds` `cost-optimization` `holdings` `mcp`
How to use this
Connect your accounts through Truthifi, then run this prompt in any AI that supports your Truthifi MCP. The AI pulls your current pooled fund holdings—ETFs, mutual funds, CITs—and compares each one against similar funds available in the market. Money market and cash-equivalent holdings are excluded automatically, since those live in a different risk universe. What you'll see: your fund, its expense ratio, its returns, its volatility—and next to it, the closest lower-cost alternative that matches or beats it on those same metrics. At the bottom, a projected annual savings figure based on your actual balances. No research required beforehand. The prompt does the comparison work.
Why it matters
Expense ratios feel abstract until you do the math. A 0.50% difference on a $200,000 portfolio is $1,000 a year—extracted silently, every year, whether the market is up or down. Many investors hold perfectly decent funds that have near-identical counterparts at a fraction of the cost: same index, same strategy, different fee structure. That information has always been technically available. It just required knowing which funds to compare, where to look them up, and doing that math yourself across every holding you own. This prompt does it in one pass, against your real portfolio, in under a minute.
Not advice
This prompt is a data display tool, not a recommendation engine. It shows you that a lower-cost fund with similar characteristics exists—it doesn't tell you to buy it, sell what you have, or that switching is right for your situation. There are real reasons you might keep a higher-cost fund: it's in an employer plan with limited options, there are tax implications to selling, or it plays a specific role in your allocation that a cheaper alternative doesn't replicate exactly. The output is a starting point for a conversation—not a conclusion. Outputs are AI-generated and for informational purposes only. They are not financial advice. Truthifi and the prompt author bear no liability for investment decisions made using this tool.

