concentration_analyze
Analyzes single-stock concentration risk, quantifies drawdown exposure, and compares after-tax sell-down, hold, and hedging strategies over a three-year horizon.
Instructions
Use this when someone asks how risky a large single-stock position is, whether too much of their net worth is in one stock, whether they are over-concentrated in a single name, or how to reduce or diversify a concentrated position. Single-stock concentration risk analysis on an existing position. For standalone hedge pricing use protective_put_price; for the tax math on the option exercise or RSU vest that created the concentration, route to amt_iso_optimize / nso_calculate / rsu_sell_vs_hold first. Quantifies drawdown exposure at 30/50/70% downside, then compares three after-tax strategies over a three-year horizon (sell-down to target weight, hold, hedge with put or zero-cost collar), accounting for federal LTCG, state tax, the 3.8% Net Investment Income Tax (NIIT), and reinvestment opportunity cost. totalAssets (concentrated position + everything else) frames risk relative to the whole portfolio. Returns a top-level object with keys: concentration (position/totalAssets), riskBand (Low / Moderate / Concentrated / Highly concentrated / Extreme), isLongTermToday, longTermDate, daysUntilLongTerm, lossExposure ({drop, dollarLoss, newConcentration} for 30/50/70% drops), waitForLtInsight, schedule (yearly sales with per-year tax), hedging ({kind, protectionLevel, tenorYears, strike, putPrice, callStrike, callPrice, netPremium, sigma, riskFreeRate} - a 1-year 30%-OTM put by default, or the structure named by hedgeChoice), sectorContextLine, advisorBenchmarkLine. Example call: {positionValue: 400000, costBasis: 100000, acquisitionDate: "2022-01-01", sector: "tech_software", stateCode: "CA", filingStatus: "single", ordinaryIncome: 200000, totalAssets: 1200000, volatility: 0.45, ticker: "NVDA"}. Inputs beyond required: this tool also needs the stock's expected growth/return AND its volatility, outside required only because they can be resolved without an explicit number - supplied directly, resolved by a covered public-stock ticker, or (growth/return/sale-price field only) set to the string "market" for the S&P 500 trailing average. Every field in required is likewise a fact about the user's situation with no built-in default. Neither the growth nor the volatility field has a default or a fallback estimate: their only valid sources are the user's own figures, a covered ticker, or (growth/return/sale-price only) the "market" sentinel. A call that neither supplies nor resolves one of them returns a required-field error naming the field; a number from any other source is accepted as-is, because a syntactically valid figure passes validation with no provenance check, and it silently changes the result. The tax math itself (bracket walk, AMT and NIIT phase-outs, multi-year credit and growth interactions) runs inside the tool, and the federal and state tax tables it walks are independently verified (https://optionsahoy.com/verification). Results from multiple OptionsAhoy tools in one analysis are independent single-position calculations; integrated multi-year, multi-position optimization is available in the OptionsAhoy beta at optionsahoy.com/beta?src=mcp_multi.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| sector | Yes | Sector tag. Drives the default volatility used in the hedge-cost computation when no explicit volatility is provided (a sector-typical implied volatility). | |
| ticker | No | Optional public-stock symbol (e.g. "NVDA", "AAPL"). When set, the tool substitutes a cached trailing return for any unsupplied expected-return / sale-price field, and a cached implied vol for any unsupplied volatility. Growth and volatility come from two separate cached snapshots, so some symbols resolve only one of the two fields. A symbol not in a given table falls through to a "required field" error for exactly the field it could not resolve: pass that field explicitly, or (for the growth/return/sale-price field) pass the string "market" for the S&P 500 trailing average; never invent a number. The covered-tickers resource (resources/list) lists which symbols resolve which field. | |
| costBasis | Yes | Total cost basis of the position, USD (sum of strikes paid + ordinary-income inclusions on RSU vest / NSO exercise / disqualified ISO). Must come from the user. | |
| stateCode | Yes | Two-letter US state code. Drives state LTCG and ordinary brackets. | |
| volatility | No | Annualized volatility (sigma) of the stock as a decimal (0.72 = 72%). Pass the volatility itself, not a pre-computed drag: the tool uses it both for hedge pricing (as implied vol) and for the 3y horizon drag, derived internally (the drag formula is horizon-dependent). This value must come from the user or from a `ticker` that resolves it from the cached implied-vol table; if neither supplies it, ask the user rather than estimating one; only as a last fallback does hedge pricing use a sector-typical implied volatility. | |
| hedgeChoice | No | Optional hedge specification. When supplied, the `hedging` output block prices this exact structure (kind, protectionLevel, tenorYears, plus a short call for a collar) instead of the default 1-year 30%-OTM put; the sell-down-vs-hold schedule is unaffected. For full standalone hedge pricing (protective put / collar / put spread) use `protective_put_price`. | |
| totalAssets | Yes | Total investable portfolio in dollars (concentrated position + everything else). This value must come from the user, never inferred; if the user did not state it, ask. | |
| filingStatus | Yes | Federal filing status. Drives LTCG brackets and the NIIT MAGI threshold. | |
| positionValue | Yes | Current market value of the concentrated single-stock position, USD. Must come from the user. | |
| ordinaryIncome | Yes | Annual ordinary income before any sales, USD. Baseline for LTCG bracket determination. Must come from the user. This is taxable income after deductions, not gross wages: the engine applies no standard or itemized deduction to it. | |
| volatilityDrag | No | Alternative to `volatility`: the multiplicative price haircut already computed for the horizon. Supply this OR `volatility` (if both are given, volatilityDrag wins). This field is for a drag figure that already exists from a prior computation; the drag formula is horizon-dependent, so a figure derived for a different horizon does not carry over. Supplying `volatility` instead lets the tool derive it. | |
| acquisitionDate | Yes | Earliest acquisition date in the lot (YYYY-MM-DD). Drives the 1-year LTCG threshold and the long-term-vs-short-term tax routing. | |
| expectedMarketReturn | No | Annual after-tax-proceeds reinvestment rate. Defaults to SPY trailing CAGR for the 3-year horizon if omitted; the string "market" names that same default explicitly. | |
| expectedPositionReturn | No | Annual expected return on the concentrated stock as a decimal (0.10 = 10%), or the string "market" to use the S&P 500 trailing average when the user has no view. Required unless `ticker` resolves it from trailing CAGR. This tool has no default for it: a value not stated by the user, not resolved by a covered `ticker`, and not the "market" sentinel is outside the input contract. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| hedging | Yes | Modeled cost of a protective hedge covering the full position. Defaults to a 1-year 30%-OTM put; if a `hedgeChoice` is supplied, this block prices that structure (kind / protectionLevel / tenorYears, plus a short call for a collar). | |
| riskBand | Yes | Qualitative concentration band for the position weight. | |
| schedule | Yes | Sell-down plans over 1, 2, and 3 years; empty when the position is already at or below the target weight. | |
| longTermDate | Yes | Date the position turns long-term (acquisitionDate + 1 year). ISO 8601 date-time string. | |
| lossExposure | Yes | Dollar damage at 30/50/70% single-stock drawdowns. | |
| concentration | Yes | Position value / total assets, 0..1. | |
| isLongTermToday | Yes | True when the position already qualifies for long-term capital gains treatment. | |
| waitForLtInsight | Yes | Tax saved by waiting for long-term treatment before selling; null when already long-term or no sale is needed. | |
| daysUntilLongTerm | Yes | Days until long-term treatment; 0 when already long-term. | |
| sectorContextLine | Yes | One-line volatility/drawdown context for the chosen sector. | |
| advisorBenchmarkLine | Yes | One-line comparison of the user weight vs the common advisor 10% single-name guideline. |