Vai al contenuto

API Python

import fairmark as fm

La documentazione delle singole funzioni è generata dal codice sorgente ed è in inglese.

Eseguire i metodi

fairmark.run

run(method: str, inputs: Mapping[str, Any] | str) -> Result

Run any engine method by id, e.g. run("dcf.fcff", {...}).

fairmark.run_json

run_json(
    method: str, inputs: Mapping[str, Any] | str
) -> dict[str, Any]

Run a method and return the raw JSON envelope as a dict (decimals as strings).

fairmark.methods

methods() -> list[dict[str, str]]

Catalogue of available methods (id, title, description, version).

fairmark.input_schema

input_schema(method: str) -> dict[str, Any]

JSON Schema (2020-12) of a method's input.

Risultati ed errori

fairmark.Result dataclass

A valuation result: exact values, the audit trail and reproducibility metadata.

Value fields are reachable as attributes: result.enterprise_value.

to_json

to_json() -> str

The exact JSON envelope returned by the engine (decimals as strings).

explain_markdown

explain_markdown() -> str

A methodology note ready to paste into a report.

fairmark.Step dataclass

fairmark.FairmarkError

Bases: ValueError

Raised when the engine rejects an input. code is stable, e.g. FM-E004.

Metodi

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

npv(rate: Number, cash_flows: Sequence[Number]) -> Result

Net present value. The first cash flow is at t = 0 and is not discounted.

irr

irr(
    cash_flows: Sequence[Number],
    *,
    guess: Number | None = None,
) -> Result

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

mirr(
    cash_flows: Sequence[Number],
    finance_rate: Number,
    reinvest_rate: Number,
) -> Result

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.

given

given(flows: Sequence[Number]) -> dict[str, Any]

A stage of given flows, one per period.

constant_growth

constant_growth(
    periods: int, growth: Number
) -> dict[str, Any]

A stage of periods flows, each equal to the previous one times (1 + growth).

linear_decline

linear_decline(
    periods: int, from_growth: Number, to_growth: Number
) -> dict[str, Any]

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')

Tool per gli agenti

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

tool_name(method_id: str) -> str

dcf.fcff -> fairmark_dcf_fcff (valid for every major provider).

method_id

method_id(name: str) -> str

fairmark_dcf_fcff -> dcf.fcff.

definitions

definitions(portable: bool = False) -> list[dict[str, Any]]

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 pattern/additionalProperties).

False

anthropic

anthropic() -> list[dict[str, Any]]

Tool definitions for the Anthropic Messages API.

openai

openai(portable: bool = False) -> list[dict[str, Any]]

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

openai_responses(
    portable: bool = False,
) -> list[dict[str, Any]]

Tool definitions for the OpenAI Responses API (flat function tools).

gemini

gemini() -> list[dict[str, Any]]

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

for_provider(provider: str) -> list[dict[str, Any]]

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() -> list[Any]

LangChain / LangGraph tools (pip install "fairmark[langchain]").

dispatch

dispatch(
    name: str, arguments: Mapping[str, Any] | str
) -> dict[str, Any]

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.