From 33ac1f9f6fed7cf8d4a0f5f3e4382a663a0aabfb Mon Sep 17 00:00:00 2001 From: alecloudenback Date: Sat, 4 Nov 2023 09:10:22 -0500 Subject: [PATCH] allow projections on AbstractArray of contracts (#170) --- docs/src/contracts.md | 16 ++++++++++++++++ src/Projection.jl | 5 +++++ test/sp.jl | 12 ++++++++++++ 3 files changed, 33 insertions(+) diff --git a/docs/src/contracts.md b/docs/src/contracts.md index 440c7e2..a637893 100644 --- a/docs/src/contracts.md +++ b/docs/src/contracts.md @@ -88,6 +88,22 @@ Note that all contracts in FinanceModels.jl are currently *unit* contracts in th #### More complex Contracts +##### Sets of contracts + +Sets of contracts can be put in an `AbstractArray` contained (e.g. a `Vector`) and then handled together. For example, we combine two bonds as a portfolio to project together: + +```julia-repl +julia> c1 = Bond.Fixed(0.05, Periodic(1), 2.0); +julia> c2 = Bond.Fixed(0.04, Periodic(1), 2.0); + +julia> Projection([c1, c2]) |> collect +4-element Vector{Cashflow{Float64, Float64}}: + Cashflow{Float64, Float64}(0.05, 1.0) + Cashflow{Float64, Float64}(1.05, 2.0) + Cashflow{Float64, Float64}(0.04, 1.0) + Cashflow{Float64, Float64}(1.04, 2.0) +``` + ##### Transformations Contracts (`<:AbstractContract`) and [`Projection`](@ref)s can be modified to be scaled or transformed using the transformations in [Transducers.jl](https://juliafolds2.github.io/Transducers.jl/stable/#List-of-transducers) after importing that package. diff --git a/src/Projection.jl b/src/Projection.jl index ba2a503..3baf262 100644 --- a/src/Projection.jl +++ b/src/Projection.jl @@ -88,6 +88,11 @@ Projection(c, m) = Projection(c, m, CashflowProjection()) function Transducers.asfoldable(c::C) where {C<:FinanceCore.AbstractContract} Projection(c) |> Map(identity) end +function Transducers.asfoldable(p::Projection{C,M,K}) where {C<:AbstractArray,M,K} + map(p.contract) do c + Projection(c, p.model, p.kind) + end |> Cat() +end # A cashflow is the simplest, single item reducible collection @inline function Transducers.__foldl__(rf, val, p::Projection{C,M,K}) where {C<:Cashflow,M,K} diff --git a/test/sp.jl b/test/sp.jl index 74c21c1..082fc5a 100644 --- a/test/sp.jl +++ b/test/sp.jl @@ -23,6 +23,18 @@ end @test pv(Yield.Constant(0.05), p) ≈ 1.0 end +@testset "AbstractArray of contracts" begin + c = Bond.Fixed(0.05, Periodic(1), 3.0) + p = Projection([c, c]) + @test length(collect(p)) == 6 + @test pv(Yield.Constant(0.00), p) ≈ 2.3 + p = Projection([c, c |> Map(-)]) + @test length(collect(p)) == 6 + @test pv(Yield.Constant(0.00), p) ≈ 0.0 + + + +end @testset "Floating Bonds" begin p = Projection( Bond.Floating(0.02, Periodic(1), 3.0, "SOFR"),