diff options
Diffstat (limited to 'tests/FundLab.Domain.Tests')
| -rw-r--r-- | tests/FundLab.Domain.Tests/DomainTests.fs | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/tests/FundLab.Domain.Tests/DomainTests.fs b/tests/FundLab.Domain.Tests/DomainTests.fs index f2b4138..6a9fc66 100644 --- a/tests/FundLab.Domain.Tests/DomainTests.fs +++ b/tests/FundLab.Domain.Tests/DomainTests.fs @@ -491,3 +491,51 @@ module DomainTests = Assert.Equal(Error(InvalidObservation "net assets cannot be negative"), negative) Assert.Equal(Error(InvalidObservation "first net assets must be positive"), zero) + +module RedemptionPolicyTests = + + open Xunit + open FundLab.Domain + + let private unwrap result = + match result with + | Ok value -> value + | Error error -> failwithf "%A" error + + [<Fact>] + let ``redemption request above available units is rejected`` () = + Assert.Equal(Error "requested units exceed available holdings", RedemptionPolicy.validateRequest 10.00000000m 10.00000001m 0.00m) + Assert.Equal(Error "redemption units must be positive", RedemptionPolicy.validateRequest 10.00000000m 0m 0.00m) + Assert.Equal(Error "redemption fee cannot be negative", RedemptionPolicy.validateRequest 10.00000000m 5.00000000m -0.01m) + Assert.Equal(Ok(), RedemptionPolicy.validateRequest 10.00000000m 10.00000000m 1.50m) + + [<Fact>] + let ``full redemption releases the entire position cost`` () = + let computed = RedemptionPolicy.compute 40.00000000m 2.5m 1.00m 100.00m 40.00000000m |> unwrap + + Assert.Equal(100.00m, computed.GrossCash) + Assert.Equal(1.00m, computed.Fee) + Assert.Equal(99.00m, computed.Proceeds) + Assert.Equal(100.00m, computed.RedeemedCost) + + [<Fact>] + let ``partial redemption writes off cost pro rata rounded down`` () = + let computed = RedemptionPolicy.compute 10.00000000m 2.5m 0.00m 100.00m 40.00000000m |> unwrap + + Assert.Equal(25.00m, computed.GrossCash) + Assert.Equal(0.00m, computed.Fee) + Assert.Equal(25.00m, computed.Proceeds) + Assert.Equal(25.00m, computed.RedeemedCost) + + let uneven = RedemptionPolicy.compute 1.00000000m 3m 0.00m 100.00m 3.00000000m |> unwrap + + Assert.Equal(3.00m, uneven.GrossCash) + Assert.Equal(33.33m, uneven.RedeemedCost) + + [<Fact>] + let ``redemption computation rejects invalid economics`` () = + Assert.Equal(Error "redemption units exceed position units", RedemptionPolicy.compute 41.00000000m 2.5m 0.00m 100.00m 40.00000000m) + Assert.Equal(Error "unit nav must be positive", RedemptionPolicy.compute 1.00000000m 0m 0.00m 100.00m 40.00000000m) + Assert.Equal(Error "redemption fee exceeds redemption value", RedemptionPolicy.compute 1.00000000m 2.5m 3.00m 100.00m 40.00000000m) + Assert.Equal(Error "redemption proceeds rounds to zero", RedemptionPolicy.compute 0.00000001m 1500000m 0.01m 100.00m 40.00000000m) + Assert.Equal(Error "redemption cash rounds to zero", RedemptionPolicy.compute 0.00000001m 2m 0.00m 100.00m 40.00000000m) |
