Skip to main content
Glama
Finance Toolkit

Finance Toolkit

portfolio_performance

Read-onlyIdempotent

Calculate period-by-period returns for each position and the overall portfolio, helping compare holdings and track performance over time.

Instructions

The value and returns of a portfolio over time, built from one of: transactions (a list of trades, e.g. [{'date': '2023-01-03', 'ticker': 'AAPL', 'volume': 10, 'price': 125.1}]; volume negative for a sale, price optional (the closing price of the day), costs and currency optional), holdings ({'AAPL': 10, 'MSFT': 5}, bought at the close of start_date), weights ({'VTI': 0.6, 'BND': 0.4}, investing initial_value on start_date and rebalancing as rebalancing= says) or preset (a classic portfolio such as '60/40', 'All Weather' or 'Permanent'; get_presets lists them). get_portfolio_overview: per position and for the Portfolio the volume, average purchase price, invested amount, latest value, return, dividends, weight, volatility, beta and alpha against the benchmark. get_portfolio_performance (period=): the return per period of each position and the Portfolio. get_positions_overview: per day the volume, invested amount, value, cumulative return and weights of each position (use limit=-5 for the latest days). get_transactions_overview (pnl_method='FIFO'|'LIFO'|'AVERAGE'): each trade with its value, return and profit and loss. get_transactions_performance (period=): how the units bought in each period did against the same purchases of the benchmark. get_money_weighted_return: the annual money-weighted return (XIRR) per position and for the Portfolio. Prices are valued in one currency (currency=, by default the currency most of the portfolio trades in). Returns, weights and rates are decimals.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "indicator": "<indicator>"
    },
    "name": "portfolio_performance"
  }
}

Input Schema

NameRequiredDescriptionDefault
limitNoThe rows to return, like head and tail: 5 for the first five, -5 for the last five (the most recent of a time series). A table with its periods as columns (financial statements, ratios) keeps its first or last periods instead, and rows per ticker (an earnings calendar) are selected per ticker. For ETF holdings the largest (or, negative, the smallest) by weight, and for a list (e.g. news or a screener) its length. 0 returns every row.
periodNoObservation frequency, e.g. 'daily', 'weekly', 'monthly', 'quarterly', or 'annual' (supported values differ per method).
presetNoA classic portfolio by name, e.g. '60/40', 'All Weather', 'Permanent', 'Golden Butterfly' or 'Three Fund' (get_presets lists them all).
weightsNoThe target weight per ticker, e.g. {'VTI': 0.6, 'BND': 0.4} or 'VTI:0.6, BND:0.4': initial_value is invested on start_date and brought back to these weights as rebalancing says, with the dividends reinvested.
currencyNoThe currency the portfolio is valued in, e.g. 'USD' or 'EUR'; prices in other currencies are converted at each day's rate. Defaults to the currency most of the portfolio trades in.
holdingsNoThe shares held per ticker, e.g. {'AAPL': 10, 'MSFT': 5} or 'AAPL:10, MSFT:5', bought at the close of start_date.
indicatorYesName of the specific metric to calculate, one of the listed values. Required — search_metrics finds the indicator (and its tool) for a metric by name.
pnl_methodNoThe method for calculating profit & loss. Options are: 'FIFO' (First In, First Out), 'LIFO' (Last In, First Out), or 'AVERAGE'.FIFO
start_dateNoWhen holdings, weights or a preset are invested, YYYY-MM-DD; left empty, ten years ago for weights and presets and five years ago for holdings. Transactions start on their first date.
rebalancingNoHow often weights or a preset return to their weights: 'none', 'monthly', 'quarterly' or 'yearly'. Defaults to quarterly (a preset: its own frequency).
show_columnsNoComma-separated names to filter the output. For historical data use the key names visible in any response record (e.g. 'Close,Volume,Return'). For financial statements use the 'metric' field values from the response (e.g. 'Revenue,Net Income,EBITDA'). Call the tool once without this parameter to see all available names, then repeat with show_columns to reduce response size and token usage.
transactionsNoThe trades of the portfolio as a list, e.g. [{'date': '2023-01-03', 'ticker': 'AAPL', 'volume': 10, 'price': 125.1}, {'date': '2024-06-03', 'ticker': 'AAPL', 'volume': -5, 'price': 194.0}]. volume is negative for a sale; price (for every trade or none: the close of the day), costs (negative) and currency are optional. At most 1000 trades.
initial_valueNoThe amount invested in weights or a preset. Defaults to 10,000.
benchmark_tickerNoTicker used as the market benchmark, e.g. 'SPY' or '^GSPC'; 'None' for no benchmark.SPY
include_portfolioNoA boolean flag indicating whether the portfolio itself should be included in the overview.
exclude_sold_positionsNoA flag indicating whether to exclude sold positions.

Output Schema

NameRequiredDescriptionDefault
resultYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changedv2.3.2
    • changedInput schema / properties / limit / description
      Previous value: -"The rows to return, like head and tail: 5 for the first five, -5 for the last five (the most recent of a time series). A table with its periods as columns (financial statements, ratios) keeps its first or last periods instead. For ETF holdings the largest (or, negative, the smallest) by weight, and for a list (e.g. news or a screener) its length. 0 returns every row."New value: +"The rows to return, like head and tail: 5 for the first five, -5 for the last five (the most recent of a time series). A table with its periods as columns (financial statements, ratios) keeps its first or last periods instead, and rows per ticker (an earnings calendar) are selected per ticker. For ETF holdings the largest (or, negative, the smallest) by weight, and for a list (e.g. news or a screener) its length. 0 returns every row."
  2. Addedv2.3.1

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, openWorldHint and idempotentHint, but the description adds real operational context: a hard cap of 1000 trades, default initial_value of 10,000, default start dates of ten/five years ago, quarterly default rebalancing, SPY default benchmark, and a note that returns/weights/rates are decimals. It stops short of describing response shape or computation cost, which is acceptable given an output schema exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded, but the body is a single dense block of nested parentheticals and semicolons that is hard to scan, and the indicator enumeration would read far better as a list. Most sentences carry information, yet the packaging undercuts it.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 16-parameter router tool with an output schema, the description covers the input modes, per-indicator outputs, currency handling, benchmarks and key defaults. What is missing is any disambiguation against sibling tools and any cue about which indicator to pick given a user goal.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaning the schema does not: the four portfolio sources are mutually exclusive ('one of'), sale volume is negative, price must be given for every trade or none, and holdings are bought at the close of start_date. These relationships and constraints are genuine added semantics rather than restatement.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb-and-resource statement ('The value and returns of a portfolio over time') and then enumerates the exact indicator values this tool can compute, so an agent knows precisely what comes back. It does not, however, differentiate this tool from the sibling 'portfolio' or 'performance' tools, leaving the agent to guess which entry point to use.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the portfolio can be 'built from one of' transactions, holdings, weights or preset, and points to get_presets and search_metrics for discovery of related values. That is implied construction guidance rather than explicit when-to-use guidance: there is no statement about when this tool is preferable to the sibling 'portfolio' tool, and no exclusion conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.