返回博客

金融风控 Ontology 建模:实时风险感知与关系网络分析

金融领域的关系复杂度远超其他行业:

Coomia发布于 2025年8月21日15 分钟阅读
分享本文Twitter / X

金融风控 Ontology 建模:实时风险感知与关系网络分析

系列:S4 本体建模 · 第 17 篇 | 难度:中级 | 阅读时间:18 分钟

#TL;DR

  • 金融风控 Ontology 以"客户-账户-交易"为核心三元组——个人、企业、账户、交易、产品、风险事件构成关系网络,coomia-dip 通过 RelationType 表达担保关系、资金流向、关联关系等复杂金融语义。
  • 派生属性实现实时风险指标计算——客户的信用评分、账户的异常交易检测、产品的风险暴露度,全部通过派生属性自动计算,数据变更时毫秒级更新,消灭了"T+1 风控报表"的延迟。
  • 关系图谱遍历发现隐性风险——通过 2~3 跳关系遍历发现"看似无关但实际关联"的客户群体、资金环路、担保链条,是传统规则引擎无法实现的风控能力。

#1. 金融数据的独特挑战

#1.1 关系复杂度

Code
金融领域的关系复杂度远超其他行业:

个人客户 张三:
├── 持有 3 个账户(储蓄、信用卡、理财)
├── 是 公司A 的法定代表人
├── 是 公司B 的股东(30%)
├── 为 公司C 提供了担保
├── 配偶 李四 也是客户
├── 李四 是 公司D 的法定代表人
├── 公司A 和 公司D 有资金往来
└── 公司B 为 公司A 提供了担保

问题:张三的贷款风险不仅取决于他个人的信用,
还取决于他关联的所有企业、担保链条、家庭成员。

传统方式:每种关系在不同系统中,分析需要手动关联
coomia-dip:所有关系在统一的 Ontology 模型中,一个查询搞定

#2. 核心 ObjectType 设计

#2.1 客户模型

Code
ObjectType: Individual(个人客户)
  properties:
    customerId: STRING (PK)
    name: STRING
    idNumber: STRING (SENSITIVE)
    phone: STRING
    email: STRING
    occupation: STRING
    annualIncome: DECIMAL
    riskPreference: ENUM [CONSERVATIVE, MODERATE, AGGRESSIVE]
    kycStatus: ENUM [PENDING, VERIFIED, REJECTED, EXPIRED]
    kycVerifiedAt: TIMESTAMP
    accounts: RELATION[] → Account
    relatedCompanies: RELATION[] → CorporateRelation
    familyMembers: RELATION[] → FamilyRelation
  metrics:
    monthlyTransactionVolume: METRIC(counter, source=core_banking)
    avgDailyBalance: METRIC(gauge, source=core_banking)
    loginFrequency: METRIC(counter, source=mobile_banking)
  derivedProperties:
    creditScore: DERIVED
      expression: |
        baseScore(annualIncome, occupation) * 0.3 +
        paymentHistoryScore(accounts) * 0.35 +
        utilizationScore(accounts) * 0.15 +
        accountAgeScore(accounts) * 0.1 +
        inquiryScore(creditInquiries) * 0.1
    riskLevel: CASE
      WHEN creditScore >= 750 THEN "LOW"
      WHEN creditScore >= 600 THEN "MEDIUM"
      WHEN creditScore >= 400 THEN "HIGH"
      ELSE "VERY_HIGH"
    END
    totalAssets: SUM(Account.balance WHERE accountType IN ("SAVINGS","INVESTMENT"))
    totalLiabilities: SUM(Account.balance WHERE accountType IN ("CREDIT","LOAN"))
    debtToIncomeRatio: totalLiabilities / annualIncome

ObjectType: Corporate(企业客户)
  properties:
    companyId: STRING (PK)
    companyName: STRING
    registrationNumber: STRING
    industry: STRING
    registeredCapital: DECIMAL
    establishedDate: DATE
    legalRepresentative: RELATION → Individual
    shareholders: RELATION[] → ShareholderRelation
    accounts: RELATION[] → Account
    guarantees: RELATION[] → GuaranteeRelation
  metrics:
    revenue: METRIC(counter, source=financial_reports)
    netProfit: METRIC(gauge, source=financial_reports)
    assetTurnoverRatio: METRIC(gauge, source=computed)
  derivedProperties:
    companyRiskScore: DERIVED
      expression: |
        financialHealthScore(revenue, netProfit) * 0.3 +
        industryRiskScore(industry) * 0.2 +
        guaranteeExposure(guarantees) * 0.2 +
        paymentHistoryScore(accounts) * 0.3
    isHighRisk: companyRiskScore < 50
    totalGuaranteeAmount: SUM(GuaranteeRelation.amount)
    guaranteeConcentration: MAX(GuaranteeRelation.amount) / totalGuaranteeAmount

