Пример #1
0
 def test_rebalance_reinvest(self):
     portfolio = Portfolio({CCC: Decimal(2000), DDD: Decimal(8000)})
     orders = portfolio.rebalance(self.model_portfolio)
     self.assertEqual(orders, [(SELL, CCC, Decimal(2000)),
                               (SELL, DDD, Decimal(8000)),
                               (BUY, AAA, Decimal(4000)),
                               (BUY, BBB, Decimal(5000))])
Пример #2
0
 def test_get_returns_cash_only(self):
     portfolio = Portfolio({CASH: Decimal(1000)})
     act_dates, act_returns = portfolio.get_returns()
     self.assertEqual(len(act_dates), 365)
     self.assertEqual(len(act_returns), len(act_dates))
     self.assertEqual(act_returns[0][0], 1000)
     self.assertEqual(act_returns[-1][0], 1000)
Пример #3
0
    def test_rebalancing2(self):
        """
        Test rebalancing algorithm. Part 2.

        Cash is not in the same currency as the assets.
        """
        p = Portfolio()

        p.add_cash(200., "USD")
        p.add_cash(250., "GBP")

        tickers = ["VCN.TO", "XAW.TO", "ZAG.TO"]
        quantities = [5, 12, 20]
        p.easy_add_assets(tickers=tickers, quantities=quantities)

        target_asset_alloc = {
            "VCN.TO": 40.0,
            "ZAG.TO": 40.0,
            "XAW.TO": 20.0,
        }

        initial_value = p.value("CAD")
        p.selling_allowed = False
        (_, prices, _, _) = p.rebalance(target_asset_alloc, verbose=True)
        final_value = p.value("CAD")
        self.assertAlmostEqual(initial_value, final_value, -1)

        # The prices should be in the tickers' currency
        for ticker in tickers:
            self.assertEqual(prices[ticker][1], "CAD")

        # Since there was no CAD to start off with,
        # there should be none after rebalacing either
        # (i.e. amount converted to CAD should be the amount used to purchase CAD assets)
        self.assertAlmostEqual(p.cash["CAD"].amount, 0., 1)
Пример #4
0
class PortfolioPlottingTest(unittest.TestCase):
    def setUp(self):
        self.portfolio = Portfolio({CASH: Decimal(129), AAA: Decimal(4034)})

    def test_plot(self):
        # mock matplotlib.pyplot pie chart
        fig, ax, plt = [MagicMock() for _ in range(3)]
        plt.subplots.return_value = (fig, ax)
        self.portfolio.plot(plt)

        # check arguments to ax.pie(...)
        args = ax.pie.call_args
        values = args[0][0]
        labels = args[1]['labels']

        pos, allocs = self.portfolio.positions, self.portfolio.allocations
        self.assertEqual(values, [pos[CASH], pos[AAA]])
        self.assertEqual(labels, [CASH, AAA])

        # call autopct function for the pie wedge texts
        autopct = args[1]['autopct']
        text1 = autopct(allocs[CASH])
        text2 = autopct(allocs[AAA])
        self.assertEqual(text1, '$129.00 (3.10%)')
        self.assertEqual(text2, '$4,034.00 (96.90%)')
Пример #5
0
    def test_asset_allocation(self):
        """
        Test asset allocation method.
        """
        p = Portfolio()

        tickers = ["VCN.TO", "ZAG.TO", "XAW.TO", "TSLA"]
        quantities = [2, 20, 10, 4]
        p.easy_add_assets(tickers=tickers, quantities=quantities)

        asset_alloc = p.asset_allocation()
        self.assertAlmostEqual(sum(asset_alloc.values()), 100., 7)

        rates = CurrencyRates()

        prices = [
            yf.Ticker(ticker).info["ask"] *
            rates.get_rate(yf.Ticker(ticker).info["currency"], "CAD")
            for ticker in tickers
        ]
        total = np.sum(np.asarray(quantities) * np.asarray(prices))
        n = len(tickers)
        for i in range(n):
            self.assertAlmostEqual(asset_alloc[tickers[i]],
                                   quantities[i] * prices[i] / total * 100., 1)
Пример #6
0
 def test_get_returns(self):
     portfolio = Portfolio({CASH: Decimal(1000), VFV: Decimal(1000)})
     act_dates, act_returns = portfolio.get_returns()
     self.assertEqual(len(act_dates), 365)
     self.assertEqual(len(act_returns), len(act_dates))
     shares = Decimal(1000) / Decimal('28.89')
     self.assertEqual(act_returns[0][0], 2000)  # starting CASH + VFV
     self.assertEqual(act_returns[-1][0], shares * Decimal('30.69') + 1000)
Пример #7
0
 def test_rebalance_balanced(self):
     portfolio = Portfolio({
         CASH: Decimal(500),
         AAA: Decimal(2000),
         BBB: Decimal(2500)
     })
     orders = portfolio.rebalance(self.model_portfolio)
     self.assertEqual(orders, [])
