Stock Averager API
The maths behind every calculator on this site, available as JSON. Stateless, unauthenticated, and deterministic — you supply the numbers, it returns the arithmetic. Nothing is stored.
Getting started
Every operation is a POST with a JSON body. There is no authentication, no API key and no signup. Responses are application/json; errors are RFC 9457 problem details.
curl -X POST https://www.stockaverager.com/api/v1/cagr \
-H "Content-Type: application/json" \
-d '{"initialValue": 12000, "finalValue": 31000, "years": 7}'When to use this API
Good fit
- Working out a position's new average cost, cost basis or break-even including fees
- Projecting a monthly plan, a lump sum, or a withdrawal schedule at an assumed return
- Turning a start and end value into a comparable annualised rate
- Pricing a single option and reading its Delta, Gamma, Theta and Vega
Wrong tool
- Quotes, tickers or historical prices — there is no market data here at all
- Placing trades, tracking a portfolio, or reading account data
- Personalised financial or tax advice — see the disclaimer
- Jurisdiction-exact tax figures
Authentication and limits
None. The API is public and unauthenticated because every operation is a pure function over numbers you send — there is no account, no stored data and no per-caller state to protect. CORS is open, so browser-based clients can call it directly. There is no enforced rate limit today; please keep to roughly 60 requests a minute. If that has to change, it will be announced on this page before it is enforced.
Endpoints
8 operations. Each has a stable operationId, typed parameters and a response schema, so the spec can be loaded directly as LLM function-calling tool definitions.
/api/v1/average-downPositionShares needed to reach a target average price
operationId: calculateAverageDown
Given an existing position and the current market price, returns how many additional shares to buy to bring the average cost down to a target, and the resulting position. The target must sit strictly between the current price and the original price — no share count reaches an average below the price you are buying at.
Interactive equivalent: /tools/stock-averager
Request body
| Field | Type | Constraints | Description |
|---|---|---|---|
| shares | number | > 0 | Shares currently held. |
| originalPrice | number | > 0 | Average price already paid per share. |
| currentPrice | number | > 0 | Current market price per share. |
| targetAveragePrice | number | > 0 | Average price per share you want to reach. |
Result fields
| Field | Type | Constraints | Description |
|---|---|---|---|
| additionalShares | number | — | Shares to buy at currentPrice to reach the target average. |
| additionalInvestment | number | — | Cash required for those shares. |
| newTotalShares | number | — | Shares held afterwards. |
| newTotalInvestment | number | — | Total cash invested afterwards. |
| newAveragePrice | number | — | Resulting average cost per share. |
Example
curl -X POST https://www.stockaverager.com/api/v1/average-down \
-H "Content-Type: application/json" \
-d '{"shares":100,"originalPrice":80,"currentPrice":50,"targetAveragePrice":65}'/api/v1/cost-basisPositionAverage cost basis across purchase lots
operationId: calculateCostBasis
Average-cost basis for a position built from several purchases, including per-lot fees. Use this before computing a gain, a break-even or a tax liability on a position bought in tranches.
Interactive equivalent: /tools/stock-averager/cost-basis-calculator
Request body
| Field | Type | Constraints | Description |
|---|---|---|---|
| lots | array of objects | ≥ 1 item(s), ≤ 500 items | One entry per purchase lot, in any order. |
Result fields
| Field | Type | Constraints | Description |
|---|---|---|---|
| totalShares | number | — | Shares held across every lot. |
| totalInvested | number | — | Cash invested across every lot, fees included. |
| averageCostPerShare | number | — | Cost basis per share. |
Example
curl -X POST https://www.stockaverager.com/api/v1/cost-basis \
-H "Content-Type: application/json" \
-d '{"lots":[{"shares":100,"price":50,"fees":0},{"shares":100,"price":50,"fees":0}]}'/api/v1/sipProjectionFuture value of a monthly investment plan
operationId: calculateSip
Compounds a fixed monthly contribution at an assumed annual return. The return is an assumption you supply, not a forecast — no market data is involved.
Interactive equivalent: /tools/sip-calculator
Request body
| Field | Type | Constraints | Description |
|---|---|---|---|
| monthlyInvestment | number | > 0 | Amount invested every month. |
| expectedAnnualReturn | number | > 0, ≤ 50 | Assumed annual return, as a percentage. |
| years | number | > 0, ≤ 50 | Contribution period in years. |
Result fields
| Field | Type | Constraints | Description |
|---|---|---|---|
| futureValue | number | — | Projected value at the end of the period. |
| totalInvestment | number | — | Sum of every contribution. |
| totalReturns | number | — | futureValue minus totalInvestment. |
Example
curl -X POST https://www.stockaverager.com/api/v1/sip \
-H "Content-Type: application/json" \
-d '{"monthlyInvestment":500,"expectedAnnualReturn":12,"years":10}'/api/v1/lumpsumProjectionFuture value of a one-time investment
operationId: calculateLumpsum
Compounds a single deposit at an assumed annual return and returns the year-by-year path. Use calculateSip instead when money goes in on a schedule.
Interactive equivalent: /tools/lumpsum-calculator
Request body
| Field | Type | Constraints | Description |
|---|---|---|---|
| amount | number | > 0 | Amount invested once, up front. |
| expectedAnnualReturn | number | > 0, ≤ 50 | Assumed annual return, as a percentage. |
| years | integer | > 0, ≤ 50 | Holding period in whole years. |
Result fields
| Field | Type | Constraints | Description |
|---|---|---|---|
| futureValue | number | — | Projected value at the end of the period. |
| totalReturns | number | — | futureValue minus the amount invested. |
| wealthGainPercent | number | — | Total return as a percentage of the amount invested. |
| yearlyBreakdown | array of objects | — | Value and cumulative return at the end of each year, in order. |
Example
curl -X POST https://www.stockaverager.com/api/v1/lumpsum \
-H "Content-Type: application/json" \
-d '{"amount":10000,"expectedAnnualReturn":9,"years":15}'/api/v1/swpProjectionHow long a corpus survives fixed withdrawals
operationId: calculateSwp
Draws a fixed amount every month while the remaining balance keeps compounding, and reports when the corpus runs out. Capped at 600 months (50 years); if the withdrawal is smaller than the growth, `depleted` is false and the corpus survives the cap.
Interactive equivalent: /tools/swp-calculator
Request body
| Field | Type | Constraints | Description |
|---|---|---|---|
| initialInvestment | number | > 0 | Starting corpus. |
| monthlyWithdrawal | number | > 0 | Amount withdrawn every month. |
| expectedAnnualReturn | number | > 0, ≤ 50 | Assumed annual return on the remaining balance, as a percentage. |
Result fields
| Field | Type | Constraints | Description |
|---|---|---|---|
| withdrawalMonths | number | — | Months of withdrawals before the corpus is exhausted, or 600 if it survives the cap. |
| totalWithdrawals | number | — | Total cash withdrawn over that period. |
| remainingBalance | number | — | Balance left at the end. |
| totalInterestEarned | number | — | Growth earned across the period. |
| depleted | boolean | — | True when the corpus ran out before the 600-month cap. |
Example
curl -X POST https://www.stockaverager.com/api/v1/swp \
-H "Content-Type: application/json" \
-d '{"initialInvestment":500000,"monthlyWithdrawal":3000,"expectedAnnualReturn":8}'/api/v1/cagrReturnCompound annual growth rate
operationId: calculateCagr
The annualised rate implied by a start value, an end value and a holding period. Use it to compare investments held for different lengths of time. For uneven cash flows in and out, CAGR is the wrong measure — IRR is.
Interactive equivalent: /tools/cagr-calculator
Request body
| Field | Type | Constraints | Description |
|---|---|---|---|
| initialValue | number | > 0 | Value at the start of the period. |
| finalValue | number | > 0 | Value at the end of the period. |
| years | number | > 0, ≤ 100 | Holding period in years. |
Result fields
| Field | Type | Constraints | Description |
|---|---|---|---|
| cagrPercent | number | — | Compound annual growth rate, as a percentage. |
| absoluteReturn | number | — | finalValue minus initialValue. |
| totalGrowthPercent | number | — | Total return over the whole period, as a percentage. |
Example
curl -X POST https://www.stockaverager.com/api/v1/cagr \
-H "Content-Type: application/json" \
-d '{"initialValue":12000,"finalValue":31000,"years":7}'/api/v1/break-evenPositionBreak-even price including fees
operationId: calculateBreakEven
The selling price at which a position covers its cost once buy-side and sell-side charges are included. On small positions the fee impact is often larger than it looks.
Interactive equivalent: /tools/break-even-calculator
Request body
| Field | Type | Constraints | Description |
|---|---|---|---|
| shares | number | > 0 | Shares held. |
| purchasePrice | number | > 0 | Price paid per share. |
| buyFees | number | ≥ 0, optional | Total charges on the purchase. |
| sellFees | number | ≥ 0, optional | Total charges expected on the sale. |
Result fields
| Field | Type | Constraints | Description |
|---|---|---|---|
| breakEvenPrice | number | — | Price per share that covers cost and all charges. |
| totalCost | number | — | Cash spent acquiring the position, buy fees included. |
| totalFees | number | — | Buy plus sell charges. |
| feeImpact | number | — | How far fees push the break-even above the purchase price. |
Example
curl -X POST https://www.stockaverager.com/api/v1/break-even \
-H "Content-Type: application/json" \
-d '{"shares":100,"purchasePrice":50,"buyFees":10,"sellFees":10}'/api/v1/options/greeksOptionsBlack-Scholes price and Greeks for one option
operationId: calculateOptionGreeks
Prices a single European option with Black-Scholes and returns its sensitivities. Theta is per calendar day and Vega is per one percentage point of implied volatility, matching how desks quote them. Requires a volatility input — there is no market data behind this, so supply the implied volatility you want to model.
Interactive equivalent: /tools/options-greeks-calculator
Request body
| Field | Type | Constraints | Description |
|---|---|---|---|
| spotPrice | number | > 0 | Current price of the underlying. |
| strikePrice | number | > 0 | Strike price of the option. |
| daysToExpiry | number | > 0, ≤ 3650 | Calendar days until expiry. |
| volatilityPercent | number | > 0, ≤ 500 | Implied volatility, as an annualised percentage. |
| riskFreeRatePercent | number | ≥ 0, ≤ 100 | Annual risk-free rate, as a percentage. |
| optionType | string | call | put | Which side to price. |
Result fields
| Field | Type | Constraints | Description |
|---|---|---|---|
| optionPrice | number | — | Theoretical premium per share. |
| delta | number | — | Change in premium per 1 unit move in the underlying. |
| gamma | number | — | Change in delta per 1 unit move in the underlying. |
| theta | number | — | Premium lost per calendar day, all else equal. |
| vega | number | — | Premium change per 1 percentage point of implied volatility. |
| intrinsicValue | number | — | Value if exercised now. |
| timeValue | number | — | optionPrice minus intrinsicValue. |
Example
curl -X POST https://www.stockaverager.com/api/v1/options/greeks \
-H "Content-Type: application/json" \
-d '{"spotPrice":147,"strikePrice":150,"daysToExpiry":30,"volatilityPercent":28,"riskFreeRatePercent":4,"optionType":"call"}'Errors
Errors follow RFC 9457 problem details and are served as application/problem+json. Beyond the standard fields, every response carries a stable code to branch on and a hint describing the fix; validation failures add a per-field errors array.
| Code | Status | Meaning |
|---|---|---|
| malformed_json | 400 | The body could not be parsed as JSON. |
| operation_not_found | 404 | No operation is published at that path. |
| method_not_allowed | 405 | Operations are POST only; the index is GET only. |
| validation_failed | 422 | One or more fields failed validation. See errors[]. |
| calculation_impossible | 422 | Fields are individually valid but cannot be solved together. |
| internal_error | 500 | The calculation failed unexpectedly. Safe to retry once. |
{
"type": "https://www.stockaverager.com/docs#errors-validation-failed",
"title": "Request failed validation",
"status": 422,
"detail": "1 field could not be accepted. See \"errors\" for each one.",
"code": "validation_failed",
"hint": "Fix the listed fields and retry.",
"errors": [
{
"field": "years",
"code": "range",
"message": "\"years\" must be greater than 0 and at most 50, received 0.",
"hint": "Adjust \"years\" so it is greater than 0 and at most 50."
}
]
}For AI agents
The spec at /openapi.json is OpenAPI 3.1 with a unique operationId, a description and typed schemas on every operation, which is what function-calling formats need. Site-wide guidance lives in /llms.txt and /agent-instructions.md. Every page on this site also serves Markdown from the same URL — send Accept: text/markdown or append .md to any path.