#2.2 账户与交易

Code
ObjectType: Account(账户)
  properties:
    accountId: STRING (PK)
    accountType: ENUM [SAVINGS, CHECKING, CREDIT, LOAN, INVESTMENT, MARGIN]
    owner: RELATION → Individual | Corporate
    currency: STRING
    balance: DECIMAL
    creditLimit: DECIMAL
    interestRate: DECIMAL
    openDate: DATE
    status: ENUM [ACTIVE, FROZEN, CLOSED, DORMANT]
    branch: RELATION → Branch
  metrics:
    dailyTransactionCount: METRIC(counter, source=core_banking)
    dailyTransactionVolume: METRIC(counter, source=core_banking)
    monthlyAvgBalance: METRIC(gauge, source=core_banking)
  derivedProperties:
    utilizationRate: balance / creditLimit (信用账户)
    isOverLimit: balance > creditLimit
    dormantDays: TODAY() - lastTransactionDate
    isDormant: dormantDays > 180
    averageTransactionSize: dailyTransactionVolume / dailyTransactionCount

ObjectType: Transaction(交易)
  properties:
    transactionId: STRING (PK)
    fromAccount: RELATION → Account
    toAccount: RELATION → Account
    amount: DECIMAL
    currency: STRING
    transactionType: ENUM [TRANSFER, PAYMENT, WITHDRAWAL, DEPOSIT, FX, INVESTMENT]
    channel: ENUM [COUNTER, ATM, MOBILE, ONLINE, API]
    timestamp: TIMESTAMP
    status: ENUM [PENDING, COMPLETED, FAILED, REVERSED]
    description: STRING
    location: STRING
    deviceId: STRING
    ipAddress: STRING (SENSITIVE)
  derivedProperties:
    isLargeTransaction: amount > threshold(fromAccount.accountType)
    isCrossBoorder: fromAccount.currency != toAccount.currency
    isUnusualTime: HOUR(timestamp) < 6 OR HOUR(timestamp) > 23
    riskScore: DERIVED
      expression: |
        baseRisk(transactionType, amount) +
        (IF(isLargeTransaction, 20, 0)) +
        (IF(isCrossBoorder, 15, 0)) +
        (IF(isUnusualTime, 10, 0)) +
        velocityRisk(fromAccount, "1h") +
        locationRisk(location, fromAccount.owner)

#2.3 风险关系模型

Code
RelationType: GuaranteeRelation(担保关系)
  properties:
    guarantor: RELATION → Individual | Corporate
    borrower: RELATION → Individual | Corporate
    guaranteeType: ENUM [JOINT, COLLATERAL, PLEDGE, LETTER_OF_CREDIT]
    amount: DECIMAL
    collateralType: STRING
    collateralValue: DECIMAL
    startDate: DATE
    endDate: DATE
    status: ENUM [ACTIVE, RELEASED, DEFAULTED]

RelationType: ShareholderRelation(股权关系)
  properties:
    shareholder: RELATION → Individual | Corporate
    company: RELATION → Corporate
    shareholdingPercentage: DECIMAL
    shareType: ENUM [COMMON, PREFERRED]
    beneficialOwner: BOOLEAN

RelationType: FamilyRelation(家庭关系)
  properties:
    person1: RELATION → Individual
    person2: RELATION → Individual
    relationship: ENUM [SPOUSE, PARENT, CHILD, SIBLING]

RelationType: FundFlow(资金流向)
  properties:
    from: RELATION → Account
    to: RELATION → Account
    totalAmount: DECIMAL
    transactionCount: INT
    timeRange: STRING
    flowType: ENUM [REGULAR, OCCASIONAL, SUSPICIOUS]

#3. 实时风险指标计算

#3.1 客户级风险仪表盘