Пример #8
0
 def test_get_returns_mismatched_dates(self):
     aaa_dates = np.array([[date(2016, 1, 1)], [date(2016, 1, 2)],
                           [date(2016, 1, 3)]])
     aaa_prices = np.array([[42], [43], [44]])
     bbb_dates = np.array([[date(2016, 1, 2)], [date(2016, 1, 3)]])
     bbb_prices = np.array([[57], [58]])
     AAA = FixedPricesInstrument('AAA', aaa_dates, aaa_prices)
     BBB = FixedPricesInstrument('BBB', bbb_dates, bbb_prices)
     portfolio = Portfolio({AAA: Decimal(1000), BBB: Decimal(1000)})
     act_dates, act_returns = portfolio.get_returns()
Пример #9
0
    def test_portfolio_value(self):
        """
        Test total market value, total cash value, and total value methods.
        """

        p = Portfolio()

        tickers = ["VCN.TO", "ZAG.TO", "XAW.TO", "TSLA"]
        quantities = [2, 20, 10, 4]
        p.easy_add_assets(tickers=tickers, quantities=quantities)

        mv = p.market_value("CAD")

        total_mv = np.sum(
            [asset.market_value_in("CAD") for asset in p.assets.values()])

        self.assertAlmostEqual(mv, total_mv, 1)

        amounts = [500.15, 200.00]
        currencies = ["CAD", "USD"]
        p.easy_add_cash(amounts, currencies)

        cv = p.cash_value("CAD")

        usd_to_cad = CurrencyRates().get_rate("USD", "CAD")
        total_cv = np.sum(amounts[0] + amounts[1] * usd_to_cad)
        self.assertAlmostEqual(cv, total_cv, 1)

        self.assertAlmostEqual(p.value("CAD"), total_mv + total_cv, 1)
Пример #10
0
    def test_cash_interface2(self):
        """
        Test portfolio's interface related to Cash class.

        Collectively adding cash to the portfolio.
        """
        p = Portfolio()
        amounts = [500.15, 200.00]
        currencies = ["CAD", "USD"]
        p.easy_add_cash(amounts, currencies)

        self.assertEqual(p.cash[currencies[0]].amount, amounts[0])
        self.assertEqual(p.cash[currencies[1]].amount, amounts[1])
Пример #11
0
    def test_asset_interface2(self):
        """
        Test portfolio's interface related to Asset class.

        Collectively adding assets to the portfolio.
        """

        p = Portfolio()

        tickers = ["VCN.TO", "ZAG.TO"]
        quantities = [2, 20]
        p.easy_add_assets(tickers=tickers, quantities=quantities)

        n = len(tickers)
        for i in range(n):
            self.assertEqual(tickers[i], p.assets[tickers[i]].ticker)
            self.assertEqual(quantities[i], p.assets[tickers[i]].quantity)
            self.assertEqual(
                yf.Ticker(tickers[i]).info["ask"], p.assets[tickers[i]].price)
Пример #12
0
    def test_asset_interface(self):
        """
        Test portfolio's interface related to Asset class.

        Adding assets individually to the portfolio.
        """
        p = Portfolio()

        ticker = "VCN.TO"
        quantity = 2
        ticker_info = yf.Ticker(ticker).info
        price = ticker_info["ask"]
        asset = Asset(ticker=ticker, quantity=quantity)

        p.add_asset(asset)
        self.assertEqual(asset.ticker, p.assets[ticker].ticker)
        self.assertEqual(asset.quantity, p.assets[ticker].quantity)
        self.assertEqual(asset.price, p.assets[ticker].price)

        ticker = "ZAG.TO"
        quantity = 20
        asset2 = Asset(ticker=ticker, quantity=quantity)
        p.add_asset(asset2)

        self.assertEqual(asset2.ticker, p.assets[ticker].ticker)
        self.assertEqual(asset2.quantity, p.assets[ticker].quantity)
        self.assertEqual(asset2.price, p.assets[ticker].price)
Пример #13
0
    def test_cash_interface(self):
        """
        Test portfolio's interface related to Cash class.

        Adding cash of different currency individually to the portfolio.
        """
        p = Portfolio()
        amount1 = 500.15
        p.add_cash(amount1, "cad")
        amount2 = 200.00
        p.add_cash(amount2, "usd")

        self.assertEqual(p.cash["CAD"].amount, amount1)
        self.assertEqual(p.cash["USD"].amount, amount2)
Пример #14
0
 def test_rebalance_unbalanced(self):
     portfolio = Portfolio({AAA: Decimal(2000), BBB: Decimal(8000)})
     orders = portfolio.rebalance(self.model_portfolio)
     self.assertEqual(orders, [(SELL, BBB, Decimal(3000)),
                               (BUY, AAA, Decimal(2000))])
Пример #15
0
 def test_rebalance_cash(self):
     portfolio = Portfolio({CASH: Decimal(5000)})
     orders = portfolio.rebalance(self.model_portfolio)
     self.assertEqual(orders, [(BUY, AAA, Decimal(2000)),
                               (BUY, BBB, Decimal(2500))])
