示例#1
0
def get_setup(config):
    ConstSettings.IAASettings.MARKET_TYPE = 2
    ConstSettings.IAASettings.BID_OFFER_MATCH_TYPE = (
        BidOfferMatchAlgoEnum.EXTERNAL.value)
    area = Area("Grid", [
        Area(
            "House 1",
            [
                Area("H1 General Load1",
                     strategy=LoadHoursExternalStrategy(avg_power_W=200,
                                                        hrs_per_day=6,
                                                        hrs_of_day=list(
                                                            range(12, 18)),
                                                        final_buying_rate=35)),
                Area("H1 General Load2",
                     strategy=LoadHoursExternalStrategy(avg_power_W=150,
                                                        hrs_per_day=24,
                                                        hrs_of_day=list(
                                                            range(0, 24)),
                                                        final_buying_rate=40)),
                Area("H1 Storage1",
                     strategy=StorageExternalStrategy(
                         initial_soc=100, battery_capacity_kWh=20)),
                Area("H1 Storage2",
                     strategy=StorageExternalStrategy(
                         initial_soc=100, battery_capacity_kWh=20)),
                Area("H1 PV1", strategy=PVExternalStrategy(panel_count=4)),
                Area("H1 PV2", strategy=PVExternalStrategy(panel_count=4)),
            ],
        ),
        Area(
            "House 2",
            [
                Area("H2 General Load1",
                     strategy=LoadHoursExternalStrategy(avg_power_W=200,
                                                        hrs_per_day=24,
                                                        hrs_of_day=list(
                                                            range(0, 24)),
                                                        final_buying_rate=35)),
                Area("H2 Storage1",
                     strategy=StorageExternalStrategy(
                         initial_soc=100, battery_capacity_kWh=20)),
                Area("H2 PV", strategy=PVExternalStrategy(panel_count=4)),
            ],
        ),
        Area("Cell Tower",
             strategy=LoadHoursExternalStrategy(avg_power_W=100,
                                                hrs_per_day=24,
                                                hrs_of_day=list(range(0, 24)),
                                                final_buying_rate=35)),
        Area("Market Maker", strategy=MarketMakerStrategy(energy_rate=30)),
    ],
                config=config)
    return area
示例#2
0
def get_setup(config):
    area = Area('Grid', [
        Area(
            'House 1',
            [
                Area('H1 General Load',
                     strategy=LoadHoursStrategy(avg_power_W=200,
                                                hrs_per_day=6,
                                                hrs_of_day=list(range(12, 18)),
                                                final_buying_rate=35),
                     appliance=SwitchableAppliance()),
                Area('H1 Storage1',
                     strategy=StorageStrategy(initial_soc=100,
                                              battery_capacity_kWh=20),
                     appliance=SwitchableAppliance()),
                Area('H1 Storage2',
                     strategy=StorageExternalStrategy(initial_soc=100,
                                                      battery_capacity_kWh=20),
                     appliance=SwitchableAppliance()),
            ],
        ),
        Area(
            'House 2',
            [
                Area('Green Load 1',
                     strategy=LoadHoursExternalStrategy(avg_power_W=200,
                                                        hrs_per_day=24,
                                                        hrs_of_day=list(
                                                            range(0, 24)),
                                                        final_buying_rate=35),
                     appliance=SwitchableAppliance()),
                Area('Green Load 5',
                     strategy=LoadHoursExternalStrategy(avg_power_W=200,
                                                        hrs_per_day=20,
                                                        hrs_of_day=list(
                                                            range(2, 22)),
                                                        final_buying_rate=35),
                     appliance=SwitchableAppliance()),
                Area('Green PV 1',
                     strategy=PVExternalStrategy(panel_count=4),
                     appliance=PVAppliance()),
                Area('Green Storage 1',
                     strategy=StorageExternalStrategy(
                         initial_soc=50,
                         min_allowed_soc=10,
                         battery_capacity_kWh=5,
                         max_abs_battery_power_kW=4),
                     appliance=SwitchableAppliance()),
            ],
            external_connection_available=True,
        ),
        Area('Cell Tower',
             strategy=CellTowerLoadHoursStrategy(avg_power_W=100,
                                                 hrs_per_day=24,
                                                 hrs_of_day=list(range(0, 24)),
                                                 final_buying_rate=35),
             appliance=SwitchableAppliance()),
    ],
                config=config)
    return area