Code
Individual 的风险指标 DAG:

Level 0(源数据):
  交易记录、账户余额、个人信息、外部征信

Level 1(账户级派生):
  Account.utilizationRate
  Account.overdueDay s
  Account.averageTransactionSize

Level 2(客户级聚合):
  Individual.totalAssets = SUM(Account.balance WHERE type IN savings/investment)
  Individual.totalLiabilities = SUM(Account.balance WHERE type IN credit/loan)
  Individual.maxOverdueDays = MAX(Account.overdueDays)

Level 3(客户级派生):
  Individual.debtToIncomeRatio = totalLiabilities / annualIncome
  Individual.creditScore = weighted_sum(...)
  Individual.riskLevel = CASE(creditScore)

Level 4(关联风险):
  Individual.guaranteeExposure = SUM(GuaranteeRelation.amount)
  Individual.relatedCompanyRisk = MAX(Corporate.companyRiskScore)

Level 5(综合风险):
  Individual.compositeRiskScore = creditScore * 0.6 + guaranteeExposure * 0.2 + relatedCompanyRisk * 0.2

交易发生时的级联更新:
  新交易 → 账户余额变 → utilizationRate 变 → creditScore 变 → riskLevel 变
  全链路毫秒级更新,无需等 T+1 报表

#3.2 反洗钱(AML)指标

Code
AML 相关的派生属性:

ObjectType: Individual(扩展 AML 属性)
  derivedProperties:
    # 交易速度检测
    transactionVelocity_1h: COUNT(Transaction WHERE timestamp > NOW() - 1h)
    transactionVelocity_24h: COUNT(Transaction WHERE timestamp > NOW() - 24h)
    isHighVelocity: transactionVelocity_1h > 10 OR transactionVelocity_24h > 50

    # 分散交易检测(Structuring / Smurfing)
    nearThresholdTransactions: COUNT(Transaction WHERE amount BETWEEN 9000 AND 10000 AND timestamp > NOW() - 7d)
    isStructuring: nearThresholdTransactions >= 3

    # 跨境交易模式
    crossBorderFrequency: COUNT(Transaction WHERE isCrossBoorder AND timestamp > NOW() - 30d)
    highRiskCountryTransactions: COUNT(Transaction WHERE toAccount.country IN highRiskCountries)

    # 资金环路检测(通过关系遍历)
    hasFundCycle: EXISTS(
      TRAVERSE fromAccount → Transaction.toAccount → Transaction.fromAccount
      WHERE depth <= 3 AND endpoint == startpoint
    )

    # 综合 AML 风险
    amlRiskScore: DERIVED
      expression: |
        (IF(isHighVelocity, 25, 0)) +
        (IF(isStructuring, 30, 0)) +
        (IF(crossBorderFrequency > 10, 15, 0)) +
        (IF(highRiskCountryTransactions > 0, 20, 0)) +
        (IF(hasFundCycle, 30, 0))

    amlAlert: amlRiskScore >= 50

告警 Action:
  ActionType: CreateSAR(可疑交易报告)
    trigger: amlAlert == true
    parameters:
      customerId: REQUIRED
      alertType: ENUM [STRUCTURING, HIGH_VELOCITY, FUND_CYCLE, HIGH_RISK_COUNTRY]
      assignedAnalyst: RELATION → Employee
      dueDate: NOW() + 5d
    guards:
      - NOT EXISTS(SAR WHERE customerId = this.customerId AND status = "OPEN")

#4. 关系图谱分析

#4.1 关联客户发现

Code
通过关系遍历发现隐性关联:

查询:找出与"张三"有关联的所有客户

API: POST /api/v1/objects/Individual/zhang-san/graph
{
  "maxDepth": 3,
  "relationTypes": ["FamilyRelation", "ShareholderRelation", "GuaranteeRelation"],
  "includeProperties": ["name", "creditScore", "riskLevel"]
}

结果:

张三 (creditScore: 720, riskLevel: MEDIUM)
├── [配偶] 李四 (creditScore: 680, riskLevel: MEDIUM)
│   └── [法定代表人] 公司D (riskScore: 45, isHighRisk: true)
│       └── [资金往来] 公司A
├── [法定代表人] 公司A (riskScore: 72)
│   └── [担保] ← 公司B (riskScore: 55)
├── [股东30%] 公司B (riskScore: 55)
│   └── [担保] → 公司A
└── [担保人] → 公司C (riskScore: 38, isHighRisk: true)

