Output:
Chunk ID: 66cf37
Wall time: 0.0001 seconds
Process exited with code 0
Original token count: 7665
Output:
+                 ORDER BY balance_date,created_at,cash_balance_id""",
+            (account_id,),
+        ).fetchall()
+        materialized_by_currency: dict[str, list[Row]] = {}
+        for balance_row in materialized_rows:
+            materialized_by_currency.setdefault(
+                str(balance_row["currency"]), []
+            ).append(balance_row)
+        ledger_currencies = {
+            currency
+            for ledger_account_id, currency in ledger.balances
+            if ledger_account_id == account_id
+        }
+        # Manual balances and CSV anchors are account-level CHF controls. They must
+        # not be added to per-currency ledger rows from the same account.
+        currencies = (
+            {default_currency}
+            if manual or anchor
+            else set(ledger_currencies) | set(materialized_by_currency)
+            or {default_currency}
         )
+        for currency in sorted(currencies):
+            ledger_balance = ledger.balances.get((account_id, currency))
+            currency_rows = materialized_by_currency.get(currency, [])
+            # Equity actions write their cash leg only to cash_balances. Other
+            # materialized rows are used only when no same-currency ledger exists,
+            # avoiding duplicate vue_manual_cash transaction/materialization pairs.
+            additional_rows = (
+                [
+                    balance_row
+                    for balance_row in currency_rows
+                    if str(balance_row["source_type"] or "").startswith(
+                        ("vue_equity_sale:", "vue_equity_dividend")
+                    )
+                ]
+                if ledger_balance is not None
+                else currency_rows
+            )
+            if manual or anchor:
+                calculated = _calculated_balance(conn, account_id)
+                amount_original = (
+                    calculated if currency.upper() == "CHF" else Decimal("0")
+                )
+            elif ledger_balance is not None:
+                calculated = ledger_balance.amount_chf or Decimal("0")
+                amount_original = ledger_balance.amount_original
+            else:
+                calculated = Decimal("0")
+                amount_original = Decimal("0")
+            if not (manual or anchor):
+                amount_original += sum(
+                    (
+                        Decimal(str(balance_row["amount_original"]))
+                        for balance_row in additional_rows
+                    ),
+                    Decimal("0"),
+                )
+                calculated += sum(
+                    (
+                        Decimal(str(balance_row["amount_chf"]))
+                        for balance_row in additional_rows
+                        if balance_row["amount_chf"] is not None
+                    ),
+                    Decimal("0"),
+                )
+            manual_amount = (
+                Decimal(str(manual["amount_chf"]))
+                if manual and currency == default_currency
+                else None
+            )
+            used = (
+                manual_amount
+                if mode == "manual" and manual_amount is not None
+                else calculated
+            )
+            difference = (
+                manual_amount - calculated
+                if manual_amount is not None
+                else Decimal("0")
+            )
+            missing_fx = (
+                ledger_balance is not None and ledger_balance.amount_chf is None
+            ) or any(
+                balance_row["amount_chf"] is None for balance_row in additional_rows
+            )
+            status = (
+                "Abgleich offen"
+                if missing_fx or manual_amount is not None and difference != 0
+                else "Aktuell"
+            )
+            positions.append(
+                CashPosition(
+                    id=f"{account_id}:{currency}",
+                    account_id=account_id,
+                    platform=row["platform"],
+                    account_label=row["account_name"],
+                    account_type=row["account_type"],
+                    currency=currency,
+                    balance_mode=mode,
+                    amount=decimal_text(amount_original, 2),
+                    amount_chf=decimal_text(used, 2),
+                    calculated_balance_chf=decimal_text(calculated, 2),
+                    manual_balance_chf=(
+                        decimal_text(manual_amount, 2)
+                        if manual_amount is not None
+                        else None
+                    ),
+                    csv_anchor_balance_chf=(
+                        decimal_text(anchor["amount_chf"], 2)
+                        if anchor and currency == default_currency
+                        else None
+                    ),
+                    used_value_chf=decimal_text(used, 2),
+                    difference_chf=decimal_text(difference, 2),
+                    last_manual_reconciliation=(
+                        manual["balance_date"]
+                        if manual and currency == default_currency
+                        else None
+                    ),
+                    last_imported_booking=_last_imported_booking(conn, account_id),
+                    status=status,
+                )
+            )
     return positions

@@ -252,10 +519,10 @@ def confirm_cash_snapshot(conn: Connection, request: CashSnapshotConfirmRequest)

 def get_cash_position_detail(conn: Connection, position_id: str) -> CashPositionDetail:
-    account_id, _currency = position_id.split(":", 1)
-    position = next((p for p in get_cash_summary(conn).positions if p.account_id == account_id), None)
+    position = next((p for p in get_cash_summary(conn).positions if p.id == position_id), None)
     if not position:
         raise HTTPException(status_code=404, detail="Cash position not found")
+    account_id = position.account_id
     rows = conn.execute(
         """
         SELECT snapshot_id, snapshot_type, balance_date, amount_chf, source, COALESCE(note,'') AS note, audit_id
