> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qwedai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# QWED Finance guards for financial AI verification

> QWED Finance guards for financial AI verification including ComplianceGuard, CalendarGuard, DerivativesGuard, MessageGuard, and QueryGuard.

QWED-Finance uses **Neurosymbolic AI** - combining neural (LLM) outputs with symbolic (math/logic) verification.

## 1. Compliance guard (Z3)

**Purpose:** Verify KYC/AML regulatory decisions using formal boolean logic.

```python theme={null}
from qwed_finance import ComplianceGuard

guard = ComplianceGuard()

# AML Threshold Check (BSA/FinCEN)
result = guard.verify_aml_flag(
    amount=15000,
    country_code="US",
    llm_flagged=True
)
# result.compliant = True ✅
# result.proof = "amount >= 10000 → CTR required"
```

### Methods

| Method                       | Description                        |
| ---------------------------- | ---------------------------------- |
| `verify_aml_flag()`          | Check CTR threshold (\$10,000)     |
| `verify_kyc_complete()`      | Validate KYC document requirements |
| `verify_transaction_limit()` | Enforce daily limits               |
| `verify_sanctions_check()`   | OFAC sanctions screening           |

### How Z3 works

```python theme={null}
# Z3 proves: IF amount >= 10000 THEN flag_required
from z3 import *
amount = Real('amount')
flag = Bool('flag')
solver = Solver()
solver.add(Implies(amount >= 10000, flag == True))
```

***

## 2. Calendar guard (SymPy)

**Purpose:** Deterministic day count conventions for interest calculations.

```python theme={null}
from qwed_finance import CalendarGuard, DayCountConvention
from datetime import date

guard = CalendarGuard()

# Verify 30/360 day count
result = guard.verify_day_count(
    start_date=date(2026, 1, 1),
    end_date=date(2026, 7, 1),
    llm_days=180,
    convention=DayCountConvention.THIRTY_360
)
# result.verified = True ✅
```

### Supported conventions

| Convention      | Use Case                  |
| --------------- | ------------------------- |
| `ACTUAL_ACTUAL` | US Treasury bonds         |
| `ACTUAL_360`    | T-Bills, Commercial paper |
| `ACTUAL_365`    | UK Gilts                  |
| `THIRTY_360`    | Corporate bonds           |
| `THIRTY_E_360`  | Eurobonds                 |

***

## 3. Derivatives guard (Black-Scholes)

**Purpose:** Options pricing and margin verification using pure calculus.

```python theme={null}
from qwed_finance import DerivativesGuard, OptionType

guard = DerivativesGuard()

# Verify Black-Scholes call price
result = guard.verify_black_scholes(
    spot_price=100,
    strike_price=105,
    time_to_expiry=0.25,
    risk_free_rate=0.05,
    volatility=0.20,
    option_type=OptionType.CALL,
    llm_price="$3.50"
)
# result.greeks = {"delta": "0.4502", "gamma": "0.0389", ...}
```

### Methods

| Method                     | Description                 |
| -------------------------- | --------------------------- |
| `verify_black_scholes()`   | Options pricing with Greeks |
| `verify_delta()`           | Delta calculation           |
| `verify_margin_call()`     | Margin call decision        |
| `verify_put_call_parity()` | Arbitrage detection         |

### Arbitrary-precision arithmetic

<Info>
  **Since the Decimal/mpmath migration:** `DerivativesGuard` uses `mpmath` (30 decimal places) for all transcendental functions — `log`, `exp`, `sqrt`, and `erf` — replacing IEEE-754 `math.*` calls. The standard normal CDF and PDF (`_norm_cdf`, `_norm_pdf`) are now exact to 30 dp, and `verify_margin_call` and `verify_put_call_parity` compare values in `Decimal` space.
</Info>

<Warning>
  **Breaking change — Greeks are now `str`, not `float`.** Each Greek is `Decimal.quantize()`'d and returned as a string to preserve precision across serialization boundaries. Cast explicitly if you need a numeric type:

  ```python theme={null}
  # Before
  greeks["delta"] * notional  # 0.4502 * notional

  # After
  from decimal import Decimal
  Decimal(greeks["delta"]) * Decimal(notional)  # "0.4502" → exact
  ```
