Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more profit measures #61

Open
1 of 2 tasks
alecloudenback opened this issue Jan 19, 2022 · 6 comments · May be fixed by #91
Open
1 of 2 tasks

Add more profit measures #61

alecloudenback opened this issue Jan 19, 2022 · 6 comments · May be fixed by #91
Labels

Comments

@alecloudenback
Copy link
Member

alecloudenback commented Jan 19, 2022

There's already breakeven, irr, embedded_value (via pv) Add

@leeyuntien
Copy link

Has mirr been implemented? If not maybe i can take a stab.

@alecloudenback
Copy link
Member Author

Has mirr been implemented? If not maybe i can take a stab.

Nope, it hasn't! Go for it :)

@KuldeepBorkar
Copy link
Contributor

@alecloudenback could you please tell me where npv (net present value) is implemented so that I can use it to implement mirr

@alecloudenback
Copy link
Member Author

@alecloudenback could you please tell me where npv (net present value) is implemented so that I can use it to implement mirr

"""
present_value(interest, cashflows::Vector, timepoints)
present_value(interest, cashflows::Vector)
Discount the `cashflows` vector at the given `interest_interestrate`, with the cashflows occurring
at the times specified in `timepoints`. If no `timepoints` given, assumes that cashflows happen at times 1,2,...,n.
The `interest` can be an `InterestCurve`, a single scalar, or a vector wrapped in an `InterestCurve`.
# Examples
```julia-repl
julia> present_value(0.1, [10,20],[0,1])
28.18181818181818
julia> present_value(Yields.Forward([0.1,0.2]), [10,20],[0,1])
28.18181818181818 # same as above, because first cashflow is at time zero
```
Example on how to use real dates using the [DayCounts.jl](https://github.com/JuliaFinance/DayCounts.jl) package
```jldoctest
using DayCounts
dates = Date(2012,12,31):Year(1):Date(2013,12,31)
times = map(d -> yearfrac(dates[1], d, DayCounts.Actual365Fixed()),dates) # [0.0,1.0]
present_value(0.1, [10,20],times)
# output
28.18181818181818
```
"""
function present_value(yc::T, cashflows, timepoints) where {T <: Yields.AbstractYield}
s = 0.0
for (cf,t) in zip(cashflows,timepoints)
v = discount(yc,t)
@muladd s = s + v * cf
end
# sum(discount(yc,t) * cf for (t,cf) in zip(timepoints, cashflows))
s
end
function present_value(yc::T, cashflows) where {T <: Yields.AbstractYield}
present_value(yc,cashflows,1:length(cashflows))
end
function present_value(i, x)
v = 1.0
v_factor = discount(i,0,1)
pv = 0.0
for (t,cf) in enumerate(x)
v = v * v_factor
@muladd pv = pv + v * cf
end
return pv
end
function present_value(i, v, times)
return present_value(Yields.Constant(i), v, times)
end
# Interest Given is an array, assume forwards.
function present_value(i::AbstractArray, v)
yc = Yields.Forward(i)
return sum(discount(yc, t) * cf for (t,cf) in enumerate(v))
end
# Interest Given is an array, assume forwards.
function present_value(i::AbstractArray, v, times)
yc = Yields.Forward(i, times)
return sum(discount(yc, t) * cf for (cf, t) in zip(v,times))
end
"""
pv()
An alias for `present_value`.
"""
pv = present_value
"""
present_value(interest, cashflows::Vector, timepoints)
present_value(interest, cashflows::Vector)
Efficiently calculate a vector representing the present value of the given cashflows at each period prior to the given timepoint.
# Examples
```julia-repl
julia> present_values(0.00, [1,1,1])
[3,2,1]
julia> present_values(Yields.Forward([0.1,0.2]), [10,20],[0,1])
2-element Vector{Float64}:
28.18181818181818
18.18181818181818
```
"""
function present_values(interest, cashflows)
pvs = Vector{Float64}(undef,length(cashflows))
pvs[end] = Yields.discount(interest, lastindex(cashflows) - 1, lastindex(cashflows)) * cashflows[end]
for (t, cf) in Iterators.reverse(enumerate(cashflows[1:end - 1]))
pvs[t] = Yields.discount(interest, t - 1, t) * (cf + pvs[t + 1])
end
return pvs
end
function present_values(interest,cashflows,times)
present_values_accumulator(interest,cashflows,times)
end
function present_values_accumulator(interest,cashflows,times,pvs=[0.0])
from_time = length(times) == 1 ? 0. : times[end-1]
pv = discount(interest,from_time,last(times)) *(first(pvs) + last(cashflows))
pvs = pushfirst!(pvs,pv)
if length(cashflows) > 1
new_cfs = @view cashflows[1:end-1]
new_times = @view times[1:end-1]
return present_values_accumulator(interest,new_cfs,new_times,pvs)
else
# last discount and return
return pvs[1:end-1] # end-1 get rid of trailing 0.0
end
end
# if given a vector of rates, assume that it should be a forward discount yield
function present_values(y::Vector{T}, cfs, times) where {T <: Real}
return present_values(Yields.Forward(y), cfs, times)
end

@KuldeepBorkar
Copy link
Contributor

@alecloudenback I was able to find PV there but I was not able to find NPV.
Is NPV implemented seperately or should I be using PV only????
Could you please elaborate a bit😿

@alecloudenback
Copy link
Member Author

present_value is a more flexible and generic version of what other languages (python, Excel) call NPV, see #27

@KuldeepBorkar KuldeepBorkar linked a pull request Oct 27, 2022 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: New features
Development

Successfully merging a pull request may close this issue.

3 participants