Skip to content

Commit 1498f6a

Browse files
authored
Merge pull request #818 from smucclaw/mengwong/fibo
Merging ACTUS/FIBO analyzer with qualia-based classification. Changes: - jl4-actus-analyzer: New static analyzer for ACTUS/FIBO classification - Qualia-based classification system (ObligationGraph, Essence, Archetypes) - ACTUS L4 library (actus-core, actus-daycount, actus-schedule, etc.) - Refactored ACTUS to use daydate library (DRY) - Fixed Scorer.hs: minConfidence now properly parameterized - Comprehensive end-of-month date handling tests Note: Admin merge due to pre-existing doc validation errors from main branch restructure (tracked in separate issue).
2 parents 41edd3d + 0856a7f commit 1498f6a

File tree

74 files changed

+12625
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+12625
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,4 @@ yarn-error.log*
6363
# Generated skill packages
6464
l4/l4.skill
6565
l4/l4.zip
66+
.cache/

cabal.project

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ packages:
66
./jl4-repl
77
./jl4-decision-service
88
./jl4-websessions
9+
./jl4-actus-analyzer
910

1011
index-state: 2025-03-31T10:46:26Z
1112

jl4-actus-analyzer/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 SMU Centre for Computational Law
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

jl4-actus-analyzer/README.md

