testing ordering as taker
This commit is contained in:
19
algo.ipynb
19
algo.ipynb
@@ -2,7 +2,7 @@
|
|||||||
"cells": [
|
"cells": [
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 76,
|
"execution_count": 8,
|
||||||
"id": "d1eed397",
|
"id": "d1eed397",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 77,
|
"execution_count": 9,
|
||||||
"id": "c6151613",
|
"id": "c6151613",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
@@ -38,21 +38,22 @@
|
|||||||
"1"
|
"1"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 131,
|
"execution_count": 19,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"source": [
|
"source": [
|
||||||
"config_update = {\n",
|
"config_update = {\n",
|
||||||
" 'Min_Time_To_Funding_Minutes': 7,\n",
|
" # 'Min_Time_To_Funding_Minutes': 60,\n",
|
||||||
" # 'Allow_Ordering_Aster': True,\n",
|
" # 'Allow_Ordering_Aster': False,\n",
|
||||||
" # 'Allow_Ordering_Extend': True,\n",
|
" # 'Allow_Ordering_Extend': False,\n",
|
||||||
" 'Loop_Sleep_Sec': 0.00,\n",
|
" 'Loop_Sleep_Sec': 0.00,\n",
|
||||||
"# 'Flip_Side_For_Testing': False,\n",
|
" 'Min_Fund_Rate_Pct_To_Trade': 0.0001,\n",
|
||||||
|
" # 'Flip_Side_For_Testing': False,\n",
|
||||||
"# 'Price_Worsener_Extend': 0.0,\n",
|
"# 'Price_Worsener_Extend': 0.0,\n",
|
||||||
" 'Log_Summary_Each_Loop': False,\n",
|
" # 'Log_Summary_Each_Loop': False,\n",
|
||||||
" 'Print_Summary_Each_Loop': False,\n",
|
" # 'Print_Summary_Each_Loop': False,\n",
|
||||||
"}\n",
|
"}\n",
|
||||||
"VAL_KEY.publish('fr_orchestrator_input', json.dumps(config_update))"
|
"VAL_KEY.publish('fr_orchestrator_input', json.dumps(config_update))"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
{
|
{
|
||||||
"Config_Updated_Timestamp": 1777312620005,
|
"Config_Updated_Timestamp": 1777388081818,
|
||||||
"Allow_Ordering_Aster": true,
|
"Allow_Ordering_Aster": true,
|
||||||
"Allow_Ordering_Extend": true,
|
"Allow_Ordering_Extend": true,
|
||||||
"Loop_Sleep_Sec": 0.0,
|
"Loop_Sleep_Sec": 0.0,
|
||||||
"Max_Target_Notional": 0.0,
|
"Max_Target_Notional": 0.0,
|
||||||
"Min_Time_To_Funding_Minutes": 7,
|
"Min_Time_To_Funding_Minutes": 60,
|
||||||
"Price_Worsener_Aster": 0.0,
|
"Min_Fund_Rate_Pct_To_Trade": 0.000,
|
||||||
"Price_Worsener_Extend": 0.0,
|
"Price_Worsener_Aster": 0.01,
|
||||||
|
"Price_Worsener_Extend": -0.1,
|
||||||
"Target_Open_Cash_Position": 10,
|
"Target_Open_Cash_Position": 10,
|
||||||
"Log_Summary_Each_Loop": false,
|
"Log_Summary_Each_Loop": false,
|
||||||
"Print_Summary_Each_Loop": false,
|
"Print_Summary_Each_Loop": true,
|
||||||
|
"Flatten_Open_Positions": true,
|
||||||
"Flip_Side_For_Testing": false
|
"Flip_Side_For_Testing": false
|
||||||
}
|
}
|
||||||
@@ -594,7 +594,7 @@
|
|||||||
"name": "python",
|
"name": "python",
|
||||||
"nbconvert_exporter": "python",
|
"nbconvert_exporter": "python",
|
||||||
"pygments_lexer": "ipython3",
|
"pygments_lexer": "ipython3",
|
||||||
"version": "3.13.12"
|
"version": "3.13.13"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nbformat": 4,
|
"nbformat": 4,
|
||||||
|
|||||||
5701
engine_dispersion.ipynb
Normal file
5701
engine_dispersion.ipynb
Normal file
File diff suppressed because one or more lines are too long
@@ -27,7 +27,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 2,
|
"execution_count": null,
|
||||||
"id": "ff971ca9",
|
"id": "ff971ca9",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
"ORDER_MARKET = \"ETH-USD\"\n",
|
"ORDER_MARKET = \"ETH-USD\"\n",
|
||||||
"ORDER_SIDE = OrderSide.BUY\n",
|
"ORDER_SIDE = OrderSide.BUY\n",
|
||||||
"ORDER_QTY = Decimal(\"0.01\")\n",
|
"ORDER_QTY = Decimal(\"0.01\")\n",
|
||||||
"ORDER_PRICE = Decimal(\"2200\")"
|
"ORDER_PRICE = Decimal(\"2200.1\")"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -59,10 +59,33 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 41,
|
"execution_count": 4,
|
||||||
"id": "c366706f",
|
"id": "c366706f",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Error response from https://api.starknet.extended.exchange/api/v1/user/order: {\"status\":\"ERROR\",\"error\":{\"code\":1125,\"message\":\"Invalid price precision\"}}\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ename": "ValueError",
|
||||||
|
"evalue": "Error response from https://api.starknet.extended.exchange/api/v1/user/order: code 400 - {\"status\":\"ERROR\",\"error\":{\"code\":1125,\"message\":\"Invalid price precision\"}}",
|
||||||
|
"output_type": "error",
|
||||||
|
"traceback": [
|
||||||
|
"\u001b[31m---------------------------------------------------------------------------\u001b[39m",
|
||||||
|
"\u001b[31mValueError\u001b[39m Traceback (most recent call last)",
|
||||||
|
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[4]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m placed_order = await trading_client.place_order(\n\u001b[32m 2\u001b[39m market_name=ORDER_MARKET,\n\u001b[32m 3\u001b[39m amount_of_synthetic=ORDER_QTY,\n\u001b[32m 4\u001b[39m price=ORDER_PRICE,\n",
|
||||||
|
"\u001b[36mFile \u001b[39m\u001b[32m~/miniconda3/envs/py_313/lib/python3.13/site-packages/x10/perpetual/trading_client/trading_client.py:101\u001b[39m, in \u001b[36mPerpetualTradingClient.place_order\u001b[39m\u001b[34m(self, market_name, amount_of_synthetic, price, side, taker_fee, post_only, previous_order_id, expire_time, time_in_force, self_trade_protection_level, external_id, builder_fee, builder_id, reduce_only, tp_sl_type, take_profit, stop_loss)\u001b[39m\n\u001b[32m 78\u001b[39m expire_time = utc_now() + timedelta(hours=\u001b[32m1\u001b[39m)\n\u001b[32m 80\u001b[39m order = create_order_object(\n\u001b[32m 81\u001b[39m account=\u001b[38;5;28mself\u001b[39m.__stark_account,\n\u001b[32m 82\u001b[39m market=market,\n\u001b[32m (...)\u001b[39m\u001b[32m 99\u001b[39m stop_loss=stop_loss,\n\u001b[32m 100\u001b[39m )\n\u001b[32m--> \u001b[39m\u001b[32m101\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;01mawait\u001b[39;00m \u001b[38;5;28mself\u001b[39m.__order_management_module.place_order(order)\n",
|
||||||
|
"\u001b[36mFile \u001b[39m\u001b[32m~/miniconda3/envs/py_313/lib/python3.13/site-packages/x10/perpetual/trading_client/order_management_module.py:31\u001b[39m, in \u001b[36mOrderManagementModule.place_order\u001b[39m\u001b[34m(self, order)\u001b[39m\n\u001b[32m 28\u001b[39m LOGGER.debug(\u001b[33m\"\u001b[39m\u001b[33mPlacing an order: id=\u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[33m\"\u001b[39m, order.id)\n\u001b[32m 30\u001b[39m url = \u001b[38;5;28mself\u001b[39m._get_url(\u001b[33m\"\u001b[39m\u001b[33m/user/order\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m---> \u001b[39m\u001b[32m31\u001b[39m response = \u001b[38;5;28;01mawait\u001b[39;00m send_post_request(\n\u001b[32m 32\u001b[39m \u001b[38;5;28;01mawait\u001b[39;00m \u001b[38;5;28mself\u001b[39m.get_session(),\n\u001b[32m 33\u001b[39m url,\n\u001b[32m 34\u001b[39m PlacedOrderModel,\n\u001b[32m 35\u001b[39m json=order.to_api_request_json(exclude_none=\u001b[38;5;28;01mTrue\u001b[39;00m),\n\u001b[32m 36\u001b[39m api_key=\u001b[38;5;28mself\u001b[39m._get_api_key(),\n\u001b[32m 37\u001b[39m )\n\u001b[32m 38\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m response\n",
|
||||||
|
"\u001b[36mFile \u001b[39m\u001b[32m~/miniconda3/envs/py_313/lib/python3.13/site-packages/x10/utils/http.py:173\u001b[39m, in \u001b[36msend_post_request\u001b[39m\u001b[34m(session, url, model_class, json, api_key, request_headers, response_code_to_exception)\u001b[39m\n\u001b[32m 171\u001b[39m \u001b[38;5;28;01masync\u001b[39;00m \u001b[38;5;28;01mwith\u001b[39;00m session.post(url, json=json, headers=headers) \u001b[38;5;28;01mas\u001b[39;00m response:\n\u001b[32m 172\u001b[39m response_text = \u001b[38;5;28;01mawait\u001b[39;00m response.text()\n\u001b[32m--> \u001b[39m\u001b[32m173\u001b[39m \u001b[30;43mhandle_known_errors\u001b[39;49m\u001b[30;43m(\u001b[39;49m\u001b[30;43murl\u001b[39;49m\u001b[30;43m,\u001b[39;49m\u001b[30;43m \u001b[39;49m\u001b[30;43mresponse_code_to_exception\u001b[39;49m\u001b[30;43m,\u001b[39;49m\u001b[30;43m \u001b[39;49m\u001b[30;43mresponse\u001b[39;49m\u001b[30;43m,\u001b[39;49m\u001b[30;43m \u001b[39;49m\u001b[30;43mresponse_text\u001b[39;49m\u001b[30;43m)\u001b[39;49m\n\u001b[32m 174\u001b[39m response_model = parse_response_to_model(response_text, model_class)\n\u001b[32m 176\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m (response_model.status != ResponseStatus.OK) \u001b[38;5;129;01mor\u001b[39;00m (response_model.error \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m):\n",
|
||||||
|
"\u001b[36mFile \u001b[39m\u001b[32m~/miniconda3/envs/py_313/lib/python3.13/site-packages/x10/utils/http.py:243\u001b[39m, in \u001b[36mhandle_known_errors\u001b[39m\u001b[34m(url, response_code_handler, response, response_text)\u001b[39m\n\u001b[32m 241\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m response.status > \u001b[32m299\u001b[39m:\n\u001b[32m 242\u001b[39m LOGGER.error(\u001b[33m\"\u001b[39m\u001b[33mError response from \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[33m: \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[33m\"\u001b[39m, url, response_text)\n\u001b[32m--> \u001b[39m\u001b[32m243\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[33mError response from \u001b[39m\u001b[38;5;132;01m{\u001b[39;00murl\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m: code \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mresponse.status\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m - \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mresponse_text\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m\"\u001b[39m)\n",
|
||||||
|
"\u001b[31mValueError\u001b[39m: Error response from https://api.starknet.extended.exchange/api/v1/user/order: code 400 - {\"status\":\"ERROR\",\"error\":{\"code\":1125,\"message\":\"Invalid price precision\"}}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"source": [
|
"source": [
|
||||||
"placed_order = await trading_client.place_order(\n",
|
"placed_order = await trading_client.place_order(\n",
|
||||||
" market_name=ORDER_MARKET,\n",
|
" market_name=ORDER_MARKET,\n",
|
||||||
@@ -70,7 +93,7 @@
|
|||||||
" price=ORDER_PRICE,\n",
|
" price=ORDER_PRICE,\n",
|
||||||
" side=ORDER_SIDE,\n",
|
" side=ORDER_SIDE,\n",
|
||||||
" taker_fee=Decimal(\"0.00025\"),\n",
|
" taker_fee=Decimal(\"0.00025\"),\n",
|
||||||
" previous_order_id='1295034892466447624365619416628580523728221205816494340545831832663414858661'\n",
|
" # previous_order_id='1295034892466447624365619416628580523728221205816494340545831832663414858661'\n",
|
||||||
")"
|
")"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -789,7 +812,7 @@
|
|||||||
"name": "python",
|
"name": "python",
|
||||||
"nbconvert_exporter": "python",
|
"nbconvert_exporter": "python",
|
||||||
"pygments_lexer": "ipython3",
|
"pygments_lexer": "ipython3",
|
||||||
"version": "3.13.12"
|
"version": "3.13.13"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nbformat": 4,
|
"nbformat": 4,
|
||||||
|
|||||||
324
main.py
324
main.py
@@ -350,11 +350,13 @@ async def run_algo():
|
|||||||
logging.info(f'ASTER ORDER PARTIALLY FILLED: {order_id}')
|
logging.info(f'ASTER ORDER PARTIALLY FILLED: {order_id}')
|
||||||
await get_aster_collateral()
|
await get_aster_collateral()
|
||||||
await get_aster_notional_position()
|
await get_aster_notional_position()
|
||||||
|
utils.send_tg_alert(f'FR_ALGO - ASTER PARTIALLY FILLED ({order_id})')
|
||||||
elif order_update_status in ['FILLED']:
|
elif order_update_status in ['FILLED']:
|
||||||
logging.info(f'ASTER ORDER FILLED: {order_id}')
|
logging.info(f'ASTER ORDER FILLED: {order_id}')
|
||||||
ASTER_OPEN_ORDERS.pop(idx)
|
ASTER_OPEN_ORDERS.pop(idx)
|
||||||
await get_aster_collateral()
|
await get_aster_collateral()
|
||||||
await get_aster_notional_position()
|
await get_aster_notional_position()
|
||||||
|
utils.send_tg_alert(f'FR_ALGO - ASTER FILLED ({order_id})')
|
||||||
else:
|
else:
|
||||||
logging.critical(f'EXTEND ORDER STATUS CHG TO UNEXPECTED VALUE, KILLING... ({order_id}): {order_orig_status} -> {order_update_status}')
|
logging.critical(f'EXTEND ORDER STATUS CHG TO UNEXPECTED VALUE, KILLING... ({order_id}): {order_orig_status} -> {order_update_status}')
|
||||||
if EXTEND_WS_ORDER_UPDATES is not None:
|
if EXTEND_WS_ORDER_UPDATES is not None:
|
||||||
@@ -379,11 +381,13 @@ async def run_algo():
|
|||||||
logging.info(f'EXTEND ORDER PARTIALLY FILLED: {order_id}')
|
logging.info(f'EXTEND ORDER PARTIALLY FILLED: {order_id}')
|
||||||
await get_extend_collateral()
|
await get_extend_collateral()
|
||||||
await get_extend_notional()
|
await get_extend_notional()
|
||||||
|
utils.send_tg_alert(f'FR_ALGO - EXTEND PARTIALLY FILLED ({order_id})')
|
||||||
elif order_update_status in ['FILLED']:
|
elif order_update_status in ['FILLED']:
|
||||||
logging.info(f'EXTEND ORDER FILLED: {order_id}')
|
logging.info(f'EXTEND ORDER FILLED: {order_id}')
|
||||||
EXTEND_OPEN_ORDERS.pop(idx)
|
EXTEND_OPEN_ORDERS.pop(idx)
|
||||||
await get_extend_collateral()
|
await get_extend_collateral()
|
||||||
await get_extend_notional()
|
await get_extend_notional()
|
||||||
|
utils.send_tg_alert(f'FR_ALGO - EXTEND FILLED ({order_id})')
|
||||||
else:
|
else:
|
||||||
logging.critical(f'EXTEND ORDER STATUS CHG TO UNEXPECTED VALUE, KILLING... ({order_id}): {order_orig_status} -> {order_update_status}')
|
logging.critical(f'EXTEND ORDER STATUS CHG TO UNEXPECTED VALUE, KILLING... ({order_id}): {order_orig_status} -> {order_update_status}')
|
||||||
|
|
||||||
@@ -414,10 +418,18 @@ async def run_algo():
|
|||||||
return EXTEND_FUND_RATE
|
return EXTEND_FUND_RATE
|
||||||
|
|
||||||
NEXT_NET_FUNDING_RATE = calc_next_net_fund_rate(FUNDINGS_AT_SAME_TIME_NEXT_HR)
|
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
|
Flags.NET_FUNDING_IS_ZERO = ( NEXT_NET_FUNDING_RATE >= ( (ALGO_CONFIG.Min_Fund_Rate_Pct_To_Trade*-1) / 100) ) and ( NEXT_NET_FUNDING_RATE <= ( ALGO_CONFIG.Min_Fund_Rate_Pct_To_Trade / 100 ) )
|
||||||
if Flags.NET_FUNDING_IS_ZERO:
|
if Flags.NET_FUNDING_IS_ZERO or ALGO_CONFIG.Flatten_Open_Positions:
|
||||||
logging.info('NET FUNDING = 0.00; Cancelling Open Orders; Wait Until Non-Zero.')
|
|
||||||
ALPHA_TGT_NOTIONAL = 0.00
|
ALPHA_TGT_NOTIONAL = 0.00
|
||||||
|
# if ASTER_OPEN_ORDERS or EXTEND_OPEN_ORDERS:
|
||||||
|
# logging.info('NET FUNDING = 0.00; Cancelling Open Orders! then Waiting...')
|
||||||
|
# aster_cancel_all_orders()
|
||||||
|
# extend_cancel_all_orders()
|
||||||
|
# time.sleep(5)
|
||||||
|
# else:
|
||||||
|
# logging.info('NET FUNDING = 0.00; NO OPEN ORDERS; Waiting...')
|
||||||
|
# time.sleep(5)
|
||||||
|
|
||||||
|
|
||||||
if ALPHA_EXCH == 'EXTEND':
|
if ALPHA_EXCH == 'EXTEND':
|
||||||
ASTER_TGT_NOTIONAL = ALPHA_TGT_NOTIONAL*-1
|
ASTER_TGT_NOTIONAL = ALPHA_TGT_NOTIONAL*-1
|
||||||
@@ -425,19 +437,38 @@ async def run_algo():
|
|||||||
if ALPHA_CARRY_SIDE == 'BUY':
|
if ALPHA_CARRY_SIDE == 'BUY':
|
||||||
ASTER_TOB_PX = float(ASTER_TICKER_DICT['best_ask_px'])
|
ASTER_TOB_PX = float(ASTER_TICKER_DICT['best_ask_px'])
|
||||||
EXTEND_TOB_PX = float(EXTENDED_TICKER_DICT['best_bid_px'])
|
EXTEND_TOB_PX = float(EXTENDED_TICKER_DICT['best_bid_px'])
|
||||||
|
Alpha_Nominator = ASTER_TOB_PX
|
||||||
|
Alpha_Denominator = EXTEND_TOB_PX
|
||||||
|
ALPHA_RATIO = ASTER_TOB_PX / EXTEND_TOB_PX
|
||||||
|
Expected_Alpha = ( ( ASTER_TOB_PX - EXTEND_TOB_PX ) / (( ASTER_TOB_PX + EXTEND_TOB_PX ) / 2) )
|
||||||
else:
|
else:
|
||||||
ASTER_TOB_PX = float(ASTER_TICKER_DICT['best_bid_px'])
|
ASTER_TOB_PX = float(ASTER_TICKER_DICT['best_bid_px'])
|
||||||
EXTEND_TOB_PX = float(EXTENDED_TICKER_DICT['best_ask_px'])
|
EXTEND_TOB_PX = float(EXTENDED_TICKER_DICT['best_ask_px'])
|
||||||
|
Alpha_Nominator = EXTEND_TOB_PX
|
||||||
|
Alpha_Denominator = ASTER_TOB_PX
|
||||||
|
ALPHA_RATIO = EXTEND_TOB_PX / ASTER_TOB_PX
|
||||||
|
Expected_Alpha = ( ( EXTEND_TOB_PX - ASTER_TOB_PX ) / (( ASTER_TOB_PX + EXTEND_TOB_PX ) / 2) )
|
||||||
else:
|
else:
|
||||||
ASTER_TGT_NOTIONAL = ALPHA_TGT_NOTIONAL
|
ASTER_TGT_NOTIONAL = ALPHA_TGT_NOTIONAL
|
||||||
EXTEND_TGT_NOTIONAL = ALPHA_TGT_NOTIONAL*-1
|
EXTEND_TGT_NOTIONAL = ALPHA_TGT_NOTIONAL*-1
|
||||||
if ALPHA_CARRY_SIDE == 'BUY':
|
if ALPHA_CARRY_SIDE == 'BUY':
|
||||||
ASTER_TOB_PX = float(ASTER_TICKER_DICT['best_bid_px'])
|
ASTER_TOB_PX = float(ASTER_TICKER_DICT['best_bid_px'])
|
||||||
EXTEND_TOB_PX = float(EXTENDED_TICKER_DICT['best_ask_px'])
|
EXTEND_TOB_PX = float(EXTENDED_TICKER_DICT['best_ask_px'])
|
||||||
|
Alpha_Nominator = EXTEND_TOB_PX
|
||||||
|
Alpha_Denominator = ASTER_TOB_PX
|
||||||
|
ALPHA_RATIO = EXTEND_TOB_PX / ASTER_TOB_PX
|
||||||
|
Expected_Alpha = ( ( EXTEND_TOB_PX - ASTER_TOB_PX ) / (( EXTEND_TOB_PX + ASTER_TOB_PX ) / 2) )
|
||||||
else:
|
else:
|
||||||
ASTER_TOB_PX = float(ASTER_TICKER_DICT['best_ask_px'])
|
ASTER_TOB_PX = float(ASTER_TICKER_DICT['best_ask_px'])
|
||||||
EXTEND_TOB_PX = float(EXTENDED_TICKER_DICT['best_bid_px'])
|
EXTEND_TOB_PX = float(EXTENDED_TICKER_DICT['best_bid_px'])
|
||||||
|
Alpha_Nominator = ASTER_TOB_PX
|
||||||
|
Alpha_Denominator = EXTEND_TOB_PX
|
||||||
|
ALPHA_RATIO = ASTER_TOB_PX / EXTEND_TOB_PX
|
||||||
|
Expected_Alpha = ( ( ASTER_TOB_PX - EXTEND_TOB_PX ) / (( ASTER_TOB_PX + EXTEND_TOB_PX ) / 2) )
|
||||||
|
|
||||||
|
Expected_Alpha_Net_FR = abs(NEXT_NET_FUNDING_RATE) + Expected_Alpha
|
||||||
|
Expected_Alpha_Net_FR_w_Taker = Expected_Alpha_Net_FR-0.0002
|
||||||
|
Expected_Alpha_w_Taker = Expected_Alpha-0.0002
|
||||||
|
|
||||||
ASTER_TGT_TAIL = ASTER_TGT_NOTIONAL - ( float(ASTER_NOTIONAL_POSITION) + float(ASTER_UNREALIZED_PNL) )
|
ASTER_TGT_TAIL = ASTER_TGT_NOTIONAL - ( float(ASTER_NOTIONAL_POSITION) + float(ASTER_UNREALIZED_PNL) )
|
||||||
EXTEND_TGT_TAIL = EXTEND_TGT_NOTIONAL - ( float(EXTEND_NOTIONAL_POSITION) + float(EXTEND_UNREALIZED_PNL) )
|
EXTEND_TGT_TAIL = EXTEND_TGT_NOTIONAL - ( float(EXTEND_NOTIONAL_POSITION) + float(EXTEND_UNREALIZED_PNL) )
|
||||||
@@ -455,22 +486,26 @@ async def run_algo():
|
|||||||
|
|
||||||
OUT(f'''
|
OUT(f'''
|
||||||
LOOP SLEEP (SEC): {ALGO_CONFIG.Loop_Sleep_Sec}
|
LOOP SLEEP (SEC): {ALGO_CONFIG.Loop_Sleep_Sec}
|
||||||
FLIP SIDES FOR TESTING?: {ALGO_CONFIG.Flip_Side_For_Testing}
|
FLIP SIDES FOR TESTING?: {ALGO_CONFIG.Flip_Side_For_Testing}; ASTER ORDER ENABLED? {ALGO_CONFIG.Allow_Ordering_Aster}; EXTEND ORDER ENABLED? {ALGO_CONFIG.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()):})
|
{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: {'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: [ 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} ]
|
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} ]
|
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}
|
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.Min_Fund_Rate_Pct_To_Trade}]
|
||||||
ALPHA SIDE : {ALPHA_EXCH} [{ALPHA_CARRY_SIDE}]
|
ALPHA SIDE : {ALPHA_EXCH} [{ALPHA_CARRY_SIDE}]
|
||||||
|
|
||||||
TGT NOTIONAL: $ {ALGO_CONFIG.Max_Target_Notional if not Flags.NET_FUNDING_IS_ZERO else 0.00}
|
TGT NOTIONAL: $ {ALGO_CONFIG.Max_Target_Notional if not Flags.NET_FUNDING_IS_ZERO else 0.00}; Flatten Open Positions Flag? {ALGO_CONFIG.Flatten_Open_Positions}
|
||||||
|
|
||||||
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_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_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_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} ]
|
||||||
|
|
||||||
|
ALPHA: {ALPHA_RATIO:.8f} ALPHA_RATIO: {Alpha_Nominator:_.2f} / {Alpha_Denominator:_.2f}; Expected_Alpha = {Expected_Alpha:.6f} + FR[{NEXT_NET_FUNDING_RATE:.6f}] = * {Expected_Alpha_Net_FR:.6f} *
|
||||||
|
FEES : TAKER: {0.02:.2%}; Expected Alpha w Taker = {Expected_Alpha_Net_FR-0.0002:.6f} [w/o FR: {Expected_Alpha_w_Taker:.6f}]
|
||||||
|
|
||||||
|
|
||||||
--- ASTER OPEN ORDERS ---
|
--- ASTER OPEN ORDERS ---
|
||||||
{ASTER_OPEN_ORDERS}
|
{ASTER_OPEN_ORDERS}
|
||||||
@@ -478,6 +513,7 @@ async def run_algo():
|
|||||||
--- EXTEND OPEN ORDERS ---
|
--- EXTEND OPEN ORDERS ---
|
||||||
{EXTEND_OPEN_ORDERS}
|
{EXTEND_OPEN_ORDERS}
|
||||||
''')
|
''')
|
||||||
|
# Try Making Hedge Order Contingent on Alpha Order Fills (Basically Hedge has to wait for sig Diff in Balance to order.) would improve when extended is thin (Overnight).
|
||||||
if ALGO_CONFIG.Log_Summary_Each_Loop:
|
if ALGO_CONFIG.Log_Summary_Each_Loop:
|
||||||
print_summary(use_logging=True)
|
print_summary(use_logging=True)
|
||||||
if ALGO_CONFIG.Print_Summary_Each_Loop:
|
if ALGO_CONFIG.Print_Summary_Each_Loop:
|
||||||
@@ -485,150 +521,160 @@ async def run_algo():
|
|||||||
# print_summary()
|
# print_summary()
|
||||||
|
|
||||||
### ROUTES ###
|
### ROUTES ###
|
||||||
# ASTER
|
# ALPHA RATIO CHECK
|
||||||
if ASTER_TGT_TAIL_ORDERABLE and ALGO_CONFIG.Allow_Ordering_Aster:
|
if not( ( Expected_Alpha_w_Taker > 0 ) or ( ASTER_OPEN_ORDERS or EXTEND_OPEN_ORDERS ) ):
|
||||||
symbol = ASTER.symbol
|
# logging.info(f'Alpha Ratio too low ({ALPHA_RATIO:.8f}) and no Open Orders...')
|
||||||
side = 'BUY' if ASTER_TGT_TAIL_BASE_QTY > 0.00 else 'SELL'
|
pass
|
||||||
qty = str(abs(ASTER_TGT_TAIL_BASE_QTY))
|
else:
|
||||||
price = ASTER_TOB_PX - ALGO_CONFIG.Price_Worsener_Aster if side == 'BUY' else ASTER_TOB_PX + ALGO_CONFIG.Price_Worsener_Aster
|
# logging.info(f'*** Alpha Ratio HIT - LETS ORDER: {ALPHA_RATIO:.8f}')
|
||||||
|
# ASTER
|
||||||
|
if ASTER_TGT_TAIL_ORDERABLE and ALGO_CONFIG.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.Price_Worsener_Aster if side == 'BUY' else ASTER_TOB_PX + ALGO_CONFIG.Price_Worsener_Aster
|
||||||
|
|
||||||
if abs( ( float(ASTER_TGT_TAIL_BASE_QTY)*float(price) ) + ASTER_NOTIONAL_POSITION ) > ALGO_CONFIG.Max_Target_Notional*1.01:
|
if abs( ( float(ASTER_TGT_TAIL_BASE_QTY)*float(price) ) + ASTER_NOTIONAL_POSITION ) > ALGO_CONFIG.Max_Target_Notional*1.01:
|
||||||
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})')
|
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 kill_algo()
|
await kill_algo()
|
||||||
if ASTER_OPEN_ORDERS:
|
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_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'])
|
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:
|
if round(open_order_px - float(price), 2) == 0.00:
|
||||||
logging.info('ASTER OPEN ORDER NO PX CHG; SKIPPING')
|
logging.info('ASTER OPEN ORDER NO PX CHG; SKIPPING')
|
||||||
place_order = False
|
place_order = False
|
||||||
|
else:
|
||||||
|
cancel_order = {
|
||||||
|
"url": "/fapi/v3/order",
|
||||||
|
"method": "DELETE",
|
||||||
|
"params": {
|
||||||
|
'symbol': ASTER.symbol,
|
||||||
|
'orderId': open_order_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cr = await aster_auth.post_authenticated_url(cancel_order)
|
||||||
|
if cr.get('status', None) == 'CANCELED':
|
||||||
|
ASTER_OPEN_ORDERS.pop(0)
|
||||||
|
place_order = True
|
||||||
|
else:
|
||||||
|
logging.warning(f'ASTER ORDER FAILED TO CANCEL DURING CR ({open_order_id}): RESP {cr}')
|
||||||
|
place_order = False
|
||||||
else:
|
else:
|
||||||
cancel_order = {
|
place_order = True
|
||||||
|
|
||||||
|
if ASTER_TGT_TAIL_BASE_QTY == 0.00:
|
||||||
|
place_order = False
|
||||||
|
logging.info('ASTER TRYNG TO ORDER 0.00 BASE QTY, SKIPPING')
|
||||||
|
|
||||||
|
if place_order:
|
||||||
|
price = Decimal(str(price)).quantize(Decimal(str(0.01)), rounding=ROUND_DOWN)
|
||||||
|
post_order = {
|
||||||
"url": "/fapi/v3/order",
|
"url": "/fapi/v3/order",
|
||||||
"method": "DELETE",
|
"method": "POST",
|
||||||
"params": {
|
"params": {
|
||||||
'symbol': ASTER.symbol,
|
'symbol': symbol,
|
||||||
'orderId': open_order_id,
|
'side': side,
|
||||||
|
'type': 'LIMIT',
|
||||||
|
'timeInForce': 'GTC',
|
||||||
|
'quantity': qty,
|
||||||
|
'price': price,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cr = await aster_auth.post_authenticated_url(cancel_order)
|
order_resp = await aster_auth.post_authenticated_url(post_order)
|
||||||
if cr.get('status', None) == 'CANCELED':
|
if order_resp.get('orderId', None) is not None:
|
||||||
ASTER_OPEN_ORDERS.pop(0)
|
order_resp['original_price'] = price
|
||||||
|
order_resp['order_status'] = order_resp['status']
|
||||||
|
ASTER_OPEN_ORDERS.append(order_resp)
|
||||||
|
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:
|
||||||
|
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')
|
||||||
|
await aster_cancel_all_orders()
|
||||||
|
|
||||||
|
# EXTEND
|
||||||
|
if EXTEND_TGT_TAIL_ORDERABLE and ALGO_CONFIG.Allow_Ordering_Extend:
|
||||||
|
symbol = EXTEND_TICKER
|
||||||
|
side = OrderSide.BUY if EXTEND_TGT_TAIL_BASE_QTY > 0.00 else OrderSide.SELL
|
||||||
|
qty = Decimal(str(abs(EXTEND_TGT_TAIL_BASE_QTY)))
|
||||||
|
price = EXTEND_TOB_PX - ALGO_CONFIG.Price_Worsener_Extend if side == 'BUY' else EXTEND_TOB_PX + ALGO_CONFIG.Price_Worsener_Extend
|
||||||
|
|
||||||
|
if abs( ( float(EXTEND_TGT_TAIL_BASE_QTY)*float(price) ) + EXTEND_NOTIONAL_POSITION ) > ALGO_CONFIG.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})')
|
||||||
|
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_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:
|
||||||
place_order = True
|
place_order = True
|
||||||
else:
|
else:
|
||||||
logging.warning(f'ASTER ORDER FAILED TO CANCEL DURING CR ({open_order_id}): RESP {cr}')
|
|
||||||
place_order = False
|
place_order = False
|
||||||
else:
|
logging.info(f'EXTEND NOT ORDERING DUE TO FILLED QTY RESIDUAL < MIN ORDER; Filled: {float(open_order_filled_qty):.4f}; Residual: {qty:.4f}')
|
||||||
place_order = True
|
else:
|
||||||
|
open_order_id = None
|
||||||
if ASTER_TGT_TAIL_BASE_QTY == 0.00:
|
open_order_px = 0
|
||||||
place_order = False
|
|
||||||
logging.info('ASTER TRYNG TO ORDER 0.00 BASE QTY, SKIPPING')
|
|
||||||
|
|
||||||
if place_order:
|
|
||||||
price = Decimal(str(price)).quantize(Decimal(str(0.01)), rounding=ROUND_DOWN)
|
|
||||||
post_order = {
|
|
||||||
"url": "/fapi/v3/order",
|
|
||||||
"method": "POST",
|
|
||||||
"params": {
|
|
||||||
'symbol': symbol,
|
|
||||||
'side': side,
|
|
||||||
'type': 'LIMIT',
|
|
||||||
'timeInForce': 'GTC',
|
|
||||||
'quantity': qty,
|
|
||||||
'price': price,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
order_resp = await aster_auth.post_authenticated_url(post_order)
|
|
||||||
if order_resp.get('orderId', None) is not None:
|
|
||||||
order_resp['original_price'] = price
|
|
||||||
order_resp['order_status'] = order_resp['status']
|
|
||||||
ASTER_OPEN_ORDERS.append(order_resp)
|
|
||||||
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}')
|
|
||||||
print_summary(use_logging=True)
|
|
||||||
else:
|
|
||||||
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')
|
|
||||||
await aster_cancel_all_orders()
|
|
||||||
|
|
||||||
# EXTEND
|
|
||||||
if EXTEND_TGT_TAIL_ORDERABLE and ALGO_CONFIG.Allow_Ordering_Extend:
|
|
||||||
symbol = EXTEND_TICKER
|
|
||||||
side = OrderSide.BUY if EXTEND_TGT_TAIL_BASE_QTY > 0.00 else OrderSide.SELL
|
|
||||||
qty = Decimal(str(abs(EXTEND_TGT_TAIL_BASE_QTY)))
|
|
||||||
price = EXTEND_TOB_PX - ALGO_CONFIG.Price_Worsener_Extend if side == 'BUY' else EXTEND_TOB_PX + ALGO_CONFIG.Price_Worsener_Extend
|
|
||||||
|
|
||||||
if abs( ( float(EXTEND_TGT_TAIL_BASE_QTY)*float(price) ) + EXTEND_NOTIONAL_POSITION ) > ALGO_CONFIG.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})')
|
|
||||||
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_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:
|
|
||||||
place_order = True
|
place_order = True
|
||||||
else:
|
if place_order:
|
||||||
place_order = False
|
price = Decimal(str(price)).quantize(Decimal(str(0.01)), rounding=ROUND_DOWN)
|
||||||
logging.info(f'EXTEND NOT ORDERING DUE TO FILLED QTY RESIDUAL < MIN ORDER; Filled: {float(open_order_filled_qty):.4f}; Residual: {qty:.4f}')
|
if round(open_order_px - float(price), 2) == 0.00:
|
||||||
else:
|
logging.info('EXTEND OPEN ORDER NO PX CHG; SKIPPING')
|
||||||
open_order_id = None
|
|
||||||
open_order_px = 0
|
|
||||||
place_order = True
|
|
||||||
if place_order:
|
|
||||||
price = Decimal(str(price)).quantize(Decimal(str(0.01)), rounding=ROUND_DOWN)
|
|
||||||
if round(open_order_px - float(price), 2) == 0.00:
|
|
||||||
logging.info('EXTEND OPEN ORDER NO PX CHG; SKIPPING')
|
|
||||||
else:
|
|
||||||
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)
|
|
||||||
|
|
||||||
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:
|
else:
|
||||||
order_resp_dict.get
|
try:
|
||||||
else:
|
order_resp = await EXTEND_CLIENT.place_order(
|
||||||
logging.warning('EXTEND PLACE ORDER CHECKS FAILED, SKIPPING')
|
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())
|
||||||
|
|
||||||
elif not(EXTEND_TGT_TAIL_ORDERABLE) and EXTEND_OPEN_ORDERS:
|
order_resp_dict = dict(order_resp)
|
||||||
logging.info('EXTEND HAS NO TAIL BUT OPEN ORDERS - CANCELLING OPEN ORDERS')
|
|
||||||
await extend_cancel_all_orders()
|
|
||||||
|
|
||||||
# print(f'__________ End ___________ (Algo Engine ms: {(time.time() - loop_start)*1000}); Sleeping for sec: {ALGO_CONFIG.Loop_Sleep_Sec}')
|
if order_resp_dict.get('status', None) == 'OK':
|
||||||
|
if EXTEND_OPEN_ORDERS:
|
||||||
|
EXTEND_OPEN_ORDERS.pop(0)
|
||||||
|
|
||||||
time.sleep(ALGO_CONFIG.Loop_Sleep_Sec)
|
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)
|
||||||
|
order_dict['side'] = str(side)
|
||||||
|
|
||||||
|
EXTEND_OPEN_ORDERS.append(order_dict)
|
||||||
|
utils.send_tg_alert(f'FR_ALGO - EXTEND Order ({order_dict.get('id', None)}). 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')
|
||||||
|
|
||||||
|
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:
|
||||||
|
time.sleep(ALGO_CONFIG.Loop_Sleep_Sec)
|
||||||
|
# logging.info(f'_____ End No Open Orders _____ (Algo Engine ms: {(time.time() - loop_start)*1000:.2f}); Sleeping for sec: {ALGO_CONFIG.Loop_Sleep_Sec:.0f}')
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
logging.info('CANCELLING OPEN ORDERS')
|
logging.info('CANCELLING OPEN ORDERS')
|
||||||
|
|||||||
@@ -13,12 +13,14 @@ class Algo_Config:
|
|||||||
Loop_Sleep_Sec: int
|
Loop_Sleep_Sec: int
|
||||||
Max_Target_Notional: float
|
Max_Target_Notional: float
|
||||||
Min_Time_To_Funding_Minutes: int
|
Min_Time_To_Funding_Minutes: int
|
||||||
|
Min_Fund_Rate_Pct_To_Trade: float
|
||||||
Price_Worsener_Aster: float
|
Price_Worsener_Aster: float
|
||||||
Price_Worsener_Extend: float
|
Price_Worsener_Extend: float
|
||||||
Target_Open_Cash_Position: int
|
Target_Open_Cash_Position: int
|
||||||
|
|
||||||
Log_Summary_Each_Loop: bool = False
|
Log_Summary_Each_Loop: bool = False
|
||||||
Print_Summary_Each_Loop: bool = False
|
Print_Summary_Each_Loop: bool = False
|
||||||
|
Flatten_Open_Positions: bool = False
|
||||||
Flip_Side_For_Testing: bool = False
|
Flip_Side_For_Testing: bool = False
|
||||||
|
|
||||||
@dataclass(kw_only=True)
|
@dataclass(kw_only=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user