风险发现:
├── 张三的配偶李四关联了高风险企业(公司D)
├── 公司A 和 公司B 形成了互保关系
├── 公司C 是高风险企业,张三为其提供了担保
└── 如果公司C 违约,张三需要承担担保责任
    → 这会影响张三的信用评分和贷款审批

#4.2 担保链分析

Code
担保链风险分析:

查询:分析企业 A 的担保链条

API: POST /api/v1/objects/Corporate/company-a/trace
{
  "relationType": "GuaranteeRelation",
  "direction": "BOTH",
  "maxDepth": 5,
  "includeRiskScores": true
}

结果:

担保链路可视化:
  公司E (riskScore: 82)
    ↓ 担保 500万
  公司B (riskScore: 55)
    ↓ 担保 1000万
  公司A (riskScore: 72)     ← 分析目标
    ↓ 担保 800万
  公司C (riskScore: 38)     ← 高风险!
    ↓ 担保 600万
  公司F (riskScore: 25)     ← 高风险!

风险分析:
├── 担保链深度:5 层
├── 链上高风险企业:2 家(公司C、公司F)
├── 公司A 的下游担保暴露:800万(直接)+ 600万(间接)= 1400万
├── 如果公司F 违约:公司C 需要代偿 600万
│   → 公司C 可能无法代偿(riskScore=38)
│   → 公司A 需要为公司C 代偿 800万
│   → 级联风险总额:1400万
└── 建议:降低公司A 的信用额度,要求补充担保物

#4.3 资金流向分析

Code
资金流向网络分析:

查询:分析账户 A001 的资金流向网络

API: POST /api/v1/objects/Account/A001/fund-flow
{
  "timeRange": {"from": "2025-01-01", "to": "2025-01-31"},
  "minAmount": 100000,
  "maxDepth": 3,
  "detectCycles": true
}

结果:

A001 (张三储蓄)
├──→ A002 (公司A 对公) ¥500,000 × 3次
│    ├──→ A005 (公司D 对公) ¥300,000 × 2次
│    │    └──→ A003 (李四储蓄) ¥200,000 × 1次
│    │         └──→ A001 (张三储蓄) ¥150,000 × 1次  ← 资金环路!
│    └──→ A006 (供应商E) ¥400,000 × 5次 (正常业务)
└──→ A004 (张三信用卡) ¥100,000 × 2次 (自有账户)

发现:
├── 资金环路:A001 → A002 → A005 → A003 → A001
├── 环路金额:¥150,000
├── 可疑性:资金通过 4 个账户 3 家关联企业回流
├── 可能目的:虚增交易量 / 洗钱 / 转移资产
└── 自动触发 SAR(可疑交易报告)

coomia-dip 的优势:
  传统方式需要数据分析师手动追踪资金流向
  coomia-dip 通过关系遍历 + 环检测自动发现
  秒级完成,覆盖所有账户

#5. 风控规则引擎

#5.1 规则与 Ontology 的结合

Code
风控规则通过 Ontology 的 ActionType 实现:

ActionType: FreezeAccount(冻结账户)
  trigger:
    OR:
      - account.overdueDays > 90
      - account.owner.amlRiskScore >= 80
      - account.owner.creditScore < 300
      - manual_trigger
  parameters:
    accountId: REQUIRED
    freezeReason: ENUM [OVERDUE, AML_ALERT, FRAUD_SUSPECT, LEGAL_ORDER]
    freezeLevel: ENUM [DEBIT_ONLY, FULL_FREEZE]
    duration: DURATION
  guards:
    - account.status != "FROZEN"
    - account.balance >= 0 OR freezeReason == "LEGAL_ORDER"
  approvalWorkflow:
    - IF freezeLevel == "FULL_FREEZE": require_approval("risk_manager")
    - IF freezeReason == "LEGAL_ORDER": require_approval("compliance_officer")
  sideEffects:
    - NOTIFY(account.owner, "ACCOUNT_FROZEN")
    - UPDATE(account.status, "FROZEN")
    - LOG(auditTrail)

