Free investment calculators — no signup required
StockAverager logoStockAverager
No API key · OpenAPI 3.1 · Free

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.

POST/api/v1/average-downPosition

Shares 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

FieldTypeConstraintsDescription
sharesnumber> 0Shares currently held.
originalPricenumber> 0Average price already paid per share.
currentPricenumber> 0Current market price per share.
targetAveragePricenumber> 0Average price per share you want to reach.

Result fields

FieldTypeConstraintsDescription
additionalSharesnumberShares to buy at currentPrice to reach the target average.
additionalInvestmentnumberCash required for those shares.
newTotalSharesnumberShares held afterwards.
newTotalInvestmentnumberTotal cash invested afterwards.
newAveragePricenumberResulting 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}'
POST/api/v1/cost-basisPosition

Average 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

FieldTypeConstraintsDescription
lotsarray of objects≥ 1 item(s), ≤ 500 itemsOne entry per purchase lot, in any order.

Result fields

FieldTypeConstraintsDescription
totalSharesnumberShares held across every lot.
totalInvestednumberCash invested across every lot, fees included.
averageCostPerSharenumberCost 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}]}'
POST/api/v1/sipProjection

Future 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

FieldTypeConstraintsDescription
monthlyInvestmentnumber> 0Amount invested every month.
expectedAnnualReturnnumber> 0, ≤ 50Assumed annual return, as a percentage.
yearsnumber> 0, ≤ 50Contribution period in years.

Result fields

FieldTypeConstraintsDescription
futureValuenumberProjected value at the end of the period.
totalInvestmentnumberSum of every contribution.
totalReturnsnumberfutureValue 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}'
POST/api/v1/lumpsumProjection

Future 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

FieldTypeConstraintsDescription
amountnumber> 0Amount invested once, up front.
expectedAnnualReturnnumber> 0, ≤ 50Assumed annual return, as a percentage.
yearsinteger> 0, ≤ 50Holding period in whole years.

Result fields

FieldTypeConstraintsDescription
futureValuenumberProjected value at the end of the period.
totalReturnsnumberfutureValue minus the amount invested.
wealthGainPercentnumberTotal return as a percentage of the amount invested.
yearlyBreakdownarray of objectsValue 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}'
POST/api/v1/swpProjection

How 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

FieldTypeConstraintsDescription
initialInvestmentnumber> 0Starting corpus.
monthlyWithdrawalnumber> 0Amount withdrawn every month.
expectedAnnualReturnnumber> 0, ≤ 50Assumed annual return on the remaining balance, as a percentage.

Result fields

FieldTypeConstraintsDescription
withdrawalMonthsnumberMonths of withdrawals before the corpus is exhausted, or 600 if it survives the cap.
totalWithdrawalsnumberTotal cash withdrawn over that period.
remainingBalancenumberBalance left at the end.
totalInterestEarnednumberGrowth earned across the period.
depletedbooleanTrue 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}'
POST/api/v1/cagrReturn

Compound 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

FieldTypeConstraintsDescription
initialValuenumber> 0Value at the start of the period.
finalValuenumber> 0Value at the end of the period.
yearsnumber> 0, ≤ 100Holding period in years.

Result fields

FieldTypeConstraintsDescription
cagrPercentnumberCompound annual growth rate, as a percentage.
absoluteReturnnumberfinalValue minus initialValue.
totalGrowthPercentnumberTotal 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}'
POST/api/v1/break-evenPosition

Break-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

FieldTypeConstraintsDescription
sharesnumber> 0Shares held.
purchasePricenumber> 0Price paid per share.
buyFeesnumber≥ 0, optionalTotal charges on the purchase.
sellFeesnumber≥ 0, optionalTotal charges expected on the sale.

Result fields

FieldTypeConstraintsDescription
breakEvenPricenumberPrice per share that covers cost and all charges.
totalCostnumberCash spent acquiring the position, buy fees included.
totalFeesnumberBuy plus sell charges.
feeImpactnumberHow 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}'
POST/api/v1/options/greeksOptions

Black-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

FieldTypeConstraintsDescription
spotPricenumber> 0Current price of the underlying.
strikePricenumber> 0Strike price of the option.
daysToExpirynumber> 0, ≤ 3650Calendar days until expiry.
volatilityPercentnumber> 0, ≤ 500Implied volatility, as an annualised percentage.
riskFreeRatePercentnumber≥ 0, ≤ 100Annual risk-free rate, as a percentage.
optionTypestringcall | putWhich side to price.

Result fields

FieldTypeConstraintsDescription
optionPricenumberTheoretical premium per share.
deltanumberChange in premium per 1 unit move in the underlying.
gammanumberChange in delta per 1 unit move in the underlying.
thetanumberPremium lost per calendar day, all else equal.
veganumberPremium change per 1 percentage point of implied volatility.
intrinsicValuenumberValue if exercised now.
timeValuenumberoptionPrice 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.

CodeStatusMeaning
malformed_json400The body could not be parsed as JSON.
operation_not_found404No operation is published at that path.
method_not_allowed405Operations are POST only; the index is GET only.
validation_failed422One or more fields failed validation. See errors[].
calculation_impossible422Fields are individually valid but cannot be solved together.
internal_error500The 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.