Exemplo n.º 1
0
def cncapital(value, capital=True, prefix=False, classical=None):
    '''
    人民币数字转汉字表示 Ver 0.03
    作者: qianjin(AT)ustc.edu
    版权声明:
        只要保留本代码最初作者的电子邮件即可,随便用。用得爽的话,不反对请
    作者吃一顿。

    参数:
    capital:    True   大写汉字金额
                False  一般汉字金额
    classical:  True   圆
                False  元
    prefix:     True   以'人民币'开头
                False, 无开头
    '''

    # 转换为Decimal
    if isinstance(value, float):
        msg = '''
        由于浮点数精度问题,请使用考虑使用字符串,或者 decimal.Decimal 类。
        因使用浮点数造成误差而带来的可能风险和损失作者概不负责。
        '''
        warnings.warn(msg, UserWarning)
        value = Decimal(str(value))
    elif isinstance(value, int):
        value = Decimal(value)
    elif not isinstance(value, Decimal):
        try:
            value = Decimal(str(value))
        except:
            raise TypeError('无法转换为Decimal:%s' % value.__repr__())

    # 截断多余小数
    value = Decimal(value).quantize(Decimal('0.01'))

    # 默认大写金额用圆,一般汉字金额用元
    if classical is None:
        classical = True if capital else False

    # 汉字金额前缀
    if prefix is True:
        prefix = '人民币'
    else:
        prefix = ''

    # 汉字金额字符定义
    dunit = ('角', '分')
    if capital:
        num = ('零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖')
        iunit = [None, '拾', '佰', '仟', '万', '拾', '佰', '仟',
                 '亿', '拾', '佰', '仟', '万', '拾', '佰', '仟']
    else:
        num = ('〇', '一', '二', '三', '四', '五', '六', '七', '八', '九')
        iunit = [None, '十', '百', '千', '万', '十', '百', '千',
                 '亿', '十', '百', '千', '万', '十', '百', '千']

    if classical:
        iunit[0] = '圆' if classical else '元'

    # 处理负数
    if value < 0:
        prefix += '负'          # 输出前缀,加负
        value = - value         # 取正数部分,无须过多考虑正负数舍入
                                # assert - value + value == 0

    # 转化为字符串
    s = str(value)

    if len(s) > 19:
        raise ValueError('金额太大了,不知道该怎么表达。')

    istr, dstr = s.split('.')           # 小数部分和整数部分分别处理
    istr = istr[::-1]                   # 翻转整数部分字符串

    so = []     # 用于记录转换结果

    # 零
    if value == 0:
        return prefix + num[0] + iunit[0]

    haszero = False     # 用于标记零的使用
    if dstr == '00':
        haszero = True  # 如果无小数部分,则标记加过零,避免出现“圆零整”

    # 处理小数部分
    # 分
    if dstr[1] != '0':
        so.append(dunit[1])
        so.append(num[int(dstr[1])])
    else:
        so.append('整')         # 无分,则加“整”
    # 角
    if dstr[0] != '0':
        so.append(dunit[0])
        so.append(num[int(dstr[0])])
    elif dstr[1] != '0':
        so.append(num[0])       # 无角有分,添加“零”
        haszero = True          # 标记加过零了

    # 无整数部分
    if istr == '0':
        if haszero:             # 既然无整数部分,那么去掉角位置上的零
            so.pop()
        so.append(prefix)       # 加前缀
        so.reverse()            # 翻转
        return ''.join(so)

    # 处理整数部分
    for i, n in enumerate(istr):
        n = int(n)
        if i % 4 == 0:          # 在圆、万、亿等位上,即使是零,也必须有单位
            if i == 8 and so[-1] == iunit[4]:   # 亿和万之间全部为零的情况
                so.pop()                        # 去掉万
            so.append(iunit[i])
            if n == 0:                          # 处理这些位上为零的情况
                if not haszero:                 # 如果以前没有加过零
                    so.insert(-1, num[0])       # 则在单位后面加零
                    haszero = True              # 标记加过零了
            else:                               # 处理不为零的情况
                so.append(num[n])
                haszero = False                 # 重新开始标记加零的情况
        else:                                   # 在其他位置上
            if n != 0:                          # 不为零的情况
                so.append(iunit[i])
                so.append(num[n])
                haszero = False                 # 重新开始标记加零的情况
            else:                               # 处理为零的情况
                if not haszero:                 # 如果以前没有加过零
                    so.append(num[0])
                    haszero = True

    # 最终结果
    so.append(prefix)
    so.reverse()
    return ''.join(so)
