diff --git a/gsy_framework/constants_limits.py b/gsy_framework/constants_limits.py
index 26994619..98b174a9 100644
--- a/gsy_framework/constants_limits.py
+++ b/gsy_framework/constants_limits.py
@@ -338,7 +338,7 @@ class HeartBeat:
JWT_TOKEN_EXPIRY_IN_SECS = 48 * 3600
DEFAULT_PRECISION = 8
-ENERGY_RATE_PRECISION = 5
+ENERGY_RATE_PRECISION = DEFAULT_PRECISION
# In order to cover conversion and reverse-conversion to 5 decimal points, the tolerance has to be
# 0.00002. That way off-by-one consecutive rounding errors would not be treated as errors, e.g.
# when recalculating the original energy rate in trade chains.
diff --git a/gsy_framework/data_classes.py b/gsy_framework/data_classes.py
index bf783fb6..8b409ae8 100644
--- a/gsy_framework/data_classes.py
+++ b/gsy_framework/data_classes.py
@@ -15,6 +15,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
+
# pylint: disable=invalid-name
# pylint: disable=redefined-builtin
# pylint: disable=too-many-arguments
@@ -31,9 +32,11 @@
from pendulum import DateTime
from gsy_framework.constants_limits import (
- DEFAULT_PRECISION, FLOATING_POINT_TOLERANCE, ENERGY_RATE_PRECISION)
-from gsy_framework.utils import (
- limit_float_precision, datetime_to_string_incl_seconds, str_to_pendulum_datetime)
+ DEFAULT_PRECISION,
+ FLOATING_POINT_TOLERANCE,
+ ENERGY_RATE_PRECISION,
+)
+from gsy_framework.utils import datetime_to_string_incl_seconds, str_to_pendulum_datetime
def json_datetime_serializer(datetime_obj: DateTime) -> Optional[str]:
@@ -45,14 +48,22 @@ def json_datetime_serializer(datetime_obj: DateTime) -> Optional[str]:
class BaseBidOffer:
"""Base class defining shared functionality of Bid and Offer market structures."""
- def __init__(self, id: str, creation_time: DateTime, price: float, energy: float,
- original_price: Optional[float] = None, time_slot: DateTime = None):
+
+ def __init__(
+ self,
+ id: str,
+ creation_time: DateTime,
+ price: float,
+ energy: float,
+ original_price: Optional[float] = None,
+ time_slot: DateTime = None,
+ ):
self.id = str(id)
self.creation_time = creation_time
self.time_slot = time_slot # market slot of creation
- self.original_price = limit_float_precision(original_price or price)
- self.price = limit_float_precision(price)
- self.energy = limit_float_precision(energy)
+ self.original_price = original_price or price
+ self.price = price
+ self.energy = energy
self.type = self.__class__.__name__
@property
@@ -112,18 +123,24 @@ def from_serializable_dict(cls, offer_bid_dict: Dict) -> Union["Offer", "Bid"]:
order_dict_copy.pop("energy_rate", None)
order_dict_copy["creation_time"] = (
str_to_pendulum_datetime(order_dict_copy["creation_time"])
- if order_dict_copy.get("creation_time") else None)
+ if order_dict_copy.get("creation_time")
+ else None
+ )
order_dict_copy["time_slot"] = (
str_to_pendulum_datetime(order_dict_copy["time_slot"])
- if order_dict_copy.get("time_slot") else None)
+ if order_dict_copy.get("time_slot")
+ else None
+ )
if order_dict_copy.get("seller"):
order_dict_copy["seller"] = TraderDetails.from_serializable_dict(
- order_dict_copy["seller"])
+ order_dict_copy["seller"]
+ )
if order_dict_copy.get("buyer"):
order_dict_copy["buyer"] = TraderDetails.from_serializable_dict(
- order_dict_copy["buyer"])
+ order_dict_copy["buyer"]
+ )
if object_type == "Offer":
return Offer(**order_dict_copy)
@@ -143,6 +160,7 @@ class TraderDetails:
Details about the trader. Includes trader name and unique identifier, and also the original
trader for this order.
"""
+
name: str
uuid: str
origin: Optional[str] = None
@@ -150,10 +168,10 @@ class TraderDetails:
def __eq__(self, other: "TraderDetails") -> bool:
return (
- self.name == other.name and
- self.origin == other.origin and
- self.uuid == other.uuid and
- self.origin_uuid == other.origin_uuid
+ self.name == other.name
+ and self.origin == other.origin
+ and self.uuid == other.uuid
+ and self.origin_uuid == other.origin_uuid
)
def serializable_dict(self) -> Dict:
@@ -162,7 +180,7 @@ def serializable_dict(self) -> Dict:
"name": self.name,
"origin": self.origin,
"origin_uuid": self.origin_uuid,
- "uuid": self.uuid
+ "uuid": self.uuid,
}
@staticmethod
@@ -173,11 +191,25 @@ def from_serializable_dict(trader_details: Dict) -> "TraderDetails":
class Offer(BaseBidOffer):
"""Offer class"""
- def __init__(self, id: str, creation_time: DateTime, price: float,
- energy: float, seller: TraderDetails, original_price: Optional[float] = None,
- time_slot: DateTime = None):
- super().__init__(id=id, creation_time=creation_time, price=price, energy=energy,
- original_price=original_price, time_slot=time_slot)
+
+ def __init__(
+ self,
+ id: str,
+ creation_time: DateTime,
+ price: float,
+ energy: float,
+ seller: TraderDetails,
+ original_price: Optional[float] = None,
+ time_slot: DateTime = None,
+ ):
+ super().__init__(
+ id=id,
+ creation_time=creation_time,
+ price=price,
+ energy=energy,
+ original_price=original_price,
+ time_slot=time_slot,
+ )
self.seller = seller
def __hash__(self) -> int:
@@ -186,37 +218,54 @@ def __hash__(self) -> int:
def __repr__(self) -> str:
return (
f"")
+ f" '{self.seller.name} {self.energy_rate}'>"
+ )
def __str__(self) -> str:
- return (f"{{{self.id!s:.6s}}} [origin: {self.seller.origin}] "
- f"[{self.seller.name}]: {self.energy} kWh @ {self.price} "
- f"@ {self.energy_rate}")
+ return (
+ f"{{{self.id!s:.6s}}} [origin: {self.seller.origin}] "
+ f"[{self.seller.name}]: {self.energy} kWh @ {self.price} "
+ f"@ {self.energy_rate}"
+ )
def serializable_dict(self) -> Dict:
"""Return a json serializable representation of the class."""
return {**super().serializable_dict(), "seller": self.seller.serializable_dict()}
def __eq__(self, other: "Offer") -> bool:
- return (self.id == other.id and
- isclose(self.energy_rate, other.energy_rate, rel_tol=FLOATING_POINT_TOLERANCE) and
- isclose(self.energy, other.energy, rel_tol=FLOATING_POINT_TOLERANCE) and
- isclose(self.price, other.price, rel_tol=FLOATING_POINT_TOLERANCE) and
- self.seller == other.seller and
- self.creation_time == other.creation_time and
- self.time_slot == other.time_slot)
+ return (
+ self.id == other.id
+ and isclose(self.energy_rate, other.energy_rate, rel_tol=FLOATING_POINT_TOLERANCE)
+ and isclose(self.energy, other.energy, rel_tol=FLOATING_POINT_TOLERANCE)
+ and isclose(self.price, other.price, rel_tol=FLOATING_POINT_TOLERANCE)
+ and self.seller == other.seller
+ and self.creation_time == other.creation_time
+ and self.time_slot == other.time_slot
+ )
def csv_values(self) -> Tuple:
"""Return values of class members that are needed for creation of CSV export."""
rate = round(self.energy_rate, 4)
- return (self.creation_time, rate, self.energy, self.price, self.seller.name,
- self.seller.origin)
+ return (
+ self.creation_time,
+ rate,
+ self.energy,
+ self.price,
+ self.seller.name,
+ self.seller.origin,
+ )
@classmethod
def csv_fields(cls) -> Tuple:
"""Return labels for csv_values for CSV export."""
- return ("creation_time", "rate [ct./kWh]", "energy [kWh]", "price [ct.]", "seller",
- "seller origin")
+ return (
+ "creation_time",
+ "rate [ct./kWh]",
+ "energy [kWh]",
+ "price [ct.]",
+ "seller",
+ "seller origin",
+ )
@property
def accumulated_grid_fees(self):
@@ -227,19 +276,37 @@ def accumulated_grid_fees(self):
def copy(offer: "Offer") -> "Offer":
"""Return a copy of an offer Object."""
return Offer(
- offer.id, offer.creation_time, offer.price, offer.energy, seller=offer.seller,
- original_price=offer.original_price, time_slot=offer.time_slot)
+ offer.id,
+ offer.creation_time,
+ offer.price,
+ offer.energy,
+ seller=offer.seller,
+ original_price=offer.original_price,
+ time_slot=offer.time_slot,
+ )
class Bid(BaseBidOffer):
"""Bid class."""
- def __init__(self, id: str, creation_time: DateTime, price: float,
- energy: float, buyer: TraderDetails,
- original_price: Optional[float] = None,
- time_slot: Optional[DateTime] = None
- ):
- super().__init__(id=id, creation_time=creation_time, price=price, energy=energy,
- original_price=original_price, time_slot=time_slot)
+
+ def __init__(
+ self,
+ id: str,
+ creation_time: DateTime,
+ price: float,
+ energy: float,
+ buyer: TraderDetails,
+ original_price: Optional[float] = None,
+ time_slot: Optional[DateTime] = None,
+ ):
+ super().__init__(
+ id=id,
+ creation_time=creation_time,
+ price=price,
+ energy=energy,
+ original_price=original_price,
+ time_slot=time_slot,
+ )
self.buyer = buyer
def __hash__(self) -> int:
@@ -264,14 +331,26 @@ def serializable_dict(self) -> Dict:
def csv_values(self) -> Tuple:
"""Return values of class members that are needed for creation of CSV export."""
rate = round(self.energy_rate, 4)
- return (self.creation_time, rate, self.energy, self.price, self.buyer.name,
- self.buyer.origin)
+ return (
+ self.creation_time,
+ rate,
+ self.energy,
+ self.price,
+ self.buyer.name,
+ self.buyer.origin,
+ )
@classmethod
def csv_fields(cls) -> Tuple:
"""Return labels for csv_values for CSV export."""
- return ("creation_time", "rate [ct./kWh]", "energy [kWh]", "price [ct.]", "buyer",
- "buyer origin")
+ return (
+ "creation_time",
+ "rate [ct./kWh]",
+ "energy [kWh]",
+ "price [ct.]",
+ "buyer",
+ "buyer origin",
+ )
@property
def accumulated_grid_fees(self):
@@ -279,15 +358,18 @@ def accumulated_grid_fees(self):
return self.original_price - self.price
def __eq__(self, other: "Bid") -> bool:
- return (self.id == other.id and
- self.buyer == other.buyer and
- self.creation_time == other.creation_time and
- self.time_slot == other.time_slot)
+ return (
+ self.id == other.id
+ and self.buyer == other.buyer
+ and self.creation_time == other.creation_time
+ and self.time_slot == other.time_slot
+ )
@dataclass
class TradeBidOfferInfo:
"""Class that contains information about the original bid or offer."""
+
original_bid_rate: Optional[float]
propagated_bid_rate: Optional[float]
original_offer_rate: Optional[float]
@@ -312,24 +394,33 @@ def from_json(trade_bid_offer_info: Union[str, Dict]) -> "TradeBidOfferInfo":
def __eq__(self, other: "TradeBidOfferInfo") -> bool:
return (
- self.original_offer_rate == other.original_offer_rate and
- self.original_bid_rate == other.original_bid_rate and
- self.propagated_bid_rate == other.propagated_bid_rate and
- self.propagated_offer_rate == other.propagated_offer_rate and
- self.trade_rate == self.trade_rate)
+ self.original_offer_rate == other.original_offer_rate
+ and self.original_bid_rate == other.original_bid_rate
+ and self.propagated_bid_rate == other.propagated_bid_rate
+ and self.propagated_offer_rate == other.propagated_offer_rate
+ and self.trade_rate == self.trade_rate
+ )
class Trade:
"""Trade class."""
- def __init__(self, id: str, creation_time: DateTime,
- seller: TraderDetails, buyer: TraderDetails,
- traded_energy: float, trade_price: float,
- offer: Offer = None,
- bid: Bid = None,
- residual: Optional[Union[Offer, Bid]] = None,
- offer_bid_trade_info: Optional[TradeBidOfferInfo] = None,
- fee_price: Optional[float] = None, time_slot: Optional[DateTime] = None,
- matching_requirements: Optional[Dict] = None):
+
+ def __init__(
+ self,
+ id: str,
+ creation_time: DateTime,
+ seller: TraderDetails,
+ buyer: TraderDetails,
+ traded_energy: float,
+ trade_price: float,
+ offer: Offer = None,
+ bid: Bid = None,
+ residual: Optional[Union[Offer, Bid]] = None,
+ offer_bid_trade_info: Optional[TradeBidOfferInfo] = None,
+ fee_price: Optional[float] = None,
+ time_slot: Optional[DateTime] = None,
+ matching_requirements: Optional[Dict] = None,
+ ):
self.id = str(id)
self.creation_time = creation_time
@@ -342,9 +433,7 @@ def __init__(self, id: str, creation_time: DateTime,
self.seller = seller
self.buyer = buyer
self.matching_requirements = matching_requirements
- self.match_details = {
- "offer": offer, "bid": bid
- }
+ self.match_details = {"offer": offer, "bid": bid}
def __str__(self) -> str:
return (
@@ -356,19 +445,34 @@ def __str__(self) -> str:
f"{self.match_details['offer'].id if self.match_details['offer'] else ''} "
f"{self.match_details['bid'].id if self.match_details['bid'] else ''} "
f"[fee: {self.fee_price} cts.] "
- f"{self.matching_requirements or ''}")
+ f"{self.matching_requirements or ''}"
+ )
@classmethod
def csv_fields(cls) -> Tuple:
"""Return labels for csv_values for CSV export."""
- return ("creation_time", "rate [ct./kWh]", "energy [kWh]", "seller", "seller origin",
- "buyer", "buyer origin")
+ return (
+ "creation_time",
+ "rate [ct./kWh]",
+ "energy [kWh]",
+ "seller",
+ "seller origin",
+ "buyer",
+ "buyer origin",
+ )
def csv_values(self) -> Tuple:
"""Return values of class members that are needed for creation of CSV export."""
rate = round(self.trade_rate, 4)
- return (self.creation_time, rate, self.traded_energy, self.seller.name,
- self.seller.origin, self.buyer.name, self.buyer.origin)
+ return (
+ self.creation_time,
+ rate,
+ self.traded_energy,
+ self.seller.name,
+ self.seller.origin,
+ self.buyer.name,
+ self.buyer.origin,
+ )
def to_json_string(self) -> str:
"""Return json string of the representation."""
@@ -386,23 +490,32 @@ def from_dict(cls, trade_dict: Dict) -> "Trade":
(including offer, bid, residual and datetimes).
"""
trade_dict["offer"] = (
- BaseBidOffer.from_json(trade_dict["offer"]) if trade_dict.get("offer") else None)
+ BaseBidOffer.from_json(trade_dict["offer"]) if trade_dict.get("offer") else None
+ )
trade_dict["bid"] = (
- BaseBidOffer.from_json(trade_dict["bid"]) if trade_dict.get("bid") else None)
+ BaseBidOffer.from_json(trade_dict["bid"]) if trade_dict.get("bid") else None
+ )
trade_dict["residual"] = (
- BaseBidOffer.from_json(trade_dict["residual"]) if trade_dict.get("residual") else None)
+ BaseBidOffer.from_json(trade_dict["residual"]) if trade_dict.get("residual") else None
+ )
trade_dict["creation_time"] = (
str_to_pendulum_datetime(trade_dict["creation_time"])
- if trade_dict.get("creation_time") else None)
+ if trade_dict.get("creation_time")
+ else None
+ )
trade_dict["time_slot"] = (
str_to_pendulum_datetime(trade_dict["time_slot"])
- if trade_dict.get("time_slot") else None)
+ if trade_dict.get("time_slot")
+ else None
+ )
trade_dict["offer_bid_trade_info"] = (
TradeBidOfferInfo.from_json(trade_dict["offer_bid_trade_info"])
- if trade_dict.get("offer_bid_trade_info") else None)
+ if trade_dict.get("offer_bid_trade_info")
+ else None
+ )
if trade_dict["seller"] is not None:
trade_dict["seller"] = TraderDetails.from_serializable_dict(trade_dict["seller"])
@@ -430,16 +543,18 @@ def serializable_dict(self) -> Dict:
"""Return a json serializable representation of the class."""
return {
"type": "Trade",
- "match_type": (
- "Bid" if self.is_bid_trade else "Offer"
- ),
+ "match_type": ("Bid" if self.is_bid_trade else "Offer"),
"id": self.id,
"bid": (
self.match_details["bid"].serializable_dict()
- if self.match_details.get("bid") else None),
+ if self.match_details.get("bid")
+ else None
+ ),
"offer": (
self.match_details["offer"].serializable_dict()
- if self.match_details.get("offer") else None),
+ if self.match_details.get("offer")
+ else None
+ ),
"residual": self.residual.serializable_dict() if self.residual is not None else None,
"energy": self.traded_energy,
"energy_rate": self.trade_rate,
@@ -451,7 +566,9 @@ def serializable_dict(self) -> Dict:
"time_slot": datetime_to_string_incl_seconds(self.time_slot),
"offer_bid_trade_info": (
self.offer_bid_trade_info.serializable_dict()
- if self.offer_bid_trade_info else None)
+ if self.offer_bid_trade_info
+ else None
+ ),
}
@classmethod
@@ -460,43 +577,53 @@ def from_serializable_dict(cls, trade_dict: Dict) -> "Trade":
return Trade(
id=trade_dict["id"],
creation_time=trade_dict["creation_time"],
- seller=trade_dict["seller"], buyer=trade_dict["buyer"],
- traded_energy=trade_dict["energy"], trade_price=trade_dict["price"],
- offer=trade_dict["offer"], bid=trade_dict["bid"],
+ seller=trade_dict["seller"],
+ buyer=trade_dict["buyer"],
+ traded_energy=trade_dict["energy"],
+ trade_price=trade_dict["price"],
+ offer=trade_dict["offer"],
+ bid=trade_dict["bid"],
offer_bid_trade_info=trade_dict.get("offer_bid_trade_info"),
residual=trade_dict.get("residual"),
- time_slot=trade_dict["time_slot"])
+ time_slot=trade_dict["time_slot"],
+ )
def __eq__(self, other: "Trade") -> bool:
return (
- self.id == other.id and
- self.creation_time == other.creation_time and
- self.time_slot == other.time_slot and
- self.match_details["offer"] == other.match_details["offer"] and
- self.match_details["bid"] == other.match_details["bid"] and
- self.seller == other.seller and
- self.buyer == other.buyer and
- self.traded_energy == other.traded_energy and
- self.trade_price == other.trade_price and
- self.residual == other.residual and
- self.offer_bid_trade_info == other.offer_bid_trade_info)
+ self.id == other.id
+ and self.creation_time == other.creation_time
+ and self.time_slot == other.time_slot
+ and self.match_details["offer"] == other.match_details["offer"]
+ and self.match_details["bid"] == other.match_details["bid"]
+ and self.seller == other.seller
+ and self.buyer == other.buyer
+ and self.traded_energy == other.traded_energy
+ and self.trade_price == other.trade_price
+ and self.residual == other.residual
+ and self.offer_bid_trade_info == other.offer_bid_trade_info
+ )
class BalancingOffer(Offer):
"""BalancingOffer class."""
def __repr__(self) -> str:
- return (f"")
+ return (
+ f""
+ )
def __str__(self) -> str:
- return (f"")
+ return (
+ f""
+ )
class BalancingTrade(Trade):
"""BalancingTrade class."""
+
def __str__(self) -> str:
return (
f"{{{self.id!s:.6s}}} [{self.seller.name} -> {self.buyer.name}] "
@@ -510,6 +637,7 @@ def __str__(self) -> str:
@dataclass
class BidOfferMatch:
"""Representation of a market match."""
+
market_id: str
time_slot: str
bid: Bid.serializable_dict
@@ -531,7 +659,7 @@ def serializable_dict(self) -> Dict:
"offer": self.offer,
"selected_energy": self.selected_energy,
"trade_rate": self.trade_rate,
- "matching_requirements": self.matching_requirements
+ "matching_requirements": self.matching_requirements,
}
@classmethod
@@ -546,7 +674,13 @@ def is_valid_dict(cls, bid_offer_match: Dict) -> bool:
"""Check whether a serialized dict can be a valid BidOfferMatch instance."""
is_valid = True
required_arguments = (
- "market_id", "time_slot", "bid", "offer", "selected_energy", "trade_rate")
+ "market_id",
+ "time_slot",
+ "bid",
+ "offer",
+ "selected_energy",
+ "trade_rate",
+ )
if not all(key in bid_offer_match for key in required_arguments):
is_valid = False
elif not isinstance(bid_offer_match["market_id"], str):
@@ -555,8 +689,10 @@ def is_valid_dict(cls, bid_offer_match: Dict) -> bool:
is_valid = False
elif not isinstance(bid_offer_match["trade_rate"], (int, float)):
is_valid = False
- elif not (bid_offer_match.get("matching_requirements") is None or
- isinstance(bid_offer_match.get("matching_requirements"), Dict)):
+ elif not (
+ bid_offer_match.get("matching_requirements") is None
+ or isinstance(bid_offer_match.get("matching_requirements"), Dict)
+ ):
is_valid = False
return is_valid
@@ -569,8 +705,8 @@ def bid_energy(self):
"""
if "bid_requirement" in (self.matching_requirements or {}):
return (
- self.matching_requirements["bid_requirement"].get("energy")
- or self.bid["energy"])
+ self.matching_requirements["bid_requirement"].get("energy") or self.bid["energy"]
+ )
return self.bid["energy"]
@property
@@ -582,29 +718,26 @@ def bid_energy_rate(self):
"""
if "bid_requirement" in (self.matching_requirements or {}):
if "price" in self.matching_requirements["bid_requirement"]:
- return (
- self.matching_requirements["bid_requirement"].get("price") /
- self.bid_energy)
+ return self.matching_requirements["bid_requirement"].get("price") / self.bid_energy
return self.bid["energy_rate"]
@dataclass
class Clearing:
"""Class that contains information about the market clearing."""
+
rate: float
energy: float
def serializable_dict(self):
"""Return a json serializable representation of the class."""
- return {
- "rate": self.rate,
- "energy": self.energy
- }
+ return {"rate": self.rate, "energy": self.energy}
@dataclass
class MarketClearingState:
"""MarketClearingState class."""
+
cumulative_offers: Dict[str, Dict[DateTime, Dict]] = field(default_factory=dict)
cumulative_bids: Dict[str, Dict[DateTime, Dict]] = field(default_factory=dict)
clearing: Dict[str, Dict[DateTime, Clearing]] = field(default_factory=dict)
diff --git a/tests/test_dataclasses.py b/tests/test_dataclasses.py
index bd4e11c5..656ff9bd 100644
--- a/tests/test_dataclasses.py
+++ b/tests/test_dataclasses.py
@@ -15,6 +15,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
+
# pylint: disable=missing-function-docstring
# pylint: disable=missing-class-docstring
# pylint: disable=attribute-defined-outside-init
@@ -22,14 +23,25 @@
import json
import uuid
from copy import deepcopy
+from math import isclose
import pytest
from pendulum import DateTime, datetime
from gsy_framework.data_classes import (
- BidOfferMatch, BaseBidOffer, Offer, Bid, json_datetime_serializer,
- TradeBidOfferInfo, Trade, BalancingOffer, BalancingTrade, Clearing,
- MarketClearingState, TraderDetails)
+ BidOfferMatch,
+ BaseBidOffer,
+ Offer,
+ Bid,
+ json_datetime_serializer,
+ TradeBidOfferInfo,
+ Trade,
+ BalancingOffer,
+ BalancingTrade,
+ Clearing,
+ MarketClearingState,
+ TraderDetails,
+)
from gsy_framework.utils import datetime_to_string_incl_seconds
@@ -56,72 +68,86 @@ def test_serializable_dict():
bid={"type": "bid"},
offer={"type": "offer"},
selected_energy=1,
- trade_rate=1)
- expected_dict = {"market_id": "market_id",
- "time_slot": "2021-10-06T12:00",
- "bid": {"type": "bid"},
- "offer": {"type": "offer"},
- "selected_energy": 1,
- "trade_rate": 1,
- "matching_requirements": None}
+ trade_rate=1,
+ )
+ expected_dict = {
+ "market_id": "market_id",
+ "time_slot": "2021-10-06T12:00",
+ "bid": {"type": "bid"},
+ "offer": {"type": "offer"},
+ "selected_energy": 1,
+ "trade_rate": 1,
+ "matching_requirements": None,
+ }
assert bid_offer_match.serializable_dict() == expected_dict
@staticmethod
def test_is_valid_dict():
"""Test the is_valid_dict method of BidOfferMatch dataclass."""
- bid_offer_match = {"market_id": "market_id",
- "time_slot": "2021-10-06T12:00",
- "bid": {"type": "bid"},
- "offer": {"type": "offer"},
- "selected_energy": 1,
- "trade_rate": 1}
+ bid_offer_match = {
+ "market_id": "market_id",
+ "time_slot": "2021-10-06T12:00",
+ "bid": {"type": "bid"},
+ "offer": {"type": "offer"},
+ "selected_energy": 1,
+ "trade_rate": 1,
+ }
assert BidOfferMatch.is_valid_dict(bid_offer_match)
# Key does not exist
- bid_offer_match = {"market_id": "market_id",
- "time_slot": "2021-10-06T12:00",
- "bid": {"type": "bid"},
- "offer": {"type": "offer"},
- "selected_energy": 1,
- }
+ bid_offer_match = {
+ "market_id": "market_id",
+ "time_slot": "2021-10-06T12:00",
+ "bid": {"type": "bid"},
+ "offer": {"type": "offer"},
+ "selected_energy": 1,
+ }
assert not BidOfferMatch.is_valid_dict(bid_offer_match)
# Wrong type
- bid_offer_match = {"market_id": "market_id",
- "time_slot": "2021-10-06T12:00",
- "bid": {"type": "bid"},
- "offer": {"type": "offer"},
- "selected_energy": 1,
- "trade_rate": ""}
+ bid_offer_match = {
+ "market_id": "market_id",
+ "time_slot": "2021-10-06T12:00",
+ "bid": {"type": "bid"},
+ "offer": {"type": "offer"},
+ "selected_energy": 1,
+ "trade_rate": "",
+ }
assert not BidOfferMatch.is_valid_dict(bid_offer_match)
# No market id
- bid_offer_match = {"market_id": None,
- "time_slot": "2021-10-06T12:00",
- "bid": {"type": "bid"},
- "offer": {"type": "offer"},
- "selected_energy": 1,
- "trade_rate": ""}
+ bid_offer_match = {
+ "market_id": None,
+ "time_slot": "2021-10-06T12:00",
+ "bid": {"type": "bid"},
+ "offer": {"type": "offer"},
+ "selected_energy": 1,
+ "trade_rate": "",
+ }
assert not BidOfferMatch.is_valid_dict(bid_offer_match)
# No selected energy
- bid_offer_match = {"market_id": "market_id",
- "time_slot": "2021-10-06T12:00",
- "bid": {"type": "bid"},
- "offer": {"type": "offer"},
- "selected_energy": None,
- "trade_rate": ""}
+ bid_offer_match = {
+ "market_id": "market_id",
+ "time_slot": "2021-10-06T12:00",
+ "bid": {"type": "bid"},
+ "offer": {"type": "offer"},
+ "selected_energy": None,
+ "trade_rate": "",
+ }
assert not BidOfferMatch.is_valid_dict(bid_offer_match)
@staticmethod
def test_from_dict():
"""Test the from_dict method of BidOfferMatch dataclass."""
- expected_dict = {"market_id": "market_id",
- "time_slot": "2021-10-06T12:00",
- "bid": {"type": "bid"},
- "offer": {"type": "offer"},
- "selected_energy": 1,
- "trade_rate": 1}
+ expected_dict = {
+ "market_id": "market_id",
+ "time_slot": "2021-10-06T12:00",
+ "bid": {"type": "bid"},
+ "offer": {"type": "offer"},
+ "selected_energy": 1,
+ "trade_rate": 1,
+ }
bid_offer_match = BidOfferMatch.from_dict(expected_dict)
assert bid_offer_match.market_id == expected_dict["market_id"]
assert bid_offer_match.time_slot == expected_dict["time_slot"]
@@ -137,8 +163,14 @@ def test_from_dict_returns_none_for_invalid_dict():
@staticmethod
def test_bid_energy():
"""Test whether the bid_energy property returns the correct value."""
- orders_match = BidOfferMatch(bid={"energy": 10}, offer={}, market_id="",
- time_slot="", selected_energy=1, trade_rate=1)
+ orders_match = BidOfferMatch(
+ bid={"energy": 10},
+ offer={},
+ market_id="",
+ time_slot="",
+ selected_energy=1,
+ trade_rate=1,
+ )
assert orders_match.bid_energy == 10
# When there is a bid_requirement, it should be prioritized
@@ -147,15 +179,21 @@ def test_bid_energy():
@staticmethod
def test_bid_energy_rate():
- orders_match = BidOfferMatch(bid={"energy_rate": 2,
- "energy": 1}, offer={}, market_id="",
- time_slot="", selected_energy=1, trade_rate=1)
+ orders_match = BidOfferMatch(
+ bid={"energy_rate": 2, "energy": 1},
+ offer={},
+ market_id="",
+ time_slot="",
+ selected_energy=1,
+ trade_rate=1,
+ )
assert orders_match.bid_energy_rate == 2
# When there is a bid_requirement, it should be prioritized
orders_match.matching_requirements = {"bid_requirement": {"price": 4}}
assert orders_match.bid_energy_rate == (
orders_match.matching_requirements["bid_requirement"]["price"]
- / orders_match.selected_energy)
+ / orders_match.selected_energy
+ )
class TestBaseBidOffer:
@@ -175,59 +213,58 @@ def setup_method(self):
def test_init(self):
"""Test __init__."""
- bid_offer = BaseBidOffer(
- **self.initial_data
- )
+ bid_offer = BaseBidOffer(**self.initial_data)
assert bid_offer.id == str(self.initial_data["id"])
assert bid_offer.creation_time == self.initial_data["creation_time"]
assert bid_offer.price == self.initial_data["price"]
assert bid_offer.energy == self.initial_data["energy"]
assert bid_offer.original_price == self.initial_data["original_price"]
- assert bid_offer.energy_rate == round(
- self.initial_data["price"] / self.initial_data["energy"], 5)
+ assert isclose(
+ bid_offer.energy_rate,
+ self.initial_data["price"] / self.initial_data["energy"],
+ rel_tol=1e-06,
+ )
# Test whether the original_price will resort to the "price" member
self.initial_data.pop("original_price")
- bid_offer = BaseBidOffer(
- **self.initial_data
- )
+ bid_offer = BaseBidOffer(**self.initial_data)
assert bid_offer.original_price == self.initial_data["price"]
def test_update_price(self):
- bid_offer = BaseBidOffer(
- **self.initial_data
- )
+ bid_offer = BaseBidOffer(**self.initial_data)
bid_offer.update_price(30)
assert bid_offer.price == 30
assert bid_offer.energy_rate == 30 / bid_offer.energy
def test_update_energy(self):
- bid_offer = BaseBidOffer(
- **self.initial_data
- )
+ bid_offer = BaseBidOffer(**self.initial_data)
bid_offer.update_energy(40)
assert bid_offer.energy == 40
assert bid_offer.energy_rate == bid_offer.price / 40
def test_to_json_string(self):
bid_offer_keys = {
- "id", "creation_time", "time_slot", "original_price", "price", "energy",
- "type", "energy_rate"}
- bid_offer = BaseBidOffer(
- **self.initial_data
- )
+ "id",
+ "creation_time",
+ "time_slot",
+ "original_price",
+ "price",
+ "energy",
+ "type",
+ "energy_rate",
+ }
+ bid_offer = BaseBidOffer(**self.initial_data)
obj_dict = json.loads(bid_offer.to_json_string())
assert set(obj_dict.keys()) == bid_offer_keys
assert json.dumps(obj_dict, sort_keys=True) == json.dumps(
- {key: getattr(bid_offer, key) for key in bid_offer_keys}, sort_keys=True,
- default=json_datetime_serializer
+ {key: getattr(bid_offer, key) for key in bid_offer_keys},
+ sort_keys=True,
+ default=json_datetime_serializer,
)
def test_serializable_dict(self):
- bid_offer = BaseBidOffer(
- **self.initial_data
- )
+ bid_offer = BaseBidOffer(**self.initial_data)
assert bid_offer.serializable_dict() == {
"type": "BaseBidOffer",
"id": str(bid_offer.id),
@@ -236,29 +273,22 @@ def test_serializable_dict(self):
"energy_rate": bid_offer.energy_rate,
"original_price": bid_offer.original_price,
"creation_time": datetime_to_string_incl_seconds(bid_offer.creation_time),
- "time_slot": datetime_to_string_incl_seconds(bid_offer.time_slot)
+ "time_slot": datetime_to_string_incl_seconds(bid_offer.time_slot),
}
def test_from_json(self):
- offer = Offer(
- **self.initial_data,
- seller=self._seller
- )
+ offer = Offer(**self.initial_data, seller=self._seller)
offer_json = offer.to_json_string()
assert offer == Offer.from_json(offer_json)
- bid = Bid(
- **self.initial_data,
- buyer=self._buyer
- )
+ bid = Bid(**self.initial_data, buyer=self._buyer)
bid_json = bid.to_json_string()
assert bid == Bid.from_json(bid_json)
@pytest.mark.parametrize("time_stamp", [None, DEFAULT_DATETIME])
def test_from_json_deals_with_time_stamps_correctly(self, time_stamp):
updated_initial_data = self.initial_data
- updated_initial_data.update({"time_slot": time_stamp,
- "creation_time": time_stamp})
+ updated_initial_data.update({"time_slot": time_stamp, "creation_time": time_stamp})
bid = Bid(**updated_initial_data, buyer=self._buyer)
bid_json = bid.to_json_string()
bid = Bid.from_json(bid_json)
@@ -288,21 +318,22 @@ def setup_method(self):
"energy": 30,
"original_price": 8,
"seller": TraderDetails("seller", str(uuid.uuid4())),
- "time_slot": DEFAULT_DATETIME
+ "time_slot": DEFAULT_DATETIME,
}
def test_init(self):
- offer = Offer(
- **self.initial_data
- )
+ offer = Offer(**self.initial_data)
assert offer.id == str(self.initial_data["id"])
assert offer.creation_time == self.initial_data["creation_time"]
assert offer.time_slot == self.initial_data["time_slot"]
assert offer.price == self.initial_data["price"]
assert offer.energy == self.initial_data["energy"]
- assert offer.original_price == self.initial_data["original_price"]
- assert offer.energy_rate == round(
- self.initial_data["price"] / self.initial_data["energy"], 5)
+ assert isclose(offer.original_price, self.initial_data["original_price"])
+ assert isclose(
+ offer.energy_rate,
+ self.initial_data["price"] / self.initial_data["energy"],
+ rel_tol=1e-06,
+ )
assert offer.seller.name == "seller"
assert offer.seller.uuid == self.initial_data["seller"].uuid
assert offer.seller.origin is None
@@ -312,23 +343,25 @@ def test_hash(self):
offer = Offer(
**self.initial_data,
)
- assert offer.__hash__() == hash(offer.id)
+ assert hash(offer) == hash(offer.id)
def test_repr(self):
offer = Offer(
**self.initial_data,
)
- assert (repr(offer) ==
- f"")
+ assert (
+ repr(offer) == f""
+ )
def test_str(self):
offer = Offer(
**self.initial_data,
)
- assert (str(offer) ==
- f"{{{offer.id!s:.6s}}} [origin: {offer.seller.origin}] "
- f"[{offer.seller.name}]: {offer.energy} kWh @ {offer.price} @ {offer.energy_rate}")
+ assert (
+ str(offer) == f"{{{offer.id!s:.6s}}} [origin: {offer.seller.origin}] "
+ f"[{offer.seller.name}]: {offer.energy} kWh @ {offer.price} @ {offer.energy_rate}"
+ )
def test_serializable_dict(self):
offer = Offer(
@@ -343,7 +376,7 @@ def test_serializable_dict(self):
"original_price": offer.original_price,
"creation_time": datetime_to_string_incl_seconds(offer.creation_time),
"seller": offer.seller.serializable_dict(),
- "time_slot": datetime_to_string_incl_seconds(offer.time_slot)
+ "time_slot": datetime_to_string_incl_seconds(offer.time_slot),
}
def test_from_dict(self):
@@ -353,36 +386,38 @@ def test_from_dict(self):
assert Offer.from_dict(offer.serializable_dict()) == offer
def test_eq(self):
- offer = Offer(
- **self.initial_data
- )
- other_offer = Offer(
- **self.initial_data
- )
+ offer = Offer(**self.initial_data)
+ other_offer = Offer(**self.initial_data)
assert offer == other_offer
other_offer.id = "other_id"
assert offer != other_offer
def test_csv_values(self):
- offer = Offer(
- **self.initial_data
- )
+ offer = Offer(**self.initial_data)
rate = round(offer.energy_rate, 4)
assert offer.csv_values() == (
- offer.creation_time, rate, offer.energy, offer.price, offer.seller.name,
- offer.seller.origin)
+ offer.creation_time,
+ rate,
+ offer.energy,
+ offer.price,
+ offer.seller.name,
+ offer.seller.origin,
+ )
@staticmethod
def test_csv_fields():
- assert (Offer.csv_fields() ==
- ("creation_time", "rate [ct./kWh]", "energy [kWh]", "price [ct.]", "seller",
- "seller origin"))
+ assert Offer.csv_fields() == (
+ "creation_time",
+ "rate [ct./kWh]",
+ "energy [kWh]",
+ "price [ct.]",
+ "seller",
+ "seller origin",
+ )
def test_copy(self):
- offer = Offer(
- **self.initial_data
- )
+ offer = Offer(**self.initial_data)
second_offer = Offer.copy(offer)
assert offer == second_offer
@@ -400,51 +435,46 @@ def setup_method(self):
"energy": 30,
"original_price": 8,
"buyer": TraderDetails("buyer", str(uuid.uuid4())),
- "time_slot": DEFAULT_DATETIME
+ "time_slot": DEFAULT_DATETIME,
}
def test_init(self):
- bid = Bid(
- **self.initial_data
- )
+ bid = Bid(**self.initial_data)
assert bid.id == str(self.initial_data["id"])
assert bid.creation_time == self.initial_data["creation_time"]
assert bid.price == self.initial_data["price"]
assert bid.energy == self.initial_data["energy"]
assert bid.original_price == self.initial_data["original_price"]
- assert bid.energy_rate == round(
- self.initial_data["price"] / self.initial_data["energy"], 5)
+ assert isclose(
+ bid.energy_rate,
+ self.initial_data["price"] / self.initial_data["energy"],
+ rel_tol=1e-06,
+ )
assert bid.buyer.name == "buyer"
assert bid.buyer.uuid == self.initial_data["buyer"].uuid
assert bid.buyer.origin is None
assert bid.buyer.origin_uuid is None
def test_hash(self):
- bid = Bid(
- **self.initial_data
- )
- assert bid.__hash__() == hash(bid.id)
+ bid = Bid(**self.initial_data)
+ assert hash(bid) == hash(bid.id)
def test_repr(self):
- bid = Bid(
- **self.initial_data
+ bid = Bid(**self.initial_data)
+ assert (
+ repr(bid) == f""
)
- assert (repr(bid) ==
- f"")
def test_str(self):
- bid = Bid(
- **self.initial_data
+ bid = Bid(**self.initial_data)
+ assert (
+ str(bid) == f"{{{bid.id!s:.6s}}} [origin: {bid.buyer.origin}] [{bid.buyer.name}] "
+ f"{bid.energy} kWh @ {bid.price} {bid.energy_rate}"
)
- assert (str(bid) ==
- f"{{{bid.id!s:.6s}}} [origin: {bid.buyer.origin}] [{bid.buyer.name}] "
- f"{bid.energy} kWh @ {bid.price} {bid.energy_rate}")
def test_serializable_dict(self):
- bid = Bid(
- **self.initial_data
- )
+ bid = Bid(**self.initial_data)
assert bid.serializable_dict() == {
"type": "Bid",
@@ -455,7 +485,7 @@ def test_serializable_dict(self):
"original_price": bid.original_price,
"creation_time": datetime_to_string_incl_seconds(bid.creation_time),
"buyer": bid.buyer.serializable_dict(),
- "time_slot": datetime_to_string_incl_seconds(bid.time_slot)
+ "time_slot": datetime_to_string_incl_seconds(bid.time_slot),
}
def test_from_dict(self):
@@ -465,30 +495,35 @@ def test_from_dict(self):
assert Bid.from_dict(bid.serializable_dict()) == bid
def test_eq(self):
- bid = Bid(
- **self.initial_data
- )
- other_bid = Bid(
- **self.initial_data
- )
+ bid = Bid(**self.initial_data)
+ other_bid = Bid(**self.initial_data)
assert bid == other_bid
other_bid.id = "other_id"
assert bid != other_bid
def test_csv_values(self):
- bid = Bid(
- **self.initial_data
- )
+ bid = Bid(**self.initial_data)
rate = round(bid.energy_rate, 4)
- assert bid.csv_values() == (bid.creation_time, rate, bid.energy, bid.price, bid.buyer.name,
- bid.buyer.origin)
+ assert bid.csv_values() == (
+ bid.creation_time,
+ rate,
+ bid.energy,
+ bid.price,
+ bid.buyer.name,
+ bid.buyer.origin,
+ )
@staticmethod
def test_csv_fields():
- assert (Bid.csv_fields() ==
- ("creation_time", "rate [ct./kWh]", "energy [kWh]", "price [ct.]", "buyer",
- "buyer origin"))
+ assert Bid.csv_fields() == (
+ "creation_time",
+ "rate [ct./kWh]",
+ "energy [kWh]",
+ "price [ct.]",
+ "buyer",
+ "buyer origin",
+ )
def test_accumulated_grid_fees(self):
bid = Bid(**self.initial_data)
@@ -498,20 +533,16 @@ def test_accumulated_grid_fees(self):
class TestTradeBidOfferInfo:
@staticmethod
def test_to_json_string():
- trade_bid_offer_info = TradeBidOfferInfo(
- 1, 1, 1, 1, 1
+ trade_bid_offer_info = TradeBidOfferInfo(1, 1, 1, 1, 1)
+ assert trade_bid_offer_info.to_json_string() == json.dumps(
+ trade_bid_offer_info.serializable_dict()
)
- assert (trade_bid_offer_info.to_json_string() ==
- json.dumps(trade_bid_offer_info.serializable_dict()))
@staticmethod
def test_from_json():
- trade_bid_offer_info = TradeBidOfferInfo(
- 1, 1, 1, 1, 1
- )
+ trade_bid_offer_info = TradeBidOfferInfo(1, 1, 1, 1, 1)
trade_bid_offer_info_json = trade_bid_offer_info.to_json_string()
- assert (TradeBidOfferInfo.from_json(trade_bid_offer_info_json) ==
- trade_bid_offer_info)
+ assert TradeBidOfferInfo.from_json(trade_bid_offer_info_json) == trade_bid_offer_info
class TestTrade:
@@ -526,42 +557,53 @@ def setup_method(self):
"buyer": self._buyer,
"traded_energy": 1,
"trade_price": 1,
- "matching_requirements": {"requirement": "value"}}
+ "matching_requirements": {"requirement": "value"},
+ }
def test_str(self):
trade = Trade(**self.initial_data)
- assert (str(trade) ==
- f"{{{trade.id!s:.6s}}} [origin: {trade.seller.origin} -> {trade.buyer.origin}] "
- f"[{trade.seller.name} -> {trade.buyer.name}] {trade.traded_energy} kWh"
- f" @ {trade.trade_price} {round(trade.trade_rate, 8)} "
- f"{trade.match_details['offer'].id} [fee: {trade.fee_price} cts.] "
- f"{trade.matching_requirements or ''}")
+ assert (
+ str(trade)
+ == f"{{{trade.id!s:.6s}}} [origin: {trade.seller.origin} -> {trade.buyer.origin}] "
+ f"[{trade.seller.name} -> {trade.buyer.name}] {trade.traded_energy} kWh"
+ f" @ {trade.trade_price} {round(trade.trade_rate, 8)} "
+ f"{trade.match_details['offer'].id} [fee: {trade.fee_price} cts.] "
+ f"{trade.matching_requirements or ''}"
+ )
@staticmethod
def test_csv_fields():
assert Trade.csv_fields() == (
- "creation_time", "rate [ct./kWh]", "energy [kWh]", "seller", "seller origin", "buyer",
- "buyer origin")
+ "creation_time",
+ "rate [ct./kWh]",
+ "energy [kWh]",
+ "seller",
+ "seller origin",
+ "buyer",
+ "buyer origin",
+ )
def test_csv_values(self):
trade = Trade(**self.initial_data)
rate = round(trade.trade_rate, 4)
- assert (trade.csv_values() ==
- (trade.creation_time, rate, trade.traded_energy, trade.seller.name,
- trade.seller.origin, trade.buyer.name, trade.buyer.origin))
+ assert trade.csv_values() == (
+ trade.creation_time,
+ rate,
+ trade.traded_energy,
+ trade.seller.name,
+ trade.seller.origin,
+ trade.buyer.name,
+ trade.buyer.origin,
+ )
def test_to_json_string(self):
trade = Trade(**self.initial_data)
assert trade.to_json_string() == json.dumps(trade.serializable_dict())
def test_from_json(self):
- trade = Trade(
- **self.initial_data
- )
+ trade = Trade(**self.initial_data)
trade.residual = deepcopy(trade.match_details["offer"])
- trade.offer_bid_trade_info = TradeBidOfferInfo(
- 1, 1, 1, 1, 1
- )
+ trade.offer_bid_trade_info = TradeBidOfferInfo(1, 1, 1, 1, 1)
trade_json_str = trade.to_json_string()
assert Trade.from_json(trade_json_str) == trade
@@ -569,17 +611,14 @@ def test_from_json(self):
@pytest.mark.parametrize("time_stamp", [None, DEFAULT_DATETIME])
def test_from_json_deals_with_time_stamps_correctly(self, time_stamp):
updated_initial_data = self.initial_data
- updated_initial_data.update({"time_slot": time_stamp,
- "creation_time": time_stamp})
+ updated_initial_data.update({"time_slot": time_stamp, "creation_time": time_stamp})
trade = Trade(**updated_initial_data)
trade_json = trade.to_json_string()
trade = Trade.from_json(trade_json)
assert trade.creation_time == time_stamp
def test_is_bid_trade(self):
- trade = Trade(
- **self.initial_data
- )
+ trade = Trade(**self.initial_data)
assert trade.is_bid_trade is False
trade.match_details["bid"] = Bid("id", DateTime.now(), 1, 2, self._buyer)
@@ -587,9 +626,7 @@ def test_is_bid_trade(self):
assert trade.is_bid_trade is True
def test_is_offer_trade(self):
- trade = Trade(
- **self.initial_data
- )
+ trade = Trade(**self.initial_data)
assert trade.is_offer_trade is True
trade.match_details["bid"] = Bid("id", DateTime.now(), 1, 2, self._buyer)
@@ -617,7 +654,7 @@ def test_serializable_dict(self):
"trade_price": 1,
"fee_price": 2,
"creation_time": DEFAULT_DATETIME,
- "time_slot": DEFAULT_DATETIME
+ "time_slot": DEFAULT_DATETIME,
}
)
assert trade.serializable_dict() == {
@@ -634,18 +671,18 @@ def test_serializable_dict(self):
"name": trade.buyer.name,
"uuid": trade.buyer.uuid,
"origin": trade.buyer.origin,
- "origin_uuid": trade.buyer.origin_uuid
+ "origin_uuid": trade.buyer.origin_uuid,
},
"seller": {
"name": trade.seller.name,
"uuid": trade.seller.uuid,
"origin": trade.seller.origin,
- "origin_uuid": trade.seller.origin_uuid
+ "origin_uuid": trade.seller.origin_uuid,
},
"fee_price": trade.fee_price,
"creation_time": datetime_to_string_incl_seconds(trade.creation_time),
"time_slot": datetime_to_string_incl_seconds(trade.creation_time),
- "offer_bid_trade_info": None
+ "offer_bid_trade_info": None,
}
@@ -658,39 +695,41 @@ def setup_method(self):
"energy": 30,
"original_price": 8,
"seller": TraderDetails("seller", str(uuid.uuid4())),
- "time_slot": DEFAULT_DATETIME
+ "time_slot": DEFAULT_DATETIME,
}
def test_repr(self):
offer = BalancingOffer(**self.initial_data)
- assert (repr(offer) ==
- f"")
+ assert (
+ repr(offer) == f""
+ )
def test_str(self):
offer = BalancingOffer(**self.initial_data)
- assert (str(offer) ==
- f"")
+ assert (
+ str(offer) == f""
+ )
class TestBalancingTrade(TestTrade):
def test_str(self):
trade = BalancingTrade(**self.initial_data)
- assert (str(trade) ==
- f"{{{trade.id!s:.6s}}} [{trade.seller.name} -> {trade.buyer.name}] "
- f"{trade.traded_energy} kWh @ {trade.trade_price}"
- f" {trade.trade_rate} {trade.match_details['offer'].id} ")
+ assert (
+ str(trade) == f"{{{trade.id!s:.6s}}} [{trade.seller.name} -> {trade.buyer.name}] "
+ f"{trade.traded_energy} kWh @ {trade.trade_price}"
+ f" {trade.trade_rate} {trade.match_details['offer'].id} "
+ )
class TestClearing:
@staticmethod
def test_serializable_dict():
clearing = Clearing(energy=1, rate=1)
- assert clearing.serializable_dict() == {
- "energy": 1, "rate": 1}
+ assert clearing.serializable_dict() == {"energy": 1, "rate": 1}
class TestMarketClearingState: