開発者向けの保険ドメイン: 製品、アクター、データ モデル
あなたが保険の世界に不慣れなソフトウェア開発者であれば、おそらく、 理解できない専門用語に直面することになります。 引受, 承認, FNOL, 代位, ボーダーロー。心配しないでください。このガイドはドメイン全体を翻訳します。 開発者が理解できる概念、データ モデル、アーキテクチャ パターンに保険を適用し、 実装し、そして何よりも 正しくモデル化する コードで。
保険業界は世界的に前進する 年間保険料は7兆ドル (データ 2025、Swiss Re Sigma) であり、世界で最も規制の厳しい部門の 1 つです。それでも、ほとんどの これをサポートする情報システムの歴史は 80 年代から 90 年代にまで遡ります。COBOL メインフレーム、夜間バッチ、 グリーンスクリーンインターフェイス。業界のデジタル変革、として知られています。 インシュアテック、 はこれらすべてを再設計しており、開発者がその変化の中心にいます。
この記事がシリーズの始まりです インシュアテックエンジニアリング 完全な概要付き ドメインの: 保険商品、バリューチェーンプレーヤー、基本的なデータモデル、 ポリシーと請求のライフサイクル、およびプラットフォームを構築するための最新のアーキテクチャ パターン クラウドネイティブな保険。
この記事で学べること
- 保険商品のカテゴリー(生命、損害、健康、専門)とその技術的な違い
- バリューチェーンのプレーヤー: 保険契約者、保険会社、ブローカー、代理店、再保険会社、規制当局
- 保険のバリューチェーン: 販売、引受業務、保険契約管理、保険金請求、投資
- 基本的なデータ モデル: ポリシー、保険金請求、プレミアム、補償範囲、裏書、特約
- 保険契約の完全なライフサイクル: 見積り、発行、変更、更新、キャンセル
- 請求のライフサイクル: FNOL、評価、和解、回収
- 保険に適用されるドメイン駆動設計: 境界のあるコンテキストと集計
- 評価エンジンのアーキテクチャと保険料の計算
- 相互運用性のための ACORD 標準と API パターン
- 規制の状況: ソルベンシー II、IFRS 第 17 号、GDPR
保険業界: 開発者の概要
一行のコードを書く前に、次のことを理解することが重要です。 ビジネスの仕組み 保険。商品が目に見える電子商取引とは異なり、保険では 「製品」とは、 約束: 事由が発生した場合の将来の補償金の支払い 不確かな出来事。これにより、データ モデリングの観点からドメインが本質的に複雑になります。
「保険は、絶対に使わないことを願って買う唯一の商品だ。この矛盾 それを管理するシステムのアーキテクチャ全体を定義します。」
基本原則: リスクの相互性
重要なコンセプトは、 リスクの相互作用 (リスクプーリング): 素晴らしいです 人々または企業のグループが定期的に保険料を共通基金に拠出し、そこから保険料が引き出されます。 損害を受けた少数の人々を補償するための資金。保険会社の役割とこれを管理する 保険数理上持続可能な方法で資金を積み立て、集められた保険料が保険料をカバーするのに十分であることを保証する 予想されるクレームに営業コストと利益率を加えたものです。
保険商品カテゴリー
保険商品は、大きく異なる技術的特性を持つマクロ カテゴリに分類されます。 データを正しくモデル化するには、これらの違いを理解することが重要です。
| カテゴリ | Esempi | 通常の期間 | リスクの性質 | データの複雑さ |
|---|---|---|---|---|
| ライフ (ライフ) | 期間、混合、ユニットリンク、ボード | 10~40年 | 死亡率、寿命 | 高(保険数理表、数学的積立金) |
| 損害賠償(損害賠償) | 車、自宅、プロ用ラジコン、火災 | 1年(更新可能) | 財産、民事責任 | 平均(請求頻度、平均費用) |
| 健康(健康) | 費用、事故、LTC の払い戻し | 1年/複数年 | 疾病、障害 | 高 (ICD、DRG、医療ネットワークのコーディング) |
| 特産品 | 海洋、航空、サイバー、D&O、E&O | 変数 | 複雑な/大惨事のリスク | 非常に高い (CAT モデル、累積) |
開発者への影響
保険には、単一の「万能の」データ モデルはありません。ライフシステムが管理する 数学的予備力と死亡率表。損保システムは免責金額、限度額、および限度額を管理します。 評価;医療システムは医療コードと医療提供者ネットワークを管理します。建築上の選択 の間 統一モデル e LOBに特化したモデル (基幹業務) は、保険プラットフォームの設計において最も重要な決定の 1 つです。
バリューチェーンの主体
保険のエコシステムには、異なる役割を持つ多数の関係者が関与しています。それらのそれぞれは、 データ モデル内のエンティティと、多くの場合、アーキテクチャ内の別の境界付きコンテキストです。
主要人物の地図
| 俳優 | ドメイン内での役割 | 主要なデータエンティティ | 主なやりとり |
|---|---|---|---|
| 契約者(保険契約者) | 保険を購入し、保険料を支払う | 顧客、アカウント、支払い方法 | クォータ、バインド、プレミアムの支払い、ファイル請求 |
| 保険加入済み | 保険の対象となる人・物 | 被保険者、リスクオブジェクト | 契約者とは異なる場合があります |
| 保険会社(保険会社/運送業者) | リスクを負い、保険金を支払います | 会社、ポートフォリオ、リザーブ | 保険金の引受、発行、解決 |
| エージェント | 保険会社を代表して保険を販売します | 代理店、代理店、委員会 | 分散、割り当て、サービス |
| ブローカ | クライアントを代表して条件交渉を行う | ブローカー、ブローカーファーム、紹介 | リスクを負い、条件を交渉する |
| 再保険会社 | 保険会社に保険をかける(過剰リスク) | 条約、譲渡、回復 | 収量、撤退、定住 |
| 専門家(鑑定士) | 請求を評価し、補償を決定します | 評価・見積り・報告書 | 検査、評価、推奨 |
| レギュレーター(レギュレーター) | 市場を監督し、ルールを課す | ファイリング、コンプライアンス、レポート | 製品の承認、監査、終了 |
重要な関係: 契約者 vs 被保険者 vs 受取人
最も過小評価されている複雑さの 1 つは、 保険契約者、被保険者、および被保険者の区別 受益者。最も単純なケース (個別の車のポリシー) では、3 つの数字は一致します。 しかし、法人生命保険では、 請負業者 そして会社は、 保険をかけられた 従業員です、そして 受益者 彼らは指定された家族のメンバーです。データモデルは次のことを行う必要があります。 これらのエンティティ間の多対多の関係により、この柔軟性がサポートされます。
保険のバリューチェーン
保険バリューチェーンは、保険会社との最初の接触からビジネスの全体の流れを表します。 請求が解決され、ポリシーが更新されるまで、お客様は、チェーン内のすべてのリンク 通常、に対応します 境界のあるコンテキスト ソフトウェアアーキテクチャにおいて。
Distribution Underwriting Policy Admin Claims Investment
| | | | |
v v v v v
+-----------+ +-----------+ +------------+ +-----------+ +-----------+
| Marketing | | Risk | | Issue | | FNOL | | Asset |
| Lead Gen | | Selection | | Endorse | | Assess | | Mgmt |
| Quoting | | Pricing | | Renew | | Adjust | | ALM |
| Binding | | Approval | | Cancel | | Settle | | Reserves |
+-----------+ +-----------+ +------------+ +-----------+ +-----------+
| | | | |
+-------+-------+--------+-------+------+-------+-------+------+
| | | |
+---------+ +---------+ +---------+ +---------+
|Reinsur. | | Billing | | Fraud | | Report |
|Cessions | | Collect | | Detect | | Regulat.|
+---------+ +---------+ +---------+ +---------+
1.配布
販売には、保険商品が顧客に届けられるすべてのチャネルが含まれます。 エージェント (単一企業または複数企業)、 ブローカ, 銀行窓販, オンラインコンパレーター e ダイレクトチャネル (ウェブ、アプリ、コールセンター)。開発者にとって、 これは、マルチチャネルの見積 API、統合 CRM、および製品構成エンジンに変換されます。
2. 引受業務(リスクの引き受け)
引受業務は、保険会社が提案されたリスクを評価し、それを受け入れるかどうかを決定するプロセスです。 どのような条件で、どのような価格で。これは保険ビジネスの技術的中心であり、以下が含まれます。
- リスクアセスメント: リスク特性の評価(年齢、健康状態、所在地、保険金請求履歴)
- 評価: による保険料の計算 評価エンジン (保険数理アルゴリズム + ビジネス ルール)
- リスクの選択: 条件を受け入れるか、拒否するか、変更するかの決定
- 紹介: 自動パラメータ以外のリスクについては上級引受会社にエスカレーション
3. ポリシー管理(ポリシー管理)
Il ポリシー管理システム (PAS) は全体を管理する中央システムです。 保険契約のライフサイクル: 発行、変更 (承認)、更新、キャンセル、 復帰。通常、これは保険 IT エコシステムの中で最も複雑なシステムです。
4. クレーム管理
クレーム管理は、クレームの通知からプロセス全体をカバーします(FNOL - 最初の通知 損失)清算および回収の可能性(代位)まで。そしてそのプロセスは、 顧客満足度と保険会社の収益性に直接影響します。
5. 投資と準備金の管理
保険会社は、将来の保険金支払いに備えて、集めた保険料を投資します。経営陣 投資額(資産負債管理) との計算 埋蔵量 テクニック これらは、洗練された保険数理モデルを必要とする規制されたプロセスです。
基本的なデータモデル
開発者が何をモデル化する必要があるか、その核心に迫ってみましょう。以下は、 骨材 (DDD の意味で) あらゆる保険プラットフォームの基本。
主な実体と関係
// ============================================
// Core Insurance Domain Model (TypeScript)
// ============================================
/** Tipologia di prodotto assicurativo */
type LineOfBusiness = 'LIFE' | 'PROPERTY' | 'CASUALTY' | 'HEALTH' | 'MARINE' | 'CYBER';
/** Stato della polizza nel suo ciclo di vita */
type PolicyStatus =
| 'QUOTE' // Preventivo
| 'APPLICATION' // Proposta
| 'BOUND' // Vincolata (impegno assunto)
| 'ISSUED' // Emessa
| 'IN_FORCE' // In vigore
| 'SUSPENDED' // Sospesa
| 'LAPSED' // Decaduta (mancato pagamento)
| 'CANCELLED' // Cancellata
| 'EXPIRED' // Scaduta
| 'NON_RENEWED'; // Non rinnovata
/** Aggregato principale: la Polizza */
interface Policy {
readonly id: string;
readonly policyNumber: string;
readonly version: number; // Versioning per endorsement
readonly lineOfBusiness: LineOfBusiness;
readonly status: PolicyStatus;
readonly effectiveDate: Date;
readonly expirationDate: Date;
readonly inceptionDate: Date; // Data prima emissione
readonly policyholder: Party; // Contraente
readonly insuredParties: readonly InsuredParty[];
readonly coverages: readonly Coverage[];
readonly premium: PremiumBreakdown;
readonly endorsements: readonly Endorsement[];
readonly documents: readonly Document[];
readonly underwritingInfo: UnderwritingInfo;
readonly createdAt: Date;
readonly updatedAt: Date;
}
/** Parte coinvolta (persona fisica o giuridica) */
interface Party {
readonly id: string;
readonly type: 'INDIVIDUAL' | 'ORGANIZATION';
readonly firstName?: string;
readonly lastName?: string;
readonly companyName?: string;
readonly taxId: string; // Codice fiscale / P.IVA
readonly dateOfBirth?: Date;
readonly addresses: readonly Address[];
readonly contacts: readonly ContactInfo[];
readonly riskProfile?: RiskProfile;
}
/** Soggetto assicurato con specifico ruolo */
interface InsuredParty {
readonly party: Party;
readonly role: 'PRIMARY' | 'ADDITIONAL' | 'NAMED_INSURED';
readonly relationship: string; // Relazione col contraente
}
/** Copertura: cosa e protetto e fino a quanto */
interface Coverage {
readonly id: string;
readonly code: string; // Es: "TPL", "CASCO", "FIRE"
readonly name: string;
readonly description: string;
readonly type: 'BASE' | 'OPTIONAL' | 'MANDATORY';
readonly limit: Money; // Massimale
readonly deductible: Deductible; // Franchigia
readonly premium: Money; // Premio per questa copertura
readonly effectiveDate: Date;
readonly expirationDate: Date;
readonly exclusions: readonly string[];
readonly conditions: readonly string[];
}
/** Franchigia con diverse modalità di applicazione */
interface Deductible {
readonly type: 'FIXED' | 'PERCENTAGE' | 'WAITING_PERIOD' | 'AGGREGATE';
readonly amount?: Money; // Per FIXED
readonly percentage?: number; // Per PERCENTAGE
readonly waitingDays?: number; // Per WAITING_PERIOD
readonly aggregateLimit?: Money; // Per AGGREGATE
readonly appliesToEach: 'CLAIM' | 'OCCURRENCE' | 'POLICY_PERIOD';
}
/** Scomposizione del premio */
interface PremiumBreakdown {
readonly grossPremium: Money; // Premio lordo
readonly netPremium: Money; // Premio netto (per l'assicuratore)
readonly taxes: Money; // Imposte
readonly fees: Money; // Diritti e commissioni
readonly commission: Money; // Provvigione intermediario
readonly components: readonly PremiumComponent[];
readonly paymentPlan: PaymentPlan;
}
/** Variazione contrattuale in corso di polizza */
interface Endorsement {
readonly id: string;
readonly endorsementNumber: number;
readonly type: 'COVERAGE_CHANGE' | 'LIMIT_CHANGE' | 'ADD_INSURED'
| 'REMOVE_INSURED' | 'ADDRESS_CHANGE' | 'VEHICLE_CHANGE'
| 'GENERAL_CHANGE';
readonly effectiveDate: Date;
readonly description: string;
readonly premiumAdjustment: Money; // Differenza premio (+/-)
readonly previousVersion: number;
readonly newVersion: number;
readonly changes: readonly FieldChange[];
readonly approvedBy?: string;
readonly approvedAt?: Date;
}
/** Valore monetario con valuta */
interface Money {
readonly amount: number;
readonly currency: string; // ISO 4217: "EUR", "USD", "GBP"
}
/** Singola modifica tracciata nell'endorsement */
interface FieldChange {
readonly field: string;
readonly oldValue: string;
readonly newValue: string;
}
主要なパターン: 不変性とバージョン管理
各インターフェイスがどのように使用するかに注目してください readonly すべてのプロパティで。保険の分野では、
の トレーサビリティ そして規制要件: ポリシーに変更を加えるたびに、
新しいもの 承認 それは増加します version。それは決して「変わらない」のです。
ポリシー。新しいバージョンが作成されます。このパターンは、イベントソーシング
そしてCQRSアーキテクチャを使用します。
ポリシーのライフサイクル
ポリシーは、その存在中に明確に定義された状態を通過します。このライフサイクルをモデル化してみましょう 一つのように ステートマシン、保険ソフトウェアの基本的なパターン。
// ============================================
// Policy Lifecycle State Machine
// ============================================
/** Transizioni valide nel ciclo di vita della polizza */
type PolicyTransition =
| { from: 'QUOTE'; to: 'APPLICATION'; action: 'SUBMIT_APPLICATION' }
| { from: 'QUOTE'; to: 'CANCELLED'; action: 'DECLINE_QUOTE' }
| { from: 'APPLICATION'; to: 'BOUND'; action: 'BIND_COVERAGE' }
| { from: 'APPLICATION'; to: 'CANCELLED'; action: 'DECLINE_APPLICATION' }
| { from: 'BOUND'; to: 'ISSUED'; action: 'ISSUE_POLICY' }
| { from: 'ISSUED'; to: 'IN_FORCE'; action: 'ACTIVATE' }
| { from: 'IN_FORCE'; to: 'IN_FORCE'; action: 'ENDORSE' }
| { from: 'IN_FORCE'; to: 'SUSPENDED'; action: 'SUSPEND' }
| { from: 'IN_FORCE'; to: 'CANCELLED'; action: 'CANCEL' }
| { from: 'IN_FORCE'; to: 'EXPIRED'; action: 'EXPIRE' }
| { from: 'IN_FORCE'; to: 'IN_FORCE'; action: 'RENEW' }
| { from: 'IN_FORCE'; to: 'NON_RENEWED'; action: 'NON_RENEW' }
| { from: 'SUSPENDED'; to: 'IN_FORCE'; action: 'REINSTATE' }
| { from: 'SUSPENDED'; to: 'LAPSED'; action: 'LAPSE' }
| { from: 'LAPSED'; to: 'IN_FORCE'; action: 'REINSTATE' }
| { from: 'LAPSED'; to: 'CANCELLED'; action: 'CANCEL' };
/** Mappa delle transizioni valide per validazione runtime */
const VALID_TRANSITIONS: ReadonlyMap<PolicyStatus, readonly PolicyTransition[]> = new Map([
['QUOTE', [
{ from: 'QUOTE', to: 'APPLICATION', action: 'SUBMIT_APPLICATION' },
{ from: 'QUOTE', to: 'CANCELLED', action: 'DECLINE_QUOTE' },
]],
['APPLICATION', [
{ from: 'APPLICATION', to: 'BOUND', action: 'BIND_COVERAGE' },
{ from: 'APPLICATION', to: 'CANCELLED', action: 'DECLINE_APPLICATION' },
]],
['IN_FORCE', [
{ from: 'IN_FORCE', to: 'IN_FORCE', action: 'ENDORSE' },
{ from: 'IN_FORCE', to: 'SUSPENDED', action: 'SUSPEND' },
{ from: 'IN_FORCE', to: 'CANCELLED', action: 'CANCEL' },
{ from: 'IN_FORCE', to: 'EXPIRED', action: 'EXPIRE' },
{ from: 'IN_FORCE', to: 'IN_FORCE', action: 'RENEW' },
{ from: 'IN_FORCE', to: 'NON_RENEWED', action: 'NON_RENEW' },
]],
]);
/** Funzione pura per la transizione di stato */
function transitionPolicy(
policy: Policy,
action: PolicyTransition['action'],
context: TransitionContext
): Policy {
const validTransitions = VALID_TRANSITIONS.get(policy.status);
const transition = validTransitions?.find(t => t.action === action);
if (!transition) {
throw new InvalidTransitionError(
`Cannot perform ${action} on policy in status ${policy.status}`
);
}
// Crea nuova versione immutabile della polizza
return {
...policy,
status: transition.to,
version: policy.version + 1,
updatedAt: new Date(),
endorsements: action === 'ENDORSE'
? [...policy.endorsements, context.endorsement!]
: policy.endorsements,
};
}
ライフサイクルの主要な段階
発行前フェーズ
- オッズ: 最小限のデータに基づく推定値。通常の有効期限: 30 日間
- 応用: 引受に必要なすべてのデータを含む正式な提案書
- バインド: 保険会社は補償を提供することに同意します(ただし、保険はまだ発行されていません)
- 問題: 公式政策文書の発行
発行後のフェーズ
- 支持者: 有効条件の変更(新バージョン)
- 更新: 有効期限切れによる更新 (再評価が必要な場合があります)
- つるす: 一時停止(未払いなど)
- キャンセル: 未払保険料計算を伴う解約
- リセット: 一時停止または没収後の復帰
請求のライフサイクル
事故は保険の約束を有効にする出来事です。ライフサイクルは同じです 構造化されており、ステートマシンとしてのモデリングに最適です。
// ============================================
// Claims Domain Model
// ============================================
type ClaimStatus =
| 'FNOL' // First Notice of Loss - notifica iniziale
| 'REGISTERED' // Registrato nel sistema
| 'UNDER_INVESTIGATION' // In fase di indagine/perizia
| 'ASSESSED' // Valutato dal perito
| 'APPROVED' // Approvato per liquidazione
| 'PARTIALLY_APPROVED'// Parzialmente approvato
| 'DENIED' // Rifiutato
| 'SETTLED' // Liquidato
| 'REOPENED' // Riaperto
| 'CLOSED' // Chiuso definitivamente
| 'SUBROGATION'; // In fase di recupero
interface Claim {
readonly id: string;
readonly claimNumber: string;
readonly policyId: string;
readonly policyNumber: string;
readonly status: ClaimStatus;
readonly lossDate: Date; // Data del sinistro
readonly reportDate: Date; // Data della denuncia
readonly lossType: string; // Tipo di danno
readonly lossDescription: string;
readonly lossLocation: Address;
readonly claimant: Party; // Chi richiede l'indennizzo
readonly reserves: readonly Reserve[];
readonly payments: readonly ClaimPayment[];
readonly assessments: readonly Assessment[];
readonly documents: readonly Document[];
readonly fraudIndicators: readonly FraudIndicator[];
readonly totalIncurred: Money; // Riserva + Pagato
readonly totalPaid: Money;
readonly totalReserve: Money;
}
/** Riserva: stima del costo futuro del sinistro */
interface Reserve {
readonly id: string;
readonly type: 'INDEMNITY' | 'EXPENSE' | 'LEGAL';
readonly amount: Money;
readonly setDate: Date;
readonly setBy: string;
readonly reason: string;
readonly history: readonly ReserveChange[];
}
/** Pagamento effettuato sul sinistro */
interface ClaimPayment {
readonly id: string;
readonly type: 'INDEMNITY' | 'EXPENSE' | 'LEGAL' | 'SALVAGE' | 'SUBROGATION';
readonly amount: Money;
readonly payee: Party;
readonly paymentDate: Date;
readonly paymentMethod: string;
readonly invoiceReference?: string;
readonly approvedBy: string;
}
/** Valutazione peritale */
interface Assessment {
readonly id: string;
readonly assessor: Party; // Perito
readonly assessmentDate: Date;
readonly damageEstimate: Money;
readonly findings: string;
readonly recommendation: 'APPROVE' | 'DENY' | 'FURTHER_INVESTIGATION';
readonly photos: readonly string[]; // URL delle foto
readonly report: Document;
}
/** Indicatore di potenziale frode */
interface FraudIndicator {
readonly rule: string;
readonly score: number; // 0-100
readonly description: string;
readonly triggeredAt: Date;
}
事故の各段階の詳細
| 段階 | 活動 | 関与する俳優 | 生成されたデータ |
|---|---|---|---|
| FNOL | 電話、Web、アプリ、メールで事故報告 | 保険付き、コールセンター | 請求通知、初期予約 |
| トリアージ | 保険金請求の分類、優先順位の割り当て、適用範囲の検証 | クレームハンドラー、自動システム | 対象範囲検証、優先順位、割り当て |
| 調査 | 資料の収集、鑑定、状況の確認 | 専門家、捜査官、監察医 | 評価、写真、エキスパートレポート |
| 判決 | 決定: 全面的、部分的承認または拒否 | 保険金請求委員会、保険金請求マネージャー | 決定・調整計算 |
| 集落 | 報酬の計算と支払い | 請求処理担当者、支払局 | 支払い・決済契約 |
| 回復 | 責任ある第三者に対する代位、サルベージ回収 | 法務事務所、回復事務所 | 代位請求・回収 |
評価エンジンのアーキテクチャ
Il 評価エンジン 保険料を計算するコンポーネント。そしてそのうちの1つが、 インシュアテック エコシステムの中で最も重要で高性能なシステム: 何千もの見積もりを処理する必要があります 数理上の精度と完全なトレーサビリティを備えた毎秒の速度。
保険料計算の仕組み
保険料の計算は、リスク要因をリスク要因に変換する明確に定義されたパイプラインに従います。 最終価格。 Car TPL の簡略化された例を見てみましょう。
// ============================================
// Rating Engine - Esempio RC Auto
// ============================================
/** Fattori di rischio per la tariffazione auto */
interface AutoRatingFactors {
readonly driverAge: number;
readonly driverExperience: number; // Anni di patente
readonly vehicleGroup: number; // Gruppo tariffario 1-20
readonly vehicleAge: number;
readonly postalCode: string;
readonly claimsHistory: number; // Sinistri ultimi 5 anni
readonly bonusMalusClass: number; // Classe CU (1-18 in Italia)
readonly annualMileage: number;
readonly garaging: 'GARAGE' | 'STREET' | 'PARKING';
readonly usage: 'PERSONAL' | 'COMMUTE' | 'BUSINESS';
}
/** Risultato del calcolo tariffario */
interface RatingResult {
readonly baseRate: Money;
readonly factors: readonly AppliedFactor[];
readonly technicalPremium: Money; // Premio tecnico (puro rischio)
readonly loadings: readonly Loading[];
readonly grossPremium: Money; // Premio lordo finale
readonly taxes: Money;
readonly totalPremium: Money; // Totale da pagare
readonly ratingDate: Date;
readonly rateTableVersion: string;
readonly auditTrail: readonly string[];
}
interface AppliedFactor {
readonly name: string;
readonly inputValue: string | number;
readonly factor: number; // Moltiplicatore (es: 1.25 = +25%)
readonly source: string; // Tabella di riferimento
}
interface Loading {
readonly type: 'EXPENSE' | 'COMMISSION' | 'PROFIT' | 'CATASTROPHE' | 'REINSURANCE';
readonly percentage: number;
readonly amount: Money;
}
/** Rating Engine: funzione pura che calcola il premio */
function calculateAutoRate(
factors: AutoRatingFactors,
rateTables: RateTableSet
): RatingResult {
const auditTrail: string[] = [];
// 1. Base Rate dalla tabella territoriale
const baseRate = rateTables.territorial.lookup(factors.postalCode);
auditTrail.push(`Base rate for ${factors.postalCode}: ${baseRate}`);
// 2. Applicazione fattori moltiplicativi
const ageMultiplier = rateTables.ageFactors.lookup(factors.driverAge);
const vehicleMultiplier = rateTables.vehicleGroups.lookup(factors.vehicleGroup);
const bonusMalusMultiplier = rateTables.bonusMalus.lookup(factors.bonusMalusClass);
const experienceMultiplier = rateTables.experience.lookup(factors.driverExperience);
const mileageMultiplier = rateTables.mileage.lookup(factors.annualMileage);
const appliedFactors: AppliedFactor[] = [
{ name: 'Age', inputValue: factors.driverAge, factor: ageMultiplier, source: 'AGE_TABLE_v3' },
{ name: 'Vehicle Group', inputValue: factors.vehicleGroup, factor: vehicleMultiplier, source: 'VEH_TABLE_v2' },
{ name: 'Bonus/Malus', inputValue: factors.bonusMalusClass, factor: bonusMalusMultiplier, source: 'BM_TABLE_v1' },
{ name: 'Experience', inputValue: factors.driverExperience, factor: experienceMultiplier, source: 'EXP_TABLE_v1' },
{ name: 'Mileage', inputValue: factors.annualMileage, factor: mileageMultiplier, source: 'KM_TABLE_v2' },
];
// 3. Premio tecnico = base * prodotto dei fattori
const combinedFactor = appliedFactors.reduce((acc, f) => acc * f.factor, 1);
const technicalPremium = baseRate * combinedFactor;
auditTrail.push(`Technical premium: ${baseRate} * ${combinedFactor.toFixed(4)} = ${technicalPremium.toFixed(2)}`);
// 4. Caricamenti (expense loading, commissioni, profitto)
const loadings: Loading[] = [
{ type: 'EXPENSE', percentage: 0.15, amount: { amount: technicalPremium * 0.15, currency: 'EUR' } },
{ type: 'COMMISSION', percentage: 0.12, amount: { amount: technicalPremium * 0.12, currency: 'EUR' } },
{ type: 'PROFIT', percentage: 0.05, amount: { amount: technicalPremium * 0.05, currency: 'EUR' } },
{ type: 'CATASTROPHE', percentage: 0.02, amount: { amount: technicalPremium * 0.02, currency: 'EUR' } },
];
const totalLoadingPct = loadings.reduce((acc, l) => acc + l.percentage, 0);
const grossPremium = technicalPremium * (1 + totalLoadingPct);
// 5. Imposte (22.25% per RC Auto in Italia)
const taxRate = 0.2225;
const taxes = grossPremium * taxRate;
const totalPremium = grossPremium + taxes;
return {
baseRate: { amount: baseRate, currency: 'EUR' },
factors: appliedFactors,
technicalPremium: { amount: technicalPremium, currency: 'EUR' },
loadings,
grossPremium: { amount: grossPremium, currency: 'EUR' },
taxes: { amount: taxes, currency: 'EUR' },
totalPremium: { amount: totalPremium, currency: 'EUR' },
ratingDate: new Date(),
rateTableVersion: 'RC_AUTO_2026_Q1',
auditTrail,
};
}
最新の評価エンジンのアーキテクチャ
実稼働環境の評価エンジンは、この例よりもはるかに複雑です。主な機能は次のとおりです。
- バージョン管理されたレートテーブル: 各料金表には発効日があります。システムは、現在の日付ではなく、ポリシーの発効日に基づいて正しいテーブルを適用する必要があります。
- 個別のルール エンジン: ビジネス ルール (制限、除外、割引) は、コードをデプロイしなくても、通常はルール エンジン (Drools、RETE、または JSON ベース) を介して構成できます。
- 完全な監査証跡: 計算の各ステップは、法規制に準拠するために追跡可能でなければなりません
- 水平方向のスケーラビリティ: 評価エンジンは、1 秒あたり数千件の見積もりのピークを管理する必要があります (コンパレーター、オープン登録)
- 冪等性: 同じ入力は常に同じ出力を生成する必要があります (純粋関数)
保険のためのドメイン駆動設計
ドメイン駆動設計 (DDD) は保険ドメインに最適なアーキテクチャ アプローチです その本質的な複雑さと、ソフトウェアをビジネス言語に合わせる必要性です。 具体的にどのように応用すればよいのか見ていきましょう。
保険エコシステムの限定されたコンテキスト
境界付けられた各コンテキストには独自のコンテキストがあります ユビキタス言語、そのモデルと 自分自身のルール。 「ポリシー」という用語は、引受業務の文脈ではさまざまな意味を持ちます。 ポリシー管理(発行された契約)と比較した(評価される提案)。
// ============================================
// Bounded Context Map
// ============================================
//
// +------------------+ +------------------+ +------------------+
// | Distribution | | Underwriting | | Policy Admin |
// | | | | | |
// | - Lead | | - Submission | | - Policy |
// | - Opportunity |---->| - Risk |---->| - Coverage |
// | - Quote Request | | - Rating | | - Endorsement |
// | - Channel | | - Decision | | - Renewal |
// +------------------+ +------------------+ +------------------+
// | | |
// | | |
// v v v
// +------------------+ +------------------+ +------------------+
// | CRM / Party | | Reinsurance | | Claims |
// | | | | | |
// | - Customer | | - Treaty | | - Claim |
// | - Agent | | - Cession | | - Reserve |
// | - Broker | | - Recovery | | - Payment |
// | - Address | | - Bordereaux | | - Assessment |
// +------------------+ +------------------+ +------------------+
// | | |
// v v v
// +------------------+ +------------------+ +------------------+
// | Billing | | Compliance | | Fraud Detection |
// | | | | | |
// | - Invoice | | - Filing | | - Alert |
// | - Payment | | - Report | | - Investigation |
// | - Collection | | - Audit | | - Score |
// | - Installment | | - Solvency | | - Rule |
// +------------------+ +------------------+ +------------------+
// Context Mapping Relationships:
// Distribution --[Conformist]--> Underwriting
// Underwriting --[Published Language]--> Policy Admin
// Policy Admin --[Shared Kernel]--> Billing
// Policy Admin --[Customer/Supplier]--> Claims
// Claims --[Anti-Corruption Layer]--> Fraud Detection
// Underwriting --[Partnership]--> Reinsurance
// All Contexts --[Conformist]--> Compliance
集約と不変式
DDD では、すべての 集計 ビジネスの不変条件を保護します。ここにいます 2 つの主要な集計の主な不変式:
集約ポリシー
- 保険には少なくとも 1 つの有効な補償が必要です
- 有効期限は発効日以降である必要があります
- 保険料総額は、補償保険料 + 負担額の合計でなければなりません
- 承認ごとにバージョンをインクリメントする必要があります
- 状態遷移はステートマシンを尊重する必要があります
- 未処理の保険金請求では保険をキャンセルすることはできません
保険金請求の集計
- 事故発生日が保険の補償期間内である必要があります
- リザーブをマイナスにすることはできません
- 支払総額が補償限度額を超えることはできません
- クローズされた請求は新たな支払いを受け取ることができません(再度オープンする必要があります)
- 決定には少なくとも専門家の評価が必要です
- 支払いが権限のしきい値を超える場合、支払いには承認が必要です
ドメインイベント
I ドメインイベント それらは、境界のあるコンテキストが何らかの方法で通信するためのメカニズムです。 切り離された。各イベントは、ドメイン内で起こった重要な何かを表します。
// ============================================
// Insurance Domain Events
// ============================================
interface DomainEvent {
readonly eventId: string;
readonly eventType: string;
readonly occurredAt: Date;
readonly aggregateId: string;
readonly aggregateType: string;
readonly version: number;
readonly correlationId: string;
readonly causationId?: string;
}
// --- Policy Events ---
interface PolicyQuoted extends DomainEvent {
readonly eventType: 'POLICY_QUOTED';
readonly aggregateType: 'Policy';
readonly quoteNumber: string;
readonly premium: Money;
readonly validUntil: Date;
}
interface PolicyIssued extends DomainEvent {
readonly eventType: 'POLICY_ISSUED';
readonly aggregateType: 'Policy';
readonly policyNumber: string;
readonly effectiveDate: Date;
readonly premium: Money;
readonly coverages: readonly string[];
}
interface PolicyEndorsed extends DomainEvent {
readonly eventType: 'POLICY_ENDORSED';
readonly aggregateType: 'Policy';
readonly endorsementNumber: number;
readonly changes: readonly FieldChange[];
readonly premiumAdjustment: Money;
}
// --- Claim Events ---
interface ClaimFiled extends DomainEvent {
readonly eventType: 'CLAIM_FILED';
readonly aggregateType: 'Claim';
readonly policyNumber: string;
readonly lossDate: Date;
readonly lossType: string;
readonly initialReserve: Money;
}
interface ClaimSettled extends DomainEvent {
readonly eventType: 'CLAIM_SETTLED';
readonly aggregateType: 'Claim';
readonly settlementAmount: Money;
readonly payee: string;
}
// --- Cross-Context Reactions ---
// PolicyIssued -> Billing: createInvoice()
// PolicyIssued -> Reinsurance: calculateCession()
// ClaimFiled -> FraudDetection: screenClaim()
// ClaimFiled -> Reinsurance: notifyCession()
// ClaimSettled -> Billing: adjustReserve()
// ClaimSettled -> Reinsurance: calculateRecovery()
ACORD標準と相互運用性
アコード (協同組合事業研究開発協会) 世界の保険業界のデータ標準を設定する組織。 開発者にとって、ACORD はヘルスケアの HL7/FHIR や金融の SWIFT に相当します。
ACORD データ標準: 概要
ACORD は、詳細なデータ モデル、メッセージ形式 (XML および JSON)、およびスキーマを提供します。 保険プロセス専用に設計されています。目標は流れを確保することです エコシステム内のすべてのプレーヤー(保険会社、ブローカー、代理店、 再保険会社と規制当局。
| スタンダードアコード | 形式 | 使用法 | セクタ |
|---|---|---|---|
| アコードAL3 | 所有者 (固定長) | 代理店と保険会社のデータ交換 (米国) | 損保パーソナルライン |
| ACORD XML | XMLスキーマ | 見積、発行、請求、請求 | 損保、生命、健康 |
| アコードGRLC2.0 | JSON/XML | 再保険および大規模商業(グローバル) | 再保険、専門分野 |
| ACORD次世代 | JSON (API ファースト) | マイクロサービス、REST API、非同期イベント | 分野横断型 |
| ACORDフォーム | PDF/XML | 標準化されたフォーム(証明書、付録) | 損保(米国) |
GRLC ジェネレーション 2.0 (2025 年 4 月)
近年で最も重要なアップデートと GRLC ジェネレーション 2.0、 マイクロサービスなどのきめ細かいトランザクション向けに最適化された、デジタルファーストの JSON ベースの標準 そしてAPI。ポリシーのライフサイクル全体のエンドツーエンドのストレートスルー処理をサポートします。 グローバルな再保険エコシステムで、古いものを経由せずに最新の統合を可能にします バッチ XML 形式。
保険用APIパターン
最新の保険 API は、ドメインの複雑さを反映した特定のパターンに従います。
- 非同期引用: 複雑な見積もり (商用、専門) には非同期処理が必要です。 API は、
quoteRequestId完了時に Webhook 経由で通知します - 一時的なバージョン管理: 各リソース (ポリシー、カバレッジ) には時間の次元があります。 API は次のクエリをサポートしています。
asOfDate歴史的な状態を回復する - 冪等性: バインドおよび支払い操作は冪等経由で行う必要があります
idempotencyKey重複を避けるために - イベントストリーミング: 状態の変更はイベント (Webhook またはメッセージ ブローカー) 経由で通知され、ダウンストリーム システムと統合されます。
規制の状況
保険業界は世界で最も規制が厳しい業界の 1 つです。開発者にとって、これはつまり、 多くのアーキテクチャ上の決定は コンプライアンスによって決まるからだけでなく、 エンジニアリングのベストプラクティス。
主要な規制とソフトウェアへの影響
| 規制 | 範囲 | ソフトウェアへの影響 |
|---|---|---|
| ソルベンシー II | EU - 資本と支払能力の要件 | リスクモデル、SCR(ソルベンシー資本要件)計算、XBRLレポート、データ品質フレームワーク |
| IFRS第17号 | グローバル - 保険契約の会計 | CSM(契約サービスマージン)計算、契約グループ化、測定モデル(BBA、VFA、PAA) |
| GDPR / プライバシー | EU - 個人データ保護 | きめ細かな同意、忘れられる権利と強制的な保持(矛盾)、仮名化、DPIA |
| IDD | EU - 保険販売 | コンサルティングのトレーサビリティ、製品の適切性、利益相反、契約前の文書化 |
| ドーラ | EU - デジタルオペレーショナルレジリエンス | ICTリスク管理、インシデントレポート、回復力テスト、サードパーティリスク(クラウドプロバイダー) |
| ICS2025 | グローバル - IAIG の自己資本基準 | 世界統一基準による自己資本計算(2025年より運用開始) |
GDPR と保険留保の対立
保険開発者にとって最も複雑なジレンマの 1 つは、GDPR によって次のことが課されることです。 そうだよ 忘却へ、ただし、保険規制では、 データの保持 5年から30年の範囲の期間(未引当金を伴う請求、法的紛争、義務) 保険数理)。典型的な解決策としては、 進歩的な仮名化: データ 識別子はトランザクションデータから分離され、可能な場合には削除され、維持されます。 規制上の義務のために匿名化されたデータ。
最新のインシュアテック プラットフォームのアーキテクチャ
最新の保険プラットフォームはアーキテクチャを採用しています クラウドネイティブ、APIファースト、 イベント駆動型。従来のモノリスは、境界が整ったマイクロサービスに分割されます ドメインコンテキスト。
典型的なテクノロジースタック (2025-2026)
| レイヤー | テクノロジー | 関数 |
|---|---|---|
| フロントエンド | Angular、React、Vue + マイクロフロントエンド | エージェントポータル、カスタマーポータル、バックオフィス |
| APIゲートウェイ | Kong、AWS API ゲートウェイ、Apigee | レート制限、認証、ルーティング、バージョン管理 |
| マイクロサービス | Node.js/NestJS、Java/Spring Boot、Go | ポリシー、請求、評価、請求、CRM |
| イベントバス | Apache Kafka、AWS EventBridge、RabbitMQ | ドメイン イベント、CQRS、イベント ソーシング |
| データベース | PostgreSQL、MongoDB、DynamoDB | サービスごとのデータベース (境界付きコンテキストごとのデータベース) |
| AI/ML | Python、TensorFlow、SageMaker | 不正行為の検出、価格設定の最適化、OCR ドキュメント |
| オーケストレーション | Kubernetes、AWS ECS、Temporal.io | スケーリング、サーガ パターン、長期実行ワークフロー |
| 可観測性 | Datadog、Grafana、OpenTelemetry | 分散トレース、メトリクス、集中ログ |
主要なアーキテクチャ パターン
ポリシーのイベントソーシング
L'イベントソーシング 特に保険分野に適しています。 ポリシーと本質的に一連のイベント (発行、承認、更新、請求) です。 現在の状態を単に保存するのではなく、すべてのイベントを保存して再構築します。 現在のステータスを経由して リプレイ。これにより、完全な監査証跡が自動的に提供されます。 重要な規制要件です。
クロスコンテキストプロセスの Saga パターン
保険契約の発行などのプロセスには、引受会社の承認、 保険契約管理者が発行し、請求担当者が請求書を作成し、再保険担当者が割り当てを計算します。の 物語のパターン (オーケストレーションされた、または振り付けされた)これらの分散されたステップを調整します 最終的な整合性と障害時の補償を確保します。 Temporal.io e 長時間実行されるステートフル ワークフローを実装するためにインシュアテックで特に人気があります しつこい。
マルチエージェント AI システム (トレンド 2026)
単一のモノリシックな AI アシスタントの代わりに、最先端の InsurTech プラットフォームが存在します。 実装する マルチエージェントシステム 専門エージェントの場合: 1 人のエージェント クレームの受付、1 つは不正行為のチェック、1 つは顧客への連絡、1 つは顧客への連絡 支払いと回収。これらのエージェントは明確なワークフローを通じて調整され、 これらは連携して、請求ライフサイクル全体を自動化します。
結論と次のステップ
保険ドメインは、開発者が直面する可能性のあるものの中で最も複雑かつ複雑なものの 1 つです。 この記事では、製品、アクター、バリュー チェーン、 データ モデル、ライフ サイクル、評価エンジン、適用される DDD、および規制の状況です。
ここにあります テイクアウト 主要:
- 保険商品は次のことを約束します。 これにより、データ モデルは本質的に一時的でバージョン管理されたものになります。
- 普遍的なモデルはありません。 生命保険、損保、健康、専門分野には大きく異なるニーズがあります
- ステートマシンと基本パターン: ポリシーとクレームの両方、ライフサイクル、および明確に定義された遷移を備えたステートマシン
- 不変性は次のような規制要件です。 変更を加えるたびに新しいバージョンが生成され、上書きされることはありません
- DDD と自然なアプローチ: バリューチェーンに合わせた限定されたコンテキスト、ビジネスの不変条件を保護する集計、分離のためのドメインイベント
- コンプライアンスがアーキテクチャを推進します。 ソルベンシー II、IFRS 17、GDPR、および DORA は「あれば便利」ではなく、主なアーキテクチャ上の制約です
- ACORD と共通語: ACORD 標準 (特に次世代 JSON) は、エコシステム内の相互運用性に不可欠です
次のエピソードでは
InsurTech Engineering シリーズの次回の記事では、 ポリシー 管理システム: 製品コンフィギュレーターを使用して最新の PAS を設計する方法、 一時的なバージョン管理、承認エンジン、および評価エンジンとの統合。見てみましょう 複数の補償が適用される保険商品の複雑さを管理するための具体的なパターン ドメイン主導のアプローチ。







