Python API¶
Running methods¶
fairmark.run ¶
Run any engine method by id, e.g. run("dcf.fcff", {...}).
fairmark.run_json ¶
Run a method and return the raw JSON envelope as a dict (decimals as strings).
fairmark.methods ¶
Catalogue of available methods (id, title, description, version).
fairmark.input_schema ¶
JSON Schema (2020-12) of a method's input.
Results and errors¶
fairmark.Result
dataclass
¶
A valuation result: exact values, the audit trail and reproducibility metadata.
Value fields are reachable as attributes: result.enterprise_value.
fairmark.Step
dataclass
¶
fairmark.FairmarkError ¶
Methods¶
fairmark.tvm ¶
Time value of money: present values, NPV and XNPV, IRR and XIRR, MIRR, annuities, perpetuities and future value.
In npv, irr and mirr the first cash flow occurs at t = 0. In present_value
the flows are those of periods 1..n. Dated methods take datetime.date objects or ISO
8601 strings.
npv ¶
Net present value. The first cash flow is at t = 0 and is not discounted.
irr ¶
Internal rate of return, solved deterministically.
Raises FairmarkError with code FM-E011 when more than one rate solves the equation.
present_value ¶
present_value(
cash_flows: Sequence[Number],
*,
timing: PeriodTiming,
rate: Number | None = None,
period_rates: Sequence[Number] | None = None,
) -> Result
Present value of the flows of periods 1..n, with one rate or one rate per period.
present_value([100, 100, 100], period_rates=["0.05", "0.06", "0.07"], ... timing="end_of_period").present_value Decimal('269.05475644675080400702...')
xnpv ¶
xnpv(
rate: Number,
cash_flows: DatedFlows,
*,
valuation_date: DateLike | None = None,
day_count: DayCount | None = None,
compounding: Compounding | None = None,
) -> Result
Net present value of dated flows [(date, amount), ...] at the valuation date.
When omitted, the engine applies the ECMA-376 XNPV defaults (valuation at the earliest
flow, Actual/365 (Fixed), annual compounding) and lists them in result.conventions.
xirr ¶
xirr(
cash_flows: DatedFlows,
*,
day_count: DayCount | None = None,
compounding: Compounding | None = None,
guess: Number | None = None,
) -> Result
Annual rate at which the XNPV of dated flows is zero.
Raises FairmarkError FM-E011 when the rate is ambiguous; uniqueness_verified
tells whether other rates are excluded. Omitted options take the ECMA-376 defaults.
mirr ¶
Modified internal rate of return (ECMA-376 MIRR). The first flow is at t = 0.
annuity ¶
annuity(
payment: Number,
rate: Number,
periods: int,
*,
timing: AnnuityTiming,
growth: Number | None = None,
) -> Result
Present and future value of a level (default) or growing annuity, ordinary or due.
perpetuity ¶
perpetuity(
payment: Number,
rate: Number,
*,
timing: AnnuityTiming,
growth: Number | None = None,
) -> Result
Present value of a level (default) or growing perpetuity (Gordon), ordinary or due.
future_value ¶
future_value(
rate: Number,
periods: int,
*,
timing: AnnuityTiming,
present_value: Number | None = None,
payment: Number | None = None,
) -> Result
Value at t = n of a present amount and level payments at a rate per period.
Amounts of the same sign accumulate; a negative amount is a withdrawal. Give at least one
of present_value and payment.
future_value("0.01", 12, payment=1000, timing="ordinary").future_value Decimal('12682.50301319697206612010...')
fairmark.dcf ¶
Discounted cash flow on the shared engine (SPEC-0001).
fcff values the operating business from free cash flows to the firm discounted at the
WACC, over one to three explicit stages followed by a terminal value. Every choice is explicit:
the stages and their projection, the terms of the flows and of the rates, the timing, and the
terminal technique. The helpers given, constant_growth, linear_decline and
gordon only build the input objects; the engine computes everything.
Rates and growths are decimal fractions per period ("0.09" = 9%); one period is one year.
constant_growth ¶
A stage of periods flows, each equal to the previous one times (1 + growth).
linear_decline ¶
A stage whose growth moves from from_growth (the growth before the stage) to
to_growth in equal steps, reaching to_growth in its last period.
gordon ¶
gordon(
growth: Number,
*,
first_flow: FirstFlow,
normalised_next_flow: Number | None = None,
growth_cap: Number | None = None,
) -> dict[str, Any]
The terminal technique tv.gordon, written {"tv.gordon": {...}}.
first_flow is "last_flow_grown" (CF_N x (1 + g)) or "normalised_next_flow"
(then give normalised_next_flow, the flow at N + 1 in the terms of the cash flows).
fcff ¶
fcff(
stages: Iterable[Mapping[str, Any]],
*,
cash_flow_terms: Terms,
discount_rate_terms: Terms,
timing: Timing,
terminal: Mapping[str, Any],
wacc: Number | None = None,
wacc_per_period: Sequence[Number] | None = None,
terminal_wacc: Number | None = None,
terminal_discount_time: TerminalDiscountTime
| None = None,
base_flow: Number | None = None,
net_financial_position: Mapping[str, Any] | None = None,
non_operating_assets: Iterable[Mapping[str, Any]]
| None = None,
) -> Result
Enterprise DCF (dcf.fcff version 3): value of operations, enterprise value and
equity value from FCFF discounted at the WACC.
Give wacc (one rate, also used for the terminal value) or wacc_per_period with
terminal_wacc. Under timing="mid_period" give terminal_discount_time.
r = fcff( ... [given([100, 110, 120])], ... cash_flow_terms="nominal", ... discount_rate_terms="nominal", ... wacc="0.10", ... timing="end_of_period", ... terminal=gordon("0.02", first_flow="last_flow_grown"), ... net_financial_position={"gross_debt": 200, "cash": 0}, ... ) r.value_of_operations Decimal('1421.4876033057851239669421487')
Agent tools¶
fairmark.tools ¶
Function-calling adapters: give any LLM deterministic valuation tools.
Provider-agnostic by design. Tool definitions are generated from the engine's JSON Schemas,
so they never drift from the implementation; the same dispatch executes calls from any
provider.
from fairmark import tools
tools.for_provider("anthropic") # Anthropic Messages API
tools.for_provider("openai") # OpenAI Chat Completions and every compatible API:
# Ollama, OpenRouter, LiteLLM, vLLM, LM Studio, ...
tools.for_provider("openai-responses")
tools.for_provider("gemini") # Google Gemini (function declarations)
result = tools.dispatch(name, arguments) # arguments: dict or JSON string
The LLM extracts parameters; Fairmark computes; the LLM writes the report citing
explain. The model never does the arithmetic.
tool_name ¶
dcf.fcff -> fairmark_dcf_fcff (valid for every major provider).
definitions ¶
Provider-neutral tool definitions: name, description, JSON Schema parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
portable
|
bool
|
simplify the schemas for providers or models with limited JSON Schema
support (decimals as strings, no |
False
|
openai ¶
Tool definitions for OpenAI Chat Completions and every OpenAI-compatible API.
Works with OpenAI, Azure OpenAI, Ollama (/v1), OpenRouter, LiteLLM, vLLM, LM Studio,
Mistral, Groq and others. Use portable=True with open-weight models.
openai_responses ¶
Tool definitions for the OpenAI Responses API (flat function tools).
gemini ¶
Function declarations for Google Gemini (google-genai SDK or REST).
Uses parametersJsonSchema with the portable schema. Wrap them as
{"function_declarations": fm.tools.gemini()} in the request tools.
for_provider ¶
Tool definitions in the format a provider expects, by provider name.
Known names: anthropic, openai, azure-openai, ollama, openrouter, litellm, vllm, lmstudio, mistral, groq, openai-responses, gemini. Local open-weight runtimes get the portable schema.
langchain ¶
LangChain / LangGraph tools (pip install "fairmark[langchain]").
dispatch ¶
Execute a tool call coming from an LLM.
Never raises on bad input: returns {"error": {"code", "message"}} so the
model can read the error and correct its parameters.