extend positions bug fix
This commit is contained in:
38
algo.ipynb
38
algo.ipynb
@@ -2,7 +2,7 @@
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"execution_count": 7,
|
||||
"id": "d1eed397",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -18,7 +18,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"execution_count": 8,
|
||||
"id": "c6151613",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
@@ -28,7 +28,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"execution_count": 31,
|
||||
"id": "d83c61e5",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
@@ -38,16 +38,32 @@
|
||||
"1"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"execution_count": 31,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"config_update = {'Min_Time_To_Funding_Minutes': 7}\n",
|
||||
"config_update = {\n",
|
||||
" 'Min_Time_To_Funding_Minutes': 60,\n",
|
||||
" 'Print_Summary_Each_Loop': True,\n",
|
||||
" 'Allow_Ordering_Aster': True,\n",
|
||||
" 'Allow_Ordering_Extend': True,\n",
|
||||
" 'Loop_Sleep_Sec': 0.0,\n",
|
||||
" 'Flip_Side_For_Testing': False,\n",
|
||||
" 'Price_Worsener_Extend': 0.0,\n",
|
||||
"}\n",
|
||||
"VAL_KEY.publish('fr_orchestrator_input', json.dumps(config_update))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "d2fdd7d2",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
@@ -71,24 +87,26 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'Config_Updated_Timestamp': 1777098091913,\n",
|
||||
" 'Allow_Ordering_Aster': True,\n",
|
||||
" 'Allow_Ordering_Extend': True,\n",
|
||||
" 'Allow_Ordering_Aster': False,\n",
|
||||
" 'Allow_Ordering_Extend': False,\n",
|
||||
" 'Loop_Sleep_Sec': 1,\n",
|
||||
" 'Max_Target_Notional': 0.0,\n",
|
||||
" 'Min_Time_To_Funding_Minutes': 60,\n",
|
||||
" 'Price_Worsener_Aster': 0.0,\n",
|
||||
" 'Price_Worsener_Extend': 0.0,\n",
|
||||
" 'Target_Open_Cash_Position': 10}"
|
||||
" 'Target_Open_Cash_Position': 10,\n",
|
||||
" 'Print_Summary_Each_Loop': False,\n",
|
||||
" 'Flip_Side_For_Testing': False}"
|
||||
]
|
||||
},
|
||||
"execution_count": 16,
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
"Config_Updated_Timestamp": 1777098091913,
|
||||
"Allow_Ordering_Aster": true,
|
||||
"Allow_Ordering_Extend": true,
|
||||
"Loop_Sleep_Sec": 1,
|
||||
"Loop_Sleep_Sec": 0.00,
|
||||
"Max_Target_Notional": 0.00,
|
||||
"Min_Time_To_Funding_Minutes": 60,
|
||||
"Min_Time_To_Funding_Minutes": 10,
|
||||
"Price_Worsener_Aster": 0.0,
|
||||
"Price_Worsener_Extend": 0.0,
|
||||
"Target_Open_Cash_Position": 10,
|
||||
"Print_Summary_Each_Loop" : false
|
||||
"Print_Summary_Each_Loop" : false,
|
||||
"Flip_Side_For_Testing": false
|
||||
}
|
||||
98
aster.ipynb
98
aster.ipynb
File diff suppressed because one or more lines are too long
64
main.py
64
main.py
@@ -229,6 +229,8 @@ async def kill_algo():
|
||||
### ALGO LOOP ###
|
||||
async def run_algo():
|
||||
global ALGO_CONFIG
|
||||
global ASTER_OPEN_ORDERS
|
||||
global EXTEND_OPEN_ORDERS
|
||||
|
||||
try:
|
||||
while True:
|
||||
@@ -246,8 +248,14 @@ async def run_algo():
|
||||
|
||||
ASTER_FUND_RATE = float(ASTER_FUND_RATE_DICT.get('funding_rate', 0))
|
||||
EXTEND_FUND_RATE = float(EXTENDED_FUND_RATE_DICT.get('funding_rate', 0))
|
||||
|
||||
if ALGO_CONFIG.Flip_Side_For_Testing:
|
||||
ASTER_FUND_RATE = ASTER_FUND_RATE * -1
|
||||
EXTEND_FUND_RATE = EXTEND_FUND_RATE * -1
|
||||
|
||||
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])
|
||||
|
||||
ASTER_TICKER_DICT = json.loads(VAL_KEY.get('fut_ticker_aster'))
|
||||
EXTENDED_TICKER_DICT = json.loads(VAL_KEY.get('fut_ticker_extended'))
|
||||
@@ -290,11 +298,13 @@ async def run_algo():
|
||||
|
||||
if len(EXTEND_WS_POS_UPDATES) > 0:
|
||||
await get_extend_notional(resp=EXTEND_WS_POS_UPDATES)
|
||||
# await get_extend_notional() # ************** NOT USING WEBSOCKET FEED DUE TO ISSUES WITH IT OVERWRITING API DATA ie the WS just statically shows last update and doesnt pull new when you start the algo.
|
||||
### Also WS was just stale and caused issues where it sees a fill then gets new API Collateral (correct) and then the next loop would be the old incorrect collateral in the WS, causing bad orders. Do not have issue on ASTER.
|
||||
|
||||
if ASTER_WS_ORDER_UPDATES is not None:
|
||||
for idx, o in enumerate(ASTER_OPEN_ORDERS):
|
||||
order_id = o.get('order_id') if o.get('order_id') is not None else o.get('orderId')
|
||||
order_orig_status = o['status']
|
||||
order_id = o.get('order_id') if o.get('order_id') is not None else o['orderId']
|
||||
order_orig_status = o['status'] ### Got a keyerror on this
|
||||
order_update = [ou for ou in ASTER_WS_ORDER_UPDATES if ou.get('order_id', None) == order_id]
|
||||
|
||||
if len(order_update) > 0:
|
||||
@@ -349,9 +359,6 @@ async def run_algo():
|
||||
else:
|
||||
logging.critical(f'EXTEND ORDER STATUS CHG TO UNEXPECTED VALUE, KILLING... ({order_id}): {order_orig_status} -> {order_update_status}')
|
||||
|
||||
|
||||
ASTER_PAYOUT_DIRECTION_STR = 'LONG PAYS SHORT' if ASTER_FUND_RATE > 0 else 'SHORT PAYS LONG'
|
||||
EXTEND_PAYOUT_DIRECTION_STR = 'LONG PAYS SHORT' if EXTEND_FUND_RATE > 0 else 'SHORT PAYS LONG'
|
||||
|
||||
min_between_fundings = round((abs(ASTER_FUND_RATE_TIME - EXTEND_FUND_RATE_TIME) / 1000 / 60))
|
||||
FUNDINGS_AT_SAME_TIME_NEXT_HR = min_between_fundings < 5
|
||||
@@ -382,7 +389,6 @@ async def run_algo():
|
||||
Flags.NET_FUNDING_IS_ZERO = NEXT_NET_FUNDING_RATE == 0.00
|
||||
if Flags.NET_FUNDING_IS_ZERO:
|
||||
logging.info('NET FUNDING = 0.00; Cancelling Open Orders; Wait Until Non-Zero.')
|
||||
|
||||
ALPHA_TGT_NOTIONAL = 0.00
|
||||
|
||||
if ALPHA_EXCH == 'EXTEND':
|
||||
@@ -420,9 +426,10 @@ async def run_algo():
|
||||
OUT: print | logging.info = logging.info if use_logging else print
|
||||
|
||||
OUT(f'''
|
||||
FLIP SIDES FOR TESTING?: {ALGO_CONFIG.Flip_Side_For_Testing}
|
||||
{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_PAYOUT_DIRECTION_STR} | EXTEND: {EXTEND_PAYOUT_DIRECTION_STR}
|
||||
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: [ Available Collateral: {ASTER_AVAIL_COLLATERAL:.4f} ] | EXTEND: [ Available Collateral: {EXTEND_AVAIL_COLLATERAL:.4f} ]
|
||||
ASTER: [ Notional Position $ : {ASTER_NOTIONAL_POSITION:.4f} ] | EXTEND: [ Notional Position $ : {EXTEND_NOTIONAL_POSITION:.4f} ]
|
||||
|
||||
@@ -508,7 +515,8 @@ async def run_algo():
|
||||
logging.info(f'ASTER ORDER PLACED SUCCESS: {order_resp}')
|
||||
print_summary(use_logging=True)
|
||||
else:
|
||||
logging.warning('ASTER PLACE ORDER CHECKS FAILED, SKIPPING')
|
||||
pass
|
||||
# logging.warning('ASTER PLACE ORDER CHECKS FAILED, SKIPPING')
|
||||
|
||||
elif not(ASTER_TGT_TAIL_ORDERABLE) and ASTER_OPEN_ORDERS:
|
||||
logging.info('ASTER HAS NO TAIL BUT OPEN ORDERS - CANCELLING OPEN ORDERS')
|
||||
@@ -528,7 +536,16 @@ async def run_algo():
|
||||
open_order_dict = dict(EXTEND_OPEN_ORDERS[0])
|
||||
open_order_id = open_order_dict['external_id']
|
||||
open_order_px = float(open_order_dict['price'])
|
||||
place_order = True
|
||||
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:
|
||||
place_order = True
|
||||
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}')
|
||||
else:
|
||||
open_order_id = None
|
||||
open_order_px = 0
|
||||
@@ -538,15 +555,22 @@ async def run_algo():
|
||||
if round(open_order_px - float(price), 2) == 0.00:
|
||||
logging.info('EXTEND OPEN ORDER NO PX CHG; SKIPPING')
|
||||
else:
|
||||
order_resp = await EXTEND_CLIENT.place_order(
|
||||
market_name=symbol,
|
||||
amount_of_synthetic=qty,
|
||||
price=price,
|
||||
side=side,
|
||||
taker_fee=Decimal("0.00025"),
|
||||
previous_order_id=open_order_id,
|
||||
)
|
||||
try:
|
||||
order_resp = await EXTEND_CLIENT.place_order(
|
||||
market_name=symbol,
|
||||
amount_of_synthetic=qty,
|
||||
price=price,
|
||||
side=side,
|
||||
taker_fee=Decimal("0.00025"),
|
||||
previous_order_id=open_order_id,
|
||||
)
|
||||
except Exception as e:
|
||||
logging.error(f'EXTEND ORDER PLACEMENT FAILED - RESP: {order_resp}')
|
||||
logging.error(f'EXTEND ORDER PLACEMENT FAILED: {e}')
|
||||
logging.error(traceback.format_exc())
|
||||
|
||||
order_resp_dict = dict(order_resp)
|
||||
|
||||
if order_resp_dict.get('status', None) == 'OK':
|
||||
if EXTEND_OPEN_ORDERS:
|
||||
EXTEND_OPEN_ORDERS.pop(0)
|
||||
@@ -554,11 +578,15 @@ async def run_algo():
|
||||
order_dict = dict(order_resp_dict['data'])
|
||||
order_dict['status'] = 'NEW'
|
||||
order_dict['price'] = str(price)
|
||||
order_dict['qty'] = str(qty)
|
||||
order_dict['filled_qty'] = str(0)
|
||||
|
||||
EXTEND_OPEN_ORDERS.append(order_dict)
|
||||
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}')
|
||||
print_summary(use_logging=True)
|
||||
else:
|
||||
order_resp_dict.get
|
||||
else:
|
||||
logging.warning('EXTEND PLACE ORDER CHECKS FAILED, SKIPPING')
|
||||
|
||||
@@ -595,6 +623,8 @@ async def main():
|
||||
with open('algo_config.json', 'r', encoding='utf-8') as file:
|
||||
ALGO_CONFIG = json.load(file, object_hook=lambda d: structs.Algo_Config(**d))
|
||||
ALGO_CONFIG.Max_Target_Notional = float(min([ASTER_MULT, EXTEND_MULT]) * ALGO_CONFIG.Target_Open_Cash_Position)
|
||||
|
||||
VAL_KEY.set('fr_orchestrator_output', json.dumps(asdict(ALGO_CONFIG)))
|
||||
|
||||
async with engine.connect() as CON:
|
||||
### ASTER SETUP ###
|
||||
|
||||
Binary file not shown.
@@ -20,7 +20,6 @@ async def insert_df_to_mysql(
|
||||
df = pd.DataFrame(params)
|
||||
else:
|
||||
df = params
|
||||
print(f'DB INSERT: table: {table_name}; CON: {CON}; params: {params}')
|
||||
await CON.run_sync(
|
||||
lambda sync_conn: df.to_sql(name=table_name, con=sync_conn, if_exists='append', index=False)
|
||||
)
|
||||
|
||||
@@ -18,6 +18,7 @@ class Algo_Config:
|
||||
Target_Open_Cash_Position: int
|
||||
|
||||
Print_Summary_Each_Loop: bool = False
|
||||
Flip_Side_For_Testing: bool = False
|
||||
|
||||
@dataclass(kw_only=True)
|
||||
class Flags:
|
||||
|
||||
@@ -193,7 +193,7 @@ async def ws_stream():
|
||||
'updated_at_ts': p['updatedAt'],
|
||||
}
|
||||
list_for_df.append(position_update)
|
||||
LOCAL_RECENT_POSITIONS = utils.upsert_list_of_dicts_by_id(LOCAL_RECENT_POSITIONS, position_update, id='position_id', seq_check_field='sequence_id')
|
||||
LOCAL_RECENT_POSITIONS = utils.upsert_list_of_dicts_by_id(LOCAL_RECENT_POSITIONS, position_update, id='market', seq_check_field='sequence_id')
|
||||
LOCAL_RECENT_POSITIONS = [t for t in LOCAL_RECENT_POSITIONS if t.get('timestamp_arrival', 0) >= LOOKBACK_MIN_TS_MS]
|
||||
|
||||
VAL_KEY_OBJ = json.dumps(LOCAL_RECENT_POSITIONS)
|
||||
|
||||
Reference in New Issue
Block a user