</Warning>

`mpmath` is now a runtime dependency. It was already pulled in transitively by `sympy`, so no extra install step is required.

***

## 4. Message guard (XML schema)

**Purpose:** Validate ISO 20022 and SWIFT messages before transmission.

```python theme={null}
from qwed_finance import MessageGuard, MessageType

guard = MessageGuard()

# Verify pacs.008 payment message
result = guard.verify_iso20022_xml(
    xml_string=pacs008_xml,
    msg_type=MessageType.PACS_008
)
# result.valid = True/False
# result.errors = ["Missing required element: GrpHdr"]
```

### Supported formats

| Format     | Description              |
| ---------- | ------------------------ |
| `PACS_008` | Customer Credit Transfer |
| `CAMT_053` | Bank Statement           |
| `PAIN_001` | Payment Initiation       |
| `MT103`    | SWIFT Single Transfer    |
| `MT202`    | SWIFT Bank Transfer      |

### SWIFT MT validation

```python theme={null}
# Validate MT103 fields
result = guard.verify_swift_mt(
    mt_string=mt103_message,
    mt_type=SwiftMtType.MT103
)
# Checks Field 20, 32A, 50K, 59, etc.
```

***

## 5. ISOGuard (JSON schema)

**Purpose:** Enforce ISO 20022 compliance for JSON-based Agentic Banking.

```python theme={null}
from qwed_finance import ISOGuard

guard = ISOGuard()

# Verify pacs.008 (JSON format)
result = guard.verify_payment_message(
    message={
        "MsgId": "1234AB",
        "CreDtTm": "2026-01-28T10:00:00",
        "NbOfTxs": 1,
        "TtlIntrBkSttlmAmt": {"amount": 100.50, "currency": "USD"}
    },
    msg_type="pacs.008"
)
# result.verified = True ✅
```

### Why JSON vs. XML?

While `MessageGuard` handles traditional XML SWIFT messages, `ISOGuard` enables **Modern Banking Agents** to speak the same standard using lightweight JSON.

***

## 6. Query guard (SQLGlot)

**Purpose:** Prevent SQL injection and unauthorized data access.

```python theme={null}
from qwed_finance import QueryGuard

guard = QueryGuard(allowed_tables={"transactions", "accounts"})

# Check read-only safety
result = guard.verify_readonly_safety(
    "DELETE FROM users WHERE id=1"
)
# result.safe = False ❌
# result.violations = ["Mutation detected: DELETE statement"]
```

### Methods

| Method                     | Description                     |
| -------------------------- | ------------------------------- |
| `verify_readonly_safety()` | Block INSERT/UPDATE/DELETE/DROP |
| `verify_table_access()`    | Whitelist allowed tables        |
| `verify_column_access()`   | Block PII columns               |
| `verify_no_injection()`    | Detect injection patterns       |

### Why AST, not regex?

```sql theme={null}
-- Regex might miss this:
SELECT * FROM (DELETE FROM users RETURNING *) AS x

-- SQLGlot AST catches it by parsing the tree structure
```

***

## 7. Cross-guard (multi-layer)

**Purpose:** Combine multiple guards to verify every component.

```python theme={null}
from qwed_finance import CrossGuard

guard = CrossGuard()

# SWIFT + Sanctions in one call
result = guard.verify_swift_with_sanctions(
    mt_string=swift_message,
    sanctions_list=["ACME Corp", "Bad Bank LLC"]
)
# Validates SWIFT format AND screens entities
```

***

## 8. Bond guard (yield analytics)

**Purpose:** Verify fixed income calculations like Yield to Maturity (YTM) and duration using Newton-Raphson.

```python theme={null}
from qwed_finance import BondGuard

guard = BondGuard()

# Verify YTM calculation
result = guard.verify_ytm(
    face_value=1000,
    coupon_rate=0.05,
    price=950,
    years_to_maturity=10,
    llm_output="5.66%"
)
# result.verified = True ✅
# result.computed_ytm = 0.0566...
```

### Rate format rules

