class TestProfitLossBuying(unittest.TestCase):
    """
    Tests that the unrealised and realised pnls are
    working after position initialization, every
    transaction, and every price update
    """
    def setUp(self):
        self.position = Position("BOT", "XOM", 100, PriceParser.parse(74.78),
                                 PriceParser.parse(1.00),
                                 PriceParser.parse(74.77),
                                 PriceParser.parse(74.79))

    def test_realised_unrealised_calcs(self):
        self.assertEqual(PriceParser.display(self.position.unrealised_pnl),
                         -1.00)
        self.assertEqual(PriceParser.display(self.position.realised_pnl), 0.00)

        self.position.update_market_value(PriceParser.parse(75.77),
                                          PriceParser.parse(75.79))
        self.assertEqual(PriceParser.display(self.position.unrealised_pnl),
                         99.00)
        self.position.transact_shares("SLD", 100, PriceParser.parse(75.78),
                                      PriceParser.parse(1.00))
        self.assertEqual(PriceParser.display(self.position.unrealised_pnl),
                         99.00)  # still high
        self.assertEqual(PriceParser.display(self.position.realised_pnl),
                         98.00)

        self.position.update_market_value(PriceParser.parse(75.77),
                                          PriceParser.parse(75.79))
        self.assertEqual(PriceParser.display(self.position.unrealised_pnl),
                         0.00)
Пример #2
0
class TestRoundTripPGPosition(unittest.TestCase):
    """
    Test a round-trip trade in Proctor & Gamble where the initial
    trade is a sell/short of 100 shares of PG, at a price of
    $77.69, with $1.00 commission.
    """
    def setUp(self):
        self.position = Position("SLD", "PG", 100, PriceParser.parse(77.69),
                                 PriceParser.parse(1.00),
                                 PriceParser.parse(77.68),
                                 PriceParser.parse(77.70))

    def test_calculate_round_trip(self):
        """
        After the subsequent sale, carry out two more sells/shorts
        and then close the position out with two additional buys/longs.

        The following prices have been tested against those calculated
        via Interactive Brokers' Trader Workstation (TWS).
        """
        self.position.transact_shares("SLD", 100, PriceParser.parse(77.68),
                                      PriceParser.parse(1.00))
        self.position.transact_shares("SLD", 50, PriceParser.parse(77.70),
                                      PriceParser.parse(1.00))
        self.position.transact_shares("BOT", 100, PriceParser.parse(77.77),
                                      PriceParser.parse(1.00))
        self.position.transact_shares("BOT", 150, PriceParser.parse(77.73),
                                      PriceParser.parse(1.00))
        self.position.update_market_value(PriceParser.parse(77.72),
                                          PriceParser.parse(77.72))

        self.assertEqual(self.position.action, "SLD")
        self.assertEqual(self.position.ticker, "PG")
        self.assertEqual(self.position.quantity, 0)

        self.assertEqual(self.position.buys, 250)
        self.assertEqual(self.position.sells, 250)
        self.assertEqual(self.position.net, 0)
        self.assertEqual(PriceParser.display(self.position.avg_bot, 3), 77.746)
        self.assertEqual(PriceParser.display(self.position.avg_sld, 3), 77.688)
        self.assertEqual(PriceParser.display(self.position.total_bot),
                         19436.50)
        self.assertEqual(PriceParser.display(self.position.total_sld),
                         19422.00)
        self.assertEqual(PriceParser.display(self.position.net_total), -14.50)
        self.assertEqual(PriceParser.display(self.position.total_commission),
                         5.00)
        self.assertEqual(PriceParser.display(self.position.net_incl_comm),
                         -19.50)

        self.assertEqual(PriceParser.display(self.position.avg_price, 5),
                         77.67600)
        self.assertEqual(PriceParser.display(self.position.cost_basis), 0.00)
        self.assertEqual(PriceParser.display(self.position.market_value), 0.00)
        self.assertEqual(PriceParser.display(self.position.unrealised_pnl),
                         0.00)
        self.assertEqual(PriceParser.display(self.position.realised_pnl),
                         -19.50)
