Exemple #1
0
    def _calc(self):
        if self.portfolio.value >= (1 + self.up_threshold) * self.get_required_portfolio():
            new_amount = pmt(self.get_rate(), self.get_life_expectancy(), self.portfolio.value)
            new_rate = new_amount / self.portfolio.value
            self.current_rate += (new_rate - self.current_rate) * self.upward_rate_adjustment
            self.current_rate = min(self.current_rate, self.ceiling_rate)
        if self.portfolio.value < (1 + self.down_threshold) * self.get_required_portfolio():
            new_amount = pmt(self.get_rate(), self.get_life_expectancy(), self.portfolio.value)
            new_rate = new_amount / self.portfolio.value
            self.current_rate -= (self.current_rate - new_rate) * self.downward_rate_adjustment
            self.current_rate = max(self.current_rate, self.floor_rate)

        amount = self.current_rate * self.portfolio.value
        self.current_age += 1
        return amount
    def harvest(self):
        amount = yield
        while True:
            amount_left = amount

            if self.portfolio.bonds_pct > self.target_bonds:
                bonds_excess = (self.portfolio.bonds_pct - self.target_bonds) * self.portfolio.value
                bonds_excess = round(bonds_excess)
                bonds_to_sell = min(amount, bonds_excess)
                self.portfolio.sell_bonds(bonds_to_sell)
                amount_left -= bonds_to_sell
            else:
                bonds_deficit = -(self.portfolio.bonds_pct - self.target_bonds) * self.portfolio.value
                bonds_deficit = round(bonds_deficit)
                self.portfolio.sell_stocks(bonds_deficit)
                self.portfolio.buy_bonds(bonds_deficit)

            bonds_to_sell = amount_left * self.target_bonds
            stocks_to_sell = amount_left - bonds_to_sell
            self.portfolio.sell_bonds(bonds_to_sell)
            self.portfolio.sell_stocks(stocks_to_sell)

            pmt_amount = pmt(self.discount_rate, self.final_age - self.current_age, self.portfolio.value)
            if amount < pmt_amount and amount >= self.initial_withdrawal:
                harvest = pmt_amount - amount
                self.portfolio.buy_bonds(harvest)

            amount = yield self.portfolio.empty_cash()
    def harvest(self):
        amount = yield
        while True:
            amount_left = amount

            if self.portfolio.bonds_pct > self.target_bonds:
                bonds_excess = (self.portfolio.bonds_pct -
                                self.target_bonds) * self.portfolio.value
                bonds_excess = round(bonds_excess)
                bonds_to_sell = min(amount, bonds_excess)
                self.portfolio.sell_bonds(bonds_to_sell)
                amount_left -= bonds_to_sell
            else:
                bonds_deficit = -(self.portfolio.bonds_pct -
                                  self.target_bonds) * self.portfolio.value
                bonds_deficit = round(bonds_deficit)
                self.portfolio.sell_stocks(bonds_deficit)
                self.portfolio.buy_bonds(bonds_deficit)

            bonds_to_sell = amount_left * self.target_bonds
            stocks_to_sell = amount_left - bonds_to_sell
            self.portfolio.sell_bonds(bonds_to_sell)
            self.portfolio.sell_stocks(stocks_to_sell)

            pmt_amount = pmt(self.discount_rate,
                             self.final_age - self.current_age,
                             self.portfolio.value)
            if amount < pmt_amount and amount >= self.initial_withdrawal:
                harvest = pmt_amount - amount
                self.portfolio.buy_bonds(harvest)

            amount = yield self.portfolio.empty_cash()
Exemple #4
0
 def _calc(self):
     rate = (self.portfolio.stocks_pct * self.stock_growth_rate
             + self.portfolio.bonds_pct * self.bond_growth_rate)
     amt = pmt(rate, self.years_left, self.portfolio.value)
     # max out at 20% of the current portfolio...this allows it to run
     # "indefinitely"
     return min(amt, self.portfolio.value / 5)
 def _calc(self):
     amount = pmt(self.rate, self.final_age - self.current_age, self.portfolio.value)
     desired_pmt = self.desired_payment * self.cumulative_inflation
     desired_value = pv(float(self.rate), self.final_age - self.current_age, float(-desired_pmt), when='begin')
     desired_value = Decimal(desired_value)
     tilt = (self.portfolio.value / desired_value) ** self.tilt
     return amount * tilt