Пример #16
0
 def setUp(self):
     self.model_portfolio = Portfolio({
         CASH: Decimal(10),
         AAA: Decimal(40),
         BBB: Decimal(50)
     })
Пример #17
0
 def setUp(self):
     self.portfolio = Portfolio({CASH: Decimal(1200), AAA: Decimal(300)})
Пример #18
0
 def setUp(self):
     self.portfolio = Portfolio({CASH: Decimal(129), AAA: Decimal(4034)})
Пример #19
0
    def test_rebalancing(self):
        """
        Test rebalancing algorithm.

        This might break over time as prices increase.
        If we have enough cash though, the optimizer should ideally
        be able to match the target asset allocation
        pretty closely
        """

        p = Portfolio()

        tickers = ["XBB.TO", "XIC.TO", "ITOT", "IEFA", "IEMG"]
        quantities = [36, 64, 32, 8, 7]
        p.easy_add_assets(tickers=tickers, quantities=quantities)
        p.add_cash(3000, "USD")
        p.add_cash(515.21, "CAD")
        p.add_cash(5.00, "GBP")
        p.selling_allowed = True

        self.assertTrue(p.selling_allowed)

        # different order than tickers.
        # rebalance method should be able to handle such a case
        target_asset_alloc = {
            "XBB.TO": 20,
            "XIC.TO": 20,
            "IEFA": 20,
            "ITOT": 36,
            "IEMG": 4
        }

        initial_value = p.value("CAD")
        (_, _, _, max_diff) = p.rebalance(target_asset_alloc, verbose=True)
        final_value = p.value("CAD")
        self.assertAlmostEqual(initial_value, final_value, 1)
        self.assertLessEqual(max_diff, 2.)

        # Error handling
        with self.assertRaises(Exception):
            target_asset_alloc = {
                "XBB.TO": 20,
                "XIC.TO": 20,
                "IEFA": 20,
            }
            p.rebalance(target_asset_alloc)
Пример #20
0
    def test_exchange(self):
        """
        Test currency exchange in Portfolio.
        """

        p = Portfolio()

        amounts = [500.15, 200.00]
        currencies = ["CAD", "USD"]
        p.easy_add_cash(amounts, currencies)

        cad_to_usd = CurrencyRates().get_rate("CAD", "USD")

        p.exchange_currency(to_currency="CAD",
                            from_currency="USD",
                            to_amount=100)
        self.assertAlmostEqual(p.cash["CAD"].amount, 500.15 + 100., 1)
        self.assertAlmostEqual(p.cash["USD"].amount, 200. - 100. * cad_to_usd,
                               1)

        p.exchange_currency(from_currency="USD",
                            to_currency="CAD",
                            from_amount=50)
        self.assertAlmostEqual(p.cash["CAD"].amount,
                               500.15 + 100 + 50 / cad_to_usd, 1)
        self.assertAlmostEqual(p.cash["USD"].amount,
                               200. - 100. * cad_to_usd - 50, 1)

        # error handling:
        with self.assertRaises(Exception):
            p.exchange_currency(to_currency="CAD",
                                from_currency="USD",
                                to_amount=100,
                                from_amount=20)

        # error handling
        with self.assertRaises(Exception):
            p.exchange_currency(to_currency="CAD", from_currency="USD")
Пример #21
0
 def setUp(self):
     self.model_portfolio = Portfolio({AAA: Decimal(10), BBB: Decimal(90)})
Пример #22
0
from rebalance import Portfolio

# My portfolio
p = Portfolio()

# Cash in portfolio
cash_amounts = [5000]
cash_currency = ["CAD"]
p.easy_add_cash(amounts=cash_amounts, currencies=cash_currency)

# Assets in portfolio
# The price will be retrieved automatically
tickers = ["XIC.TO", "VCN.TO", "TSLA"]
quantities = [20, 20, 10]
p.easy_add_assets(tickers=tickers, quantities=quantities)

# Target asset allocation (in %)
target_asset_alloc = {"XIC.TO": 20, "VCN.TO": 30, "TSLA": 50}

# rebalance
p.selling_allowed = True  # Don't allow selling while rebalancing
p.rebalance(target_asset_alloc, verbose=True)
Пример #23
0
 def make_portfolio(self, aaa, bbb):
     return Portfolio({AAA: Decimal(aaa), BBB: Decimal(bbb)})
Пример #24
0
from rebalance import Portfolio

p = Portfolio()

tickers = ["XBB.TO", "XIC.TO", "ITOT", "IEFA", "IEMG"]
quantities = [36, 64, 32, 8, 7]
p.easy_add_assets(tickers=tickers, quantities = quantities)
p.add_cash(5000.00, "GBP")
p.add_cash(1000.00, "EUR")

target_asset_alloc = {
"XBB.TO": 20,
"XIC.TO": 20,
"IEFA":   20,
"ITOT":   36,
"IEMG":    4
}


initial_value = p.value("CAD")
p.selling_allowed = False
(_, _, exchange_rates, _) = p.rebalance(target_asset_alloc, verbose=True)
final_value = p.value("CAD")