From 1014cb2bda7e2a61efa185490af60c49099e779d Mon Sep 17 00:00:00 2001 From: tim Date: Sat, 21 Sep 2024 01:57:31 -0400 Subject: [PATCH] trigger price fixes (inverted test) --- src/dexorder/order/orderstate.py | 4 +-- src/dexorder/order/triggers.py | 47 ++++++++++++++++++++------------ 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/dexorder/order/orderstate.py b/src/dexorder/order/orderstate.py index a58429c..0193a58 100644 --- a/src/dexorder/order/orderstate.py +++ b/src/dexorder/order/orderstate.py @@ -3,12 +3,13 @@ import logging from dataclasses import dataclass from typing import overload -from dexorder import DELETE, db, order_log +from dexorder import DELETE, db, order_log, dec from dexorder.base.chain import current_chain from dexorder.base.order import OrderKey, TrancheKey from dexorder.base.orderlib import SwapOrderState, ElaboratedSwapOrderStatus, Fill from dexorder.blockstate import BlockDict, BlockSet from dexorder.database.model.orderindex import OrderIndex +from dexorder.pools import get_pool, ensure_pool_price, pool_prices from dexorder.routing import pool_address from dexorder.util import json from dexorder.vault_blockdata import vault_owners @@ -193,7 +194,6 @@ class Order: order_log.debug(f'updated order_filled: {new}') Order.order_filled[self.key] = new - def complete(self, final_state: SwapOrderState): """ updates the static order record with its final values, then deletes all its dynamic blockstate and removes the Order from the actives list """ assert final_state in (SwapOrderState.Canceled, SwapOrderState.Expired, SwapOrderState.Filled, SwapOrderState.Error) diff --git a/src/dexorder/order/triggers.py b/src/dexorder/order/triggers.py index 734ad01..a483b56 100644 --- a/src/dexorder/order/triggers.py +++ b/src/dexorder/order/triggers.py @@ -48,7 +48,9 @@ class OrderTriggers: @staticmethod async def create(order: Order): - triggers = await asyncio.gather(*[TrancheTrigger.create(order, tk) for tk in order.tranche_keys]) + pool = await get_pool(order.pool_address) + await ensure_pool_price(pool) + triggers = await asyncio.gather(*[TrancheTrigger.create(order, tk, pool) for tk in order.tranche_keys]) return OrderTriggers(order, triggers) def __init__(self, order: Order, triggers: Sequence['TrancheTrigger']): @@ -315,21 +317,23 @@ class PriceLineTrigger (Trigger): by_pool: dict[str,set['PriceLineTrigger']] = defaultdict(set) @staticmethod - async def create(tk: TrancheKey, line: Line, is_min: bool, is_barrier: bool): + def create(tk: TrancheKey, scale: dec, inverted: bool, price: dec, line: Line, is_min: bool, is_barrier: bool): if line.intercept == 0 and line.slope == 0: return None # no constraint (deactivated) - pool = await get_pool(Order.of(tk).pool_address) - await ensure_pool_price(pool) - price_now = pool_prices[pool['address']] * dec(10) ** dec(-pool['decimals']) # adjust for pool decimals to get onchain price - return PriceLineTrigger(tk, line, is_min, is_barrier, price_now) + return PriceLineTrigger(tk, scale, inverted, line, is_min, is_barrier, price) - def __init__(self, tk: TrancheKey, line: Line, is_min: bool, is_barrier: bool, price_now: dec): + def __init__(self, tk: TrancheKey, scale: dec, inverted: bool, line: Line, is_min: bool, is_barrier: bool, price_now: dec): if is_barrier: log.warning('Barriers not supported') value_now = line.intercept + line.slope * current_clock.get().timestamp + if inverted: + price_now = 1/price_now + price_now *= scale activated = value_now < price_now if is_min else value_now > price_now log.debug(f'initial price line {value_now} {"<" if is_min else ">"} {price_now} {activated}') super().__init__(3 if is_min else 4, tk, activated) + self.scale = scale + self.inverted = inverted self.line = line self.is_min = is_min self.is_barrier = is_barrier @@ -356,12 +360,16 @@ class PriceLineTrigger (Trigger): PriceLineTrigger.triggers_set.clear() def update(self, price: float): + # oldPrice = price + if self.inverted: + price = 1/price + log.debug(f'price trigger {price}') if self not in PriceLineTrigger.triggers_set: self.index = len(PriceLineTrigger.y) PriceLineTrigger.y.append(price) PriceLineTrigger.m.append(self.line.slope) PriceLineTrigger.b.append(self.line.intercept) - PriceLineTrigger.sign.append(-1 if self.is_min else 1) + PriceLineTrigger.sign.append(1 if (self.is_min != self.inverted) else -1) PriceLineTrigger.triggers.append(self) PriceLineTrigger.triggers_set.add(self) else: @@ -376,8 +384,8 @@ class PriceLineTrigger (Trigger): line_value = m * time + b price_diff = sign * (y - line_value) activated = price_diff > 0 - for price, line, s, a in zip(y, line_value, sign, activated): - log.debug(f'price: {line} {"<" if s == -1 else ">"} {price} {a}') + for price, line, s, a, diff in zip(y, line_value, sign, activated, price_diff): + log.debug(f'price: {line} {"<" if s == 1 else ">"} {price} {a} ({diff:+})') for t, activated in zip(PriceLineTrigger.triggers, activated): t.handle_result(activated) PriceLineTrigger.clear_data() @@ -429,10 +437,10 @@ class TrancheState (Enum): class TrancheTrigger: - all: dict[TrancheKey,'TrancheTrigger'] = {} + all: dict[TrancheKey, 'TrancheTrigger'] = {} @staticmethod - async def create(order: Order, tk: TrancheKey) -> 'TrancheTrigger': + async def create(order: Order, tk: TrancheKey, pool: OldPoolDict) -> 'TrancheTrigger': time = current_clock.get().timestamp tranche = order.order.tranches[tk.tranche_index] ts = order.status.trancheStatus[tk.tranche_index] @@ -443,12 +451,15 @@ class TrancheTrigger: min_trigger = max_trigger = None else: # tranche minLine and maxLine are relative to the pool and will be flipped from the orderspec if the - # order is selling the base and buying the quote. - pool = await get_pool(order.pool_address) - buy = pool['base'] == order.order.tokenOut - min_trigger, max_trigger = await asyncio.gather( - PriceLineTrigger.create(tk, tranche.minLine, True is buy, tranche.minIsBarrier), - PriceLineTrigger.create(tk, tranche.maxLine, False is buy, tranche.maxIsBarrier)) + # order is buying the base and selling the quote. + price = pool_prices[pool['address']] + scale = 10 ** -pool['decimals'] + inverted = order.order.tokenIn != pool['base'] + assert inverted and order.order.tokenIn == pool['quote'] or not inverted and order.order.tokenIn == pool['base'] + min_trigger = PriceLineTrigger.create(tk, scale, inverted, price, tranche.minLine, True, + tranche.minIsBarrier) + max_trigger = PriceLineTrigger.create(tk, scale, inverted, price, tranche.maxLine, False, + tranche.maxIsBarrier) return TrancheTrigger(order, tk, balance_trigger, activation_trigger, expiration_trigger, min_trigger, max_trigger) def __init__(self, order: Order, tk: TrancheKey,