Template
add
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# MIT License
|
||||
# Copyright (c) 2017 Igor Kroitor
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
from ccxt.base import errors
|
||||
from ccxt.base import exchange
|
||||
from ccxt.base import decimal_to_precision
|
||||
|
||||
__all__ = exchange.__all__ + decimal_to_precision.__all__ + errors.__all__ # noqa: F405
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,178 @@
|
||||
import decimal
|
||||
import numbers
|
||||
import itertools
|
||||
import re
|
||||
|
||||
__all__ = [
|
||||
'TRUNCATE',
|
||||
'ROUND',
|
||||
'ROUND_UP',
|
||||
'ROUND_DOWN',
|
||||
'DECIMAL_PLACES',
|
||||
'SIGNIFICANT_DIGITS',
|
||||
'TICK_SIZE',
|
||||
'NO_PADDING',
|
||||
'PAD_WITH_ZERO',
|
||||
'decimal_to_precision',
|
||||
]
|
||||
|
||||
|
||||
# rounding mode
|
||||
TRUNCATE = 0
|
||||
ROUND = 1
|
||||
ROUND_UP = 2
|
||||
ROUND_DOWN = 3
|
||||
|
||||
# digits counting mode
|
||||
DECIMAL_PLACES = 2
|
||||
SIGNIFICANT_DIGITS = 3
|
||||
TICK_SIZE = 4
|
||||
|
||||
# padding mode
|
||||
NO_PADDING = 5
|
||||
PAD_WITH_ZERO = 6
|
||||
|
||||
|
||||
def decimal_to_precision(n, rounding_mode=ROUND, precision=None, counting_mode=DECIMAL_PLACES, padding_mode=NO_PADDING):
|
||||
assert precision is not None, 'precision should not be None'
|
||||
|
||||
if isinstance(precision, str):
|
||||
precision = float(precision)
|
||||
assert isinstance(precision, float) or isinstance(precision, decimal.Decimal) or isinstance(precision, numbers.Integral), 'precision has an invalid number'
|
||||
|
||||
if counting_mode == TICK_SIZE:
|
||||
assert precision > 0, 'negative or zero precision can not be used with TICK_SIZE precisionMode'
|
||||
else:
|
||||
assert isinstance(precision, numbers.Integral)
|
||||
|
||||
assert rounding_mode in [TRUNCATE, ROUND]
|
||||
assert counting_mode in [DECIMAL_PLACES, SIGNIFICANT_DIGITS, TICK_SIZE]
|
||||
assert padding_mode in [NO_PADDING, PAD_WITH_ZERO]
|
||||
# end of checks
|
||||
|
||||
context = decimal.getcontext()
|
||||
|
||||
if counting_mode != TICK_SIZE:
|
||||
precision = min(context.prec - 2, precision)
|
||||
|
||||
# all default except decimal.Underflow (raised when a number is rounded to zero)
|
||||
context.traps[decimal.Underflow] = True
|
||||
context.rounding = decimal.ROUND_HALF_UP # rounds 0.5 away from zero
|
||||
|
||||
dec = decimal.Decimal(str(n))
|
||||
precision_dec = decimal.Decimal(str(precision))
|
||||
string = '{:f}'.format(dec) # convert to string using .format to avoid engineering notation
|
||||
precise = None
|
||||
|
||||
def power_of_10(x):
|
||||
return decimal.Decimal('10') ** (-x)
|
||||
|
||||
if precision < 0:
|
||||
if counting_mode == TICK_SIZE:
|
||||
raise ValueError('TICK_SIZE cant be used with negative numPrecisionDigits')
|
||||
to_nearest = power_of_10(precision)
|
||||
if rounding_mode == ROUND:
|
||||
return "{:f}".format(to_nearest * decimal.Decimal(decimal_to_precision(dec / to_nearest, rounding_mode, 0, DECIMAL_PLACES, padding_mode)))
|
||||
elif rounding_mode == TRUNCATE:
|
||||
return decimal_to_precision(dec - dec % to_nearest, rounding_mode, 0, DECIMAL_PLACES, padding_mode)
|
||||
|
||||
if counting_mode == TICK_SIZE:
|
||||
# python modulo with negative numbers behaves different than js/php, so use abs first
|
||||
missing = abs(dec) % precision_dec
|
||||
if missing != 0:
|
||||
if rounding_mode == ROUND:
|
||||
if dec > 0:
|
||||
if missing >= precision_dec / 2:
|
||||
dec = dec - missing + precision_dec
|
||||
else:
|
||||
dec = dec - missing
|
||||
else:
|
||||
if missing >= precision_dec / 2:
|
||||
dec = dec + missing - precision_dec
|
||||
else:
|
||||
dec = dec + missing
|
||||
elif rounding_mode == TRUNCATE:
|
||||
if dec < 0:
|
||||
dec = dec + missing
|
||||
else:
|
||||
dec = dec - missing
|
||||
parts = re.sub(r'0+$', '', '{:f}'.format(precision_dec)).split('.')
|
||||
if len(parts) > 1:
|
||||
new_precision = len(parts[1])
|
||||
else:
|
||||
match = re.search(r'0+$', parts[0])
|
||||
if match is None:
|
||||
new_precision = 0
|
||||
else:
|
||||
new_precision = - len(match.group(0))
|
||||
return decimal_to_precision('{:f}'.format(dec), ROUND, new_precision, DECIMAL_PLACES, padding_mode)
|
||||
|
||||
if rounding_mode == ROUND:
|
||||
if counting_mode == DECIMAL_PLACES:
|
||||
precise = '{:f}'.format(dec.quantize(power_of_10(precision))) # ROUND_HALF_EVEN is default context
|
||||
elif counting_mode == SIGNIFICANT_DIGITS:
|
||||
q = precision - dec.adjusted() - 1
|
||||
sigfig = power_of_10(q)
|
||||
if q < 0:
|
||||
string_to_precision = string[:precision]
|
||||
# string_to_precision is '' when we have zero precision
|
||||
below = sigfig * decimal.Decimal(string_to_precision if string_to_precision else '0')
|
||||
above = below + sigfig
|
||||
precise = '{:f}'.format(min((below, above), key=lambda x: abs(x - dec)))
|
||||
else:
|
||||
precise = '{:f}'.format(dec.quantize(sigfig))
|
||||
if precise.startswith('-0') and all(c in '0.' for c in precise[1:]):
|
||||
precise = precise[1:]
|
||||
|
||||
elif rounding_mode == TRUNCATE:
|
||||
# Slice a string
|
||||
if counting_mode == DECIMAL_PLACES:
|
||||
before, after = string.split('.') if '.' in string else (string, '')
|
||||
precise = before + '.' + after[:precision]
|
||||
elif counting_mode == SIGNIFICANT_DIGITS:
|
||||
if precision == 0:
|
||||
return '0'
|
||||
dot = string.index('.') if '.' in string else len(string)
|
||||
start = dot - dec.adjusted()
|
||||
end = start + precision
|
||||
# need to clarify these conditionals
|
||||
if dot >= end:
|
||||
end -= 1
|
||||
if precision >= len(string.replace('.', '')):
|
||||
precise = string
|
||||
else:
|
||||
precise = string[:end].ljust(dot, '0')
|
||||
if precise.startswith('-0') and all(c in '0.' for c in precise[1:]):
|
||||
precise = precise[1:]
|
||||
precise = precise.rstrip('.')
|
||||
|
||||
if padding_mode == NO_PADDING:
|
||||
return precise.rstrip('0').rstrip('.') if '.' in precise else precise
|
||||
elif padding_mode == PAD_WITH_ZERO:
|
||||
if '.' in precise:
|
||||
if counting_mode == DECIMAL_PLACES:
|
||||
before, after = precise.split('.')
|
||||
return before + '.' + after.ljust(precision, '0')
|
||||
|
||||
elif counting_mode == SIGNIFICANT_DIGITS:
|
||||
fsfg = len(list(itertools.takewhile(lambda x: x == '.' or x == '0', precise)))
|
||||
if '.' in precise[fsfg:]:
|
||||
precision += 1
|
||||
return precise[:fsfg] + precise[fsfg:].rstrip('0').ljust(precision, '0')
|
||||
else:
|
||||
if counting_mode == SIGNIFICANT_DIGITS:
|
||||
if precision > len(precise):
|
||||
return precise + '.' + (precision - len(precise)) * '0'
|
||||
elif counting_mode == DECIMAL_PLACES:
|
||||
if precision > 0:
|
||||
return precise + '.' + precision * '0'
|
||||
return precise
|
||||
|
||||
|
||||
def number_to_string(x):
|
||||
# avoids scientific notation for too large and too small numbers
|
||||
if x is None:
|
||||
return None
|
||||
d = decimal.Decimal(str(x))
|
||||
formatted = '{:f}'.format(d)
|
||||
return formatted.rstrip('0').rstrip('.') if '.' in formatted else formatted
|
||||
@@ -0,0 +1,273 @@
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
|
||||
# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
|
||||
# EDIT THE CORRESPONDENT .ts FILE INSTEAD
|
||||
|
||||
error_hierarchy = {
|
||||
'BaseError': {
|
||||
'ExchangeError': {
|
||||
'AuthenticationError': {
|
||||
'PermissionDenied': {
|
||||
'AccountNotEnabled': {},
|
||||
},
|
||||
'AccountSuspended': {},
|
||||
},
|
||||
'ArgumentsRequired': {},
|
||||
'BadRequest': {
|
||||
'BadSymbol': {},
|
||||
},
|
||||
'OperationRejected': {
|
||||
'NoChange': {
|
||||
'MarginModeAlreadySet': {},
|
||||
},
|
||||
'MarketClosed': {},
|
||||
'ManualInteractionNeeded': {},
|
||||
'RestrictedLocation': {},
|
||||
},
|
||||
'InsufficientFunds': {},
|
||||
'InvalidAddress': {
|
||||
'AddressPending': {},
|
||||
},
|
||||
'InvalidOrder': {
|
||||
'OrderNotFound': {},
|
||||
'OrderNotCached': {},
|
||||
'OrderImmediatelyFillable': {},
|
||||
'OrderNotFillable': {},
|
||||
'DuplicateOrderId': {},
|
||||
'ContractUnavailable': {},
|
||||
},
|
||||
'NotSupported': {},
|
||||
'InvalidProxySettings': {},
|
||||
'ExchangeClosedByUser': {},
|
||||
},
|
||||
'OperationFailed': {
|
||||
'NetworkError': {
|
||||
'DDoSProtection': {},
|
||||
'RateLimitExceeded': {},
|
||||
'ExchangeNotAvailable': {
|
||||
'OnMaintenance': {},
|
||||
},
|
||||
'InvalidNonce': {
|
||||
'ChecksumError': {},
|
||||
},
|
||||
'RequestTimeout': {},
|
||||
},
|
||||
'BadResponse': {
|
||||
'NullResponse': {},
|
||||
},
|
||||
'CancelPending': {},
|
||||
},
|
||||
'UnsubscribeError': {},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class BaseError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class ExchangeError(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class AuthenticationError(ExchangeError):
|
||||
pass
|
||||
|
||||
|
||||
class PermissionDenied(AuthenticationError):
|
||||
pass
|
||||
|
||||
|
||||
class AccountNotEnabled(PermissionDenied):
|
||||
pass
|
||||
|
||||
|
||||
class AccountSuspended(AuthenticationError):
|
||||
pass
|
||||
|
||||
|
||||
class ArgumentsRequired(ExchangeError):
|
||||
pass
|
||||
|
||||
|
||||
class BadRequest(ExchangeError):
|
||||
pass
|
||||
|
||||
|
||||
class BadSymbol(BadRequest):
|
||||
pass
|
||||
|
||||
|
||||
class OperationRejected(ExchangeError):
|
||||
pass
|
||||
|
||||
|
||||
class NoChange(OperationRejected):
|
||||
pass
|
||||
|
||||
|
||||
class MarginModeAlreadySet(NoChange):
|
||||
pass
|
||||
|
||||
|
||||
class MarketClosed(OperationRejected):
|
||||
pass
|
||||
|
||||
|
||||
class ManualInteractionNeeded(OperationRejected):
|
||||
pass
|
||||
|
||||
|
||||
class RestrictedLocation(OperationRejected):
|
||||
pass
|
||||
|
||||
|
||||
class InsufficientFunds(ExchangeError):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidAddress(ExchangeError):
|
||||
pass
|
||||
|
||||
|
||||
class AddressPending(InvalidAddress):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidOrder(ExchangeError):
|
||||
pass
|
||||
|
||||
|
||||
class OrderNotFound(InvalidOrder):
|
||||
pass
|
||||
|
||||
|
||||
class OrderNotCached(InvalidOrder):
|
||||
pass
|
||||
|
||||
|
||||
class OrderImmediatelyFillable(InvalidOrder):
|
||||
pass
|
||||
|
||||
|
||||
class OrderNotFillable(InvalidOrder):
|
||||
pass
|
||||
|
||||
|
||||
class DuplicateOrderId(InvalidOrder):
|
||||
pass
|
||||
|
||||
|
||||
class ContractUnavailable(InvalidOrder):
|
||||
pass
|
||||
|
||||
|
||||
class NotSupported(ExchangeError):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidProxySettings(ExchangeError):
|
||||
pass
|
||||
|
||||
|
||||
class ExchangeClosedByUser(ExchangeError):
|
||||
pass
|
||||
|
||||
|
||||
class OperationFailed(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class NetworkError(OperationFailed):
|
||||
pass
|
||||
|
||||
|
||||
class DDoSProtection(NetworkError):
|
||||
pass
|
||||
|
||||
|
||||
class RateLimitExceeded(NetworkError):
|
||||
pass
|
||||
|
||||
|
||||
class ExchangeNotAvailable(NetworkError):
|
||||
pass
|
||||
|
||||
|
||||
class OnMaintenance(ExchangeNotAvailable):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidNonce(NetworkError):
|
||||
pass
|
||||
|
||||
|
||||
class ChecksumError(InvalidNonce):
|
||||
pass
|
||||
|
||||
|
||||
class RequestTimeout(NetworkError):
|
||||
pass
|
||||
|
||||
|
||||
class BadResponse(OperationFailed):
|
||||
pass
|
||||
|
||||
|
||||
class NullResponse(BadResponse):
|
||||
pass
|
||||
|
||||
|
||||
class CancelPending(OperationFailed):
|
||||
pass
|
||||
|
||||
|
||||
class UnsubscribeError(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
__all__ = [
|
||||
'error_hierarchy',
|
||||
'BaseError',
|
||||
'ExchangeError',
|
||||
'AuthenticationError',
|
||||
'PermissionDenied',
|
||||
'AccountNotEnabled',
|
||||
'AccountSuspended',
|
||||
'ArgumentsRequired',
|
||||
'BadRequest',
|
||||
'BadSymbol',
|
||||
'OperationRejected',
|
||||
'NoChange',
|
||||
'MarginModeAlreadySet',
|
||||
'MarketClosed',
|
||||
'ManualInteractionNeeded',
|
||||
'RestrictedLocation',
|
||||
'InsufficientFunds',
|
||||
'InvalidAddress',
|
||||
'AddressPending',
|
||||
'InvalidOrder',
|
||||
'OrderNotFound',
|
||||
'OrderNotCached',
|
||||
'OrderImmediatelyFillable',
|
||||
'OrderNotFillable',
|
||||
'DuplicateOrderId',
|
||||
'ContractUnavailable',
|
||||
'NotSupported',
|
||||
'InvalidProxySettings',
|
||||
'ExchangeClosedByUser',
|
||||
'OperationFailed',
|
||||
'NetworkError',
|
||||
'DDoSProtection',
|
||||
'RateLimitExceeded',
|
||||
'ExchangeNotAvailable',
|
||||
'OnMaintenance',
|
||||
'InvalidNonce',
|
||||
'ChecksumError',
|
||||
'RequestTimeout',
|
||||
'BadResponse',
|
||||
'NullResponse',
|
||||
'CancelPending',
|
||||
'UnsubscribeError'
|
||||
]
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,297 @@
|
||||
# Author: carlo.revelli@berkeley.edu
|
||||
#
|
||||
# Precise
|
||||
# Representation
|
||||
# Expanding
|
||||
# CCXT
|
||||
# Internal
|
||||
# Scientific
|
||||
# Exponents
|
||||
#
|
||||
# (╯°□°)╯︵ ┻━┻
|
||||
|
||||
|
||||
class Precise:
|
||||
def __init__(self, number, decimals=None):
|
||||
if decimals is None:
|
||||
modifier = 0
|
||||
number = number.lower()
|
||||
if 'e' in number:
|
||||
number, modifier = number.split('e')
|
||||
modifier = int(modifier)
|
||||
decimal_index = number.find('.')
|
||||
if decimal_index > -1:
|
||||
self.decimals = len(number) - decimal_index - 1
|
||||
self.integer = int(number.replace('.', ''))
|
||||
else:
|
||||
self.decimals = 0
|
||||
self.integer = int(number)
|
||||
self.decimals = self.decimals - modifier
|
||||
else:
|
||||
self.integer = number
|
||||
self.decimals = decimals
|
||||
self.base = 10
|
||||
|
||||
def __add__(self, other):
|
||||
return self.add(other)
|
||||
|
||||
def __sub__(self, other):
|
||||
return self.sub(other)
|
||||
|
||||
def __mul__(self, other):
|
||||
return self.mul(other)
|
||||
|
||||
def __truediv__(self, other):
|
||||
return self.div(other)
|
||||
|
||||
def __mod__(self, other):
|
||||
return self.mod(other)
|
||||
|
||||
def __neg__(self):
|
||||
return self.neg()
|
||||
|
||||
def __abs__(self):
|
||||
return self.abs()
|
||||
|
||||
def __min__(self, other):
|
||||
return self.min(other)
|
||||
|
||||
def __max__(self, other):
|
||||
return self.max(other)
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.lt(other)
|
||||
|
||||
def __le__(self, other):
|
||||
return self.le(other)
|
||||
|
||||
def __gt__(self, other):
|
||||
return self.gt(other)
|
||||
|
||||
def __ge__(self, other):
|
||||
return self.ge(other)
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, str):
|
||||
# Allow comparisons with Precise("5") == "5"
|
||||
return str(self) == other
|
||||
return self.equals(other)
|
||||
|
||||
def mul(self, other):
|
||||
integer_result = self.integer * other.integer
|
||||
return Precise(integer_result, self.decimals + other.decimals)
|
||||
|
||||
def div(self, other, precision=18):
|
||||
distance = precision - self.decimals + other.decimals
|
||||
if distance == 0:
|
||||
numerator = self.integer
|
||||
elif distance < 0:
|
||||
exponent = self.base ** -distance
|
||||
numerator = self.integer // exponent
|
||||
else:
|
||||
exponent = self.base ** distance
|
||||
numerator = self.integer * exponent
|
||||
result, mod = divmod(numerator, other.integer)
|
||||
# python floors negative numbers down instead of truncating
|
||||
# if mod is zero it will be floored to itself so we do not add one
|
||||
result = result + 1 if result < 0 and mod else result
|
||||
return Precise(result, precision)
|
||||
|
||||
def add(self, other):
|
||||
if self.decimals == other.decimals:
|
||||
integer_result = self.integer + other.integer
|
||||
return Precise(integer_result, self.decimals)
|
||||
else:
|
||||
smaller, bigger = [other, self] if self.decimals > other.decimals else [self, other]
|
||||
exponent = bigger.decimals - smaller.decimals
|
||||
normalised = smaller.integer * (self.base ** exponent)
|
||||
result = normalised + bigger.integer
|
||||
return Precise(result, bigger.decimals)
|
||||
|
||||
def sub(self, other):
|
||||
negative = Precise(-other.integer, other.decimals)
|
||||
return self.add(negative)
|
||||
|
||||
def abs(self):
|
||||
return Precise(abs(self.integer), self.decimals)
|
||||
|
||||
def neg(self):
|
||||
return Precise(-self.integer, self.decimals)
|
||||
|
||||
def mod(self, other):
|
||||
rationizerNumberator = max(-self.decimals + other.decimals, 0)
|
||||
numerator = self.integer * (self.base ** rationizerNumberator)
|
||||
rationizerDenominator = max(-other.decimals + self.decimals, 0)
|
||||
denominator = other.integer * (self.base ** rationizerDenominator)
|
||||
result = numerator % denominator
|
||||
return Precise(result, rationizerDenominator + other.decimals)
|
||||
|
||||
def orn(self, other):
|
||||
integer_result = self.integer | other.integer
|
||||
return Precise(integer_result, self.decimals)
|
||||
|
||||
def min(self, other):
|
||||
return self if self.lt(other) else other
|
||||
|
||||
def max(self, other):
|
||||
return self if self.gt(other) else other
|
||||
|
||||
def gt(self, other):
|
||||
add = self.sub(other)
|
||||
return add.integer > 0
|
||||
|
||||
def ge(self, other):
|
||||
add = self.sub(other)
|
||||
return add.integer >= 0
|
||||
|
||||
def lt(self, other):
|
||||
return other.gt(self)
|
||||
|
||||
def le(self, other):
|
||||
return other.ge(self)
|
||||
|
||||
def reduce(self):
|
||||
string = str(self.integer)
|
||||
start = len(string) - 1
|
||||
if start == 0:
|
||||
if string == "0":
|
||||
self.decimals = 0
|
||||
return self
|
||||
for i in range(start, -1, -1):
|
||||
if string[i] != '0':
|
||||
break
|
||||
difference = start - i
|
||||
if difference == 0:
|
||||
return self
|
||||
self.decimals -= difference
|
||||
self.integer = int(string[:i + 1])
|
||||
|
||||
def equals(self, other):
|
||||
self.reduce()
|
||||
other.reduce()
|
||||
return self.decimals == other.decimals and self.integer == other.integer
|
||||
|
||||
def __str__(self):
|
||||
self.reduce()
|
||||
sign = '-' if self.integer < 0 else ''
|
||||
integer_array = list(str(abs(self.integer)).rjust(self.decimals, '0'))
|
||||
index = len(integer_array) - self.decimals
|
||||
if index == 0:
|
||||
item = '0.'
|
||||
elif self.decimals < 0:
|
||||
item = '0' * (-self.decimals)
|
||||
elif self.decimals == 0:
|
||||
item = ''
|
||||
else:
|
||||
item = '.'
|
||||
integer_array.insert(index, item)
|
||||
return sign + ''.join(integer_array)
|
||||
|
||||
def __repr__(self):
|
||||
return "Precise(" + str(self) + ")"
|
||||
|
||||
def __float__(self):
|
||||
return float(str(self))
|
||||
|
||||
@staticmethod
|
||||
def string_mul(string1, string2):
|
||||
if string1 is None or string2 is None:
|
||||
return None
|
||||
return str(Precise(string1).mul(Precise(string2)))
|
||||
|
||||
@staticmethod
|
||||
def string_div(string1, string2, precision=18):
|
||||
if string1 is None or string2 is None:
|
||||
return None
|
||||
string2_precise = Precise(string2)
|
||||
if string2_precise.integer == 0:
|
||||
return None
|
||||
return str(Precise(string1).div(string2_precise, precision))
|
||||
|
||||
@staticmethod
|
||||
def string_add(string1, string2):
|
||||
if string1 is None and string2 is None:
|
||||
return None
|
||||
if string1 is None:
|
||||
return string2
|
||||
elif string2 is None:
|
||||
return string1
|
||||
return str(Precise(string1).add(Precise(string2)))
|
||||
|
||||
@staticmethod
|
||||
def string_sub(string1, string2):
|
||||
if string1 is None or string2 is None:
|
||||
return None
|
||||
return str(Precise(string1).sub(Precise(string2)))
|
||||
|
||||
@staticmethod
|
||||
def string_abs(string):
|
||||
if string is None:
|
||||
return None
|
||||
return str(Precise(string).abs())
|
||||
|
||||
@staticmethod
|
||||
def string_neg(string):
|
||||
if string is None:
|
||||
return None
|
||||
return str(Precise(string).neg())
|
||||
|
||||
@staticmethod
|
||||
def string_mod(string1, string2):
|
||||
if string1 is None or string2 is None:
|
||||
return None
|
||||
return str(Precise(string1).mod(Precise(string2)))
|
||||
|
||||
@staticmethod
|
||||
def string_or(string1, string2):
|
||||
if string1 is None or string2 is None:
|
||||
return None
|
||||
return str(Precise(string1).orn(Precise(string2)))
|
||||
|
||||
@staticmethod
|
||||
def string_equals(string1, string2):
|
||||
if string1 is None or string2 is None:
|
||||
return None
|
||||
return Precise(string1).equals(Precise(string2))
|
||||
|
||||
@staticmethod
|
||||
def string_eq(string1, string2):
|
||||
if string1 is None or string2 is None:
|
||||
return None
|
||||
return Precise(string1).equals(Precise(string2))
|
||||
|
||||
@staticmethod
|
||||
def string_min(string1, string2):
|
||||
if string1 is None or string2 is None:
|
||||
return None
|
||||
return str(Precise(string1).min(Precise(string2)))
|
||||
|
||||
@staticmethod
|
||||
def string_max(string1, string2):
|
||||
if string1 is None or string2 is None:
|
||||
return None
|
||||
return str(Precise(string1).max(Precise(string2)))
|
||||
|
||||
@staticmethod
|
||||
def string_gt(string1, string2):
|
||||
if string1 is None or string2 is None:
|
||||
return None
|
||||
return Precise(string1).gt(Precise(string2))
|
||||
|
||||
@staticmethod
|
||||
def string_ge(string1, string2):
|
||||
if string1 is None or string2 is None:
|
||||
return None
|
||||
return Precise(string1).ge(Precise(string2))
|
||||
|
||||
@staticmethod
|
||||
def string_lt(string1, string2):
|
||||
if string1 is None or string2 is None:
|
||||
return None
|
||||
return Precise(string1).lt(Precise(string2))
|
||||
|
||||
@staticmethod
|
||||
def string_le(string1, string2):
|
||||
if string1 is None or string2 is None:
|
||||
return None
|
||||
return Precise(string1).le(Precise(string2))
|
||||
@@ -0,0 +1,612 @@
|
||||
import sys
|
||||
import types
|
||||
from typing import Union, List, Optional, Any as PythonAny
|
||||
from decimal import Decimal
|
||||
|
||||
|
||||
if sys.version_info >= (3, 8):
|
||||
from typing import TypedDict, Literal, Dict
|
||||
else:
|
||||
from typing import Dict
|
||||
from typing_extensions import Literal
|
||||
TypedDict = Dict
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
from typing import NotRequired
|
||||
else:
|
||||
from typing_extensions import NotRequired
|
||||
|
||||
|
||||
OrderSide = Literal['buy', 'sell']
|
||||
OrderType = Literal['limit', 'market']
|
||||
PositionSide = Literal['long', 'short']
|
||||
Any = PythonAny
|
||||
|
||||
|
||||
class Entry:
|
||||
def __init__(self, path, api, method, config):
|
||||
self.name = None
|
||||
self.path = path
|
||||
self.api = api
|
||||
self.method = method
|
||||
self.config = config
|
||||
|
||||
def unbound_method(_self, params={}):
|
||||
return _self.request(self.path, self.api, self.method, params, config=self.config)
|
||||
|
||||
self.unbound_method = unbound_method
|
||||
|
||||
def __get__(self, instance, owner):
|
||||
if instance is None:
|
||||
return self.unbound_method
|
||||
else:
|
||||
return types.MethodType(self.unbound_method, instance)
|
||||
|
||||
def __set_name__(self, owner, name):
|
||||
self.name = name
|
||||
|
||||
|
||||
IndexType = Union[str, int]
|
||||
Num = Union[None, str, float, int, Decimal]
|
||||
Str = Optional[str]
|
||||
Strings = Optional[List[str]]
|
||||
Int = Optional[int]
|
||||
Bool = Optional[bool]
|
||||
MarketType = Literal['spot', 'margin', 'swap', 'future', 'option']
|
||||
SubType = Literal['linear', 'inverse']
|
||||
|
||||
|
||||
class FeeInterface(TypedDict):
|
||||
currency: Str
|
||||
cost: Num
|
||||
rate: NotRequired[Num]
|
||||
|
||||
|
||||
Fee = Optional[FeeInterface]
|
||||
|
||||
|
||||
class TradingFeeInterface(TypedDict):
|
||||
info: Dict[str, Any]
|
||||
symbol: Str
|
||||
maker: Num
|
||||
taker: Num
|
||||
percentage: Bool
|
||||
tierBased: Bool
|
||||
|
||||
|
||||
class Balance(TypedDict):
|
||||
free: Num
|
||||
used: Num
|
||||
total: Num
|
||||
debt: NotRequired[Num]
|
||||
|
||||
|
||||
class BalanceAccount(TypedDict):
|
||||
free: Str
|
||||
used: Str
|
||||
total: Str
|
||||
|
||||
|
||||
class Account(TypedDict):
|
||||
id: Str
|
||||
type: Str
|
||||
code: Str
|
||||
info: Dict[str, Any]
|
||||
|
||||
|
||||
class Trade(TypedDict):
|
||||
info: Dict[str, Any]
|
||||
amount: Num
|
||||
datetime: Str
|
||||
id: Str
|
||||
order: Str
|
||||
price: Num
|
||||
timestamp: Int
|
||||
type: Str
|
||||
side: Str
|
||||
symbol: Str
|
||||
takerOrMaker: Str
|
||||
cost: Num
|
||||
fee: Fee
|
||||
|
||||
|
||||
class Position(TypedDict):
|
||||
info: Dict[str, Any]
|
||||
symbol: Str
|
||||
id: Str
|
||||
timestamp: Int
|
||||
datetime: Str
|
||||
contracts: Num
|
||||
contractSize: Num
|
||||
side: Str
|
||||
notional: Num
|
||||
leverage: Num
|
||||
unrealizedPnl: Num
|
||||
realizedPnl: Num
|
||||
collateral: Num
|
||||
entryPrice: Num
|
||||
markPrice: Num
|
||||
liquidationPrice: Num
|
||||
hedged: bool
|
||||
maintenanceMargin: Num
|
||||
initialMargin: Num
|
||||
initialMarginPercentage: Num
|
||||
marginMode: Str
|
||||
marginRatio: Num
|
||||
lastUpdateTimestamp: Int
|
||||
lastPrice: Num
|
||||
percentage: Num
|
||||
stopLossPrice: Num
|
||||
takeProfitPrice: Num
|
||||
|
||||
class OrderRequest(TypedDict):
|
||||
symbol: Str
|
||||
type: Str
|
||||
side: Str
|
||||
amount: Union[None, float]
|
||||
price: Union[None, float]
|
||||
params: Dict[str, Any]
|
||||
|
||||
|
||||
class CancellationRequest(TypedDict):
|
||||
id: Str
|
||||
symbol: Str
|
||||
clientOrderId: Str
|
||||
|
||||
|
||||
class Order(TypedDict):
|
||||
info: Dict[str, Any]
|
||||
id: Str
|
||||
clientOrderId: Str
|
||||
datetime: Str
|
||||
timestamp: Int
|
||||
lastTradeTimestamp: Int
|
||||
lastUpdateTimestamp: Int
|
||||
status: Str
|
||||
symbol: Str
|
||||
type: Str
|
||||
timeInForce: Str
|
||||
side: OrderSide
|
||||
price: Num
|
||||
average: Num
|
||||
amount: Num
|
||||
filled: Num
|
||||
remaining: Num
|
||||
stopPrice: Num
|
||||
takeProfitPrice: Num
|
||||
stopLossPrice: Num
|
||||
cost: Num
|
||||
trades: List[Trade]
|
||||
reduceOnly: Bool
|
||||
postOnly: Bool
|
||||
fee: Fee
|
||||
|
||||
|
||||
class Liquidation(TypedDict):
|
||||
info: Dict[str, Any]
|
||||
symbol: Str
|
||||
timestamp: Int
|
||||
datetime: Str
|
||||
price: Num
|
||||
baseValue: Num
|
||||
quoteValue: Num
|
||||
side: OrderSide
|
||||
contracts: Num
|
||||
contractSize: Num
|
||||
|
||||
|
||||
class FundingHistory(TypedDict):
|
||||
info: Dict[str, Any]
|
||||
symbol: Str
|
||||
code: Str
|
||||
timestamp: Int
|
||||
datetime: Str
|
||||
id: Str
|
||||
amount: Num
|
||||
|
||||
|
||||
class Balances(Dict[str, Balance]):
|
||||
datetime: Str
|
||||
timestamp: Int
|
||||
|
||||
|
||||
class OrderBook(TypedDict):
|
||||
asks: List[List[Num]]
|
||||
bids: List[List[Num]]
|
||||
datetime: Str
|
||||
timestamp: Int
|
||||
nonce: Int
|
||||
symbol: Str
|
||||
|
||||
|
||||
class Transaction(TypedDict):
|
||||
info: Dict[str, any]
|
||||
id: Str
|
||||
txid: Str
|
||||
timestamp: Int
|
||||
datetime: Str
|
||||
address: Str
|
||||
addressFrom: Str
|
||||
addressTo: Str
|
||||
tag: Str
|
||||
tagFrom: Str
|
||||
tagTo: Str
|
||||
type: Str
|
||||
amount: Num
|
||||
currency: Str
|
||||
status: Str
|
||||
updated: Int
|
||||
fee: Fee
|
||||
network: Str
|
||||
comment: Str
|
||||
internal: Bool
|
||||
|
||||
|
||||
class TransferEntry(TypedDict):
|
||||
info: Dict[str, any]
|
||||
id: Str
|
||||
timestamp: Int
|
||||
datetime: Str
|
||||
currency: Str
|
||||
amount: Num
|
||||
fromAccount: Str
|
||||
toAccount: Str
|
||||
status: Str
|
||||
|
||||
|
||||
class Ticker(TypedDict):
|
||||
info: Dict[str, Any]
|
||||
symbol: Str
|
||||
timestamp: Int
|
||||
datetime: Str
|
||||
high: Num
|
||||
low: Num
|
||||
bid: Num
|
||||
bidVolume: Num
|
||||
ask: Num
|
||||
askVolume: Num
|
||||
vwap: Num
|
||||
open: Num
|
||||
close: Num
|
||||
last: Num
|
||||
previousClose: Num
|
||||
change: Num
|
||||
percentage: Num
|
||||
average: Num
|
||||
quoteVolume: Num
|
||||
baseVolume: Num
|
||||
markPrice: Num
|
||||
indexPrice: Num
|
||||
|
||||
|
||||
Tickers = Dict[str, Ticker]
|
||||
|
||||
OrderBooks = Dict[str, OrderBook]
|
||||
class MarginMode(TypedDict):
|
||||
info: Dict[str, Any]
|
||||
symbol: Str
|
||||
marginMode: Str
|
||||
|
||||
|
||||
MarginModes = Dict[str, MarginMode]
|
||||
|
||||
|
||||
class Leverage(TypedDict):
|
||||
info: Dict[str, Any]
|
||||
symbol: Str
|
||||
marginMode: Str
|
||||
longLeverage: Num
|
||||
shortLeverage: Num
|
||||
|
||||
|
||||
Leverages = Dict[str, Leverage]
|
||||
|
||||
|
||||
class Greeks(TypedDict):
|
||||
symbol: Str
|
||||
timestamp: Int
|
||||
datetime: Str
|
||||
delta: Num
|
||||
gamma: Num
|
||||
theta: Num
|
||||
vega: Num
|
||||
rho: Num
|
||||
vanna: Num
|
||||
volga: Num
|
||||
charm: Num
|
||||
bidSize: Num
|
||||
askSize: Num
|
||||
bidImpliedVolatility: Num
|
||||
askImpliedVolatility: Num
|
||||
markImpliedVolatility: Num
|
||||
bidPrice: Num
|
||||
askPrice: Num
|
||||
markPrice: Num
|
||||
lastPrice: Num
|
||||
underlyingPrice: Num
|
||||
info: Dict[str, Any]
|
||||
|
||||
|
||||
class Conversion(TypedDict):
|
||||
info: Dict[str, Any]
|
||||
timestamp: Int
|
||||
datetime: Str
|
||||
id: Str
|
||||
fromCurrency: Str
|
||||
fromAmount: Num
|
||||
toCurrency: Str
|
||||
toAmount: Num
|
||||
price: Num
|
||||
fee: Num
|
||||
|
||||
|
||||
class Option(TypedDict):
|
||||
info: Dict[str, Any]
|
||||
currency: Str
|
||||
symbol: Str
|
||||
timestamp: Int
|
||||
datetime: Str
|
||||
impliedVolatility: Num
|
||||
openInterest: Num
|
||||
bidPrice: Num
|
||||
askPrice: Num
|
||||
midPrice: Num
|
||||
markPrice: Num
|
||||
lastPrice: Num
|
||||
underlyingPrice: Num
|
||||
change: Num
|
||||
percentage: Num
|
||||
baseVolume: Num
|
||||
quoteVolume: Num
|
||||
|
||||
|
||||
OptionChain = Dict[str, Option]
|
||||
|
||||
class MarketMarginModes(TypedDict):
|
||||
cross: bool
|
||||
isolated: bool
|
||||
|
||||
class MinMax(TypedDict):
|
||||
min: Num
|
||||
max: Num
|
||||
|
||||
class MarketLimits(TypedDict):
|
||||
amount: Optional[MinMax]
|
||||
cost: Optional[MinMax]
|
||||
leverage: Optional[MinMax]
|
||||
price: Optional[MinMax]
|
||||
market: Optional[MinMax]
|
||||
|
||||
class MarketInterface(TypedDict):
|
||||
info: Dict[str, Any]
|
||||
id: Str
|
||||
symbol: Str
|
||||
base: Str
|
||||
quote: Str
|
||||
baseId: Str
|
||||
quoteId: Str
|
||||
active: Bool
|
||||
type: Str
|
||||
subType: Str
|
||||
spot: bool
|
||||
margin: bool
|
||||
marginModes: MarketMarginModes
|
||||
swap: bool
|
||||
future: bool
|
||||
option: bool
|
||||
contract: bool
|
||||
settle: Str
|
||||
settleId: Str
|
||||
contractSize: Num
|
||||
linear: bool
|
||||
inverse: bool
|
||||
expiry: Num
|
||||
expiryDatetime: Str
|
||||
strike: Num
|
||||
optionType: Str
|
||||
taker: Num
|
||||
maker: Num
|
||||
percentage: bool
|
||||
tierBased: bool
|
||||
feeSide: Str
|
||||
precision: Any
|
||||
limits: MarketLimits
|
||||
created: Int
|
||||
|
||||
class Limit(TypedDict):
|
||||
min: Num
|
||||
max: Num
|
||||
|
||||
|
||||
class CurrencyLimits(TypedDict):
|
||||
amount: Limit
|
||||
withdraw: Limit
|
||||
|
||||
|
||||
class CurrencyInterface(TypedDict):
|
||||
id: Str
|
||||
code: Str
|
||||
numericId: Int
|
||||
precision: Num
|
||||
type: Str
|
||||
margin: Bool
|
||||
name: Str
|
||||
active: Bool
|
||||
deposit: Bool
|
||||
withdraw: Bool
|
||||
fee: Num
|
||||
limits: CurrencyLimits
|
||||
networks: Dict[str, any]
|
||||
info: any
|
||||
|
||||
|
||||
class LastPrice(TypedDict):
|
||||
symbol: Str
|
||||
timestamp: Int
|
||||
datetime: Str
|
||||
price: Num
|
||||
side: OrderSide
|
||||
info: Dict[str, Any]
|
||||
|
||||
|
||||
class MarginModification(TypedDict):
|
||||
info: Dict[str, any]
|
||||
symbol: str
|
||||
type: Optional[Literal['add', 'reduce', 'set']]
|
||||
marginMode: Optional[Literal['isolated', 'cross']]
|
||||
amount: Optional[float]
|
||||
code: Str
|
||||
status: Str
|
||||
timestamp: Int
|
||||
datetime: Str
|
||||
|
||||
|
||||
class CrossBorrowRate(TypedDict):
|
||||
info: Dict[str, any]
|
||||
currency: Str
|
||||
rate: float
|
||||
period: Optional[float]
|
||||
timestamp: Int
|
||||
datetime: Str
|
||||
|
||||
|
||||
class IsolatedBorrowRate(TypedDict):
|
||||
info: Dict[str, any]
|
||||
symbol: str
|
||||
base: str
|
||||
baseRate: float
|
||||
quote: str
|
||||
quoteRate: float
|
||||
period: Int
|
||||
timestamp: Int
|
||||
datetime: Str
|
||||
|
||||
|
||||
class FundingRate(TypedDict):
|
||||
symbol: Str
|
||||
timestamp: Int
|
||||
fundingRate: Num
|
||||
datetime: Str
|
||||
markPrice: Num
|
||||
indexPrice: Num
|
||||
interestRate: Num
|
||||
estimatedSettlePrice: Num
|
||||
fundingTimestamp: Int
|
||||
fundingDatetime: Str
|
||||
nextFundingTimestamp: Int
|
||||
nextFundingDatetime: Str
|
||||
nextFundingRate: Num
|
||||
previousFundingTimestamp: Int
|
||||
previousFundingDatetime: Str
|
||||
previousFundingRate: Num
|
||||
info: Dict[str, Any]
|
||||
interval: Str
|
||||
|
||||
class OpenInterest(TypedDict):
|
||||
symbol: Str
|
||||
openInterestAmount: Num
|
||||
openInterestValue: Num
|
||||
baseVolume: Num
|
||||
quoteVolume: Num
|
||||
timestamp: Int
|
||||
datetime: Str
|
||||
info: Dict[str, Any]
|
||||
|
||||
class LeverageTier:
|
||||
tier: Num
|
||||
symbol: Str
|
||||
currency: Str
|
||||
minNotional: Num
|
||||
maxNotional: Num
|
||||
maintenanceMarginRate: Num
|
||||
maxLeverage: Num
|
||||
info: Dict[str, Any]
|
||||
|
||||
|
||||
class LedgerEntry:
|
||||
id: Str
|
||||
info: Any
|
||||
timestamp: Int
|
||||
datetime: Str
|
||||
direction: Str
|
||||
account: Str
|
||||
referenceId: Str
|
||||
referenceAccount: Str
|
||||
type: Str
|
||||
currency: Str
|
||||
amount: Str
|
||||
before: float
|
||||
after: float
|
||||
status: Str
|
||||
fee: Fee
|
||||
|
||||
|
||||
class DepositAddress:
|
||||
info: Any
|
||||
currency: Str
|
||||
network: Optional[Str]
|
||||
address: Str
|
||||
tag: Optional[Str]
|
||||
|
||||
|
||||
class LongShortRatio:
|
||||
info: Any
|
||||
symbol: Str
|
||||
timestamp: Optional[Int]
|
||||
datetime: Optional[Str]
|
||||
timeframe: Optional[Str]
|
||||
longShortRatio: float
|
||||
|
||||
|
||||
class BorrowInterest:
|
||||
info: Any
|
||||
symbol: Optional[Str]
|
||||
currency: Optional[Str]
|
||||
interest: Optional[Num]
|
||||
interestRate: Optional[Num]
|
||||
amountBorrowed: Optional[Num]
|
||||
marginMode: Optional[Str]
|
||||
timestamp: Optional[Int]
|
||||
datetime: Optional[Str]
|
||||
|
||||
|
||||
FundingRates = Dict[Str, FundingRate]
|
||||
OpenInterests = Dict[Str, OpenInterest]
|
||||
LastPrices = Dict[Str, LastPrice]
|
||||
Currencies = Dict[Str, CurrencyInterface]
|
||||
TradingFees = Dict[Str, TradingFeeInterface]
|
||||
IsolatedBorrowRates = Dict[Str, IsolatedBorrowRate]
|
||||
CrossBorrowRates = Dict[Str, CrossBorrowRate]
|
||||
LeverageTiers = Dict[Str, List[LeverageTier]]
|
||||
|
||||
Market = Optional[MarketInterface]
|
||||
Currency = Optional[CurrencyInterface]
|
||||
|
||||
class ConstructorArgs(TypedDict, total=False):
|
||||
apiKey: str
|
||||
secret: str
|
||||
passphrase: str
|
||||
password: str
|
||||
privateKey: str
|
||||
walletAddress: str
|
||||
uid: str
|
||||
verbose: bool
|
||||
testnet: bool
|
||||
sandbox: bool # redudant but kept for backwards compatibility
|
||||
options: Dict[str, Any]
|
||||
enableRateLimit: bool
|
||||
httpsProxy: str
|
||||
socksProxy: str
|
||||
wssProxy: str
|
||||
proxy: str
|
||||
rateLimit: Num
|
||||
commonCurrencies: Dict[str, Any]
|
||||
userAgent: str
|
||||
userAgents: Dict[str, Any]
|
||||
timeout: Num
|
||||
markets: Dict[str, Any]
|
||||
currencies: Dict[str, Any]
|
||||
hostname: str
|
||||
urls: Dict[str, Any]
|
||||
headers: Dict[str, Any]
|
||||
session: Any
|
||||
Reference in New Issue
Block a user