# 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/assets.py
# def asset_factory(symbol=None):
#     """
#         Create the appropriate asset based on the symbol.
#     :param symbol: Case-insensitive symbol for the asset being created
#     :return: An object that's a subclass of Asset or None
#     """
# 
#     if symbol is None:
#         return None
# 
#     if isinstance(symbol, Asset):
#         return symbol
# 
#     symbol = symbol.upper()
# 
#     if len(symbol) > 8:
#         if 'P0' in symbol:
#             return Put(symbol)
#         elif 'C0' in symbol:
#             return Call(symbol)
#         else:
#             return Option(symbol)
#     else:
#         return Asset(symbol)
# 
# class Option(Asset):
# 
#     def __init__(self, symbol:str = None, underlying=None, option_type:str = None, strike:float = None, expiration_date = None):
# 
#         if symbol is not None:
# 
#             # if a symbol is provided, then we create the asset based on the symbol
# 
#             r = symbol[::-1]
# 
#             self.strike = float(r[0:8][::-1]) / 1000
#             self.option_type = 'call' if r[8] == 'C' else 'put'
#             self.expiration_date = arrow.get(r[9:15][::-1], 'YYMMDD').format('YYYY-MM-DD')
#             self.underlying = asset_factory(r[15:][::-1])
# 
#         else:
# 
#             # if not then we piece it together with the data we have
# 
#             underlying = asset_factory(underlying)
# 
#             if underlying is None:
#                 raise Exception('Option(Asset): An underlying is required')
# 
#             if option_type is None or option_type not in ['call', 'put']:
#                 raise Exception('Option(Asset): option_type is required and must be `call` or `put`')
# 
#             if strike is None or strike <= 0.0:
#                 raise Exception('Option(Asset): strike is required and must be > 0.0')
# 
#             if expiration_date is None:
#                 raise Exception('Option(Asset): expiration_date is required')
# 
#             # parse the date real quick to check on it
#             try:
#                 expiration_date = arrow.get(expiration_date).format('YYMMDD')
#             except Exception as e:
#                 raise Exception('Option(Asset): expiration_date is invalid')
# 
#             # build the symbol
#             symbol = (underlying.symbol + expiration_date + option_type[0] + str(int(round(strike, 2) * 1000)).zfill(8)).upper()
# 
#             self.underlying = underlying
#             self.option_type = option_type
#             self.strike = float(strike)
#             self.expiration_date = arrow.get(expiration_date, 'YYMMDD').format('YYYY-MM-DD')
# 
#         super(Option, self).__init__(symbol, self.option_type)
# 
#     def get_extrinsic_value(self, underlying_price=None, price=None):
#         return (abs(price) - self.get_intrinsic_value(underlying_price=underlying_price)) if price is not None else None
# 
#     def get_intrinsic_value(self, underlying_price=None):
# 
#         if self.strike is None:
#             return None
# 
#         if underlying_price is None:
#             return None
# 
#         if self.option_type == 'call':
#             return max(underlying_price - self.strike, 0)
#         if self.option_type == 'put':
#             return max(self.strike - underlying_price, 0)
# 
#         return None
# 
#     def get_days_to_expiration(self, as_of_date):
#         return (arrow.get(self.expiration_date) - arrow.get(as_of_date)).days


