def update_world(self, change, portfolio_pre, withdrawal): assert isinstance(change, AnnualChange) assert isinstance(portfolio_pre, PortfolioSnapshot) # Because withdrawals happen at the *beginning* of the year, we have to # calculate the real withdrawal value *before* we apply the current year's inflation withdrawal_deflated = withdrawal / self.cumulative_inflation # then we apply that to our portfolio & capture the updated state of the portfolio self.current_inflation = change.inflation self.cumulative_inflation *= (1 + change.inflation) (p_gains, p_val_pre, p_val_post) = self.portfolio.adjust_returns(change) portfolio_post = adt.snapshot_portfolio(self.portfolio) # Now we can finally report this year's activity to our controller # We need to avoid DivisionByZero in cases where the portfolio is exhausted if portfolio_pre.value_n == 0: withdraw_pct_cur = 0 else: withdraw_pct_cur = withdrawal / portfolio_pre.value_n return YearlyResults(returns_n=p_gains, returns_r=((1 + p_gains) / (1 + self.current_inflation)) - 1, withdraw_n=withdrawal, withdraw_r=withdrawal_deflated, withdraw_pct_cur=withdraw_pct_cur, withdraw_pct_orig=withdrawal_deflated / self.portfolio.starting_value, portfolio_pre=portfolio_pre, portfolio_post=portfolio_post)
def simulate_accumulation(series, portfolio=(0, 0), years=35, annual_inflow=25000, accumulation=N_80_RebalanceAccumulation): portfolio = Portfolio(portfolio[0], portfolio[1]) strategy = accumulation(portfolio).accumulate() strategy.send(None) annual = [] for _, change in zip(range(years), series): gains, _, _ = portfolio.adjust_returns(change) strategy.send(annual_inflow) annual.append( YearlyResults(returns=gains, withdraw_n=0, withdraw_r=0, withdraw_pct_cur=0, withdraw_pct_orig=0, portfolio_n=portfolio.value, portfolio_r=portfolio.real_value, portfolio_bonds=portfolio.bonds, portfolio_stocks=portfolio.stocks)) annual_inflow *= 1 + change.inflation return annual
def simulate_lmp(series, portfolio=(750000,250000), years=40, lmp_real_annual=Decimal('.01')): count = 0 annual = [] cumulative_inflation = 1 lmp = portfolio[0] rp = portfolio[1] for (year, stocks, bonds, inflation) in series: if count > years: break if count < 5: amount = 50000 else: amount = 21700 cumulative_inflation *= (1 + inflation) amount *= cumulative_inflation previous_portfolio_amount = rp + lmp rp *= (1 + stocks) lmp_gains = lmp_real_annual + inflation lmp *= (1 + lmp_gains) gains = (rp + lmp) - previous_portfolio_amount if amount < lmp: lmp -= amount else: a1 = amount - lmp lmp = 0 if rp > a1: rp -= a1 else: amount = rp rp = 0 annual.append(YearlyResults( year = 0, returns = gains, withdraw_n = amount, withdraw_r = amount / cumulative_inflation, withdraw_pct_cur = amount / (rp + lmp), withdraw_pct_orig = (amount / cumulative_inflation) / (portfolio[0] + portfolio[1]), portfolio_n = rp + lmp, portfolio_r = (rp + lmp) / cumulative_inflation, portfolio_bonds = lmp, portfolio_stocks = rp )) count += 1 return annual