From 9470ea697b384e40285cea66552eea43d4d430db Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 20 Apr 2017 11:37:44 -0400 Subject: [PATCH 1/7] created income statement-single year initial feature. --- bpfin/financials/financial_lib.py | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 bpfin/financials/financial_lib.py diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py new file mode 100644 index 0000000..8ae73b7 --- /dev/null +++ b/bpfin/financials/financial_lib.py @@ -0,0 +1,42 @@ +import datetime +import calendar +from bpfin.lib import other as lib + + +# calculate single year income statement given inputs from UI +def income_statement_single_year(income_input): + year = income_input['year'] + revenue = income_input['revenue'] + utility_expense = income_input['utility_expense'] + energy_opex = + +class Income_Statement(): + def __init__(self, FinancialDict): + + self.year = FinancialDict['year'][:] + self.IS_start = self.year[0] + self.IS_end = self.year[-1] + self.revenue = FinancialDict['revenue'] + self.utility_expense = FinancialDict['utility_expense'] + self.non_utility_expense = FinancialDict['non_utility_expense'] + self.energy_opex = {} # hist: income statement/read from energy bill, future: read from energy bill + self.other_utility = {} # hist: utility expense - energy opex, future: project with growth rate + self.net_non_energy_opex = {} # other_utility expense + non_utility_expense + self.total_opex = {} # energy_opex+net_non_energy_opex + self.noi = {} # net operating income, total revenue - total opex + self.energy_debt_service = {} + self.other_debt_service = {} + self.total_debt_service = {} + self.bill_saving = {} + self.energy_DSCR = {} + self.total_DSCR = {} + + +income_input_2016 = { + 'year': 2017, + 'revenue': 100000, + 'utility_expense': 60000, + 'non_utility_expense': 3000 +} + +bill_overview -- GitLab From 9e0dd3d3fee42702b0423e15e0a169ee8e26a60a Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 20 Apr 2017 12:15:53 -0400 Subject: [PATCH 2/7] finished single year financial statement calculation function. need to discuss I/O formatting. need to create test file. --- bpfin/financials/financial_lib.py | 107 ++++++++++++++++++++---------- 1 file changed, 71 insertions(+), 36 deletions(-) diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index 8ae73b7..86bd62e 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -1,42 +1,77 @@ -import datetime -import calendar -from bpfin.lib import other as lib +# import datetime +# import calendar +# from bpfin.lib import other as lib +# import pprint # calculate single year income statement given inputs from UI -def income_statement_single_year(income_input): +def income_statement_single_year(income_input, bill_overview): + '''calculate income statement for 1 year, with inputs from UI and energy bill overview + + Args: + income_input (dictionary): 4 elements of inputs + bill_overview (dictionary): contains annual energy charge for 4 utility types + Returns: + dictionary: income statement with standarized items + + Description Sample: + income_input = {'year': 2016, 'revenue': 100000, 'utility_expense': 60000,'non_utility_expense': 3000} + bill_overview = {'electricity': electricity_bill, 'oil': oil_bill, 'gas': gas_bill, 'water': water_bill} + ''' + year = income_input['year'] revenue = income_input['revenue'] utility_expense = income_input['utility_expense'] - energy_opex = - -class Income_Statement(): - def __init__(self, FinancialDict): - - self.year = FinancialDict['year'][:] - self.IS_start = self.year[0] - self.IS_end = self.year[-1] - self.revenue = FinancialDict['revenue'] - self.utility_expense = FinancialDict['utility_expense'] - self.non_utility_expense = FinancialDict['non_utility_expense'] - self.energy_opex = {} # hist: income statement/read from energy bill, future: read from energy bill - self.other_utility = {} # hist: utility expense - energy opex, future: project with growth rate - self.net_non_energy_opex = {} # other_utility expense + non_utility_expense - self.total_opex = {} # energy_opex+net_non_energy_opex - self.noi = {} # net operating income, total revenue - total opex - self.energy_debt_service = {} - self.other_debt_service = {} - self.total_debt_service = {} - self.bill_saving = {} - self.energy_DSCR = {} - self.total_DSCR = {} - - -income_input_2016 = { - 'year': 2017, - 'revenue': 100000, - 'utility_expense': 60000, - 'non_utility_expense': 3000 -} - -bill_overview + non_utility_expense = income_input['non_utility_expense'] + + electricity_opex = bill_overview['electricity'][year] + oil_opex = bill_overview['oil'][year] + gas_opex = bill_overview['gas'][year] + water_opex = bill_overview['water'][year] + energy_opex = electricity_opex + oil_opex + gas_opex + water_opex + + other_utility = utility_expense - energy_opex + net_non_energy_opex = other_utility + non_utility_expense + total_opex = energy_opex + net_non_energy_opex + noi = revenue - total_opex # net operating income + # energy_debt_service = + # other_debt_service = + # total_debt_service = + # bill_saving = + # energy_DSCR = + # total_DSCR = + + income_statement = { + 'year': year, + 'revenue': revenue, + 'utility_expense': utility_expense, + 'energy_opex': energy_opex, + 'electricity_opex': electricity_opex, + 'oil_opex': oil_opex, + 'gas_opex': gas_opex, + 'water_opex': water_opex, + 'other_utility': other_utility, + 'non_utility_expense': non_utility_expense, + 'net_non_energy_opex': net_non_energy_opex, + 'total_opex': total_opex, + 'noi': noi} + + # print(income_statement) + return income_statement + + +# income_input_2016 = { +# 'year': 2016, +# 'revenue': 100000, +# 'utility_expense': 60000, +# 'non_utility_expense': 3000 +# } + +# electricity_bill = {2015: 1000, 2016: 1200, 2017: 1500} +# oil_bill = {2015: 1010, 2016: 1210, 2017: 1510} +# gas_bill = {2015: 1020, 2016: 1220, 2017: 1520} +# water_bill = {2015: 0, 2016: 0, 2017: 0} + +# bill_overview = {'electricity': electricity_bill, 'oil': oil_bill, 'gas': gas_bill, 'water': water_bill} + +# income_statement_single_year(income_input_2016, bill_overview) -- GitLab From 0dc82a4d87da986b3ca9d559fa61c2ca11f1877a Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 20 Apr 2017 13:07:21 -0400 Subject: [PATCH 3/7] created oil price calculation in bill_month_norm_rough still need to improve test file --- bpfin/lib/other.py | 32 ++++++++++++------- bpfin/utilbills/bill_lib.py | 19 +++++++++++ bpfin/utilbills/bill_month_normalize_rough.py | 11 +++++-- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/bpfin/lib/other.py b/bpfin/lib/other.py index a2f081b..63cdf26 100644 --- a/bpfin/lib/other.py +++ b/bpfin/lib/other.py @@ -4,9 +4,10 @@ import bpfin.lib.math import statsmodels.api as sm import datetime import calendar -from dateutil.parser import * +# from dateutil.parser import * +import dateutil.parser import numpy as np -import pandas +import pandas as pd import xlrd from scipy.optimize import linprog import matplotlib @@ -351,16 +352,23 @@ def monthly_average(daily, matrix): return month_average -# oil price calculation -def cal_oil_price(oilcharge, oiluse): - if sum(oilcharge) == 0 or pd.isnull(sum(oilcharge)) == 1: - overall_price = 0 - else: - overall_price = sum(oilcharge) / sum(oiluse) - oil_price = [] - for i in range(1, 13): - oil_price.append(overall_price) - return oil_price +# # oil price calculation +# def cal_oil_price(oilcharge, oiluse): +# '''calculate oil price +# Args: +# oilcharge (list): list of charges, float values, from raw bill +# oiluse (list): list of usage, float values, from raw bill +# Return: +# list: 12 elements, average price for oil +# ''' +# if sum(oilcharge) == 0 or pd.isnull(sum(oilcharge)) == 1: +# overall_price = 0 +# else: +# overall_price = sum(oilcharge) / sum(oiluse) +# oil_price = [] +# for i in range(1, 13): +# oil_price.append(overall_price) +# return oil_price # list1=12 month values, target_terms = multiple years. Copy the values to all months diff --git a/bpfin/utilbills/bill_lib.py b/bpfin/utilbills/bill_lib.py index d872fbe..4310e28 100644 --- a/bpfin/utilbills/bill_lib.py +++ b/bpfin/utilbills/bill_lib.py @@ -174,3 +174,22 @@ def occupancy_final_list(occupancy_rate_list): for occ in occupancy_rate_list: occupancy_list.append(occ * 24) return occupancy_list + + +# oil price calculation +def cal_oil_price(oilcharge, oiluse): + '''calculate oil price + Args: + oilcharge (list): list of charges, float values, from raw bill + oiluse (list): list of usage, float values, from raw bill + Return: + list: 12 elements, average price for oil + ''' + if sum(oilcharge) == 0 or pd.isnull(sum(oilcharge)) == 1: + overall_price = 0 + else: + overall_price = sum(oilcharge) / sum(oiluse) + oil_price = [] + for i in range(1, 13): + oil_price.append(overall_price) + return oil_price diff --git a/bpfin/utilbills/bill_month_normalize_rough.py b/bpfin/utilbills/bill_month_normalize_rough.py index ccf9d9b..854c107 100644 --- a/bpfin/utilbills/bill_month_normalize_rough.py +++ b/bpfin/utilbills/bill_month_normalize_rough.py @@ -1,6 +1,7 @@ import datetime # import sys import bpfin.lib.other as lib +import bpfin.utilbills.bill_lib as bl def bill_month_normalize_rough(raw_bill): @@ -28,7 +29,7 @@ def bill_month_normalize_rough(raw_bill): bill_end = lib.convert_timestamp_date(raw_bill['date_to']) usage = raw_bill['usage'] charge = raw_bill['charge'] - # utility_type = raw_bill['utility_type'] + utility_type = raw_bill['utility_type'] if bill_start != []: month_matrix = lib.form_month_matrix(bill_start, bill_end) @@ -36,8 +37,12 @@ def bill_month_normalize_rough(raw_bill): daily_charge = lib.division(charge, lib.date_diff(bill_start, bill_end)) month_norm_usage = lib.monthly_average(daily_usage, month_matrix) - month_norm_charge = lib.monthly_average(daily_charge, month_matrix) - month_norm_price = lib.division(month_norm_charge, month_norm_usage) + if utility_type == 'oil': + month_norm_price = bl.cal_oil_price(charge, usage) + month_norm_charge = lib.product2list(month_norm_usage, month_norm_price) + else: + month_norm_charge = lib.monthly_average(daily_charge, month_matrix) + month_norm_price = lib.division(month_norm_charge, month_norm_usage) else: month_norm_usage = [0] * 12 month_norm_charge = [0] * 12 -- GitLab From d2b7b9404f5a249649d1a332ce8b7b0332f563c3 Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 20 Apr 2017 15:11:29 -0400 Subject: [PATCH 4/7] clean leftover from merging --- bpfin/utilbills/bill_lib.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bpfin/utilbills/bill_lib.py b/bpfin/utilbills/bill_lib.py index efc5cd3..9bb00d3 100644 --- a/bpfin/utilbills/bill_lib.py +++ b/bpfin/utilbills/bill_lib.py @@ -201,7 +201,6 @@ def occupancy_final_list(occupancy_rate_list): return occupancy_list -<<<<<<< HEAD # oil price calculation def cal_oil_price(oilcharge, oiluse): '''calculate oil price @@ -219,7 +218,7 @@ def cal_oil_price(oilcharge, oiluse): for i in range(1, 13): oil_price.append(overall_price) return oil_price -======= + def annualizing_projection(dates, values): """Return annualized values of monthly projections. Args: @@ -247,4 +246,3 @@ def annualizing_projection(dates, values): final_dict[year] = sum(value) return final_dict ->>>>>>> 0a00c294e87bbc0b00bd793e63c4dacfbafd20c2 -- GitLab From 73d620fc28d1c1a3e5e105862252d3c76a5bc959 Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 20 Apr 2017 15:13:06 -0400 Subject: [PATCH 5/7] just a space --- bpfin/utilbills/bill_lib.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bpfin/utilbills/bill_lib.py b/bpfin/utilbills/bill_lib.py index 9bb00d3..3f2536a 100644 --- a/bpfin/utilbills/bill_lib.py +++ b/bpfin/utilbills/bill_lib.py @@ -219,6 +219,7 @@ def cal_oil_price(oilcharge, oiluse): oil_price.append(overall_price) return oil_price + def annualizing_projection(dates, values): """Return annualized values of monthly projections. Args: -- GitLab From 6fdf166031f20ec3f46933d4fe1544fcd60fedb2 Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 20 Apr 2017 15:53:26 -0400 Subject: [PATCH 6/7] wrote an sample function calls for bill_overview for individual utility type --- bpfin/utilbills/data_generation.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/bpfin/utilbills/data_generation.py b/bpfin/utilbills/data_generation.py index e69de29..a4acc79 100644 --- a/bpfin/utilbills/data_generation.py +++ b/bpfin/utilbills/data_generation.py @@ -0,0 +1,13 @@ +from bpfin.utilbills.bill_month_normalize_rough import bill_month_normalize_rough +from bpfin.utilbills.bill_prior_proj_rough import bill_prior_proj_rough +from bpfin.utilbills import bill_lib as bl +from bpfin.tests.testdata import sample_data as db + + +raw_bill = db.raw_bill +norm_bill = bill_month_normalize_rough(raw_bill) +prior_bill_electricity = bill_prior_proj_rough(norm_bill, raw_bill, db.analysis_date, db.inflation_coeff_dict) +annual_bill_electricity = bl.annualizing_projection(prior_bill_electricity['date_to'], prior_bill_electricity['charge']) + +print(annual_bill_electricity) + -- GitLab From 7da217e55cec297162429fc12c47b7a11e487a54 Mon Sep 17 00:00:00 2001 From: chenzheng06 Date: Thu, 20 Apr 2017 16:18:58 -0400 Subject: [PATCH 7/7] created test_income_statement_single_year created sample data for the test created a real annual bill for electricity sample data --- bpfin/financials/financial_lib.py | 13 +++++-- .../test_financials/test_financial_lib.py | 11 ++++++ bpfin/tests/testdata/sample_data.py | 38 +++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 bpfin/tests/test_financials/test_financial_lib.py diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py index 86bd62e..3b213e2 100644 --- a/bpfin/financials/financial_lib.py +++ b/bpfin/financials/financial_lib.py @@ -25,8 +25,8 @@ def income_statement_single_year(income_input, bill_overview): non_utility_expense = income_input['non_utility_expense'] electricity_opex = bill_overview['electricity'][year] - oil_opex = bill_overview['oil'][year] gas_opex = bill_overview['gas'][year] + oil_opex = bill_overview['oil'][year] water_opex = bill_overview['water'][year] energy_opex = electricity_opex + oil_opex + gas_opex + water_opex @@ -47,8 +47,8 @@ def income_statement_single_year(income_input, bill_overview): 'utility_expense': utility_expense, 'energy_opex': energy_opex, 'electricity_opex': electricity_opex, - 'oil_opex': oil_opex, 'gas_opex': gas_opex, + 'oil_opex': oil_opex, 'water_opex': water_opex, 'other_utility': other_utility, 'non_utility_expense': non_utility_expense, @@ -67,7 +67,14 @@ def income_statement_single_year(income_input, bill_overview): # 'non_utility_expense': 3000 # } -# electricity_bill = {2015: 1000, 2016: 1200, 2017: 1500} +# electricity_bill = { +# 2012: 32220.590596217822, 2013: 32782.518348206999, 2014: 33293.100530249467, 2015: 33546.761580451312, +# 2016: 33844.501703633454, 2017: 34523.27291517199, 2018: 35384.966283060414, 2019: 36251.490761516034, +# 2020: 37100.197369238413, 2021: 37887.082013632862, 2022: 38603.765037606507, 2023: 39307.925216552088, +# 2024: 40028.077679374117, 2025: 40772.42926238777, 2026: 41575.666985412594, 2027: 42439.918590730398, +# 2028: 43325.235463581725, 2029: 44211.298795796341, 2030: 45097.667796776521, 2031: 45986.665329650692, +# 2032: 46886.305428683903, 2033: 47806.578908870637, 2034: 48751.551094031129, 2035: 49722.255450564422, +# 2036: 50718.832984188753} # oil_bill = {2015: 1010, 2016: 1210, 2017: 1510} # gas_bill = {2015: 1020, 2016: 1220, 2017: 1520} # water_bill = {2015: 0, 2016: 0, 2017: 0} diff --git a/bpfin/tests/test_financials/test_financial_lib.py b/bpfin/tests/test_financials/test_financial_lib.py new file mode 100644 index 0000000..6bf20bd --- /dev/null +++ b/bpfin/tests/test_financials/test_financial_lib.py @@ -0,0 +1,11 @@ +import datetime +from bpfin.financials import financial_lib as fl +from bpfin.tests.testdata import sample_data as db + + +def test_income_statement_single_year(): + income_input = db.income_input_2016 + bill_overview = db.bill_overview + output_dict = db.income_statement_2016 + result_dict = fl.income_statement_single_year(income_input, bill_overview) + assert output_dict == result_dict diff --git a/bpfin/tests/testdata/sample_data.py b/bpfin/tests/testdata/sample_data.py index 1619199..92f6081 100644 --- a/bpfin/tests/testdata/sample_data.py +++ b/bpfin/tests/testdata/sample_data.py @@ -837,6 +837,44 @@ prior_proj_rough_price = [ 42131.00318614885, 40054.83089682108, 40079.848368848034, 40883.798098440246, 40432.470041231565, 40779.34931771414, 41139.21219179594, 40321.43463472525, 43237.085994998866, 48437.35375945405, 51641.29962190506, 48278.23252154697] +annual_bill_electricity ={ + 2012: 32220.590596217822, 2013: 32782.518348206999, 2014: 33293.100530249467, 2015: 33546.761580451312, + 2016: 33844.501703633454, 2017: 34523.27291517199, 2018: 35384.966283060414, 2019: 36251.490761516034, + 2020: 37100.197369238413, 2021: 37887.082013632862, 2022: 38603.765037606507, 2023: 39307.925216552088, + 2024: 40028.077679374117, 2025: 40772.42926238777, 2026: 41575.666985412594, 2027: 42439.918590730398, + 2028: 43325.235463581725, 2029: 44211.298795796341, 2030: 45097.667796776521, 2031: 45986.665329650692, + 2032: 46886.305428683903, 2033: 47806.578908870637, 2034: 48751.551094031129, 2035: 49722.255450564422, + 2036: 50718.832984188753} +annual_bill_gas = {2015: 1020, 2016: 1220, 2017: 1520} +annual_bill_oil = {2015: 1010, 2016: 1210, 2017: 1510} +annual_bill_water = {2015: 0, 2016: 0, 2017: 0} +bill_overview = { + 'electricity': annual_bill_electricity, + 'gas': annual_bill_gas, + 'oil': annual_bill_oil, + 'water': annual_bill_water} + +income_input_2016 = { + 'year': 2016, + 'revenue': 100000, + 'utility_expense': 60000, + 'non_utility_expense': 3000} + +income_statement_2016 = { + 'year': 2016, + 'revenue': 100000, + 'utility_expense': 60000, + 'energy_opex': 36274.501703633454, + 'electricity_opex': 33844.501703633454, + 'gas_opex': 1220, + 'oil_opex': 1210, + 'water_opex': 0, + 'other_utility': 23725.498296366546, + 'non_utility_expense': 3000, + 'net_non_energy_opex': 26725.498296366546, + 'total_opex': 63000.0, + 'noi': 37000.0} + inflation_coeff_dict = { datetime.date(1981, 1, 31): 0.3381208260704529, -- GitLab