Module orca_whirlpool.internal.utils.price_math
Expand source code
import math
from decimal import Decimal
from .q64_fixed_point_math import Q64FixedPointMath
from .tick_util import TickUtil
def mul_shift(a: int, b: int, shift: int) -> int:
    return (a * b) >> shift
def tick_index_to_sqrt_price_positive(tick_index: int) -> int:
    tick_index_shifted = tick_index
    if tick_index_shifted & 1 == 0:
        ratio = 79228162514264337593543950336  # 0
    else:
        ratio = 79232123823359799118286999567  # 1
    precalculated_factor = [
        79236085330515764027303304731,  # 2
        79244008939048815603706035061,  # 4
        79259858533276714757314932305,  # 8
        79291567232598584799939703904,  # ...
        79355022692464371645785046466,
        79482085999252804386437311141,
        79736823300114093921829183326,
        80248749790819932309965073892,
        81282483887344747381513967011,
        83390072131320151908154831281,
        87770609709833776024991924138,
        97234110755111693312479820773,
        119332217159966728226237229890,
        179736315981702064433883588727,
        407748233172238350107850275304,
        2098478828474011932436660412517,
        55581415166113811149459800483533,
        38992368544603139932233054999993551,  # 262144
    ]
    for i in range(len(precalculated_factor)):
        tick_index_shifted = tick_index_shifted >> 1
        if tick_index_shifted & 1 != 0:
            ratio = mul_shift(ratio, precalculated_factor[i], 96)
    return mul_shift(ratio, 1, 32)
def tick_index_to_sqrt_price_negative(tick_index: int) -> int:
    tick_index_shifted = abs(tick_index)
    if tick_index_shifted & 1 == 0:
        ratio = 18446744073709551616  # 0
    else:
        ratio = 18445821805675392311  # 1
    precalculated_factor = [
        18444899583751176498,  # 2
        18443055278223354162,  # 4
        18439367220385604838,  # 8
        18431993317065449817,  # ...
        18417254355718160513,
        18387811781193591352,
        18329067761203520168,
        18212142134806087854,
        17980523815641551639,
        17526086738831147013,
        16651378430235024244,
        15030750278693429944,
        12247334978882834399,
        8131365268884726200,
        3584323654723342297,
        696457651847595233,
        26294789957452057,
        37481735321082,  # 262144
    ]
    for i in range(len(precalculated_factor)):
        tick_index_shifted = tick_index_shifted >> 1
        if tick_index_shifted & 1 != 0:
            ratio = mul_shift(ratio, precalculated_factor[i], 64)
    return ratio