ActionType: AdjustCreditLimit(调整信用额度)
  trigger:
    OR:
      - creditScore 变化超过 50 分
      - debtToIncomeRatio > 0.6
      - guaranteeExposure 新增
  parameters:
    accountId: REQUIRED
    newLimit: DECIMAL
    adjustmentReason: STRING
  guards:
    - newLimit >= 0
    - newLimit <= maxAllowedLimit(account.owner.creditScore)

#6. 信贷审批模型

Code
ObjectType: LoanApplication(贷款申请)
  properties:
    applicationId: STRING (PK)
    applicant: RELATION → Individual | Corporate
    loanType: ENUM [PERSONAL, MORTGAGE, AUTO, BUSINESS, CREDIT_LINE]
    requestedAmount: DECIMAL
    requestedTerm: INT (months)
    purpose: STRING
    collateral: RELATION[] → Collateral
    guarantors: RELATION[] → Individual
    status: ENUM [SUBMITTED, UNDER_REVIEW, APPROVED, REJECTED, DISBURSED]
    submittedAt: TIMESTAMP
    decisionAt: TIMESTAMP
    assignedOfficer: RELATION → Employee
  derivedProperties:
    autoDecision: DERIVED
      expression: |
        CASE
          WHEN applicant.creditScore >= 750 AND requestedAmount <= preApprovedLimit THEN "AUTO_APPROVE"
          WHEN applicant.creditScore < 400 THEN "AUTO_REJECT"
          WHEN applicant.amlRiskScore >= 50 THEN "MANUAL_REVIEW"
          WHEN applicant.debtToIncomeRatio > 0.5 THEN "MANUAL_REVIEW"
          WHEN guaranteeChainRisk > 0.7 THEN "MANUAL_REVIEW"
          ELSE "MANUAL_REVIEW"
        END

    guaranteeChainRisk: DERIVED
      expression: |
        # 遍历担保链条,计算级联违约概率
        TRAVERSE(applicant, "GuaranteeRelation", depth=3)
        → 统计链上高风险企业数量和占比

    expectedLossRate: DERIVED
      expression: |
        PD(applicant.creditScore) * LGD(collateral) * EAD(requestedAmount)

    riskAdjustedPricing: DERIVED
      expression: |
        baseRate + riskPremium(expectedLossRate) + operatingCostRate

#7. 监管合规模型

Code
ObjectType: RegulatoryReport(监管报表)
  properties:
    reportId: STRING (PK)
    reportType: ENUM [CAR, LCR, NSFR, LR, SAR, CTR]
    reportingPeriod: STRING
    status: ENUM [DRAFT, SUBMITTED, ACCEPTED, REJECTED]
    submittedAt: TIMESTAMP
    dueDate: DATE
  derivedProperties:
    capitalAdequacyRatio: DERIVED(资本充足率)
      expression: |
        (tier1Capital + tier2Capital) / riskWeightedAssets * 100

    liquidityCoverageRatio: DERIVED(流动性覆盖率)
      expression: |
        highQualityLiquidAssets / totalNetCashOutflows30d * 100

    nonPerformingLoanRatio: DERIVED(不良贷款率)
      expression: |
        COUNT(Account WHERE overdueDays > 90 AND accountType = "LOAN") /
        COUNT(Account WHERE accountType = "LOAN") * 100

所有监管指标都是 Ontology 派生属性:
├── 数据实时计算,随时可以查看最新值
├── 历史值自动保存,支持趋势分析
├── 数据血缘可追溯到每一笔交易
└── 审计时可以精确重现任何时间点的指标值

#8. 欺诈检测模型

Code
ObjectType: FraudAlert(欺诈告警)
  properties:
    alertId: STRING (PK)
    alertType: ENUM [IDENTITY_THEFT, CARD_FRAUD, ACCOUNT_TAKEOVER,
                     APPLICATION_FRAUD, INSIDER_FRAUD]
    relatedTransaction: RELATION → Transaction
    relatedAccount: RELATION → Account
    relatedCustomer: RELATION → Individual
    confidence: DECIMAL
    status: ENUM [OPEN, INVESTIGATING, CONFIRMED, FALSE_POSITIVE]
    assignedAnalyst: RELATION → Employee

欺诈检测派生属性(实时计算):

