# Path: paperbroker/quotes.py
# class Quote(object):
# 
#     def __init__(self, quote_date, asset, price=None, bid=0.0, ask=0.0, bid_size=0, ask_size=0):
#         self.asset = asset_factory(asset)
#         self.quote_date = quote_date
#         self.bid = float(bid) if bid is not None else 0.0
#         self.ask = float(ask) if ask is not None else 0.0
#         self.bid_size = float(bid_size) if bid_size is not None else 0
#         self.ask_size = float(ask_size) if ask_size is not None else 0
#         self.price = float(price) if price is not None else None
# 
#         if self.price is None and self.bid + self.ask != 0.0:
#             self.price = ((self.bid + self.ask) / 2)
# 
#         self.delta = 1.0
# 
#     def is_priceable(self):
#         return self.price is not None


from math import copysign
from .quotes import Quote


class Estimator:
    """
        THe mother of all estimators, midway between the bid and ask
    """
    def estimate(self, quote:Quote, quantity = None):

        if quote.bid is not None and quote.ask is None and quote.bid > 0.0 and quote.ask > 0.0:
            return round((quote.bid + quote.ask) / 2, 2)

        if quote.price is not None:
            return round(quote.price,2)

        raise Exception('Estimator.estimate: Cannot estimate a price if the bid or ask are None or 0.0')


class MidpointEstimator(Estimator):
    """
        The default estimator if nothing else is available, just passes through to estimator base
    """

class FixedPriceEstimator(Estimator):
    """
        Used to force orders to fill at certain prices, such as for when options expire or testing
    """
    def __init__(self, price= 0.0):
        self.price = price
        return


# Path: paperbroker/quotes.py
# class Quote(object):
# 
#     def __init__(self, quote_date, asset, price=None, bid=0.0, ask=0.0, bid_size=0, ask_size=0):
#         self.asset = asset_factory(asset)
#         self.quote_date = quote_date
#         self.bid = float(bid) if bid is not None else 0.0
#         self.ask = float(ask) if ask is not None else 0.0
#         self.bid_size = float(bid_size) if bid_size is not None else 0
#         self.ask_size = float(ask_size) if ask_size is not None else 0
#         self.price = float(price) if price is not None else None
# 
#         if self.price is None and self.bid + self.ask != 0.0:
#             self.price = ((self.bid + self.ask) / 2)
# 
#         self.delta = 1.0
# 
#     def is_priceable(self):
#         return self.price is not None


# Path: paperbroker/estimators.py
from math import copysign
from .quotes import Quote



class Estimator:
    """
        THe mother of all estimators, midway between the bid and ask
    """
    def estimate(self, quote:Quote, quantity = None):

        if quote.bid is not None and quote.ask is None and quote.bid > 0.0 and quote.ask > 0.0:
            return round((quote.bid + quote.ask) / 2, 2)

        if quote.price is not None:
            return round(quote.price,2)

        raise Exception('Estimator.estimate: Cannot estimate a price if the bid or ask are None or 0.0')


class MidpointEstimator(Estimator):
    """
        The default estimator if nothing else is available, just passes through to estimator base
    """

class FixedPriceEstimator(Estimator):
    """
        Used to force orders to fill at certain prices, such as for when options expire or testing
    """
    def __init__(self, price= 0.0):
        self.price = price
        return


    def estimate(self, quote: Quote, quantity=None):