Created
March 6, 2015 01:43
-
-
Save brianbruggeman/797f18fecf021b7414d9 to your computer and use it in GitHub Desktop.
solar energy roi
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
""" | |
Calculates return on investment over time. | |
Usage: | |
calc_roi [options] | |
Options: | |
-h, --help This message | |
-u, --unit-cost <uc> Cost per panel (USD) [Default: 750] | |
-i, --initial <ic> Initial investment cost (USD) [Default: 9000] | |
-i, --units <units> Initial units purchased [Default: 15] | |
-d, --degradation <deg> Efficiency degradation per year % [Default: 0.007] | |
-y, --years <years> Years to calculate [Default: 25] | |
-r, --return <return> Annual return per unit (USD) [Default: 90] | |
-p, --purchase Purchase new units with profit [Default: True] | |
-s, --sunset <year> When to sunset a panel [Default: 100] | |
-m, --margin <margin> Percentage of revenue kept [Default: 80%] | |
-c, --cease <year> Year to cease purchasing new units [Default: 100] | |
""" | |
class Panel(object): | |
""" | |
Solar Panel used for calculating roi per unit | |
""" | |
@property | |
def break_even(self): | |
""" Year when this panel will break even """ | |
investment_return = 0 | |
for year in xrange(100): | |
coeff = 1.0 - (self.degradation) | |
margin = self.profit_margin | |
revenue = self.annual_revenue | |
investment_return += coeff * revenue * margin | |
if investment_return >= self.investment: | |
return year | |
@property | |
def age(self): | |
""" age of panel """ | |
return self.start + self.year | |
@property | |
def roi(self): | |
""" return on investment (%) """ | |
return self.investment / self.generated_revenue | |
@property | |
def degraded_revenue(self): | |
""" degradation of panel in revenue """ | |
value = 0 | |
if self.age < self.sunset: | |
coefficient = (1.0 - self.degradation * self.age) | |
value = coefficient * self.annual_revenue * self.profit_margin | |
return value | |
def __init__(self, cost=750, year=0, revenue=2250 / 25, degradation=0.007, margin=0.8, sunset=100): | |
""" Creates a unit which can be updated """ | |
self.investment = cost | |
self.start = year | |
self.year = 0 | |
self.profit_margin = 0.8 | |
self.degradation = degradation | |
self.annual_revenue = revenue | |
self.generated_revenue = 0 | |
self.sunset = sunset | |
def update(self): | |
""" Increments unit for this year """ | |
self.generated_revenue += self.degraded_revenue | |
self.year += 1 | |
def __repr__(self): | |
""" Panel at any point in time """ | |
args = { | |
"years": self.years, | |
"capital": self.investment, | |
"return": self.generated_revenue, | |
"roi": self.roi, | |
} | |
string = "<Panel age:{years}, capital:{investment}, "\ | |
"return:{revenue}, roi:{roi}>" | |
return string.format(args) | |
def calculate(args): | |
unit_cost = args.get("--unit-cost") | |
initial_cost = args.get("--initial") | |
units_purchased = args.get("--units") | |
degradation = args.get("--degradation") | |
years = args.get("--years") | |
annual_return = args.get("--return") | |
purchase_new_units = args.get("--purchase", False) | |
sunset = args.get("--sunset") | |
margin = args.get("--margin") | |
cease = args.get("--cease") | |
cpu = initial_cost / units_purchased | |
units = [Panel(cost=cpu, | |
revenue=annual_return, | |
degradation=degradation, | |
margin=margin, | |
sunset=sunset) | |
for unit in xrange(units_purchased)] | |
titles = ["year", "units", "monthly", "roi", "investment", "return"] | |
print "{0:>4}: {1:>10} | {2:>16} | {3:<15} | ({4:>19}/{5:>19})".format(*titles) | |
cumulative = 0 | |
for year in xrange(years): | |
profit = sum(u.degraded_revenue for u in units) | |
cumulative += profit | |
if purchase_new_units and year < cease: | |
while cumulative > unit_cost: | |
panel = Panel(cost=unit_cost, | |
year=year, | |
revenue=annual_return, | |
degradation=degradation, | |
margin=margin, | |
sunset=sunset) | |
units.append(panel) | |
cumulative = cumulative - unit_cost | |
data = { | |
"units": sum(1 for u in units), | |
"year": year, | |
"cost": sum(u.investment for u in units), | |
"profit": sum(u.generated_revenue for u in units), | |
"monthly": sum(u.degraded_revenue/12.0 for u in units), | |
} | |
data["roi"] = data["profit"] / data["cost"] | |
print("{year:>4}: {units:>10} | ${monthly:>15,} | {roi:<15} | (${cost:>18,}/${profit:>18,})".format(**data)) | |
for unit in units: | |
unit.update() | |
if __name__ == "__main__": | |
import docopt | |
args = docopt.docopt(__doc__) | |
for k, v in args.iteritems(): | |
try: | |
if "." not in v: | |
v = int(v) | |
args[k] = v | |
else: | |
v = float(v) | |
args[k] = v | |
except: | |
pass | |
calculate(args) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment