v1 working switch symbols w volume filter

This commit is contained in:
2026-05-01 20:45:26 +00:00
parent 7d579faa82
commit b05f389e49
40 changed files with 12837 additions and 28654 deletions

407
main.py
View File

@@ -1,3 +1,4 @@
from orjson import JSONDecodeError
from x10.utils.http import WrappedApiResponse
from x10.perpetual.trading_client.trading_client import PerpetualTradingClient
import asyncio
@@ -8,7 +9,7 @@ import os
import time
import traceback
from datetime import datetime, timezone
from decimal import ROUND_DOWN, Decimal
from decimal import ROUND_DOWN, ROUND_HALF_UP, Decimal
from typing import AsyncContextManager
from dataclasses import dataclass, asdict
from typing import Any
@@ -42,29 +43,14 @@ ALGO_CONFIG: structs.Algo_Config
MIN_TIME_TO_FUNDING: int
### EXCHANGES ###
ASTER = structs.Perpetual_Exchange(
mult = 150,
lh_asset = 'ETH',
rh_asset = 'USDT',
symbol_asset_separator = '',
)
EXTEND = structs.Perpetual_Exchange(
mult = 50,
lh_asset = 'ETH',
rh_asset = 'USD',
symbol_asset_separator = '-',
)
ASTER: structs.Perpetual_Exchange
EXTEND: structs.Perpetual_Exchange
### GLOBALS ###
Open_Symbols: list[str] = []
Last_Aster_Fill_Time_Ts: float = 0.00
Just_Rejected_Or_Expired: bool = False
# ASTER_MULT = 150
# EXTEND_MULT = 50
ASTER_MIN_ORDER_QTY = 0.001
EXTEND_MIN_ORDER_QTY = 0.01
ASTER_AVAIL_COLLATERAL = 0
EXTEND_AVAIL_COLLATERAL = 0
@@ -89,11 +75,11 @@ EXTEND_OPEN_ORDERS = []
Flags = structs.Flags()
### UTILS ###
def round_decimal_down(value, decimal_places):
# Construct precision string like '0.01' for 2 places
fmt = f'0.{"0" * decimal_places}' if decimal_places > 0 else '0'
precision = Decimal(fmt)
return Decimal(str(value)).quantize(precision, rounding=ROUND_DOWN)
# def round_decimal_down(value, decimal_places):
# # Construct precision string like '0.01' for 2 places
# fmt = f'0.{"0" * decimal_places}' if decimal_places > 0 else '0'
# precision = Decimal(fmt)
# return Decimal(str(value)).quantize(precision, rounding=ROUND_HALF_UP)
### OPEN ORDERS ###
async def get_aster_open_orders():
@@ -112,16 +98,28 @@ async def get_extend_open_orders():
EXTEND_OPEN_ORDERS = list(dict(await EXTEND_CLIENT.account.get_open_orders()).get('data', 0))
### WALLLET ###
async def get_aster_collateral():
global ASTER_AVAIL_COLLATERAL
# async def get_aster_collateral():
# global ASTER_AVAIL_COLLATERAL
fut_acct_balances = {
"url": "/fapi/v3/balance",
"method": "GET",
"params": {}
}
r = await aster_auth.post_authenticated_url(fut_acct_balances)
ASTER_AVAIL_COLLATERAL = float([d for d in r if d.get('asset')==ASTER.rh_asset][0].get('availableBalance'))
# fut_acct_balances = {
# "url": "/fapi/v3/balance",
# "method": "GET",
# "params": {}
# }
# r = await aster_auth.post_authenticated_url(fut_acct_balances)
# ASTER_AVAIL_COLLATERAL = float([d for d in r if d.get('asset')==ASTER.rh_asset][0].get('availableBalance'))
async def get_aster_account_open_symbols() -> list[str]:
fut_acct_positionRisk: dict = {
"url": "/fapi/v3/positionRisk",
"method": "GET",
"params": {
'symbol': ASTER.symbol,
}
}
resp: list = await aster_auth.post_authenticated_url(req=fut_acct_positionRisk) # ty:ignore[invalid-assignment]
ld = [ utils.symbol_to_extend_fmt(x['symbol']) for x in resp if abs(float(x.get('positionAmt', 0))) > 0]
return ld
async def get_aster_notional_position(resp: list | None = None):
global ASTER_NOTIONAL_OBJ
@@ -130,8 +128,13 @@ async def get_aster_notional_position(resp: list | None = None):
global ASTER
previous_notional_obj = ASTER_NOTIONAL_OBJ
previous_notional_position = ASTER_NOTIONAL_POSITION
if not resp:
if resp:
d = [x for x in resp if x.get('symbol', None) == ASTER.symbol]
d = d[0] if d else {}
if ( not resp ) or ( not d ):
fut_acct_positionRisk: dict = {
"url": "/fapi/v3/positionRisk",
"method": "GET",
@@ -139,11 +142,14 @@ async def get_aster_notional_position(resp: list | None = None):
'symbol': ASTER.symbol,
}
}
resp: list = await aster_auth.post_authenticated_url(req=fut_acct_positionRisk) # ty:ignore[invalid-assignment]
try:
resp: list = await aster_auth.post_authenticated_url(req=fut_acct_positionRisk) # ty:ignore[invalid-assignment]
except JSONDecodeError as e:
logging.warning(f'JSONDecodeError trying to get Aster notional: {e}; resp: {resp}')
time.sleep(0.1)
resp: list = await aster_auth.post_authenticated_url(req=fut_acct_positionRisk) # ty:ignore[invalid-assignment]
d = [x for x in resp if x.get('symbol', None) == ASTER.symbol][0]
d['timestamp_arrival'] = round(datetime.now().timestamp()*1000)
else:
d = [x for x in resp if x.get('symbol', None) == ASTER.symbol][0]
if previous_notional_obj is not None:
if previous_notional_obj['timestamp_arrival'] > d['timestamp_arrival']:
@@ -162,8 +168,6 @@ async def get_aster_notional_position(resp: list | None = None):
ASTER_NOTIONAL_POSITION = float(d['notional']) - ASTER_UNREALIZED_PNL
else:
ASTER_NOTIONAL_POSITION = float(d['position_amount'])*float(d['entry_price'])
previous_notional_position = ASTER_NOTIONAL_POSITION
# if not resp: # this can never evaluate
# ASTER.mult = float(d['leverage'])
if abs(ASTER_NOTIONAL_POSITION) > ALGO_CONFIG.Config.Max_Target_Notional*ALGO_CONFIG.Config.Max_Order_Over_Notional_Ratio:
@@ -172,11 +176,25 @@ async def get_aster_notional_position(resp: list | None = None):
if ASTER_NOTIONAL_POSITION != previous_notional_position:
logging.info(f'ASTER NOTIONAL CHANGE: {previous_notional_position:.2f} -> {ASTER_NOTIONAL_POSITION:.2f}; UR PNL: {ASTER_UNREALIZED_PNL:.2f}; MULT: {ASTER.mult:.0f}; resp: {bool(resp)}')
async def get_extend_collateral():
global EXTEND_AVAIL_COLLATERAL
# async def get_extend_collateral():
# global EXTEND_AVAIL_COLLATERAL
# get_bals = dict(dict(await EXTEND_CLIENT.account.get_balance()).get('data', {}))
# EXTEND_AVAIL_COLLATERAL = get_bals.get('available_for_trade', 0) if get_bals.get('collateral_name', None)==EXTEND.rh_asset else 0
async def get_extend_account_open_symbols() -> list[str]:
resp = dict(await EXTEND_CLIENT.account.get_positions()).get('data', [])
ld = [x.market for x in list(resp) if abs(float(x.size)) > 0]
return ld
async def set_comb_open_symbols() -> None:
global Open_Symbols
open_aster_symbols = await get_aster_account_open_symbols()
open_extend_symbols = await get_extend_account_open_symbols()
Open_Symbols = list(set(open_aster_symbols + open_extend_symbols))
get_bals = dict(dict(await EXTEND_CLIENT.account.get_balance()).get('data', {}))
EXTEND_AVAIL_COLLATERAL = get_bals.get('available_for_trade', 0) if get_bals.get('collateral_name', None)==EXTEND.rh_asset else 0
async def get_extend_notional(resp: list | None = None):
global EXTEND_NOTIONAL_OBJ
@@ -207,8 +225,9 @@ async def get_extend_notional(resp: list | None = None):
pos_dict = {}
pos_dict['side'] = 'LONG'
pos_dict['value'] = 0.00
logging.info('get_extend_notional - No Positions')
# logging.info('get_extend_notional - No Positions')
pos_dict['timestamp_arrival'] = round(datetime.now().timestamp()*1000)
if previous_notional_obj is not None:
if previous_notional_obj['timestamp_arrival'] > pos_dict['timestamp_arrival']:
@@ -228,17 +247,20 @@ async def get_extend_notional(resp: list | None = None):
logging.info(f'EXTEND BAD SIDE ON POSITION UPDATE: {pos_dict}')
EXTEND_NOTIONAL_POSITION = notional_pos_sided - float(EXTEND_UNREALIZED_PNL)
EXTEND.mult = pos_dict.get('leverage', EXTEND)
EXTEND.mult = pos_dict.get('leverage', EXTEND.mult)
if abs(EXTEND_NOTIONAL_POSITION) > ALGO_CONFIG.Config.Max_Target_Notional*ALGO_CONFIG.Config.Max_Order_Over_Notional_Ratio:
logging.info(f'BAD NOTIONAL - EXTEND CHANGE: {previous_notional_position} -> {EXTEND_NOTIONAL_POSITION}; UR PNL: {EXTEND_UNREALIZED_PNL}; MULT: {EXTEND.mult}; d: {pos_dict}; resp: {resp}')
await kill_algo()
if EXTEND_NOTIONAL_POSITION != previous_notional_position:
logging.info(f'EXTEND NOTIONAL CHANGE: {previous_notional_position} -> {EXTEND_NOTIONAL_POSITION:.2f}; UR PNL: {EXTEND_UNREALIZED_PNL:.2f}; MULT: {EXTEND.mult:.0f}; resp: {bool(resp)}')
logging.info(f'EXTEND NOTIONAL CHANGE: {previous_notional_position} -> {EXTEND_NOTIONAL_POSITION:.2f}; UR PNL: {EXTEND_UNREALIZED_PNL:.2f}; MULT: {EXTEND.mult}; resp: {bool(resp)}')
### EXCHANGE INFO ###
async def get_aster_exch_info():
global ASTER_MIN_ORDER_QTY
async def get_aster_exch_info(symbol_override: str | None = None):
global ASTER
if symbol_override:
ASTER.symbol = utils.symbol_to_aster_fmt(symbol_override)
fut_acct_exchangeInfo: dict = {
"url": "/fapi/v3/exchangeInfo",
"method": "GET",
@@ -246,15 +268,27 @@ async def get_aster_exch_info():
}
r: dict = await aster_auth.post_authenticated_url(fut_acct_exchangeInfo) # ty:ignore[invalid-assignment]
s: list = r['symbols']
d: dict = [d for d in s if d.get('symbol', None) == 'ETHUSDT'][0]
d: dict = [d for d in s if d.get('symbol', None) == ASTER.symbol][0]
f: dict = [f for f in d['filters'] if f.get('filterType', None) == 'LOT_SIZE'][0]
ASTER_MIN_ORDER_QTY = float(f['minQty'])
async def get_extend_exch_info():
global EXTEND_MIN_ORDER_QTY
q: dict = [f for f in d['filters'] if f.get('filterType', None) == 'PRICE_FILTER'][0]
min_qty = float(f['minQty'])
min_qty = int(min_qty) if min_qty == int(min_qty) else min_qty
min_price = float(q['minPrice'])
min_price = int(min_price) if min_price == int(min_price) else min_price
ASTER.min_order_size = min_qty
ASTER.min_price = min_price
async def get_extend_exch_info(symbol_override: str | None = None):
global EXTEND
if symbol_override:
EXTEND.symbol = utils.symbol_to_extend_fmt(symbol_override)
r = await EXTEND_CLIENT.markets_info.get_markets_dict()
EXTEND_MIN_ORDER_QTY = float(r['ETH-USD'].trading_config.min_order_size)
EXTEND.min_order_size = float(r[EXTEND.symbol].trading_config.min_order_size)
EXTEND.min_price = float(r[EXTEND.symbol].trading_config.min_price_change)
### CANCEL ORDERS ###
async def aster_cancel_all_orders():
@@ -262,7 +296,7 @@ async def aster_cancel_all_orders():
"url": "/fapi/v3/allOpenOrders",
"method": "DELETE",
"params": {
'symbol': 'ETHUSDT',
'symbol': ASTER.symbol,
}
}
r = await aster_auth.post_authenticated_url(cancel_all_open_orders)
@@ -310,28 +344,60 @@ async def run_algo():
best_symbol_by_exchange_aster = structs.Perpetual_Exchange(**best_symbol_by_exchange['ASTER'])
best_symbol_by_exchange_extend = structs.Perpetual_Exchange(**best_symbol_by_exchange['EXTEND'])
ASTER_FUND_RATE_DICT = json.loads(VAL_KEY.get('fund_rate_aster')) # ty:ignore[invalid-argument-type]
EXTENDED_FUND_RATE_DICT = json.loads(VAL_KEY.get('fund_rate_extended')) # ty:ignore[invalid-argument-type]
ASTER_FUND_RATE: float = float(ASTER_FUND_RATE_DICT.get('funding_rate', 0))
EXTEND_FUND_RATE: float = float(EXTENDED_FUND_RATE_DICT.get('funding_rate', 0))
ASTER_FUND_RATE_DICT: Any = VAL_KEY.get('fund_rate_aster')
ASTER_FUND_RATE_DICT: dict = json.loads(s=ASTER_FUND_RATE_DICT) if ASTER_FUND_RATE_DICT is not None else {}
if ASTER_FUND_RATE_DICT.get('symbol', None) != ASTER.symbol:
ASTER_FUND_RATE: float = ASTER.initial_funding_rate
# logging.info(f'ASTER Symbol mismatch: {ASTER_FUND_RATE_DICT}; expected symbol: {ASTER.symbol}')
# raise ValueError(f'ASTER Symbol mismatch: {ASTER_FUND_RATE_DICT}; expected symbol: {ASTER.symbol}')
else:
ASTER_FUND_RATE: float = float(ASTER_FUND_RATE_DICT.get('funding_rate', 0))
EXTENDED_FUND_RATE_DICT: Any = VAL_KEY.get('fund_rate_extended')
EXTENDED_FUND_RATE_DICT: dict = json.loads(s=EXTENDED_FUND_RATE_DICT) if EXTENDED_FUND_RATE_DICT is not None else {}
if EXTENDED_FUND_RATE_DICT.get('symbol', None) != EXTEND.symbol:
EXTEND_FUND_RATE: float = EXTEND.initial_funding_rate
# logging.info(f'ASTER Symbol mismatch: {EXTENDED_FUND_RATE_DICT}; expected symbol: {EXTEND.symbol}')
# raise ValueError(f'ASTER Symbol mismatch: {EXTENDED_FUND_RATE_DICT}; expected symbol: {EXTEND.symbol}')
else:
EXTEND_FUND_RATE: float = float(EXTENDED_FUND_RATE_DICT.get('funding_rate', 0))
if ALGO_CONFIG.Overrides.Flip_Side_For_Testing:
ASTER_FUND_RATE = ASTER_FUND_RATE * -1
EXTEND_FUND_RATE = EXTEND_FUND_RATE * -1
if ALGO_CONFIG.Overrides.Flatten_Open_Positions or ALGO_CONFIG.Overrides.Flatten_Open_Positions_Opportunistic:
ROUNDING = ROUND_HALF_UP
else:
ROUNDING = ROUND_DOWN
ASTER_FUND_RATE_TIME = float(ASTER_FUND_RATE_DICT.get('next_funding_time_ts_ms', 0))
EXTEND_FUND_RATE_TIME = float(EXTENDED_FUND_RATE_DICT.get('next_funding_time_ts_ms', 0))
EXTEND_FUND_RATE_TIME = max([EXTEND_FUND_RATE_TIME, 0])
EXTEND_FUND_RATE_TIME = max([float(EXTENDED_FUND_RATE_DICT.get('next_funding_time_ts_ms', 0)), 0])
ASTER_TICKER_DICT = json.loads(VAL_KEY.get('fut_ticker_aster')) # ty:ignore[invalid-argument-type]
EXTENDED_TICKER_DICT = json.loads(VAL_KEY.get('fut_ticker_extended')) # ty:ignore[invalid-argument-type]
ASTER_TICKER_DICT: Any = VAL_KEY.get('fut_ticker_aster')
ASTER_TICKER_DICT: dict = json.loads(s=ASTER_TICKER_DICT) if ASTER_TICKER_DICT is not None else {}
if ( ASTER_TICKER_DICT.get('symbol', None) != ASTER.symbol ) and not(ALGO_CONFIG.Overrides.Flatten_Open_Positions):
logging.warning(f'ASTER Symbol mismatch: {ASTER_TICKER_DICT}; expected symbol: {ASTER.symbol}')
VAL_KEY.set(name='fr_algo_working_symbol', value=json.dumps(obj={'ASTER': asdict(obj=ASTER), 'EXTEND': asdict(obj=EXTEND)}))
time.sleep(5)
continue
# raise ValueError(f'ASTER Symbol mismatch: {ASTER_TICKER_DICT}; expected symbol: {ASTER.symbol}')
EXTENDED_TICKER_DICT: Any = VAL_KEY.get('fut_ticker_extended')
EXTENDED_TICKER_DICT: dict = json.loads(s=EXTENDED_TICKER_DICT) if EXTENDED_TICKER_DICT is not None else {}
if ( EXTENDED_TICKER_DICT.get('symbol', None) != EXTEND.symbol) and not(ALGO_CONFIG.Overrides.Flatten_Open_Positions):
logging.warning(f'EXTEND Symbol mismatch: {EXTENDED_TICKER_DICT}; expected symbol: {EXTEND.symbol}')
VAL_KEY.set(name='fr_algo_working_symbol', value=json.dumps(obj={'ASTER': asdict(obj=ASTER), 'EXTEND': asdict(obj=EXTEND)}))
time.sleep(5)
continue
# raise ValueError(f'EXTEND Symbol mismatch: {EXTENDED_TICKER_DICT}; expected symbol: {EXTEND.symbol}')
### Manage Local Collateral Using Updates from WS ###
ASTER_WS_COLLATERAL_UPDATES = VAL_KEY.get('fr_aster_user_positions')
ASTER_WS_COLLATERAL_UPDATES = json.loads(ASTER_WS_COLLATERAL_UPDATES) if ASTER_WS_COLLATERAL_UPDATES is not None else [] # ty:ignore[invalid-argument-type]
EXTEND_WS_COLLATERAL_UPDATES = VAL_KEY.get('fr_extended_user_positions')
EXTEND_WS_COLLATERAL_UPDATES = json.loads(EXTEND_WS_COLLATERAL_UPDATES) if EXTEND_WS_COLLATERAL_UPDATES is not None else [] # ty:ignore[invalid-argument-type]
# ASTER_WS_COLLATERAL_UPDATES = VAL_KEY.get('fr_aster_user_positions')
# ASTER_WS_COLLATERAL_UPDATES = json.loads(ASTER_WS_COLLATERAL_UPDATES) if ASTER_WS_COLLATERAL_UPDATES is not None else [] # ty:ignore[invalid-argument-type]
# EXTEND_WS_COLLATERAL_UPDATES = VAL_KEY.get('fr_extended_user_positions')
# EXTEND_WS_COLLATERAL_UPDATES = json.loads(EXTEND_WS_COLLATERAL_UPDATES) if EXTEND_WS_COLLATERAL_UPDATES is not None else [] # ty:ignore[invalid-argument-type]
### Manage Local Notionals Using Updates from WS ###
ASTER_WS_POS_UPDATES: Any = VAL_KEY.get(name='fr_aster_user_positions')
@@ -426,32 +492,42 @@ async def run_algo():
utils.send_tg_alert(f'FR_ALGO - EXTEND REJECTED ({order_id})')
elif order_update_status in ['PARTIALLY_FILLED']:
logging.info(f'EXTEND ORDER PARTIALLY FILLED: {order_id}')
await get_extend_collateral()
# await get_extend_collateral()
await get_extend_notional()
utils.send_tg_alert(f'FR_ALGO - EXTEND PARTIALLY FILLED ({order_id})')
elif order_update_status in ['FILLED']:
logging.info(f'EXTEND ORDER FILLED: {order_id}')
EXTEND_OPEN_ORDERS.pop(idx)
await get_extend_collateral()
# await get_extend_collateral()
await get_extend_notional()
utils.send_tg_alert(f'FR_ALGO - EXTEND FILLED ({order_id})')
else:
logging.critical(f'EXTEND ORDER STATUS CHG TO UNEXPECTED VALUE, KILLING... ({order_id}): {order_orig_status} -> {order_update_status}')
# if (best_symbol_by_exchange_aster.symbol != ASTER.symbol) or (best_symbol_by_exchange_extend.symbol != EXTEND.symbol):
# if abs( ASTER_NOTIONAL_POSITION ) > 0.00 or abs( EXTEND_NOTIONAL_POSITION ) > 0.00:
# print('Symbol switch - Flattening Positions')
# ALGO_CONFIG.Overrides.Flatten_Open_Positions = True
# else:
# print('Balances Flattened - Updating to Trade New Symbols:')
# print(f' ASTER.symbol -> {best_symbol_by_exchange_aster.symbol}')
# print(f' EXTEND.symbol -> {best_symbol_by_exchange_extend.symbol}')
# ALGO_CONFIG.Overrides.Flatten_Open_Positions = False
# ASTER = best_symbol_by_exchange_aster
# EXTEND = best_symbol_by_exchange_extend
# VAL_KEY.set(name='fr_algo_working_symbol', value=json.dumps(obj={'ASTER': asdict(obj=ASTER), 'EXTEND': asdict(obj=EXTEND)}))
if ALGO_CONFIG.Overrides.Allow_Symbol_Change:
if (best_symbol_by_exchange_aster.symbol != ASTER.symbol) or (best_symbol_by_exchange_extend.symbol != EXTEND.symbol):
if abs( ASTER_NOTIONAL_POSITION ) > 0.00 or abs( EXTEND_NOTIONAL_POSITION ) > 0.00:
if ALGO_CONFIG.Logging.Print_Summary_Each_Loop:
print(f'Symbol switch [{ASTER.symbol} > {best_symbol_by_exchange_aster.symbol}] - Flattening Positions')
ALGO_CONFIG.Overrides.Flatten_Open_Positions = True
else:
logging.info('Balances Flattened - Updating to Trade New Symbols:')
logging.info(f' ASTER.symbol -> {best_symbol_by_exchange_aster.symbol}')
logging.info(f' EXTEND.symbol -> {best_symbol_by_exchange_extend.symbol}')
ALGO_CONFIG.Overrides.Flatten_Open_Positions = False
if Open_Symbols:
logging.info(f'OPEN SYMBOLS TO CLOSE: {Open_Symbols}')
await get_aster_exch_info(symbol_override=Open_Symbols[0])
await get_extend_exch_info(symbol_override=Open_Symbols[0])
Open_Symbols.pop(0)
await get_aster_notional_position()
await get_extend_notional()
else:
ASTER = best_symbol_by_exchange_aster
EXTEND = best_symbol_by_exchange_extend
VAL_KEY.set(name='fr_algo_working_symbol', value=json.dumps(obj={'ASTER': asdict(obj=ASTER), 'EXTEND': asdict(obj=EXTEND)}))
min_between_fundings = round((abs(ASTER_FUND_RATE_TIME - EXTEND_FUND_RATE_TIME) / 1000 / 60))
@@ -479,7 +555,7 @@ 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 >= ( (ALGO_CONFIG.Config.Min_Fund_Rate_Pct_To_Trade*-1) / 100) ) and ( NEXT_NET_FUNDING_RATE <= ( ALGO_CONFIG.Config.Min_Fund_Rate_Pct_To_Trade / 100 ) )
if Flags.NET_FUNDING_IS_ZERO or ALGO_CONFIG.Overrides.Flatten_Open_Positions:
if Flags.NET_FUNDING_IS_ZERO or ALGO_CONFIG.Overrides.Flatten_Open_Positions or ALGO_CONFIG.Overrides.Flatten_Open_Positions_Opportunistic:
ALPHA_TGT_NOTIONAL = 0.00
# if ASTER_OPEN_ORDERS or EXTEND_OPEN_ORDERS:
# logging.info('NET FUNDING = 0.00; Cancelling Open Orders! then Waiting...')
@@ -536,16 +612,22 @@ async def run_algo():
EXTEND_TGT_TAIL = EXTEND_TGT_NOTIONAL - ( float(EXTEND_NOTIONAL_POSITION) + float(EXTEND_UNREALIZED_PNL) )
# EXTEND_TGT_TAIL = float(ASTER_NOTIONAL_POSITION)*-1
ASTER_TGT_TAIL_BASE_QTY = Decimal(str(float(ASTER_TGT_TAIL) / float(ASTER_TOB_PX))).quantize(Decimal(str(0.001)), rounding=ROUND_DOWN)
EXTEND_TGT_TAIL_BASE_QTY = Decimal(str(float(EXTEND_TGT_TAIL) / float(EXTEND_TOB_PX))).quantize(Decimal(str(0.001)), rounding=ROUND_DOWN)
min_order_size = ASTER.min_order_size
min_order_size = int(min_order_size) if min_order_size == int(min_order_size) else min_order_size
ASTER_TGT_TAIL_BASE_QTY = Decimal(str(float(ASTER_TGT_TAIL) / float(ASTER_TOB_PX))).quantize(Decimal(str(min_order_size)), rounding=ROUNDING)
MAX_MIN_ORDER_QTY = max([ASTER_MIN_ORDER_QTY, EXTEND_MIN_ORDER_QTY])
min_order_size = EXTEND.min_order_size
min_order_size = int(min_order_size) if min_order_size == int(min_order_size) else min_order_size
EXTEND_TGT_TAIL_BASE_QTY = Decimal(str(float(EXTEND_TGT_TAIL) / float(EXTEND_TOB_PX))).quantize(Decimal(str(min_order_size)), rounding=ROUNDING)
ASTER_TGT_TAIL_ORDERABLE = abs(ASTER_TGT_TAIL_BASE_QTY) >= MAX_MIN_ORDER_QTY
EXTEND_TGT_TAIL_ORDERABLE = abs(EXTEND_TGT_TAIL_BASE_QTY) >= MAX_MIN_ORDER_QTY
# MAX_MIN_ORDER_QTY = max([ASTER.min_order_size, EXTEND.min_order_size])
ASTER_TGT_TAIL_ORDERABLE = Decimal(str(abs(ASTER_TGT_TAIL_BASE_QTY))) >= Decimal(str(abs(ASTER.min_order_size)))
EXTEND_TGT_TAIL_ORDERABLE = Decimal(str(abs(EXTEND_TGT_TAIL_BASE_QTY))) >= Decimal(str(abs(EXTEND.min_order_size)))
# ASTER_TGT_TAIL_ORDERABLE = abs(ASTER_TGT_TAIL_BASE_QTY) >= MAX_MIN_ORDER_QTY
# EXTEND_TGT_TAIL_ORDERABLE = abs(EXTEND_TGT_TAIL_BASE_QTY) >= MAX_MIN_ORDER_QTY
# Hedge_Ratio = abs(( abs( max([abs(float(EXTEND_NOTIONAL_POSITION)), 0.01]) / max([abs(float(ASTER_NOTIONAL_POSITION)), 0.01]) ) - 1 ) * 100)
Hedge_Ratio = abs( ( EXTEND_NOTIONAL_POSITION + ASTER_NOTIONAL_POSITION ) / ASTER_NOTIONAL_POSITION ) * 100
Hedge_Ratio = abs( ( EXTEND_NOTIONAL_POSITION + ASTER_NOTIONAL_POSITION ) / max([ASTER_NOTIONAL_POSITION, 0.01]) ) * 100
Currently_Hedged = Hedge_Ratio < 1.00
def print_summary(use_logging: bool = False):
@@ -555,25 +637,25 @@ async def run_algo():
LOOP SLEEP (SEC): {ALGO_CONFIG.Config.Loop_Sleep_Sec}
FLIP SIDES FOR TESTING?: {ALGO_CONFIG.Overrides.Flip_Side_For_Testing}; ASTER ORDER ENABLED? {ALGO_CONFIG.Overrides.Allow_Ordering_Aster}; EXTEND ORDER ENABLED? {ALGO_CONFIG.Overrides.Allow_Ordering_Extend}
{pd.to_datetime(ASTER_FUND_RATE_TIME, unit='ms')} ({(pd.to_datetime(ASTER_FUND_RATE_TIME, unit='ms')-datetime.now()):}) | {pd.to_datetime(EXTEND_FUND_RATE_TIME, unit='ms')} ({(pd.to_datetime(EXTEND_FUND_RATE_TIME, unit='ms')-datetime.now()):})
ASTER: {ASTER_FUND_RATE:.6%} [{ASTER_FUND_RATE*10_000:.2f}bps] [{ASTER_FUND_RATE*1_000_000:.0f}pips] | EXTEND: {EXTEND_FUND_RATE:.6%} [{EXTEND_FUND_RATE*10_000:.2f}bps] [{EXTEND_FUND_RATE*1_000_000:.0f}pips]
ASTER: {ASTER_FUND_RATE:.6%} [{ASTER_FUND_RATE*10_000:.2f}bps] [{ASTER_FUND_RATE*1_000_000:.0f}pips] | EXTEND: {EXTEND_FUND_RATE:.6%} [{EXTEND_FUND_RATE*10_000:.2f}bps] [{EXTEND_FUND_RATE*1_000_000:.0f}pips]
ASTER: {'LONG PAYS SHORT' if ASTER_FUND_RATE > 0 else 'SHORT PAYS LONG'} | EXTEND: {'LONG PAYS SHORT' if EXTEND_FUND_RATE > 0 else 'SHORT PAYS LONG'}
ASTER: [ Notional Position $ : {ASTER_NOTIONAL_POSITION:.4f} ] | EXTEND: [ Notional Position $ : {EXTEND_NOTIONAL_POSITION:.4f} ]
ASTER: [ Notional Position $ : {ASTER_NOTIONAL_POSITION:.4f} ] | EXTEND: [ Notional Position $ : {EXTEND_NOTIONAL_POSITION:.4f} ]
SAME TIME? : {FUNDINGS_AT_SAME_TIME_NEXT_HR} [ Minutes Between Fundings: {min_between_fundings} ]
NET FUNDING : {NEXT_NET_FUNDING_RATE:.6%} [{NEXT_NET_FUNDING_RATE*10_000:.2f}bps] [{NEXT_NET_FUNDING_RATE*1_000_000:.0f}pips]; Is Zero?: {Flags.NET_FUNDING_IS_ZERO} [Min: {ALGO_CONFIG.Config.Min_Fund_Rate_Pct_To_Trade}]
ALPHA SIDE : {ALPHA_EXCH} [{ALPHA_CARRY_SIDE}]
TGT NOTIONAL: $ {abs(ALPHA_TGT_NOTIONAL):.2f}; Flatten Open Positions Flag? {ALGO_CONFIG.Overrides.Flatten_Open_Positions}
TGT NOTIONAL: $ {abs(ALPHA_TGT_NOTIONAL):.2f}; Flatten Open Positions Flag? {ALGO_CONFIG.Overrides.Flatten_Open_Positions}; Opportunistic? {ALGO_CONFIG.Overrides.Flatten_Open_Positions_Opportunistic}
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:.2f} - {ASTER_NOTIONAL_POSITION:.2f} + {ASTER_UNREALIZED_PNL:.2f} = {ASTER_TGT_TAIL:2f} | EXTEND: {EXTEND_TGT_NOTIONAL:.2f} - {EXTEND_NOTIONAL_POSITION:.2f} + {EXTEND_UNREALIZED_PNL:.2f} = {EXTEND_TGT_TAIL:2f}
ASTER: {ASTER_TGT_TAIL_BASE_QTY:.4f} > {MAX_MIN_ORDER_QTY:.4f} min [ Order: {ASTER_TGT_TAIL_ORDERABLE} ] | EXTEND: {EXTEND_TGT_TAIL_BASE_QTY:.4f} > {MAX_MIN_ORDER_QTY:.4f} min [ Order: {EXTEND_TGT_TAIL_ORDERABLE} ]
ASTER: {ASTER_TGT_NOTIONAL:.2f} - {ASTER_NOTIONAL_POSITION:.2f} + {ASTER_UNREALIZED_PNL:.2f} = {ASTER_TGT_TAIL:2f} | EXTEND: {EXTEND_TGT_NOTIONAL:.2f} - {EXTEND_NOTIONAL_POSITION:.2f} + {EXTEND_UNREALIZED_PNL:.2f} = {EXTEND_TGT_TAIL:2f}
ASTER: {ASTER_TGT_TAIL_BASE_QTY:.4f} > {ASTER.min_order_size:.4f} min [ Order: {ASTER_TGT_TAIL_ORDERABLE} ] | EXTEND: {EXTEND_TGT_TAIL_BASE_QTY:.4f} > {EXTEND.min_order_size:.4f} min [ Order: {EXTEND_TGT_TAIL_ORDERABLE} ]
ALPHA: {ALPHA_RATIO:.8f} ALPHA_RATIO: {Alpha_Nominator:_.2f} / {Alpha_Denominator:_.2f} (Px Diff: {abs(Alpha_Nominator-Alpha_Denominator):.2f}); Expected_Alpha = {Expected_Alpha:.6f} + FR[{NEXT_NET_FUNDING_RATE:.6f}] = * {Expected_Alpha_Net_FR:.6f} *
ALPHA: {ALPHA_RATIO:.8f} ALPHA_RATIO: {Alpha_Nominator:_.6f} / {Alpha_Denominator:_.6f} (Px Diff: {abs(Alpha_Nominator-Alpha_Denominator):.2f}); Expected_Alpha = {Expected_Alpha:.6f} + FR[{NEXT_NET_FUNDING_RATE:.6f}] = * {Expected_Alpha_Net_FR:.6f} *
FEES : TAKER: {0.0002:.2%}; Expected Alpha w Taker = {Expected_Alpha_Net_FR-0.0002:.6f} [w/o FR: {Expected_Alpha_w_Taker:.6f}]
HEDGE: {Hedge_Ratio:.2f}% <= {1:.2f}%: {Currently_Hedged} [{EXTEND_NOTIONAL_POSITION:.2f} / {ASTER_NOTIONAL_POSITION:.2f}]
MKT : Aster: {ASTER.symbol} (best: {best_symbol_by_exchange_aster.symbol}) | Extend: {ASTER.symbol} (best: {best_symbol_by_exchange_extend.symbol})
MKT : Aster: {ASTER.symbol} (best: {best_symbol_by_exchange_aster.symbol}) | Extend: {ASTER.symbol} (best: {best_symbol_by_exchange_extend.symbol})
--- ASTER OPEN ORDERS ---
{ASTER_OPEN_ORDERS}
@@ -591,14 +673,15 @@ async def run_algo():
### ROUTES ###
MIN_EXPECTED_ALPHA_TO_TRADE = 0.0001
# Just_Rejected_Or_Expired
# MIN_EXPECTED_ALPHA_TO_TRADE = 0.0001
MIN_EXPECTED_ALPHA_TO_TRADE = abs(NEXT_NET_FUNDING_RATE)*-1
# MIN_EXPECTED_ALPHA_TO_TRADE = -0.000001
# ALPHA RATIO CHECK
if not( ( Expected_Alpha_Net_FR_w_Taker > MIN_EXPECTED_ALPHA_TO_TRADE ) or ( ASTER_OPEN_ORDERS or EXTEND_OPEN_ORDERS or Just_Rejected_Or_Expired or ALGO_CONFIG.Overrides.Flatten_Open_Positions) ):
if not( ( Expected_Alpha_Net_FR_w_Taker > MIN_EXPECTED_ALPHA_TO_TRADE ) or ( ASTER_OPEN_ORDERS or EXTEND_OPEN_ORDERS or ALGO_CONFIG.Overrides.Flatten_Open_Positions) ) and Currently_Hedged:
if ALGO_CONFIG.Logging.Print_Summary_Each_Loop:
print(f'Alpha Ratio too low ({ALPHA_RATIO:.8f}) and no Open Orders...')
pass
elif ( Expected_Alpha_Net_FR_w_Taker <= MIN_EXPECTED_ALPHA_TO_TRADE ) and ( ASTER_OPEN_ORDERS or EXTEND_OPEN_ORDERS ) and Currently_Hedged:
elif ( Expected_Alpha_Net_FR_w_Taker <= MIN_EXPECTED_ALPHA_TO_TRADE ) and ( ASTER_OPEN_ORDERS or EXTEND_OPEN_ORDERS ) and Currently_Hedged and not(ALGO_CONFIG.Overrides.Flatten_Open_Positions):
await aster_cancel_all_orders()
await extend_cancel_all_orders()
logging.info('Expected_Alpha went away with open orders...cancelling since we are currently hedged...')
@@ -607,10 +690,12 @@ async def run_algo():
# logging.info(f'*** Alpha Ratio HIT - LETS ORDER: {ALPHA_RATIO:.8f}')
# ASTER
if ASTER_TGT_TAIL_ORDERABLE and ALGO_CONFIG.Overrides.Allow_Ordering_Aster:
# if ALGO_CONFIG.Overrides.Allow_Ordering_Aster:
symbol = ASTER.symbol
side = 'BUY' if ASTER_TGT_TAIL_BASE_QTY > 0.00 else 'SELL'
qty = str(abs(ASTER_TGT_TAIL_BASE_QTY))
price = ASTER_TOB_PX - ALGO_CONFIG.Config.Price_Worsener_Aster if side == 'BUY' else ASTER_TOB_PX + ALGO_CONFIG.Config.Price_Worsener_Aster
# qty = str(abs(ASTER_TGT_TAIL_BASE_QTY))
qty = Decimal(value=str(abs(ASTER_TGT_TAIL_BASE_QTY)))
price = ASTER_TOB_PX - ( float(ASTER.min_price)*int(ALGO_CONFIG.Config.Price_Worsener_Aster) ) if side == 'BUY' else ASTER_TOB_PX + ( float(ASTER.min_price)*int(ALGO_CONFIG.Config.Price_Worsener_Aster) )
if abs( ( float(ASTER_TGT_TAIL_BASE_QTY)*float(price) ) + ASTER_NOTIONAL_POSITION ) > ALGO_CONFIG.Config.Max_Target_Notional*ALGO_CONFIG.Config.Max_Order_Over_Notional_Ratio:
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})')
@@ -618,8 +703,12 @@ async def run_algo():
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']
open_order_px = float(ASTER_OPEN_ORDERS[0].get('price')) if ASTER_OPEN_ORDERS[0].get('price') is not None else float(ASTER_OPEN_ORDERS[0]['original_price'])
if round(open_order_px - float(price), 2) == 0.00:
logging.info('ASTER OPEN ORDER NO PX CHG; SKIPPING')
min_price = ASTER.min_price
min_price = int(min_price) if min_price == int(min_price) else min_price
if Decimal(str( float(open_order_px) - float(price) )).quantize(Decimal(str(min_price)), rounding=ROUND_HALF_UP) == 0.00:
# if round(open_order_px - float(price), len(str(ASTER.min_price)) - 2 ) == 0.00:
if ALGO_CONFIG.Logging.Print_Summary_Each_Loop:
print('ASTER OPEN ORDER NO PX CHG; SKIPPING')
place_order = False
else:
cancel_order: dict = {
@@ -644,8 +733,17 @@ async def run_algo():
place_order = False
logging.info('ASTER TRYNG TO ORDER 0.00 BASE QTY, SKIPPING')
if place_order:
price: Decimal = Decimal(str(price)).quantize(Decimal(str(0.01)), rounding=ROUND_DOWN)
if place_order:
min_price = ASTER.min_price
min_price = int(min_price) if min_price == int(min_price) else min_price
price: Decimal = Decimal(str(price)).quantize(Decimal(str(min_price)), rounding=ROUND_HALF_UP)
if qty >= ASTER.min_order_size:
reduceOnly = False
else:
reduceOnly = True
post_order = {
"url": "/fapi/v3/order",
"method": "POST",
@@ -656,6 +754,7 @@ async def run_algo():
'timeInForce': 'GTX',
'quantity': qty,
'price': price,
'reduceOnly': reduceOnly
}
}
order_resp: dict = await aster_auth.post_authenticated_url(post_order) # ty:ignore[invalid-assignment]
@@ -667,69 +766,93 @@ async def run_algo():
utils.send_tg_alert(f'FR_ALGO - ASTER Order ({order_resp['orderId']}). 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}')
print_summary(use_logging=True)
else:
logging.critical(f'*** Aster Order Response Abnormal: {order_resp}; post_order: {post_order}')
await kill_algo()
else:
pass
# logging.warning('ASTER PLACE ORDER CHECKS FAILED, SKIPPING')
elif not(ASTER_TGT_TAIL_ORDERABLE) and ASTER_OPEN_ORDERS:
### Add code to flatten small balances
logging.info('ASTER HAS NO TAIL BUT OPEN ORDERS - CANCELLING OPEN ORDERS')
await aster_cancel_all_orders()
# EXTEND
if EXTEND_TGT_TAIL_ORDERABLE and ALGO_CONFIG.Overrides.Allow_Ordering_Extend:
# if ALGO_CONFIG.Overrides.Allow_Ordering_Extend:
side = OrderSide.BUY if EXTEND_TGT_TAIL_BASE_QTY > 0.00 else OrderSide.SELL
symbol = EXTEND.symbol
qty = Decimal(value=str(abs(EXTEND_TGT_TAIL_BASE_QTY)))
Time_Since_Last_Aster_Fill_ms = ( datetime.now().timestamp()*1000 ) - Last_Aster_Fill_Time_Ts
min_price = EXTEND.min_price
min_price = int(min_price) if min_price == int(min_price) else min_price
if Time_Since_Last_Aster_Fill_ms > ( 1000 * ALGO_CONFIG.Config.Switch_To_Taker_Seconds ): # Change to allow taker orders if its been more than x seconds
post_only = False
price: Decimal = Decimal(value=str(EXTEND_TOB_PX - ALGO_CONFIG.Config.Price_Worsener_Extend if side == 'BUY' else EXTEND_TOB_PX + ALGO_CONFIG.Config.Price_Worsener_Extend)).quantize(Decimal(str(0.1)), rounding=ROUND_DOWN)
price: Decimal = Decimal(value=str(EXTEND_TOB_PX - ( float(min_price)*int(ALGO_CONFIG.Config.Price_Worsener_Extend) ) if side == 'BUY' else EXTEND_TOB_PX + ( float(min_price)*int(ALGO_CONFIG.Config.Price_Worsener_Extend) ) )).quantize(Decimal(str(min_price)), rounding=ROUND_HALF_UP)
else:
post_only = True
price: Decimal = Decimal(value=str(EXTEND_TOB_PX)).quantize(Decimal(str(0.1)), rounding=ROUND_DOWN)
price: Decimal = Decimal(value=str(EXTEND_TOB_PX)).quantize(Decimal(str(min_price)), rounding=ROUND_HALF_UP)
symbol = EXTEND.symbol
side = OrderSide.BUY if EXTEND_TGT_TAIL_BASE_QTY > 0.00 else OrderSide.SELL
qty = Decimal(value=str(abs(EXTEND_TGT_TAIL_BASE_QTY)))
if abs( ( float(EXTEND_TGT_TAIL_BASE_QTY)*float(price) ) + EXTEND_NOTIONAL_POSITION ) > ALGO_CONFIG.Config.Max_Target_Notional*ALGO_CONFIG.Config.Max_Order_Over_Notional_Ratio:
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})')
await kill_algo()
if EXTEND_OPEN_ORDERS:
open_order_dict = dict(EXTEND_OPEN_ORDERS[0])
open_order_id = open_order_dict['external_id']
open_order_id = str(open_order_dict['external_id'])
open_order_px = float(open_order_dict['price'])
open_order_filled_qty = float(open_order_dict['filled_qty'])
# qty = abs(float(qty)) - abs(float(open_order_filled_qty)) # Was trying to account for partial fills but thats not necessary, handled by position change so qty is correct w/o further adj.
# qty = Decimal(str(qty))
if qty >= MAX_MIN_ORDER_QTY:
if qty >= EXTEND.min_order_size:
place_order = True
place_residual_order = False
else:
place_order = False
logging.info(f'EXTEND NOT ORDERING DUE TO FILLED QTY RESIDUAL < MIN ORDER; Filled: {float(open_order_filled_qty):.4f}; Residual: {qty:.4f}')
if int(qty) == 0:
place_order = False
place_residual_order = False
logging.info(f'EXTEND NOT ORDERING DUE TO NOTIONAL QTY == 0; Filled: {float(open_order_filled_qty):.4f}; Residual: {qty:.4f}')
else:
place_order = True
place_residual_order = True
logging.info(f'Ordering RESIDUAL market order for remaining small amount: {qty}')
else:
open_order_id = None
open_order_px = 0
place_order = True
if place_order:
price: Decimal = Decimal(str(price)).quantize(Decimal(str(0.1)), rounding=ROUND_DOWN)
if round(open_order_px - float(price), 2) == 0.00:
logging.info('EXTEND OPEN ORDER NO PX CHG; SKIPPING')
if qty >= EXTEND.min_order_size:
place_residual_order = False
else:
place_residual_order = True
if place_order:
price: Decimal = Decimal(str(price)).quantize(Decimal(str(min_price)), rounding=ROUND_HALF_UP)
if round(open_order_px - float(price), len(str(min_price)) - 2 ) == 0.00:
if ALGO_CONFIG.Logging.Print_Summary_Each_Loop:
print('EXTEND OPEN ORDER NO PX CHG; SKIPPING')
else:
try:
if place_residual_order:
post_only = False
reduce_only = True
else:
# post_only = SEE ABOVE
reduce_only = False
taker_fee = taker_fee=Decimal("0.00000") if post_only else Decimal("0.00025")
order_resp: WrappedApiResponse[PlacedOrderModel] = await EXTEND_CLIENT.place_order(
market_name=symbol,
amount_of_synthetic=qty,
price=price,
amount_of_synthetic=Decimal(str(qty)),
price=Decimal(str(price)),
side=side,
taker_fee=taker_fee,
previous_order_id=open_order_id,
post_only=post_only,
post_only=post_only
# reduce_only=reduce_only
)
except Exception as e:
logging.error(f'EXTEND ORDER PLACEMENT FAILED - RESP: {order_resp}')
logging.error(f'EXTEND ORDER PLACEMENT FAILED: {e}')
logging.error(f'EXTEND ORDER PLACEMENT FAILED - POSTED: market_name:{symbol}, amount_of_synthetic:{qty}, price:{price}, side:{side},taker_fee:{taker_fee}, previous_order_id:{open_order_id}, post_only:{post_only}')
logging.error(f'EXTEND ORDER PLACEMENT FAILED - POSTED: market_name:{symbol}, amount_of_synthetic:{qty}, price:{price}, side:{side},taker_fee:{taker_fee}, previous_order_id:{open_order_id}, post_only:{post_only}; reduce_only:{reduce_only}')
logging.error(traceback.format_exc())
order_resp_dict = dict(order_resp)
@@ -751,15 +874,16 @@ async def run_algo():
logging.info(f'EXTEND ORDER PLACED SUCCESS: {order_dict}')
print_summary(use_logging=True)
else:
order_resp_dict.get
logging.critical(f'*** Extend Order Response Abnormal: {order_resp};')
await kill_algo()
else:
logging.warning('EXTEND PLACE ORDER CHECKS FAILED, SKIPPING')
elif not(EXTEND_TGT_TAIL_ORDERABLE) and EXTEND_OPEN_ORDERS:
logging.info('EXTEND HAS NO TAIL BUT OPEN ORDERS - CANCELLING OPEN ORDERS')
await extend_cancel_all_orders()
if ASTER_OPEN_ORDERS or EXTEND_OPEN_ORDERS:
continue
else:
@@ -783,11 +907,27 @@ async def main():
global VAL_KEY
global CON
global ALGO_CONFIG
global ASTER
global EXTEND
global Open_Symbols
_, EXTEND_CLIENT = await extend_auth.create_auth_account_and_trading_client()
VAL_KEY = valkey.Valkey(host='localhost', port=6379, db=0, decode_responses=True)
engine = create_async_engine('mysql+asyncmy://root:pwd@localhost/fund_rate')
best_symbol_by_exchange: dict = json.loads(s=VAL_KEY.get(name='fr_engine_best_fund_rate_output')) # ty:ignore[invalid-argument-type]
ASTER = structs.Perpetual_Exchange(**best_symbol_by_exchange['ASTER'])
EXTEND = structs.Perpetual_Exchange(**best_symbol_by_exchange['EXTEND'])
await set_comb_open_symbols()
if Open_Symbols:
logging.info(f'OPEN SYMBOLS TO CLOSE: {Open_Symbols}')
await get_aster_exch_info(symbol_override=Open_Symbols[0])
await get_extend_exch_info(symbol_override=Open_Symbols[0])
Open_Symbols.pop(0)
with open('algo_config.json', mode='r', encoding='utf-8') as file:
ALGO_CONFIG = json.load(file)
ALGO_CONFIG = structs.Algo_Config(**ALGO_CONFIG)
@@ -799,12 +939,12 @@ async def main():
async with engine.connect() as CON:
### ASTER SETUP ###
await get_aster_collateral()
# await get_aster_collateral()
await get_aster_notional_position()
await get_aster_exch_info()
await get_aster_open_orders()
### EXTEND SETUP ###
await get_extend_collateral()
# await get_extend_collateral()
await get_extend_notional()
await get_extend_exch_info()
await get_extend_open_orders()
@@ -826,4 +966,3 @@ if __name__ == '__main__':
logging.info(f"STARTED: {START_TIME}")
asyncio.run(main())