diff --git a/src/jarvis_finance/services/equity_service.py b/src/jarvis_finance/services/equity_service.py
index 614e76b..9fd4f2e 100644
--- a/src/jarvis_finance/services/equity_service.py
+++ b/src/jarvis_finance/services/equity_service.py
@@ -101,6 +101,20 @@ def _mapping_details(conn: Connection, instrument_id: str) -> dict[str, str | No
     return dict(row) if row else {"provider": None, "provider_symbol": None, "provider_market": None, "currency": None}

+def _analysis_value_is_eligible(
+    analysis: Mapping[str, object] | None,
+    candidate: Mapping[str, object] | None,
+    row: Mapping[str, object],
+) -> bool:
+    if not analysis or not candidate or candidate.get("quality_status") != "fresh":
+        return False
+    analysis_as_of = str(analysis.get("as_of") or "")
+    row_as_of = str(row.get("valuation_as_of") or row.get("price_date") or "")
+    if row.get("valuation_source") == "postfinance_official_import":
+        return analysis_as_of > row_as_of
+    return analysis_as_of >= row_as_of
+
+
 def list_equity_positions(conn: Connection) -> list[EquityPosition]:
     source_rows = [
         row for row in dashboard_data.get_positions(conn)
@@ -108,24 +122,49 @@ def list_equity_positions(conn: Connection) -> list[EquityPosition]:
         and row.get("instrument_status", "").lower() != "inactive"
     ]
     analysis, values, missing = _latest_analysis(conn)
-    use_cache_fallback = analysis is None
-    expected_keys = {(str(row.get("account_id") or ""), str(row.get("instrument_id") or "")) for row in source_rows}
-    complete = bool(analysis and analysis.get("quality_status") == "complete" and set(values) == expected_keys)
-    total = sum((Decimal(str(item.get("value_chf") or "0")) for item in values.values()), Decimal("0"))
+    effective_values: dict[tuple[str, str], Decimal | None] = {}
+    for row in source_rows:
+        key = (str(row.get("account_id") or ""), str(row.get("instrument_id") or ""))
+        candidate = values.get(key)
+        row_is_audited = row.get("valuation_source") in {
+            "postfinance_official_import",
+            "audited_market_run",
+        }
+        candidate_is_newer = _analysis_value_is_eligible(analysis, candidate, row)
+        raw = (
+            candidate.get("value_chf")
+            if candidate_is_newer and candidate
+            else row.get("market_value_chf") if analysis is None or row_is_audited else None
+        )
+        effective_values[key] = Decimal(str(raw)) if raw not in {None, ""} else None
+    complete = bool(source_rows) and all(value is not None for value in effective_values.values())
+    total = sum((value or Decimal("0") for value in effective_values.values()), Decimal("0"))
     positions: list[EquityPosition] = []
     for row in source_rows:
         account_id = str(row.get("account_id") or "")
         instrument_id = str(row.get("instrument_id") or "")
         snapshot_value = values.get((account_id, instrument_id))
-        value = snapshot_value if snapshot_value and snapshot_value.get("quality_status") == "fresh" else None
+        value = (
+            snapshot_value
+            if _analysis_value_is_eligible(analysis, snapshot_value, row)
+            else None
+        )
+        row_fallback_allowed = analysis is None or row.get("valuation_source") in {
+            "postfinance_official_import",
+            "audited_market_run",
+        }
         mapping = _mapping_details(conn, instrument_id)
-        raw_market_value = value.get("value_chf") if value else (row.get("market_value_chf") if use_cache_fallback else None)
-        if use_cache_fallback and Decimal(str(row.get("quantity") or "0")) <= 0:
+        raw_market_value = (
+            value.get("value_chf")
+            if value
+            else row.get("market_value_chf") if row_fallback_allowed else None
+        )
+        if Decimal(str(row.get("quantity") or "0")) <= 0:
             raw_market_value = None
         market_value = Decimal(str(raw_market_value)) if raw_market_value not in {None, ""} else None
         share = (market_value / total * Decimal("100")) if complete and market_value is not None and total > 0 else None
         code = "valued" if market_value is not None else ("stale_price" if snapshot_value else missing.get(instrument_id, "price_missing"))
-        status = "Bewertet" if value else ("Kurs veraltet" if snapshot_value else (_position_status(row) if use_cache_fallback else "Kurs fehlt"))
+        status = "Bewertet" if market_value is not None else ("Kurs veraltet" if snapshot_value else _position_status(row))
         provenance = value.get("price_input_provenance") if value else None
         provenance_provider = provenance.get("provider") if isinstance(provenance, dict) else None
         positions.append(EquityPosition(
@@ -138,11 +177,23 @@ def list_equity_positions(conn: Connection) -> list[EquityPosition]:
             asset_class=_asset_class_label(row.get("asset_class")),
             quantity=optional_decimal_text(row.get("quantity")) or "0",
             currency=str(value.get("currency") if value else mapping.get("currency") or row.get("price_currency") or row.get("currency") or ""),
-            price=optional_decimal_text(value.get("close")) if value else (optional_decimal_text(row.get("market_price_original") or row.get("price")) if use_cache_fallback else None),
+            price=(
+                optional_decimal_text(value.get("close"))
+                if value
+                else optional_decimal_text(row.get("market_price_original") or row.get("price"))
+                if row_fallback_allowed
+                else None
+            ),
             market_value_chf=optional_decimal_text(market_value, 2) if market_value is not None else None,
             portfolio_share_pct=optional_decimal_text(share, 2) if share is not None else None,
-            price_date=str(value.get("as_of")) if value else (str(analysis.get("as_of")) if analysis else None),
-            provider=str((value.get("provider") if value else None) or provenance_provider or mapping.get("provider") or ""),
+            price_date=(
+                str(analysis.get("as_of"))
+                if value and analysis
+                else str(row.get("valuation_as_of") or row.get("price_date") or "") or None
+                if row_fallback_allowed
+                else str(analysis.get("as_of")) if analysis else None
+            ),
+            provider=str((value.get("provider") if value else None) or provenance_provider or row.get("price_provider") or mapping.get("provider") or ""),
             provider_symbol=str(mapping.get("provider_symbol") or ""),
             exchange=str(mapping.get("provider_market") or ""),
             price_currency=str(value.get("currency") if value else mapping.get("currency") or row.get("price_currency") or row.get("currency") or ""),
@@ -161,6 +212,14 @@ def get_equity_summary(conn: Connection) -> EquityPortfolioSummary:
     complete = bool(positions) and len(valued) == len(positions)
     analysis, _, _ = _latest_analysis(conn)
     status = "complete" if complete else ("partial" if positions else "unavailable")
+    effective_as_of = max((item.price_date or "" for item in valued), default="") or None
+    analysis_as_of = str(analysis.get("as_of") or "") if analysis else ""
+    response_as_of = effective_as_of or analysis_as_of or None
+    last_successful = (
+        str(analysis.get("completed_at"))
+        if analysis and (not effective_as_of or analysis_as_of >= str(effective_as_of)[:10])
+        else effective_as_of
+    )
     return EquityPortfolioSummary(
         total_positions=len(positions),
         valued_positions=len(valued),
@@ -169,8 +228,8 @@ def get_equity_summary(conn: Connection) -> EquityPortfolioSummary:
         equity_value_chf=optional_decimal_text(partial, 2) if complete else None,
         valued_partial_chf=optional_decimal_text(partial, 2) or "0.00",
         value_label="Aktien-/ETF-Gesamtwert" if complete else "Bewerteter Teilwert",
-        as_of=str(analysis.get("as_of")) if analysis else None,
-        last_successful_run=str(analysis.get("completed_at")) if analysis else None,
+        as_of=response_as_of,
+        last_successful_run=last_successful,
         status=status,
         status_label=f"{len(valued)}/{len(positions)} bewertet" if positions else "Keine Aktien-/ETF-Positionen",
         unvalued_tickers=[item.ticker for item in positions if item.market_value_chf is None],
diff --git a/src/jarvis_finance/services/portfolio_analytics.py b/src/jarvis_finance/services/portfolio_analytics.py
index f6acbd6..5331de3 100644
--- a/src/jarvis_finance/services/portfolio_analytics.py
+++ b/src/jarvis_finance/services/portfolio_analytics.py
@@ -25,6 +25,11 @@ from jarvis_finance.market_data.prices import (
     exchange_matches,
     store_market_price,
 )
+from jarvis_finance.services.portfolio_aggregation import (
+    latest_official_postfinance_positions,
+    post_snapshot_postfinance_quantity_deltas,
+    postfinance_account_roles,
+)
 from jarvis_finance.services.portfolio_performance import build_portfolio_performance

 ZERO = Decimal("0")
@@ -224,6 +229,43 @@ def confirmed_canonical_positions(conn: Connection, *, as_of: str | None = None)
         item = grouped.setdefault(key, dict(row) | {"quantity_total": ZERO})
         quantity = _decimal(row["quantity"])
         item["quantity_total"] += -abs(quantity) if str(row["transaction_type"]).lower() in SELL_TYPES else quantity
+    official = latest_official_postfinance_positions(conn, as_of=as_of)
+    post_snapshot_deltas = post_snapshot_postfinance_quantity_deltas(
+        conn,
+        official,
+        as_of=as_of,
+    )
+    trading_cash_id = postfinance_account_roles(conn).get("etrading_cash")
+    official_instruments = {key[1] for key in official}
+    for key in list(grouped):
+        if key[0] == trading_cash_id and key[1] in official_instruments:
+            grouped.pop(key)
+    for key, override in official.items():
+        item = grouped.get(key)
+        if item is None:
+            instrument = conn.execute(
+                """SELECT isin,name,lower(asset_class) asset_class,
+                          upper(COALESCE(trading_currency,currency,'')) instrument_currency
+                   FROM instruments WHERE instrument_id=? AND is_active=1""",
+                (override.instrument_id,),
+            ).fetchone()
+            if not instrument:
+                continue
+            item = {
+                "account_id": override.account_id,
+                "instrument_id": override.instrument_id,
+                "isin": instrument["isin"],
+                "name": instrument["name"],
+                "asset_class": instrument["asset_class"],
+                "instrument_currency": instrument["instrument_currency"],
+            }
+            grouped[key] = item
+        # The official snapshot is the baseline. Only confirmed trades after that
+        # snapshot are replayed, so imported history is not counted twice.
+        item["quantity_total"] = override.quantity + post_snapshot_deltas.get(
+            override.instrument_id,
+            ZERO,
+        )
     return [
         ConfirmedPosition(
             account_id=item["account_id"],
diff --git a/src/jarvis_finance/services/portfolio_data.py b/src/jarvis_finance/services/portfolio_data.py
index 7a5762e..a80d646 100644
--- a/src/jarvis_finance/services/portfolio_data.py
+++ b/src/jarvis_finance/services/portfolio_data.py
@@ -6,27 +6,33 @@ reconciliation are pure database projections. Confirm is the only write boundary

 from __future__ import annotations

-from dataclasses import dataclass
-from datetime import UTC, date, datetime, timedelta
-from decimal import Decimal, InvalidOperation
 import base64
 import binascii
 import hashlib
 import json
 import re
+import uuid
+from dataclasses import dataclass
+from datetime import UTC, date, datetime, timedelta
+from decimal import Decimal, InvalidOperation
 from sqlite3 import Connection, IntegrityError
 from typing import Any
-import uuid

 from jarvis_finance.audit.log import record_audit_event
+from jarvis_finance.imports.common import stable_id
 from jarvis_finance.imports.postfinance_etrading import (
     PostFinanceDocument,
-    decimal_text as postfinance_decimal_text,
     normalize_label,
     parse_postfinance_portfolio,
 )
-from jarvis_finance.imports.common import stable_id
+from jarvis_finance.imports.postfinance_etrading import (
+    decimal_text as postfinance_decimal_text,
+)
 from jarvis_finance.market_data.mappings import confirm_instrument_price_mapping
+from jarvis_finance.services.portfolio_aggregation import (
+    latest_official_postfinance_cash,
+    postfinance_account_roles,
+)

 INGESTION_VERSION = "portfolio_ingestion_v1"
 RECONCILIATION_VERSION = "portfolio_reconciliation_v1"
@@ -1434,7 +1440,8 @@ def _latest_fx(conn: Connection, currency: str, as_of: str, cutoff: str) -> tupl
         return Decimal("1"), as_of, "identity"
     row = conn.execute(
         """SELECT rate, rate_date, provider FROM fx_rates
-           WHERE base_currency=? AND quote_currency='CHF' AND rate_date<=? AND created_at<=?
+           WHERE base_currency=? AND quote_currency='CHF' AND rate_date<=?
+             AND datetime(created_at)<=datetime(?)
              AND rate IS NOT NULL AND quality_status IN ('ok','fresh','complete')
            ORDER BY rate_date DESC, created_at DESC, fx_rate_id DESC LIMIT 1""", (currency, as_of, cutoff)
     ).fetchone()
@@ -1463,7 +1470,8 @@ def build_portfolio_reconciliation(
         return {"as_of": as_of, "data_cutoff": cutoff, "base_currency": "CHF", "status": "unavailable", "reason_codes": ["missing_account_valuation"], "tolerance": {"version": TOLERANCE_VERSION, "absolute": str(absolute), "relative": str(relative)}, "coverage": empty_coverage, "differences": [], "account_totals": [], "input_fingerprint": _hash([as_of, cutoff, []]), "sources": [], "limit": limit, "offset": offset, "total": 0}
     placeholders = ",".join("?" for _ in account_map)
     transaction_rows = conn.execute(
-        f"""SELECT * FROM transactions WHERE account_id IN ({placeholders}) AND trade_date<=? AND created_at<=?
+        f"""SELECT * FROM transactions WHERE account_id IN ({placeholders}) AND trade_date<=?
+            AND datetime(created_at)<=datetime(?)
             AND COALESCE(is_voided,0)=0 AND COALESCE(is_confirmed,1)=1
             ORDER BY trade_date, created_at, transaction_id""", (*account_map, as_of, cutoff)
     ).fetchall()
@@ -1490,7 +1498,8 @@ def build_portfolio_reconciliation(
     reported_rows = conn.execute(
         f"""WITH ranked AS (
               SELECT p.*, ROW_NUMBER() OVER(PARTITION BY account_id,instrument_id ORDER BY snapshot_date DESC,created_at DESC,position_snapshot_id DESC) rn
-              FROM positions_snapshot p WHERE account_id IN ({placeholders}) AND snapshot_date<=? AND created_at<=?
+              FROM positions_snapshot p WHERE account_id IN ({placeholders}) AND snapshot_date<=?
+                AND datetime(created_at)<=datetime(?)
             ) SELECT * FROM ranked WHERE rn=1""", (*account_map, as_of, cutoff)
     ).fetchall()
     reported = {(str(row["account_id"]), str(row["instrument_id"])): row for row in reported_rows}
@@ -1523,7 +1532,8 @@ def build_portfolio_reconciliation(
         derived_value: Decimal | None = None
         reported_value = _stored_decimal(source["market_value_chf"], "Gemeldeter Positionswert") if source and source["market_value_chf"] not in (None, "") else None
         price_row = conn.execute(
-            """SELECT close,currency,price_date,provider FROM market_prices WHERE instrument_id=? AND price_date<=? AND created_at<=?
+            """SELECT close,currency,price_date,provider FROM market_prices WHERE instrument_id=? AND price_date<=?
+               AND datetime(created_at)<=datetime(?)
                AND quality_status IN ('ok','fresh','complete') ORDER BY price_date DESC,created_at DESC,market_price_id DESC LIMIT 1""", (instrument, as_of, cutoff)
         ).fetchone()
         price_date = str(price_row["price_date"]) if price_row else None
@@ -1586,18 +1596,37 @@ def build_portfolio_reconciliation(
                           "position_as_of": str(source["snapshot_date"]) if source else None, "price_as_of": price_date, "fx_as_of": fx_date, "price_source": price_source, "fx_source": fx_source},
             "reason_codes": sorted(set(reasons)),
         })
+    pf_roles = postfinance_account_roles(conn)
+    official_pf_cash = latest_official_postfinance_cash(
+        conn,
+        as_of=as_of,
+        data_cutoff=cutoff,
+    )
+    official_pf_cash_total = sum(
+        (component.amount_chf for component in official_pf_cash), Decimal("0")
+    )
+    official_pf_cash_date = max(
+        (component.snapshot_date for component in official_pf_cash), default=None
+    )
     account_totals: list[dict[str, Any]] = []
     account_covered = 0
     for account, meta in account_map.items():
         cash = conn.execute(
-            """SELECT amount_chf,balance_date,source FROM cash_account_snapshots WHERE account_id=? AND balance_date<=? AND created_at<=?
+            """SELECT amount_chf,balance_date,source FROM cash_account_snapshots WHERE account_id=? AND balance_date<=?
+               AND datetime(created_at)<=datetime(?)
                ORDER BY balance_date DESC,created_at DESC,snapshot_id DESC LIMIT 1""", (account, as_of, cutoff)
         ).fetchone()
         cash_value = _stored_decimal(cash["amount_chf"], "Cashbestand") if cash else None
         cash_date = str(cash["balance_date"]) if cash else None
+        if account == pf_roles.get("etrading_depot") and official_pf_cash:
+            # The provider account total spans the distinct depot and trading-cash
+            # roles. This is a reconciliation-only join, not an additive holding.
+            cash_value = official_pf_cash_total
+            cash_date = official_pf_cash_date
         legacy = conn.execute(
             """SELECT total_value_chf,valuation_date,source_type FROM account_value_snapshots
-               WHERE account_id=? AND valuation_date<=? AND created_at<=? AND COALESCE(is_active,1)=1
+               WHERE account_id=? AND valuation_date<=? AND datetime(created_at)<=datetime(?)
+                 AND COALESCE(is_active,1)=1
                ORDER BY valuation_date DESC,
                         CASE source_type WHEN 'truewealth_official_import' THEN 3 WHEN 'truewealth_manual_provisional' THEN 2 ELSE 1 END DESC,
                         COALESCE(valuation_at,created_at) DESC,created_at DESC,snapshot_id DESC LIMIT 1""", (account, as_of, cutoff)
@@ -1614,7 +1643,8 @@ def build_portfolio_reconciliation(
         if total_value_only:
             canonical = conn.execute(
                 """SELECT value_original,valuation_at FROM portfolio_valuation_snapshots
-                   WHERE scope_kind='account' AND scope_id=? AND substr(valuation_at,1,10)<=? AND captured_at<=?
+                   WHERE scope_kind='account' AND scope_id=? AND substr(valuation_at,1,10)<=?
+                     AND datetime(captured_at)<=datetime(?)
                    ORDER BY valuation_at DESC,snapshot_version DESC,captured_at DESC,snapshot_id DESC LIMIT 1""", (account, as_of, cutoff)
             ).fetchone()
             derived_total = _stored_decimal(canonical["value_original"], "Kanonischer Totalwert") if canonical else None
@@ -1651,10 +1681,10 @@ def build_portfolio_reconciliation(
         return {"covered": covered, "total": total, "ratio": _decimal_text(Decimal(covered) / Decimal(total)) if total else None}
     instrument_total = len(keys)
     opening_rows = conn.execute(
-        f"SELECT COUNT(DISTINCT account_id) AS count FROM portfolio_valuation_snapshots WHERE account_id IN ({placeholders}) AND substr(valuation_at,1,10)<? AND captured_at<=?", (*account_map, as_of, cutoff)
+        f"SELECT COUNT(DISTINCT account_id) AS count FROM portfolio_valuation_snapshots WHERE account_id IN ({placeholders}) AND substr(valuation_at,1,10)<? AND datetime(captured_at)<=datetime(?)", (*account_map, as_of, cutoff)
     ).fetchone()
     closing_rows = conn.execute(
-        f"SELECT COUNT(DISTINCT account_id) AS count FROM portfolio_valuation_snapshots WHERE account_id IN ({placeholders}) AND substr(valuation_at,1,10)=? AND captured_at<=?", (*account_map, as_of, cutoff)
+        f"SELECT COUNT(DISTINCT account_id) AS count FROM portfolio_valuation_snapshots WHERE account_id IN ({placeholders}) AND substr(valuation_at,1,10)=? AND datetime(captured_at)<=datetime(?)", (*account_map, as_of, cutoff)
     ).fetchone()
     opening_covered = int(opening_rows["count"] or 0)
     closing_covered = int(closing_rows["count"] or 0)
diff --git a/src/jarvis_finance/services/postfinance_service.py b/src/jarvis_finance/services/postfinance_service.py
index 9ea4ba8..b34d319 100644
--- a/src/jarvis_finance/services/postfinance_service.py
+++ b/src/jarvis_finance/services/postfinance_service.py
@@ -2,12 +2,12 @@ from __future__ import annotations

 import base64
 import binascii
+import json
+import os
 from collections import defaultdict
 from datetime import UTC, datetime
 from decimal import Decimal
 from hashlib import sha256
-import json
-import os
 from pathlib import Path
 from sqlite3 import Connection, IntegrityError
 from typing import Any
@@ -22,6 +22,10 @@ from jarvis_finance.imports.postfinance_documents import (
     normalize_label,
     parse_postfinance_bundle,
 )
+from jarvis_finance.services.portfolio_aggregation import (
+    latest_official_postfinance_cash,
+    latest_official_postfinance_positions,
+)

 TOLERANCE = Decimal("0.05")

@@ -876,6 +880,10 @@ def get_postfinance_summary(conn: Connection) -> dict[str, Any]:
             "event_counts": {},
             "imports": [],
         }
+    official_position_values = {
+        override.instrument_id: override.market_value_chf
+        for override in latest_official_postfinance_positions(conn).values()
+    }
     positions = [
         {
             "row_key": _hash("position", row["instrument_name"], row["quantity"])[:16],
@@ -887,13 +895,13 @@ def get_postfinance_summary(conn: Connection) -> dict[str, Any]:
             "provider_cost_total_original": row["provider_cost_total_original"],
             "price_original": row["price_original"],
             "price_currency": row["price_currency"],
-            "value_chf": row["value_chf"],
+            "value_chf": _money(official_position_values.get(row["instrument_id"], Decimal(str(row["value_chf"])))),
             "weight_pct": row["weight_pct"],
             "computed_cost_basis_original": row["computed_cost_basis_original"],
             "computed_cost_basis_status": row["computed_cost_basis_status"],
         }
         for row in conn.execute(
-            """SELECT p.asset_class,p.quantity,p.provider_average_cost_original,
+            """SELECT p.instrument_id,p.asset_class,p.quantity,p.provider_average_cost_original,
                       p.provider_cost_total_original,p.price_original,p.price_currency,p.value_chf,
                       p.weight_pct,p.computed_cost_basis_original,p.computed_cost_basis_status,
                       i.name AS instrument_name,i.ticker
@@ -905,17 +913,13 @@ def get_postfinance_summary(conn: Connection) -> dict[str, Any]:
     ]
     cash = [
         {
-            "row_key": _hash("cash", row["currency"])[:16],
-            "currency": row["currency"],
-            "amount_original": row["amount_original"],
-            "fx_rate_to_chf": row["fx_rate_to_chf"],
-            "value_chf": row["value_chf"],
+            "row_key": _hash("cash", component.currency)[:16],
+            "currency": component.currency,
+            "amount_original": _text(component.amount_original),
+            "fx_rate_to_chf": _text(component.source_fx_rate_to_chf),
+            "value_chf": _money(component.amount_chf),
         }
-        for row in conn.execute(
-            """SELECT currency,amount_original,fx_rate_to_chf,value_chf
-               FROM postfinance_snapshot_cash WHERE snapshot_id=? ORDER BY currency""",
-            (latest["snapshot_id"],),
-        ).fetchall()
+        for component in latest_official_postfinance_cash(conn)
     ]
     events = {
         str(row["event_type"]): int(row["c"])


grep -R "CREATE TABLE postfinance_snapshots\|postfinance_snapshots" -n src tests | head -50 && grep -R "postfinance_import_batches" -n src/jarvis_finance | head -40


Output:
Chunk ID: 02d7d8
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1343
Output:
grep: src/jarvis_finance/storage/__pycache__/postfinance_schema.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/postfinance_service.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/portfolio_aggregation.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/portfolio_aggregation.cpython-312.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/postfinance_service.cpython-312.pyc: binary file matches
grep: tests/__pycache__/test_postfinance_sprint13.cpython-311-pytest-9.1.1.pyc: binary file matches
grep: tests/__pycache__/test_postfinance_sprint13.cpython-311.pyc: binary file matches
grep: tests/__pycache__/test_postfinance_sprint13.cpython-311-pytest-9.0.2.pyc: binary file matches
src/jarvis_finance/storage/postfinance_schema.py:56:        CREATE TABLE IF NOT EXISTS postfinance_snapshots (
src/jarvis_finance/storage/postfinance_schema.py:77:            snapshot_id TEXT NOT NULL REFERENCES postfinance_snapshots(snapshot_id),
src/jarvis_finance/storage/postfinance_schema.py:97:            snapshot_id TEXT NOT NULL REFERENCES postfinance_snapshots(snapshot_id),
src/jarvis_finance/storage/postfinance_schema.py:172:        CREATE TRIGGER IF NOT EXISTS postfinance_snapshots_immutable BEFORE UPDATE ON postfinance_snapshots
src/jarvis_finance/storage/postfinance_schema.py:174:        CREATE TRIGGER IF NOT EXISTS postfinance_snapshots_no_delete BEFORE DELETE ON postfinance_snapshots
src/jarvis_finance/services/portfolio_aggregation.py:117:            FROM postfinance_snapshots {where}
src/jarvis_finance/services/portfolio_aggregation.py:170:            FROM postfinance_snapshots {where}
src/jarvis_finance/services/postfinance_service.py:602:            """INSERT INTO postfinance_snapshots(snapshot_id,batch_id,account_id,snapshot_at,total_chf,securities_chf,cash_chf,stocks_chf,etfs_chf,component_total_chf,difference_chf,tolerance_chf,position_count,cash_count,open_orders,reconciliation_status,created_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,? ,?,?,?,?,?)""",
src/jarvis_finance/services/postfinance_service.py:873:           FROM postfinance_snapshots ORDER BY snapshot_at DESC,created_at DESC LIMIT 1"""
src/jarvis_finance/services/postfinance_service.py:937:               FROM postfinance_import_batches b JOIN postfinance_snapshots s ON s.batch_id=b.batch_id
tests/test_postfinance_sprint13.py:299:    assert conn.execute("SELECT COUNT(*) FROM postfinance_snapshots").fetchone()[0] == 1
tests/test_postfinance_sprint13.py:469:            "UPDATE postfinance_snapshots SET total_chf='0' WHERE snapshot_id=?",
tests/test_postfinance_sprint13.py:474:            "DELETE FROM postfinance_snapshots WHERE snapshot_id=?", (result["snapshot_id"],)
tests/test_postfinance_sprint13.py:754:    source_snapshot = dict(conn.execute("SELECT * FROM postfinance_snapshots LIMIT 1").fetchone())
tests/test_postfinance_sprint13.py:770:        f"INSERT INTO postfinance_snapshots({','.join(columns)}) VALUES({','.join('?' for _ in columns)})",
grep: src/jarvis_finance/storage/__pycache__/postfinance_schema.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/postfinance_service.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/postfinance_service.cpython-312.pyc: binary file matches
src/jarvis_finance/storage/postfinance_schema.py:22:        CREATE TABLE IF NOT EXISTS postfinance_import_batches (
src/jarvis_finance/storage/postfinance_schema.py:52:            batch_id TEXT NOT NULL REFERENCES postfinance_import_batches(batch_id),
src/jarvis_finance/storage/postfinance_schema.py:58:            batch_id TEXT NOT NULL UNIQUE REFERENCES postfinance_import_batches(batch_id),
src/jarvis_finance/storage/postfinance_schema.py:160:        CREATE TRIGGER IF NOT EXISTS postfinance_batches_immutable BEFORE UPDATE ON postfinance_import_batches
src/jarvis_finance/storage/postfinance_schema.py:162:        CREATE TRIGGER IF NOT EXISTS postfinance_batches_no_delete BEFORE DELETE ON postfinance_import_batches
src/jarvis_finance/services/postfinance_service.py:167:        "postfinance_import_batches",
src/jarvis_finance/services/postfinance_service.py:171:        if table == "postfinance_import_batches":
src/jarvis_finance/services/postfinance_service.py:319:        "SELECT batch_id FROM postfinance_import_batches WHERE bundle_sha256=?",
src/jarvis_finance/services/postfinance_service.py:323:        "SELECT batch_id FROM postfinance_import_batches WHERE substr(snapshot_at,1,10)=? AND bundle_sha256<>?",
src/jarvis_finance/services/postfinance_service.py:501:            "SELECT batch_id,audit_id FROM postfinance_import_batches WHERE bundle_sha256=?",
src/jarvis_finance/services/postfinance_service.py:553:            """INSERT INTO postfinance_import_batches(batch_id,bundle_sha256,zip_sha256,overview_sha256,parser_id,parser_version,db_revision,archive_reference,snapshot_at,status,audit_id,confirmed_at,confirmed_by) VALUES(?,?,?,?,?,?,?,?,?,'confirmed',?,?,'user')""",
src/jarvis_finance/services/postfinance_service.py:840:            "SELECT batch_id,audit_id FROM postfinance_import_batches WHERE bundle_sha256=?",
src/jarvis_finance/services/postfinance_service.py:937:               FROM postfinance_import_batches b JOIN postfinance_snapshots s ON s.batch_id=b.batch_id


sed -n '1,130p' src/jarvis_finance/storage/postfinance_schema.py && sed -n '520,640p' src/jarvis_finance/services/postfinance_service.py


Output:
Chunk ID: e5f35e
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 3282
Output:
from __future__ import annotations

from sqlite3 import Connection

def create_postfinance_ledger_import_v1(conn: Connection) -> None:
    """Create immutable PostFinance source, ledger, snapshot and cost-basis tables."""
    position_columns = {row[1] for row in conn.execute("PRAGMA table_info(positions_snapshot)")}
    if "source_type" not in position_columns:
        conn.execute("ALTER TABLE positions_snapshot ADD COLUMN source_type TEXT")
    if "source_reference" not in position_columns:
        conn.execute("ALTER TABLE positions_snapshot ADD COLUMN source_reference TEXT")
    conn.executescript(
        """
        CREATE TABLE IF NOT EXISTS postfinance_account_roles (
            role TEXT PRIMARY KEY CHECK(role IN ('efinance','etrading_depot','etrading_cash')),
            account_id TEXT NOT NULL REFERENCES accounts(account_id),
            source_reference_hash TEXT,
            created_at TEXT NOT NULL,
            UNIQUE(account_id, role)
        );
        CREATE TABLE IF NOT EXISTS postfinance_import_batches (
            batch_id TEXT PRIMARY KEY,
            bundle_sha256 TEXT NOT NULL UNIQUE CHECK(length(bundle_sha256)=64),
            zip_sha256 TEXT NOT NULL CHECK(length(zip_sha256)=64),
            overview_sha256 TEXT NOT NULL CHECK(length(overview_sha256)=64),
            parser_id TEXT NOT NULL,
            parser_version TEXT NOT NULL,
            db_revision TEXT NOT NULL,
            archive_reference TEXT NOT NULL,
            snapshot_at TEXT NOT NULL,
            status TEXT NOT NULL CHECK(status='confirmed'),
            audit_id TEXT NOT NULL,
            confirmed_at TEXT NOT NULL,
            confirmed_by TEXT NOT NULL DEFAULT 'user'
        );
        CREATE TABLE IF NOT EXISTS postfinance_documents (
            document_hash TEXT PRIMARY KEY CHECK(length(document_hash)=64),
            filename_hash TEXT NOT NULL CHECK(length(filename_hash)=64),
            semantic_identity TEXT NOT NULL UNIQUE CHECK(length(semantic_identity)=64),
            semantic_reference_hash TEXT NOT NULL CHECK(length(semantic_reference_hash)=64),
            document_type TEXT NOT NULL,
            document_date TEXT,
            account_reference_hash TEXT,
            account_role TEXT NOT NULL CHECK(account_role IN ('efinance','etrading_depot','etrading_cash')),
            page_count INTEGER NOT NULL CHECK(page_count > 0),
            archive_reference TEXT NOT NULL,
            parser_version TEXT NOT NULL,
            created_at TEXT NOT NULL
        );
        CREATE TABLE IF NOT EXISTS postfinance_batch_documents (
            batch_id TEXT NOT NULL REFERENCES postfinance_import_batches(batch_id),
            document_hash TEXT NOT NULL REFERENCES postfinance_documents(document_hash),
            PRIMARY KEY(batch_id, document_hash)
        );
        CREATE TABLE IF NOT EXISTS postfinance_snapshots (
            snapshot_id TEXT PRIMARY KEY,
            batch_id TEXT NOT NULL UNIQUE REFERENCES postfinance_import_batches(batch_id),
            account_id TEXT NOT NULL REFERENCES accounts(account_id),
            snapshot_at TEXT NOT NULL,
            total_chf TEXT NOT NULL,
            securities_chf TEXT NOT NULL,
            cash_chf TEXT NOT NULL,
            stocks_chf TEXT NOT NULL,
            etfs_chf TEXT NOT NULL,
            component_total_chf TEXT NOT NULL,
            difference_chf TEXT NOT NULL,
            tolerance_chf TEXT NOT NULL,
            position_count INTEGER NOT NULL,
            cash_count INTEGER NOT NULL,
            open_orders INTEGER NOT NULL,
            reconciliation_status TEXT NOT NULL CHECK(reconciliation_status IN ('matched','within_tolerance')),
            created_at TEXT NOT NULL
        );
        CREATE TABLE IF NOT EXISTS postfinance_snapshot_positions (
            snapshot_position_id TEXT PRIMARY KEY,
            snapshot_id TEXT NOT NULL REFERENCES postfinance_snapshots(snapshot_id),
            source_row_reference TEXT NOT NULL,
            instrument_id TEXT NOT NULL REFERENCES instruments(instrument_id),
            asset_class TEXT NOT NULL CHECK(asset_class IN ('stock','etf')),
            quantity TEXT NOT NULL,
            provider_average_cost_original TEXT,
            provider_cost_total_original TEXT,
            price_original TEXT NOT NULL,
            price_currency TEXT NOT NULL,
            value_chf TEXT NOT NULL,
            weight_pct TEXT NOT NULL,
            computed_cost_basis_original TEXT,
            computed_cost_basis_status TEXT NOT NULL CHECK(computed_cost_basis_status IN ('complete','partial','unavailable')),
            provenance_json TEXT NOT NULL CHECK(json_valid(provenance_json)),
            created_at TEXT NOT NULL,
            UNIQUE(snapshot_id, source_row_reference),
            UNIQUE(snapshot_id, instrument_id)
        );
        CREATE TABLE IF NOT EXISTS postfinance_snapshot_cash (
            snapshot_cash_id TEXT PRIMARY KEY,
            snapshot_id TEXT NOT NULL REFERENCES postfinance_snapshots(snapshot_id),
            currency TEXT NOT NULL,
            amount_original TEXT NOT NULL,
            fx_rate_to_chf TEXT NOT NULL,
            value_chf TEXT NOT NULL,
            created_at TEXT NOT NULL,
            UNIQUE(snapshot_id, currency)
        );
        CREATE TABLE IF NOT EXISTS postfinance_ledger_events (
            event_id TEXT PRIMARY KEY,
            event_fingerprint TEXT NOT NULL UNIQUE CHECK(length(event_fingerprint)=64),
            document_hash TEXT NOT NULL REFERENCES postfinance_documents(document_hash),
            semantic_reference_hash TEXT NOT NULL CHECK(length(semantic_reference_hash)=64),
            event_type TEXT NOT NULL CHECK(event_type IN ('buy','sell','dividend','interest','fee','internal_transfer','fx','split','corporate_action')),
            account_role TEXT NOT NULL CHECK(account_role IN ('efinance','etrading_depot','etrading_cash')),
            account_id TEXT NOT NULL REFERENCES accounts(account_id),
            occurred_on TEXT NOT NULL,
            settlement_on TEXT,
            direction TEXT NOT NULL CHECK(direction IN ('in','out','neutral')),
            instrument_id TEXT REFERENCES instruments(instrument_id),
            quantity TEXT,
            price_original TEXT,
            gross_original TEXT,
            fee_original TEXT NOT NULL DEFAULT '0',
            tax_original TEXT NOT NULL DEFAULT '0',
            net_original TEXT,
            currency TEXT,
            fx_rate_to_chf TEXT,
            internal_transfer_group TEXT,
            quality_status TEXT NOT NULL CHECK(quality_status IN ('complete','partial')),
            reason_codes_json TEXT NOT NULL CHECK(json_valid(reason_codes_json)),
            created_at TEXT NOT NULL
        );
        CREATE INDEX IF NOT EXISTS idx_postfinance_events_time ON postfinance_ledger_events(occurred_on, event_type);
        event.event_fingerprint: _event_instrument(event, bundle, position_map, conn)
        for event in bundle.events
    }
    archive_refs: list[tuple[str, bool]] = []
    zip_ref, created = _archive(zip_raw, bundle.zip_hash, "zip")
    archive_refs.append((zip_ref, created))
    overview_ref, created = _archive(overview_raw, bundle.overview_hash, "pdf")
    archive_refs.append((overview_ref, created))
    for document in bundle.documents:
        reference, created = _archive(document.raw, document.document_hash, "pdf")
        archive_refs.append((reference, created))
    now = _now()
    batch_id = _id("pfbatch")
    snapshot_id = _id("pfsnapshot")
    try:
        conn.execute("BEGIN IMMEDIATE")
        if _revision(conn, accounts) != preview["db_revision"]:
            raise ValueError("PostFinance database revision changed before persistence")
        _ensure_efinance_account(conn, accounts, now)
        for role, account_id in accounts.items():
            conn.execute(
                "INSERT OR IGNORE INTO postfinance_account_roles(role,account_id,source_reference_hash,created_at) VALUES(?,?,NULL,?)",
                (role, account_id, now),
            )
            mapped = conn.execute(
                "SELECT account_id FROM postfinance_account_roles WHERE role=?", (role,)
            ).fetchone()
            if not mapped or mapped["account_id"] != account_id:
                raise ValueError(
                    "PostFinance account-role mapping conflicts with confirmed mapping"
                )
        audit_id = _audit(conn, batch_id, bundle, now)
        conn.execute(
            """INSERT INTO postfinance_import_batches(batch_id,bundle_sha256,zip_sha256,overview_sha256,parser_id,parser_version,db_revision,archive_reference,snapshot_at,status,audit_id,confirmed_at,confirmed_by) VALUES(?,?,?,?,?,?,?,?,?,'confirmed',?,?,'user')""",
            (
                batch_id,
                bundle.bundle_hash,
                bundle.zip_hash,
                bundle.overview_hash,
                PARSER_ID,
                PARSER_VERSION,
                preview["db_revision"],
                zip_ref,
                bundle.snapshot.valuation_at,
                audit_id,
                now,
            ),
        )
        for document in bundle.documents:
            reference = f"postfinance/archive/{document.document_hash}.pdf"
            ref_hash = _hash(document.semantic_reference)
            existing = conn.execute(
                "SELECT document_hash FROM postfinance_documents WHERE semantic_identity=?",
                (document.semantic_identity,),
            ).fetchone()
            if existing and existing["document_hash"] != document.document_hash:
                raise ValueError("PostFinance semantic document conflict")
            conn.execute(
                """INSERT OR IGNORE INTO postfinance_documents(document_hash,filename_hash,semantic_identity,semantic_reference_hash,document_type,document_date,account_reference_hash,account_role,page_count,archive_reference,parser_version,created_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?)""",
                (
                    document.document_hash,
                    document.filename_hash,
                    document.semantic_identity,
                    ref_hash,
                    document.document_type,
                    document.document_date,
                    document.account_reference_hash,
                    document.account_role,
                    document.page_count,
                    reference,
                    PARSER_VERSION,
                    now,
                ),
            )
            conn.execute(
                "INSERT INTO postfinance_batch_documents(batch_id,document_hash) VALUES(?,?)",
                (batch_id, document.document_hash),
            )
        snapshot = bundle.snapshot
        component_total = snapshot.securities_total_chf + snapshot.cash_total_chf
        difference = snapshot.total_value_chf - component_total
        conn.execute(
            """INSERT INTO postfinance_snapshots(snapshot_id,batch_id,account_id,snapshot_at,total_chf,securities_chf,cash_chf,stocks_chf,etfs_chf,component_total_chf,difference_chf,tolerance_chf,position_count,cash_count,open_orders,reconciliation_status,created_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,? ,?,?,?,?,?)""",
            (
                snapshot_id,
                batch_id,
                accounts["etrading_depot"],
                snapshot.valuation_at,
                _money(snapshot.total_value_chf),
                _money(snapshot.securities_total_chf),
                _money(snapshot.cash_total_chf),
                _money(snapshot.stock_total_chf),
                _money(snapshot.etf_total_chf),
                _money(component_total),
                _money(difference),
                _money(TOLERANCE),
                len(snapshot.positions),
                len(snapshot.cash),
                snapshot.open_orders,
                "matched" if difference == 0 else "within_tolerance",
                now,
            ),
        )
        for event in bundle.events:
            instrument_id = event_instruments[event.event_fingerprint]
            event_id = f"pfevent_{event.event_fingerprint[:24]}"
            account_id = accounts[event.account_role]
            conn.execute(
                """INSERT INTO postfinance_ledger_events(event_id,event_fingerprint,document_hash,semantic_reference_hash,event_type,account_role,account_id,occurred_on,settlement_on,direction,instrument_id,quantity,price_original,gross_original,fee_original,tax_original,net_original,currency,fx_rate_to_chf,internal_transfer_group,quality_status,reason_codes_json,created_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
                (
                    event_id,
                    event.event_fingerprint,
                    event.document_hash,
                    _hash(event.semantic_reference),
                    event.event_type,
                    event.account_role,
                    account_id,
                    event.occurred_on,
                    event.settlement_on,
                    event.direction or "neutral",
                    instrument_id,


Output:
Chunk ID: 543fc9
Wall time: 2.1151 seconds
Process exited with code 0
Original token count: 25
Output:
.........                                                                [100%]
9 passed in 1.87s


sed -n '180,280p' src/jarvis_finance/services/portfolio_analytics.py && grep -R "def calculate_positions" -n src/jarvis_finance/ledger/positions.py && sed -n '1,220p' src/jarvis_finance/ledger/positions.py


Output:
Chunk ID: fb5854
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 3612
Output:
        currency=currency,
        close=close,
        adjusted_close=_decimal(row["adjusted_close"]) if row["adjusted_close"] not in {None, ""} else None,
        provider=str(row["provider"]),
        provider_market=row["provider_market"],
        price_timestamp=row["price_timestamp"] or actual_price_date.isoformat(),
        quality_status=str(row["quality_status"]),
        error_message=row["error_message"],
    )
    provenance = {
        "market_price_id": str(row["market_price_id"]),
        "provider": str(row["provider"]),
        "provider_symbol": str(row["provider_symbol"]),
        "provider_market": str(row["provider_market"] or ""),
        "price_date": actual_price_date.isoformat(),
        "original_run_id": str(row["run_id"]) if row["run_id"] else None,
        "fetched_at": str(row["fetched_at"]) if row["fetched_at"] else None,
        "created_at": str(row["created_at"]) if row["created_at"] else None,
    }
    return quote, provenance

def confirmed_canonical_positions(conn: Connection, *, as_of: str | None = None) -> list[ConfirmedPosition]:
    """Return only active, confirmed ledger positions. Preview and ingestion staging tables are never read."""

    rows = conn.execute(
        """
        SELECT t.account_id, t.instrument_id, i.isin, i.name, lower(i.asset_class) AS asset_class,
               upper(COALESCE(i.trading_currency, i.currency, '')) AS instrument_currency,
               t.transaction_type, t.quantity
        FROM transactions t
        JOIN instruments i ON i.instrument_id=t.instrument_id
        JOIN accounts a ON a.account_id=t.account_id
        WHERE t.instrument_id IS NOT NULL
          AND COALESCE(t.is_confirmed, 0)=1
          AND COALESCE(t.is_voided, 0)=0
          AND i.is_active=1 AND a.is_active=1
          AND COALESCE(i.instrument_status,'active') NOT IN ('inactive','delisted','suspended','merged')
          AND COALESCE(i.valuation_policy,'')!='exclude_from_auto_price_update'
          AND lower(i.asset_class) IN ('stock','equity','etf')
          AND lower(t.transaction_type) IN ('initial_position_snapshot','buy','sell','partial_sell','full_sell')
          AND t.trade_date<=?
        ORDER BY t.account_id, t.instrument_id, t.trade_date, t.created_at
        """,
        (as_of or datetime.now(timezone.utc).date().isoformat(),),
    ).fetchall()
    grouped: dict[tuple[str, str], dict[str, Any]] = {}
    for row in rows:
        key = (str(row["account_id"]), str(row["instrument_id"]))
        item = grouped.setdefault(key, dict(row) | {"quantity_total": ZERO})
        quantity = _decimal(row["quantity"])
        item["quantity_total"] += -abs(quantity) if str(row["transaction_type"]).lower() in SELL_TYPES else quantity
    official = latest_official_postfinance_positions(conn, as_of=as_of)
    post_snapshot_deltas = post_snapshot_postfinance_quantity_deltas(
        conn,
        official,
        as_of=as_of,
    )
    trading_cash_id = postfinance_account_roles(conn).get("etrading_cash")
    official_instruments = {key[1] for key in official}
    for key in list(grouped):
        if key[0] == trading_cash_id and key[1] in official_instruments:
            grouped.pop(key)
    for key, override in official.items():
        item = grouped.get(key)
        if item is None:
            instrument = conn.execute(
                """SELECT isin,name,lower(asset_class) asset_class,
                          upper(COALESCE(trading_currency,currency,'')) instrument_currency
                   FROM instruments WHERE instrument_id=? AND is_active=1""",
                (override.instrument_id,),
            ).fetchone()
            if not instrument:
                continue
            item = {
                "account_id": override.account_id,
                "instrument_id": override.instrument_id,
                "isin": instrument["isin"],
                "name": instrument["name"],
                "asset_class": instrument["asset_class"],
                "instrument_currency": instrument["instrument_currency"],
            }
            grouped[key] = item
        # The official snapshot is the baseline. Only confirmed trades after that
        # snapshot are replayed, so imported history is not counted twice.
        item["quantity_total"] = override.quantity + post_snapshot_deltas.get(
            override.instrument_id,
            ZERO,
        )
    return [
        ConfirmedPosition(
            account_id=item["account_id"],
            instrument_id=item["instrument_id"],
            isin=item["isin"],
            name=item["name"],
            asset_class=item["asset_class"],
            instrument_currency=item["instrument_currency"],
            quantity=item["quantity_total"],
        )
        for item in grouped.values()
        if item["quantity_total"] > ZERO
135:def calculate_positions(
from __future__ import annotations

from dataclasses import dataclass, field
from datetime import datetime, timezone
from decimal import Decimal, ROUND_HALF_UP
from sqlite3 import Connection

from jarvis_finance.audit.log import record_audit_event
from jarvis_finance.imports.common import stable_id, utc_now
from jarvis_finance.quality.alerts import create_alert
from jarvis_finance.fx.rates import latest_fx_rate

from .cost_basis import WeightedAverageLot

MONEY = Decimal("0.01")

def _d(value: object, default: str = "0") -> Decimal:
    if value is None or str(value).strip() == "":
        return Decimal(default)
    return Decimal(str(value))

def _money(value: Decimal | None) -> Decimal | None:
    if value is None:
        return None
    return value.quantize(MONEY, rounding=ROUND_HALF_UP)

@dataclass
class Position:
    account_id: str
    instrument_id: str
    quantity: Decimal = Decimal("0")
    cost_basis_original: Decimal = Decimal("0")
    cost_basis_chf: Decimal = Decimal("0")
    average_cost_original: Decimal | None = None
    average_cost_chf: Decimal | None = None
    realized_pnl_chf: Decimal = Decimal("0")
    income_chf: Decimal = Decimal("0")
    fees_chf: Decimal = Decimal("0")
    taxes_chf: Decimal = Decimal("0")
    market_price_original: Decimal | None = None
    market_value_original: Decimal | None = None
    market_value_chf: Decimal | None = None
    unrealized_pnl_chf: Decimal | None = None
    total_return_chf: Decimal | None = None
    data_quality_status: str = "ok"
    valuation_status: str = "not_valuable"
    valuation_timestamp_status: str = "missing_timestamp"
    hedge_status: str = "unknown"
    instrument_status: str = "unknown"
    valuation_policy: str = "live_price"
    corporate_action_status: str = "not_checked"
    quality_warnings: list[str] = field(default_factory=list)

@dataclass
class PositionCalculationResult:
    positions: dict[tuple[str, str], Position] = field(default_factory=dict)
    as_of_date: str | None = None

def _latest_market_price(conn: Connection, instrument_id: str, as_of_date: str | None):
    if as_of_date:
        return conn.execute(
            """
            SELECT close, currency, price_timestamp, price_date, corporate_action_status FROM market_prices
            WHERE instrument_id=? AND price_date <= ? AND quality_status IN ('fresh','ok')
            ORDER BY price_date DESC, created_at DESC LIMIT 1
            """,
            (instrument_id, as_of_date),
        ).fetchone()
    return conn.execute(
        """
        SELECT close, currency, price_timestamp, price_date, corporate_action_status FROM market_prices
        WHERE instrument_id=? AND quality_status IN ('fresh','ok')
        ORDER BY price_date DESC, created_at DESC LIMIT 1
        """,
        (instrument_id,),
    ).fetchone()

def _add_warning(
    conn: Connection,
    pos: Position,
    rule_id: str,
    message: str,
    *,
    persist: bool = True,
) -> None:
    if rule_id not in pos.quality_warnings:
        pos.quality_warnings.append(rule_id)
    pos.data_quality_status = "incomplete"
    if persist:
        create_alert(
            conn,
            priority="kritisch" if rule_id == "missing_fx" else "warnung",
            category="ledger",
            entity_type="instrument",
            entity_id=pos.instrument_id,
            rule_id=rule_id,
            message=message,
            evidence={"account_id": pos.account_id, "instrument_id": pos.instrument_id},
        )

def _timestamp_status(price_ts: str | None, fx_ts: str | None, *, max_delta_hours: int = 24) -> str:
    if not price_ts or not fx_ts:
        return "missing_timestamp"
    try:
        p = datetime.fromisoformat(price_ts.replace("Z", "+00:00"))
        f = datetime.fromisoformat(fx_ts.replace("Z", "+00:00"))
        if p.tzinfo is None:
            p = p.replace(tzinfo=timezone.utc)
        if f.tzinfo is None:
            f = f.replace(tzinfo=timezone.utc)
    except ValueError:
        return "missing_timestamp"
    delta_hours = abs((p - f).total_seconds()) / 3600
    if delta_hours <= 1:
        return "aligned"
    if delta_hours <= max_delta_hours:
        return "acceptable"
    return "stale_mismatch"

def _instrument_metadata(conn: Connection, instrument_id: str) -> dict[str, object]:
    row = conn.execute("SELECT * FROM instruments WHERE instrument_id=?", (instrument_id,)).fetchone()
    if not row:
        return {"hedge_status": "unknown", "instrument_status": "unknown", "valuation_policy": "live_price", "corporate_action_status": "not_checked"}
    return dict(row)

def calculate_positions(
    conn: Connection,
    *,
    as_of_date: str | None = None,
    max_price_fx_time_delta_hours: int = 24,
    persist_alerts: bool = True,
) -> PositionCalculationResult:
    def add_warning(pos: Position, rule_id: str, message: str) -> None:
        _add_warning(conn, pos, rule_id, message, persist=persist_alerts)

    result = PositionCalculationResult(as_of_date=as_of_date)
    lots: dict[tuple[str, str], WeightedAverageLot] = {}
    params: tuple[object, ...] = ()
    where = "WHERE instrument_id IS NOT NULL AND COALESCE(is_voided, 0) = 0"
    if as_of_date:
        where += " AND trade_date <= ?"
        params = (as_of_date,)
    rows = conn.execute(
        f"""
        SELECT * FROM transactions
        {where}
        ORDER BY account_id, instrument_id, trade_date, created_at, transaction_id
        """,
        params,
    ).fetchall()
    for row in rows:
        key = (row["account_id"], row["instrument_id"])
        pos = result.positions.setdefault(key, Position(row["account_id"], row["instrument_id"]))
        lot = lots.setdefault(key, WeightedAverageLot())
        t = row["transaction_type"]
        qty = _d(row["quantity"])
        gross = _d(row["gross_amount_original"])
        fee = _d(row["fee_original"])
        tax = _d(row["tax_original"])
        fx = _d(row["fx_rate_to_chf"], "1") if row["fx_rate_to_chf"] is not None else None
        if fx is None or row["fx_status"] == "missing":
            add_warning(pos, "missing_fx", "Historic FX is missing; precise CHF total return cannot be calculated.")
        if t in {"initial_position_snapshot", "buy"}:
            if qty > 0:
                cost_original = gross + fee
                cost_chf = (gross + fee) * fx if fx is not None else Decimal("0")
                lot.buy(qty, cost_original, cost_chf)
                pos.fees_chf += fee * fx if fx is not None else Decimal("0")
                pos.taxes_chf += tax * fx if fx is not None else Decimal("0")
        elif t in {"partial_sell", "full_sell"}:
            if qty > 0:
                proceeds_chf = (gross - fee - tax) * fx if fx is not None else Decimal("0")
                lot.sell(qty, proceeds_chf)
                pos.fees_chf += fee * fx if fx is not None else Decimal("0")
                pos.taxes_chf += tax * fx if fx is not None else Decimal("0")
        elif t in {"dividend", "etf_distribution"}:
            income_original = _d(row["net_amount_original"]) if row["net_amount_original"] is not None else gross - fee - tax
            if fx is not None:
                pos.income_chf += income_original * fx
                pos.fees_chf += fee * fx
                pos.taxes_chf += tax * fx
        if t == "initial_position_snapshot":
            add_warning(pos, "snapshot_only", "Initial snapshot lacks full transaction history; performance is incomplete.")
            if gross == 0 or fx is None:
                add_warning(pos, "cost_basis_uncertain", "Cost basis is uncertain for this initial snapshot.")
    for key, lot in lots.items():
        pos = result.positions[key]
        meta = _instrument_metadata(conn, pos.instrument_id)
        pos.hedge_status = str(meta.get("hedge_status") or "unknown")
        pos.instrument_status = str(meta.get("instrument_status") or "unknown")
        pos.valuation_policy = str(meta.get("valuation_policy") or "live_price")
        pos.corporate_action_status = str(meta.get("corporate_action_status") or "not_checked")
        if pos.hedge_status == "unknown":
            add_warning(pos, "hedge_status_unknown", "Currency hedge status is unknown; FX attribution is incomplete.")
        if pos.instrument_status in {"delisted", "suspended", "merged", "inactive"} and pos.valuation_policy in {"live_price", "exclude_from_auto_price_update"}:
            add_warning(pos, "delisted_or_suspended", "Instrument status excludes or limits automatic valuation.")
        if pos.corporate_action_status in {"suspected", "confirmed"} or meta.get("split_or_corporate_action_review_required"):
            add_warning(pos, "corporate_action_suspected", "Corporate action review is required before high-confidence valuation.")
        pos.quantity = lot.quantity.normalize()
        pos.cost_basis_original = _money(lot.cost_basis_original) or Decimal("0")
        pos.cost_basis_chf = _money(lot.cost_basis_chf) or Decimal("0")
        pos.average_cost_original = lot.average_cost_original
        pos.average_cost_chf = lot.average_cost_chf
        pos.realized_pnl_chf = _money(lot.realized_pnl_chf) or Decimal("0")
        pos.income_chf = _money(pos.income_chf) or Decimal("0")
        pos.fees_chf = _money(pos.fees_chf) or Decimal("0")
        pos.taxes_chf = _money(pos.taxes_chf) or Decimal("0")
        market = _latest_market_price(conn, pos.instrument_id, as_of_date)
        if market is None:
            add_warning(pos, "missing_market_price", "Market price is missing; unrealized P&L cannot be calculated.")
        else:


grep -R "transaction_type.*sell\|transaction_type.*'sell'\|\"sell\"" -n src tests | head -100


Output:
Chunk ID: 5d0508
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1097
Output:
grep: src/jarvis_finance/services/__pycache__/portfolio_aggregation.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/portfolio_analytics.cpython-312.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/portfolio_analytics.cpython-311.pyc: binary file matches
src/jarvis_finance/crypto/transactions.py:327:        tx_type="sell",
src/jarvis_finance/crypto/holdings.py:134:        elif t == "sell":
src/jarvis_finance/ledger/cash.py:49:    elif t in {"sell", "partial_sell", "full_sell"}:
src/jarvis_finance/ledger/cost_basis.py:124:        if kind != "sell":
src/jarvis_finance/imports/postfinance_documents.py:333:            else "sell"
src/jarvis_finance/equity/manage.py:546:    if transaction_type in {"buy", "partial_sell", "full_sell", "initial_position_snapshot"} and qty <= 0:
src/jarvis_finance/equity/manage.py:550:    if transaction_type in {"partial_sell", "full_sell"}:
src/jarvis_finance/equity/manage.py:555:        if transaction_type == "full_sell" and qty != current_qty:
src/jarvis_finance/equity/manage.py:679:    if transaction_type in {"initial_position_snapshot", "buy", "partial_sell", "full_sell", "manual_adjustment"} and qty <= 0:
src/jarvis_finance/equity/manage.py:695:    if transaction_type in {"partial_sell", "full_sell"}:
src/jarvis_finance/equity/manage.py:700:        if transaction_type == "full_sell" and qty != current_qty:
src/jarvis_finance/services/portfolio_aggregation.py:243:              AND lower(transaction_type) IN ('buy','sell','partial_sell','full_sell')
src/jarvis_finance/services/portfolio_aggregation.py:251:        if str(row["transaction_type"]) in {"sell", "partial_sell", "full_sell"}:
src/jarvis_finance/services/portfolio_data.py:45:    "sell", "dividend", "etf_distribution", "distribution", "fee", "tax",
src/jarvis_finance/services/portfolio_data.py:48:POSITION_ACTIVITY_TYPES = {"buy", "partial_sell", "full_sell", "sell", "initial_position_snapshot"}
src/jarvis_finance/services/portfolio_data.py:1496:        elif kind in {"partial_sell", "full_sell", "sell"}:
src/jarvis_finance/services/portfolio_performance.py:37:    "partial_sell": "sell",
src/jarvis_finance/services/portfolio_performance.py:38:    "full_sell": "sell",
src/jarvis_finance/services/portfolio_performance.py:39:    "sell": "sell",
src/jarvis_finance/services/portfolio_performance.py:338:        if item.kind not in {"buy", "sell"}:
src/jarvis_finance/services/portfolio_analytics.py:40:SELL_TYPES = {"sell", "partial_sell", "full_sell"}
src/jarvis_finance/services/portfolio_analytics.py:220:          AND lower(t.transaction_type) IN ('initial_position_snapshot','buy','sell','partial_sell','full_sell')
src/jarvis_finance/services/postfinance_service.py:425:        "sell": "sell",
src/jarvis_finance/services/postfinance_service.py:693:            elif event.event_type == "sell" and instrument_id and event.quantity:
tests/unit/test_portfolio_performance_foundation.py:150:    add_activity(conn, "sell", "sell", "2025-02-10T00:00:00", instrument_id="i", quantity="4", gross="480", fee="2", tax="3")
tests/unit/test_portfolio_performance_foundation.py:190:            {"activity_id": "sell", "kind": "sell", "quantity": Decimal("4"), "gross": Decimal("480"), "fee": Decimal("2"), "tax": Decimal("3")},
tests/unit/test_portfolio_performance_foundation.py:203:        {"activity_id": "s", "kind": "sell", "quantity": Decimal("4"), "gross": Decimal("600"), "fee": Decimal("4"), "tax": Decimal("0")},
tests/unit/test_portfolio_performance_foundation.py:365:    add_activity(conn, "sell-old", "sell", "2024-06-01", instrument_id="i", quantity="2", gross="240")
tests/unit/test_portfolio_performance_foundation.py:366:    add_activity(conn, "sell-period", "sell", "2025-06-01", instrument_id="i", quantity="2", gross="260")
tests/unit/test_equity_manage.py:175:        transaction_type="partial_sell",
tests/unit/test_equity_manage.py:191:            transaction_type="partial_sell",
tests/unit/test_equity_manage.py:275:            transaction_type="full_sell",
tests/unit/test_equity_manage.py:288:        transaction_type="full_sell",
tests/unit/test_crypto_core.py:148:    assert ledger['transaction_type'] == 'partial_sell'
tests/unit/test_dashboard_functional_actions_v2.py:101:    assert tx[:] == ("sell", "-4", "47", "1")
tests/test_postfinance_sprint13.py:366:        event_type="sell",


sed -n '660,730p' src/jarvis_finance/services/postfinance_service.py && sed -n '1480,1510p' src/jarvis_finance/services/portfolio_data.py


Output:
Chunk ID: 1fb68a
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1292
Output:
            ):
                if amount is not None and event.currency:
                    conn.execute(
                        "INSERT INTO postfinance_event_components(component_id,event_id,component_type,amount_original,currency,provenance_document_hash,created_at) VALUES(?,?,?,?,?,?,?)",
                        (
                            _id("pfcomponent"),
                            event_id,
                            kind,
                            _text(amount),
                            event.currency,
                            event.document_hash,
                            now,
                        ),
                    )
            _canonical_transaction(conn, event_id, event, account_id, instrument_id, now)
        lots: dict[str, list[dict[str, Any]]] = defaultdict(list)
        for event in sorted(
            bundle.events,
            key=lambda item: (
                item.occurred_on,
                0 if item.event_type == "buy" else 1,
                item.event_fingerprint,
            ),
        ):
            instrument_id = event_instruments[event.event_fingerprint]
            if (
                event.event_type == "buy"
                and instrument_id
                and event.quantity
                and event.price_original
                and event.currency
            ):
                lots[instrument_id].append({"event": event, "remaining": event.quantity})
            elif event.event_type == "sell" and instrument_id and event.quantity:
                to_consume = event.quantity
                for lot in lots[instrument_id]:
                    if to_consume <= 0:
                        break
                    consumed = min(lot["remaining"], to_consume)
                    lot["remaining"] -= consumed
                    to_consume -= consumed
        for instrument_id, instrument_lots in lots.items():
            for lot in instrument_lots:
                event = lot["event"]
                conn.execute(
                    """INSERT INTO postfinance_cost_basis_lots(lot_id,event_id,instrument_id,acquired_on,quantity_acquired,quantity_remaining,unit_cost_original,fees_original,currency,method,provenance_document_hash,created_at) VALUES(?,?,?,?,?,?,?,?,?,'documented_trade_fifo',?,?)""",
                    (
                        _id("pflot"),
                        f"pfevent_{event.event_fingerprint[:24]}",
                        instrument_id,
                        event.occurred_on,
                        _text(event.quantity),
                        _text(lot["remaining"]),
                        _text(event.price_original),
                        _text(event.fee_original) or "0",
                        event.currency,
                        event.document_hash,
                        now,
                    ),
                )
        for position in snapshot.positions:
            instrument_id = position_map[position.row_reference]
            matched_lots = lots.get(instrument_id, [])
            quantity = sum((lot["remaining"] for lot in matched_lots), Decimal("0"))
            complete = (
                bool(matched_lots)
                and quantity == position.quantity
                and len({lot["event"].currency for lot in matched_lots}) == 1
            )
            calculated = (
                sum(
    cost_basis_keys: set[tuple[str, str]] = set()
    for row in transaction_rows:
        kind = str(row["activity_kind"] or row["transaction_type"] or "").lower()
        if kind in SUPPORTED_ACTIVITIES:
            activity_supported += 1
        if not row["instrument_id"] or row["quantity"] in (None, ""):
            continue
        key = (str(row["account_id"]), str(row["instrument_id"]))
        try:
            quantity = _stored_decimal(row["quantity"], "Menge", non_negative=True)
        except ValueError:
            continue
        if kind in {"buy", "initial_position_snapshot"}:
            quantities[key] = quantities.get(key, Decimal("0")) + quantity
            if row["gross_amount_original"] not in (None, ""):
                cost_basis_keys.add(key)
        elif kind in {"partial_sell", "full_sell", "sell"}:
            quantities[key] = quantities.get(key, Decimal("0")) - quantity
    reported_rows = conn.execute(
        f"""WITH ranked AS (
              SELECT p.*, ROW_NUMBER() OVER(PARTITION BY account_id,instrument_id ORDER BY snapshot_date DESC,created_at DESC,position_snapshot_id DESC) rn
              FROM positions_snapshot p WHERE account_id IN ({placeholders}) AND snapshot_date<=?
                AND datetime(created_at)<=datetime(?)
            ) SELECT * FROM ranked WHERE rn=1""", (*account_map, as_of, cutoff)
    ).fetchall()
    reported = {(str(row["account_id"]), str(row["instrument_id"])): row for row in reported_rows}
    keys = sorted(set(quantities) | set(reported))
    differences: list[dict[str, Any]] = []
    price_covered = fx_covered = recon_covered = 0
    account_position_values: dict[str, Decimal] = {key: Decimal("0") for key in account_map}
    account_position_dates: dict[str, set[str]] = {key: set() for key in account_map}


grep -n "def _canonical_transaction" -A80 src/jarvis_finance/services/postfinance_service.py


Output:
Chunk ID: 881c62
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 746
Output:
413:def _canonical_transaction(
414-    conn: Connection,
415-    event_id: str,
416-    event: PFEvent,
417-    account_id: str,
418-    instrument_id: str | None,
419-    now: str,
420-) -> None:
421-    if event.event_type in {"split", "corporate_action"}:
422-        return
423-    tx_type = {
424-        "buy": "buy",
425-        "sell": "sell",
426-        "dividend": "dividend",
427-        "interest": "interest",
428-        "fee": "fee",
429-        "internal_transfer": "transfer",
430-        "fx": "fx",
431-    }[event.event_type]
432-    activity = (
433-        "internal_transfer"
434-        if event.event_type == "internal_transfer"
435-        else "external_cashflow"
436-        if event.event_type in {"dividend", "interest", "fee"}
437-        else "trade"
438-    )
439-    columns = (
440-        "transaction_id,transaction_type,account_id,instrument_id,trade_date,settlement_date,quantity,"
441-        "price_original,gross_amount_original,fee_original,tax_original,net_amount_original,currency_original,"
442-        "fx_rate_to_chf,fx_source,fx_status,gross_amount_chf,fee_chf,tax_chf,net_amount_chf,source_type,source_id,"
443-        "external_transaction_id,row_hash,is_confirmed,quality_status,notes,created_at,updated_at,is_voided,"
444-        "activity_kind,booking_date,base_currency,internal_transfer_group_id,source_reference"
445-    )
446-    values = (
447-        event_id,
448-        tx_type,
449-        account_id,
450-        instrument_id,
451-        event.occurred_on,
452-        event.settlement_on,
453-        _text(event.quantity),
454-        _text(event.price_original),
455-        _text(event.gross_original),
456-        _text(event.fee_original) or "0",
457-        _text(event.tax_original) or "0",
458-        _text(event.net_original),
459-        event.currency,
460-        _text(event.fx_rate_to_chf),
461-        None,
462-        "unavailable",
463-        None,
464-        None,
465-        None,
466-        None,
467-        "postfinance_official_import",
468-        event_id,
469-        event.event_fingerprint,
470-        event.event_fingerprint,
471-        1,
472-        event.quality_status,
473-        "Verified PostFinance document event",
474-        now,
475-        None,
476-        0,
477-        activity,
478-        event.settlement_on or event.occurred_on,
479-        "CHF",
480-        event.internal_transfer_group,
481-        _hash(event.semantic_reference),
482-    )
483-    conn.execute(
484-        f"INSERT INTO transactions({columns}) VALUES({','.join('?' for _ in values)})", values
485-    )
486-
487-
488-def confirm_postfinance_import(conn: Connection, request: dict[str, Any]) -> dict[str, Any]:
489-    if request.get("confirm") is not True:
490-        raise ValueError("Explicit PostFinance import confirmation is required")
491-    preview = preview_postfinance_import(conn, request)
492-    if (
493-        request.get("preview_id") != preview["preview_id"]


sed -n '1,90p' src/jarvis_finance/ledger/cash.py


Output:
Chunk ID: bfa383
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 796
Output:
from __future__ import annotations

from dataclasses import dataclass, field
from decimal import Decimal
from sqlite3 import Connection

from jarvis_finance.audit.log import record_audit_event
from jarvis_finance.imports.common import stable_id, utc_now
from jarvis_finance.quality.alerts import create_alert

@dataclass
class CashBalance:
    account_id: str
    currency: str
    amount_original: Decimal = Decimal("0")
    amount_chf: Decimal | None = Decimal("0")
    quality_status: str = "ok"

@dataclass
class CashCalculationResult:
    balances: dict[tuple[str, str], CashBalance] = field(default_factory=dict)
    negative_cash_warnings: list[str] = field(default_factory=list)

def _d(value: object, default: str = "0") -> Decimal:
    if value is None or str(value).strip() == "":
        return Decimal(default)
    return Decimal(str(value))

def _signed_cash_delta(row) -> tuple[Decimal, Decimal | None]:
    t = row["transaction_type"]
    gross = _d(row["gross_amount_original"])
    net = _d(row["net_amount_original"]) if row["net_amount_original"] is not None else None
    fee = _d(row["fee_original"])
    tax = _d(row["tax_original"])
    fx = _d(row["fx_rate_to_chf"], "1") if row["fx_rate_to_chf"] is not None else None

    if t == "initial_cash_snapshot":
        original = net if net is not None else gross
    elif t == "cash_deposit":
        original = net if net is not None else gross
    elif t == "cash_withdrawal":
        original = -(net if net is not None else gross)
    elif t == "buy":
        original = -(net if net is not None else gross + fee + tax)
    elif t in {"sell", "partial_sell", "full_sell"}:
        original = net if net is not None else gross - fee - tax
    elif t in {"dividend", "etf_distribution"}:
        original = net if net is not None else gross - tax - fee
    elif t in {"fee", "tax"}:
        original = -(net if net is not None else gross or fee or tax)
    elif t == "fx_conversion":
        original = net if net is not None else gross
    elif t == "manual_cash_correction":
        original = net if net is not None else gross
    else:
        original = Decimal("0")
    chf = original * fx if fx is not None else None
    return original, chf

def calculate_cash_balances(
    conn: Connection, *, as_of_date: str | None = None, persist_alerts: bool = True
) -> CashCalculationResult:
    result = CashCalculationResult()
    params: tuple[object, ...] = ()
    where = "WHERE COALESCE(is_voided, 0) = 0"
    if as_of_date:
        where += " AND trade_date <= ?"
        params = (as_of_date,)
    rows = conn.execute(
        f"""
        SELECT * FROM transactions
        {where}
        ORDER BY account_id, currency_original, trade_date, created_at, transaction_id
        """,
        params,
    ).fetchall()
    for row in rows:
        account_id = row["account_id"]
        currency = row["currency_original"]
        key = (account_id, currency)
        balance = result.balances.setdefault(key, CashBalance(account_id, currency))
        original, chf = _signed_cash_delta(row)
        balance.amount_original += original
        if chf is None:
            balance.amount_chf = None


grep -n "vue_equity_sale\|vue_equity_dividend" -n src/jarvis_finance/services/equity_service.py src/jarvis_finance/equity/manage.py


Output:
Chunk ID: b86f0c
Wall time: 0.0000 seconds
Process exited with code 1
Original token count: 0
Output:


grep -R "vue_equity" -n src/jarvis_finance tests | head -100


Output:
Chunk ID: db5a7c
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 852
Output:
grep: src/jarvis_finance/services/__pycache__/cash_service.cpython-311.pyc: binary file matches
grep: src/jarvis_finance/services/__pycache__/manual_entry_service.cpython-311.pyc: binary file matches
grep: tests/__pycache__/test_postfinance_sprint13.cpython-311-pytest-9.1.1.pyc: binary file matches
grep: tests/__pycache__/test_postfinance_sprint13.cpython-311.pyc: binary file matches
grep: tests/__pycache__/test_postfinance_sprint13.cpython-311-pytest-9.0.2.pyc: binary file matches
grep: tests/unit/__pycache__/test_dashboard_functional_actions_v2.cpython-311-pytest-9.0.2.pyc: binary file matches
grep: tests/unit/__pycache__/test_dashboard_functional_actions_v2.cpython-311-pytest-9.1.1.pyc: binary file matches
grep: tests/unit/__pycache__/test_dashboard_functional_actions_v2.cpython-311.pyc: binary file matches
src/jarvis_finance/services/manual_entry_service.py:916:        VALUES (?, 'sell', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'vue_equity_sale', 1, ?, ?, ?)
src/jarvis_finance/services/manual_entry_service.py:919:        conn.execute("INSERT INTO cash_balances(cash_balance_id, account_id, balance_date, currency, amount_original, fx_rate_to_chf, amount_chf, source_type, quality_status, notes, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (_uuid("cash"), request.cash_account_id, request.trade_date, request.currency.upper(), _format_decimal(net), fx_rate, net_chf, f"vue_equity_sale:{tx_id}", "ok" if fx_status != "missing" else "missing_fx", request.note, ts))
src/jarvis_finance/services/manual_entry_service.py:955:        VALUES (?, 'dividend', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'vue_equity_dividend', 1, ?, ?, ?)
src/jarvis_finance/services/manual_entry_service.py:957:    conn.execute("INSERT INTO cash_balances(cash_balance_id, account_id, balance_date, currency, amount_original, fx_rate_to_chf, amount_chf, source_type, quality_status, notes, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, 'vue_equity_dividend', ?, ?, ?)", (_uuid("cash"), request.cash_account_id, request.payment_date, request.currency.upper(), _format_decimal(net), fx_rate, net_chf, "ok" if fx_status != "missing" else "missing_fx", request.note, ts))
src/jarvis_finance/services/cash_service.py:228:              AND (source_type LIKE 'vue_equity_sale:%'
src/jarvis_finance/services/cash_service.py:229:                   OR source_type='vue_equity_dividend')
src/jarvis_finance/services/cash_service.py:237:            if source_type.startswith("vue_equity_sale:")
src/jarvis_finance/services/cash_service.py:242:        if source_type == "vue_equity_dividend":
src/jarvis_finance/services/cash_service.py:245:                    WHERE account_id=? AND source_type='vue_equity_dividend'
src/jarvis_finance/services/cash_service.py:381:                        ("vue_equity_sale:", "vue_equity_dividend")
tests/unit/test_dashboard_functional_actions_v2.py:102:    assert conn.execute("SELECT COUNT(*) FROM cash_balances WHERE source_type LIKE 'vue_equity_sale:%'").fetchone()[0] == 1
tests/unit/test_dashboard_functional_actions_v2.py:128:    assert conn.execute("SELECT COUNT(*) FROM cash_balances WHERE source_type='vue_equity_dividend'").fetchone()[0] == 1
tests/test_postfinance_sprint13.py:703:                  '1.1','11','vue_equity_dividend','ok','2026-07-27T10:00:02Z')"""
tests/test_postfinance_sprint13.py:852:                  'vue_equity_dividend','ok','2026-08-02T10:03:00Z')""",


sed -n '890,970p' src/jarvis_finance/services/manual_entry_service.py


Output:
Chunk ID: 0df41f
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 1944
Output:
    amount_chf = _chf_amount(_format_decimal(net), Decimal(fx_rate) if fx_rate else None)
    avg = _weighted_average_cost(conn, account_id=account_id, instrument_id=instrument_id)
    warnings = [fx_warning] if fx_warning else []
    if avg is None:
        warnings.append("Einstand unvollständig: realisierter P&L nur eingeschränkt verfügbar.")
    return PreviewResponse(preview_id=_uuid("preview"), asset_class="equity", summary=f"Verkauf {quantity} · Erlös {currency} {_format_decimal(net)}", amount_chf=amount_chf, fx_status=fx_status, warnings=warnings)

def confirm_equity_sell(conn: Connection, request: EquitySellConfirmRequest) -> ConfirmResponse:
    if not request.confirm:
        raise HTTPException(status_code=400, detail="Explicit confirm required")
    preview = preview_equity_sell(conn, request)
    account_id, instrument_id = _position_ids(request.position_id)
    quantity = _decimal(request.quantity, "quantity")
    price = _decimal(request.price_original, "price_original")
    fees = _decimal_non_negative(request.fees_original, "fees_original")
    gross = quantity * price
    net = gross - fees
    fx_status, fx_rate, fx_source, _ = _fx_for_explicit_save(conn, currency=request.currency, trade_date=request.trade_date)
    gross_chf = _chf_amount(_format_decimal(gross), Decimal(fx_rate) if fx_rate else None)
    fee_chf = _chf_amount(_format_decimal(fees), Decimal(fx_rate) if fx_rate else None)
    net_chf = _chf_amount(_format_decimal(net), Decimal(fx_rate) if fx_rate else None)
    tx_id = _uuid("tx")
    ts = _now()
    conn.execute("""
        INSERT INTO transactions(transaction_id, transaction_type, account_id, instrument_id, trade_date, quantity, price_original, gross_amount_original, fee_original, net_amount_original, currency_original, fx_rate_to_chf, fx_source, fx_status, gross_amount_chf, fee_chf, net_amount_chf, source_type, is_confirmed, quality_status, notes, created_at)
        VALUES (?, 'sell', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'vue_equity_sale', 1, ?, ?, ?)
    """, (tx_id, account_id, instrument_id, request.trade_date, _format_decimal(-quantity), _format_decimal(price), _format_decimal(gross), _format_decimal(fees), _format_decimal(net), request.currency.upper(), fx_rate, fx_source, fx_status, gross_chf, fee_chf, net_chf, "ok" if fx_status != "missing" else "missing_fx", request.note, ts))
    if _cash_account_exists(conn, request.cash_account_id):
        conn.execute("INSERT INTO cash_balances(cash_balance_id, account_id, balance_date, currency, amount_original, fx_rate_to_chf, amount_chf, source_type, quality_status, notes, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", (_uuid("cash"), request.cash_account_id, request.trade_date, request.currency.upper(), _format_decimal(net), fx_rate, net_chf, f"vue_equity_sale:{tx_id}", "ok" if fx_status != "missing" else "missing_fx", request.note, ts))
    audit_id = _audit(conn, action="equity_sell_confirm", entity_type="position", entity_id=request.position_id, payload={**request.model_dump(), "net_amount_original": _format_decimal(net), "gross_amount_original": _format_decimal(gross)}, note=request.note, quality_status="ok" if fx_status != "missing" else "missing_fx")
    conn.commit()
    return ConfirmResponse(status="confirmed", entity_id=tx_id, audit_id=audit_id, message="Verkauf bestätigt · Audit geschrieben")

def preview_equity_dividend(conn: Connection, request: EquityDividendPreviewRequest) -> PreviewResponse:
    _position_ids(request.position_id)
    gross = _decimal(request.gross_amount, "gross_amount")
    taxes = _decimal_non_negative(request.swiss_tax, "swiss_tax") + _decimal_non_negative(request.foreign_tax, "foreign_tax") + _decimal_non_negative(request.other_deductions, "other_deductions")
    net = gross - taxes
    if net < 0:
        raise HTTPException(status_code=422, detail="deductions exceed gross dividend")
    if not _cash_account_exists(conn, request.cash_account_id):
        raise HTTPException(status_code=404, detail="Cash account not found")
    fx_status, fx_rate, _fx_source, fx_warning = _fx_for_explicit_save(conn, currency=request.currency, trade_date=request.payment_date)
    warnings = [fx_warning] if fx_warning else []
    return PreviewResponse(preview_id=_uuid("preview"), asset_class="income", summary=f"Dividende netto {request.currency.upper()} {_format_decimal(net)}", amount_chf=_chf_amount(_format_decimal(net), Decimal(fx_rate) if fx_rate else None), fx_status=fx_status, warnings=warnings)

def confirm_equity_dividend(conn: Connection, request: EquityDividendConfirmRequest) -> ConfirmResponse:
    if not request.confirm:
        raise HTTPException(status_code=400, detail="Explicit confirm required")
    preview = preview_equity_dividend(conn, request)
    account_id, instrument_id = _position_ids(request.position_id)
    gross = _decimal(request.gross_amount, "gross_amount")
    taxes = _decimal_non_negative(request.swiss_tax, "swiss_tax") + _decimal_non_negative(request.foreign_tax, "foreign_tax") + _decimal_non_negative(request.other_deductions, "other_deductions")
    net = gross - taxes
    fx_status, fx_rate, fx_source, _ = _fx_for_explicit_save(conn, currency=request.currency, trade_date=request.payment_date)
    gross_chf = _chf_amount(_format_decimal(gross), Decimal(fx_rate) if fx_rate else None)
    tax_chf = _chf_amount(_format_decimal(taxes), Decimal(fx_rate) if fx_rate else None)
    net_chf = _chf_amount(_format_decimal(net), Decimal(fx_rate) if fx_rate else None)
    tx_id = _uuid("tx")
    ts = _now()
    conn.execute("""
        INSERT INTO transactions(transaction_id, transaction_type, account_id, instrument_id, trade_date, gross_amount_original, tax_original, net_amount_original, currency_original, fx_rate_to_chf, fx_source, fx_status, gross_amount_chf, tax_chf, net_amount_chf, source_type, is_confirmed, quality_status, notes, created_at)
        VALUES (?, 'dividend', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'vue_equity_dividend', 1, ?, ?, ?)
    """, (tx_id, account_id, instrument_id, request.payment_date, _format_decimal(gross), _format_decimal(taxes), _format_decimal(net), request.currency.upper(), fx_rate, fx_source, fx_status, gross_chf, tax_chf, net_chf, "ok" if fx_status != "missing" else "missing_fx", request.note, ts))
    conn.execute("INSERT INTO cash_balances(cash_balance_id, account_id, balance_date, currency, amount_original, fx_rate_to_chf, amount_chf, source_type, quality_status, notes, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, 'vue_equity_dividend', ?, ?, ?)", (_uuid("cash"), request.cash_account_id, request.payment_date, request.currency.upper(), _format_decimal(net), fx_rate, net_chf, "ok" if fx_status != "missing" else "missing_fx", request.note, ts))
    audit_id = _audit(conn, action="equity_dividend_confirm", entity_type="position", entity_id=request.position_id, payload={**request.model_dump(), "net_amount_original": _format_decimal(net), "tax_original": _format_decimal(taxes)}, note=request.note, quality_status="ok" if fx_status != "missing" else "missing_fx")
    conn.commit()
    return ConfirmResponse(status="confirmed", entity_id=tx_id, audit_id=audit_id, message="Dividende bestätigt · Audit geschrieben")

def cleanup_review_artifacts_preview(conn: Connection) -> CleanupPreviewResponse:
    plan = identify_review_test_equity_artifacts(conn)
    warnings = []
    if plan.artifact_count:
        warnings.append("Review-/Test-Artefakte werden archiviert; manuelle Positionen bleiben erhalten.")
    return CleanupPreviewResponse(accounts=len(plan.account_ids), instruments=len(plan.instrument_ids), transactions=len(plan.transaction_ids), alerts=len(plan.alert_ids), manual_positions_preserved=plan.manual_position_count, warnings=warnings)


Output:
Chunk ID: 1eca49
Wall time: 30.0020 seconds
Process running with session ID 11766
Original token count: 7
Output:
............................


Output:
Chunk ID: 7b56b0
Wall time: 30.0015 seconds
Process running with session ID 11766
Original token count: 0
Output:


Output:
Chunk ID: b8fb3c
Wall time: 30.0006 seconds
Process running with session ID 11766
Original token count: 0
Output:


Output:
Chunk ID: ace93f
Wall time: 30.0018 seconds
Process running with session ID 11766
Original token count: 0
Output:


Output: write_stdin failed: stdin is closed for this session; rerun exec_command with tty=true to keep stdin open


Output:
Chunk ID: fc0924
Wall time: 300.0011 seconds
Process running with session ID 11766
Original token count: 0
Output:


Output:
Chunk ID: 0a9007
Wall time: 0.0000 seconds
Process exited with code 143
Original token count: 0
Output:


nl -ba src/jarvis_finance/services/portfolio_aggregation.py | sed -n '100,135p;155,185p;230,255p'
nl -ba src/jarvis_finance/services/cash_service.py | sed -n '320,395p'