def _set_alternative_pricing_scheme(self): if ConstSettings.IAASettings.AlternativePricing.PRICING_SCHEME != 0: if ConstSettings.IAASettings.AlternativePricing.PRICING_SCHEME == 1: for time_slot in generate_market_slot_list(): self.bid_update.reassign_mixin_arguments(time_slot, initial_rate=0, final_rate=0) self.offer_update.reassign_mixin_arguments(time_slot, initial_rate=0, final_rate=0) elif ConstSettings.IAASettings.AlternativePricing.PRICING_SCHEME == 2: for time_slot in generate_market_slot_list(): rate = \ self.area.config.market_maker_rate[time_slot] * \ ConstSettings.IAASettings.AlternativePricing.FEED_IN_TARIFF_PERCENTAGE / \ 100 self.bid_update.reassign_mixin_arguments(time_slot, initial_rate=0, final_rate=rate) self.offer_update.reassign_mixin_arguments( time_slot, initial_rate=rate, final_rate=rate) elif ConstSettings.IAASettings.AlternativePricing.PRICING_SCHEME == 3: for time_slot in generate_market_slot_list(): rate = self.area.config.market_maker_rate[time_slot] self.bid_update.reassign_mixin_arguments(time_slot, initial_rate=0, final_rate=rate) self.offer_update.reassign_mixin_arguments( time_slot, initial_rate=rate, final_rate=rate) else: raise MarketException
def update_sold_bought_energy(self, area: Area): if ConstSettings.GeneralSettings.KEEP_PAST_MARKETS: self.traded_energy[area.uuid] = \ self._calculate_devices_sold_bought_energy_past_markets(area, area.past_markets) self.traded_energy[area.name] = self.traded_energy[area.uuid] self.balancing_traded_energy[area.name] = \ self._calculate_devices_sold_bought_energy_past_markets( area, area.past_balancing_markets) self.traded_energy_profile_redis[area.uuid] = \ self._serialize_traded_energy_lists(self.traded_energy, area.uuid) self.traded_energy_profile[ area.slug] = self.traded_energy_profile_redis[area.uuid] else: if area.uuid not in self.traded_energy: self.traded_energy[area.uuid] = { "sold_energy": {}, "bought_energy": {} } self._calculate_devices_sold_bought_energy( self.traded_energy[area.uuid], area.current_market) self.traded_energy[area.name] = self.traded_energy[area.uuid] if area.name not in self.balancing_traded_energy: self.balancing_traded_energy[area.name] = { "sold_energy": {}, "bought_energy": {} } if len(area.past_balancing_markets) > 0: self._calculate_devices_sold_bought_energy( self.balancing_traded_energy[area.name], area.current_balancing_market) if area.uuid not in self.traded_energy_current: self.traded_energy_current[area.uuid] = { "sold_energy": {}, "bought_energy": {} } if area.current_market is not None: self.time_slots = [area.current_market.time_slot] self._calculate_devices_sold_bought_energy( self.traded_energy_current[area.uuid], area.current_market) self.traded_energy_current[ area.uuid] = self._serialize_traded_energy_lists( self.traded_energy_current, area.uuid) self.time_slots = generate_market_slot_list(area) self.balancing_traded_energy[ area.uuid] = self.balancing_traded_energy[area.name] # TODO: Adapt to not store the full results on D3A. self.traded_energy_profile_redis = merge_energy_trade_profile_to_global( self.traded_energy_current, self.traded_energy_profile_redis, generate_market_slot_list(area)) self.traded_energy_profile[ area.slug] = self.traded_energy_profile_redis[area.uuid]
def __init__(self, initial_soc=StorageSettings.MIN_ALLOWED_SOC, initial_energy_origin=ESSEnergyOrigin.EXTERNAL, capacity=StorageSettings.CAPACITY, max_abs_battery_power_kW=StorageSettings.MAX_ABS_POWER, loss_per_hour=0.01, min_allowed_soc=StorageSettings.MIN_ALLOWED_SOC): initial_capacity_kWh = capacity * initial_soc / 100 self.min_allowed_soc_ratio = min_allowed_soc / 100 self.capacity = capacity self.loss_per_hour = loss_per_hour self.max_abs_battery_power_kW = max_abs_battery_power_kW # storage capacity, that is already sold: self.pledged_sell_kWh = \ {slot: 0. for slot in generate_market_slot_list()} # type: Dict[DateTime, float] # storage capacity, that has been offered (but not traded yet): self.offered_sell_kWh = \ {slot: 0. for slot in generate_market_slot_list()} # type: Dict[DateTime, float] # energy, that has been bought: self.pledged_buy_kWh = \ {slot: 0. for slot in generate_market_slot_list()} # type: Dict[DateTime, float] # energy, that the storage wants to buy (but not traded yet): self.offered_buy_kWh = \ {slot: 0. for slot in generate_market_slot_list()} # type: Dict[DateTime, float] self.time_series_ess_share = \ {slot: {ESSEnergyOrigin.UNKNOWN: 0., ESSEnergyOrigin.LOCAL: 0., ESSEnergyOrigin.EXTERNAL: 0.} for slot in generate_market_slot_list()} # type: Dict[DateTime, float] self.charge_history = \ {slot: '-' for slot in generate_market_slot_list()} # type: Dict[DateTime, float] self.charge_history_kWh = \ {slot: '-' for slot in generate_market_slot_list()} # type: Dict[DateTime, float] self.offered_history = \ {slot: '-' for slot in generate_market_slot_list()} # type: Dict[DateTime, float] self.used_history = \ {slot: '-' for slot in generate_market_slot_list()} # type: Dict[DateTime, float] self.energy_to_buy_dict = { slot: 0. for slot in generate_market_slot_list() } self._used_storage = initial_capacity_kWh self._battery_energy_per_slot = 0.0 self._used_storage_share = [ EnergyOrigin(initial_energy_origin, initial_capacity_kWh) ]
def __call__(self, area): self.time_slots = generate_market_slot_list(area) # Resetting traded energy before repopulating it self.traded_energy_current = {} self._populate_area_children_data(area) self.traded_energy_current = self._round_energy_trade_profile( self.traded_energy_current)
def _set_alternative_pricing_scheme(self): if ConstSettings.IAASettings.AlternativePricing.PRICING_SCHEME != 0: for time_slot in generate_market_slot_list(): final_rate = self.area.config.market_maker_rate[time_slot] self.bid_update.reassign_mixin_arguments(time_slot, initial_rate=0, final_rate=final_rate)
def assign_energy_requirement(self, avg_power_W): self.energy_per_slot_Wh = (avg_power_W / (duration(hours=1) / self.area.config.slot_length)) for slot_time in generate_market_slot_list(area=self.area): if self._allowed_operating_hours(slot_time) and slot_time >= self.area.now: self.energy_requirement_Wh[slot_time] = self.energy_per_slot_Wh self.state.desired_energy_Wh[slot_time] = self.energy_per_slot_Wh
def produced_energy_forecast_kWh(self): """ Returns flat PV production curve. """ for slot_time in generate_market_slot_list(area=self.area): self.energy_production_forecast_kWh[slot_time] = 100
def _plot_ess_energy_trace(self, energy: dict, subdir: str, root_name: str): """ Plots ess energy trace for each knot in the hierarchy """ data = list() barmode = "stack" title = 'ESS ENERGY SHARE ({})'.format(root_name) xtitle = 'Time' ytitle = 'Energy [kWh]' temp = { ESSEnergyOrigin.UNKNOWN: {slot: 0. for slot in generate_market_slot_list()}, ESSEnergyOrigin.LOCAL: {slot: 0. for slot in generate_market_slot_list()}, ESSEnergyOrigin.EXTERNAL: {slot: 0. for slot in generate_market_slot_list()} } for time, energy_info in energy.items(): temp[ESSEnergyOrigin.EXTERNAL][time] = energy_info[ ESSEnergyOrigin.EXTERNAL] temp[ESSEnergyOrigin.LOCAL][time] = energy_info[ ESSEnergyOrigin.LOCAL] temp[ESSEnergyOrigin.UNKNOWN][time] = energy_info[ ESSEnergyOrigin.UNKNOWN] for energy_type in [ ESSEnergyOrigin.EXTERNAL, ESSEnergyOrigin.LOCAL, ESSEnergyOrigin.UNKNOWN ]: data_obj = go.Bar(x=list(temp[energy_type].keys()), y=list(temp[energy_type].values()), name=f"{energy_type}") data.append(data_obj) if len(data) == 0: return plot_dir = os.path.join(self.plot_dir, subdir) mkdir_from_str(plot_dir) output_file = os.path.join( plot_dir, 'ess_energy_share_{}.html'.format(root_name)) PlotlyGraph.plot_bar_graph(barmode, title, xtitle, ytitle, data, output_file)
def _validate_rates(self): for time_slot in generate_market_slot_list(): rate_change = None if self.fit_to_limit else \ self.bid_update.energy_rate_change_per_update[time_slot] validate_load_device_price( initial_buying_rate=self.bid_update.initial_rate[time_slot], energy_rate_increase_per_update=rate_change, final_buying_rate=self.bid_update.final_rate[time_slot], fit_to_limit=self.bid_update.fit_to_limit)
def copy_profile_to_multiple_days(profile): daytime_dict = dict((time_str(time.hour, time.minute), time) for time in profile.keys()) for slot_time in generate_market_slot_list(): if slot_time not in profile.keys(): time_key = time_str(slot_time.hour, slot_time.minute) if time_key in daytime_dict: profile[slot_time] = profile[daytime_dict[time_key]] return profile
def _set_or_update_energy_rate_change_per_update(self): energy_rate_change_per_update = {} for slot in generate_market_slot_list(): if self.fit_to_limit: energy_rate_change_per_update[slot] = \ (self.initial_rate[slot] - self.final_rate[slot]) / \ self.number_of_available_updates else: energy_rate_change_per_update[slot] = self.energy_rate_change_per_update[slot] self.energy_rate_change_per_update = energy_rate_change_per_update
def read_config_event(self): self._power_profile_index = self.cloud_coverage \ if self.cloud_coverage is not None else self.area.config.cloud_coverage data = self._read_predefined_profile_for_pv() for slot_time in generate_market_slot_list(area=self.area): self.energy_production_forecast_kWh[slot_time] = \ data[slot_time] * self.panel_count self.state.available_energy_kWh[slot_time] = \ self.energy_production_forecast_kWh[slot_time]
def __init__( self, panel_count: int = 1, initial_selling_rate: float = ConstSettings.GeneralSettings. DEFAULT_MARKET_MAKER_RATE, final_selling_rate: float = ConstSettings.PVSettings. FINAL_SELLING_RATE, fit_to_limit: bool = True, update_interval=duration( minutes=ConstSettings.GeneralSettings.DEFAULT_UPDATE_INTERVAL), energy_rate_decrease_per_update: float = ConstSettings. GeneralSettings.ENERGY_RATE_DECREASE_PER_UPDATE, max_panel_power_W: float = None, use_market_maker_rate: bool = False): """ :param panel_count: Number of solar panels for this PV plant :param initial_selling_rate: Upper Threshold for PV offers :param final_selling_rate: Lower Threshold for PV offers :param fit_to_limit: Linear curve following initial_selling_rate & initial_selling_rate :param update_interval: Interval after which PV will update its offer :param energy_rate_decrease_per_update: Slope of PV Offer change per update :param max_panel_power_W: """ # If use_market_maker_rate is true, overwrite initial_selling_rate to market maker rate if use_market_maker_rate: initial_selling_rate = GlobalConfig.market_maker_rate try: validate_pv_device(panel_count=panel_count, max_panel_power_W=max_panel_power_W) except D3ADeviceException as e: raise D3ADeviceException(str(e)) if isinstance(update_interval, int): update_interval = duration(minutes=update_interval) BaseStrategy.__init__(self) self.offer_update = UpdateFrequencyMixin( initial_selling_rate, final_selling_rate, fit_to_limit, energy_rate_decrease_per_update, update_interval) for time_slot in generate_market_slot_list(): try: validate_pv_device( initial_selling_rate=self.offer_update. initial_rate[time_slot], final_selling_rate=self.offer_update.final_rate[time_slot]) except D3ADeviceException as e: raise D3ADeviceException(str(e)) self.panel_count = panel_count self.final_selling_rate = final_selling_rate self.max_panel_power_W = max_panel_power_W self.energy_production_forecast_kWh = {} # type: Dict[Time, float] self.state = PVState()
def event_activate(self): self.energy_per_slot_Wh = (self.avg_power_W / (duration(hours=1) / self.area.config.slot_length)) self._simulation_start_timestamp = self.area.now self.hrs_per_day = {day: self._initial_hrs_per_day for day in range(self.area.config.duration.days + 1)} for slot_time in generate_market_slot_list(self.area): if self._allowed_operating_hours(slot_time): self.energy_requirement_Wh[slot_time] = self.energy_per_slot_Wh self.state.desired_energy_Wh[slot_time] = self.energy_per_slot_Wh
def _update_energy_requirement(self): """ Update required energy values for each market slot. :return: None """ self._simulation_start_timestamp = self.area.now self.hrs_per_day = {day: self._initial_hrs_per_day for day in range(self.area.config.sim_duration.days + 1)} for slot_time in generate_market_slot_list(area=self.area): if self._allowed_operating_hours(slot_time.hour): self.energy_requirement_Wh[slot_time] = self.load_profile[slot_time] * 1000 self.state.desired_energy_Wh[slot_time] = self.load_profile[slot_time] * 1000 self.state.total_energy_demanded_wh += self.load_profile[slot_time] * 1000
def produced_energy_forecast_kWh(self): # This forecast ist based on the real PV system data provided by enphase # They can be found in the tools folder # A fit of a gaussian function to those data results in a formula Energy(time) for slot_time in generate_market_slot_list(self.area): difference_to_midnight_in_minutes = \ slot_time.diff(self.midnight).in_minutes() % (60 * 24) self.energy_production_forecast_kWh[slot_time] = \ self.gaussian_energy_forecast_kWh( difference_to_midnight_in_minutes) * self.panel_count self.state.available_energy_kWh[slot_time] = \ self.energy_production_forecast_kWh[slot_time] assert self.energy_production_forecast_kWh[slot_time] >= 0.0
def _validate_rates(self): for time_slot in generate_market_slot_list(): bid_rate_change = None if self.bid_update.fit_to_limit else \ self.bid_update.energy_rate_change_per_update[time_slot] offer_rate_change = None if self.offer_update.fit_to_limit else \ self.offer_update.energy_rate_change_per_update[time_slot] validate_storage_device( initial_selling_rate=self.offer_update.initial_rate[time_slot], final_selling_rate=self.offer_update.final_rate[time_slot], initial_buying_rate=self.bid_update.initial_rate[time_slot], final_buying_rate=self.bid_update.final_rate[time_slot], energy_rate_increase_per_update=bid_rate_change, energy_rate_decrease_per_update=offer_rate_change, fit_to_limit=self.bid_update.fit_to_limit, update_interval=self.bid_update.update_interval)
def event_activate(self): """ Runs on activate event. Reads the power profile data and calculates the required energy for each slot. :return: None """ # TODO: Need to have 2-stage initialization as well, because the area objects are not # created when the constructor is executed if we inherit from a mixin class, # therefore config cannot be read at that point data = self._read_predefined_profile_for_pv() for slot_time in generate_market_slot_list(self.area): self.energy_production_forecast_kWh[slot_time] = \ data[slot_time.format(PENDULUM_TIME_FORMAT)] * self.panel_count self.state.available_energy_kWh[slot_time] = \ self.energy_production_forecast_kWh[slot_time] # TODO: A bit clumsy, but this decrease price calculation needs to be added here as well # Need to refactor once we convert the config object to a singleton that is shared globally # in the simulation self._decrease_price_every_nr_s = \ (self.area.config.tick_length.seconds * ConstSettings.GeneralSettings.MAX_OFFER_TRAVERSAL_LENGTH + 1)
def __call__(self, area): self.time_slots = generate_market_slot_list(area) self._populate_area_children_data(area)
def __init__(self): self.available_energy_kWh = \ {slot: 0. for slot in generate_market_slot_list()} # type: Dict[DateTime, float]
def __init__(self): self.desired_energy_Wh = \ {slot: 0. for slot in generate_market_slot_list()} # type: Dict[DateTime, float] self.total_energy_demanded_wh = 0
def update_sold_bought_energy(self, area: Area): if ConstSettings.GeneralSettings.KEEP_PAST_MARKETS: self.traded_energy[area.uuid] = \ self._calculate_devices_sold_bought_energy_past_markets(area, area.past_markets) self.traded_energy[area.name] = self.traded_energy[area.uuid] self.balancing_traded_energy[area.name] = \ self._calculate_devices_sold_bought_energy_past_markets( area, area.past_balancing_markets) self.traded_energy_profile[area.slug] = \ self._serialize_traded_energy_lists(self.traded_energy, area.uuid) else: # Calculates current market traded energy if area.uuid not in self.traded_energy_current: self.traded_energy_current[area.uuid] = { "sold_energy": {}, "bought_energy": {} } if area.current_market is not None: self.time_slots = [area.current_market.time_slot] self._calculate_devices_sold_bought_energy( self.traded_energy_current[area.uuid], area.current_market) self.traded_energy_current[ area.uuid] = self._serialize_traded_energy_lists( self.traded_energy_current, area.uuid) self.time_slots = generate_market_slot_list(area) # Merges traded energy for the CSV file # TODO: Adapt to not store the full results on D3A. if area.slug not in self.traded_energy_profile: self.traded_energy_profile[area.slug] = \ {"sold_energy": {}, "bought_energy": {}} self._calculate_devices_sold_bought_energy( self.traded_energy_profile[area.slug], area.current_market) self.traded_energy_profile[ area.slug] = self._serialize_traded_energy_lists( self.traded_energy_profile, area.slug) else: traded_energy_current_name = { area.slug: self.traded_energy_current[area.uuid] } self.traded_energy_profile = merge_energy_trade_profile_to_global( traded_energy_current_name, self.traded_energy_profile, generate_market_slot_list(area)) if self._should_export_plots: # Traded energy for plot if area.uuid not in self.traded_energy: self.traded_energy[area.uuid] = { "sold_energy": {}, "bought_energy": {} } self._calculate_devices_sold_bought_energy( self.traded_energy[area.uuid], area.current_market) self.traded_energy[area.name] = self.traded_energy[area.uuid] if area.name not in self.balancing_traded_energy: self.balancing_traded_energy[area.name] = { "sold_energy": {}, "bought_energy": {} } if len(area.past_balancing_markets) > 0: self._calculate_devices_sold_bought_energy( self.balancing_traded_energy[area.name], area.current_balancing_market) self.balancing_traded_energy[ area.uuid] = self.balancing_traded_energy[area.name]
def __init__( self, initial_soc: float = StorageSettings.MIN_ALLOWED_SOC, min_allowed_soc=StorageSettings.MIN_ALLOWED_SOC, battery_capacity_kWh: float = StorageSettings.CAPACITY, max_abs_battery_power_kW: float = StorageSettings.MAX_ABS_POWER, cap_price_strategy: bool = False, initial_selling_rate: Union[ float, dict] = StorageSettings.SELLING_RATE_RANGE.initial, final_selling_rate: Union[ float, dict] = StorageSettings.SELLING_RATE_RANGE.final, initial_buying_rate: Union[ float, dict] = StorageSettings.BUYING_RATE_RANGE.initial, final_buying_rate: Union[ float, dict] = StorageSettings.BUYING_RATE_RANGE.final, loss_per_hour=StorageSettings.LOSS_PER_HOUR, loss_function=StorageSettings.LOSS_FUNCTION, fit_to_limit=True, energy_rate_increase_per_update=None, energy_rate_decrease_per_update=None, update_interval=None, initial_energy_origin: Enum = ESSEnergyOrigin.EXTERNAL, balancing_energy_ratio: tuple = ( BalancingSettings.OFFER_DEMAND_RATIO, BalancingSettings.OFFER_SUPPLY_RATIO)): if update_interval is None: update_interval = \ duration(minutes=ConstSettings.GeneralSettings.DEFAULT_UPDATE_INTERVAL) if min_allowed_soc is None: min_allowed_soc = StorageSettings.MIN_ALLOWED_SOC self.initial_soc = initial_soc validate_storage_device( initial_soc=initial_soc, min_allowed_soc=min_allowed_soc, battery_capacity_kWh=battery_capacity_kWh, max_abs_battery_power_kW=max_abs_battery_power_kW, loss_per_hour=loss_per_hour, loss_function=loss_function, fit_to_limit=fit_to_limit, energy_rate_increase_per_update=energy_rate_increase_per_update, energy_rate_decrease_per_update=energy_rate_decrease_per_update) if isinstance(update_interval, int): update_interval = duration(minutes=update_interval) BidEnabledStrategy.__init__(self) self.offer_update = \ UpdateFrequencyMixin(initial_rate=initial_selling_rate, final_rate=final_selling_rate, fit_to_limit=fit_to_limit, energy_rate_change_per_update=energy_rate_decrease_per_update, update_interval=update_interval) for time_slot in generate_market_slot_list(): validate_storage_device( initial_selling_rate=self.offer_update.initial_rate[time_slot], final_selling_rate=self.offer_update.final_rate[time_slot]) self.bid_update = \ UpdateFrequencyMixin( initial_rate=initial_buying_rate, final_rate=final_buying_rate, fit_to_limit=fit_to_limit, energy_rate_change_per_update=energy_rate_increase_per_update, update_interval=update_interval, rate_limit_object=min ) for time_slot in generate_market_slot_list(): validate_storage_device( initial_buying_rate=self.bid_update.initial_rate[time_slot], final_buying_rate=self.bid_update.final_rate[time_slot]) self.state = \ StorageState(initial_soc=initial_soc, initial_energy_origin=initial_energy_origin, capacity=battery_capacity_kWh, max_abs_battery_power_kW=max_abs_battery_power_kW, loss_per_hour=loss_per_hour, loss_function=loss_function, min_allowed_soc=min_allowed_soc) self.cap_price_strategy = cap_price_strategy self.balancing_energy_ratio = BalancingRatio(*balancing_energy_ratio)
def _validate_rates(self): for time_slot in generate_market_slot_list(): validate_pv_device_price( initial_selling_rate=self.offer_update.initial_rate[time_slot], final_selling_rate=self.offer_update.final_rate[time_slot])
def __init__(self): self.available_energy_kWh = \ {slot: 0. for slot in generate_market_slot_list()}
def __init__( self, avg_power_W, hrs_per_day=None, hrs_of_day=None, fit_to_limit=True, energy_rate_increase_per_update=1, update_interval=duration( minutes=ConstSettings.GeneralSettings.DEFAULT_UPDATE_INTERVAL), initial_buying_rate: Union[ float, dict, str] = ConstSettings.LoadSettings.INITIAL_BUYING_RATE, final_buying_rate: Union[ float, dict, str] = ConstSettings.LoadSettings.FINAL_BUYING_RATE, balancing_energy_ratio: tuple = ( ConstSettings.BalancingSettings.OFFER_DEMAND_RATIO, ConstSettings.BalancingSettings.OFFER_SUPPLY_RATIO), use_market_maker_rate: bool = False): """ Constructor of LoadHoursStrategy :param avg_power_W: Power rating of load device :param hrs_per_day: Daily energy usage :param hrs_of_day: hours of day energy is needed :param fit_to_limit: if set to True, it will make a linear curve following following initial_buying_rate & final_buying_rate :param energy_rate_increase_per_update: Slope of Load bids change per update :param update_interval: Interval after which Load will update its offer :param initial_buying_rate: Starting point of load's preferred buying rate :param final_buying_rate: Ending point of load's preferred buying rate :param use_market_maker_rate: If set to True, Load would track its final buying rate as per utility's trading rate """ # If use_market_maker_rate is true, overwrite final_buying_rate to market maker rate if use_market_maker_rate: final_buying_rate = GlobalConfig.market_maker_rate if isinstance(update_interval, int): update_interval = duration(minutes=update_interval) BidEnabledStrategy.__init__(self) self.bid_update = \ UpdateFrequencyMixin(initial_rate=initial_buying_rate, final_rate=final_buying_rate, fit_to_limit=fit_to_limit, energy_rate_change_per_update=energy_rate_increase_per_update, update_interval=update_interval, rate_limit_object=min) try: validate_load_device(avg_power_W=avg_power_W, hrs_per_day=hrs_per_day, hrs_of_day=hrs_of_day) except D3ADeviceException as e: raise D3ADeviceException(str(e)) for time_slot in generate_market_slot_list(): rate_change = self.bid_update.energy_rate_change_per_update[ time_slot] try: validate_load_device( initial_buying_rate=self.bid_update. initial_rate[time_slot], final_buying_rate=self.bid_update.final_rate[time_slot], energy_rate_increase_per_update=rate_change) except D3ADeviceException as e: raise D3ADeviceException(str(e)) self.state = LoadState() self.avg_power_W = avg_power_W # consolidated_cycle is KWh energy consumed for the entire year self.daily_energy_required = None # Energy consumed during the day ideally should not exceed daily_energy_required self.energy_per_slot_Wh = None self.energy_requirement_Wh = {} # type: Dict[Time, float] self.hrs_per_day = {} # type: Dict[int, int] self.assign_hours_of_per_day(hrs_of_day, hrs_per_day) self.balancing_energy_ratio = BalancingRatio(*balancing_energy_ratio)
def __init__(self): self.desired_energy_Wh = \ {slot: 0. for slot in generate_market_slot_list()} self.total_energy_demanded_wh = 0