Exemplo n.º 2
0
def cncapital(value, capital=True, prefix=False, classical=None):
    '''
    人民币数字转汉字表示 Ver 0.03
    作者: qianjin(AT)ustc.edu
    版权声明:
        只要保留本代码最初作者的电子邮件即可,随便用。用得爽的话,不反对请
    作者吃一顿。

    参数:
    capital:    True   大写汉字金额
                False  一般汉字金额
    classical:  True   圆
                False  元
    prefix:     True   以'人民币'开头
                False, 无开头
    '''

    # 转换为Decimal
    if isinstance(value, float):
        msg = '''
        由于浮点数精度问题,请使用考虑使用字符串,或者 decimal.Decimal 类。
        因使用浮点数造成误差而带来的可能风险和损失作者概不负责。
        '''
        warnings.warn(msg, UserWarning)
        value = Decimal(str(value))
    elif isinstance(value, int):
        value = Decimal(value)
    elif not isinstance(value, Decimal):
        try:
            value = Decimal(str(value))
        except:
            raise TypeError('无法转换为Decimal:%s' % value.__repr__())

    # 截断多余小数
    value = Decimal(value).quantize(Decimal('0.01'))

    # 默认大写金额用圆,一般汉字金额用元
    if classical is None:
        classical = True if capital else False

    # 汉字金额前缀
    if prefix is True:
        prefix = '人民币'
    else:
        prefix = ''

    # 汉字金额字符定义
    dunit = ('角', '分')
    if capital:
        num = ('零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖')
        iunit = [
            None, '拾', '佰', '仟', '万', '拾', '佰', '仟', '亿', '拾', '佰', '仟', '万',
            '拾', '佰', '仟'
        ]
    else:
        num = ('〇', '一', '二', '三', '四', '五', '六', '七', '八', '九')
        iunit = [
            None, '十', '百', '千', '万', '十', '百', '千', '亿', '十', '百', '千', '万',
            '十', '百', '千'
        ]

    if classical:
        iunit[0] = '圆' if classical else '元'

    # 处理负数
    if value < 0:
        prefix += '负'  # 输出前缀,加负
        value = -value  # 取正数部分,无须过多考虑正负数舍入
        # assert - value + value == 0

    # 转化为字符串
    s = str(value)

    if len(s) > 19:
        raise ValueError('金额太大了,不知道该怎么表达。')

    istr, dstr = s.split('.')  # 小数部分和整数部分分别处理
    istr = istr[::-1]  # 翻转整数部分字符串

    so = []  # 用于记录转换结果

    # 零
    if value == 0:
        return prefix + num[0] + iunit[0]

    haszero = False  # 用于标记零的使用
    if dstr == '00':
        haszero = True  # 如果无小数部分,则标记加过零,避免出现“圆零整”

    # 处理小数部分
    # 分
    if dstr[1] != '0':
        so.append(dunit[1])
        so.append(num[int(dstr[1])])
    else:
        so.append('整')  # 无分,则加“整”
    # 角
    if dstr[0] != '0':
        so.append(dunit[0])
        so.append(num[int(dstr[0])])
    elif dstr[1] != '0':
        so.append(num[0])  # 无角有分,添加“零”
        haszero = True  # 标记加过零了

    # 无整数部分
    if istr == '0':
        if haszero:  # 既然无整数部分,那么去掉角位置上的零
            so.pop()
        so.append(prefix)  # 加前缀
        so.reverse()  # 翻转
        return ''.join(so)

    # 处理整数部分
    for i, n in enumerate(istr):
        n = int(n)
        if i % 4 == 0:  # 在圆、万、亿等位上,即使是零,也必须有单位
            if i == 8 and so[-1] == iunit[4]:  # 亿和万之间全部为零的情况
                so.pop()  # 去掉万
            so.append(iunit[i])
            if n == 0:  # 处理这些位上为零的情况
                if not haszero:  # 如果以前没有加过零
                    so.insert(-1, num[0])  # 则在单位后面加零
                    haszero = True  # 标记加过零了
            else:  # 处理不为零的情况
                so.append(num[n])
                haszero = False  # 重新开始标记加零的情况
        else:  # 在其他位置上
            if n != 0:  # 不为零的情况
                so.append(iunit[i])
                so.append(num[n])
                haszero = False  # 重新开始标记加零的情况
            else:  # 处理为零的情况
                if not haszero:  # 如果以前没有加过零
                    so.append(num[0])
                    haszero = True

    # 最终结果
    so.append(prefix)
    so.reverse()
    return ''.join(so)
