start of legs
This commit is contained in:
356
main.py
356
main.py
@@ -19,7 +19,8 @@ from py_clob_client.clob_types import (
|
|||||||
OrderType,
|
OrderType,
|
||||||
PartialCreateOrderOptions,
|
PartialCreateOrderOptions,
|
||||||
PostOrdersArgs,
|
PostOrdersArgs,
|
||||||
BalanceAllowanceParams
|
BalanceAllowanceParams,
|
||||||
|
OpenOrderParams
|
||||||
)
|
)
|
||||||
from py_clob_client.order_builder.constants import BUY, SELL
|
from py_clob_client.order_builder.constants import BUY, SELL
|
||||||
from sqlalchemy import text
|
from sqlalchemy import text
|
||||||
@@ -31,6 +32,7 @@ import modules.api as api
|
|||||||
@dataclass
|
@dataclass
|
||||||
class Custom_OrderArgs(OrderArgs):
|
class Custom_OrderArgs(OrderArgs):
|
||||||
max_price: float = 0.00
|
max_price: float = 0.00
|
||||||
|
post_only: bool = False
|
||||||
|
|
||||||
|
|
||||||
### Database ###
|
### Database ###
|
||||||
@@ -45,10 +47,10 @@ LOG_FILEPATH: str = os.getenv("LOGS_PATH") + '/Polymarket_5min_Algo.log'
|
|||||||
### ALGO CONFIG / CONSTANTS ###
|
### ALGO CONFIG / CONSTANTS ###
|
||||||
SLOPE_YES_THRESH = 0.01 # In Percent % Chg (e.g. 0.02 == 0.02%)
|
SLOPE_YES_THRESH = 0.01 # In Percent % Chg (e.g. 0.02 == 0.02%)
|
||||||
ENDTIME_BUFFER_SEC = 30 # Stop trading, cancel all open orders and exit positions this many seconds before mkt settles.
|
ENDTIME_BUFFER_SEC = 30 # Stop trading, cancel all open orders and exit positions this many seconds before mkt settles.
|
||||||
TGT_PX_INDEX_DIFF_THRESH = 0.1 # In Percent % Chg (e.g. 0.02 == 0.02%)
|
TGT_PX_INDEX_DIFF_THRESH = 0.05 # In Percent % Chg (e.g. 0.02 == 0.02%)
|
||||||
DEFAULT_ORDER_SIZE = 10 # In USDe
|
DEFAULT_ORDER_SIZE = 10 # In USDe
|
||||||
MIN_ORDER_SIZE = 5 # In USDe
|
MIN_ORDER_SIZE = 5 # In USDe
|
||||||
TGT_PROFIT_CENTS = 0.02
|
TGT_PROFIT_CENTS = 0.04
|
||||||
CHASE_TO_BUY_CENTS = 0.05
|
CHASE_TO_BUY_CENTS = 0.05
|
||||||
MAX_ALLOWED_POLY_PX = 0.90
|
MAX_ALLOWED_POLY_PX = 0.90
|
||||||
|
|
||||||
@@ -226,9 +228,9 @@ async def slope_decision() -> list[bool, str]:
|
|||||||
# print(f'Len Hist : {len(hist_trades[:, 1])}')
|
# print(f'Len Hist : {len(hist_trades[:, 1])}')
|
||||||
# print(f'First Hist : {pd.to_datetime(np.min(hist_trades[:, 0]), unit='ms')}')
|
# print(f'First Hist : {pd.to_datetime(np.min(hist_trades[:, 0]), unit='ms')}')
|
||||||
# print(f'Latest Hist: {pd.to_datetime(np.max(hist_trades[:, 0]), unit='ms')}')
|
# print(f'Latest Hist: {pd.to_datetime(np.max(hist_trades[:, 0]), unit='ms')}')
|
||||||
print(f'Slope Hist Avg: {np.mean(SLOPE_HIST):.4%}')
|
# print(f'Slope Hist Avg: {np.mean(SLOPE_HIST):.4%}')
|
||||||
print(f'Slope Hist Max: {np.max(SLOPE_HIST):.4%}')
|
# print(f'Slope Hist Max: {np.max(SLOPE_HIST):.4%}')
|
||||||
print(f'Slope Hist Std: {np.std(SLOPE_HIST):.4%}')
|
# print(f'Slope Hist Std: {np.std(SLOPE_HIST):.4%}')
|
||||||
slope_1_buy = abs(slope) >= ( SLOPE_YES_THRESH / 100)
|
slope_1_buy = abs(slope) >= ( SLOPE_YES_THRESH / 100)
|
||||||
slope_5_buy = abs(slope_5) >= ( SLOPE_YES_THRESH / 100)
|
slope_5_buy = abs(slope_5) >= ( SLOPE_YES_THRESH / 100)
|
||||||
|
|
||||||
@@ -263,12 +265,25 @@ async def cancel_single_order_by_id(CLIENT, order_id):
|
|||||||
if o.get('orderID') == order_id:
|
if o.get('orderID') == order_id:
|
||||||
if bool(cxl_resp.get('not_canceled', True)):
|
if bool(cxl_resp.get('not_canceled', True)):
|
||||||
if cxl_resp.get('not_canceled', {}).get(order_id, None) == "matched orders can't be canceled":
|
if cxl_resp.get('not_canceled', {}).get(order_id, None) == "matched orders can't be canceled":
|
||||||
|
LOCAL_ACTIVE_ORDERS[idx]['status'] = 'MATCHED'
|
||||||
logging.info(f'Cancel request failed b/c already matched: {cxl_resp}')
|
logging.info(f'Cancel request failed b/c already matched: {cxl_resp}')
|
||||||
return False
|
return True
|
||||||
elif cxl_resp.get('not_canceled', {}).get(order_id, None) == "order can't be found - already canceled or matched":
|
elif cxl_resp.get('not_canceled', {}).get(order_id, None) == "order can't be found - already canceled or matched":
|
||||||
logging.info(f'Cancel request failed b/c already matched or cancelled: {cxl_resp}')
|
logging.info(f'Cancel request failed b/c already matched or cancelled: {cxl_resp}')
|
||||||
LOCAL_ACTIVE_ORDERS.pop(idx)
|
# GET ORDER STATUS
|
||||||
return False
|
order_status = CLIENT.get_orders(
|
||||||
|
OpenOrderParams(id=o['orderID'])
|
||||||
|
)[0]['status'].upper()
|
||||||
|
logging.info(f'Fetched status from CLOB: {order_status} for order: {o['orderID']}')
|
||||||
|
if order_status == 'MATCHED':
|
||||||
|
logging.info('Order is MATCHED')
|
||||||
|
return True
|
||||||
|
elif order_status == 'CANCELED':
|
||||||
|
logging.info('Order is CANCELED')
|
||||||
|
LOCAL_ACTIVE_ORDERS.pop(idx)
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
raise ValueError(f'ORDER CXL FAILED AND ORDER STILL SHOWS AS LIVE: {cxl_resp}; STATUS: {order_status}; ID: {o.get('orderID')}')
|
||||||
else:
|
else:
|
||||||
logging.warning(f'*** Cancel Request FAILED, shutting down: {cxl_resp}')
|
logging.warning(f'*** Cancel Request FAILED, shutting down: {cxl_resp}')
|
||||||
raise Exception('*** Cancel Request FAILED - SHUTDONW')
|
raise Exception('*** Cancel Request FAILED - SHUTDONW')
|
||||||
@@ -282,8 +297,12 @@ async def flatten_open_positions(CLIENT, token_id_up, token_id_down):
|
|||||||
up = await get_balance_by_token_id(CLIENT=CLIENT, token_id=token_id_up)
|
up = await get_balance_by_token_id(CLIENT=CLIENT, token_id=token_id_up)
|
||||||
down = await get_balance_by_token_id(CLIENT=CLIENT, token_id=token_id_down)
|
down = await get_balance_by_token_id(CLIENT=CLIENT, token_id=token_id_down)
|
||||||
|
|
||||||
|
logging.info('*********FLATTENING*********')
|
||||||
|
logging.info(f'UP BALANCE = {up}')
|
||||||
|
logging.info(f'DOWN BALANCE = {down}')
|
||||||
|
|
||||||
### Submit orders to flatten outstanding balances ###
|
### Submit orders to flatten outstanding balances ###
|
||||||
if up > MIN_ORDER_SIZE:
|
if abs(up) > MIN_ORDER_SIZE:
|
||||||
logging.info(f'Flattening Up Position: {up}')
|
logging.info(f'Flattening Up Position: {up}')
|
||||||
await post_order(
|
await post_order(
|
||||||
CLIENT = CLIENT,
|
CLIENT = CLIENT,
|
||||||
@@ -291,12 +310,12 @@ async def flatten_open_positions(CLIENT, token_id_up, token_id_down):
|
|||||||
neg_risk = POLY_CLOB['neg_risk'],
|
neg_risk = POLY_CLOB['neg_risk'],
|
||||||
OrderArgs_list = [Custom_OrderArgs(
|
OrderArgs_list = [Custom_OrderArgs(
|
||||||
token_id=token_id_up,
|
token_id=token_id_up,
|
||||||
price=float(POLY_CLOB['price'])-0.01,
|
price=float(POLY_CLOB['price'])-0.05,
|
||||||
size=up,
|
size=up,
|
||||||
side=SELL,
|
side=SELL,
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
if down > MIN_ORDER_SIZE:
|
if abs(down) > MIN_ORDER_SIZE:
|
||||||
logging.info(f'Flattening Down Position: {down}')
|
logging.info(f'Flattening Down Position: {down}')
|
||||||
await post_order(
|
await post_order(
|
||||||
CLIENT = CLIENT,
|
CLIENT = CLIENT,
|
||||||
@@ -304,7 +323,7 @@ async def flatten_open_positions(CLIENT, token_id_up, token_id_down):
|
|||||||
neg_risk = POLY_CLOB['neg_risk'],
|
neg_risk = POLY_CLOB['neg_risk'],
|
||||||
OrderArgs_list = [Custom_OrderArgs(
|
OrderArgs_list = [Custom_OrderArgs(
|
||||||
token_id=token_id_down,
|
token_id=token_id_down,
|
||||||
price=float(POLY_CLOB_DOWN['price'])-0.01,
|
price=float(POLY_CLOB_DOWN['price'])-0.05,
|
||||||
size=down,
|
size=down,
|
||||||
side=SELL,
|
side=SELL,
|
||||||
|
|
||||||
@@ -354,7 +373,7 @@ async def check_for_open_positions(CLIENT, token_id_up, token_id_down):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
@async_timeit
|
@async_timeit
|
||||||
async def post_order(CLIENT, OrderArgs_list: list[Custom_OrderArgs], tick_size: float | str, neg_risk: bool):
|
async def post_order(CLIENT, OrderArgs_list: list[Custom_OrderArgs], tick_size: float | str, neg_risk: bool) -> list[dict]: # Returns order response dict
|
||||||
global LOCAL_ACTIVE_ORDERS
|
global LOCAL_ACTIVE_ORDERS
|
||||||
global LOCAL_TOKEN_BALANCES
|
global LOCAL_TOKEN_BALANCES
|
||||||
|
|
||||||
@@ -370,7 +389,7 @@ async def post_order(CLIENT, OrderArgs_list: list[Custom_OrderArgs], tick_size:
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
orderType=OrderType.GTC,
|
orderType=OrderType.GTC,
|
||||||
postOnly=False,
|
postOnly=oa.post_only,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -379,7 +398,15 @@ async def post_order(CLIENT, OrderArgs_list: list[Custom_OrderArgs], tick_size:
|
|||||||
for idx, d in enumerate(response):
|
for idx, d in enumerate(response):
|
||||||
if d['errorMsg'] == '':
|
if d['errorMsg'] == '':
|
||||||
d['token_id'] = OrderArgs_list[idx].token_id
|
d['token_id'] = OrderArgs_list[idx].token_id
|
||||||
|
if d['token_id'] == POLY_CLOB['token_id_up']:
|
||||||
|
d['outcome'] = "UP"
|
||||||
|
elif d['token_id'] == POLY_CLOB['token_id_down']:
|
||||||
|
d['outcome'] = "DOWN"
|
||||||
|
else:
|
||||||
|
d['outcome'] = "UNKNOWN"
|
||||||
|
|
||||||
d['price'] = OrderArgs_list[idx].price
|
d['price'] = OrderArgs_list[idx].price
|
||||||
|
d['max_price'] = OrderArgs_list[idx].max_price
|
||||||
d['size'] = OrderArgs_list[idx].size
|
d['size'] = OrderArgs_list[idx].size
|
||||||
d['side'] = str(OrderArgs_list[idx].side).upper()
|
d['side'] = str(OrderArgs_list[idx].side).upper()
|
||||||
|
|
||||||
@@ -387,8 +414,7 @@ async def post_order(CLIENT, OrderArgs_list: list[Custom_OrderArgs], tick_size:
|
|||||||
### Order Immediately Matched, Can Put in Offsetting Order Depending on State ###
|
### Order Immediately Matched, Can Put in Offsetting Order Depending on State ###
|
||||||
print('******** ORDER APPEND TO LOCAL - MATCHED ********* ')
|
print('******** ORDER APPEND TO LOCAL - MATCHED ********* ')
|
||||||
LOCAL_ACTIVE_ORDERS.append(d)
|
LOCAL_ACTIVE_ORDERS.append(d)
|
||||||
|
elif d['status'].upper() == 'CONFIRMED':
|
||||||
if d['status'].upper() == 'CONFIRMED':
|
|
||||||
current_balance = float(LOCAL_TOKEN_BALANCES.get(d['token_id'], 0.00))
|
current_balance = float(LOCAL_TOKEN_BALANCES.get(d['token_id'], 0.00))
|
||||||
if d['side'] == 'BUY':
|
if d['side'] == 'BUY':
|
||||||
size = float(d['size'])
|
size = float(d['size'])
|
||||||
@@ -400,15 +426,17 @@ async def post_order(CLIENT, OrderArgs_list: list[Custom_OrderArgs], tick_size:
|
|||||||
else:
|
else:
|
||||||
print('******** ORDER APPEND TO LOCAL - LIVE ********* ')
|
print('******** ORDER APPEND TO LOCAL - LIVE ********* ')
|
||||||
LOCAL_ACTIVE_ORDERS.append(d)
|
LOCAL_ACTIVE_ORDERS.append(d)
|
||||||
|
elif d['errorMsg'] == "invalid post-only order: order crosses book":
|
||||||
|
logging.info(f'invalid post-only order: order crosses book. posted: {OrderArgs_list[idx].price}')
|
||||||
else:
|
else:
|
||||||
raise ValueError(f'Order entry failed: {d}')
|
raise ValueError(f'Order entry failed: {d}')
|
||||||
|
|
||||||
logging.info(f'Order Posted Resp: {response}')
|
logging.info(f'Order Posted Resp: {response}')
|
||||||
print(f'Order Posted Resp: {response}')
|
print(f'Order Posted Resp: {response}')
|
||||||
|
return response
|
||||||
|
|
||||||
### Routes ###
|
### Routes ###
|
||||||
async def no_orders_no_positions_route():
|
async def no_orders(entry_or_exit: str = 'ENTRY'):
|
||||||
global ORDER_LOCK
|
global ORDER_LOCK
|
||||||
|
|
||||||
### Check for Price Bands ###
|
### Check for Price Bands ###
|
||||||
@@ -427,122 +455,217 @@ async def no_orders_no_positions_route():
|
|||||||
logging.info(f'Tgt Diff to Index Outside Limit ({TGT_PX_INDEX_DIFF_THRESH}%); Diff {tgt_px_diff_to_index:.4%}; Index: {ref_px:.2f}; Tgt: {tgt_px:.2f}')
|
logging.info(f'Tgt Diff to Index Outside Limit ({TGT_PX_INDEX_DIFF_THRESH}%); Diff {tgt_px_diff_to_index:.4%}; Index: {ref_px:.2f}; Tgt: {tgt_px:.2f}')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
### Check Slope ###
|
### Check Slope ###
|
||||||
slope_bool, slope_side = await slope_decision()
|
slope_bool, slope_side = await slope_decision()
|
||||||
if not slope_bool:
|
if not slope_bool:
|
||||||
logging.info('Failed Slope Check')
|
logging.info('Failed Slope Check')
|
||||||
return False
|
return False
|
||||||
token_id = POLY_CLOB.get('token_id_up', None) if slope_side=='UP' else POLY_CLOB.get('token_id_down', None)
|
|
||||||
|
token_id_up = POLY_CLOB.get('token_id_up', None)
|
||||||
|
token_id_down = POLY_CLOB.get('token_id_down', None)
|
||||||
|
|
||||||
### Order Entry ###
|
### Order Entry ###
|
||||||
px = float(POLY_CLOB['price'])+0.01
|
if slope_side == 'UP':
|
||||||
order = Custom_OrderArgs(
|
if entry_or_exit == 'ENTRY':
|
||||||
token_id=token_id,
|
side = BUY
|
||||||
price=px,
|
size = DEFAULT_ORDER_SIZE
|
||||||
size=DEFAULT_ORDER_SIZE,
|
up_px = up_px + 0.01
|
||||||
side=BUY,
|
down_px = down_px - TGT_PROFIT_CENTS
|
||||||
max_price = px + CHASE_TO_BUY_CENTS
|
up_post_only = False
|
||||||
|
down_post_only = False # T
|
||||||
|
else: # entry_or_exit == 'EXIT'
|
||||||
|
side = SELL
|
||||||
|
size = await get_balance_by_token_id(CLIENT=CLIENT, token_id=token_id_up)
|
||||||
|
up_px = up_px + TGT_PROFIT_CENTS
|
||||||
|
down_px = down_px - 0.01
|
||||||
|
up_post_only = False # T
|
||||||
|
down_post_only = False
|
||||||
|
else: # slope_side == 'DOWN'
|
||||||
|
if entry_or_exit == 'ENTRY':
|
||||||
|
side = BUY
|
||||||
|
size = DEFAULT_ORDER_SIZE
|
||||||
|
up_px = up_px - TGT_PROFIT_CENTS
|
||||||
|
down_px = down_px + 0.01
|
||||||
|
up_post_only = False # T
|
||||||
|
down_post_only = False
|
||||||
|
else:
|
||||||
|
side = SELL
|
||||||
|
size = await get_balance_by_token_id(CLIENT=CLIENT, token_id=token_id_up)
|
||||||
|
up_px = up_px - 0.01
|
||||||
|
down_px = down_px + TGT_PROFIT_CENTS
|
||||||
|
up_post_only = False
|
||||||
|
down_post_only = False # T
|
||||||
|
|
||||||
|
buy_up_leg = Custom_OrderArgs(
|
||||||
|
token_id=token_id_up,
|
||||||
|
price=up_px,
|
||||||
|
size=size,
|
||||||
|
side=side,
|
||||||
|
max_price = 0.99,
|
||||||
|
post_only=up_post_only
|
||||||
)
|
)
|
||||||
|
buy_down_leg = Custom_OrderArgs(
|
||||||
|
token_id=token_id_down,
|
||||||
|
price=down_px,
|
||||||
|
size=size,
|
||||||
|
side=side,
|
||||||
|
max_price = 0.99,
|
||||||
|
post_only=down_post_only
|
||||||
|
)
|
||||||
|
order_list = [buy_up_leg, buy_down_leg]
|
||||||
|
|
||||||
### ADD CHECK FOR MKT MOVED AWAY FROM OPPORTNITY ###
|
### ADD CHECK FOR MKT MOVED AWAY FROM OPPORTNITY ###
|
||||||
|
|
||||||
if ORDER_LOCK:
|
if ORDER_LOCK:
|
||||||
logging.info(f'BUY ORDER BLOCKED BY LOCK: {order}')
|
logging.info(f'BUY ORDER BLOCKED BY LOCK: {order_list}')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logging.info(f'Attempting BUY Order {order}')
|
logging.info(f'Attempting BUY Order {order_list}')
|
||||||
await post_order(
|
await post_order(
|
||||||
CLIENT = CLIENT,
|
CLIENT = CLIENT,
|
||||||
tick_size = POLY_CLOB['tick_size'],
|
tick_size = POLY_CLOB['tick_size'],
|
||||||
neg_risk = POLY_CLOB['neg_risk'],
|
neg_risk = POLY_CLOB['neg_risk'],
|
||||||
OrderArgs_list = [order]
|
OrderArgs_list = order_list
|
||||||
)
|
)
|
||||||
# ORDER_LOCK = ORDER_LOCK + 1
|
# ORDER_LOCK = ORDER_LOCK + 1
|
||||||
|
|
||||||
async def active_orders_no_positions_route():
|
async def active_orders_no_positions_route():
|
||||||
|
global LOCAL_ACTIVE_ORDERS
|
||||||
|
|
||||||
if len(LOCAL_ACTIVE_ORDERS) > 2:
|
if len(LOCAL_ACTIVE_ORDERS) > 2:
|
||||||
logging.critical('More than two active orders, shutting down')
|
logging.critical('More than two active orders, shutting down')
|
||||||
await kill_algo()
|
await kill_algo()
|
||||||
b_c = 0
|
b_c = 0
|
||||||
s_c = 0
|
s_c = 0
|
||||||
|
|
||||||
|
active_buy_up = False
|
||||||
|
active_buy_down = False
|
||||||
|
|
||||||
|
active_sell_up = False
|
||||||
|
active_sell_down = False
|
||||||
|
|
||||||
for o in LOCAL_ACTIVE_ORDERS:
|
for o in LOCAL_ACTIVE_ORDERS:
|
||||||
if o['side'] == 'BUY':
|
if o['side'] == 'BUY':
|
||||||
|
if o['token_id']==POLY_CLOB['token_id_up']:
|
||||||
|
active_buy_up = True
|
||||||
|
else:
|
||||||
|
active_buy_down = True
|
||||||
|
|
||||||
b_c = b_c + 1
|
b_c = b_c + 1
|
||||||
elif o['side'] == 'SELL':
|
elif o['side'] == 'SELL':
|
||||||
s_c = s_c + 1
|
if o['token_id']==POLY_CLOB['token_id_up']:
|
||||||
if (b_c > 1) or (s_c > 1):
|
active_sell_up = True
|
||||||
logging.critical(f'More than one active buy or more than one active sell: b_c {b_c}; s_c{s_c}')
|
else:
|
||||||
await kill_algo()
|
active_sell_down = True
|
||||||
|
|
||||||
|
s_c = s_c + 1
|
||||||
|
|
||||||
|
if (b_c > 2) or (s_c > 2):
|
||||||
|
logging.critical(f'More than two active buys or more than two active sells: b_c {b_c}; s_c{s_c}')
|
||||||
|
await kill_algo()
|
||||||
|
|
||||||
for o in LOCAL_ACTIVE_ORDERS:
|
for o in LOCAL_ACTIVE_ORDERS:
|
||||||
logging.info(f'Working on order ({o['side']}): {o['orderID']}')
|
logging.info(f'Working on order ({o['side']}): {o['orderID']}')
|
||||||
|
|
||||||
if o.get('status').upper() == 'MATCHED':
|
if o.get('status').upper() == 'MATCHED':
|
||||||
logging.info('Order is matched, awaiting confirm or kickback')
|
# logging.info('Order is matched, awaiting confirm or kickback')
|
||||||
|
if active_buy_up and active_buy_down:
|
||||||
|
logging.info('BUY UP AND BUY DOWN ACTIVE/MATCHED - WAITING FOR CONFIRMS')
|
||||||
|
continue
|
||||||
|
logging.info('Order is matched, ordering inverse side')
|
||||||
|
order_matched=True
|
||||||
elif o.get('status').upper() == 'FAILED':
|
elif o.get('status').upper() == 'FAILED':
|
||||||
|
order_matched=True
|
||||||
raise ValueError(f'Trade FAILED after matching: {o}')
|
raise ValueError(f'Trade FAILED after matching: {o}')
|
||||||
|
elif o.get('status').upper() == 'RETRYING':
|
||||||
|
order_matched=True
|
||||||
|
raise ValueError(f'Trade RETRYING after matching: {o}')
|
||||||
else:
|
else:
|
||||||
orig_px = float(o['price'])
|
order_matched = False
|
||||||
orig_size = float(o['size'])
|
|
||||||
if o['side'] == 'BUY':
|
orig_px = float(o['price'])
|
||||||
if POLY_CLOB['token_id_up'] == o['token_id']:
|
orig_size = float(o['size'])
|
||||||
clob_px = float(POLY_CLOB['price'])
|
|
||||||
else:
|
### BUY
|
||||||
clob_px = float(POLY_CLOB_DOWN['price'])
|
if o['side'] == 'BUY':
|
||||||
|
if POLY_CLOB['token_id_up'] == o['token_id']:
|
||||||
|
clob_px = float(POLY_CLOB['price'])
|
||||||
|
token_id_inverse = POLY_CLOB['token_id_down']
|
||||||
|
else:
|
||||||
|
clob_px = float(POLY_CLOB_DOWN['price'])
|
||||||
|
token_id_inverse = POLY_CLOB['token_id_up']
|
||||||
|
|
||||||
if clob_px >= orig_px:
|
if (clob_px >= orig_px) or order_matched:
|
||||||
|
if (clob_px >= orig_px):
|
||||||
logging.info(f"Market px: ({clob_px} is above buy order px: {orig_px:.2f})")
|
logging.info(f"Market px: ({clob_px} is above buy order px: {orig_px:.2f})")
|
||||||
if o.get('max_price', 0) > clob_px:
|
|
||||||
|
if (o.get('max_price', 0) > clob_px) or order_matched:
|
||||||
|
if (o.get('max_price', 0) > clob_px):
|
||||||
logging.info(f"Market px: ({clob_px} has moved too far away from original target, cancelling and resetting algo: {o.get('max_price', 0) :.2f})")
|
logging.info(f"Market px: ({clob_px} has moved too far away from original target, cancelling and resetting algo: {o.get('max_price', 0) :.2f})")
|
||||||
|
|
||||||
|
if not order_matched:
|
||||||
order_matched = await cancel_single_order_by_id(CLIENT=CLIENT, order_id=o['orderID'])
|
order_matched = await cancel_single_order_by_id(CLIENT=CLIENT, order_id=o['orderID'])
|
||||||
|
|
||||||
if order_matched:
|
if order_matched:
|
||||||
o['status'] = 'MATCHED'
|
o['status'] = 'MATCHED'
|
||||||
else:
|
if order_matched and (not (active_buy_up and active_buy_down)):
|
||||||
px = orig_px+0.01
|
logging.info('BUY Order Matched Immediately, Ordering Inverse BUY')
|
||||||
|
token_id = token_id_inverse
|
||||||
await post_order(
|
px = 1 - (orig_px+TGT_PROFIT_CENTS)
|
||||||
CLIENT = CLIENT,
|
if clob_px > px:
|
||||||
tick_size = POLY_CLOB['tick_size'],
|
px = clob_px + 0.01
|
||||||
neg_risk = POLY_CLOB['neg_risk'],
|
# max_price = px + CHASE_TO_BUY_CENTS
|
||||||
OrderArgs_list = [Custom_OrderArgs(
|
max_price = px
|
||||||
token_id=o['token_id'],
|
post_only = False
|
||||||
price=px,
|
elif order_matched and (active_buy_up and active_buy_down):
|
||||||
size=orig_size,
|
logging.info('BUY UP AND BUY DOWN MATCHED - WAITING FOR CONFIRMS (IN LOOP)')
|
||||||
side=BUY,
|
continue
|
||||||
max_price=o['max_price']
|
|
||||||
|
|
||||||
)]
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
await cancel_single_order_by_id(CLIENT=CLIENT, order_id=o['orderID'])
|
token_id = o['token_id']
|
||||||
elif o['side'] == 'SELL':
|
px = clob_px+0.01
|
||||||
if POLY_CLOB['token_id_up'] == o['token_id']:
|
max_price = o['max_price']
|
||||||
clob_px = float(POLY_CLOB['price'])
|
post_only = False
|
||||||
|
|
||||||
|
await post_order(
|
||||||
|
CLIENT = CLIENT,
|
||||||
|
tick_size = POLY_CLOB['tick_size'],
|
||||||
|
neg_risk = POLY_CLOB['neg_risk'],
|
||||||
|
OrderArgs_list = [Custom_OrderArgs(
|
||||||
|
token_id=token_id,
|
||||||
|
price=px,
|
||||||
|
size=orig_size,
|
||||||
|
side=BUY,
|
||||||
|
max_price=max_price,
|
||||||
|
post_only=post_only
|
||||||
|
|
||||||
|
)]
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
clob_px = float(POLY_CLOB_DOWN['price'])
|
await cancel_single_order_by_id(CLIENT=CLIENT, order_id=o['orderID'])
|
||||||
|
### SELL
|
||||||
|
elif o['side'] == 'SELL':
|
||||||
|
if POLY_CLOB['token_id_up'] == o['token_id']:
|
||||||
|
clob_px = float(POLY_CLOB['price'])
|
||||||
|
else:
|
||||||
|
clob_px = float(POLY_CLOB_DOWN['price'])
|
||||||
|
|
||||||
|
if clob_px <= orig_px:
|
||||||
|
logging.info(f"Market px: ({clob_px} is below sell order px: {orig_px:.2f})")
|
||||||
|
|
||||||
if clob_px <= orig_px:
|
order_filled = await cancel_single_order_by_id(CLIENT=CLIENT, order_id=o['orderID'])
|
||||||
logging.info(f"Market px: ({clob_px} is below sell order px: {orig_px:.2f})")
|
if not order_filled:
|
||||||
|
await post_order(
|
||||||
order_filled = await cancel_single_order_by_id(CLIENT=CLIENT, order_id=o['orderID'])
|
CLIENT = CLIENT,
|
||||||
if not order_filled:
|
tick_size = POLY_CLOB['tick_size'],
|
||||||
await post_order(
|
neg_risk = POLY_CLOB['neg_risk'],
|
||||||
CLIENT = CLIENT,
|
OrderArgs_list = [Custom_OrderArgs(
|
||||||
tick_size = POLY_CLOB['tick_size'],
|
token_id=o['token_id'],
|
||||||
neg_risk = POLY_CLOB['neg_risk'],
|
price=orig_px-0.01,
|
||||||
OrderArgs_list = [Custom_OrderArgs(
|
size=orig_size,
|
||||||
token_id=o['token_id'],
|
side=SELL,
|
||||||
price=orig_px-0.01,
|
max_price = 0.00
|
||||||
size=orig_size,
|
)]
|
||||||
side=SELL,
|
)
|
||||||
max_price = 0.00
|
|
||||||
)]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def no_orders_active_positions_route():
|
async def no_orders_active_positions_route():
|
||||||
@@ -587,7 +710,7 @@ async def no_orders_active_positions_route():
|
|||||||
async def active_orders_active_positions_route():
|
async def active_orders_active_positions_route():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def kill_algo():
|
async def kill_algo(msg: str = 'No kill msg provided'):
|
||||||
logging.info('Killing algo...')
|
logging.info('Killing algo...')
|
||||||
await cancel_all_orders(CLIENT=CLIENT)
|
await cancel_all_orders(CLIENT=CLIENT)
|
||||||
await flatten_open_positions(
|
await flatten_open_positions(
|
||||||
@@ -595,8 +718,8 @@ async def kill_algo():
|
|||||||
token_id_up = POLY_CLOB.get('token_id_up', None),
|
token_id_up = POLY_CLOB.get('token_id_up', None),
|
||||||
token_id_down = POLY_CLOB.get('token_id_down', None),
|
token_id_down = POLY_CLOB.get('token_id_down', None),
|
||||||
)
|
)
|
||||||
logging.info('...algo killed')
|
logging.info(f'...algo killed: {msg}')
|
||||||
raise Exception('Algo Killed')
|
raise Exception(f'Algo Killed: {msg}')
|
||||||
|
|
||||||
async def run_algo():
|
async def run_algo():
|
||||||
global POLY_BINANCE
|
global POLY_BINANCE
|
||||||
@@ -617,8 +740,13 @@ async def run_algo():
|
|||||||
print(f'token_id_up: {POLY_CLOB.get('token_id_up', None)}')
|
print(f'token_id_up: {POLY_CLOB.get('token_id_up', None)}')
|
||||||
print(f'token_id_down: {POLY_CLOB.get('token_id_down', None)}')
|
print(f'token_id_down: {POLY_CLOB.get('token_id_down', None)}')
|
||||||
|
|
||||||
|
|
||||||
POLY_CLOB = json.loads(VAL_KEY.get('poly_5min_btcusd'))
|
POLY_CLOB = json.loads(VAL_KEY.get('poly_5min_btcusd'))
|
||||||
|
|
||||||
|
### Check for missing target px (Poly 5min Target BTC Px Target) ###
|
||||||
|
if POLY_CLOB.get('target_price', 0) <= 1.00:
|
||||||
|
kill_algo('')
|
||||||
|
|
||||||
ACTIVE_BALANCES_EXIST = await check_for_open_positions(
|
ACTIVE_BALANCES_EXIST = await check_for_open_positions(
|
||||||
CLIENT=CLIENT,
|
CLIENT=CLIENT,
|
||||||
token_id_up=POLY_CLOB.get('token_id_up', None),
|
token_id_up=POLY_CLOB.get('token_id_up', None),
|
||||||
@@ -641,12 +769,13 @@ async def run_algo():
|
|||||||
### DO THIS TO AVOID DELAY WITH FILL CONFIRMS
|
### DO THIS TO AVOID DELAY WITH FILL CONFIRMS
|
||||||
|
|
||||||
### Manage Local vs User Stream Orders ###
|
### Manage Local vs User Stream Orders ###
|
||||||
print(f'LOCAL_ACTIVE_ORDERS: {LOCAL_ACTIVE_ORDERS}')
|
# print(f'LOCAL_ACTIVE_ORDERS: {LOCAL_ACTIVE_ORDERS}')
|
||||||
|
# print(f'USER_TRADES: {USER_TRADES}')
|
||||||
for idx, o in enumerate(LOCAL_ACTIVE_ORDERS):
|
for idx, o in enumerate(LOCAL_ACTIVE_ORDERS):
|
||||||
user_order = next((item for item in USER_ORDERS if item["id"] == o['orderID']), None)
|
user_order = next((item for item in USER_ORDERS if item["id"] == o['orderID']), None)
|
||||||
user_trade = next( ( item for item in USER_TRADES if ( o['orderID'] == item['taker_order_id'] ) or ( o["orderID"] == json.loads(item['maker_orders'])[0]['order_id'] ) ), None )
|
user_trade = next( ( item for item in USER_TRADES if ( o['orderID'] == item['taker_order_id'] ) or ( o["orderID"] == json.loads(item['maker_orders'])[0]['order_id'] ) ), None )
|
||||||
|
|
||||||
print(f'USER TRADE: {user_trade}')
|
print(f'*****USER TRADE: {user_trade}')
|
||||||
|
|
||||||
if user_trade is not None:
|
if user_trade is not None:
|
||||||
trade_status = str(user_trade['status']).upper()
|
trade_status = str(user_trade['status']).upper()
|
||||||
@@ -676,43 +805,24 @@ async def run_algo():
|
|||||||
logging.info('Order FILLED!')
|
logging.info('Order FILLED!')
|
||||||
elif trade_status == 'MATCHED':
|
elif trade_status == 'MATCHED':
|
||||||
logging.info(f'Order Matched...awaiting confirm: {trade_status}')
|
logging.info(f'Order Matched...awaiting confirm: {trade_status}')
|
||||||
|
elif trade_status == 'MINED':
|
||||||
|
logging.info(f'Order Mined ...awaiting confirm: {trade_status}')
|
||||||
else:
|
else:
|
||||||
logging.info(f'Trade status but not filled: trade= {user_trade}; order={o}')
|
logging.info(f'Trade status but not filled: trade= {user_trade}; order={o}')
|
||||||
|
|
||||||
elif user_order is not None:
|
elif user_order is not None:
|
||||||
order_status = str(user_order['status']).upper()
|
order_status = str(user_order['status']).upper()
|
||||||
|
o['status'] = order_status
|
||||||
logging.info(f'Updated Order Status: {o['status']} --> {order_status}; {o['orderID']}')
|
logging.info(f'Updated Order Status: {o['status']} --> {order_status}; {o['orderID']}')
|
||||||
# LOCAL_ACTIVE_ORDERS[idx]['status'] = order_status
|
|
||||||
# if order_status == 'MATCHED':
|
|
||||||
# LOCAL_ACTIVE_ORDERS.pop(idx)
|
|
||||||
|
|
||||||
# token_id = user_order['asset_id']
|
|
||||||
# current_balance = float(LOCAL_TOKEN_BALANCES.get(token_id, 0.00))
|
|
||||||
|
|
||||||
# if user_order['side'] == 'BUY':
|
|
||||||
# size = float(user_order['size_matched'])
|
|
||||||
# else:
|
|
||||||
# size = float(user_order['size_matched']) * -1
|
|
||||||
|
|
||||||
# LOCAL_TOKEN_BALANCES[token_id] = current_balance + size
|
if order_status == 'MATCHED':
|
||||||
|
logging.info('Order MATCHED, awaiting confirm')
|
||||||
|
|
||||||
# # px = user_order['price']
|
elif order_status == 'CANCELED':
|
||||||
# # LOCAL_ACTIVE_POSITIONS.append({
|
|
||||||
# # 'token_id': token_id,
|
|
||||||
# # 'order_id': o['orderID'],
|
|
||||||
# # 'associate_trades': user_order['associate_trades'],
|
|
||||||
# # 'size_matched': user_order['size_matched'],
|
|
||||||
# # 'price': px,
|
|
||||||
# # 'timestamp_value': user_order['timestamp'],
|
|
||||||
# # })
|
|
||||||
# logging.info('Order FILLED!')
|
|
||||||
if order_status == 'CANCELED':
|
|
||||||
LOCAL_ACTIVE_ORDERS.pop(idx)
|
LOCAL_ACTIVE_ORDERS.pop(idx)
|
||||||
logging.info('Order Canceled')
|
logging.info('Order Canceled')
|
||||||
else:
|
else:
|
||||||
logging.info('Order Live or Trade Awaiting Confirm')
|
logging.info('Order Live')
|
||||||
|
|
||||||
### UPDATES CAN COME THRU EITHER ORDER OR TRADE CHANNELS - NEED TO UPDATE TO HANDLE TRADE CHANNLE
|
|
||||||
|
|
||||||
token_id_up = POLY_CLOB.get('token_id_up', 0)
|
token_id_up = POLY_CLOB.get('token_id_up', 0)
|
||||||
token_id_down = POLY_CLOB.get('token_id_down', 0)
|
token_id_down = POLY_CLOB.get('token_id_down', 0)
|
||||||
@@ -749,7 +859,7 @@ async def run_algo():
|
|||||||
### Execution Route ###
|
### Execution Route ###
|
||||||
if not(LOCAL_ACTIVE_ORDERS) and not(ACTIVE_BALANCES_EXIST): # No Orders, No Positions
|
if not(LOCAL_ACTIVE_ORDERS) and not(ACTIVE_BALANCES_EXIST): # No Orders, No Positions
|
||||||
print('ROUTE: no_orders_no_positions_route')
|
print('ROUTE: no_orders_no_positions_route')
|
||||||
await no_orders_no_positions_route()
|
await no_orders(entry_or_exit='ENTRY')
|
||||||
|
|
||||||
### Open Orders Route ###
|
### Open Orders Route ###
|
||||||
elif LOCAL_ACTIVE_ORDERS and not(ACTIVE_BALANCES_EXIST): # Orders, No Positions
|
elif LOCAL_ACTIVE_ORDERS and not(ACTIVE_BALANCES_EXIST): # Orders, No Positions
|
||||||
@@ -758,13 +868,13 @@ async def run_algo():
|
|||||||
|
|
||||||
### Open Positions Route ###
|
### Open Positions Route ###
|
||||||
elif not(LOCAL_ACTIVE_ORDERS) and ACTIVE_BALANCES_EXIST: # No Orders, Positions
|
elif not(LOCAL_ACTIVE_ORDERS) and ACTIVE_BALANCES_EXIST: # No Orders, Positions
|
||||||
print('ROUTE: no_orders_no_positions_route')
|
print('ROUTE: no_orders_route_active_positions_route')
|
||||||
await no_orders_active_positions_route()
|
await no_orders(entry_or_exit='EXIT')
|
||||||
|
|
||||||
### Open Orders and Open Positions Route ###
|
### Open Orders and Open Positions Route ###
|
||||||
else:
|
else:
|
||||||
print('ROUTE: active_orders_active_positions_route')
|
print('ROUTE: active_orders_active_positions_route - OFF')
|
||||||
await active_orders_no_positions_route() # Orders and Positions
|
# await active_orders_no_positions_route() # Orders and Positions
|
||||||
|
|
||||||
print(f'__________________________ (Algo Engine ms: {(time.time() - loop_start)*1000})')
|
print(f'__________________________ (Algo Engine ms: {(time.time() - loop_start)*1000})')
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ async def polymarket_stream():
|
|||||||
event_type = data.get('event_type', None)
|
event_type = data.get('event_type', None)
|
||||||
match event_type:
|
match event_type:
|
||||||
case 'trade':
|
case 'trade':
|
||||||
logging.info(f'TRADE: {data}')
|
# logging.info(f'TRADE: {data}')
|
||||||
# trade_status = data.get('status')
|
# trade_status = data.get('status')
|
||||||
# match trade_status: # Raise TELEGRAM ALERT ???
|
# match trade_status: # Raise TELEGRAM ALERT ???
|
||||||
# case 'MATCHED':
|
# case 'MATCHED':
|
||||||
@@ -326,9 +326,9 @@ async def polymarket_stream():
|
|||||||
LOOKBACK_MIN_TS_MS = ts_arrival-LOCAL_RECENT_TRADES_LOOKBACK_SEC*1000
|
LOOKBACK_MIN_TS_MS = ts_arrival-LOCAL_RECENT_TRADES_LOOKBACK_SEC*1000
|
||||||
LOCAL_RECENT_TRADES = [t for t in LOCAL_RECENT_TRADES if t.get('timestamp_arrival', 0) >= LOOKBACK_MIN_TS_MS]
|
LOCAL_RECENT_TRADES = [t for t in LOCAL_RECENT_TRADES if t.get('timestamp_arrival', 0) >= LOOKBACK_MIN_TS_MS]
|
||||||
|
|
||||||
print("---------------------")
|
# print("---------------------")
|
||||||
print(LOCAL_RECENT_TRADES)
|
# print(LOCAL_RECENT_TRADES)
|
||||||
print("---------------------")
|
# print("---------------------")
|
||||||
|
|
||||||
VAL_KEY_OBJ = json.dumps(LOCAL_RECENT_TRADES)
|
VAL_KEY_OBJ = json.dumps(LOCAL_RECENT_TRADES)
|
||||||
# VAL_KEY.publish(VK_CHANNEL, VAL_KEY_OBJ)
|
# VAL_KEY.publish(VK_CHANNEL, VAL_KEY_OBJ)
|
||||||
|
|||||||
Reference in New Issue
Block a user