Пример #3
0
class TestRoundTripXOMPosition(unittest.TestCase):
    """
    Test a round-trip trade in Exxon-Mobil where the initial
    trade is a buy/long of 100 shares of XOM, at a price of
    $74.78, with $1.00 commission.
    """
    def setUp(self):
        """
        Set up the Position object that will store the PnL.
        """
        self.position = Position(
            "BOT", "XOM", Decimal('100'),
            Decimal("74.78"), Decimal("1.00"),
            Decimal('74.78'), Decimal('74.80')
        )

    def test_calculate_round_trip(self):
        """
        After the subsequent purchase, carry out two more buys/longs
        and then close the position out with two additional sells/shorts.

        The following prices have been tested against those calculated
        via Interactive Brokers' Trader Workstation (TWS).
        """
        self.position.transact_shares(
            "BOT", Decimal('100'), Decimal('74.63'), Decimal('1.00')
        )
        self.position.transact_shares(
            "BOT", Decimal('250'), Decimal('74.620'), Decimal('1.25')
        )
        self.position.transact_shares(
            "SLD", Decimal('200'), Decimal('74.58'), Decimal('1.00')
        )
        self.position.transact_shares(
            "SLD", Decimal('250'), Decimal('75.26'), Decimal('1.25')
        )
        self.position.update_market_value(Decimal("77.75"), Decimal("77.77"))

        self.assertEqual(self.position.action, "BOT")
        self.assertEqual(self.position.ticker, "XOM")
        self.assertEqual(self.position.quantity, Decimal("0"))

        self.assertEqual(self.position.buys, Decimal("450"))
        self.assertEqual(self.position.sells, Decimal("450"))
        self.assertEqual(self.position.net, Decimal("0"))
        self.assertEqual(self.position.avg_bot, Decimal("74.65778"))
        self.assertEqual(self.position.avg_sld, Decimal("74.95778"))
        self.assertEqual(self.position.total_bot, Decimal("33596.00"))
        self.assertEqual(self.position.total_sld, Decimal("33731.00"))
        self.assertEqual(self.position.net_total, Decimal("135.00"))
        self.assertEqual(self.position.total_commission, Decimal("5.50"))
        self.assertEqual(self.position.net_incl_comm, Decimal("129.50"))

        self.assertEqual(self.position.avg_price, Decimal("74.665"))
        self.assertEqual(self.position.cost_basis, Decimal("0.00"))
        self.assertEqual(self.position.market_value, Decimal("0.00"))
        self.assertEqual(self.position.unrealised_pnl, Decimal("0.00"))
        self.assertEqual(self.position.realised_pnl, Decimal("129.50"))
Пример #4
0
class TestRoundTripPGPosition(unittest.TestCase):
    """
    Test a round-trip trade in Proctor & Gamble where the initial
    trade is a sell/short of 100 shares of PG, at a price of
    $77.69, with $1.00 commission.
    """
    def setUp(self):
        self.position = Position(
            "SLD", "PG", Decimal('100'),
            Decimal("77.69"), Decimal("1.00"),
            Decimal('77.68'), Decimal('77.70')
        )

    def test_calculate_round_trip(self):
        """
        After the subsequent sale, carry out two more sells/shorts
        and then close the position out with two additional buys/longs.

        The following prices have been tested against those calculated
        via Interactive Brokers' Trader Workstation (TWS).
        """
        self.position.transact_shares(
            "SLD", Decimal('100'), Decimal('77.68'), Decimal('1.00')
        )
        self.position.transact_shares(
            "SLD", Decimal('50'), Decimal('77.70'), Decimal('1.00')
        )
        self.position.transact_shares(
            "BOT", Decimal('100'), Decimal('77.77'), Decimal('1.00')
        )
        self.position.transact_shares(
            "BOT", Decimal('150'), Decimal('77.73'), Decimal('1.00')
        )
        self.position.update_market_value(Decimal("77.72"), Decimal("77.72"))

        self.assertEqual(self.position.action, "SLD")
        self.assertEqual(self.position.ticker, "PG")
        self.assertEqual(self.position.quantity, Decimal("0"))

        self.assertEqual(self.position.buys, Decimal("250"))
        self.assertEqual(self.position.sells, Decimal("250"))
        self.assertEqual(self.position.net, Decimal("0"))
        self.assertEqual(self.position.avg_bot, Decimal("77.746"))
        self.assertEqual(self.position.avg_sld, Decimal("77.688"))
        self.assertEqual(self.position.total_bot, Decimal("19436.50"))
        self.assertEqual(self.position.total_sld, Decimal("19422.00"))
        self.assertEqual(self.position.net_total, Decimal("-14.50"))
        self.assertEqual(self.position.total_commission, Decimal("5.00"))
        self.assertEqual(self.position.net_incl_comm, Decimal("-19.50"))

        self.assertEqual(self.position.avg_price, Decimal("77.67600"))
        self.assertEqual(self.position.cost_basis, Decimal("0.00"))
        self.assertEqual(self.position.market_value, Decimal("0.00"))
        self.assertEqual(self.position.unrealised_pnl, Decimal("0.00"))
        self.assertEqual(self.position.realised_pnl, Decimal("-19.50"))
