Example #1
0
    def test_all_unrealized_realized(self, entries, _, options_map):
        """
        2014-01-01 open Assets:Account1
        2014-01-01 open Assets:Cash
        2014-01-01 open Income:Misc
        2014-01-01 open Income:PnL

        2014-01-15 *
          Income:Misc           -1000 USD
          Assets:Account1       10 HOUSE {100 USD}

        2014-01-15 price HOUSE  100 USD
        2014-01-20 price HOUSE  120 USD

        2014-02-10 *
          Assets:Cash           3000 USD
          Assets:Account1       -10 HOUSE {100 USD}
          Income:PnL            -2000 USD
        """
        # The goal is to have two transactions, one that registers the unrealized
        # profit and the other that negates it because there has been real profit
        new_entries, _ = unrealized_periodic.add_unrealized_gains(
            entries, options_map)
        unreal_entries = unrealized_periodic.get_unrealized_entries(
            new_entries)
        self.assertEqual(2, len(unreal_entries))
        for target, actual in zip([(None, D('200')), (None, D('-200'))],
                                  unreal_entries):
            if target[0] is not None:
                self.assertEqual(target[0], actual.postings[2].units.number)
            self.assertEqual(target[1], actual.postings[0].units.number)
Example #2
0
    def test_change_commodity_subaccount(self, entries, _, options_map):
        """
        2014-01-01 open Assets:Account1
        2014-01-01 open Income:Misc
        2014-01-01 open Income:Pnl

        2014-01-15 *
          Income:Misc           -1000 USD
          Assets:Account1       10 HOUSE {100 USD}

        2014-01-15 price HOUSE  100 USD
        2014-01-20 price HOUSE  125 USD
        2014-02-05 price HOUSE  150 USD

        2014-02-15 *
          Assets:Account1      -10 HOUSE {100 USD}
          Assets:Account1       30 CAR {50 USD}
          Income:Pnl           -500 USD
        2014-02-15 price CAR  50 USD
        2014-02-20 price CAR  100 USD
        """
        new_entries, _ = unrealized_periodic.add_unrealized_gains(
            entries, options_map, subaccount='Unrealized')
        unreal_entries = unrealized_periodic.get_unrealized_entries(
            new_entries)
        self.assertEqual(3, len(unreal_entries))
        self.assertEqual(2, len(unreal_entries[-2].postings)
                         )  # The second to last transaction zeroed the account
        self.assertEqual(
            2, len(unreal_entries[-1].postings
                   ))  # The last transaction added the new unrealized gain
        summary = summarize.balance_by_account(unreal_entries)
        self.assertEqual(summary[0]['Assets:Account1:Unrealized'],
                         inventory.Inventory.from_string("1500 USD"))
Example #3
0
    def test_three_months(self, entries, _, options_map):
        """
        2014-01-01 open Assets:Account1
        2014-01-01 open Income:Misc

        2014-01-15 *
          Income:Misc           -1000 USD
          Assets:Account1       10 HOUSE {100 USD}

        2014-01-15 price HOUSE  100 USD
        2014-01-20 price HOUSE  120 USD
        2014-02-25 price HOUSE  140 USD
        2014-03-25 price HOUSE  100 USD
        """
        # There should be three unrealized transactions
        new_entries, _ = unrealized_periodic.add_unrealized_gains(
            entries, options_map)
        unreal_entries = unrealized_periodic.get_unrealized_entries(
            new_entries)
        self.assertEqual(3, len(unreal_entries))
        for target, actual in zip([(None, D('200')), (D('-200'), D('400')),
                                   (D('-400'), ZERO)], unreal_entries):
            if target[0] is not None:
                self.assertEqual(target[0], actual.postings[2].units.number)
            self.assertEqual(target[1], actual.postings[0].units.number)