def get_setup(config):
    ConstSettings.IAASettings.MIN_BID_AGE = 0
    ConstSettings.IAASettings.MIN_OFFER_AGE = 0
    area = Area('Grid', [
        Area('House 1', [
            Area('H1 General Load',
                 strategy=LoadHoursStrategy(avg_power_W=200,
                                            hrs_per_day=6,
                                            hrs_of_day=list(range(12, 18)),
                                            final_buying_rate=35)),
            Area('H1 Storage1',
                 strategy=StorageStrategy(initial_soc=100,
                                          battery_capacity_kWh=20)),
            Area('H1 Storage2',
                 strategy=StorageStrategy(initial_soc=100,
                                          battery_capacity_kWh=20)),
        ],
             grid_fee_constant=2),
        Area('House 2', [
            Area('load',
                 strategy=LoadHoursExternalStrategy(avg_power_W=200,
                                                    hrs_per_day=24,
                                                    hrs_of_day=list(
                                                        range(0, 24)),
                                                    final_buying_rate=35)),
            Area('pv', strategy=PVExternalStrategy(panel_count=4)),
        ],
             external_connection_available=True,
             grid_fee_constant=1),
        Area('Market Maker', strategy=MarketMakerStrategy(energy_rate=30)),
    ],
                grid_fee_constant=10,
                config=config)
    return area
示例#4
0
def get_setup(config):
    area = Area('Grid', [
        Area('House 1', [
            Area(
                'H1 General Load',
                strategy=LoadHoursStrategy(avg_power_W=200,
                                           hrs_per_day=6,
                                           hrs_of_day=list(range(12, 18)),
                                           final_buying_rate=35),
            ),
            Area(
                'H1 Storage1',
                strategy=StorageStrategy(initial_soc=100,
                                         battery_capacity_kWh=20),
            ),
            Area(
                'H1 Storage2',
                strategy=StorageStrategy(initial_soc=100,
                                         battery_capacity_kWh=20),
            ),
        ],
             external_connection_available=True),
        Area('House 2', [
            Area(
                'load',
                strategy=LoadHoursExternalStrategy(avg_power_W=200,
                                                   hrs_per_day=24,
                                                   hrs_of_day=list(range(
                                                       0, 24)),
                                                   final_buying_rate=35),
            ),
            Area(
                'pv',
                strategy=PVExternalStrategy(panel_count=4),
            ),
        ],
             external_connection_available=True),
        Area(
            'Cell Tower',
            strategy=LoadHoursStrategy(avg_power_W=100,
                                       hrs_per_day=24,
                                       hrs_of_day=list(range(0, 24)),
                                       final_buying_rate=35),
        ),
    ],
                config=config)
    return area
示例#5
0
def get_setup(config):
    ConstSettings.IAASettings.MARKET_TYPE = 2
    ConstSettings.IAASettings.MIN_BID_AGE = 0
    ConstSettings.IAASettings.BID_OFFER_MATCH_TYPE = \
        BidOfferMatchAlgoEnum.PAY_AS_CLEAR.value
    ConstSettings.IAASettings.MIN_OFFER_AGE = 0
    area = Area('Grid', [
        Area(
            'House 1',
            [
                Area('H1 General Load',
                     strategy=LoadHoursStrategy(avg_power_W=200,
                                                hrs_per_day=6,
                                                hrs_of_day=list(range(12, 18)),
                                                final_buying_rate=35)),
                Area('H1 Storage1',
                     strategy=StorageStrategy(initial_soc=100,
                                              battery_capacity_kWh=20)),
                Area('H1 Storage2',
                     strategy=StorageStrategy(initial_soc=100,
                                              battery_capacity_kWh=20)),
            ],
        ),
        Area(
            'House 2',
            [
                Area('load',
                     strategy=LoadHoursExternalStrategy(avg_power_W=200,
                                                        hrs_per_day=24,
                                                        hrs_of_day=list(
                                                            range(0, 24)),
                                                        final_buying_rate=35)),
                Area('pv', strategy=PVExternalStrategy(panel_count=4)),
            ],
            external_connection_available=True,
        ),
        Area('Cell Tower',
             strategy=LoadHoursStrategy(avg_power_W=100,
                                        hrs_per_day=24,
                                        hrs_of_day=list(range(0, 24)),
                                        final_buying_rate=35)),
    ],
                config=config)
    return area