<Warning>
  **Since v2.1.0:** `_parse_rate()` no longer silently guesses whether an input is a percentage or decimal. The old heuristic (`val < 1 → decimal, else percentage`) has been removed.
</Warning>

| Input      | Parsed Value | Rule                                          |
| ---------- | ------------ | --------------------------------------------- |
| `"5.25%"`  | `0.0525`     | Explicit `%` → divide by 100                  |
| `"0.0525"` | `0.0525`     | No `%` → use as-is (decimal fraction)         |
| `"1.5"`    | `1.5`        | No `%` → use as-is (150% for distressed debt) |

```python theme={null}
# ✅ Correct: use explicit % for percentage values
guard.verify_ytm(..., llm_output="5.25%")

# ✅ Correct: use decimal fraction directly
guard.verify_ytm(..., llm_output="0.0525")

# ⚠️ Breaking: "5.25" now means 525%, NOT 5.25%
# Use "5.25%" instead
```

<Note>
  This same parsing logic is used consistently across `BondGuard._parse_rate()` and `FinanceVerifier.verify_irr()`, eliminating cross-guard inconsistencies.
</Note>

### Exact arithmetic with Decimal

<Info>
  **Since the Decimal/mpmath migration:** `BondGuard` runs Newton-Raphson YTM solving and all duration, convexity, and accrued-interest math in `Decimal` with 50-digit precision (`getcontext().prec = 50`). Inputs are converted to `Decimal` at the boundary, eliminating IEEE-754 cancellation in long-dated bond cashflow sums.

  `tolerance_pct` is now stored as `Decimal`. Pass a `float` or `int` — the guard converts it via `Decimal(str(value))` to avoid float contamination:

  ```python theme={null}
  # Both are safe
  guard = BondGuard(tolerance_pct=0.5)
  guard = BondGuard(tolerance_pct="0.5")
  ```

  `verify_ytm`, `verify_duration`, and `verify_convexity` return their `details` fields as quantized strings (e.g. `"5.6601%"`) instead of raw floats.
</Info>

## 9. FX guard (currency arbitration)

**Purpose:** Validate cross-currency conversions and detect arbitrage opportunities.

```python theme={null}
from qwed_finance import FXGuard

guard = FXGuard()

# Verify Spot Conversion
result = guard.verify_conversion(
    amount=1000,
    from_currency="USD",
    to_currency="EUR",
    rate=0.92,
    llm_output="920.00 EUR"
)
# result.verified = True ✅
```

***

## 10. Risk guard (portfolio metrics)

**Purpose:** Ensure risk metrics like Sharpe Ratio and VaR (Value at Risk) are mathematically consistent.

```python theme={null}
from qwed_finance import RiskGuard

guard = RiskGuard()

# Verify Sharpe Ratio
# (Return - RiskFree) / Volatility
result = guard.verify_sharpe_ratio(
    portfolio_return=0.12,
    risk_free_rate=0.03,
    volatility=0.15,
    llm_output="0.60" 
)
# result.verified = True ✅
# result.computed_sharpe = 0.60
```

### Exact arithmetic with Decimal

<Info>
  **Since the Decimal/mpmath migration:** every `RiskGuard` method computes in `Decimal`. `verify_var` and `verify_sortino_ratio` use `Decimal.sqrt()` instead of `math.sqrt()`, and `verify_beta` accumulates covariance and variance in `Decimal` to prevent catastrophic cancellation on large return histories.

  The `Z_SCORES` lookup table is `Decimal`-typed:

  | Method                       | Backing math                           |
  | ---------------------------- | -------------------------------------- |
  | `verify_var()`               | `Decimal.sqrt()` for time scaling      |
  | `verify_beta()`              | `Decimal` covariance accumulation      |
  | `verify_sharpe_ratio()`      | `Decimal` division                     |
  | `verify_sortino_ratio()`     | `Decimal.sqrt()` on downside deviation |
  | `verify_max_drawdown()`      | `Decimal` running peak/trough          |
  | `verify_information_ratio()` | `Decimal` division                     |
</Info>

***

:::tip PyPI Package All 10 guards are available via `pip install qwed-finance` :::