Exemple #6
0
    def _calc(self):
        # Siegel & Waring suggest the discount rate should be
        # "TIPS interest rate (present-value-weighted average interest rate across the TIPS
        # ladder)" at the start of each year.
        # Currently, we don't support changing the discount_rate every year and use a constant rate
        rate = self.discount_rate

        # Siegel & Waring suggest using the average of 120 (the maximum known human life span) and
        # life expectancy based on current age according to the Social Security tables.
        years_left = average([ARVA.MAX_AGE, get_life_expectancy(self.current_age)]) 
        return pmt(rate, years_left, self.portfolio.value)
Exemple #7
0
 def _calc(self):
     # shortcut if the portfolio is 0...some of the math
     # below doesn't like 0s.
     if self.portfolio.value == 0:
         return Decimal(0)
     amount = pmt(self.rate, self.final_age - self.current_age, self.portfolio.value)
     desired_pmt = self.desired_payment * self.cumulative_inflation
     desired_value = pv(float(self.rate), self.final_age - self.current_age, float(-desired_pmt), when='begin')
     desired_value = Decimal(desired_value)
     tilt = (self.portfolio.value / desired_value) ** self.tilt
     return amount * tilt
Exemple #8
0
    def _calc(self):
        p_v = pmt(self.discount_rate, self.final_age - self.current_age, self.portfolio.value)
        if p_v < self.current_withdrawal:
            self.retrenchments.append((self.current_age, self.current_withdrawal, p_v))

        if self.only_down:
            if p_v < self.current_withdrawal: self.current_withdrawal = p_v
        else:
            self.current_withdrawal = p_v

        return self.current_withdrawal
    def _calc(self):
        if self.portfolio.value >= (
                1 + self.up_threshold) * self.get_required_portfolio():
            new_amount = pmt(self.get_rate(), self.get_life_expectancy(),
                             self.portfolio.value)
            new_rate = new_amount / self.portfolio.value
            self.current_rate += (
                new_rate - self.current_rate) * self.upward_rate_adjustment
            self.current_rate = min(self.current_rate, self.ceiling_rate)
        if self.portfolio.value < (
                1 + self.down_threshold) * self.get_required_portfolio():
            new_amount = pmt(self.get_rate(), self.get_life_expectancy(),
                             self.portfolio.value)
            new_rate = new_amount / self.portfolio.value
            self.current_rate -= (self.current_rate -
                                  new_rate) * self.downward_rate_adjustment
            self.current_rate = max(self.current_rate, self.floor_rate)

        amount = self.current_rate * self.portfolio.value
        self.current_age += 1
        return amount
Exemple #10
0
    def _calc(self):
        # Siegel & Waring suggest the discount rate should be
        # "TIPS interest rate (present-value-weighted average interest rate across the TIPS
        # ladder)" at the start of each year.
        # Currently, we don't support changing the discount_rate every year and use a constant rate
        rate = self.discount_rate

        # Siegel & Waring suggest using the average of 120 (the maximum known human life span) and
        # life expectancy based on current age according to the Social Security tables.
        years_left = average(
            [ARVA.MAX_AGE, get_life_expectancy(self.current_age)])
        return pmt(rate, years_left, self.portfolio.value)
Exemple #11
0
    def _calc(self):
        p_v = pmt(self.discount_rate, self.final_age - self.current_age,
                  self.portfolio.value)
        if p_v < self.current_withdrawal:
            self.retrenchments.append(
                (self.current_age, self.current_withdrawal, p_v))

        if self.only_down:
            if p_v < self.current_withdrawal: self.current_withdrawal = p_v
        else:
            self.current_withdrawal = p_v

        return self.current_withdrawal