示例#6
0
def get_setup(config):
    area = Area('Grid', [
        Area(
            'House 1',
            [
                Area('H1 General Load',
                     strategy=LoadHoursStrategy(avg_power_W=200,
                                                hrs_per_day=6,
                                                hrs_of_day=list(range(12, 18)),
                                                final_buying_rate=35),
                     appliance=SwitchableAppliance()),
                Area('H1 Storage1',
                     strategy=StorageStrategy(initial_soc=50),
                     appliance=SwitchableAppliance()),
                Area('H1 Storage2',
                     strategy=StorageStrategy(initial_soc=50),
                     appliance=SwitchableAppliance()),
            ],
        ),
        Area(
            'House 2',
            [
                Area('load',
                     strategy=LoadHoursExternalStrategy(avg_power_W=200,
                                                        hrs_per_day=24,
                                                        hrs_of_day=list(
                                                            range(0, 24)),
                                                        final_buying_rate=35),
                     appliance=SwitchableAppliance()),
                Area('pv',
                     strategy=PVExternalStrategy(panel_count=4),
                     appliance=PVAppliance()),
            ],
        ),
        Area('Cell Tower',
             strategy=CellTowerLoadHoursStrategy(avg_power_W=100,
                                                 hrs_per_day=24,
                                                 hrs_of_day=list(range(0, 24)),
                                                 final_buying_rate=35),
             appliance=SwitchableAppliance()),
    ],
                config=config)
    return area
示例#7
0
 def setUp(self):
     self.config = MagicMock(spec=SimulationConfig)
     self.config.slot_length = duration(minutes=15)
     self.config.tick_length = duration(seconds=15)
     self.config.ticks_per_slot = int(self.config.slot_length.seconds /
                                      self.config.tick_length.seconds)
     self.config.start_date = today(tz=TIME_ZONE)
     self.config.sim_duration = duration(days=1)
     self.config.grid_fee_type = 1
     self.config.end_date = self.config.start_date + self.config.sim_duration
     self.config.market_count = 1
     self.config.max_panel_power_W = 1000
     self.config.external_redis_communicator = \
         MagicMock(spec=ExternalConnectionCommunicator(True))
     self.storage = Area("Storage", strategy=StorageExternalStrategy(), config=self.config,
                         external_connection_available=True)
     self.load = Area("Load", strategy=LoadHoursExternalStrategy(avg_power_W=100),
                      config=self.config, external_connection_available=True)
     self.pv = Area("PV", strategy=PVExternalStrategy(), config=self.config,
                    external_connection_available=True)
     self.house_area = Area("House", children=[self.storage, self.load, self.pv],
                            config=self.config)
     self.grid_area = Area("Grid", children=[self.house_area], config=self.config)
     self.grid_area.activate()