Lines changed: 363 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,363 @@
1+
# jl4-actus-analyzer
2+
3+
A static analyzer that classifies L4 contract encodings by ACTUS contract type and FIBO financial ontology class.
4+
5+
## Overview
6+
7+
This tool consumes FIBO/ACTUS RDF ontologies directly and uses pattern-based scoring to classify L4 contracts. It extracts semantic features from L4 AST (type declarations, deontic rules, state machines) and matches them against known financial contract patterns.
8+
9+
## Installation
10+
11+
```bash
12+
# Build the analyzer
13+
cabal build jl4-actus-analyzer
14+
15+
# Install the CLI tool
16+
cabal install exe:jl4-actus --overwrite-policy=always
17+
```
18+
19+
## Usage
20+
21+
### Command Line
22+
23+
```bash
24+
# Analyze a single L4 file (default: Markdown output)
25+
jl4-actus contract.l4
26+
27+
# Analyze multiple files together
28+
jl4-actus file1.l4 file2.l4 file3.l4
29+
30+
# Output as JSON
31+
jl4-actus --json contract.l4
32+
33+
# Output as RDF/Turtle
34+
jl4-actus --rdf contract.l4
35+
36+
# Specify custom FIBO repository path
37+
jl4-actus --fibo ~/src/edmcouncil/fibo contract.l4
38+
39+
# Disable ontology caching (slower but always fresh)
40+
jl4-actus --no-cache contract.l4
41+
42+
# Rebuild the ontology cache
43+
jl4-actus --rebuild-cache
44+
45+
# Set minimum confidence threshold (default: 0.3)
46+
jl4-actus --min-confidence 0.5 contract.l4
47+
```
48+
49+
### Programmatic API
50+
51+
```haskell
52+
import L4.ACTUS.Analyzer
53+
54+
main :: IO ()
55+
main = do
56+
result <- analyzeFile defaultConfig "contract.l4"
57+
case result of
58+
Left err -> print err
59+
Right classification -> do
60+
print classification.primaryActusType -- e.g., Just "FXOUT"
61+
print classification.primaryConfidence -- e.g., 0.87
62+
print classification.primaryFiboClass -- FIBO URI
63+
```
64+
65+
## Supported Contract Types
66+
67+
### ACTUS Types with Matching Rules
68+
69+
| ACTUS Code | Description | Key Features Detected |
70+
| ------------------- | ---------------------------- | ----------------------------------------------------------------- |
71+
| **FXOUT** | Foreign Exchange Outright | Currency types, two-currency exchange, value date, settlement |
72+
| **SWAPS** | Plain Vanilla Swap | Payment legs, notional amount, payment schedule |
73+
| **OPTNS** | Options | Strike price, expiration date, underlying asset, premium |
74+
| **PAM** | Principal at Maturity | Principal, interest rate, maturity date |
75+
| **FUTUR** | Futures | Contract size, settlement date, underlying, margin |
76+
| **MasterAgreement** | Master Agreement (container) | Schedule structure, multiple transaction types, close-out netting |
77+
78+
### ACTUS-to-FIBO Mappings
79+
80+
The analyzer maps ACTUS types to their corresponding FIBO ontology classes:
81+
82+
| ACTUS Code | FIBO Class |
83+
| --------------- | -------------------------------------------------- |
84+
| FXOUT | `fibo-der-drc-cur:ForeignExchangeForwardAgreement` |
85+
| SWAPS | `fibo-der-drc-swp:Swap` |
86+
| OPTNS | `fibo-der-drc-opt:Option` |
87+
| PAM | `fibo-sec-dbt-di:DebtInstrument` |
88+
| ANN | `fibo-sec-dbt-di:DebtInstrument` |
89+
| LAM | `fibo-sec-dbt-di:DebtInstrument` |
90+
| NAM | `fibo-sec-dbt-di:DebtInstrument` |
91+
| FUTUR | `fibo-fbc-fi-fi:Future` |
92+
| STK | `fibo-sec-eq-ei:Share` |
93+
| CDSWP | `fibo-der-cr-cds:CreditDefaultSwap` |
94+
| TRSWP | `fibo-der-drc-swp:TotalReturnSwap` |
95+
| CEG | `fibo-fbc-dae-dbt:CreditEnhancementAgreement` |
96+
| CEC | `fibo-fbc-pas-caa:CollateralAccount` |
97+
| MasterAgreement | `fibo-fnd-agr-ctr:MasterAgreement` |
98+
99+
## Architecture
100+
101+
```
102+
┌─────────────────────┐ ┌──────────────────────┐
103+
│ L4 Source Files │ │ FIBO/ACTUS RDF │
104+
│ (*.l4) │ │ (ontology files) │
105+
└─────────┬───────────┘ └──────────┬───────────┘
106+
│ │
107+
v v
108+
┌─────────────────────┐ ┌──────────────────────┐
109+
│ jl4-core Parser │ │ RDF Loader (rdf4h) │
110+
│ + TypeChecker │ │ + Binary Cache │
111+
└─────────┬───────────┘ └──────────┬───────────┘
112+
│ │
113+
v v
114+
┌─────────────────────────────────────────────────┐
115+
│ L4.ACTUS.Analyzer │
116+
│ ┌─────────────────┐ ┌─────────────────────┐ │
117+
│ │FeatureExtractor │ │ OntologyMatcher │ │
118+
│ │- Type patterns │ │- Pattern rules │ │
119+
│ │- Deontic rules │ │- Confidence scoring │ │
120+
│ │- State machine │ │- FIBO mapping │ │
121+
│ └────────┬────────┘ └──────────┬──────────┘ │
122+
│ └──────────┬───────────┘ │
123+
│ v │
124+
│ ┌──────────────────┐ │
125+
│ │ ClassificationResult │
126+
│ └──────────────────┘ │
127+
└─────────────────────┬───────────────────────────┘
128+
v
129+
┌──────────────────────────┐
130+
│ Output (JSON/RDF/MD) │
131+
└──────────────────────────┘
132+
```
133+
134+
## Feature Extraction
135+
136+
The analyzer extracts the following semantic features from L4 AST:
137+
138+
### Domain Indicators
139+
140+
| Indicator | What It Detects |
141+
| -------------------------- | --------------------------------------------------- |
142+
| `CurrencyIndicator` | Enum types with currency codes (USD, EUR, etc.) |
143+
| `FXTransactionIndicator` | Records with two currency fields, value date |
144+
| `SwapIndicator` | Leg structures, notional amounts, payment schedules |
145+
| `OptionIndicator` | Strike price, expiry date, underlying asset |
146+
| `LoanIndicator` | Principal, interest rate, amortization schedule |
147+
| `SettlementIndicator` | Netting provisions, delivery obligations |
148+
| `CreditSupportIndicator` | Guaranty, collateral, margin requirements |
149+
| `MasterAgreementIndicator` | Schedule structure, close-out netting |
150+
151+
### Deontic Patterns
152+
153+
Detects MUST/MAY/SHANT obligations from L4 regulative rules:
154+
155+
- Party roles (obligor, beneficiary)
156+
- Action types (deliver, pay, exercise)
157+
- Consequences (HENCE/LEST clauses)
158+
159+
### State Transitions
160+
161+
Extracts state machine patterns from HENCE/LEST clauses:
162+
163+
- Breach detection
164+
- State progression
165+
- Trigger conditions
166+
167+
### Type Patterns
168+
169+
Classifies L4 type declarations:
170+
171+
- `CurrencyEnumType` - Currency code enumerations
172+
- `AmountRecordType` - Value + currency records
173+
- `TransactionRecordType` - Transaction with parties, amounts, dates
174+
- `PartyRecordType` - Party/counterparty definitions
175+
- `ObligationRecordType` - Duty/obligation records
176+
- `SettlementRecordType` - Settlement/netting records
177+
178+
## Confidence Scoring
179+
180+
Each rule has weighted matchers that contribute to a total confidence score:
181+
182+
```haskell
183+
-- Example: FX Outright scoring
184+
fxOutrightRule = MatchingRule
185+
{ ruleActusType = "FXOUT"
186+
, ruleMatchers =
187+
[ FeatureMatcher "Currency types" 0.25 hasCurrencyTypes
188+
, FeatureMatcher "FX transaction type" 0.20 hasFXTransactionType
189+
, FeatureMatcher "Two currency exchange" 0.15 hasTwoCurrencyExchange
190+
, FeatureMatcher "Value date" 0.15 hasValueDateFeature
191+
, FeatureMatcher "Settlement provisions" 0.10 hasSettlementProvisions
192+
, FeatureMatcher "Bilateral parties" 0.10 hasBilateralParties
193+
, FeatureMatcher "Master agreement" 0.05 hasMasterAgreementStructure
194+
]
195+
, ruleMinConfidence = 0.3
196+
}
197+
```
198+
199+
- Scores are normalized to 0.0 - 1.0
200+
- Matches below `minConfidence` threshold are not reported
201+
- Primary classification is the highest-scoring match
202+
203+
## Container/Contained Classification
204+
205+
For master agreements that govern multiple transaction types, the analyzer reports:
206+
207+
1. **Container Type** - The master agreement itself (e.g., ISDA, IFEMA)
208+
2. **Contained Types** - Transaction types governed by the agreement
209+
210+
Example output:
211+
212+
```json
213+
{
214+
"container": {
215+
"type": "MasterAgreement",
216+
"fiboClass": "fibo-fnd-agr-ctr:MasterAgreement"
217+
},
218+
"containedTypes": [
219+
{ "actusType": "FXOUT", "confidence": 0.87 },
220+
{ "actusType": "SWAPS", "confidence": 0.42 }
221+
]
222+
}
223+
```
224+
225+
## Extending the Analyzer
226+
227+
### Adding a New Contract Type
228+
229+
1. **Add domain indicator** (if new patterns needed) in `FeatureExtractor.hs`:
230+
231+
```haskell
232+
data DomainIndicator
233+
= ...
234+
| NewContractInd NewContractIndicatorData
235+
236+
data NewContractIndicatorData = NewContractIndicatorData
237+
{ ncHasFeatureX :: Bool
238+
, ncHasFeatureY :: Bool
239+
, ncLocation :: Maybe SourceLocation
240+
}
241+
```
242+
243+
2. **Add detection logic** in `extractDomainIndicators`:
244+
245+
```haskell
246+
detectRecordIndicator name fields
247+
| isNewContractName name =
248+
Just $ NewContractInd NewContractIndicatorData
249+
{ ncHasFeatureX = hasFieldNamed ["featureX"] fields
250+
, ncHasFeatureY = hasFieldNamed ["featureY"] fields
251+
, ncLocation = Nothing
252+
}
253+
```
254+
255+
3. **Add matching rule** in `Rules.hs`:
256+
257+
```haskell
258+
newContractRule :: MatchingRule
259+
newContractRule = MatchingRule
260+
{ ruleActusType = "NEWCT"
261+
, ruleMatchers =
262+
[ FeatureMatcher "Feature X" 0.30 hasFeatureX
263+
, FeatureMatcher "Feature Y" 0.25 hasFeatureY
264+
-- ... more matchers
265+
]
266+
, ruleMinConfidence = 0.3
267+
}
268+
269+
-- Add to defaultRules list
270+
defaultRules = [..., newContractRule]
271+
```
272+
273+
4. **Add FIBO mapping** in `ACTUS.hs`:
274+
275+
```haskell
276+
actusToFIBOMapping = Map.fromList
277+
[ ...
278+
, ("NEWCT", mkURI "https://spec.edmcouncil.org/fibo/ontology/.../NewContract")
279+
]
280+
```
281+
282+
### Future: Ontology-Driven Rule Generation
283+
284+
The `buildRulesFromOntology` function is designed to eventually parse ACTUS coverage descriptions directly from RDF to generate matching rules automatically. Currently it returns `defaultRules`, but the infrastructure is in place for dynamic rule generation.
285+
286+
## Ontology Cache
287+
288+
The analyzer caches parsed ontology data for faster subsequent runs:
289+
290+
- **Cache location:** `.cache/jl4-actus/ontology.bin`
291+
- **Cache invalidation:** Automatic when source RDF files change
292+
- **Manual rebuild:** `jl4-actus --rebuild-cache`
293+
294+
## Dependencies
295+
296+
- **jl4-core** - L4 parser and type checker
297+
- **rdf4h** - RDF parsing library with proper RDF/XML support
298+
- **aeson** - JSON serialization
299+
- **binary** - Binary cache serialization
300+
- **optparse-applicative** - CLI argument parsing
301+
302+
## Testing
303+
304+
```bash
305+
# Run all tests
306+
cabal test jl4-actus-analyzer
307+
308+
# Tests include:
309+
# - Feature extraction unit tests
310+
# - Matching rule tests
311+
# - FIBO mapping tests
312+
# - Confidence scoring tests
313+
# - Container/contained detection tests
314+
```
315+
316+
## Example Output
317+
318+
### Markdown (default)
319+
320+
```markdown
321+
# ACTUS Classification Report
322+
323+
## Primary Classification
324+
325+
| Property | Value |
326+
| ---------- | -------------------------------------------------- |
327+
| ACTUS Type | **FXOUT** |
328+
| Label | foreign exchange outright |
329+
| Confidence | 100.0% |
330+
| FIBO Class | `fibo-der-drc-cur:ForeignExchangeForwardAgreement` |
331+
332+
## Supporting Evidence
333+
334+
| Feature | Weight |
335+
| --------------------- | ------ |
336+
| Currency types | 25.0% |
337+
| FX transaction type | 20.0% |
338+
| Two currency exchange | 15.0% |
339+
340+
...
341+
```
342+
343+
### JSON
344+
345+
```json
346+
{
347+
"primaryClassification": {
348+
"actusType": "FXOUT",
349+
"actusLabel": "foreign exchange outright",
350+
"confidence": 1.0,
351+
"fiboClass": "https://spec.edmcouncil.org/fibo/..."
352+
},
353+
"containerType": "MasterAgreement",
354+
"containedTypes": [...],
355+
"evidence": [...]
356+
}
357+
```
358+
359+
## Related Resources
360+
361+
- [ACTUS Algorithmic Contract Types](https://www.actusfrf.org/)
362+
- [FIBO Financial Industry Business Ontology](https://spec.edmcouncil.org/fibo/)
363+
- [L4 Language Documentation](../doc/README.md)

0 commit comments

Comments
 (0)