API Reference¶
Complete reference for Kanso's core classes, functions, and data models.
Finance Calculator¶
FinanceCalculator¶
Core calculation engine for financial metrics and chart data.
Location: app/logic/finance_calculator.py
Constructor¶
FinanceCalculator(
assets_df: pd.DataFrame | None = None,
liabilities_df: pd.DataFrame | None = None,
expenses_df: pd.DataFrame | None = None,
incomes_df: pd.DataFrame | None = None,
)
Parameters:
- assets_df - DataFrame with Date column and asset values
- liabilities_df - DataFrame with Date column and liability values
- expenses_df - DataFrame with Date, Merchant, Amount, Category, Type columns
- incomes_df - DataFrame with Date column and income sources
Methods: Net Worth¶
get_current_net_worth() -> float¶
Calculate the most recent net worth (assets - liabilities).
Returns: Latest net worth value
Example:
calc = FinanceCalculator(assets_df=assets, liabilities_df=liabilities)
net_worth = calc.get_current_net_worth() # 50000.0
get_monthly_net_worth() -> list[dict[str, Any]]¶
Get time series of net worth for charting.
Returns: List of {date: str, net_worth: float, ...} dictionaries
Example:
data = calc.get_monthly_net_worth()
# [
# {"date": "2024-01", "net_worth": 48000.0, ...},
# {"date": "2024-02", "net_worth": 50000.0, ...},
# ]
get_month_over_month_net_worth_variation_percentage() -> float¶
Calculate MoM percentage change in net worth.
Returns: Percentage change (e.g., 2.5 for +2.5%)
get_month_over_month_net_worth_variation_absolute() -> float¶
Calculate MoM absolute change in net worth.
Returns: Monetary change (e.g., 1200.0 for €1,200)
get_year_over_year_net_worth_variation_percentage() -> float¶
Calculate YoY percentage change in net worth.
Returns: Percentage change
get_year_over_year_net_worth_variation_absolute() -> float¶
Calculate YoY absolute change in net worth.
Returns: Monetary change
Methods: Savings¶
get_average_saving_ratio_last_12_months_percentage() -> float¶
Calculate average savings ratio over last 12 months.
Formula: (Income - Expenses) / Income * 100
Returns: Percentage (e.g., 25.5 for 25.5% savings rate)
get_average_saving_ratio_last_12_months_absolute() -> float¶
Calculate average monthly savings amount.
Returns: Average savings in currency units
Methods: Charts¶
get_cash_flow_last_12_months() -> dict[str, Any]¶
Get cash flow data for the past 12 months.
Returns: Dictionary with:
- dates - List of month labels
- incomes - Income values by source
- expenses - Total expenses
- savings - Net savings
Example:
chart_data = calc.get_cash_flow_last_12_months()
# {
# "dates": ["Jan", "Feb", ...],
# "incomes": {
# "Salary": [3000, 3000, ...],
# "Freelance": [500, 800, ...],
# },
# "expenses": [2000, 2200, ...],
# "savings": [1500, 1600, ...],
# }
get_average_expenses_by_category() -> dict[str, Any]¶
Get average spending by category (last 12 months).
Returns: Dictionary with:
- categories - List of category names
- values - Average amounts per category
get_incomes_vs_expenses() -> dict[str, Any]¶
Compare total income vs expenses (last 12 months).
Returns: Dictionary with:
- categories - ["Income", "Expenses"]
- values - [total_income, total_expenses]
DataFrame Processor¶
DataFrameProcessor¶
Utilities for preprocessing financial DataFrames.
Location: app/logic/dataframe_processor.py
Static Methods¶
find_date_column(df: pd.DataFrame) -> str | tuple | None¶
Find the Date column in single or multi-index DataFrame.
Returns: Column name (string or tuple for MultiIndex), or None if not found
Example:
sum_monetary_columns_for_row(row: pd.Series, exclude: list[str]) -> float¶
Sum all monetary columns in a row, excluding specified patterns.
Parameters:
- row - DataFrame row as Series
- exclude - List of column patterns to skip (e.g., ["Date", "Category"])
Returns: Total sum of parsed monetary values
preprocess_expenses(df: pd.DataFrame) -> pd.DataFrame | None¶
Preprocess expenses DataFrame with date and amount parsing.
Transformations:
- Parse Date column to datetime (date_dt)
- Parse Amount to float (amount_parsed)
- Sort by date
Returns: Processed DataFrame or None if invalid structure
preprocess_assets(df: pd.DataFrame) -> pd.DataFrame | None¶
Preprocess assets DataFrame with date parsing and sorting.
preprocess_liabilities(df: pd.DataFrame) -> pd.DataFrame | None¶
Preprocess liabilities DataFrame with date parsing and sorting.
preprocess_incomes(df: pd.DataFrame) -> pd.DataFrame | None¶
Preprocess incomes DataFrame with date parsing and sorting.
Monetary Parsing¶
Functions¶
Location: app/logic/monetary_parsing.py
detect_currency(value: str) -> str | None¶
Detect currency from symbol in string.
Parameters:
- value - String potentially containing currency symbol
Returns: Currency code ("EUR", "USD", etc.) or None
Example:
detect_currency("€ 1.234,56") # "EUR"
detect_currency("$1,234.56") # "USD"
detect_currency("1234") # None
parse_monetary_value(value: Any, currency: str | None = None) -> float¶
Parse monetary value with intelligent currency detection.
Parameters:
- value - Input value (string, int, float, or None)
- currency - Optional currency code to force specific parsing
Returns: Parsed float value (0.0 for unparseable values)
Supported Formats:
| Currency | Format Example | Parsed Value |
|---|---|---|
| EUR | € 1.234,56 | 1234.56 |
| USD | $1,234.56 | 1234.56 |
| GBP | £1,234.56 | 1234.56 |
| CHF | Fr 1 234,56 | 1234.56 |
| JPY | ¥1,234 | 1234.0 |
| CAD | C$1,234.56 | 1234.56 |
| AUD | A$1,234.56 | 1234.56 |
| CNY | ¥1,234.56 | 1234.56 |
| INR | ₹1,234.56 | 1234.56 |
| BRL | R$ 1.234,56 | 1234.56 |
Example:
parse_monetary_value("€ 1.234,56") # 1234.56
parse_monetary_value("$1,234.56") # 1234.56
parse_monetary_value(1234) # 1234.0
parse_monetary_value(None) # 0.0
parse_monetary_value("-") # 0.0
parse_monetary_value("abc") # 0.0 (with warning log)
Currency Formats¶
CurrencyFormat¶
Immutable currency configuration.
Location: app/core/currency_formats.py
Attributes¶
@dataclass(frozen=True)
class CurrencyFormat:
symbol: str # Currency symbol (€, $, £, etc.)
decimal_sep: str # Decimal separator ("." or ",")
thousands_sep: str # Thousands separator ("," or ".")
has_decimals: bool # Whether currency uses decimals
position: Literal["before", "after"] # Symbol position relative to amount
Constants¶
CURRENCY_FORMATS: dict[str, CurrencyFormat]¶
Pre-configured formats for supported currencies.
Example:
from app.core.currency_formats import CURRENCY_FORMATS
eur_format = CURRENCY_FORMATS["EUR"]
# CurrencyFormat(symbol="€", decimal_sep=",", thousands_sep=".", has_decimals=True)
Functions¶
get_currency_format(currency: str) -> CurrencyFormat¶
Get format configuration for a currency.
Raises: ValueError if currency not supported
get_currency_symbol(currency: str) -> str¶
Get symbol for a currency (with fallback to $ for unknown).
get_supported_currencies() -> list[str]¶
Get list of all supported currency codes.
Finance Service¶
FinanceService¶
Service layer for data access and business logic.
Location: app/services/finance_service.py
Methods¶
get_calculator() -> FinanceCalculator | None¶
Get a FinanceCalculator instance with loaded data.
Returns: Calculator or None if data loading failed
get_dashboard_data() -> dict[str, Any] | None¶
Get all dashboard data (KPIs + charts) in a single call.
Returns: Dictionary with kpi_data and chart_data keys
Example:
service = FinanceService()
data = service.get_dashboard_data()
if data:
kpis = data["kpi_data"]
charts = data["chart_data"]
print(f"Net Worth: {kpis['net_worth']}")
print(f"Charts: {charts.keys()}")
Data Models¶
ExpenseRow¶
Validated expense transaction.
Location: app/core/validators.py
Fields¶
class ExpenseRow(BaseModel):
date: str # YYYY-MM or YYYY-MM-DD format
merchant: str # Vendor name (non-empty)
amount: str # Monetary value with optional currency
category: str # Spending category (non-empty)
type: str # "Fixed" or "Variable" (non-empty)
Validators¶
date- Must be parseable to YYYY-MM formatmerchant,category,type- Must be non-empty after stripping whitespaceamount- Must contain at least one digit
Example:
from app.models.validators import ExpenseRow
expense = ExpenseRow(
date="2024-01",
merchant="Grocery Store",
amount="€ 150.50",
category="Food",
type="Variable"
)
AssetRow, LiabilityRow, IncomeRow¶
Similar validation models for other financial data types.
Constants¶
Date Formats¶
Location: app/core/constants.py
DATE_FORMAT_STORAGE = "%Y-%m" # YYYY-MM for monthly data
DATE_FORMAT_DISPLAY = "%m-%Y" # "01-2025" for UI
Column Names¶
COL_DATE = "Date"
COL_AMOUNT = "Amount"
COL_CATEGORY = "Category"
COL_MERCHANT = "Merchant"
COL_TYPE = "Type"
COL_DATE_DT = "date_dt" # Parsed datetime column
COL_AMOUNT_PARSED = "amount_parsed" # Parsed float column
Financial Thresholds¶
SAVING_RATIO_THRESHOLD_LOW = 0.2 # 20% - "error" level
SAVING_RATIO_THRESHOLD_MEDIUM = 0.4 # 40% - "warning" level
Time Constants¶
MONTHS_IN_YEAR = 12
MONTHS_LOOKBACK_YEAR = 13 # 12 months + 1 for YoY comparison
CACHE_TTL_SECONDS = 86400 # 24 hours
Next Steps¶
- Architecture - Understand system design
- Contributing - Contribute to Kanso
- Configuration - Customize settings