summaryrefslogtreecommitdiff
path: root/tests/FundLab.Domain.Tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests/FundLab.Domain.Tests')
-rw-r--r--tests/FundLab.Domain.Tests/DomainTests.fs48
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)