Skip to content

Instantly share code, notes, and snippets.

@brianbruggeman
Created March 6, 2015 01:43
Show Gist options
  • Save brianbruggeman/797f18fecf021b7414d9 to your computer and use it in GitHub Desktop.
Save brianbruggeman/797f18fecf021b7414d9 to your computer and use it in GitHub Desktop.

Revisions

  1. brianbruggeman created this gist Mar 6, 2015.
    152 changes: 152 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,152 @@
    #!/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)