示例#8
0
class TestExternalMixin(unittest.TestCase):
    def _create_and_activate_strategy_area(self, strategy):
        self.config = MagicMock()
        self.config.max_panel_power_W = 160
        GlobalConfig.end_date = GlobalConfig.start_date + Duration(days=1)
        self.area = Area(name="test_area",
                         config=self.config,
                         strategy=strategy)
        parent = Area(name="parent_area", children=[self.area])
        parent.activate()
        strategy.connected = True
        market = MagicMock()
        market.time_slot = GlobalConfig.start_date
        parent.get_future_market_from_id = lambda _: market
        self.area.get_future_market_from_id = lambda _: market

    def test_dispatch_tick_frequency_gets_calculated_correctly(self):
        self.external_strategy = LoadHoursExternalStrategy(100)
        self._create_and_activate_strategy_area(self.external_strategy)
        d3a.models.strategy.external_strategies.DISPATCH_EVENT_TICK_FREQUENCY_PERCENT = 20
        self.config.ticks_per_slot = 90
        assert self.external_strategy._dispatch_tick_frequency == 18
        self.config.ticks_per_slot = 10
        assert self.external_strategy._dispatch_tick_frequency == 2
        self.config.ticks_per_slot = 100
        assert self.external_strategy._dispatch_tick_frequency == 20
        self.config.ticks_per_slot = 99
        assert self.external_strategy._dispatch_tick_frequency == 19
        d3a.models.strategy.external_strategies.DISPATCH_EVENT_TICK_FREQUENCY_PERCENT = 50
        self.config.ticks_per_slot = 90
        assert self.external_strategy._dispatch_tick_frequency == 45
        self.config.ticks_per_slot = 10
        assert self.external_strategy._dispatch_tick_frequency == 5
        self.config.ticks_per_slot = 100
        assert self.external_strategy._dispatch_tick_frequency == 50
        self.config.ticks_per_slot = 99
        assert self.external_strategy._dispatch_tick_frequency == 49

    @parameterized.expand([[LoadHoursExternalStrategy(100)],
                           [PVExternalStrategy(2, max_panel_power_W=160)],
                           [StorageExternalStrategy()]])
    def test_dispatch_event_tick_to_external_agent(self, strategy):
        d3a.models.strategy.external_strategies.DISPATCH_EVENT_TICK_FREQUENCY_PERCENT = 20
        self._create_and_activate_strategy_area(strategy)
        self.config.ticks_per_slot = 90
        assert strategy._dispatch_tick_frequency == 18
        self.area.current_tick = 1
        strategy._dispatch_event_tick_to_external_agent()
        strategy.redis.publish_json.assert_not_called()
        self.area.current_tick = 17
        strategy._dispatch_event_tick_to_external_agent()
        strategy.redis.publish_json.assert_not_called()
        self.area.current_tick = 18
        strategy._dispatch_event_tick_to_external_agent()
        strategy.redis.publish_json.assert_called_once()
        assert strategy.redis.publish_json.call_args_list[0][0][
            0] == "test_area/events/tick"
        result = strategy.redis.publish_json.call_args_list[0][0][1]
        result.pop('area_uuid')
        assert result == \
            {'device_info': strategy._device_info_dict, 'event': 'tick', 'slot_completion': '20%'}
        strategy.redis.reset_mock()
        strategy.redis.publish_json.reset_mock()
        self.area.current_tick = 35
        strategy._dispatch_event_tick_to_external_agent()
        strategy.redis.publish_json.assert_not_called()
        self.area.current_tick = 36
        strategy._dispatch_event_tick_to_external_agent()
        strategy.redis.publish_json.assert_called_once()
        assert strategy.redis.publish_json.call_args_list[0][0][
            0] == "test_area/events/tick"
        result = strategy.redis.publish_json.call_args_list[0][0][1]
        result.pop('area_uuid')
        assert result == \
            {'device_info': strategy._device_info_dict, 'event': 'tick', 'slot_completion': '40%'}

    @parameterized.expand([[LoadHoursExternalStrategy(100)],
                           [PVExternalStrategy(2, max_panel_power_W=160)],
                           [StorageExternalStrategy()]])
    def test_dispatch_event_trade_to_external_agent(self, strategy):
        strategy._track_energy_sell_type = lambda _: None
        self._create_and_activate_strategy_area(strategy)
        market = self.area.get_future_market_from_id(1)
        self.area._markets.markets = {1: market}
        strategy.state.available_energy_kWh = {market.time_slot: 1000.0}
        strategy.state.pledged_sell_kWh = {market.time_slot: 0.0}
        strategy.state.offered_sell_kWh = {market.time_slot: 0.0}
        current_time = now()
        trade = Trade('id',
                      current_time,
                      Offer('offer_id', now(), 20, 1.0, 'test_area'),
                      'test_area',
                      'parent_area',
                      fee_price=0.23)
        strategy.event_trade(market_id="test_market", trade=trade)
        assert strategy.redis.publish_json.call_args_list[0][0][
            0] == "test_area/events/trade"
        call_args = strategy.redis.publish_json.call_args_list[0][0][1]
        assert call_args['trade_id'] == trade.id
        assert call_args['event'] == "trade"
        assert call_args['price'] == 20
        assert call_args['energy'] == 1.0
        assert call_args['fee_price'] == 0.23
        assert call_args['offer_id'] == trade.offer.id
        assert call_args['residual_id'] == "None"
        assert call_args['time'] == current_time.isoformat()
        assert call_args['seller'] == trade.seller
        assert call_args['buyer'] == "anonymous"
        assert call_args['device_info'] == strategy._device_info_dict

    def test_device_info_dict_for_load_strategy_reports_required_energy(self):
        strategy = LoadHoursExternalStrategy(100)
        self._create_and_activate_strategy_area(strategy)
        strategy.energy_requirement_Wh[strategy.market.time_slot] = 0.987
        assert strategy._device_info_dict["energy_requirement_kWh"] == 0.000987

    def test_device_info_dict_for_pv_strategy_reports_available_energy(self):
        strategy = PVExternalStrategy(2, max_panel_power_W=160)
        self._create_and_activate_strategy_area(strategy)
        strategy.state.available_energy_kWh[strategy.market.time_slot] = 1.123
        assert strategy._device_info_dict["available_energy_kWh"] == 1.123

    def test_device_info_dict_for_storage_strategy_reports_battery_stats(self):
        strategy = StorageExternalStrategy(battery_capacity_kWh=0.5)
        self._create_and_activate_strategy_area(strategy)
        strategy.state.energy_to_sell_dict[strategy.market.time_slot] = 0.02
        strategy.state.energy_to_buy_dict[strategy.market.time_slot] = 0.03
        strategy.state._used_storage = 0.01
        assert strategy._device_info_dict["energy_to_sell"] == 0.02
        assert strategy._device_info_dict["energy_to_buy"] == 0.03
        assert strategy._device_info_dict["used_storage"] == 0.01
        assert strategy._device_info_dict["free_storage"] == 0.49

    @parameterized.expand([[LoadHoursExternalStrategy(100)],
                           [PVExternalStrategy(2, max_panel_power_W=160)],
                           [StorageExternalStrategy()]])
    def test_register_device(self, strategy):
        self.config = MagicMock()
        self.device = Area(name="test_area",
                           config=self.config,
                           strategy=strategy)
        payload = {"data": json.dumps({"transaction_id": str(uuid.uuid4())})}
        self.device.strategy.owner = self.device
        assert self.device.strategy.connected is False
        self.device.strategy._register(payload)
        self.device.strategy.register_on_market_cycle()
        assert self.device.strategy.connected is True
        self.device.strategy._unregister(payload)
        self.device.strategy.register_on_market_cycle()
        assert self.device.strategy.connected is False

        payload = {"data": json.dumps({"transaction_id": None})}
        with self.assertRaises(ValueError):
            self.device.strategy._register(payload)
        with self.assertRaises(ValueError):
            self.device.strategy._unregister(payload)