Exemplo n.º 3
0
class Price(object):
    def __init__(
        self, price_value,
        precision=Decimal(".111111111111111")):  # precision defaults to 15
        if isinstance(price_value, Decimal):
            self.__value = price_value
        elif isinstance(price_value, float):
            self.__value = Decimal(price_value).quantize(
                precision, rounding=decimal.ROUND_HALF_UP)
        else:
            self.__value = Decimal(price_value)
        self.__hash = self.__value.__hash__()
        self.__float_value = float(self.__value)
        self.__precision = precision

    def better_than(self, other_price, side):
        """
        Determines if this price is better than the passed in price. Returns True if it is and False if it isn't.
        The determination is made using the passed in side:
           *if side is bid then better than means a higher price
           *if side is ask then better than means a lower price
           *if side is other then there is no such thing as a better price so the return is False
        
        :param other_price: Price. the price you are comparing to
        :param side: Side. the side used for the comparison
        :return: boolean
        """
        assert isinstance(side, Side), "side should be MarketObjects.Side.Side"
        # if this price is a bid it is better than otherPrice if greater than

        if side.is_bid():
            return self > other_price
        # otherwise price is an ask and it is better than otherPrice if less than
        else:
            return self < other_price

    def better_or_same_as(self, other_price, side):
        """
        Determines if this price is better than or same as the passed in price.
        Returns True if it is and False if it isn't.
        The determination is made using the passed in side:
           *if side is bid then better than means a higher price
           *if side is ask then better than means a lower price
           *if side is other then there is no such thing as a better price so the return is False
        
        :param other_price: Price. the price you are comparing to
        :param side: Side. the side used for the comparison
        :return: boolean
        """
        return True if other_price == self else self.better_than(
            other_price, side)

    def worse_than(self, other_price, side):
        """
        Determines if this price is worse than the passed in price.
        Returns True if it is and False if it isn't.
        The determination is made using the passed in side:
           *if side is bid then worse than means a lower price
           *if side is ask then worse than means a higher price
           *if side is other then there is no such thing as a worse price so the return is False
        
        :param other_price: Price. the price you are comparing to
        :param side: Side. the side used for the comparison
        :return: boolean
        """
        assert isinstance(
            other_price,
            Price), "other_price should be MarketObjects.Price.Price"
        assert isinstance(side, Side), "side should be MarketObjects.Side.Side"
        # if this price is a bid it is worse than otherPrice if less than
        if side.is_bid():
            return self < other_price
        # otherwise price is an ask and it is worse than otherPrice if greater than
        else:
            return self > other_price

    def worse_or_same_as(self, other_price, side):
        """
        Determines if this price is worse than or same as the passed in price.
        Returns True if it is and False if it isn't.
        The determination is made using the passed in side:
           *if side is bid then worse than means a lower price
           *if side is ask then worse than means a higher price
           *if side is other then there is no such thing as a worse price so the return is False

        :param other_price: Price. the price you are comparing to
        :param side: Side. the side used for the comparison
        :return: boolean
        """
        return True if other_price == self else self.worse_than(
            other_price, side)

    def ticks_behind(self, other_price, side, market):
        """
        For bids it subtracts its own price from the other price and divides by mpi
  
        For asks it subtracts the other price from its own price and divides by mpi.
  
        The result is if the other price is a better price then we get a positive
         number and if the other price is a worse price, we get a negative number.
  
        If otherprice is none it returns None
        :param other_price: MarketObjects.Price.Price the price you are comparing too
        :param side: MMarketObjects.Side.Side side of the market the comparison is happening on
        :param market: MarketObjects.Market.Market
        :return: float Can be None
        """
        if other_price is None:
            return None

        if side.is_bid():
            ticks_behind = (other_price - self) / market.mpi()
        else:
            ticks_behind = (self - other_price) / market.mpi()
        return float(ticks_behind)

    def __hash__(self):
        return self.__hash

    def __repr__(self):
        return self.__value.__repr__()

    def __str__(self):
        return self.__value.__str__()

    def __lt__(self, other):
        if not isinstance(other, Price):
            raise TypeError(other, '< requires another Price object')
        else:
            return self.__value < other.__value

    def __le__(self, other):
        if not isinstance(other, Price):
            raise TypeError(other, '<= requires another Price object')
        else:
            return self.__value <= other.__value

    def __eq__(self, other):
        if other is None:
            return False
        elif isinstance(other, Price):
            return self.__value == other.__value
        else:
            return self.__value == Price(other).__value

    def __ne__(self, other):
        return not self == other

    def __gt__(self, other):
        if not isinstance(other, Price):
            raise TypeError(other, '> requires another Price object')
        else:
            return self.__value > other.__value

    def __ge__(self, other):
        if not isinstance(other, Price):
            raise TypeError(other, '>= requires another Price object')
        else:
            return self.__value >= other.__value

    def __bool__(self):
        return bool(self.__value)

    def __add__(self, other):
        if isinstance(other, float):
            value = self.__float_value + other
        else:
            if isinstance(other, Price):
                other = other.__value
            value = self.__value + other
        return self.__class__(value, precision=self.__precision)

    def __radd__(self, other):
        return self.__add__(other)

    def __sub__(self, other):
        if isinstance(other, float):
            value = self.__float_value - other
        else:
            if isinstance(other, Price):
                other = other.__value
            value = self.__value - other
        return self.__class__(value, precision=self.__precision)

    def __rsub__(self, other):
        return (-self).__add__(other)

    def __mul__(self, other):
        if isinstance(other, float):
            value = self.__float_value * other
        else:
            if isinstance(other, Price):
                raise TypeError(
                    "Two prices cannot be multiplied"
                )  # just doesn't make sense. Why would someone do this?
            value = self.__value * other
        return self.__class__(value, precision=self.__precision)

    def __rmul__(self, other):
        return self.__mul__(other)

    def __div__(self, other):
        return self.__truediv__(other)

    def __truediv__(self, other):
        if isinstance(other, Price):
            # not really sure why someone would want to divide a price by another price
            raise TypeError("Two prices cannot be divided")
        else:
            if other == 0:
                raise ZeroDivisionError()
            if isinstance(other, float):
                value = self.__float_value / other
            else:
                value = self.__value / other
        return self.__class__(value, precision=self.__precision)

    def __floordiv__(self, other):
        if isinstance(other, Price):
            # not really sure why someone would want to divide a price by another price
            raise TypeError("Two prices cannot be divided")
        else:
            if other == 0:
                raise ZeroDivisionError()
            if isinstance(other, float):
                value = self.__float_value // other
            else:
                value = self.__value // other
        return self.__class__(value, precision=self.__precision)

    def __mod__(self, other):
        if isinstance(other, Price):
            # not really sure why someone would want to modulo a price by another price
            raise TypeError("modulo of two prices is not supported")
        if other == 0:
            raise ZeroDivisionError()
        if isinstance(other, float):
            value = self.__float_value % other
        else:
            value = self.__value % other
        return self.__class__(value, precision=self.__precision)

    def __divmod__(self, other):
        raise TypeError("divmod of a price is not supported")

    def __pow__(self, other):
        raise TypeError("pow of a price is not supported")

    def __neg__(self):
        return self.__class__(-self.__value)

    def __pos__(self):
        return self.__class__(+self.__value)

    def __abs__(self):
        return self.__class__(abs(self.__value))

    def __int__(self):
        return int(self.__value)

    def __float__(self):
        return self.__float_value
