Skip to content

Commit 5d0d9f7

Browse files
committed
add select and net_present_value functions
1 parent 33c9d52 commit 5d0d9f7

File tree

2 files changed

+107
-9
lines changed

2 files changed

+107
-9
lines changed

climada/entity/disc_rates/base.py

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
from climada.util.files_handler import to_list, get_file_names
1616
import climada.util.checker as check
1717
from climada.entity.tag import Tag
18-
import climada.util.plot as plot
18+
import climada.util.plot as u_plot
19+
import climada.util.finance as u_fin
1920

2021
LOGGER = logging.getLogger(__name__)
2122

@@ -100,6 +101,27 @@ def read(self, files, descriptions='', var_names=None):
100101
for file, desc, var in zip(all_files, desc_list, var_list):
101102
self.append(self._read_one(file, desc, var))
102103

104+
def select(self, year_range):
105+
"""Select discount rates in given years.
106+
107+
Parameters:
108+
year_range (np.array): continuous sequence of selected years.
109+
110+
Returns:
111+
DiscRates
112+
"""
113+
pos_year = np.isin(year_range, self.years)
114+
if not np.all(pos_year):
115+
LOGGER.info('No discount rates for given years.')
116+
return None
117+
pos_year = np.isin(self.years, year_range)
118+
sel_disc = self.__class__()
119+
sel_disc.tag = self.tag
120+
sel_disc.years = self.years[pos_year]
121+
sel_disc.rates = self.rates[pos_year]
122+
123+
return sel_disc
124+
103125
def append(self, disc_rates):
104126
"""Check and append discount rates to current DiscRates. Overwrite
105127
discount rate if same year.
@@ -130,6 +152,29 @@ def append(self, disc_rates):
130152
self.years = np.append(self.years, new_year).astype(int, copy=False)
131153
self.rates = np.append(self.rates, new_rate)
132154

155+
def net_present_value(self, ini_year, end_year, val_years):
156+
"""Compute net present value between present year and future year.
157+
158+
Parameters:
159+
ini_year (float): initial year
160+
end_year (float): end year
161+
val_years (np.array): cash flow at each year btw ini_year and
162+
end_year (both included)
163+
Returns:
164+
float
165+
"""
166+
year_range = np.arange(ini_year, end_year+1)
167+
if year_range.size != val_years.size:
168+
LOGGER.info('Wrong size of yearly values.')
169+
return None
170+
sel_disc = self.select(year_range)
171+
if sel_disc is None:
172+
LOGGER.info('No information of discount rates for provided years:'\
173+
' %s - %s', ini_year, end_year)
174+
return None
175+
return u_fin.net_present_value(sel_disc.years, sel_disc.rates,
176+
val_years)
177+
133178
@staticmethod
134179
def get_sup_file_format():
135180
""" Get supported file extensions that can be read.
@@ -141,7 +186,7 @@ def get_sup_file_format():
141186

142187
def plot(self):
143188
"""Plot discount rates per year."""
144-
graph = plot.Graph2D('Discount rates')
189+
graph = u_plot.Graph2D('Discount rates')
145190
graph.add_subplot('Year', 'discount rate (%)', '')
146191
graph.add_curve(self.years, self.rates * 100, 'b')
147192
graph.set_x_lim(self.years)

climada/entity/disc_rates/test/test_base.py

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,22 @@ def test_attributes_all(self):
3535

3636
def test_get_def_vars(self):
3737
""" Test def_source_vars function."""
38-
self.assertTrue(DiscRates.get_def_file_var_names('xls') ==
38+
self.assertTrue(DiscRates.get_def_file_var_names('xls') ==
3939
READ_SET['XLS'][0])
40-
self.assertTrue(DiscRates.get_def_file_var_names('.mat') ==
40+
self.assertTrue(DiscRates.get_def_file_var_names('.mat') ==
4141
READ_SET['MAT'][0])
4242

4343
class TestAppend(unittest.TestCase):
4444
"""Check append function"""
4545
def test_append_to_empty_same(self):
46-
"""Append DiscRates to empty one."""
46+
"""Append DiscRates to empty one."""
4747
disc_rate = DiscRates()
4848
disc_rate_add = DiscRates()
4949
disc_rate_add.tag.file_name = 'file1.txt'
5050
disc_rate_add.tag.description = 'descr1'
5151
disc_rate_add.years = np.array([2000, 2001, 2002])
5252
disc_rate_add.rates = np.array([0.1, 0.2, 0.3])
53-
53+
5454
disc_rate.append(disc_rate_add)
5555
disc_rate.check()
5656

@@ -62,7 +62,7 @@ def test_append_to_empty_same(self):
6262
disc_rate_add.tag.description))
6363