Пример #5
0
class TestProfitLossBuying(unittest.TestCase):
    """
    Tests that the unrealised and realised pnls are
    working after position initialization, every
    transaction, and every price update
    """
    def setUp(self):
        self.position = Position(
            "BOT", "XOM", 100,
            PriceParser.parse(74.78), PriceParser.parse(1.00),
            PriceParser.parse(74.77), PriceParser.parse(74.79)
        )

    def test_realised_unrealised_calcs(self):
        self.assertEqual(
            PriceParser.display(self.position.unrealised_pnl), -1.00
        )
        self.assertEqual(
            PriceParser.display(self.position.realised_pnl), 0.00
        )

        self.position.update_market_value(
            PriceParser.parse(75.77), PriceParser.parse(75.79)
        )
        self.assertEqual(
            PriceParser.display(self.position.unrealised_pnl), 99.00
        )
        self.position.transact_shares(
            "SLD", 100,
            PriceParser.parse(75.78), PriceParser.parse(1.00)
        )
        self.assertEqual(
            PriceParser.display(self.position.unrealised_pnl), 99.00
        )  # still high
        self.assertEqual(
            PriceParser.display(self.position.realised_pnl), 98.00
        )

        self.position.update_market_value(
            PriceParser.parse(75.77), PriceParser.parse(75.79)
        )
        self.assertEqual(
            PriceParser.display(self.position.unrealised_pnl), 0.00
        )
Пример #6
0
class TestRoundTripXOMPosition(unittest.TestCase):
    """
    Test a round-trip trade in Exxon-Mobil where the initial
    trade is a buy/long of 100 shares of XOM, at a price of
    $74.78, with $1.00 commission.
    """
    def setUp(self):
        """
        Set up the Position object that will store the PnL.
        """
        self.position = Position("BOT", "XOM", 100, PriceParser.parse(74.78),
                                 PriceParser.parse(1.00),
                                 PriceParser.parse(74.78),
                                 PriceParser.parse(74.80))

    def test_calculate_round_trip(self):
        """
        After the subsequent purchase, carry out two more buys/longs
        and then close the position out with two additional sells/shorts.

        The following prices have been tested against those calculated
        via Interactive Brokers' Trader Workstation (TWS).
        """
        self.position.transact_shares("BOT", 100, PriceParser.parse(74.63),
                                      PriceParser.parse(1.00))
        self.position.transact_shares("BOT", 250, PriceParser.parse(74.620),
                                      PriceParser.parse(1.25))
        self.position.transact_shares("SLD", 200, PriceParser.parse(74.58),
                                      PriceParser.parse(1.00))
        self.position.transact_shares("SLD", 250, PriceParser.parse(75.26),
                                      PriceParser.parse(1.25))
        self.position.update_market_value(PriceParser.parse(77.75),
                                          PriceParser.parse(77.77))

        self.assertEqual(self.position.action, "BOT")
        self.assertEqual(self.position.ticker, "XOM")
        self.assertEqual(self.position.quantity, 0)

        self.assertEqual(self.position.buys, 450)
        self.assertEqual(self.position.sells, 450)
        self.assertEqual(self.position.net, 0)
        self.assertEqual(PriceParser.display(self.position.avg_bot, 5),
                         74.65778)
        self.assertEqual(PriceParser.display(self.position.avg_sld, 5),
                         74.95778)
        self.assertEqual(PriceParser.display(self.position.total_bot),
                         33596.00)
        self.assertEqual(PriceParser.display(self.position.total_sld),
                         33731.00)
        self.assertEqual(PriceParser.display(self.position.net_total), 135.00)
        self.assertEqual(PriceParser.display(self.position.total_commission),
                         5.50)
        self.assertEqual(PriceParser.display(self.position.net_incl_comm),
                         129.50)

        self.assertEqual(PriceParser.display(self.position.avg_price, 3),
                         74.665)
        self.assertEqual(PriceParser.display(self.position.cost_basis), 0.00)
        self.assertEqual(PriceParser.display(self.position.market_value), 0.00)
        self.assertEqual(PriceParser.display(self.position.unrealised_pnl),
                         0.00)
        self.assertEqual(PriceParser.display(self.position.realised_pnl),
                         129.50)
