def to_python(self, value):
     if value is None:
         return value
     try:
         return Currency(value)
     except InvalidOperation as e:
         raise InvalidOperation(_("This value must be a decimal number."))
示例#2
0
 def decimal(data):
     try:
         return dec_con.create_decimal(data).quantize(convert_to._quantizer)
     except TypeError:
         if isinstance(data, np.ndarray):
             return convert_to._quantize_array(data.astype(str))
         else:
             return Decimal.from_float(np.float64(data)).quantize(convert_to._quantizer)
     except InvalidOperation:
         if abs(data) > Decimal('1e20'):
             raise InvalidOperation("Numeric overflow in convert_to.decimal")
         elif data == np.nan or math.nan:
             raise InvalidOperation("NaN encountered in convert_to.decimal")
     except Exception as e:
         print(data)
         print(e)
         raise e
示例#3
0
    def __sqrt__(self):
        # if self.num._sign == 1:
        #     raise InvalidOperation('sqrt(-x), x > 0')
        # return sqrt(self.num)

        if self.num >= 0:
            return sqrt(self.num)
        else:
            raise InvalidOperation('sqrt(-x), x > 0')
示例#4
0
def convert_forecast_amount(amount_string):
    if amount_string.strip() == "":
        return None

    try:
        return Decimal(amount_string.replace(",", "")) * 100
    except InvalidOperation as ex:
        logger.fatal(f"Unable to convert value '{amount_string}' to decimal")
        raise InvalidOperation(ex)
示例#5
0
def parse_latlong(value):
    """
    Given a string with a decimal value, or a float,
    parse to a Decimal and truncate to the number of places
    we're keeping for lat/long values. Return the result.
    """
    val = Decimal(value).quantize(LATLONG_QUANTIZE_PLACES)
    if val > MAX_LATLONG:
        raise InvalidOperation("Lat or long too large")
    return val
示例#6
0
def positive_decimal_validate(number):
    """
    """

    try:
        value = Decimal(number)
        if value < 0:
            raise InvalidOperation(
                '{val} should be a positive number'.format(val=value),
                code='negative number'
            )
    except (ValueError, TypeError):
        raise ValidationError('Enter a valid decimal or integer value',
                              code='invalid number')
示例#7
0
 def decimal(data):
     try:
         return Decimal(data).quantize(convert_to._quantizer)
     except TypeError:
         if isinstance(data, np.ndarray):
             # shape = data.shape
             # output = np.empty(data.flatten().shape, dtype=np.dtype(Decimal))
             # for i, item in enumerate(data.flatten()):
             #     output[i] = Decimal(np.float64(item)).quantize(convert_to._quantizer)
             # return output.reshape(shape)
             return convert_to._quantize_array(data.astype(str))
         else:
             return Decimal.from_float(np.float64(data)).quantize(
                 convert_to._quantizer)
     except InvalidOperation:
         if abs(data) > Decimal('1e15'):
             raise InvalidOperation(
                 "Numeric overflow in convert_to.decimal")
         elif data == np.nan or math.nan:
             raise InvalidOperation("NaN encountered in convert_to.decimal")
     except Exception as e:
         print(data)
         print(e)
         raise e
示例#8
0
def rebalance_portfolio(portfolio, band=Decimal(0.05)):
    """
    Rebalance the portfolio by finding the qty of each asset which falls into the given band that minimizes the
    unallocated size of the portfolio. This approach has a couple drawbacks. For one it enumerates the space. Further,
    it does not optimize for minimizing the tracking error -- it could, I just ran out of time.

    :param portfolio: Valid Portfolio
    :param band: the tracking band for each asset.
    :return: Rebalanced portfolio
    :raises: InvalidOperation("Portfolio cannot be rebalanced")


    >>> json_str = '{"assets": [{"alloc": "0.6", "symbol": "GOOG", "price": "98.0", "qty": 52}, {"alloc": "0.3", "symbol": "AAPL", "price": "22.0", "qty": 136}, {"alloc": "0.1", "symbol": "TSLA", "price": "8.0", "qty": 239}], "size": "10000.0"}'
    >>> port = portfolio_from_json(json_str)
    >>> rebalance_portfolio(port)
    Portfolio(size=Decimal('10000.0'), assets=(Asset(price=Decimal('98.0'), qty=60, alloc=Decimal('0.588'), symbol=u'GOOG'), Asset(price=Decimal('22.0'), qty=140, alloc=Decimal('0.308'), symbol=u'AAPL'), Asset(price=Decimal('8.0'), qty=130, alloc=Decimal('0.104'), symbol=u'TSLA')))

    """
    # makes a list of lists of all asset rebalances that fall within the band
    asset_options = [
        asset_rebalance_options(asset, portfolio.size, band=band)
        for asset in portfolio.assets
    ]
    # makes the cartesian product of the possible rebalances -- yes this can be optimized
    port_universe = product(*asset_options)

    best_port = None
    for port in port_universe:
        total_alloc = sum(map(lambda x: x.alloc, port))
        total_size = sum(map(lambda x: x.qty * x.price, port))
        if total_alloc > 1:
            # We've allocated over 100%
            continue

        if best_port is not None:
            if best_port.size < total_size:
                # means this port is the new max
                best_port = mk_portfolio(total_size, port)
            else:
                continue
        else:
            # NB: we don't need to check that total_size is <= size as checking allocation handles this
            best_port = mk_portfolio(total_size, port)

    if best_port is None:
        raise InvalidOperation("This portfolio cannot be rebalanced!")
    else:
        return best_port
示例#9
0
def extract_number(val: Union[int, float, Decimal, str]) -> Decimal:

    if isinstance(val, (int, float, Decimal)):
        return Decimal(val)

    val = str(val)
    val = re.sub(r'([$,%]|\s)', "", val)

    if val == "-":
        val = "0"

    if re.search(r'^\(\d+(\.\d+)?\)$', val):
        val = "-" + re.sub(r'[()]', "", val)

    try:
        return Decimal(val)
    except InvalidOperation:
        raise InvalidOperation(val)
示例#10
0
 def save(self, commit=True):
     """
     Make sure to parse the geolocation
     """
     # TODO: remove redundnacy, have this rely solely on cleaning method to
     # get the pieces
     geolocation = self.cleaned_data.get('geolocation')
     if not geolocation:
         pieces = (None, None)
     else:
         try:
             pieces = [float(x) for x in geolocation.split(",")]
         except ValueError:
             raise ValueError(
                 "Latitude and longitude must be numeric values")
         except InvalidOperation:
             raise InvalidOperation(
                 "Latitude or longitude have too many digits")
     self.instance.latitude = pieces[0]
     self.instance.longitude = pieces[1]
     return super(LocationAdminForm, self).save(commit)
示例#11
0
def convert_decimal_str(value):
    result = str(value)
    if result == "sNaN":
        raise InvalidOperation("Won't save signalling NaN")
    return result
示例#12
0
def parse_decimal_value(value: str) -> Decimal:
    if not isinstance(value, str):
        raise InvalidOperation("Decimal must be a string")
    return Decimal(sanitize_separators(value))