6464
def test_append_equal_same(self):
65-
"""Append the same DiscRates. The inital DiscRates is obtained."""
65+
"""Append the same DiscRates. The inital DiscRates is obtained."""
6666
disc_rate = DiscRates()
6767
disc_rate.tag.file_name = 'file1.txt'
6868
disc_rate.tag.description = 'descr1'
@@ -74,7 +74,7 @@ def test_append_equal_same(self):
7474
disc_rate_add.tag.description = 'descr1'
7575
disc_rate_add.years = np.array([2000, 2001, 2002])
7676
disc_rate_add.rates = np.array([0.1, 0.2, 0.3])
77-
77+
7878
disc_rate.append(disc_rate_add)
7979
disc_rate.check()
8080

@@ -97,7 +97,7 @@ def test_append_different_append(self):
9797
disc_rate_add.tag.description = 'descr2'
9898
disc_rate_add.years = np.array([2000, 2001, 2003])
9999
disc_rate_add.rates = np.array([0.11, 0.22, 0.33])
100-
100+
101101
disc_rate.append(disc_rate_add)
102102
disc_rate.check()
103103

@@ -119,9 +119,62 @@ def test_read_two_pass(self):
119119
self.assertEqual(disc_rate.tag.description, 'desc1 + desc2')
120120
self.assertEqual(disc_rate.years.size, 51)
121121

122+
class TestSelect(unittest.TestCase):
123+
"""Test select method """
124+
def test_select_pass(self):
125+
"""Test select right time range."""
126+
disc_rate = DiscRates()
127+
disc_rate.tag.file_name = 'file1.txt'
128+
disc_rate.tag.description = 'descr1'
129+
disc_rate.years = np.arange(2000, 2050)
130+
disc_rate.rates = np.arange(disc_rate.years.size)
131+
132+
year_range = np.arange(2010, 2020)
133+
sel_disc = disc_rate.select(year_range)
134+
135+
self.assertTrue(np.array_equal(sel_disc.years, year_range))
136+
self.assertTrue(np.array_equal(sel_disc.rates, disc_rate.rates[10:20]))
137+
138+
def test_select_wrong_pass(self):
139+
"""Test select wrong time range."""
140+
disc_rate = DiscRates()
141+
disc_rate.tag.file_name = 'file1.txt'
142+
disc_rate.tag.description = 'descr1'
143+
disc_rate.years = np.arange(2000, 2050)
144+
disc_rate.rates = np.arange(disc_rate.years.size)
145+
146+
year_range = np.arange(2050, 2060)
147+
self.assertEqual(None, disc_rate.select(year_range))
148+
149+
class TestNetPresValue(unittest.TestCase):
150+
"""Test select method """
151+
def test_net_present_value_pass(self):
152+
"""Test net_present_value right time range."""
153+
disc_rate = DiscRates()
154+
disc_rate.tag.file_name = 'file1.txt'
155+
disc_rate.tag.description = 'descr1'
156+
disc_rate.years = np.arange(2000, 2050)
157+
disc_rate.rates = np.ones(disc_rate.years.size)*0.02
158+
159+
val_years = np.ones(23)*6.512201157564418e9
160+
res = disc_rate.net_present_value(2018, 2040, val_years)
161+
self.assertEqual(res, 1.215049630691397e+11)
162+
163+
def test_net_present_value_wrong_pass(self):
164+
"""Test net_present_value wrong time range."""
165+
disc_rate = DiscRates()
166+
disc_rate.tag.file_name = 'file1.txt'
167+
disc_rate.tag.description = 'descr1'
168+
disc_rate.years = np.arange(2000, 2050)
169+
disc_rate.rates = np.arange(disc_rate.years.size)
170+
val_years = np.ones(11)*6.512201157564418e9
171+
self.assertEqual(None, disc_rate.net_present_value(2050, 2060, val_years))
172+
122173
# Execute Tests
123174
TESTS = unittest.TestLoader().loadTestsFromTestCase(TestChecker)
124175
TESTS.addTests(unittest.TestLoader().loadTestsFromTestCase(TestAppend))
125176
TESTS.addTests(unittest.TestLoader().loadTestsFromTestCase(TestConstructor))
126177
TESTS.addTests(unittest.TestLoader().loadTestsFromTestCase(TestReadParallel))
178+
TESTS.addTests(unittest.TestLoader().loadTestsFromTestCase(TestSelect))
179+
TESTS.addTests(unittest.TestLoader().loadTestsFromTestCase(TestNetPresValue))
127180
unittest.TextTestRunner(verbosity=2).run(TESTS)

0 commit comments

Comments
 (0)