示例#9
0
 def test_device_info_dict_for_pv_strategy_reports_available_energy(self):
     strategy = PVExternalStrategy(2, max_panel_power_W=160)
     self._create_and_activate_strategy_area(strategy)
     strategy.state.available_energy_kWh[strategy.market.time_slot] = 1.123
     assert strategy._device_info_dict["available_energy_kWh"] == 1.123
示例#10
0
def ext_pv_fixture():
    return create_areas_markets_for_strategy_fixture(PVExternalStrategy())
class TestPVForecastExternalStrategy:
    @pytest.mark.parametrize(
        "ext_strategy_fixture",
        [LoadForecastExternalStrategy(),
         PVForecastExternalStrategy()],
        indirect=True)
    def test_event_market_cycle_calls_energy_update_methods(
            self, ext_strategy_fixture):
        ext_strategy_fixture.energy_forecast_buffer = {now(): 1}
        ext_strategy_fixture.energy_measurement_buffer = {now(): 1}
        ext_strategy_fixture.update_energy_forecast = Mock()
        ext_strategy_fixture.update_energy_measurement = Mock()
        ext_strategy_fixture.event_market_cycle()
        ext_strategy_fixture.update_energy_forecast.assert_called_once()
        ext_strategy_fixture.update_energy_measurement.assert_called_once()
        assert ext_strategy_fixture.energy_forecast_buffer == {}
        assert ext_strategy_fixture.energy_measurement_buffer == {}

    @pytest.mark.parametrize("ext_strategy_fixture",
                             [PVForecastExternalStrategy()],
                             indirect=True)
    def test_update_energy_forecast_calls_set_available_energy(
            self, ext_strategy_fixture):
        time = ext_strategy_fixture.area.next_market.time_slot
        energy = 1
        ext_strategy_fixture.energy_forecast_buffer = {time: energy}
        ext_strategy_fixture.state.set_available_energy = Mock()
        ext_strategy_fixture.update_energy_forecast()
        ext_strategy_fixture.state.set_available_energy.assert_called_once_with(
            energy, time, overwrite=True)

    @pytest.mark.parametrize("ext_strategy_fixture",
                             [PVForecastExternalStrategy()],
                             indirect=True)
    def test_update_energy_forecast_doesnt_call_set_available_energy_for_past_markets(
            self, ext_strategy_fixture):
        # do not call set_available_energy for time_slots in the past
        ext_strategy_fixture.state.set_available_energy = Mock()
        time = ext_strategy_fixture.area.next_market.time_slot.subtract(
            minutes=15)
        ext_strategy_fixture.energy_forecast_buffer = {time: 1}
        ext_strategy_fixture.update_energy_forecast()
        ext_strategy_fixture.state.set_available_energy.assert_not_called()

    @pytest.mark.parametrize("ext_strategy_fixture",
                             [LoadForecastExternalStrategy()],
                             indirect=True)
    def test_update_energy_forecast_calls_set_desired_energy(
            self, ext_strategy_fixture):
        time = ext_strategy_fixture.area.next_market.time_slot
        energy = 1
        ext_strategy_fixture.energy_forecast_buffer = {time: energy}
        ext_strategy_fixture.state.set_desired_energy = Mock()
        ext_strategy_fixture.state.update_total_demanded_energy = Mock()
        ext_strategy_fixture.update_energy_forecast()
        ext_strategy_fixture.state.set_desired_energy.assert_called_once_with(
            energy * 1000, time, overwrite=True)
        ext_strategy_fixture.state.update_total_demanded_energy.assert_called_once_with(
            time)

    @pytest.mark.parametrize("ext_strategy_fixture",
                             [LoadForecastExternalStrategy()],
                             indirect=True)
    def test_update_energy_forecast_doesnt_call_set_desired_energy_for_past_markets(
            self, ext_strategy_fixture):
        time = ext_strategy_fixture.area.next_market.time_slot.subtract(
            minutes=15)
        ext_strategy_fixture.energy_forecast_buffer = {time: 1}
        ext_strategy_fixture.state.set_desired_energy = Mock()
        ext_strategy_fixture.state.update_total_demanded_energy = Mock()
        ext_strategy_fixture.update_energy_forecast()
        ext_strategy_fixture.state.set_desired_energy.assert_not_called()
        ext_strategy_fixture.state.update_total_demanded_energy.assert_not_called(
        )

    @pytest.mark.parametrize(
        "ext_strategy_fixture",
        [LoadForecastExternalStrategy(),
         PVForecastExternalStrategy()],
        indirect=True)
    def test_update_energy_measurement_calls_set_energy_measurement_kWh(
            self, ext_strategy_fixture):
        time = ext_strategy_fixture.area.next_market.time_slot.subtract(
            minutes=15)
        energy = 1
        ext_strategy_fixture.energy_measurement_buffer = {time: energy}
        ext_strategy_fixture.state.set_energy_measurement_kWh = Mock()
        ext_strategy_fixture.update_energy_measurement()
        ext_strategy_fixture.state.set_energy_measurement_kWh.assert_called_once_with(
            energy, time)

    @pytest.mark.parametrize(
        "ext_strategy_fixture",
        [LoadForecastExternalStrategy(),
         PVForecastExternalStrategy()],
        indirect=True)
    def test_update_energy_measurement_doesnt_call_set_energy_measurement_kWh_for_future_markets(
            self, ext_strategy_fixture):
        time = ext_strategy_fixture.area.next_market.time_slot.add(minutes=15)
        ext_strategy_fixture.energy_measurement_buffer = {time: 1}
        ext_strategy_fixture.state.set_energy_measurement_kWh = Mock()
        ext_strategy_fixture.update_energy_measurement()
        ext_strategy_fixture.state.set_energy_measurement_kWh.assert_not_called(
        )

    @pytest.mark.parametrize(
        "ext_strategy_fixture",
        [LoadHoursExternalStrategy(100),
         StorageExternalStrategy()],
        indirect=True)
    def test_receive_bid_successful(self, ext_strategy_fixture):
        transaction_id = str(uuid.uuid4())
        arguments = {"transaction_id": transaction_id, "price": 1, "energy": 2}
        payload = {"data": json.dumps(arguments)}
        assert ext_strategy_fixture.pending_requests == deque([])
        ext_strategy_fixture.bid(payload)
        assert len(ext_strategy_fixture.pending_requests) > 0
        response_channel = f"{ext_strategy_fixture.channel_prefix}/response/bid"
        assert (ext_strategy_fixture.pending_requests == deque(
            [IncomingRequest("bid", arguments, response_channel)]))

    @pytest.mark.parametrize(
        "ext_strategy_fixture",
        [PVExternalStrategy(), StorageExternalStrategy()],
        indirect=True)
    def test_receive_offer_successful(self, ext_strategy_fixture):
        transaction_id = str(uuid.uuid4())
        arguments = {"transaction_id": transaction_id, "price": 1, "energy": 2}
        payload = {"data": json.dumps(arguments)}
        assert ext_strategy_fixture.pending_requests == deque([])
        ext_strategy_fixture.offer(payload)
        assert len(ext_strategy_fixture.pending_requests) > 0
        response_channel = f"{ext_strategy_fixture.channel_prefix}/response/offer"
        assert (ext_strategy_fixture.pending_requests == deque(
            [IncomingRequest("offer", arguments, response_channel)]))

    @pytest.mark.parametrize(
        "ext_strategy_fixture",
        [PVExternalStrategy(), StorageExternalStrategy()],
        indirect=True)
    def test_list_offers_successful(self, ext_strategy_fixture):
        transaction_id = str(uuid.uuid4())
        arguments = {"transaction_id": transaction_id}
        payload = {"data": json.dumps(arguments)}
        assert ext_strategy_fixture.pending_requests == deque([])
        ext_strategy_fixture.list_offers(payload)
        assert len(ext_strategy_fixture.pending_requests) > 0
        response_channel = f"{ext_strategy_fixture.channel_prefix}/response/list_offers"
        assert (ext_strategy_fixture.pending_requests == deque(
            [IncomingRequest("list_offers", arguments, response_channel)]))

    @pytest.mark.parametrize(
        "ext_strategy_fixture",
        [LoadHoursExternalStrategy(100),
         StorageExternalStrategy()],
        indirect=True)
    def test_list_bids_successful(self, ext_strategy_fixture):
        transaction_id = str(uuid.uuid4())
        arguments = {"transaction_id": transaction_id}
        payload = {"data": json.dumps(arguments)}
        assert ext_strategy_fixture.pending_requests == deque([])
        ext_strategy_fixture.list_bids(payload)
        assert len(ext_strategy_fixture.pending_requests) > 0
        response_channel = f"{ext_strategy_fixture.channel_prefix}/response/list_bids"
        assert (ext_strategy_fixture.pending_requests == deque(
            [IncomingRequest("list_bids", arguments, response_channel)]))

    @pytest.mark.parametrize(
        "ext_strategy_fixture",
        [LoadHoursExternalStrategy(100),
         StorageExternalStrategy()],
        indirect=True)
    def test_delete_bid_successful(self, ext_strategy_fixture):
        transaction_id = str(uuid.uuid4())
        arguments = {"transaction_id": transaction_id}
        payload = {"data": json.dumps(arguments)}
        assert ext_strategy_fixture.pending_requests == deque([])
        ext_strategy_fixture.delete_bid(payload)
        assert len(ext_strategy_fixture.pending_requests) > 0
        response_channel = f"{ext_strategy_fixture.channel_prefix}/response/delete_bid"
        assert (ext_strategy_fixture.pending_requests == deque(
            [IncomingRequest("delete_bid", arguments, response_channel)]))

    @pytest.mark.parametrize(
        "ext_strategy_fixture",
        [PVExternalStrategy(), StorageExternalStrategy()],
        indirect=True)
    def test_delete_offer_successful(self, ext_strategy_fixture):
        transaction_id = str(uuid.uuid4())
        arguments = {"transaction_id": transaction_id}
        payload = {"data": json.dumps(arguments)}
        assert ext_strategy_fixture.pending_requests == deque([])
        ext_strategy_fixture.delete_offer(payload)
        assert len(ext_strategy_fixture.pending_requests) > 0
        response_channel = f"{ext_strategy_fixture.channel_prefix}/response/delete_offer"
        assert (ext_strategy_fixture.pending_requests == deque(
            [IncomingRequest("delete_offer", arguments, response_channel)]))