Example #4
0
    def test_not_assets(self, entries, _, options_map):
        """
        2014-01-01 open Assets:Account1
        2014-01-01 open Liabilities:Account1
        2014-01-01 open Equity:Account1
        2014-01-01 open Expenses:Account1
        2014-01-01 open Income:Account1
        2014-01-01 open Income:Misc

        2014-01-15 *
          Income:Misc
          Assets:Account1      1 HOUSE {100 USD}
          Liabilities:Account1 2 HOUSE {101 USD}
          Equity:Account1      3 HOUSE {102 USD}
          Expenses:Account1    4 HOUSE {103 USD}
          Income:Account1      5 HOUSE {104 USD}

        2014-01-16 price HOUSE 110 USD
        """
        new_entries, _ = unrealized_periodic.add_unrealized_gains(
            entries, options_map, 'Gains')
        unreal_entries = unrealized_periodic.get_unrealized_entries(
            new_entries)

        entry = get_entries_with_narration(unreal_entries, '1 units')[0]
        self.assertEqual("Assets:Account1:Gains", entry.postings[0].account)
        self.assertEqual("Income:Account1:Gains", entry.postings[1].account)
        self.assertEqual(D("10.00"), entry.postings[0].units.number)
        self.assertEqual(D("-10.00"), entry.postings[1].units.number)

        entry = get_entries_with_narration(unreal_entries, '2 units')[0]
        self.assertEqual("Liabilities:Account1:Gains",
                         entry.postings[0].account)
        self.assertEqual("Income:Account1:Gains", entry.postings[1].account)
        self.assertEqual(D("18.00"), entry.postings[0].units.number)
        self.assertEqual(D("-18.00"), entry.postings[1].units.number)

        entry = get_entries_with_narration(unreal_entries, '3 units')[0]
        self.assertEqual("Equity:Account1:Gains", entry.postings[0].account)
        self.assertEqual("Income:Account1:Gains", entry.postings[1].account)
        self.assertEqual(D("24.00"), entry.postings[0].units.number)
        self.assertEqual(D("-24.00"), entry.postings[1].units.number)

        entry = get_entries_with_narration(unreal_entries, '4 units')[0]
        self.assertEqual("Expenses:Account1:Gains", entry.postings[0].account)
        self.assertEqual("Income:Account1:Gains", entry.postings[1].account)
        self.assertEqual(D("28.00"), entry.postings[0].units.number)
        self.assertEqual(D("-28.00"), entry.postings[1].units.number)

        entry = get_entries_with_narration(unreal_entries, '5 units')[0]
        self.assertEqual("Income:Account1:Gains", entry.postings[0].account)
        self.assertEqual("Income:Account1:Gains", entry.postings[1].account)
        self.assertEqual(D("30.00"), entry.postings[0].units.number)
        self.assertEqual(D("-30.00"), entry.postings[1].units.number)
Example #5
0
    def test_conversions_only(self, entries, _, options_map):
        """
        2014-01-01 open Assets:Account1
        2014-01-01 open Income:Misc

        2014-01-15 *
          Income:Misc           -780 USD
          Assets:Account1       600 EUR @ 1.3 USD
        """
        # Check to make sure values not held at cost are not included.
        new_entries, _ = unrealized_periodic.add_unrealized_gains(
            entries, options_map)
        self.assertEqual(
            [], unrealized_periodic.get_unrealized_entries(new_entries))
Example #6
0
    def test_no_price(self, entries, _, options_map):
        """
        2014-01-01 open Assets:Account1
        2014-01-01 open Income:Misc

        2014-01-15 *
          Income:Misc           -1000 USD
          Assets:Account1       10 HOUSE {100 USD}

        2014-01-15 price HOUSE  100 USD
        """
        # Well... if there is a cost, there is at least one price, derived from
        # the cost entry. This won't generate an unrealized transaction because there is no difference.
        new_entries, _ = unrealized_periodic.add_unrealized_gains(
            entries, options_map)
        unreal_entries = unrealized_periodic.get_unrealized_entries(
            new_entries)
        self.assertEqual(0, len(unreal_entries))
Example #7
0
    def test_immediate_profit(self, entries, _, options_map):
        """
        2014-01-01 open Assets:Account1
        2014-01-01 open Income:Misc

        2014-01-15 *
          Income:Misc           -1000 USD
          Assets:Account1       10 HOUSE {100 USD} @ 120 USD

        2014-01-15 price HOUSE  120 USD
        """
        # Well... if there is a cost, there is at least one price, derived from
        # the cost entry.
        new_entries, _ = unrealized_periodic.add_unrealized_gains(
            entries, options_map)
        unreal_entries = unrealized_periodic.get_unrealized_entries(
            new_entries)
        self.assertEqual(1, len(unreal_entries))
        self.assertEqual(D('200'), unreal_entries[0].postings[0].units.number)
Example #8
0
    def test_normal_case(self, entries, _, options_map):
        """
        2014-01-01 open Assets:Account1
        2014-01-01 open Assets:Account2
        2014-01-01 open Income:Misc

        2014-01-15 *
          Income:Misc           -1000 USD
          Assets:Account1       10 HOUSE {100 USD}

        2014-01-16 *
          Income:Misc           -600 USD
          Assets:Account1       5 HOUSE {120 USD}

        2014-01-17 *
          Income:Misc           -1000 EUR
          Assets:Account2       5 MANSION {200 EUR}

        2014-01-18 * "Bought through a price conversion, not held at cost."
          Income:Misc           -1500 EUR
          Assets:Account2       5 HOTEL @ 300 EUR

        2014-02-01 price HOUSE    130 USD
        2014-02-01 price MANSION  180 EUR
        2014-02-01 price HOTEL    330 USD
        """
        new_entries, _ = unrealized_periodic.add_unrealized_gains(
            entries, options_map)

        self.assertEqual(
            2, len(unrealized_periodic.get_unrealized_entries(new_entries)))

        house = get_entries_with_narration(new_entries, "units of HOUSE")[0]
        self.assertEqual(2, len(house.postings))
        self.assertEqual(D('350'), house.postings[0].units.number)
        self.assertEqual('Assets:Account1', house.postings[0].account)
        self.assertEqual('Income:Account1', house.postings[1].account)

        mansion = get_entries_with_narration(new_entries,
                                             "units of MANSION")[0]
        self.assertEqual(2, len(mansion.postings))
        self.assertEqual(D('-100'), mansion.postings[0].units.number)