Пример #7
0
class TestRoundTripPGPosition(unittest.TestCase):
    """
    Test a round-trip trade in Proctor & Gamble where the initial
    trade is a sell/short of 100 shares of PG, at a price of
    $77.69, with $1.00 commission.
    """
    def setUp(self):
        self.position = Position(
            "SLD", "PG", 100,
            PriceParser.parse(77.69), PriceParser.parse(1.00),
            PriceParser.parse(77.68), PriceParser.parse(77.70)
        )

    def test_calculate_round_trip(self):
        """
        After the subsequent sale, carry out two more sells/shorts
        and then close the position out with two additional buys/longs.

        The following prices have been tested against those calculated
        via Interactive Brokers' Trader Workstation (TWS).
        """
        self.position.transact_shares(
            "SLD", 100, PriceParser.parse(77.68), PriceParser.parse(1.00)
        )
        self.position.transact_shares(
            "SLD", 50, PriceParser.parse(77.70), PriceParser.parse(1.00)
        )
        self.position.transact_shares(
            "BOT", 100, PriceParser.parse(77.77), PriceParser.parse(1.00)
        )
        self.position.transact_shares(
            "BOT", 150, PriceParser.parse(77.73), PriceParser.parse(1.00)
        )
        self.position.update_market_value(
            PriceParser.parse(77.72), PriceParser.parse(77.72)
        )

        self.assertEqual(self.position.action, "SLD")
        self.assertEqual(self.position.ticker, "PG")
        self.assertEqual(self.position.quantity, 0)

        self.assertEqual(self.position.buys, 250)
        self.assertEqual(self.position.sells, 250)
        self.assertEqual(self.position.net, 0)
        self.assertEqual(
            PriceParser.display(self.position.avg_bot, 3), 77.746
        )
        self.assertEqual(
            PriceParser.display(self.position.avg_sld, 3), 77.688
        )
        self.assertEqual(PriceParser.display(self.position.total_bot), 19436.50)
        self.assertEqual(PriceParser.display(self.position.total_sld), 19422.00)
        self.assertEqual(PriceParser.display(self.position.net_total), -14.50)
        self.assertEqual(PriceParser.display(self.position.total_commission), 5.00)
        self.assertEqual(PriceParser.display(self.position.net_incl_comm), -19.50)

        self.assertEqual(
            PriceParser.display(self.position.avg_price, 5), 77.67600
        )
        self.assertEqual(PriceParser.display(self.position.cost_basis), 0.00)
        self.assertEqual(PriceParser.display(self.position.market_value), 0.00)
        self.assertEqual(PriceParser.display(self.position.unrealised_pnl), 0.00)
        self.assertEqual(PriceParser.display(self.position.realised_pnl), -19.50)
Пример #8
0
class TestRoundTripXOMPosition(unittest.TestCase):
    """
    Test a round-trip trade in Exxon-Mobil where the initial
    trade is a buy/long of 100 shares of XOM, at a price of
    $74.78, with $1.00 commission.
    """
    def setUp(self):
        """
        Set up the Position object that will store the PnL.
        """
        self.position = Position(
            "BOT", "XOM", 100,
            PriceParser.parse(74.78), PriceParser.parse(1.00),
            PriceParser.parse(74.78), PriceParser.parse(74.80)
        )

    def test_calculate_round_trip(self):
        """
        After the subsequent purchase, carry out two more buys/longs
        and then close the position out with two additional sells/shorts.

        The following prices have been tested against those calculated
        via Interactive Brokers' Trader Workstation (TWS).
        """
        self.position.transact_shares(
            "BOT", 100, PriceParser.parse(74.63), PriceParser.parse(1.00)
        )
        self.position.transact_shares(
            "BOT", 250, PriceParser.parse(74.620), PriceParser.parse(1.25)
        )
        self.position.transact_shares(
            "SLD", 200, PriceParser.parse(74.58), PriceParser.parse(1.00)
        )
        self.position.transact_shares(
            "SLD", 250, PriceParser.parse(75.26), PriceParser.parse(1.25)
        )
        self.position.update_market_value(
            PriceParser.parse(77.75), PriceParser.parse(77.77)
        )

        self.assertEqual(self.position.action, "BOT")
        self.assertEqual(self.position.ticker, "XOM")
        self.assertEqual(self.position.quantity, 0)

        self.assertEqual(self.position.buys, 450)
        self.assertEqual(self.position.sells, 450)
        self.assertEqual(self.position.net, 0)
        self.assertEqual(
            PriceParser.display(self.position.avg_bot, 5), 74.65778
        )
        self.assertEqual(
            PriceParser.display(self.position.avg_sld, 5), 74.95778
        )
        self.assertEqual(PriceParser.display(self.position.total_bot), 33596.00)
        self.assertEqual(PriceParser.display(self.position.total_sld), 33731.00)
        self.assertEqual(PriceParser.display(self.position.net_total), 135.00)
        self.assertEqual(PriceParser.display(self.position.total_commission), 5.50)
        self.assertEqual(PriceParser.display(self.position.net_incl_comm), 129.50)

        self.assertEqual(
            PriceParser.display(self.position.avg_price, 3), 74.665
        )
        self.assertEqual(PriceParser.display(self.position.cost_basis), 0.00)
        self.assertEqual(PriceParser.display(self.position.market_value), 0.00)
        self.assertEqual(PriceParser.display(self.position.unrealised_pnl), 0.00)
        self.assertEqual(PriceParser.display(self.position.realised_pnl), 129.50)