def testChainedWithdrawForcedWithdrawProportionalDeposit(self): year_rec = utils.YearRecord() rrsp = funds.RRSP() rrsp.amount = 100 rrsp.forced_withdraw = 80 tfsa = funds.TFSA() tfsa.amount = 50 year_rec.tfsa_room = 50 nonreg = funds.NonRegistered() nonreg.amount = 50 nonreg.unrealized_gains = 25 fund_chain = (rrsp, tfsa, nonreg) proportions = (0.1, 0.5, 1) withdrawn, gains, year_rec = funds.ChainedWithdraw(60, fund_chain, proportions, year_rec) self.assertEqual(withdrawn, 60) self.assertEqual(gains, 0) self.assertSequenceEqual( year_rec.withdrawals, [funds.WithdrawReceipt(80, 0, funds.FUND_TYPE_RRSP)]) self.assertSequenceEqual( year_rec.deposits, [funds.DepositReceipt(10, funds.FUND_TYPE_TFSA), funds.DepositReceipt(10, funds.FUND_TYPE_NONREG)]) self.assertEqual(rrsp.amount, 20) self.assertEqual(tfsa.amount, 60) self.assertEqual(nonreg.amount, 60)
def testChainedTransactionDifferentProportion(self): year_rec = utils.YearRecord() rrsp = funds.RRSP() rrsp.amount = 100 rrsp.forced_withdraw = 80 tfsa = funds.TFSA() tfsa.amount = 50 year_rec.tfsa_room = 100 nonreg = funds.NonRegistered() fund_chain = (rrsp, tfsa, nonreg) withdrawal_proportions = (0.5, 0.5, 1) deposit_proportions = (0.5, 0.8, 1) withdrawn, gains, year_rec = funds.ChainedTransaction( 60, fund_chain, withdrawal_proportions, deposit_proportions, year_rec) self.assertEqual(withdrawn, 60) self.assertEqual(gains, 0) self.assertSequenceEqual( year_rec.withdrawals, [funds.WithdrawReceipt(80, 0, funds.FUND_TYPE_RRSP)]) self.assertSequenceEqual( year_rec.deposits, [funds.DepositReceipt(16, funds.FUND_TYPE_TFSA), funds.DepositReceipt(4, funds.FUND_TYPE_NONREG)]) self.assertEqual(rrsp.amount, 20) self.assertEqual(tfsa.amount, 66) self.assertEqual(nonreg.amount, 4)
def SetupYearRecForIncomeTax( self, earnings=0, oas=0, gis=0, cpp=0, ei=0, rrsp=0, bridging=0,nonreg=0, gains=0, eoy_gains=0, unapplied_losses=0, rrsp_contributions=0, age=30, retired=False, cpi=1): """Set up a person and a year record in one go for testing income tax.""" j_canuck = person.Person(strategy=self.default_strategy) j_canuck.capital_loss_carry_forward = unapplied_losses j_canuck.age += age - world.START_AGE j_canuck.year += age - world.START_AGE j_canuck.retired = retired year_rec = utils.YearRecord() year_rec.is_retired = j_canuck.retired year_rec.year = j_canuck.year year_rec.incomes.append(incomes.IncomeReceipt(earnings, incomes.INCOME_TYPE_EARNINGS)) year_rec.incomes.append(incomes.IncomeReceipt(oas, incomes.INCOME_TYPE_OAS)) year_rec.incomes.append(incomes.IncomeReceipt(gis, incomes.INCOME_TYPE_GIS)) year_rec.incomes.append(incomes.IncomeReceipt(cpp, incomes.INCOME_TYPE_CPP)) year_rec.incomes.append(incomes.IncomeReceipt(ei, incomes.INCOME_TYPE_EI)) year_rec.withdrawals.append(funds.WithdrawReceipt(nonreg, gains, funds.FUND_TYPE_NONREG)) year_rec.withdrawals.append(funds.WithdrawReceipt(rrsp, 0, funds.FUND_TYPE_RRSP)) year_rec.withdrawals.append(funds.WithdrawReceipt(bridging, 0, funds.FUND_TYPE_BRIDGING)) year_rec.tax_receipts.append(funds.TaxReceipt(eoy_gains, funds.FUND_TYPE_NONREG)) year_rec.deposits.append(funds.DepositReceipt(rrsp_contributions, funds.FUND_TYPE_RRSP)) year_rec.cpi = cpi year_rec = j_canuck.CalcPayrollDeductions(year_rec) return (j_canuck, year_rec)
def testDepositUnlimitedRoom(self): fund = funds.Fund() deposited, year_rec = fund.Deposit(15, utils.YearRecord()) self.assertEqual(deposited, 15) self.assertEqual(fund.amount, 15) self.assertIn(funds.DepositReceipt(15, funds.FUND_TYPE_NONE), year_rec.deposits)
def testChainedDepositInsufficientRoom(self): year_rec = utils.YearRecord() tfsa = funds.TFSA() year_rec.tfsa_room = 30 rrsp = funds.RRSP() year_rec.rrsp_room = 50 fund_chain = (tfsa, rrsp) proportions = (1, 1) deposited, year_rec = funds.ChainedDeposit(100, fund_chain, proportions, year_rec) self.assertEqual(deposited, 80) self.assertSequenceEqual(year_rec.deposits, [funds.DepositReceipt(30, funds.FUND_TYPE_TFSA), funds.DepositReceipt(50, funds.FUND_TYPE_RRSP)]) self.assertEqual(tfsa.amount, 30) self.assertEqual(rrsp.amount, 50)
def testRRSPBridgingDeposit(self): fund = funds.RRSPBridging() fund.amount = 30 deposited, year_rec = fund.Deposit(15, utils.YearRecord()) self.assertEqual(deposited, 0) self.assertEqual(fund.amount, 30) self.assertIn(funds.DepositReceipt(0, funds.FUND_TYPE_BRIDGING), year_rec.deposits)
def testNonRegisteredDeposit(self): fund = funds.NonRegistered() deposited, year_rec = fund.Deposit(15, utils.YearRecord()) self.assertEqual(deposited, 15) self.assertEqual(fund.amount, 15) self.assertIn(funds.DepositReceipt(15, funds.FUND_TYPE_NONREG), year_rec.deposits) self.assertEqual(fund.unrealized_gains, 0)
def OnRetirement(self, year_rec): """This deals with events happening at the point of retirement.""" # Update all incomes for income in self.incomes: income.OnRetirement(self) # Create RRSP bridging fund if needed if self.age < world.CPP_EXPECTED_RETIREMENT_AGE: requested = ( world.CPP_EXPECTED_RETIREMENT_AGE - self.age ) * world.OAS_BENEFIT * self.strategy.oas_bridging_fraction self.funds["wp_rrsp"], self.funds["bridging"] = funds.SplitFund( self.funds["wp_rrsp"], funds.RRSPBridging(), requested) if self.funds["bridging"].amount < requested: top_up_amount = min(self.rrsp_room, requested - self.funds["bridging"].amount) fund_chain = [self.funds["wp_nonreg"], self.funds["wp_tfsa"]] # Not using ChainedWithdraw because it can't express strict overflow withdrawn, _, year_rec = funds.ChainedTransaction( top_up_amount, fund_chain, (1, 1), (1, 1), year_rec) self.funds["bridging"].amount += withdrawn year_rec.deposits.append( funds.DepositReceipt(withdrawn, funds.FUND_TYPE_RRSP)) self.rrsp_room -= withdrawn self.bridging_withdrawal_table = world.GenerateCEDDrawdownTable( self.age, world.CPP_EXPECTED_RETIREMENT_AGE) # Split each fund into a CED and a CD fund self.funds["cd_rrsp"], self.funds["ced_rrsp"] = funds.SplitFund( self.funds["wp_rrsp"], funds.RRSP(), self.strategy.drawdown_ced_fraction * self.funds["wp_rrsp"].amount) del self.funds["wp_rrsp"] self.funds["cd_tfsa"], self.funds["ced_tfsa"] = funds.SplitFund( self.funds["wp_tfsa"], funds.TFSA(), self.strategy.drawdown_ced_fraction * self.funds["wp_tfsa"].amount) del self.funds["wp_tfsa"] self.funds["cd_nonreg"], self.funds["ced_nonreg"] = funds.SplitFund( self.funds["wp_nonreg"], funds.NonRegistered(), self.strategy.drawdown_ced_fraction * self.funds["wp_nonreg"].amount) del self.funds["wp_nonreg"] self.cd_drawdown_amount = sum( fund.amount for fund in (self.funds["cd_rrsp"], self.funds["cd_tfsa"], self.funds["cd_nonreg"] )) * self.strategy.initial_cd_fraction / year_rec.cpi self.assets_at_retirement = sum( fund.amount for fund in self.funds.values()) / year_rec.cpi if not self.basic_only: self.accumulators.fraction_persons_involuntarily_retired.UpdateOneValue( 1 if self.age < self.strategy.planned_retirement_age else 0)
def testTFSADeposit(self): fund = funds.TFSA() year_rec = utils.YearRecord() year_rec.tfsa_room = 20 deposited, year_rec = fund.Deposit(15, year_rec) self.assertEqual(deposited, 15) self.assertEqual(fund.amount, 15) self.assertIn(funds.DepositReceipt(15, funds.FUND_TYPE_TFSA), year_rec.deposits)
def testChainedDepositProportions(self): year_rec = utils.YearRecord() tfsa = funds.TFSA() year_rec.tfsa_room = 30 rrsp = funds.RRSP() year_rec.rrsp_room = 30 nonreg = funds.NonRegistered() fund_chain = (tfsa, rrsp, nonreg) proportions = (0.2, 0.5, 1) deposited, year_rec = funds.ChainedDeposit(100, fund_chain, proportions, year_rec) self.assertEqual(deposited, 100) self.assertSequenceEqual(year_rec.deposits, [funds.DepositReceipt(20, funds.FUND_TYPE_TFSA), funds.DepositReceipt(30, funds.FUND_TYPE_RRSP), funds.DepositReceipt(50, funds.FUND_TYPE_NONREG)]) self.assertEqual(tfsa.amount, 20) self.assertEqual(rrsp.amount, 30) self.assertEqual(nonreg.amount, 50)
def testRRSPDeposit(self): fund = funds.RRSP() year_rec = utils.YearRecord() year_rec.rrsp_room = 20 deposited, year_rec = fund.Deposit(15, year_rec) self.assertEqual(deposited, 15) self.assertEqual(fund.amount, 15) self.assertIn(funds.DepositReceipt(15, funds.FUND_TYPE_RRSP), year_rec.deposits) self.assertEqual(year_rec.rrsp_room, 5)
def testDepositInsufficientRoom(self): fund = funds.Fund() fund.GetRoom = unittest.mock.MagicMock(return_value=10) set_room = unittest.mock.MagicMock() fund.SetRoom = set_room deposited, year_rec = fund.Deposit(15, utils.YearRecord()) self.assertEqual(deposited, 10) self.assertEqual(fund.amount, 10) self.assertIn(funds.DepositReceipt(10, funds.FUND_TYPE_NONE), year_rec.deposits) set_room.assert_called_with(unittest.mock.ANY, 0)
def testChainedWithdrawForcedWithdrawWantZero(self): rrsp = funds.RRSP() rrsp.amount = 100 rrsp.forced_withdraw = 20 nonreg = funds.NonRegistered() fund_chain = (rrsp, nonreg) proportions = (0, 1) withdrawn, gains, year_rec = funds.ChainedWithdraw(0, fund_chain, proportions, utils.YearRecord()) self.assertEqual(withdrawn, 0) self.assertEqual(gains, 0) self.assertSequenceEqual( year_rec.withdrawals, [funds.WithdrawReceipt(20, 0, funds.FUND_TYPE_RRSP)]) self.assertSequenceEqual( year_rec.deposits, [funds.DepositReceipt(20, funds.FUND_TYPE_NONREG)]) self.assertEqual(rrsp.amount, 80) self.assertEqual(nonreg.amount, 20)
def testChainedWithdrawForcedWithdrawOverflow(self): rrsp = funds.RRSP() rrsp.amount = 100 rrsp.forced_withdraw = 80 tfsa = funds.TFSA() tfsa.amount = 50 tfsa.room = 0 fund_chain = (rrsp, tfsa) proportions = (0.5, 1) withdrawn, gains, year_rec = funds.ChainedWithdraw( 60, fund_chain, proportions, utils.YearRecord()) self.assertEqual(withdrawn, 80) self.assertEqual(gains, 0) self.assertSequenceEqual( year_rec.withdrawals, [funds.WithdrawReceipt(80, 0, funds.FUND_TYPE_RRSP)]) self.assertSequenceEqual( year_rec.deposits, [funds.DepositReceipt(0, funds.FUND_TYPE_TFSA)]) self.assertEqual(rrsp.amount, 20) self.assertEqual(tfsa.amount, 50)