Example #9
0
    def test_nothing_held_at_cost(self, entries, _, options_map):
        """
        2014-01-01 open Assets:Account1
        2014-01-01 open Assets:Account2
        2014-01-01 open Income:Misc

        2014-01-15 *
          Income:Misc           -1000 USD
          Assets:Account1

        2014-01-16 *
          Income:Misc           -1000 EUR
          Assets:Account2

        2014-02-01 price EUR  1.34 USD
        """
        new_entries, _ = unrealized_periodic.add_unrealized_gains(
            entries, options_map)
        self.assertEqual(new_entries, entries)
        self.assertEqual(
            [], unrealized_periodic.get_unrealized_entries(new_entries))
Example #10
0
    def test_with_subaccount(self, entries, _, options_map):
        """
        2014-01-01 open Assets:Account1
        2014-01-01 open Income:Misc

        2014-01-15 *
          Income:Misc
          Assets:Account1       10 HOUSE {100 USD}

        2014-01-15 price HOUSE  101 USD
        """
        entries, errors = unrealized_periodic.add_unrealized_gains(
            entries, options_map, '_invalid_')
        self.assertEqual([unrealized_periodic.UnrealizedError],
                         list(map(type, errors)))

        new_entries, _ = unrealized_periodic.add_unrealized_gains(
            entries, options_map, 'Gains')
        entries = unrealized_periodic.get_unrealized_entries(new_entries)
        entry = entries[0]
        self.assertEqual('Assets:Account1:Gains', entry.postings[0].account)
        self.assertEqual('Income:Account1:Gains', entry.postings[1].account)
Example #11
0
    def test_clear_then_new(self, entries, _, options_map):
        """
        2014-01-01 open Assets:Account1
        2014-01-01 open Assets:Cash
        2014-01-01 open Income:Misc
        2014-01-01 open Income:PnL

        2014-01-15 *
          Income:Misc           -1000 USD
          Assets:Account1       10 HOUSE {100 USD}

        2014-01-15 price HOUSE  100 USD
        2014-01-20 price HOUSE  120 USD

        2014-02-10 *
          Assets:Cash           3000 USD
          Assets:Account1       -10 HOUSE {100 USD}
          Income:PnL            -2000 USD

        2014-03-15 *
          Income:Misc           -1000 USD
          Assets:Account1       10 HOUSE {100 USD}

        2014-03-15 price HOUSE  100 USD
        2014-04-15 price HOUSE  120 USD

        """
        # We should have a profit, then clear, then profit
        new_entries, _ = unrealized_periodic.add_unrealized_gains(
            entries, options_map)
        unreal_entries = unrealized_periodic.get_unrealized_entries(
            new_entries)
        self.assertEqual(3, len(unreal_entries))
        for target, actual in zip([(None, D('200')), (None, D('-200')),
                                   (None, D('200'))], unreal_entries):
            if target[0] is not None:
                self.assertEqual(target[0], actual.postings[2].units.number)
            self.assertEqual(target[1], actual.postings[0].units.number)
Example #12
0
    def test_relative_gain_loss(self, entries, _, options_map):
        """
        2014-01-01 open Assets:Account1
        2014-01-01 open Income:Misc

        2014-01-15 *
          Income:Misc           -1000 USD
          Assets:Account1       10 HOUSE {100 USD}

        2014-01-15 price HOUSE  100 USD
        2014-01-20 price HOUSE  150 USD ; Actual gain/Relative gain
        2014-02-25 price HOUSE  140 USD ; Actual gain/Relative loss
        2014-03-25 price HOUSE  50 USD  ; Actual loss/Relative loss
        2014-04-25 price HOUSE  70 USD  ; Actual loss/Relative gain
        """
        new_entries, _ = unrealized_periodic.add_unrealized_gains(
            entries, options_map)
        unreal_entries = unrealized_periodic.get_unrealized_entries(
            new_entries)
        self.assertEqual(4, len(unreal_entries))
        for target, actual in zip(['gain', 'loss', 'loss', 'gain'],
                                  unreal_entries):
            self.assertTrue(actual.narration.startswith('Unrealized ' +
                                                        target))