예제 #1
0
def auto_scaler(ind_var, ticks):
    ''''this fucntion automatically creates scale and tick distance'''
    value_range = (max(ind_var) - min(ind_var))
    dist_per_tick = Decimal(value_range / ticks)
    exponent = dist_per_tick.adjusted()

    g = ((dist_per_tick * 2).quantize(
        Decimal(str(10**(dist_per_tick.adjusted()))), rounding=ROUND_UP)) / 2
    if round((g / Decimal(10**exponent)), 1) == 2.5 or round(
        (g / Decimal(10**exponent)), 1) == 7.5:
        b = g
    else:
        b = dist_per_tick.quantize(Decimal(str(
            10**(dist_per_tick.adjusted()))),
                                   rounding=ROUND_UP)

    lower_bound = b * (Decimal(min(ind_var)) // b)
    if Decimal(max(ind_var)) % b == 0:
        upper_bound = max(ind_var)
    else:
        upper_bound = b * (1 + Decimal(max(ind_var)) // b)

    print(lower_bound)
    print(upper_bound)
    print(b)
예제 #2
0
def nthroot(A, n:int,*, precision:int=None,decimales:int=None) -> Decimal:
    """Calcula la raiz n-esima de A"""
    #https://en.wikipedia.org/wiki/Nth_root#Logarithmic_computation
    if n>1:
        if A>0:
            DA = Decimal(A)
            #N = Decimal(n)
            if not precision:
                dec = 21 + (decimales if decimales else 0)
                precision = max( 42+dec, ((abs(DA.adjusted())+1)//n ) + dec )
                #21 y 42 números arbitrarios para minimizar
                #errores de redondeo y entregar un numero
                #con precicion más que suficiente para lo
                #que se necesite. Se eligio 42 ya que es la
                #respuesta al universo, y 21 por se la mitad
                #de la respuesta
            with localcontext() as ctx:
                ctx.prec = precision
                resul = Decimal( DA.ln() / n ).exp()
                return resul if decimales is None else round(resul,decimales)
        elif A==0:
            return Decimal(0)
        else:
            if n%2==0:
                raise ValueError("Raiz par de un número negativo")
            return - nthroot(-A, n, precision=precision, decimales=decimales)
    else:
        raise ValueError("El indice de la raiz debe ser mayor que 1")
예제 #3
0
 def parse_market(self, market):
     # {
     #     symbol: "BTC",
     #     contract_code: "BTC190906",
     #     contract_type: "this_week",
     #     contract_size: 100,
     #     price_tick: 0.01,
     #     delivery_date: "20190906",
     #     create_date: "20190823",
     #     contract_status: 1
     # }
     defaultType = self.safe_string_2(self.options, 'fetchMarkets',
                                      'defaultType', 'futures')
     base = baseId = market['symbol']
     if 'contract_type' in market:
         quote = quoteId = 'USD'
         market_type = 'futures'
         expiration = self.expirations[market['contract_type']]
         symbol = f'{baseId}_{expiration}'
     else:
         quote = quoteId = market['contract_code'].split('-')[1]
         market_type = defaultType
         symbol = f'{base}-{quote}'
     active = (self.safe_integer(market, 'contract_status') == 1)
     price_tick = Decimal(market['price_tick'])
     exp = price_tick.adjusted()
     mantissa = price_tick.scaleb(-exp)
     if round(mantissa) == 10:
         price_precision = -exp - 1
     else:
         price_precision = -exp
     return {
         'id': symbol,
         'symbol': symbol,
         'base': base,
         'quote': quote,
         'baseId': baseId,
         'quoteId': quoteId,
         'type': market_type,
         'active': active,
         'precision': {
             'amount': 0,
             'price': price_precision,
         },
         'limits': {
             'amount': {
                 'min': 1,
                 'max': None,
             },
             'price': {
                 'min': None,
                 'max': None
             },
             'cost': {
                 'min': None,
                 'max': None
             }
         },
         'info': market,
     }
예제 #4
0
def calc_price_step_min(auction):
    price_step_min = current_app.config["YAMI_PRICE_STEP_MIN"]
    if auction["price_step_min"] > price_step_min:
        price_step_min = auction["price_step_min"]

    price_reference = auction["price_current_low"] if current_app.config[
        "YAMI_PRICE_STEP_FROM_CURRENT_PRICE"] else auction["price_start"]
    if price_reference == 0:
        return price_step_min

    price_reference = Decimal(price_reference)
    exponent = price_reference.adjusted()
    exp10 = Decimal(1).scaleb(exponent)
    mantissa = price_reference / exp10
    rule = current_app.config["YAMI_PRICE_STEP_RULE"]
    rkeys = sorted(rule.keys())
    for i in range(len(rule) - 1):
        if mantissa >= rkeys[i] and mantissa < rkeys[i + 1]:
            step_from_rule = exp10 * rule[rkeys[i]]
            break
    else:
        step_from_rule = exp10 * rule[rkeys[-1]]
    step_from_rule = int(step_from_rule)

    if step_from_rule > price_step_min:
        price_step_min = step_from_rule
    return price_step_min
예제 #5
0
def scientificformat(text):
    """
    Displays a float in scientific notation.

    If the input float is infinity or NaN, the (platform-dependent) string
    representation of that value will be displayed.

    This is based on the floatformat function in django/template/defaultfilters.py
    """

    try:
        input_val = force_unicode(text)
        d = Decimal(input_val)
    except UnicodeEncodeError:
        return u''
    except InvalidOperation:
        if input_val in special_floats:
            return input_val
        try:
            d = Decimal(force_unicode(float(text)))
        except (ValueError, InvalidOperation, TypeError, UnicodeEncodeError):
            return u''

    try:
        m = int(d) - d
    except (ValueError, OverflowError, InvalidOperation):
        return input_val

    try:
        # for 'normal' sized numbers
        if d.is_zero():
            number = u'0'
        elif ( (d > Decimal('-100') and d < Decimal('-0.1')) or ( d > Decimal('0.1') and d < Decimal('100')) ) :
            # this is what the original floatformat() function does
            sign, digits, exponent = d.quantize(Decimal('.01'), ROUND_HALF_UP).as_tuple()
            digits = [unicode(digit) for digit in reversed(digits)]
            while len(digits) <= abs(exponent):
                digits.append(u'0')
            digits.insert(-exponent, u'.')
            if sign:
                digits.append(u'-')
            number = u''.join(reversed(digits))
        else: 
            # for very small and very large numbers
            sign, digits, exponent = d.as_tuple()
            exponent = d.adjusted()
            digits = [unicode(digit) for digit in digits][:3] # limit to 2 decimal places
            while len(digits) < 3:
                digits.append(u'0')
            digits.insert(1, u'.')
            if sign:
                digits.insert(0, u'-')
            number = u''.join(digits)
            number += u'e' + u'%i' % exponent

        return mark_safe(formats.number_format(number))
    except InvalidOperation:
        return input_val
예제 #6
0
def get_round_price(price: Decimal) -> Decimal:
    one_dollar = Decimal('1.00')
    if price > one_dollar:
        return price.quantize(Decimal('0.01'))

    exponent = price.adjusted()
    shifted = price.shift(abs(exponent))
    rounded = shifted.quantize(Decimal('0.01'))
    return rounded.scaleb(exponent)
예제 #7
0
def round_to_uncertainty(value, uncertainty):
    """Helper function for round_result."""
    # round the uncertainty to 1-2 significant digits
    u = Decimal(uncertainty).normalize()
    exponent = u.adjusted()  # find position of the most significant digit
    precision = (u.as_tuple().digits[0] == 1)  # is the first digit 1?
    u = u.scaleb(-exponent).quantize(Decimal(10)**-precision)
    # round the value to remove excess digits
    return round(Decimal(value).scaleb(-exponent).quantize(u)), u, exponent
예제 #8
0
 def resolve_entry_price(self, info, **kwargs):
     price = self.get("price")
     if price is None:
         raise ValueError(
             f'Expecting a value for entry_price. Got: "{price}"')
     value = Decimal(str(price))
     if value.adjusted() >= 0:
         return value.quantize(Decimal('0.01'))
     return value
예제 #9
0
 def resolve_price_paid(self, info, **kwargs):
     price_paid = self.get("pricePaid")
     if price_paid is None:
         raise ValueError(
             f'Expecting a value for price_paid. Got: "{price_paid}"')
     value = Decimal(str(price_paid))
     if value.adjusted() >= 0:
         return value.quantize(Decimal('0.01'))
     return value
예제 #10
0
 def resolve_stop_limit_price(self, info, **kwargs):
     details = self.get("OrderDetail")[0]
     stop_limit_price = details.get("stopLimitPrice")
     if not stop_limit_price and stop_limit_price != 0:
         return None
     value = Decimal(str(stop_limit_price))
     if value.adjusted() > 0:
         return value.quantize(Decimal('0.01'))
     return value
예제 #11
0
def pow(a, n):
    r = Decimal(1)

    while n:
        if n & 1:
            r *= a
        n >>= 1
        a *= a

        a /= Decimal(10**a.adjusted())
        r /= Decimal(10**r.adjusted())

    return r
예제 #12
0
def fmt_prob(prob, prec=4):
    """
    Format a float as a string in a style suitable for displaying 
    probabilities.
    This is not a particularly quick procedure. If you need to format 
    lots of probabilities, it's probably best to do something cruder.
    
    """
    from decimal import Decimal
    # Quantize the value to the correct precision
    prob = Decimal(str(prob))  #.as_tuple()
    quant = Decimal((0, [
        1,
    ], prob.adjusted() - prec + 1))
    prob = prob.quantize(quant)
    # Format it yourself, because Decimal's to_sci_string is crap
    tup = prob.as_tuple()
    sci_str = "%s%d.%se%d" % ("-" if prob.is_signed() else "", tup.digits[0],
                              "".join(["%d" % dig for dig in tup.digits[1:]
                                       ]), prob.adjusted())
    # Add more spacing for higher precisions
    #fmt_str = " >%ds" % (prec+3)
    return sci_str  #format(sci_str, fmt_str)
예제 #13
0
def get_limit_price(action: OrderAction, price: Decimal, margin: Decimal) -> Decimal:
    one_dollar = Decimal('1.00')

    if price < one_dollar:
        exponent = price.adjusted()
        quantum = Decimal(str(1 / (10**(abs(exponent) + 2))))
        shifted = price.shift(abs(exponent))
        shifted = shifted + margin if action.buying() else shifted - margin
        limit_price = shifted.scaleb(exponent)
        limit_price = limit_price.quantize(quantum)
    else:
        limit_price = price + margin if action.buying() else price - margin
        limit_price = limit_price.quantize(Decimal('0.01'))

    return limit_price
예제 #14
0
    def __round__(self, p: int = 0) -> labfloat:
        """Round labfloat's mean and uncertainty at p decimal places.

        When no arguments are passed or p=0, the mean and uncertainty will round at the
        uncertainty most significant figure to nearest with ties going away from zero
        (Round half away from zero) using Python's ROUND_HALF_UP. If a value is passe to
        p it will round at p decimal places, and if p is greater than the error's most
        significant figure decimal place, the error will be one at the mean's least
        significant figure decimal place.

        Args:
            p (int, optional): The number of decimals to use when rounding. Defaults to 0.

        Returns:
            labfloat: New labfloat with the rounded mean and error.

        """
        current_contex = getcontext()
        setcontext(self.context)

        u = Decimal(str(self._uncertainty))
        m = Decimal(str(self._mean))

        r = p - u.adjusted() * (not p)

        u = round(u, r)

        r = p - u.adjusted() * (not p)

        u += Decimal("1e{}".format(-r)) * (not u)

        m = round(m, r)

        setcontext(current_contex)

        return labfloat(type(self._mean)(m), type(self._uncertainty)(u))
예제 #15
0
def fmt_prob(prob, prec=4):
    """
    Format a float as a string in a style suitable for displaying 
    probabilities.
    This is not a particularly quick procedure. If you need to format 
    lots of probabilities, it's probably best to do something cruder.
    
    """
    from decimal import Decimal
    # Quantize the value to the correct precision
    prob = Decimal(str(prob))#.as_tuple()
    quant = Decimal((0, [1,], prob.adjusted()-prec+1))
    prob = prob.quantize(quant)
    # Format it yourself, because Decimal's to_sci_string is crap
    tup = prob.as_tuple()
    sci_str = "%s%d.%se%d" % ("-" if prob.is_signed() else "", tup.digits[0], "".join(["%d" % dig for dig in tup.digits[1:]]), prob.adjusted())
    # Add more spacing for higher precisions
    #fmt_str = " >%ds" % (prec+3)
    return sci_str #format(sci_str, fmt_str)
예제 #16
0
def general_format(x,
                   precision: int = 2,
                   pad: int = 10,
                   left: bool = False,
                   fmt: str = 'D') -> str:
    """General formatter.

    Parameters
    ----------
    x: str
        The number (string castable) to be formatted
    precision: int
        The precision of the formatter. In sig figs
    pad: int
        The amount to pad the string to
    left_pad: bool
        If False will right pad the string,
    fmt: str
        The delimiting string between the # and the exp
    Returns
    -------
    str
        The formatted number as a string

    """
    x = Decimal(str(x))
    tup = x.as_tuple()
    digits = list(tup.digits[:precision + 1])
    sign = '-' if tup.sign else '+'
    dec = ''.join(map(str, digits[1:]))
    exp = x.adjusted()
    ret = f'{sign}{digits[0]}.{dec}{fmt}{exp}'
    if not pad:
        return ret
    if not left:
        return ret.rjust(pad)
    return ret.ljust(pad)
예제 #17
0
class SigFig:
    """
    Follows the rules of significant figures
    1. All non zero numbers are significant
    2. Zeros located between non-zero digits are significant
    3. Trailing zeros are significant only if the number contains a decimal
    4. Zeros to left of the first nonzero digit are insignificant

    Exact Numbers:
    exact counts don't affect sigfigs in calculations
    and are said to have an infinite number of significant figures

    """
    _Inf = float("inf")

    def __new__(cls, value: Union[str, int, 'SigFig', Decimal], exact=False, precision=None, decimalplaces=None):
        self = object.__new__(cls)

        try:
            self.value = Decimal(value)
        except TypeError as e:
            if hasattr(value, "value"):
                self.value = Decimal(value.value)
            else:
                raise TypeError(f"cant convert from {value!r} to SigFig") from e

        if decimalplaces is None and precision is None:
            if '.' not in str(value):
                # no decimal . remove trailing zeroes
                self.value = self.value.normalize()
        else:
            if precision is not None:
                # if u are given a precision compute the best one given precision
                dp = precision - self.value.adjusted() - 1
                decimalplaces = dp if decimalplaces is None else min(dp, decimalplaces)

            self.value = self.value.__round__(decimalplaces)

        if exact:
            self.precision = SigFig._Inf
            self.decimal_places = SigFig._Inf
        else:
            self.precision = len(self.value.as_tuple().digits)
            self.decimal_places = self.precision - self.value.adjusted() - 1

        return self

    def __str__(self):
        if self.decimal_places == SigFig._Inf:
            return f"{self.value}"

        try:
            return f"{round(self.value, self.decimal_places)}"
        except decimal.InvalidOperation:
            return f"{self.value}"

    def __repr__(self):
        if self.precision == SigFig._Inf:
            return f"SigFig({str(self)!r},exact=True)"
        else:
            return f"SigFig({str(self)!r})"

    def __add__(self, other):
        """addition keeps the number of least precise decimal"""
        if not isinstance(other, self.__class__):
            other = self.__class__(other)
        return SigFig(self.value + other.value, decimalplaces=min(self.decimal_places, other.decimal_places))

    __radd__ = __add__

    def __sub__(self, other):
        """subtraction keeps the number of least precise decimal"""
        if not isinstance(other, self.__class__):
            other = self.__class__(other)
        return SigFig(self.value - other.value, decimalplaces=min(self.decimal_places, other.decimal_places))

    def __rsub__(self, other):
        if not isinstance(other, self.__class__):
            other = self.__class__(other)
        return other - self

    def __mul__(self, other):
        """multiplication keeps the precision of number with the least amount of sigfigs"""
        if not isinstance(other, self.__class__):
            other = self.__class__(other)
        return SigFig(self.value * other.value, precision=min(self.precision, other.precision))

    __rmul__ = __mul__

    def __truediv__(self, other):
        """division keeps the precision of number with the least amount of sigfigs"""
        if not isinstance(other, self.__class__):
            other = self.__class__(other)
        return SigFig(self.value / other.value, precision=min(self.precision, other.precision))

    def __rtruediv__(self, other):
        if not isinstance(other, self.__class__):
            other = self.__class__(other)
        return other / self

    def __neg__(self):
        return SigFig(-self.value, decimalplaces=self.decimalplaces, precision=self.precision)

    def __eq__(self, other):
        if hasattr(other, "value"):
            return self.value == other.value
        return self.value == Decimal(other)

    def __lt__(self, other):
        if hasattr(other, "value"):
            return self.value < other.value
        return self.value < Decimal(other)

    def __le__(self, other):
        if hasattr(other, "value"):
            return self.value <= other.value
        return self.value <= Decimal(other)
def calc_spc(Val, Series):
    # INPUT VALUES
    # replace with user input routine!!!
    targValue = Decimal('{}'.format(Val))
    targSer = '{}'.format(Series)
    print('Target Value: {} \nTarget Series: {}\n'.format(targValue, targSer))
    #
    # Set e-Values List from 1 decades below to 1 decades above target value
    valuesMat = valMat(targSer,
                       targValue.adjusted() - 1,
                       targValue.adjusted() + 1)
    #
    # Closest Value
    closestVal = Decimal('inf')
    for x in range(len(valuesMat)):
        if abs(
                min(valuesMat[x], key=lambda x: abs(x - targValue)) -
                targValue) < abs(closestVal - targValue):
            closestVal = min(valuesMat[x], key=lambda x: abs(x - targValue))
    print("Closest single value: {}\n".format(closestVal))
    #
    # Closest combinations
    # NOTE: only finds the first of equally close pairs!
    tmpSerDev = Decimal('inf')
    tmpParDev = Decimal('inf')
    for m in range(len(valuesMat)):
        for n in range(len(valuesMat[0])):
            for i in range(
                    len(valuesMat)
            ):  # TRY TO CHANGE INNER ROUTINE TO lambda AND COMPARE SPEEDS!
                for j in range(len(valuesMat[0])):
                    series = valuesMat[i][j] + valuesMat[m][n]
                    parallel = (valuesMat[i][j] * valuesMat[m][n]) / (
                        valuesMat[i][j] + valuesMat[m][n])
                    if abs(series - targValue) < tmpSerDev:
                        tmpSerDev = abs(series - targValue)
                        serVal1 = valuesMat[i][j]
                        serVal2 = valuesMat[m][n]
                    if abs(parallel - targValue) < tmpParDev:
                        tmpParDev = abs(parallel - targValue)
                        parVal1 = valuesMat[i][j]
                        parVal2 = valuesMat[m][n]
    closestDev = ((closestVal / targValue - 1) * 100).quantize(Decimal('1.00'))
    serComb = serVal1 + serVal2
    serDevPerc = ((serComb / targValue - 1) * 100).quantize(Decimal('1.00'))
    parComb = ((parVal1 * parVal2) / (parVal1 + parVal2)).quantize(
        Decimal('1.00'))
    parDevPerc = ((parComb / targValue - 1) * 100).quantize(Decimal('1.00'))
    #
    print("Closest series combination: {} + {} = {}".format(
        str(serVal1), str(serVal2), str(serComb)))
    print("Deviation from Target Value: {}%\n".format(str(serDevPerc)))
    #
    print("Closest parallel combination: {} + {} = {}".format(
        str(parVal1), str(parVal2), str(parComb)))
    print("Deviation from Target Value: {}%\n".format(str(parDevPerc)))

    vals_and_dev = {
        "cVal": closestVal,
        "cDev": closestDev,
        "sVal1": serVal1,
        "sVal2": serVal2,
        "sComb": serComb,
        "sDev": serDevPerc,
        "pVal1": parVal1,
        "pVal2": parVal2,
        "pComb": parComb,
        "pDev": parDevPerc
    }
    return vals_and_dev
예제 #19
0
    def parse_market(self, market):
        # {
        #     symbol: "BTC",
        #     contract_code: "BTC190906",
        #     contract_type: "this_week",
        #     contract_size: 100,
        #     price_tick: 0.01,
        #     delivery_date: "20190906",
        #     create_date: "20190823",
        #     contract_status: 1
        # }
        if 'delivery_date' in market:
            market_type = 'futures'
            base = baseId = market['symbol']
            quote = quoteId = 'USD'
            expiration = self.expirations[market['contract_type']]
            symbol = f'{base}_{expiration}'
        else:
            symbol = market['contract_code']
            base, quote = symbol.split('-')
            if quote == 'USDT':
                market_type = 'swap.usdt'
                base, quote = quote, base
            else:
                market_type = 'swap'
            baseId = base
            quoteId = quote

        active = (self.safe_integer(market, 'contract_status') == 1)
        price_tick = Decimal(market['price_tick'])
        exp = price_tick.adjusted()
        mantissa = price_tick.scaleb(-exp)
        if round(mantissa) == 10:
            price_precision = -exp - 1
        else:
            price_precision = -exp
        return {
            'id': symbol,
            'symbol': symbol,
            'base': base,
            'quote': quote,
            'baseId': baseId,
            'quoteId': quoteId,
            'type': market_type,
            'active': active,
            'precision': {
                'amount': 0,
                'price': price_precision,
            },
            'limits': {
                'amount': {
                    'min': 1,
                    'max': None,
                },
                'price': {
                    'min': None,
                    'max': None
                },
                'cost': {
                    'min': None,
                    'max': None
                }
            },
            'info': market,
        }
예제 #20
0
adjusted()                      return the adjusted exponent
as_integer_ratio()              return a pair (n, d) of integers that represent the given Decimal instance as a fraction
as_tuple()                      return a named tuple DecimalTuple(sign, digits, exponent)
copy_abs()                      return the absolute value of the argument
copy_sign(other)                return a copy of the first operand with the sign set to be the same as other
exp()                           return the value of the (natural) exponential function e**x at the given number
quantize(exp, rounding=None)    round a number to a fixed exponent

Rounding modes
decimal.ROUND_CEILING           round towards Infinity
decimal.ROUND_FLOOR             round towards -Infinity
decimal.ROUND_UP                round away from zero
decimal.ROUND_DOWN              round towards zero
decimal.ROUND_HALF_UP           round to nearest with ties going away from zero.
decimal.ROUND_HALF_DOWN         round to nearest with ties going towards zero
decimal.ROUND_HALF_EVEN         round to nearest with ties going to nearest even integer
"""

import decimal
from decimal import Decimal

a = Decimal(-139) + Decimal('-2e-5') + Decimal('1.53')
print(a)
print(a.adjusted())  # the position of the most significant digit with respect to the decimal point
print(a.as_integer_ratio())
print(a.as_tuple())  # sign 0 for positive or 1 for negative
print(a.copy_abs(), a.quantize(Decimal('1.000'), rounding=decimal.ROUND_UP))
b = Decimal(15)
print(a, b, a + b, a - b, a * b, a / b)