from .quotes import Quote
from .assets import asset_factory, Option
from math import copysign
        """
        return self.close_cost - self.cost_basis

    @property
    def strike(self): return self.asset.strike if isinstance(self.asset, Option) else None

    @property
    def expiration_date(self): return self.asset.expiration_date if isinstance(self.asset, Option) else None

    @property
    def underlying(self): return self.asset.underlying if isinstance(self.asset, Option) else None

    @property
    def option_type(self): return self.asset.option_type if isinstance(self.asset, Option) else None

    @property
    def symbol(self): return self.asset.symbol
    @property
    def asset_type(self): return self.asset.asset_type


    @property
    def delta(self): return (self.quote.delta * self.quantity * self.multiplier) if isinstance(self.asset, Option) else (1 * self.quantity * self.multiplier)
    @property
    def gamma(self): return (self.quote.gamma * self.quantity * self.multiplier) if isinstance(self.asset, Option) else (0.0)
    @property
    def theta(self): return (self.quote.theta * self.quantity * self.multiplier) if isinstance(self.asset, Option) else (0.0)
    @property
    def vega(self): return (self.quote.vega * self.quantity * self.multiplier) if isinstance(self.asset, Option) else (0.0)
    @property

# 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/assets.py
# def asset_factory(symbol=None):
#     """
#         Create the appropriate asset based on the symbol.
#     :param symbol: Case-insensitive symbol for the asset being created
#     :return: An object that's a subclass of Asset or None
#     """
# 
#     if symbol is None:
#         return None
# 
#     if isinstance(symbol, Asset):
#         return symbol
# 
#     symbol = symbol.upper()
# 
#     if len(symbol) > 8:
#         if 'P0' in symbol:
#             return Put(symbol)
#         elif 'C0' in symbol:
#             return Call(symbol)
#         else:
#             return Option(symbol)
#     else:
#         return Asset(symbol)
# 
# class Option(Asset):
# 
#     def __init__(self, symbol:str = None, underlying=None, option_type:str = None, strike:float = None, expiration_date = None):
# 
#         if symbol is not None:
# 
#             # if a symbol is provided, then we create the asset based on the symbol
# 
#             r = symbol[::-1]
# 
#             self.strike = float(r[0:8][::-1]) / 1000
#             self.option_type = 'call' if r[8] == 'C' else 'put'
#             self.expiration_date = arrow.get(r[9:15][::-1], 'YYMMDD').format('YYYY-MM-DD')
#             self.underlying = asset_factory(r[15:][::-1])
# 
#         else:
# 
#             # if not then we piece it together with the data we have
# 
#             underlying = asset_factory(underlying)
# 
#             if underlying is None:
#                 raise Exception('Option(Asset): An underlying is required')
# 
#             if option_type is None or option_type not in ['call', 'put']:
#                 raise Exception('Option(Asset): option_type is required and must be `call` or `put`')
# 
#             if strike is None or strike <= 0.0:
#                 raise Exception('Option(Asset): strike is required and must be > 0.0')
# 
#             if expiration_date is None:
#                 raise Exception('Option(Asset): expiration_date is required')
# 
#             # parse the date real quick to check on it
#             try:
#                 expiration_date = arrow.get(expiration_date).format('YYMMDD')
#             except Exception as e:
#                 raise Exception('Option(Asset): expiration_date is invalid')
# 
#             # build the symbol
#             symbol = (underlying.symbol + expiration_date + option_type[0] + str(int(round(strike, 2) * 1000)).zfill(8)).upper()
# 
#             self.underlying = underlying
#             self.option_type = option_type
#             self.strike = float(strike)
#             self.expiration_date = arrow.get(expiration_date, 'YYMMDD').format('YYYY-MM-DD')
# 
#         super(Option, self).__init__(symbol, self.option_type)
# 
#     def get_extrinsic_value(self, underlying_price=None, price=None):
#         return (abs(price) - self.get_intrinsic_value(underlying_price=underlying_price)) if price is not None else None
# 
#     def get_intrinsic_value(self, underlying_price=None):
# 
#         if self.strike is None:
#             return None
# 
#         if underlying_price is None:
#             return None
# 
#         if self.option_type == 'call':
#             return max(underlying_price - self.strike, 0)
#         if self.option_type == 'put':
#             return max(self.strike - underlying_price, 0)
# 
#         return None
# 
#     def get_days_to_expiration(self, as_of_date):
#         return (arrow.get(self.expiration_date) - arrow.get(as_of_date)).days


# Path: paperbroker/positions.py
from .quotes import Quote
from .assets import asset_factory, Option
from math import copysign

        """
        return self.close_cost - self.cost_basis

    @property
    def strike(self): return self.asset.strike if isinstance(self.asset, Option) else None

    @property
    def expiration_date(self): return self.asset.expiration_date if isinstance(self.asset, Option) else None

    @property
    def underlying(self): return self.asset.underlying if isinstance(self.asset, Option) else None

    @property
    def option_type(self): return self.asset.option_type if isinstance(self.asset, Option) else None

    @property
    def symbol(self): return self.asset.symbol
    @property
    def asset_type(self): return self.asset.asset_type


    @property
    def delta(self): return (self.quote.delta * self.quantity * self.multiplier) if isinstance(self.asset, Option) else (1 * self.quantity * self.multiplier)
    @property
    def gamma(self): return (self.quote.gamma * self.quantity * self.multiplier) if isinstance(self.asset, Option) else (0.0)
    @property
    def theta(self): return (self.quote.theta * self.quantity * self.multiplier) if isinstance(self.asset, Option) else (0.0)
    @property
    def vega(self): return (self.quote.vega * self.quantity * self.multiplier) if isinstance(self.asset, Option) else (0.0)
    @property

    def rho(self): return (self.quote.rho * self.quantity * self.multiplier) if isinstance(self.asset, Option) else (0.0)