algo orchestrator
This commit is contained in:
84
main.py
84
main.py
@@ -36,8 +36,8 @@ load_dotenv()
|
||||
LOG_FILEPATH: str = os.getenv("LOGS_PATH") + '/Fund_Rate_Algo.log'
|
||||
|
||||
### CONSTANTS ###
|
||||
ASTER_ALLOW_ORDERING: bool = True
|
||||
EXTEND_ALLOW_ORDERING: bool = True
|
||||
ASTER_ALLOW_ORDERING: bool = False
|
||||
EXTEND_ALLOW_ORDERING: bool = False
|
||||
LOOP_SLEEP_SEC = 1
|
||||
PRICE_WORSENER_ASTER = 0.00
|
||||
PRICE_WORSENER_EXTEND = 0.0
|
||||
@@ -102,6 +102,7 @@ class Open_Positions:
|
||||
class Asset:
|
||||
symbol: str
|
||||
balance: float
|
||||
# min_order_qty: float
|
||||
|
||||
@dataclass(kw_only=True)
|
||||
class Collateral:
|
||||
@@ -157,50 +158,77 @@ class Funding_Rate:
|
||||
async def update(self) -> None:
|
||||
self.Valkey = await self.Valkey.update()
|
||||
|
||||
### Markets Info ###
|
||||
@dataclass(kw_only=True)
|
||||
class Market:
|
||||
symbol: str
|
||||
min_order_qty: float
|
||||
|
||||
@dataclass(kw_only=True)
|
||||
class Markets_Details:
|
||||
Markets: list[Market] = field(default_factory=list)
|
||||
|
||||
|
||||
### Exchanges ###
|
||||
@dataclass(kw_only=True)
|
||||
class Perpetual_Exchange:
|
||||
Order_Updates: Order_Updates
|
||||
Position_Updates: Open_Positions
|
||||
Collateral: Collateral
|
||||
Collateral_Updates: Collateral
|
||||
Funding_Rate: Funding_Rate
|
||||
Markets: Markets_Details
|
||||
mult: int
|
||||
|
||||
lh_asset: str
|
||||
rh_asset: str
|
||||
symbol_asset_separator: str = ''
|
||||
symbol: str
|
||||
|
||||
async def update(self):
|
||||
await self.Collateral.update()
|
||||
await self.Orders.update()
|
||||
await self.Positions.update()
|
||||
await self.Collateral_Updates.update()
|
||||
await self.Order_Updates.update()
|
||||
await self.Position_Updates.update()
|
||||
await self.Funding_Rate.update()
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
self.symbol = f'{self.lh_asset.upper()}{self.symbol_asset_separator}{self.rh_asset.upper()}'
|
||||
|
||||
|
||||
@dataclass(kw_only=True)
|
||||
class Aster(Perpetual_Exchange):
|
||||
name: str = 'Aster'
|
||||
lh_asset: str = 'ETH'
|
||||
rh_asset: str = 'USDT'
|
||||
|
||||
def __post_init__(self):
|
||||
self.Collateral = Order_Updates(Valkey=Valkey_Stream(channel = 'fr_aster_user_balances', none_fills = []))
|
||||
self.Orders = Collateral(Valkey=Valkey_Stream(channel = 'fr_aster_user_orders', none_fills = []))
|
||||
self.Positions = Open_Positions(Valkey=Valkey_Stream(channel = 'fr_aster_user_positions', none_fills = []))
|
||||
super().__post_init__()
|
||||
self.Order_Updates = Order_Updates(Valkey=Valkey_Stream(channel = 'fr_aster_user_balances', none_fills = []))
|
||||
self.Collateral_Updates = Collateral(Valkey=Valkey_Stream(channel = 'fr_aster_user_orders', none_fills = []))
|
||||
self.Position_Updates = Open_Positions(Valkey=Valkey_Stream(channel = 'fr_aster_user_positions', none_fills = []))
|
||||
self.Funding_Rate - Funding_Rate(Valkey=Valkey_Stream(channel = 'fund_rate_aster', none_fills = None))
|
||||
|
||||
|
||||
# @dataclass(kw_only=True)
|
||||
# class Exchanges:
|
||||
# Aster: Aster
|
||||
# Extend: Perpetual_Exchange
|
||||
|
||||
# async def update(self):
|
||||
# await self.Aster.update()
|
||||
# await self.Extend.update()
|
||||
@dataclass(kw_only=True)
|
||||
class Extend(Perpetual_Exchange):
|
||||
name: str = 'Extended'
|
||||
lh_asset: str = 'ETH'
|
||||
rh_asset: str = 'USD'
|
||||
symbol_asset_separator: str = '-'
|
||||
|
||||
def __post_init__(self):
|
||||
super().__post_init__()
|
||||
self.Order_Updates = Order_Updates(Valkey=Valkey_Stream(channel = 'fr_aster_user_balances', none_fills = []))
|
||||
self.Collateral_Updates = Collateral(Valkey=Valkey_Stream(channel = 'fr_aster_user_orders', none_fills = []))
|
||||
self.Position_Updates = Open_Positions(Valkey=Valkey_Stream(channel = 'fr_aster_user_positions', none_fills = []))
|
||||
self.Funding_Rate - Funding_Rate(Valkey=Valkey_Stream(channel = 'fund_rate_aster', none_fills = None))
|
||||
|
||||
|
||||
# EXCHANGES: list = [ Aster(), Extend() ]
|
||||
|
||||
### FLAGS ###
|
||||
@dataclass(kw_only=True)
|
||||
class Flags:
|
||||
LIQUIDATE_POS_AND_KILL_ALGO_FLAG: bool = False
|
||||
NET_FUNDING_IS_ZERO: bool = False
|
||||
# list = field(init=False)
|
||||
Flags = Flags()
|
||||
|
||||
|
||||
@@ -508,7 +536,8 @@ async def run_algo():
|
||||
NEXT_NET_FUNDING_RATE = calc_next_net_fund_rate(FUNDINGS_AT_SAME_TIME_NEXT_HR)
|
||||
Flags.NET_FUNDING_IS_ZERO = NEXT_NET_FUNDING_RATE == 0.00
|
||||
if Flags.NET_FUNDING_IS_ZERO:
|
||||
logging.info('NET FUNDING = 0.00; Flattening Open Positions; Wait Until Non-Zero.')
|
||||
logging.info('NET FUNDING = 0.00; Cancelling Open Orders; Wait Until Non-Zero.')
|
||||
|
||||
ALPHA_TGT_NOTIONAL = 0.00
|
||||
|
||||
if ALPHA_EXCH == 'EXTEND':
|
||||
@@ -554,6 +583,7 @@ async def run_algo():
|
||||
TGT NOTIONAL: $ {MAX_TARGET_NOTIONAL if not Flags.NET_FUNDING_IS_ZERO else 0.00}
|
||||
|
||||
ASTER: {ASTER_NOTIONAL_POSITION:.4f} -> {ASTER_TGT_NOTIONAL:.2f} [ Remain: {ASTER_TGT_TAIL:.4f} ] | EXTEND: {EXTEND_NOTIONAL_POSITION:.4f} -> {EXTEND_TGT_NOTIONAL:.2f} [ Remain: {EXTEND_TGT_TAIL:.4f} ]
|
||||
ASTER: {ASTER_TGT_NOTIONAL:.4f} - {ASTER_NOTIONAL_POSITION:.4f} = Tail: {ASTER_TGT_TAIL:4f} | EXTEND: {EXTEND_TGT_NOTIONAL:.4f} - {EXTEND_NOTIONAL_POSITION:.4f} = Tail: {EXTEND_TGT_TAIL:4f}
|
||||
ASTER: {ASTER_TGT_TAIL_BASE_QTY:.4f} > {ASTER_MIN_ORDER_QTY:.4f} min [ Order: {ASTER_TGT_TAIL_ORDERABLE} ] | EXTEND: {EXTEND_TGT_TAIL_BASE_QTY:.4f} > {EXTEND_MIN_ORDER_QTY:.4f} min [ Order: {EXTEND_TGT_TAIL_ORDERABLE} ]
|
||||
|
||||
--- ASTER OPEN ORDERS ---
|
||||
@@ -572,8 +602,9 @@ async def run_algo():
|
||||
qty = str(abs(ASTER_TGT_TAIL_BASE_QTY))
|
||||
price = ASTER_TOB_PX - PRICE_WORSENER_ASTER if side == 'BUY' else ASTER_TOB_PX + PRICE_WORSENER_ASTER
|
||||
|
||||
if abs(qty*price) + abs(ASTER_NOTIONAL_POSITION) > MAX_TARGET_NOTIONAL*1.01:
|
||||
logging.info(f'TRYING TO ORDER OVER MAX NOTIOANL - ASTER: {ASTER_NOTIONAL_POSITION} + {qty*price} (qty: {qty}; px: {price})')
|
||||
if abs(abs(float(ASTER_TGT_TAIL_BASE_QTY))*float(price)) + abs(ASTER_NOTIONAL_POSITION) > MAX_TARGET_NOTIONAL*1.01:
|
||||
pass
|
||||
logging.info(f'TRYING TO ORDER OVER MAX NOTIOANL - ASTER: {ASTER_NOTIONAL_POSITION} + {float(ASTER_TGT_TAIL_BASE_QTY)*float(price)} (qty: {float(ASTER_TGT_TAIL_BASE_QTY):.2f}; px: {float(price):.2f})')
|
||||
# await aster_remainder_route()
|
||||
if ASTER_OPEN_ORDERS:
|
||||
open_order_id = ASTER_OPEN_ORDERS[0].get('order_id') if ASTER_OPEN_ORDERS[0].get('order_id') is not None else ASTER_OPEN_ORDERS[0]['orderId']
|
||||
@@ -622,7 +653,7 @@ async def run_algo():
|
||||
if order_resp.get('orderId', None) is not None:
|
||||
order_resp['original_price'] = price
|
||||
ASTER_OPEN_ORDERS.append(order_resp)
|
||||
utils.send_tg_alert(f'FR_ALGO - ASTER Order. Start_$: {ASTER_NOTIONAL_POSITION:.2f}; Value: {abs(qty*price):.2f}; Price: {str(price):.2f}')
|
||||
utils.send_tg_alert(f'FR_ALGO - ASTER Order. Start_$: {ASTER_NOTIONAL_POSITION:.2f}; Value: {float(ASTER_TGT_TAIL_BASE_QTY)*float(price):.2f}; Price: {float(price):.2f}')
|
||||
logging.info(f'ASTER ORDER PLACED SUCCESS: {order_resp}')
|
||||
else:
|
||||
logging.warning('ASTER PLACE ORDER CHECKS FAILED, SKIPPING')
|
||||
@@ -638,8 +669,9 @@ async def run_algo():
|
||||
qty = Decimal(str(abs(EXTEND_TGT_TAIL_BASE_QTY)))
|
||||
price = EXTEND_TOB_PX - PRICE_WORSENER_EXTEND if side == 'BUY' else EXTEND_TOB_PX + PRICE_WORSENER_EXTEND
|
||||
|
||||
if abs(qty*price) + abs(EXTEND_NOTIONAL_POSITION) > MAX_TARGET_NOTIONAL*1.01:
|
||||
logging.info(f'TRYING TO ORDER OVER MAX NOTIOANL - EXTEND: {EXTEND_NOTIONAL_POSITION} + {qty*price} (qty: {qty}; px: {price})')
|
||||
if abs(float(EXTEND_TGT_TAIL_BASE_QTY)*float(price)) + abs(float(EXTEND_NOTIONAL_POSITION)) > MAX_TARGET_NOTIONAL*1.01:
|
||||
logging.info(f'TRYING TO ORDER OVER MAX NOTIOANL - EXTEND: {EXTEND_NOTIONAL_POSITION:.2f} + {float(EXTEND_TGT_TAIL_BASE_QTY)*float(price):.2f} (qty: {float(EXTEND_TGT_TAIL_BASE_QTY):.2f}; px: {float(price):.2f})')
|
||||
pass
|
||||
# await extend_remainder_route()
|
||||
if EXTEND_OPEN_ORDERS:
|
||||
open_order_dict = dict(EXTEND_OPEN_ORDERS[0])
|
||||
@@ -673,7 +705,7 @@ async def run_algo():
|
||||
order_dict['price'] = str(price)
|
||||
|
||||
EXTEND_OPEN_ORDERS.append(order_dict)
|
||||
utils.send_tg_alert(f'FR_ALGO - EXTEND Order. Start_$: {EXTEND_NOTIONAL_POSITION:.2f}; Value: {abs(qty*price):.2f}; Price: {str(price):.2f}')
|
||||
utils.send_tg_alert(f'FR_ALGO - EXTEND Order. Start_$: {EXTEND_NOTIONAL_POSITION:.2f}; Value: {float(EXTEND_TGT_TAIL_BASE_QTY)*float(price):.2f}; Price: {float(price):.2f}')
|
||||
logging.info(f'EXTEND ORDER PLACED SUCCESS: {order_dict}')
|
||||
else:
|
||||
logging.warning('EXTEND PLACE ORDER CHECKS FAILED, SKIPPING')
|
||||
|
||||
Reference in New Issue
Block a user