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.
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
# 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.
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.
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
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.
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:# Before
greeks["delta"] * notional # 0.4502 * notional
# After
from decimal import Decimal
Decimal(greeks["delta"]) * Decimal(notional) # "0.4502" → exact
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.
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"]
| 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
# 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.
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.
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?
-- 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.
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.
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...
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.
| 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) |
# ✅ 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
This same parsing logic is used consistently across BondGuard._parse_rate() and FinanceVerifier.verify_irr(), eliminating cross-guard inconsistencies.
Exact arithmetic with Decimal
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:# 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.
9. FX guard (currency arbitration)
Purpose: Validate cross-currency conversions and detect arbitrage opportunities.
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.
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
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 |
:::tip PyPI Package All 10 guards are available via pip install qwed-finance :::