Exemple #12
0
    def _calc(self):
        p_v = pmt(self.discount_rate, self.final_age - self.current_age, self.portfolio.value)

        # React immediately to downward market conditions.
        if p_v < self.current_withdrawal:
            self.current_withdrawal = p_v
        # Only do the harvest if we aren't under water from where we started
        elif p_v < self.initial_withdrawal:
            self.current_withdrawal = p_v
        else:
            excess_funds = p_v - self.current_withdrawal
            lifestyle_creep = excess_funds * self.lifestyle_pct
            self.current_withdrawal = min(lifestyle_creep + self.current_withdrawal, self.max_withdrawal)
        return self.current_withdrawal
 def _calc(self):
     # shortcut if the portfolio is 0...some of the math
     # below doesn't like 0s.
     if self.portfolio.value == 0:
         return Decimal(0)
     amount = pmt(self.rate, self.final_age - self.current_age,
                  self.portfolio.value)
     desired_pmt = self.desired_payment * self.cumulative_inflation
     desired_value = pv(float(self.rate),
                        self.final_age - self.current_age,
                        float(-desired_pmt),
                        when='begin')
     desired_value = Decimal(desired_value)
     tilt = (self.portfolio.value / desired_value)**self.tilt
     return amount * tilt
    def _calc(self):
        p_v = pmt(self.discount_rate, self.final_age - self.current_age,
                  self.portfolio.value)

        # React immediately to downward market conditions.
        if p_v < self.current_withdrawal:
            self.current_withdrawal = p_v
        # Only do the harvest if we aren't under water from where we started
        elif p_v < self.initial_withdrawal:
            self.current_withdrawal = p_v
        else:
            excess_funds = p_v - self.current_withdrawal
            lifestyle_creep = excess_funds * self.lifestyle_pct
            self.current_withdrawal = min(
                lifestyle_creep + self.current_withdrawal, self.max_withdrawal)
        return self.current_withdrawal
Exemple #15
0
    def __init__(self, portfolio, harvest_strategy,
            current_age=65,
            final_age=110,
            discount_rate=.08,
            only_down=True):
        super().__init__(portfolio, harvest_strategy)

        self.discount_rate = discount_rate
        self.final_age = final_age
        self.current_age = current_age
        # Do we only "retrench" or do we also increase the withdrawals?
        # Setting this to true means using PMT directly.
        self.only_down = only_down

        self.current_withdrawal = pmt(self.discount_rate, self.final_age - self.current_age, self.portfolio.value)

        self.retrenchments = []
Exemple #16
0
    def __init__(self, portfolio,
            current_age=65,
            final_age=110,
            discount_rate=.06,
            lifestyle_pct=.25,
            lifestyle_cap=2):
        strategy = self.harvest()
        strategy.send(None)
        super().__init__(portfolio, strategy)

        self.discount_rate = discount_rate
        self.final_age = final_age
        self.current_age = current_age
        self.current_withdrawal = pmt(self.discount_rate, self.final_age - self.current_age, self.portfolio.value)
        self.initial_withdrawal = self.current_withdrawal
        self.lifestyle_pct = Decimal(lifestyle_pct)
        self.target_bonds = portfolio.bonds_pct
        self.max_withdrawal = self.initial_withdrawal * Decimal(lifestyle_cap)
Exemple #17
0
    def __init__(self,
                 portfolio,
                 harvest_strategy,
                 current_age=65,
                 final_age=110,
                 discount_rate=.08,
                 only_down=True):
        super().__init__(portfolio, harvest_strategy)

        self.discount_rate = discount_rate
        self.final_age = final_age
        self.current_age = current_age
        # Do we only "retrench" or do we also increase the withdrawals?
        # Setting this to true means using PMT directly.
        self.only_down = only_down

        self.current_withdrawal = pmt(self.discount_rate,
                                      self.final_age - self.current_age,
                                      self.portfolio.value)

        self.retrenchments = []
    def __init__(self,
                 portfolio,
                 current_age=65,
                 final_age=110,
                 discount_rate=.06,
                 lifestyle_pct=.25,
                 lifestyle_cap=2):
        strategy = self.harvest()
        strategy.send(None)
        super().__init__(portfolio, strategy)

        self.discount_rate = discount_rate
        self.final_age = final_age
        self.current_age = current_age
        self.current_withdrawal = pmt(self.discount_rate,
                                      self.final_age - self.current_age,
                                      self.portfolio.value)
        self.initial_withdrawal = self.current_withdrawal
        self.lifestyle_pct = Decimal(lifestyle_pct)
        self.target_bonds = portfolio.bonds_pct
        self.max_withdrawal = self.initial_withdrawal * Decimal(lifestyle_cap)