Exemplo n.º 4
0
class ContractingDecimal:
    def _get_other(self, other):
        if type(other) == ContractingDecimal:
            return other._d
        elif type(other) == float or type(other) == int:
            return Decimal(str(other))
        return other

    def __init__(self, a):
        if type(a) == float or type(a) == int:
            a = str(a)

        self._d = Decimal(a)

    def __bool__(self):
        return self._d > 0

    def __eq__(self, other):
        return self._d.__eq__(self._get_other(other))

    def __lt__(self, other):
        return self._d.__lt__(self._get_other(other))

    def __le__(self, other):
        return self._d.__le__(self._get_other(other))

    def __gt__(self, other):
        return self._d.__gt__(self._get_other(other))

    def __ge__(self, other):
        return self._d.__ge__(self._get_other(other))

    def __str__(self):
        return self._d.__str__()

    def __neg__(self):
        return self._d.__neg__()

    def __pos__(self):
        return self._d.__pos__()

    def __abs__(self):
        return self._d.__abs__()

    def __add__(self, other):
        x = self._d.__add__(self._get_other(other))
        return fix_precision(x)

    def __radd__(self, other):
        return fix_precision(self._d.__radd__(self._get_other(other)))

    def __sub__(self, other):
        return fix_precision(self._d.__sub__(self._get_other(other)))

    def __rsub__(self, other):
        return fix_precision(self._d.__rsub__(self._get_other(other)))

    def __mul__(self, other):
        return fix_precision(self._d.__mul__(self._get_other(other)))

    def __rmul__(self, other):
        return fix_precision(self._d.__rmul__(self._get_other(other)))

    def __truediv__(self, other):
        return fix_precision(self._d.__truediv__(self._get_other(other)))

    def __rtruediv__(self, other):
        return fix_precision(self._d.__rtruediv__(self._get_other(other)))

    def __divmod__(self, other):
        return fix_precision(self._d.__divmod__(self._get_other(other)))

    def __rdivmod__(self, other):
        return fix_precision(self._d.__divmod__(self._get_other(other)))

    def __mod__(self, other):
        return fix_precision(self._d.__mod__(self._get_other(other)))

    def __rmod__(self, other):
        return fix_precision(self._d.__rmod__(self._get_other(other)))

    def __floordiv__(self, other):
        return fix_precision(self._d.__floordiv__(self._get_other(other)))

    def __rfloordiv__(self, other):
        return fix_precision(self._d.__rfloordiv__(self._get_other(other)))

    def __pow__(self, other):
        return fix_precision(self._d.__pow__(self._get_other(other)))

    def __rpow__(self, other):
        return fix_precision(self._d.__rpow__(self._get_other(other)))

    def __int__(self):
        return self._d.__int__()

    def __float__(self):
        raise Exception('Cannot cast Decimal to float.')

    def __repr__(self):
        return self._d.__repr__()