def test_market_accept_bid_yields_partial_bid_trade(market: TwoSidedPayAsBid): bid = market.bid(2.0, 4, 'buyer', 'seller') trade = market.accept_bid(bid, energy=1, seller='seller', trade_offer_info=[2, 2, 1, 1, 2]) assert trade.offer.id == bid.id and trade.offer.energy == 1
def test_market_trade_bid_not_found(market: TwoSidedPayAsBid): bid = market.bid(20, 10, 'A', 'B') assert market.accept_bid(bid, 10, 'B') with pytest.raises(BidNotFound): market.accept_bid(bid, 10, 'B')
def test_market_accept_bid_always_updates_trade_stats(market: TwoSidedPayAsBid, called, market_method): setattr(market, market_method, called) bid = market.bid(20, 20, 'A', 'B') trade = market.accept_bid(bid, energy=5, seller='B', already_tracked=False) assert trade assert len(getattr(market, market_method).calls) == 1
def setUp(self): self.area = Area(name="test_area") self.parent_area = Area(name="parent_area") self.test_market = TwoSidedPayAsBid(name="test_market") self.parent_area._markets.markets = {1: self.test_market} self.area.parent = self.parent_area self.external_strategy = ExternalStrategy(self.area) self.external_redis = self.external_strategy.redis
def test_market_trade_partial_bid_invalid(market: TwoSidedPayAsBid, energy): bid = market.bid(20, 20, 'A', 'B') with pytest.raises(InvalidTrade): market.accept_bid(bid, energy=energy, seller='A', trade_offer_info=[1, 1, 1, 1, 1])
def setUp(self): ConstSettings.IAASettings.MARKET_TYPE = 1 self.area = Area(name="test_area") self.parent_area = Area(name="parent_area") self.test_market = TwoSidedPayAsBid(name="test_market") self.parent_area._markets.markets = {1: self.test_market} self.area.parent = self.parent_area self.external_strategy = ExternalStrategy(self.area) self.external_redis = self.external_strategy.redis
def test_market_bid_trade(market: TwoSidedPayAsBid): bid = market.bid(20, 10, 'A', 'B') trade = market.accept_bid(bid, energy=10, seller='B') assert trade assert trade == market.trades[0] assert trade.id assert trade.offer is bid assert trade.seller == 'B' assert trade.buyer == 'A' assert not trade.residual
def test_market_accept_bid_does_not_emit_bid_deleted_on_partial_bid(market: TwoSidedPayAsBid, called): market.add_listener(called) bid = market.bid(20, 20, 'A', 'B') trade = market.accept_bid(bid, energy=1) assert all([ev != repr(MarketEvent.BID_DELETED) for c in called.calls for ev in c[0]]) assert len(called.calls) == 1 assert called.calls[0][0] == (repr(MarketEvent.BID_TRADED), ) assert called.calls[0][1] == { 'market_id': repr(market.id), 'bid_trade': repr(trade), }
def test_market_bid_trade(market: TwoSidedPayAsBid): bid = market.bid(20, 10, 'A', 'B', original_bid_price=20) trade = market.accept_bid(bid, energy=10, seller='B', trade_offer_info=[2, 2, 0.5, 0.5, 2]) assert trade assert trade.id == market.trades[0].id assert trade.id assert trade.offer.price == bid.price assert trade.offer.energy == bid.energy assert trade.seller == 'B' assert trade.buyer == 'A' assert not trade.residual
def test_market_trade_bid_not_found(market=TwoSidedPayAsBid(time_slot=now())): bid = market.bid(20, 10, 'A', 'B', 'A') assert market.accept_bid(bid, 10, 'B', trade_offer_info=[2, 2, 1, 1, 2]) with pytest.raises(BidNotFound): market.accept_bid(bid, 10, 'B', trade_offer_info=[2, 2, 1, 1, 2])
def test_market_accept_bid_emits_bid_traded_and_bid_deleted_event(market: TwoSidedPayAsBid, called): market.add_listener(called) bid = market.bid(20, 20, 'A', 'B') trade = market.accept_bid(bid) assert len(called.calls) == 2 assert called.calls[0][0] == (repr(MarketEvent.BID_TRADED), ) assert called.calls[1][0] == (repr(MarketEvent.BID_DELETED), ) assert called.calls[0][1] == { 'market_id': repr(market.id), 'bid_trade': repr(trade), } assert called.calls[1][1] == { 'market_id': repr(market.id), 'bid': repr(bid), }
def test_market_bid(market: TwoSidedPayAsBid): bid = market.bid(1, 2, 'bidder', 'seller', 'bidder') assert market.bids[bid.id] == bid assert bid.price == 1 assert bid.energy == 2 assert bid.buyer == 'bidder' assert bid.seller == 'seller' assert len(bid.id) == 36
def test_market_bid_accepts_bid_id(market: TwoSidedPayAsBid): bid = market.bid(1, 2, 'bidder', 'seller', 'bidder', bid_id='123') assert market.bids['123'] == bid assert bid.id == '123' assert bid.price == 1 assert bid.energy == 2 assert bid.buyer == 'bidder' assert bid.seller == 'seller' # Update existing bid is tested here bid = market.bid(3, 4, 'updated_bidder', 'updated_seller', 'updated_bidder', bid_id='123') assert market.bids['123'] == bid assert bid.id == '123' assert isclose(bid.price, 3) assert bid.energy == 4 assert bid.buyer == 'updated_bidder' assert bid.seller == 'updated_seller'
def test_market_accept_bid_always_updates_trade_stats( called, market_method, market=TwoSidedPayAsBid(time_slot=now())): setattr(market, market_method, called) bid = market.bid(20, 20, 'A', 'B', 'A') trade = market.accept_bid(bid, energy=5, seller='B', trade_offer_info=[1, 1, 1, 1, 1]) assert trade assert len(getattr(market, market_method).calls) == 1
def test_market_trade_partial_bid_invalid( energy, market=TwoSidedPayAsBid(time_slot=DateTime.now())): bid = market.bid(20, 20, 'A', 'B', 'A') with pytest.raises(InvalidTrade): market.accept_bid(bid, energy=energy, seller='A', trade_offer_info=[1, 1, 1, 1, 1])
def test_market_trade_bid_partial(market: TwoSidedPayAsBid): bid = market.bid(20, 20, 'A', 'B') trade = market.accept_bid(bid, energy=5, seller='B') assert trade assert trade == market.trades[0] assert trade.id assert trade.offer is not bid assert trade.offer.energy == 5 assert trade.offer.price == 5 assert trade.offer.seller == 'B' assert trade.seller == 'B' assert trade.buyer == 'A' assert trade.residual assert len(market.bids) == 1 assert bid.id in market.bids assert market.bids[bid.id].energy == 15 assert market.bids[bid.id].price == 15 assert market.bids[bid.id].seller == 'B' assert market.bids[bid.id].buyer == 'A'
def test_market_accept_bid_emits_bid_split_on_partial_bid( called, market=TwoSidedPayAsBid(time_slot=now())): market.add_listener(called) bid = market.bid(20, 20, 'A', 'B', 'A') trade = market.accept_bid(bid, energy=1, trade_offer_info=[1, 1, 1, 1, 1]) assert all([ev != repr(MarketEvent.BID_DELETED) for c in called.calls for ev in c[0]]) assert len(called.calls) == 2 assert called.calls[0][0] == (repr(MarketEvent.BID_SPLIT),) assert called.calls[1][0] == (repr(MarketEvent.BID_TRADED),) assert called.calls[1][1] == { 'market_id': repr(market.id), 'bid_trade': repr(trade), }
def test_market_trade_bid_partial(market: TwoSidedPayAsBid): bid = market.bid(20, 20, 'A', 'B', original_bid_price=20) trade = market.accept_bid(bid, energy=5, seller='B', trade_offer_info=[1, 1, 1, 1, 1]) assert trade assert trade.id == market.trades[0].id assert trade.id assert trade.offer is not bid assert trade.offer.energy == 5 assert trade.offer.price == 5 assert trade.offer.seller == 'B' assert trade.seller == 'B' assert trade.buyer == 'A' assert trade.residual assert len(market.bids) == 1 assert trade.residual.id in market.bids assert market.bids[trade.residual.id].energy == 15 assert isclose(market.bids[trade.residual.id].price, 15) assert market.bids[trade.residual.id].seller == 'B' assert market.bids[trade.residual.id].buyer == 'A'
def test_market_accept_bid_emits_bid_traded_and_bid_deleted_event( called, market=TwoSidedPayAsBid(time_slot=DateTime.now())): market.add_listener(called) bid = market.bid(20, 20, 'A', 'B') trade = market.accept_bid(bid, trade_offer_info=[1, 1, 1, 1, 1]) assert len(called.calls) == 2 assert called.calls[0][0] == (repr(MarketEvent.BID_TRADED), ) assert called.calls[1][0] == (repr(MarketEvent.BID_DELETED), ) assert called.calls[0][1] == { 'market_id': repr(market.id), 'bid_trade': repr(trade), } assert called.calls[1][1] == { 'market_id': repr(market.id), 'bid': repr(bid), }
def market(): return TwoSidedPayAsBid()
assert bid.buyer == 'updated_bidder' assert bid.seller == 'updated_seller' def test_market_offer_invalid(market: OneSidedMarket): with pytest.raises(InvalidOffer): market.offer(10, -1, 'someone', 'someone') def test_market_bid_invalid(market: TwoSidedPayAsBid): with pytest.raises(InvalidBid): market.bid(10, -1, 'someone', 'noone', 'someone') @pytest.mark.parametrize("market, offer", [(TwoSidedPayAsBid(), "offer"), (BalancingMarket(), "balancing_offer")]) def test_market_offer_readonly(market, offer): market.readonly = True with pytest.raises(MarketReadOnlyException): getattr(market, offer)(10, 10, 'A', 'A') @pytest.mark.parametrize( "market, offer", [(TwoSidedPayAsBid(time_slot=DateTime.now()), "offer"), (BalancingMarket(time_slot=DateTime.now()), "balancing_offer")]) def test_market_offer_delete(market, offer): offer = getattr(market, offer)(20, 10, 'someone', 'someone') market.delete_offer(offer)
def market(): return TwoSidedPayAsBid(time_slot=now())
class TestExternalStrategy(unittest.TestCase): def setUp(self): ConstSettings.IAASettings.MARKET_TYPE = 1 self.area = Area(name="test_area") self.parent_area = Area(name="parent_area") self.test_market = TwoSidedPayAsBid(name="test_market", time_slot=now()) self.parent_area._markets.markets = {1: self.test_market} self.area.parent = self.parent_area self.external_strategy = ExternalStrategy(self.area) self.external_redis = self.external_strategy.redis def tearDown(self): ConstSettings.IAASettings.MARKET_TYPE = 1 @parameterized.expand([(2, ), (3, )]) def test_sub_to_external_requests_exposes_correct_channels_two_sided_market( self, market_type): ConstSettings.IAASettings.MARKET_TYPE = market_type self.external_strategy2 = ExternalStrategy(self.area) self.external_strategy2.redis.redis_db.sub_to_multiple_channels.assert_called_once_with( { "parent-area/test-area/offer": self.external_strategy2.redis._offer, "parent-area/test-area/delete_offer": self.external_strategy2.redis._delete_offer, "parent-area/test-area/delete_bid": self.external_strategy2.redis._delete_bid, "parent-area/test-area/bid": self.external_strategy2.redis._bid, "parent-area/test-area/bids": self.external_strategy2.redis._list_bids, "parent-area/test-area/offers": self.external_strategy2.redis._offer_lists }) def test_sub_to_external_requests_exposes_correct_channels_one_sided_market( self): self.external_redis.redis_db.sub_to_multiple_channels.assert_called_once_with( { "parent-area/test-area/offer": self.external_redis._offer, "parent-area/test-area/delete_offer": self.external_redis._delete_offer, "parent-area/test-area/accept_offer": self.external_redis._accept_offer, "parent-area/test-area/offers": self.external_redis._offer_lists }) def _assert_dict_is_the_same_as_offer(self, offer_dict, offer): assert offer.id == offer_dict["id"] assert offer.price == offer_dict["price"] assert offer.energy == offer_dict["energy"] def test_list_offers(self): offer1 = self.test_market.offer(1, 2, "A", "A") offer2 = self.test_market.offer(2, 3, "B", "B") offer3 = self.test_market.offer(3, 4, "C", "C") self.external_redis._offer_lists("") self.external_redis.redis_db.publish.assert_called_once() assert self.external_redis.redis_db.publish.call_args_list[0][0][0] == \ "parent-area/test-area/offers/response" response_payload = json.loads( self.external_redis.redis_db.publish.call_args_list[0][0][1]) offers_dict = response_payload["offer_list"] assert len(offers_dict) == 3 self._assert_dict_is_the_same_as_offer(offers_dict[0], offer1) self._assert_dict_is_the_same_as_offer(offers_dict[1], offer2) self._assert_dict_is_the_same_as_offer(offers_dict[2], offer3) @parameterized.expand([(2, ), (3, )]) def test_list_offers_two_sided(self, market_type): ConstSettings.IAASettings.MARKET_TYPE = market_type offer1 = self.test_market.offer(1, 2, "test_area", "test_area") offer2 = self.test_market.offer(2, 3, "test_area", "test_area") self.test_market.offer(3, 4, "C", "C") self.external_redis._offer_lists("") self.external_redis.redis_db.publish.assert_called_once() assert self.external_redis.redis_db.publish.call_args_list[0][0][0] == \ "parent-area/test-area/offers/response" response_payload = json.loads( self.external_redis.redis_db.publish.call_args_list[0][0][1]) offers_dict = response_payload["offer_list"] assert len(offers_dict) == 2 self._assert_dict_is_the_same_as_offer(offers_dict[0], offer1) self._assert_dict_is_the_same_as_offer(offers_dict[1], offer2) def test_offer(self): payload = {"data": json.dumps({"energy": 22, "price": 54})} self.external_redis._offer(payload) assert len(self.test_market.offers) == 1 offer = list(self.test_market.offers.values())[0] assert offer.price == 54 assert offer.energy == 22 assert offer.seller == "test_area" market_offer_json = offer.to_JSON_string() self.external_redis.redis_db.publish.assert_called_once() assert self.external_redis.redis_db.publish.call_args_list[0][0][0] == \ "parent-area/test-area/offer/response" response_payload = json.loads( self.external_redis.redis_db.publish.call_args_list[0][0][1]) assert response_payload["offer"] == market_offer_json def test_delete_offer(self): offer1 = self.test_market.offer(1, 2, "A", "A") payload = {"data": json.dumps({"offer": offer1.to_JSON_string()})} self.external_redis._delete_offer(payload) assert len(self.test_market.offers) == 0 self.external_redis.redis_db.publish.assert_called_once() assert self.external_redis.redis_db.publish.call_args_list[0][0][0] == \ "parent-area/test-area/delete_offer/response" def test_accept_offer(self): offer1 = self.test_market.offer(1, 2, "A", "A") payload = {"data": json.dumps({"offer": offer1.to_JSON_string()})} self.external_redis._accept_offer(payload) assert len(self.test_market.trades) == 1 trade = self.test_market.trades[0] assert len(self.test_market.offers) == 0 self.external_redis.redis_db.publish.assert_called_once() assert self.external_redis.redis_db.publish.call_args_list[0][0][0] == \ "parent-area/test-area/accept_offer/response" response_payload = json.loads( self.external_redis.redis_db.publish.call_args_list[0][0][1]) assert response_payload["trade"] == trade.to_JSON_string() def test_bid(self): payload = {"data": json.dumps({"energy": 12, "price": 32})} self.external_redis._bid(payload) assert len(self.test_market.bids) == 1 bid = list(self.test_market.bids.values())[0] assert bid.price == 32 assert bid.energy == 12 assert bid.buyer == "test_area" assert bid.seller == "parent_area" self.external_redis.redis_db.publish.assert_called_once() assert self.external_redis.redis_db.publish.call_args_list[0][0][0] == \ "parent-area/test-area/bid/response" response_payload = json.loads( self.external_redis.redis_db.publish.call_args_list[0][0][1]) assert response_payload["bid"] == bid.to_JSON_string() def test_delete_bid(self): bid1 = self.test_market.bid(1, 2, "B", "C", "B") payload = {"data": json.dumps({"bid": bid1.id})} self.external_redis._delete_bid(payload) assert len(self.test_market.bids) == 0 self.external_redis.redis_db.publish.assert_called_once() assert self.external_redis.redis_db.publish.call_args_list[0][0][0] == \ "parent-area/test-area/delete_bid/response" @parameterized.expand([(2, ), (3, )]) def test_list_bids(self, market_type): ConstSettings.IAASettings.MARKET_TYPE = market_type bid1 = self.test_market.bid(1, 2, "test_area", "A", "test_area") bid2 = self.test_market.bid(2, 3, "test_area", "B", "test_area") bid3 = self.test_market.bid(3, 4, "test_area", "C", "test_area") self.external_redis._list_bids("") self.external_redis.redis_db.publish.assert_called_once() assert self.external_redis.redis_db.publish.call_args_list[0][0][0] == \ "parent-area/test-area/bids/response" response_payload = json.loads( self.external_redis.redis_db.publish.call_args_list[0][0][1]) bids_list = response_payload["bid_list"] assert len(bids_list) == 3 self._assert_dict_is_the_same_as_offer(bids_list[0], bid1) self._assert_dict_is_the_same_as_offer(bids_list[1], bid2) self._assert_dict_is_the_same_as_offer(bids_list[2], bid3) def test_get_channel_list_fetches_correct_channel_names(self): channel_list = self.external_strategy.get_channel_list() assert set(channel_list["available_publish_channels"]) == { "parent-area/test-area/offer", "parent-area/test-area/delete_offer", "parent-area/test-area/accept_offer", "parent-area/test-area/offers" } assert set(channel_list["available_subscribe_channels"]) == { "parent-area/test-area/market_cycle" }
def test_market_bid_delete_missing(market: TwoSidedPayAsBid): with pytest.raises(BidNotFound): market.delete_bid("no such offer")
def test_market_bid_invalid(market: TwoSidedPayAsBid): with pytest.raises(InvalidBid): market.bid(10, -1, 'someone', 'noone', 'someone')
assert bid.seller == 'updated_seller' assert bid.market == market def test_market_offer_invalid(market: OneSidedMarket): with pytest.raises(InvalidOffer): market.offer(10, -1, 'someone') def test_market_bid_invalid(market: TwoSidedPayAsBid): with pytest.raises(InvalidBid): market.bid(10, -1, 'someone', 'noone') @pytest.mark.parametrize("market, offer", [ (TwoSidedPayAsBid(), "offer"), (BalancingMarket(), "balancing_offer") ]) def test_market_offer_readonly(market, offer): market.readonly = True with pytest.raises(MarketReadOnlyException): getattr(market, offer)(10, 10, 'A') @pytest.mark.parametrize("market, offer", [ (TwoSidedPayAsBid(), "offer"), (BalancingMarket(), "balancing_offer") ]) def test_market_offer_delete(market, offer): offer = getattr(market, offer)(20, 10, 'someone') market.delete_offer(offer)
def test_market_bid_delete_id(market: TwoSidedPayAsBid): bid = market.bid(20, 10, 'someone', 'noone', 'someone') assert bid.id in market.bids market.delete_bid(bid.id) assert bid.id not in market.bids
def market(): return TwoSidedPayAsBid(area=FakeArea("FakeArea"))
assert bid.buyer == 'updated_bidder' assert bid.seller == 'updated_seller' def test_market_offer_invalid(market: OneSidedMarket): with pytest.raises(InvalidOffer): market.offer(10, -1, 'someone', 'someone') def test_market_bid_invalid(market: TwoSidedPayAsBid): with pytest.raises(InvalidBid): market.bid(10, -1, 'someone', 'noone', 'someone') @pytest.mark.parametrize("market, offer", [ (TwoSidedPayAsBid(), "offer"), (BalancingMarket(), "balancing_offer") ]) def test_market_offer_readonly(market, offer): market.readonly = True with pytest.raises(MarketReadOnlyException): getattr(market, offer)(10, 10, 'A', 'A') @pytest.mark.parametrize("market, offer", [ (TwoSidedPayAsBid(time_slot=now()), "offer"), (BalancingMarket(time_slot=now()), "balancing_offer") ]) def test_market_offer_delete(market, offer): offer = getattr(market, offer)(20, 10, 'someone', 'someone') market.delete_offer(offer)
assert bid.buyer == 'updated_bidder' assert bid.seller == 'updated_seller' def test_market_offer_invalid(market: OneSidedMarket): with pytest.raises(InvalidOffer): market.offer(10, -1, 'someone') def test_market_bid_invalid(market: TwoSidedPayAsBid): with pytest.raises(InvalidBid): market.bid(10, -1, 'someone', 'noone') @pytest.mark.parametrize("market, offer", [ (TwoSidedPayAsBid(area=FakeArea("FakeArea", transfer_fee_pct=0)), "offer"), (BalancingMarket(area=FakeArea("FakeArea", transfer_fee_pct=0)), "balancing_offer") ]) def test_market_offer_readonly(market, offer): market.readonly = True with pytest.raises(MarketReadOnlyException): getattr(market, offer)(10, 10, 'A') @pytest.mark.parametrize("market, offer", [ (TwoSidedPayAsBid(area=FakeArea("FakeArea", transfer_fee_pct=0)), "offer"), (BalancingMarket(area=FakeArea("FakeArea", transfer_fee_pct=0)), "balancing_offer") ]) def test_market_offer_delete(market, offer):