class PriceMath:
    # https://orca-so.github.io/whirlpools/classes/PriceMath.html#sqrtPriceX64ToPrice
    # https://github.com/orca-so/whirlpools/blob/main/sdk/src/utils/public/price-math.ts#L22
    @staticmethod
    def sqrt_price_x64_to_price(sqrt_price_x64: int, decimals_a: int, decimals_b: int) -> Decimal:
        decimal_adjust = Decimal(10)**(decimals_a - decimals_b)
        price = Q64FixedPointMath.x64int_to_decimal(sqrt_price_x64) ** 2 * decimal_adjust
        return price
    # https://orca-so.github.io/whirlpools/classes/PriceMath.html#sqrtPriceX64ToTickIndex
    # https://github.com/orca-so/whirlpools/blob/2df89bb/sdk/src/utils/public/price-math.ts#L49
    @staticmethod
    def sqrt_price_x64_to_tick_index(sqrt_price_x64: int) -> int:
        # rough calculation
        shift_64 = 2**64
        sqrt_price = sqrt_price_x64 / shift_64
        price = sqrt_price**2
        tick_index = math.floor(math.log(price) / math.log(1.0001))
        # adjust to exact result
        while PriceMath.tick_index_to_sqrt_price_x64(tick_index)   >  sqrt_price_x64: tick_index = tick_index - 1
        while PriceMath.tick_index_to_sqrt_price_x64(tick_index+1) <= sqrt_price_x64: tick_index = tick_index + 1
        return tick_index
    # https://orca-so.github.io/whirlpools/classes/PriceMath.html#tickIndexToSqrtPriceX64
    # https://github.com/orca-so/whirlpools/blob/2df89bb/sdk/src/utils/public/price-math.ts#L36
    @staticmethod
    def tick_index_to_sqrt_price_x64(tick_index: int) -> int:
        if tick_index > 0:
            return tick_index_to_sqrt_price_positive(tick_index)
        else:
            return tick_index_to_sqrt_price_negative(tick_index)
    # https://orca-so.github.io/whirlpools/classes/PriceMath.html#tickIndexToPrice
    # https://github.com/orca-so/whirlpools/blob/7b9ec35/sdk/src/utils/public/price-math.ts#L101
    @staticmethod
    def tick_index_to_price(tick_index: int, decimals_a: int, decimals_b: int) -> Decimal:
        return PriceMath.sqrt_price_x64_to_price(
            PriceMath.tick_index_to_sqrt_price_x64(tick_index),
            decimals_a,
            decimals_b
        )
    # https://orca-so.github.io/whirlpools/classes/PriceMath.html#priceToSqrtPriceX64
    # https://github.com/orca-so/whirlpools/blob/7b9ec35/sdk/src/utils/public/price-math.ts#L18
    @staticmethod
    def price_to_sqrt_price_x64(price: Decimal, decimals_a: int, decimals_b: int) -> int:
        decimal_adjust = Decimal(10)**(decimals_a - decimals_b)
        return Q64FixedPointMath.decimal_to_x64int((price / decimal_adjust).sqrt())
    # https://orca-so.github.io/whirlpools/classes/PriceMath.html#priceToTickIndex
    # https://github.com/orca-so/whirlpools/blob/7b9ec35/sdk/src/utils/public/price-math.ts#L109
    @staticmethod
    def price_to_tick_index(price: Decimal, decimals_a: int, decimals_b: int) -> int:
        return PriceMath.sqrt_price_x64_to_tick_index(
            PriceMath.price_to_sqrt_price_x64(price, decimals_a, decimals_b)
        )
    # https://orca-so.github.io/whirlpools/classes/PriceMath.html#priceToInitializableTickIndex
    # https://github.com/orca-so/whirlpools/blob/7b9ec35/sdk/src/utils/public/price-math.ts#L115
    @staticmethod
    def price_to_initializable_tick_index(price: Decimal, decimals_a: int, decimals_b: int, tick_spacing: int) -> int:
        return TickUtil.get_initializable_tick_index(
            PriceMath.price_to_tick_index(price, decimals_a, decimals_b),
            tick_spacing
        )
