def _barwert(zins, daten, zahlungen, basisdatum, enddatum, startzahlung, endzahlung): if not len(daten) == len(zahlungen): return "Unterschiedliche Anzahl an Daten und Zahlungen!" if zins < -1.0: return "Der Zins muss >= -1 sein; " + str(zins) + " ist ungültig." if basisdatum > enddatum: return "Das Enddatum darf nicht vor dem Startdatum liegen!" discount = (1.0 / (1.0+zins))**(1.0/365.0) sum = 0 for i, d in enumerate(daten): if isinstance(d, float) and isinstance(zahlungen[i], float) and not (d > enddatum or d < basisdatum): sum += zahlungen[i] * discount**(d-basisdatum) sum += startzahlung if endzahlung > 0: sum += endzahlung * discount**(enddatum-basisdatum) return sum def barwert(zins, daten, zahlungen, basisdatum, enddatum, startzahlung, endzahlung): if basisdatum > enddatum: return "Das Enddatum darf nicht vor dem Startdatum liegen!" if zins < -1.0: return "Der Zins muss >= -1 sein; " + str(zins) + " ist ungültig." daten = [d[0] for d in daten] zahlungen = [z[0] for z in zahlungen] return _barwert(zins, daten, zahlungen, basisdatum, enddatum, startzahlung, endzahlung) def endwert(zins, daten, zahlungen, basisdatum, enddatum, startzahlung, endzahlung): if basisdatum > enddatum: return "Das Enddatum darf nicht vor dem Startdatum liegen!" if zins < -1.0: return "Der Zins muss >= -1 sein; " + str(zins) + " ist ungültig." daten = [d[0] for d in daten] zahlungen = [z[0] for z in zahlungen] q = (1.0+zins)**(1.0/365.0) return q**(enddatum-basisdatum) * _barwert(zins, daten, zahlungen, basisdatum, enddatum, startzahlung, endzahlung) def zinsfuss(daten, zahlungen, basisdatum, enddatum, startzahlung, endzahlung): basisdatum = basisdatum daten = [d[0] for d in daten] zahlungen = [z[0] for z in zahlungen] pos = False neg = False for z in zahlungen: if z > 0: pos = True if z < 0: neg = True if pos and neg: break if not (pos and neg): return "Es müssen positive und negative Zahlungen enthalten sein!" i0 = 0.05 i1 = 0.06 b0 = _barwert(i0, daten, zahlungen, basisdatum, enddatum, startzahlung, endzahlung) if not isinstance(b0, float): return b0 if b0 < 0: i1 = 0.04 maxiter = 10000 epsilon = 0.0001 i = 0 while abs(i0-i1) > epsilon and i < maxiter: b1 = _barwert(i1, daten, zahlungen, basisdatum, enddatum, startzahlung, endzahlung) if b0 == b1: return 0 if not isinstance(b1, float): return b1 i2 = i0 - b0 / (b1-b0) * (i1-i0) if i2 < -1.0: return -1 #str((-1, i0, i1, i2, b0, b1)) if i2 > 1000000: if b0 < 0: return -1 return "∞" b0 = b1 i0 = i1 i1 = i2 i += 1 if i == maxiter: return "∞" return i1 from itertools.chain import from_iterable as flat def sjoin( datarange , joinstring = "" ): """ Calcfunktion zum verketten ganzer Zellbereiche, mit Bereichsadressangabe und mit der optionalen Möglichkeit eines Verbindungszeichens oder -Texts""" if isinstance (datarange, tuple): # cellranges always *nested* tuples return joinstring.join("%s" % elem for elem in flat(datarange) if elem) else : return datarange # a single cellvalue