From 326ebbe083d57a454ca0105a2306d76f60128e19 Mon Sep 17 00:00:00 2001 From: spyrostz Date: Mon, 10 May 2021 13:40:38 +0200 Subject: [PATCH] D3ASIM-3442: Added the offer fix for floating point precision errors on energy values to the bids. --- src/d3a/models/market/two_sided_pay_as_bid.py | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/d3a/models/market/two_sided_pay_as_bid.py b/src/d3a/models/market/two_sided_pay_as_bid.py index b2efdeaa9..8eb678e60 100644 --- a/src/d3a/models/market/two_sided_pay_as_bid.py +++ b/src/d3a/models/market/two_sided_pay_as_bid.py @@ -16,17 +16,19 @@ along with this program. If not, see . """ import uuid -from typing import Union # noqa from logging import getLogger +from math import isclose +from typing import Union # noqa + +from d3a_interface.constants_limits import ConstSettings -from d3a.models.market import lock_market_action -from d3a.models.market.one_sided import OneSidedMarket -from d3a.d3a_core.exceptions import BidNotFound, InvalidBid, InvalidTrade, MarketException -from d3a.models.market.market_structures import Bid, Trade, TradeBidOfferInfo -from d3a.events.event_structures import MarketEvent from d3a.constants import FLOATING_POINT_TOLERANCE +from d3a.d3a_core.exceptions import BidNotFound, InvalidBid, InvalidTrade, MarketException from d3a.d3a_core.util import short_offer_bid_log_str -from d3a_interface.constants_limits import ConstSettings +from d3a.events.event_structures import MarketEvent +from d3a.models.market import lock_market_action +from d3a.models.market.market_structures import Bid, Trade, TradeBidOfferInfo +from d3a.models.market.one_sided import OneSidedMarket log = getLogger(__name__) @@ -156,7 +158,9 @@ def accept_bid(self, bid: Bid, energy: float = None, raise BidNotFound("During accept bid: " + str(bid)) buyer = market_bid.buyer if buyer is None else buyer - energy = market_bid.energy if energy is None else energy + + if energy is None or isclose(energy, market_bid.energy, abs_tol=1e-8): + energy = market_bid.energy orig_price = bid.original_bid_price if bid.original_bid_price is not None else bid.price residual_bid = None @@ -164,7 +168,8 @@ def accept_bid(self, bid: Bid, energy: float = None, if energy <= 0: raise InvalidTrade("Energy cannot be negative or zero.") elif energy > market_bid.energy: - raise InvalidTrade("Traded energy cannot be more than the bid energy.") + raise InvalidTrade(f"Traded energy ({energy}) cannot be more than the " + f"bid energy ({market_bid.energy}).") elif energy < market_bid.energy: # partial bid trade accepted_bid, residual_bid = self.split_bid(market_bid, energy, orig_price)