Functions
def mul_shift(a: int, b: int, shift: int) ‑> int- 
Expand source code
def mul_shift(a: int, b: int, shift: int) -> int: return (a * b) >> shift def tick_index_to_sqrt_price_negative(tick_index: int) ‑> int- 
Expand source code
def tick_index_to_sqrt_price_negative(tick_index: int) -> int: tick_index_shifted = abs(tick_index) if tick_index_shifted & 1 == 0: ratio = 18446744073709551616 # 0 else: ratio = 18445821805675392311 # 1 precalculated_factor = [ 18444899583751176498, # 2 18443055278223354162, # 4 18439367220385604838, # 8 18431993317065449817, # ... 18417254355718160513, 18387811781193591352, 18329067761203520168, 18212142134806087854, 17980523815641551639, 17526086738831147013, 16651378430235024244, 15030750278693429944, 12247334978882834399, 8131365268884726200, 3584323654723342297, 696457651847595233, 26294789957452057, 37481735321082, # 262144 ] for i in range(len(precalculated_factor)): tick_index_shifted = tick_index_shifted >> 1 if tick_index_shifted & 1 != 0: ratio = mul_shift(ratio, precalculated_factor[i], 64) return ratio def tick_index_to_sqrt_price_positive(tick_index: int) ‑> int- 
Expand source code
def tick_index_to_sqrt_price_positive(tick_index: int) -> int: tick_index_shifted = tick_index if tick_index_shifted & 1 == 0: ratio = 79228162514264337593543950336 # 0 else: ratio = 79232123823359799118286999567 # 1 precalculated_factor = [ 79236085330515764027303304731, # 2 79244008939048815603706035061, # 4 79259858533276714757314932305, # 8 79291567232598584799939703904, # ... 79355022692464371645785046466, 79482085999252804386437311141, 79736823300114093921829183326, 80248749790819932309965073892, 81282483887344747381513967011, 83390072131320151908154831281, 87770609709833776024991924138, 97234110755111693312479820773, 119332217159966728226237229890, 179736315981702064433883588727, 407748233172238350107850275304, 2098478828474011932436660412517, 55581415166113811149459800483533, 38992368544603139932233054999993551, # 262144 ] for i in range(len(precalculated_factor)): tick_index_shifted = tick_index_shifted >> 1 if tick_index_shifted & 1 != 0: ratio = mul_shift(ratio, precalculated_factor[i], 96) return mul_shift(ratio, 1, 32) 
Classes
class PriceMath- 
Expand source code
class PriceMath: # https://orca-so.github.io/whirlpools/classes/PriceMath.html#sqrtPriceX64ToPrice # https://github.com/orca-so/whirlpools/blob/main/sdk/src/utils/public/price-math.ts#L22 @staticmethod def sqrt_price_x64_to_price(sqrt_price_x64: int, decimals_a: int, decimals_b: int) -> Decimal: decimal_adjust = Decimal(10)**(decimals_a - decimals_b) price = Q64FixedPointMath.x64int_to_decimal(sqrt_price_x64) ** 2 * decimal_adjust return price # https://orca-so.github.io/whirlpools/classes/PriceMath.html#sqrtPriceX64ToTickIndex # https://github.com/orca-so/whirlpools/blob/2df89bb/sdk/src/utils/public/price-math.ts#L49 @staticmethod def sqrt_price_x64_to_tick_index(sqrt_price_x64: int) -> int: # rough calculation shift_64 = 2**64 sqrt_price = sqrt_price_x64 / shift_64 price = sqrt_price**2 tick_index = math.floor(math.log(price) / math.log(1.0001)) # adjust to exact result while PriceMath.tick_index_to_sqrt_price_x64(tick_index) > sqrt_price_x64: tick_index = tick_index - 1 while PriceMath.tick_index_to_sqrt_price_x64(tick_index+1) <= sqrt_price_x64: tick_index = tick_index + 1 return tick_index # https://orca-so.github.io/whirlpools/classes/PriceMath.html#tickIndexToSqrtPriceX64 # https://github.com/orca-so/whirlpools/blob/2df89bb/sdk/src/utils/public/price-math.ts#L36 @staticmethod def tick_index_to_sqrt_price_x64(tick_index: int) -> int: if tick_index > 0: return tick_index_to_sqrt_price_positive(tick_index) else: return tick_index_to_sqrt_price_negative(tick_index) # https://orca-so.github.io/whirlpools/classes/PriceMath.html#tickIndexToPrice # https://github.com/orca-so/whirlpools/blob/7b9ec35/sdk/src/utils/public/price-math.ts#L101 @staticmethod def tick_index_to_price(tick_index: int, decimals_a: int, decimals_b: int) -> Decimal: return PriceMath.sqrt_price_x64_to_price( PriceMath.tick_index_to_sqrt_price_x64(tick_index), decimals_a, decimals_b ) # https://orca-so.github.io/whirlpools/classes/PriceMath.html#priceToSqrtPriceX64 # https://github.com/orca-so/whirlpools/blob/7b9ec35/sdk/src/utils/public/price-math.ts#L18 @staticmethod def price_to_sqrt_price_x64(price: Decimal, decimals_a: int, decimals_b: int) -> int: decimal_adjust = Decimal(10)**(decimals_a - decimals_b) return Q64FixedPointMath.decimal_to_x64int((price / decimal_adjust).sqrt()) # https://orca-so.github.io/whirlpools/classes/PriceMath.html#priceToTickIndex # https://github.com/orca-so/whirlpools/blob/7b9ec35/sdk/src/utils/public/price-math.ts#L109 @staticmethod def price_to_tick_index(price: Decimal, decimals_a: int, decimals_b: int) -> int: return PriceMath.sqrt_price_x64_to_tick_index( PriceMath.price_to_sqrt_price_x64(price, decimals_a, decimals_b) ) # https://orca-so.github.io/whirlpools/classes/PriceMath.html#priceToInitializableTickIndex # https://github.com/orca-so/whirlpools/blob/7b9ec35/sdk/src/utils/public/price-math.ts#L115 @staticmethod def price_to_initializable_tick_index(price: Decimal, decimals_a: int, decimals_b: int, tick_spacing: int) -> int: return TickUtil.get_initializable_tick_index( PriceMath.price_to_tick_index(price, decimals_a, decimals_b), tick_spacing )Static methods
def price_to_initializable_tick_index(price: decimal.Decimal, decimals_a: int, decimals_b: int, tick_spacing: int) ‑> int- 
Expand source code
@staticmethod def price_to_initializable_tick_index(price: Decimal, decimals_a: int, decimals_b: int, tick_spacing: int) -> int: return TickUtil.get_initializable_tick_index( PriceMath.price_to_tick_index(price, decimals_a, decimals_b), tick_spacing ) def price_to_sqrt_price_x64(price: decimal.Decimal, decimals_a: int, decimals_b: int) ‑> int- 
Expand source code
@staticmethod def price_to_sqrt_price_x64(price: Decimal, decimals_a: int, decimals_b: int) -> int: decimal_adjust = Decimal(10)**(decimals_a - decimals_b) return Q64FixedPointMath.decimal_to_x64int((price / decimal_adjust).sqrt()) def price_to_tick_index(price: decimal.Decimal, decimals_a: int, decimals_b: int) ‑> int- 
Expand source code
@staticmethod def price_to_tick_index(price: Decimal, decimals_a: int, decimals_b: int) -> int: return PriceMath.sqrt_price_x64_to_tick_index( PriceMath.price_to_sqrt_price_x64(price, decimals_a, decimals_b) ) def sqrt_price_x64_to_price(sqrt_price_x64: int, decimals_a: int, decimals_b: int) ‑> decimal.Decimal- 
Expand source code
@staticmethod def sqrt_price_x64_to_price(sqrt_price_x64: int, decimals_a: int, decimals_b: int) -> Decimal: decimal_adjust = Decimal(10)**(decimals_a - decimals_b) price = Q64FixedPointMath.x64int_to_decimal(sqrt_price_x64) ** 2 * decimal_adjust return price def sqrt_price_x64_to_tick_index(sqrt_price_x64: int) ‑> int- 
Expand source code
@staticmethod def sqrt_price_x64_to_tick_index(sqrt_price_x64: int) -> int: # rough calculation shift_64 = 2**64 sqrt_price = sqrt_price_x64 / shift_64 price = sqrt_price**2 tick_index = math.floor(math.log(price) / math.log(1.0001)) # adjust to exact result while PriceMath.tick_index_to_sqrt_price_x64(tick_index) > sqrt_price_x64: tick_index = tick_index - 1 while PriceMath.tick_index_to_sqrt_price_x64(tick_index+1) <= sqrt_price_x64: tick_index = tick_index + 1 return tick_index def tick_index_to_price(tick_index: int, decimals_a: int, decimals_b: int) ‑> decimal.Decimal- 
Expand source code
@staticmethod def tick_index_to_price(tick_index: int, decimals_a: int, decimals_b: int) -> Decimal: return PriceMath.sqrt_price_x64_to_price( PriceMath.tick_index_to_sqrt_price_x64(tick_index), decimals_a, decimals_b ) def tick_index_to_sqrt_price_x64(tick_index: int) ‑> int- 
Expand source code
@staticmethod def tick_index_to_sqrt_price_x64(tick_index: int) -> int: if tick_index > 0: return tick_index_to_sqrt_price_positive(tick_index) else: return tick_index_to_sqrt_price_negative(tick_index)