Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- The MIT License (MIT)
- --
- -- Copyright (c) 2023 Leandro Pereira de Lima e Silva
- --
- -- Permission is hereby granted, free of charge, to any person obtaining a copy
- -- of this software and associated documentation files (the "Software"), to deal
- -- in the Software without restriction, including without limitation the rights
- -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- -- copies of the Software, and to permit persons to whom the Software is
- -- furnished to do so, subject to the following conditions:
- --
- -- The above copyright notice and this permission notice shall be included in all
- -- copies or substantial portions of the Software.
- --
- -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- -- SOFTWARE.
- CREATE OR REPLACE FUNCTION npv(
- "values" numeric[],
- rate numeric,
- months numeric DEFAULT 12,
- derivative bool DEFAULT FALSE)
- returns numeric
- AS $$
- DECLARE
- ret double precision;
- k INTEGER;
- BEGIN
- ret := 0;
- FOR i IN 1..array_length(VALUES, 1) LOOP
- k := CASE WHEN derivative THEN -i ELSE 1 END;
- ret := ret + k * VALUES[i] / (1 + rate) ^ ((i - 1) * (months / 12));
- END LOOP;
- RETURN ret;
- END;
- $$ language plpgsql;
- CREATE OR REPLACE FUNCTION irr(
- "values" numeric[],
- months numeric DEFAULT 12,
- guess numeric DEFAULT 0.1,
- tol numeric DEFAULT 1e-12,
- maxiter INTEGER DEFAULT 100)
- returns numeric
- AS $$
- DECLARE
- val double precision;
- der double precision;
- new_guess double precision;
- BEGIN
- FOR j IN 1..maxiter LOOP
- val = npv(VALUES, guess, months);
- der = npv(VALUES, guess, months, derivative := TRUE);
- new_guess := guess - val / der;
- IF ABS(guess - new_guess) <= tol THEN
- RETURN guess;
- END IF;
- guess := new_guess;
- END LOOP;
- RETURN NULL;
- END;
- $$ language plpgsql;
Advertisement