Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions gsy_framework/data_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from dataclasses import dataclass, field, asdict
from math import isclose
from typing import Dict, Optional, Tuple, Union

from decimal import Decimal
from pendulum import DateTime

from gsy_framework.constants_limits import (
Expand Down Expand Up @@ -641,7 +641,7 @@ class BidOfferMatch:
market_id: str
time_slot: str
bid: Bid.serializable_dict
selected_energy: float
selected_energy: Decimal
offer: Offer.serializable_dict
trade_rate: float
matching_requirements: Optional[Dict] = None
Expand All @@ -657,7 +657,7 @@ def serializable_dict(self) -> Dict:
"time_slot": self.time_slot,
"bid": self.bid,
"offer": self.offer,
"selected_energy": self.selected_energy,
"selected_energy": float(self.selected_energy),
"trade_rate": self.trade_rate,
"matching_requirements": self.matching_requirements,
}
Expand Down Expand Up @@ -685,7 +685,7 @@ def is_valid_dict(cls, bid_offer_match: Dict) -> bool:
is_valid = False
elif not isinstance(bid_offer_match["market_id"], str):
is_valid = False
elif not isinstance(bid_offer_match["selected_energy"], (int, float)):
elif not isinstance(bid_offer_match["selected_energy"], (int, float, Decimal)):
is_valid = False
elif not isinstance(bid_offer_match["trade_rate"], (int, float)):
is_valid = False
Expand Down
42 changes: 24 additions & 18 deletions gsy_framework/matching_algorithms/pay_as_bid_matching_algorithm.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from decimal import Decimal
from typing import Dict, List, Optional

from gsy_framework.constants_limits import FLOATING_POINT_TOLERANCE
Expand All @@ -16,8 +17,9 @@ class PayAsBidMatchingAlgorithm(BaseMatchingAlgorithm):
"""

@staticmethod
def _match_one_bid_one_offer(offer: Dict, bid: Dict, available_order_energy: Dict,
market_id: str, time_slot: str) -> Optional[BidOfferMatch]:
def _match_one_bid_one_offer(
offer: Dict, bid: Dict, available_order_energy: Dict, market_id: str, time_slot: str
) -> Optional[BidOfferMatch]:
"""
Try to match one bid with one offer, and at the same time update the dict with the
already selected order energy in order to be able to reuse the same order in future
Expand All @@ -27,31 +29,33 @@ def _match_one_bid_one_offer(offer: Dict, bid: Dict, available_order_energy: Dic
return None

if bid["id"] not in available_order_energy:
available_order_energy[bid["id"]] = bid["energy"]
available_order_energy[bid["id"]] = Decimal(bid["energy"])
if offer["id"] not in available_order_energy:
available_order_energy[offer["id"]] = offer["energy"]
available_order_energy[offer["id"]] = Decimal(offer["energy"])
offer_energy = available_order_energy[offer["id"]]
bid_energy = available_order_energy[bid["id"]]

selected_energy = min(offer_energy, bid_energy)
selected_energy = Decimal(min(offer_energy, bid_energy))
if selected_energy <= FLOATING_POINT_TOLERANCE:
return None

available_order_energy[bid["id"]] -= selected_energy
available_order_energy[offer["id"]] -= selected_energy
assert all(v >= -FLOATING_POINT_TOLERANCE
for v in available_order_energy.values())
assert all(v >= -FLOATING_POINT_TOLERANCE for v in available_order_energy.values())

return BidOfferMatch(
market_id=market_id,
time_slot=time_slot,
bid=bid, offer=offer,
bid=bid,
offer=offer,
selected_energy=selected_energy,
trade_rate=bid.get("energy_rate"))
trade_rate=bid.get("energy_rate"),
)

@classmethod
def _calculate_bid_offer_matches_for_one_market_timeslot(
cls, market_id: str, time_slot: str, data: Dict) -> List[BidOfferMatch]:
cls, market_id: str, time_slot: str, data: Dict
) -> List[BidOfferMatch]:
"""
Calculate all possible matches for one market slot.
"""
Expand All @@ -74,8 +78,10 @@ def _calculate_bid_offer_matches_for_one_market_timeslot(
if possible_match:
bid_offer_matches.append(possible_match)

if (offer["id"] in available_order_energy and
available_order_energy[offer["id"]] <= FLOATING_POINT_TOLERANCE):
if (
offer["id"] in available_order_energy
and available_order_energy[offer["id"]] <= FLOATING_POINT_TOLERANCE
):
break
return bid_offer_matches

Expand All @@ -84,9 +90,9 @@ def get_matches_recommendations(cls, matching_data: Dict) -> List:
bid_offer_matches = []
for market_id, time_slot_data in matching_data.items():
for time_slot, data in time_slot_data.items():
bid_offer_matches.extend(cls._calculate_bid_offer_matches_for_one_market_timeslot(
market_id, time_slot, data
))
return [
match.serializable_dict() for match in bid_offer_matches
]
bid_offer_matches.extend(
cls._calculate_bid_offer_matches_for_one_market_timeslot(
market_id, time_slot, data
)
)
return [match.serializable_dict() for match in bid_offer_matches]