Browse Source

Works nicely. Some magic numbers should be removed

master
Maximilian Stiefel 3 years ago
parent
commit
2345372f07
  1. 3
      ecar.json
  2. 122
      ecar.py

3
ecar.json

@ -1,4 +1,5 @@
{
"currency": "CHF",
"kwh_price_home": 0.2,
"kwh_price_commercial": 0.5,
"petrol_litre_price": 1.75,
@ -10,7 +11,7 @@
"taxes": 0,
"insurance": 354,
"kwh_per_kilometer": 0.16,
"maintenance": 200,
"maintenance": 100,
"charging_behaviour": {
"percent_free_charges": 90,
"percent_home_charges": 5,

122
ecar.py

@ -17,7 +17,9 @@ class c_settings_extractor:
kilometer_price_ecar = ( settings["ecar"]["charging_behaviour"]["percent_home_charges"] * settings["kwh_price_home"]
+ settings["ecar"]["charging_behaviour"]["percent_commercial_charges"] * settings["kwh_price_commercial"]) / 100.0
self.driving = np.array([kilometer_price_ecar * settings["kilometers_per_year"], kilometer_price_ccar * settings["kilometers_per_year"]])
self.maintenance = np.array([settings["ecar"]["maintenance"], settings["ecar"]["maintenance"]])
self.maintenance = np.array([settings["ecar"]["maintenance"], settings["ccar"]["maintenance"]])
self.kilometers = settings["kilometers_per_year"]
self.currency = settings["currency"]
def get_labels(self):
return self.labels
def get_purchase(self):
@ -30,7 +32,11 @@ class c_settings_extractor:
return self.driving
def get_maintenance(self):
return self.maintenance
def get_kilometers(self):
return self.kilometers
def get_currency(self):
return self.currency
class c_ecar_comparator:
def __init__(self, fname):
self.settings_extractor = c_settings_extractor(fname)
@ -50,24 +56,66 @@ class c_ecar_comparator:
increment = self.calculate_costs_a_year() / months_a_year
months = 0
while total_costs[0] > total_costs[1]:
total_costs += increment
total_costs = total_costs + increment
months += 1
return [months/months_a_year, months%months_a_year] # years, months
kilometers = self.settings_extractor.get_kilometers() * months / months_a_year
return [months//months_a_year, months%months_a_year, kilometers] # years, months
def calculate_amortization_point(self):
y = 0
m = 1
months_a_year = 12.0
costs_a_month = self.calculate_costs(y, m)
savings_a_month = costs_a_month[1]-costs_a_month[0]
months_till_amortized = self.settings_extractor.get_purchase()[0] / savings_a_month
kilometers = months_till_amortized * self.settings_extractor.get_kilometers() / months_a_year
months_till_amortized = np.ceil(months_till_amortized)
return months_till_amortized//months_a_year, months_till_amortized%months_a_year, round(kilometers, ndigits=2)
def main():
parser = argparse.ArgumentParser(description='This script allows to calculate if an electric car makes sense financially for you')
parser.add_argument('-a','--settings', help='Settings file', required=True, metavar=('FILENAME'))
parser.add_argument('-b','--break_even', help='Calculate the break even point. (When does the EV become cheaper)', action='store_true')
parser.add_argument('-c','--savings_per_year', help='Calculate savings per year', action='store_true')
parser.add_argument('-d','--savings_per_month', help='Calculate savings per month', action='store_true')
parser.add_argument('-e','--plot', help='Visualize costs over one or multiple years', type=int, metavar=('YEARS'))
parser = argparse.ArgumentParser(description='This script allows to calculate if an electric car makes sense financially for you.')
parser.add_argument('-a','--settings', help='Settings file.', required=True, metavar=('FILENAME'))
parser.add_argument('-b','--break_even', help='Calculate the break even point (when the EV becomes cheaper).', action='store_true')
parser.add_argument('-c','--amortization', help='Calculate the point in time when the electric vehicle is amortized completely by savings.', action='store_true')
parser.add_argument('-d','--savings_per_month', help='Calculate savings per month.', action='store_true')
parser.add_argument('-e','--savings_per_year', help='Calculate savings per year.', action='store_true')
parser.add_argument('-f','--savings_per_kilometer', help='Calculate savings per 100 kilometers (only driving, no maintenance, taxes or insurance).', action='store_true')
parser.add_argument('-g','--plot', help='Visualize costs over one or multiple years.', type=int, metavar=('YEARS'))
args = parser.parse_args()
if not args.break_even and not args.savings_per_year and not args.savings_per_month and not args.plot:
sys.exit("Please choose one or multiple options")
comparator = c_ecar_comparator(args.settings)
extractor = c_settings_extractor(args.settings)
if args.plot:
be_years = None
be_months = None
be_kilometers = None
if args.break_even:
be_years, be_months, be_kilometers = comparator.calculate_break_even()
print("Break even after {} years and {} months.".format(be_years, be_months))
if args.savings_per_month:
years = 0
months = 1
savings = comparator.calculate_costs(years, months)
print("Savings per month based on yearly spending: {}.".format(round(savings[1]-savings[0], ndigits=2)))
if args.savings_per_year:
years = 1
months = 0
savings = comparator.calculate_costs(years, months)
print("Savings per year: {}.".format(round(savings[1]-savings[0], ndigits=2)))
if args.savings_per_kilometer:
hundred_km = 100.0
driving = hundred_km * extractor.get_driving() / extractor.get_kilometers()
labels = extractor.get_labels()
print("Costs driving 100 km in the {}: {}. Costs driving 100 km in the {}: {}.".format(labels[0], round(driving[0], ndigits=2), labels[1], round(driving[1]), ndigits=2))
am_years = None
am_months = None
am_kilometers = None
if args.amortization:
am_years, am_months, am_kilometers = comparator.calculate_amortization_point()
print("The electric vehicle will be amortized by savings after {} years, {} months or exactely at {} kilometres.".format(am_years, am_months, am_kilometers))
if args.plot != None:
width = 0.3
plt_colors = ["#8ecae6", "#219ebc", "#023047", "#ffb703", "#fb8500"];
color_ind = 0
labels = extractor.get_labels()
purchase = extractor.get_purchase()
taxes = extractor.get_taxes()
@ -75,29 +123,39 @@ def main():
driving = extractor.get_driving()
maintenance = extractor.get_maintenance()
fig, ax = plt.subplots()
ax.bar(labels, purchase, width, label = "Price", color = "gray")
ax.bar(labels, purchase, width, label = "Price", color = plt_colors[0])
current_y = extractor.get_purchase()
y = 0
for i in range(args.plot):
ax.bar(labels, taxes, width, bottom = current_y, label = "Taxes".format(y), color = "darkgreen")
current_y = current_y + taxes
ax.bar(labels, insurance, width, bottom = current_y, label = "Insurance".format(y), color = "royalblue")
current_y = current_y + insurance
ax.bar(labels, driving, width, bottom = current_y, label = "Driving".format(y), color = "midnightblue")
current_y = current_y + driving
ax.bar(labels, maintenance, width, bottom = current_y, label = "Maintenance".format(y), color = "lavender")
current_y = current_y + maintenance
y += 1
ecar_top = current_y[0]
#ax.plot(np.linspace(-0.2, 1.2, 10), [ecar_top]*10, "--", color = "firebrick", label = "Break even")
#ax.text(0.3, ecar_top * 0.95, "Break even: {} years, {} kilometers".format(y, y*settings["kilometers_per_year"]))
ax.set_ylabel("CHF")
ax.set_title("Comparision of economics electric vs. combustion car")
ax.legend(["Price", "Taxes", "Insurance", "Driving", "Maintenance"])
ax.grid(axis = "y")
#print("Break even after {} years and {} kilometers. {}".format(y, y*settings["kilometers_per_year"], current_y[0]-current_y[1]))
plt.show()
for i in range(args.plot):
ax.bar(labels, taxes, width, bottom = current_y, label = "Taxes".format(y), color = plt_colors[1])
current_y = current_y + taxes
ax.bar(labels, insurance, width, bottom = current_y, label = "Insurance".format(y), color = plt_colors[2])
current_y = current_y + insurance
ax.bar(labels, driving, width, bottom = current_y, label = "Driving".format(y), color = plt_colors[3])
current_y = current_y + driving
ax.bar(labels, maintenance, width, bottom = current_y, label = "Maintenance".format(y), color = plt_colors[4])
current_y = current_y + maintenance
y += 1
labels = ["Purchase", "Taxes", "Insurance", "Driving", "Maintenance"]
if args.break_even:
months_a_year = 12.0
be_money = (be_years + be_months/months_a_year) * comparator.calculate_costs_a_year()
be_money = be_money[1] + extractor.get_purchase()
ax.plot(np.linspace(-0.2, 1.2, 10), [be_money[1]]*10, "--", color = plt_colors[2], label = "Break even")
ax.text(0.3, be_money[1] + 100, "Break even: {} years, {} months, {} kilometers".format(be_years, be_months, be_kilometers))
labels = ["Break even"] + labels
if args.amortization:
months_a_year = 12.0
am_money = (am_years + am_months/months_a_year) * comparator.calculate_costs_a_year()
am_money = am_money[1] + extractor.get_purchase()
ax.plot(np.linspace(-0.2, 1.2, 10), [am_money[1]]*10, "--", color = plt_colors[2], label = "Amortization")
ax.text(0.3, am_money[1] + 100, "Amortization: {} years, {} months, {} kilometers".format(am_years, am_months, am_kilometers))
labels = ["Amortization"] + labels
ax.set_ylabel(extractor.get_currency())
ax.set_title("Comparision of economics electric vs. combustion car")
ax.legend(labels)
ax.grid(axis = "y")
plt.show()
if __name__ == "__main__":
main()

Loading…
Cancel
Save