Transaction 的欺诈评分:
  fraudScore: DERIVED
    expression: |
      deviceRisk(deviceId, account.knownDevices) * 0.2 +
      locationRisk(location, account.normalLocations) * 0.2 +
      amountRisk(amount, account.averageTransactionSize) * 0.2 +
      velocityRisk(account, "1h") * 0.2 +
      behaviorRisk(transactionType, channel, timestamp) * 0.2

  isFraudSuspect: fraudScore >= 70

告警规则:
  当 isFraudSuspect == true:
  1. 实时阻断交易(如果 fraudScore >= 90)
  2. 发送短信验证(如果 fraudScore 70~90)
  3. 创建 FraudAlert 记录
  4. 通知反欺诈分析师
  5. 冻结相关账户(如果确认为欺诈)

#9. 关系网络全景

Code
金融风控 Ontology 的关系网络:

Individual ──holds──→ Account
Corporate ──holds──→ Account
Individual ──represents──→ Corporate
Individual ──shareholderOf──→ Corporate
Individual ──guarantees──→ Corporate
Individual ──familyOf──→ Individual
Corporate ──guarantees──→ Corporate
Corporate ──subsidiaryOf──→ Corporate
Account ──transfers──→ Account (via Transaction)
Individual ──applies──→ LoanApplication
LoanApplication ──securedBy──→ Collateral
FraudAlert ──relatedTo──→ Transaction
FraudAlert ──involves──→ Account
SAR ──reportedFor──→ Individual

关系总数:14 种
ObjectType 总数:12 种

核心价值:
  传统风控:基于规则,只看个体数据
  coomia-dip 风控:基于关系网络,看个体 + 关联 + 传导
  "张三是低风险,但他担保的公司C是高风险"
  → 这种关联风险只有关系图谱能发现

#10. 与传统风控的对比

Code
Ontology 风控 vs 传统风控:

┌──────────────────┬────────────────────┬──────────────────────┐
│ 维度              │ coomia-dip           │ 传统风控系统          │
├──────────────────┼────────────────────┼──────────────────────┤
│ 数据模型          │ 统一 Ontology       │ 多系统分散            │
│ 关系分析          │ 图遍历,N 跳        │ SQL JOIN,2~3 表     │
│ 指标计算          │ 实时派生属性        │ T+1 批量计算          │
│ 规则执行          │ ActionType + Guard  │ 独立规则引擎          │
│ 环路检测          │ 内置图算法          │ 需要专用图数据库      │
│ 监管报表          │ 派生属性自动计算    │ 手动数据提取          │
│ 审计追溯          │ 属性级血缘          │ 报表级追溯            │
│ 扩展性            │ 新增 ObjectType     │ 需要改表加字段        │
│ 开发效率          │ Schema 驱动         │ 需要开发 + 测试       │
└──────────────────┴────────────────────┴──────────────────────┘

#Key Takeaways

  1. 金融 Ontology 的核心是关系网络而非孤立实体——客户的风险不仅取决于自身数据,还取决于担保链条、股权关系、家庭关系、资金流向等网络结构,coomia-dip 的 RelationType 天然支持这种复杂关系建模。
  2. 派生属性实现了"实时风控"——信用评分、AML 指标、欺诈评分全部通过派生属性自动计算,交易发生时毫秒级更新,从"T+1 风控报表"升级为"实时风险感知"。
  3. 关系图谱遍历是 Ontology 风控的独特能力——通过 2~3 跳遍历发现隐性关联客户、资金环路、担保链条风险,这是传统 SQL JOIN 和规则引擎无法实现的。
  4. ActionType 实现了从"发现风险"到"处置风险"的闭环——账户冻结、额度调整、SAR 提交、贷款拒绝,全部通过 Ontology 的 Action 机制自动执行,带有审批流程和审计日志。
  5. 监管合规指标是派生属性的自然应用——资本充足率、流动性覆盖率、不良贷款率等监管指标通过 Ontology 自动计算,数据可追溯到每一笔交易,满足审计要求。

#Next Article

下一篇 S4-18 医疗健康 Ontology 建模 将讨论如何用 Ontology 模型表达医疗领域的复杂语义——患者、就诊、诊断、处方、检验、医疗设备,如何处理医疗数据的隐私合规要求,如何用关系网络实现疾病谱分析。

#ontology #financial-risk #aml #credit-scoring #fraud-detection #guarantee-chain #fund-flow #compliance #graph-analysis