diff --git a/bpfin/financials/financial_lib.py b/bpfin/financials/financial_lib.py new file mode 100644 index 0000000000000000000000000000000000000000..3b213e29f56c6bda8ecf9a9d3bbd3a54fb0e2dc9 --- /dev/null +++ b/bpfin/financials/financial_lib.py @@ -0,0 +1,84 @@ +# 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, 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'] + non_utility_expense = income_input['non_utility_expense'] + + electricity_opex = bill_overview['electricity'][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 + + 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, + 'gas_opex': gas_opex, + 'oil_opex': oil_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 = { +# 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} + +# bill_overview = {'electricity': electricity_bill, 'oil': oil_bill, 'gas': gas_bill, 'water': water_bill} + +# income_statement_single_year(income_input_2016, bill_overview) diff --git a/bpfin/lib/other.py b/bpfin/lib/other.py index a2f081b4ff82b909e8194bcecaf9e10208a8d5eb..63cdf26b48fc8f08cfaf6c89cece526cfd7845ea 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/tests/test_financials/test_financial_lib.py b/bpfin/tests/test_financials/test_financial_lib.py new file mode 100644 index 0000000000000000000000000000000000000000..6bf20bdf83cd71fbb92ee86b5b43c1b694df19a3 --- /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 16191994832ba2e6f9627258c64c5f7e96809f6a..92f60816db9e745b5ace2e448f73e6818fcd1803 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, diff --git a/bpfin/utilbills/bill_lib.py b/bpfin/utilbills/bill_lib.py index c452d273e76c22f71ba3cbaff00785c87ae06346..3f2536a8f7131fdcc06eac2f84818fe63a0c867f 100644 --- a/bpfin/utilbills/bill_lib.py +++ b/bpfin/utilbills/bill_lib.py @@ -201,6 +201,25 @@ def occupancy_final_list(occupancy_rate_list): 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 + + def annualizing_projection(dates, values): """Return annualized values of monthly projections. Args: diff --git a/bpfin/utilbills/bill_month_normalize_rough.py b/bpfin/utilbills/bill_month_normalize_rough.py index 2951dedf3de545477591f9eda4ad60793bfd3036..23909a9eeac2beafaa1447085ee05be8e26797ee 100644 --- a/bpfin/utilbills/bill_month_normalize_rough.py +++ b/bpfin/utilbills/bill_month_normalize_rough.py @@ -1,5 +1,6 @@ import datetime import bpfin.lib.other as lib +import bpfin.utilbills.bill_lib as bl def bill_month_normalize_rough(raw_bill): @@ -27,17 +28,21 @@ 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'] - # !!!! we will need to update oil calculation! don't forget!!!!! + utility_type = raw_bill['utility_type'] + # !!!! we will need to update oil calculation test file if bill_start != []: month_matrix = lib.form_month_matrix(bill_start, bill_end) daily_usage = lib.division(usage, lib.date_diff(bill_start, bill_end)) 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 diff --git a/bpfin/utilbills/data_generation.py b/bpfin/utilbills/data_generation.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a4acc79c932b4c8467d6443344af5f894591fee8 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) +