saving
This commit is contained in:
182
algo.ipynb
182
algo.ipynb
File diff suppressed because one or more lines are too long
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"Updated_Timestamp": 1777667398908,
|
"Updated_Timestamp": 1777828655743,
|
||||||
"Config": {
|
"Config": {
|
||||||
"Loop_Sleep_Sec": 0.0,
|
"Loop_Sleep_Sec": 0.0,
|
||||||
"Max_Order_Over_Notional_Ratio": 1.05,
|
"Max_Order_Over_Notional_Ratio": 1.05,
|
||||||
"Max_Target_Notional": 0.0,
|
"Max_Target_Notional": 0.0,
|
||||||
"Min_Time_To_Funding_Minutes": 60,
|
"Min_Time_To_Funding_Minutes": 57,
|
||||||
"Min_Fund_Rate_Pct_To_Trade": 0.0,
|
"Min_Fund_Rate_Pct_To_Trade": 0.0005,
|
||||||
"Price_Worsener_Aster": 0,
|
"Price_Worsener_Aster": 1,
|
||||||
"Price_Worsener_Extend": -1,
|
"Price_Worsener_Extend": -1,
|
||||||
"Switch_To_Taker_Seconds": 3,
|
"Switch_To_Taker_Seconds": 3,
|
||||||
"Target_Open_Cash_Position": 10
|
"Target_Open_Cash_Position": 10
|
||||||
|
|||||||
1258
aster.ipynb
1258
aster.ipynb
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,6 @@ df_leverage_by_exch = pd.DataFrame(data=leverage.LEVERAGE_BY_EXCH)
|
|||||||
### Database ###
|
### Database ###
|
||||||
# CON: AsyncContextManager | None = None
|
# CON: AsyncContextManager | None = None
|
||||||
VAL_KEY: valkey.Valkey
|
VAL_KEY: valkey.Valkey
|
||||||
VK_OUT: str = 'fr_engine_best_fund_rate_output'
|
|
||||||
|
|
||||||
### Logging ###
|
### Logging ###
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
@@ -36,6 +35,11 @@ REFRESH_MKT_VOLUME_EVERY_SEC: int = 30
|
|||||||
Mkt_Info_Last_Refresh_TS_ms: int = 0
|
Mkt_Info_Last_Refresh_TS_ms: int = 0
|
||||||
Mkt_Volume_Last_Refresh_TS_ms: int = 0
|
Mkt_Volume_Last_Refresh_TS_ms: int = 0
|
||||||
|
|
||||||
|
### TODO: score by volume, how long since last trade?, volatility, volume by time of day (active or dormant period?), funding rate consistency (% one side last 24hrs and from active close to active open periods). trade cost estimate?, max tradeable notional.
|
||||||
|
### TODO: figure out what is max percent of volume i can trade - TCA kinda? what is ideal slice size?
|
||||||
|
### TODO: Redesign so Algo allocates across the best markets with a waterfall method until at target collateral usage. order waterfall by score above^^
|
||||||
|
### TODO: NG display grid of markets sorted by above score. top left is control panel, top right is graph (goes to mkt you click on from table) (maybe tabs for different graph views/groups, e.g. PnL total or all mkts percent to liquidate, pov by market etc.) middle bottom is markets table (tabs for open orders, open positions, pnl)
|
||||||
|
|
||||||
### Funcs - Load Data ###
|
### Funcs - Load Data ###
|
||||||
async def get_extended_markets_info() -> pd.DataFrame:
|
async def get_extended_markets_info() -> pd.DataFrame:
|
||||||
r: dict = json.loads(s=requests.get(url='https://api.starknet.extended.exchange/api/v1/info/markets').text)
|
r: dict = json.loads(s=requests.get(url='https://api.starknet.extended.exchange/api/v1/info/markets').text)
|
||||||
@@ -46,8 +50,12 @@ async def get_extended_markets_info() -> pd.DataFrame:
|
|||||||
df['daily_volume'] = df['marketStats'].apply(lambda x: x.get('dailyVolume',{})).astype(float)
|
df['daily_volume'] = df['marketStats'].apply(lambda x: x.get('dailyVolume',{})).astype(float)
|
||||||
df['min_order_size'] = df['tradingConfig'].apply(lambda x: x.get('minOrderSize',{}))
|
df['min_order_size'] = df['tradingConfig'].apply(lambda x: x.get('minOrderSize',{}))
|
||||||
df['min_price'] = df['tradingConfig'].apply(lambda x: x.get('minPriceChange',{}))
|
df['min_price'] = df['tradingConfig'].apply(lambda x: x.get('minPriceChange',{}))
|
||||||
|
df['min_notional'] = 0
|
||||||
|
df['min_lot_size'] = df['tradingConfig'].apply(lambda x: x.get('minOrderSizeChange',{}))
|
||||||
df['max_leverage'] = df['tradingConfig'].apply(lambda x: x.get('maxLeverage',{}))
|
df['max_leverage'] = df['tradingConfig'].apply(lambda x: x.get('maxLeverage',{}))
|
||||||
|
|
||||||
|
#### TODO: ADD IN LOT SIZE FOR ROUND LOTS (SEE IPYNB)
|
||||||
|
|
||||||
print('Extend markets info refreshed successfully')
|
print('Extend markets info refreshed successfully')
|
||||||
|
|
||||||
return df
|
return df
|
||||||
@@ -63,7 +71,9 @@ async def get_aster_exch_info() -> pd.DataFrame:
|
|||||||
df = pd.DataFrame(r['symbols'])
|
df = pd.DataFrame(r['symbols'])
|
||||||
df['min_order_size'] = df['filters'].apply(lambda x: [f for f in x if f.get('filterType', None) == 'LOT_SIZE'][0]['minQty'] )
|
df['min_order_size'] = df['filters'].apply(lambda x: [f for f in x if f.get('filterType', None) == 'LOT_SIZE'][0]['minQty'] )
|
||||||
df['min_price'] = df['filters'].apply(lambda x: [f for f in x if f.get('filterType', None) == 'PRICE_FILTER'][0]['minPrice'] )
|
df['min_price'] = df['filters'].apply(lambda x: [f for f in x if f.get('filterType', None) == 'PRICE_FILTER'][0]['minPrice'] )
|
||||||
|
df['min_notional'] = df['filters'].apply(lambda x: [f for f in x if f.get('filterType', None) == 'MIN_NOTIONAL'][0]['notional'] )
|
||||||
|
df['min_lot_size'] = df['filters'].apply(lambda x: [f for f in x if f.get('filterType', None) == 'LOT_SIZE'][0]['stepSize'] )
|
||||||
|
|
||||||
fut_acct_ticker_stats: dict = {
|
fut_acct_ticker_stats: dict = {
|
||||||
"url": "/fapi/v3/ticker/24hr",
|
"url": "/fapi/v3/ticker/24hr",
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
@@ -71,8 +81,9 @@ async def get_aster_exch_info() -> pd.DataFrame:
|
|||||||
}
|
}
|
||||||
r: dict = await aster_auth.post_authenticated_url(fut_acct_ticker_stats) # ty:ignore[invalid-assignment]
|
r: dict = await aster_auth.post_authenticated_url(fut_acct_ticker_stats) # ty:ignore[invalid-assignment]
|
||||||
df_stats = pd.DataFrame(r)
|
df_stats = pd.DataFrame(r)
|
||||||
|
df_stats['last_trade_ts_ast'] = df_stats['closeTime']
|
||||||
|
|
||||||
df = df.merge(df_stats[['symbol','quoteVolume']].rename({'quoteVolume':'daily_volume'}, axis=1), on='symbol', how='left')
|
df = df.merge(df_stats[['symbol','quoteVolume','last_trade_ts_ast']].rename({'quoteVolume':'daily_volume'}, axis=1), on='symbol', how='left')
|
||||||
df['daily_volume'] = df['daily_volume'].astype(float)
|
df['daily_volume'] = df['daily_volume'].astype(float)
|
||||||
|
|
||||||
|
|
||||||
@@ -87,8 +98,8 @@ def load_aster_current_fr(df_aster_exch_info: pd.DataFrame) -> pd.DataFrame:
|
|||||||
df['funding_rate_updated_dt'] = pd.to_datetime(df['funding_rate_updated_ts_ms'], unit='ms')
|
df['funding_rate_updated_dt'] = pd.to_datetime(df['funding_rate_updated_ts_ms'], unit='ms')
|
||||||
df['funding_rate'] = df['funding_rate'].astype(float)
|
df['funding_rate'] = df['funding_rate'].astype(float)
|
||||||
df['time_delta_to_next_funding'] = pd.to_datetime(df['next_funding_ts'], unit='ms') - pd.Timestamp.now()
|
df['time_delta_to_next_funding'] = pd.to_datetime(df['next_funding_ts'], unit='ms') - pd.Timestamp.now()
|
||||||
df = df.merge(df_aster_exch_info[['symbol','daily_volume','min_order_size','min_price']], on='symbol', how='left')
|
df = df.merge(df_aster_exch_info[['symbol','daily_volume','min_order_size','min_price','min_lot_size','min_notional', 'last_trade_ts_ast']], on='symbol', how='left')
|
||||||
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
def load_extend_current_fr(df_mkt_stats: pd.DataFrame) -> pd.DataFrame:
|
def load_extend_current_fr(df_mkt_stats: pd.DataFrame) -> pd.DataFrame:
|
||||||
@@ -97,8 +108,8 @@ def load_extend_current_fr(df_mkt_stats: pd.DataFrame) -> pd.DataFrame:
|
|||||||
df: pd.DataFrame = df[['symbol','funding_rate_updated_ts_ms','funding_rate']]
|
df: pd.DataFrame = df[['symbol','funding_rate_updated_ts_ms','funding_rate']]
|
||||||
df['funding_rate_updated_dt'] = pd.to_datetime(df['funding_rate_updated_ts_ms'], unit='ms')
|
df['funding_rate_updated_dt'] = pd.to_datetime(df['funding_rate_updated_ts_ms'], unit='ms')
|
||||||
df['funding_rate'] = df['funding_rate'].astype(float)
|
df['funding_rate'] = df['funding_rate'].astype(float)
|
||||||
|
|
||||||
df: pd.DataFrame = df.merge(df_mkt_stats[['name','assetName','status','funding_rate_ts','daily_volume','min_order_size','min_price']].rename({'name':'symbol','funding_rate_ts':'next_funding_ts'}, axis=1), on='symbol', how='left')
|
df = df.merge(df_mkt_stats[['name','assetName','status','funding_rate_ts','min_order_size','min_price','min_lot_size','min_notional','daily_volume']].rename({'name':'symbol','funding_rate_ts':'next_funding_ts'}, axis=1), on='symbol', how='left')
|
||||||
df: pd.DataFrame = df.loc[df['status']=='ACTIVE',:]
|
df: pd.DataFrame = df.loc[df['status']=='ACTIVE',:]
|
||||||
df['USDT_Symbol'] = df['assetName'] + 'USDT'
|
df['USDT_Symbol'] = df['assetName'] + 'USDT'
|
||||||
|
|
||||||
@@ -130,35 +141,69 @@ async def loop() -> None:
|
|||||||
df_comb_fr['net_mult'] = df_comb_fr['net_mult'].round(2)
|
df_comb_fr['net_mult'] = df_comb_fr['net_mult'].round(2)
|
||||||
df_comb_fr['net_mult_x_net_fr_abs'] = df_comb_fr['net_funding_rate_abs'] * df_comb_fr['net_mult']
|
df_comb_fr['net_mult_x_net_fr_abs'] = df_comb_fr['net_funding_rate_abs'] * df_comb_fr['net_mult']
|
||||||
|
|
||||||
|
df_best_fr_rate = df_comb_fr[['symbol_ext','symbol_ast','daily_volume_ext','daily_volume_ast','min_price_ext','min_price_ast','min_order_size_ext','min_order_size_ast','min_lot_size_ext','min_lot_size_ast','min_notional_ext','min_notional_ast','funding_rate_ext','funding_rate_ast','max_leverage_ext','max_leverage_ast','lh_asset_ext','lh_asset_ast','rh_asset_ext','rh_asset_ast','net_mult_x_net_fr_abs','net_funding_rate_abs','net_funding_rate','next_funding_at_same_time','last_trade_ts_ast']].sort_values(by='net_mult_x_net_fr_abs', ascending=False).reset_index(drop=True)
|
||||||
df_best_fr_rate: pd.DataFrame = df_comb_fr[['symbol_ext','symbol_ast','daily_volume_ext','daily_volume_ast','funding_rate_ext','funding_rate_ast','min_price_ext','min_price_ast','min_order_size_ext','min_order_size_ast','max_leverage_ext','max_leverage_ast','lh_asset_ext','lh_asset_ast','rh_asset_ext','rh_asset_ast','net_mult_x_net_fr_abs','net_funding_rate_abs','net_funding_rate','next_funding_at_same_time']].sort_values(by='net_mult_x_net_fr_abs', ascending=False).reset_index(drop=True)
|
|
||||||
|
|
||||||
min_daily_volume = 100_000
|
|
||||||
df_best_fr_rate = df_best_fr_rate.loc[ (df_best_fr_rate['daily_volume_ast']>=min_daily_volume) & (df_best_fr_rate['daily_volume_ext']>min_daily_volume) ,:].reset_index(drop=True)
|
|
||||||
|
|
||||||
ASTER = structs.Perpetual_Exchange(
|
|
||||||
mult = int(df_best_fr_rate['max_leverage_ast'][0]),
|
|
||||||
lh_asset = df_best_fr_rate['lh_asset_ast'][0],
|
|
||||||
rh_asset = df_best_fr_rate['rh_asset_ast'][0],
|
|
||||||
symbol_asset_separator = '',
|
|
||||||
initial_funding_rate=float(df_best_fr_rate['funding_rate_ast'][0]),
|
|
||||||
min_price=float(df_best_fr_rate['min_price_ast'][0]),
|
|
||||||
min_order_size=float(df_best_fr_rate['min_order_size_ast'][0]),
|
|
||||||
)
|
|
||||||
EXTEND = structs.Perpetual_Exchange(
|
|
||||||
mult = int(df_best_fr_rate['max_leverage_ext'][0]),
|
|
||||||
lh_asset = df_best_fr_rate['lh_asset_ext'][0],
|
|
||||||
rh_asset = df_best_fr_rate['rh_asset_ext'][0],
|
|
||||||
symbol_asset_separator = '-',
|
|
||||||
initial_funding_rate=float(df_best_fr_rate['funding_rate_ext'][0]),
|
|
||||||
min_price=float(df_best_fr_rate['min_price_ext'][0]),
|
|
||||||
min_order_size=float(df_best_fr_rate['min_order_size_ext'][0]),
|
|
||||||
)
|
|
||||||
|
|
||||||
best_next_funding_pair: dict[str, dict] = {'ASTER': asdict(obj=ASTER), 'EXTEND': asdict(obj=EXTEND)}
|
|
||||||
|
|
||||||
VAL_KEY.set(name=VK_OUT, value=json.dumps(obj=best_next_funding_pair))
|
# min_daily_volume = 100_000
|
||||||
|
# df_best_fr_rate = df_best_fr_rate.loc[ (df_best_fr_rate['daily_volume_ast']>=min_daily_volume) & (df_best_fr_rate['daily_volume_ext']>min_daily_volume) ,:].reset_index(drop=True)
|
||||||
|
|
||||||
|
last_trade_max_ts = []
|
||||||
|
for index, row in df_best_fr_rate.iterrows():
|
||||||
|
r = json.loads(requests.get(f'https://api.starknet.extended.exchange/api/v1/info/markets/{row['symbol_ext']}/trades').text)
|
||||||
|
max_ts = max([t['T'] for t in r['data']])
|
||||||
|
last_trade_max_ts.append({'symbol_ext':row['symbol_ext'],'last_trade_ts_ext': max_ts})
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
df_best_fr_rate = df_best_fr_rate.merge(pd.DataFrame(last_trade_max_ts), on='symbol_ext', how='left')
|
||||||
|
|
||||||
|
df_best_fr_rate['last_trade_ts_dt_ast'] = pd.to_datetime(df_best_fr_rate['last_trade_ts_ast'], unit='ms')
|
||||||
|
df_best_fr_rate['last_trade_ts_dt_ext'] = pd.to_datetime(df_best_fr_rate['last_trade_ts_ext'], unit='ms')
|
||||||
|
df_best_fr_rate = df_best_fr_rate.loc[( (datetime.now().timestamp()*1000 )-df_best_fr_rate['last_trade_ts_ast']) < (3*60*1000) ]
|
||||||
|
df_best_fr_rate = df_best_fr_rate.loc[( (datetime.now().timestamp()*1000 )-df_best_fr_rate['last_trade_ts_ext']) < (15*60*1000) ]
|
||||||
|
|
||||||
|
# print(df_best_fr_rate.columns)
|
||||||
|
# print(df_best_fr_rate.iloc[0])
|
||||||
|
|
||||||
|
if len(df_best_fr_rate) < 1:
|
||||||
|
raise ValueError(f'NO BFR RATE: {df_best_fr_rate}')
|
||||||
|
|
||||||
|
try:
|
||||||
|
ASTER = structs.Perpetual_Exchange(
|
||||||
|
mult = int(df_best_fr_rate['max_leverage_ast'].iloc[0]),
|
||||||
|
lh_asset = df_best_fr_rate['lh_asset_ast'].iloc[0],
|
||||||
|
rh_asset = df_best_fr_rate['rh_asset_ast'].iloc[0],
|
||||||
|
symbol_asset_separator = '',
|
||||||
|
initial_funding_rate=float(df_best_fr_rate['funding_rate_ast'].iloc[0]),
|
||||||
|
min_price=float(df_best_fr_rate['min_price_ast'].iloc[0]),
|
||||||
|
min_order_size=float(df_best_fr_rate['min_order_size_ast'].iloc[0]),
|
||||||
|
min_lot_size=float(df_best_fr_rate['min_lot_size_ast'].iloc[0]),
|
||||||
|
min_notional=float(df_best_fr_rate['min_notional_ast'].iloc[0]),
|
||||||
|
)
|
||||||
|
EXTEND = structs.Perpetual_Exchange(
|
||||||
|
mult = int(df_best_fr_rate['max_leverage_ext'].iloc[0]),
|
||||||
|
lh_asset = df_best_fr_rate['lh_asset_ext'].iloc[0],
|
||||||
|
rh_asset = df_best_fr_rate['rh_asset_ext'].iloc[0],
|
||||||
|
symbol_asset_separator = '-',
|
||||||
|
initial_funding_rate=float(df_best_fr_rate['funding_rate_ext'].iloc[0]),
|
||||||
|
min_price=float(df_best_fr_rate['min_price_ext'].iloc[0]),
|
||||||
|
min_order_size=float(df_best_fr_rate['min_order_size_ext'].iloc[0]),
|
||||||
|
min_lot_size=float(df_best_fr_rate['min_lot_size_ext'].iloc[0]),
|
||||||
|
min_notional=float(df_best_fr_rate['min_notional_ext'].iloc[0]),
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logging.critical(f'Failed to build ASTER/EXTEND objs err: {e}; df cols: {df_best_fr_rate.columns}')
|
||||||
|
logging.error(traceback.format_exc())
|
||||||
|
continue
|
||||||
|
best_next_funding_pair: dict[str, dict] = {'ASTER': asdict(obj=ASTER), 'EXTEND': asdict(obj=EXTEND)}
|
||||||
|
VAL_KEY.set(name='fr_engine_best_fund_rate_output', value=json.dumps(obj=best_next_funding_pair))
|
||||||
|
|
||||||
|
master_data = df_comb_fr[
|
||||||
|
['symbol_ast','max_leverage_ast','lh_asset_ast','rh_asset_ast','funding_rate_ast','min_price_ast','min_order_size_ast','min_lot_size_ast','min_notional_ast',
|
||||||
|
'symbol_ext','max_leverage_ext','lh_asset_ext','rh_asset_ext','funding_rate_ext','min_price_ext','min_order_size_ext','min_lot_size_ext','min_notional_ext']
|
||||||
|
].to_json(orient='records')
|
||||||
|
|
||||||
|
VAL_KEY.set(name='fr_engine_best_fund_rate_master', value=str(master_data))
|
||||||
print(df_best_fr_rate[['symbol_ext','max_leverage_ext','funding_rate_ast','funding_rate_ext','net_funding_rate','daily_volume_ast']].head(10))
|
print(df_best_fr_rate[['symbol_ext','max_leverage_ext','funding_rate_ast','funding_rate_ext','net_funding_rate','daily_volume_ast']].head(10))
|
||||||
|
logging.info(f'BFR REFRESHED @ {datetime.now()}')
|
||||||
time.sleep(LOOP_SLEEP_SEC)
|
time.sleep(LOOP_SLEEP_SEC)
|
||||||
continue
|
continue
|
||||||
except valkey.exceptions.ConnectionError as e:
|
except valkey.exceptions.ConnectionError as e:
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
1181
extended.ipynb
1181
extended.ipynb
File diff suppressed because one or more lines are too long
246
main.py
246
main.py
@@ -1,4 +1,4 @@
|
|||||||
from orjson import JSONDecodeError
|
|
||||||
from x10.utils.http import WrappedApiResponse
|
from x10.utils.http import WrappedApiResponse
|
||||||
from x10.perpetual.trading_client.trading_client import PerpetualTradingClient
|
from x10.perpetual.trading_client.trading_client import PerpetualTradingClient
|
||||||
import asyncio
|
import asyncio
|
||||||
@@ -9,7 +9,7 @@ import os
|
|||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from decimal import ROUND_DOWN, ROUND_HALF_UP, Decimal
|
from decimal import ROUND_DOWN, ROUND_UP, ROUND_HALF_UP, Decimal
|
||||||
from typing import AsyncContextManager
|
from typing import AsyncContextManager
|
||||||
from dataclasses import dataclass, asdict
|
from dataclasses import dataclass, asdict
|
||||||
from typing import Any
|
from typing import Any
|
||||||
@@ -114,10 +114,15 @@ async def get_aster_account_open_symbols() -> list[str]:
|
|||||||
"url": "/fapi/v3/positionRisk",
|
"url": "/fapi/v3/positionRisk",
|
||||||
"method": "GET",
|
"method": "GET",
|
||||||
"params": {
|
"params": {
|
||||||
'symbol': ASTER.symbol,
|
'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 Exception as e:
|
||||||
|
logging.critical(f'JSONDecodeError trying to get Aster open orders: {e}; resp: {resp}')
|
||||||
|
await kill_algo()
|
||||||
|
resp: list = []
|
||||||
ld = [ utils.symbol_to_extend_fmt(x['symbol']) for x in resp if abs(float(x.get('positionAmt', 0))) > 0]
|
ld = [ utils.symbol_to_extend_fmt(x['symbol']) for x in resp if abs(float(x.get('positionAmt', 0))) > 0]
|
||||||
return ld
|
return ld
|
||||||
|
|
||||||
@@ -144,10 +149,11 @@ async def get_aster_notional_position(resp: list | None = None):
|
|||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
resp: list = await aster_auth.post_authenticated_url(req=fut_acct_positionRisk) # ty:ignore[invalid-assignment]
|
resp: list = await aster_auth.post_authenticated_url(req=fut_acct_positionRisk) # ty:ignore[invalid-assignment]
|
||||||
except JSONDecodeError as e:
|
except Exception as e:
|
||||||
logging.warning(f'JSONDecodeError trying to get Aster notional: {e}; resp: {resp}')
|
logging.critical(f'JSONDecodeError trying to get Aster notional: {e}; resp: {resp}')
|
||||||
time.sleep(0.1)
|
await kill_algo()
|
||||||
resp: list = await aster_auth.post_authenticated_url(req=fut_acct_positionRisk) # ty:ignore[invalid-assignment]
|
resp: list = []
|
||||||
|
|
||||||
d = [x for x in resp if x.get('symbol', None) == ASTER.symbol][0]
|
d = [x for x in resp if x.get('symbol', None) == ASTER.symbol][0]
|
||||||
d['timestamp_arrival'] = round(datetime.now().timestamp()*1000)
|
d['timestamp_arrival'] = round(datetime.now().timestamp()*1000)
|
||||||
|
|
||||||
@@ -168,10 +174,10 @@ async def get_aster_notional_position(resp: list | None = None):
|
|||||||
ASTER_NOTIONAL_POSITION = float(d['notional']) - ASTER_UNREALIZED_PNL
|
ASTER_NOTIONAL_POSITION = float(d['notional']) - ASTER_UNREALIZED_PNL
|
||||||
else:
|
else:
|
||||||
ASTER_NOTIONAL_POSITION = float(d['position_amount'])*float(d['entry_price'])
|
ASTER_NOTIONAL_POSITION = float(d['position_amount'])*float(d['entry_price'])
|
||||||
# if not resp: # this can never evaluate
|
if d.get('leverage') is not None:
|
||||||
# ASTER.mult = float(d['leverage'])
|
ASTER.mult = int(d['leverage'])
|
||||||
if abs(ASTER_NOTIONAL_POSITION) > ALGO_CONFIG.Config.Max_Target_Notional*ALGO_CONFIG.Config.Max_Order_Over_Notional_Ratio:
|
if abs(ASTER_NOTIONAL_POSITION) > ALGO_CONFIG.Config.Max_Target_Notional*ALGO_CONFIG.Config.Max_Order_Over_Notional_Ratio:
|
||||||
logging.info(f'BAD NOTIONAL - ASTER CHANGE: {previous_notional_position} -> {ASTER_NOTIONAL_POSITION}; UR PNL: {ASTER_UNREALIZED_PNL}; MULT: {ASTER.mult}; d: {d}; resp: {resp}')
|
logging.info(f'BAD NOTIONAL - ASTER CHANGE: {previous_notional_position} -> {ASTER_NOTIONAL_POSITION}; UR PNL: {ASTER_UNREALIZED_PNL}; MULT: {ASTER.mult}; d: {d}; resp: {resp}; max_tgt_notional: {ALGO_CONFIG.Config.Max_Target_Notional}')
|
||||||
await kill_algo()
|
await kill_algo()
|
||||||
if ASTER_NOTIONAL_POSITION != previous_notional_position:
|
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)}')
|
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)}')
|
||||||
@@ -210,13 +216,15 @@ async def get_extend_notional(resp: list | None = None):
|
|||||||
pos_dict = [dict(d) for d in resp if dict(d).get('market') == EXTEND.symbol]
|
pos_dict = [dict(d) for d in resp if dict(d).get('market') == EXTEND.symbol]
|
||||||
if pos_dict:
|
if pos_dict:
|
||||||
pos_dict = pos_dict[0]
|
pos_dict = pos_dict[0]
|
||||||
|
pos_dict['timestamp_arrival'] = round(datetime.now().timestamp()*1000)
|
||||||
else:
|
else:
|
||||||
pos_dict = {}
|
pos_dict = {}
|
||||||
pos_dict['side'] = 'LONG'
|
pos_dict['side'] = 'LONG'
|
||||||
pos_dict['value'] = 0.00
|
pos_dict['value'] = 0.00
|
||||||
|
pos_dict['unrealised_pnl'] = 0.00
|
||||||
|
pos_dict['timestamp_arrival'] = round(datetime.now().timestamp()*1000)
|
||||||
logging.info('get_extend_notional - No Positions')
|
logging.info('get_extend_notional - No Positions')
|
||||||
|
|
||||||
pos_dict['timestamp_arrival'] = round(datetime.now().timestamp()*1000)
|
|
||||||
else:
|
else:
|
||||||
pos_dict = [dict(d) for d in resp if dict(d).get('market') == EXTEND.symbol]
|
pos_dict = [dict(d) for d in resp if dict(d).get('market') == EXTEND.symbol]
|
||||||
if pos_dict:
|
if pos_dict:
|
||||||
@@ -225,14 +233,18 @@ async def get_extend_notional(resp: list | None = None):
|
|||||||
pos_dict = {}
|
pos_dict = {}
|
||||||
pos_dict['side'] = 'LONG'
|
pos_dict['side'] = 'LONG'
|
||||||
pos_dict['value'] = 0.00
|
pos_dict['value'] = 0.00
|
||||||
|
pos_dict['unrealised_pnl'] = 0.00
|
||||||
|
pos_dict['timestamp_arrival'] = round(datetime.now().timestamp()*1000)
|
||||||
# logging.info('get_extend_notional - No Positions')
|
# logging.info('get_extend_notional - No Positions')
|
||||||
|
|
||||||
pos_dict['timestamp_arrival'] = round(datetime.now().timestamp()*1000)
|
# pos_dict['timestamp_arrival'] = round(datetime.now().timestamp()*1000)
|
||||||
|
|
||||||
if previous_notional_obj is not None:
|
if previous_notional_obj is not None:
|
||||||
if previous_notional_obj['timestamp_arrival'] > pos_dict['timestamp_arrival']:
|
if previous_notional_obj['timestamp_arrival'] > pos_dict['timestamp_arrival']:
|
||||||
# logging.info(f'EXTEND NOTIONAL: prev timestamp ({pd.to_datetime(previous_notional_obj['timestamp_arrival'], unit='ms')}) > new timestamp ({pd.to_datetime(d['timestamp_arrival'], unit='ms')}); skipping')
|
# logging.info(f'EXTEND NOTIONAL: prev timestamp ({pd.to_datetime(previous_notional_obj['timestamp_arrival'], unit='ms')}) > new timestamp ({pd.to_datetime(pos_dict['timestamp_arrival'], unit='ms')}); skipping')
|
||||||
return
|
return
|
||||||
|
else:
|
||||||
|
previous_notional_obj = {}
|
||||||
|
|
||||||
EXTEND_NOTIONAL_OBJ = pos_dict
|
EXTEND_NOTIONAL_OBJ = pos_dict
|
||||||
|
|
||||||
@@ -252,7 +264,7 @@ async def get_extend_notional(resp: list | None = None):
|
|||||||
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}')
|
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()
|
await kill_algo()
|
||||||
if EXTEND_NOTIONAL_POSITION != previous_notional_position:
|
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}; resp: {bool(resp)}')
|
logging.info(f'EXTEND NOTIONAL CHANGE: {previous_notional_position} [{previous_notional_obj.get('timestamp_arrival')}] -> {EXTEND_NOTIONAL_POSITION:.2f} [{EXTEND_NOTIONAL_OBJ['timestamp_arrival']}]; UR PNL: {EXTEND_UNREALIZED_PNL:.2f}; MULT: {EXTEND.mult}; resp: {bool(resp)}')
|
||||||
|
|
||||||
### EXCHANGE INFO ###
|
### EXCHANGE INFO ###
|
||||||
async def get_aster_exch_info(symbol_override: str | None = None):
|
async def get_aster_exch_info(symbol_override: str | None = None):
|
||||||
@@ -271,6 +283,7 @@ async def get_aster_exch_info(symbol_override: str | None = None):
|
|||||||
d: dict = [d for d in s if d.get('symbol', None) == ASTER.symbol][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]
|
f: dict = [f for f in d['filters'] if f.get('filterType', None) == 'LOT_SIZE'][0]
|
||||||
q: dict = [f for f in d['filters'] if f.get('filterType', None) == 'PRICE_FILTER'][0]
|
q: dict = [f for f in d['filters'] if f.get('filterType', None) == 'PRICE_FILTER'][0]
|
||||||
|
n: dict = [f for f in d['filters'] if f.get('filterType', None) == 'MIN_NOTIONAL'][0]
|
||||||
|
|
||||||
min_qty = float(f['minQty'])
|
min_qty = float(f['minQty'])
|
||||||
min_qty = int(min_qty) if min_qty == int(min_qty) else min_qty
|
min_qty = int(min_qty) if min_qty == int(min_qty) else min_qty
|
||||||
@@ -279,6 +292,7 @@ async def get_aster_exch_info(symbol_override: str | None = None):
|
|||||||
min_price = int(min_price) if min_price == int(min_price) else min_price
|
min_price = int(min_price) if min_price == int(min_price) else min_price
|
||||||
ASTER.min_order_size = min_qty
|
ASTER.min_order_size = min_qty
|
||||||
ASTER.min_price = min_price
|
ASTER.min_price = min_price
|
||||||
|
ASTER.min_notional = float(n['notional'])
|
||||||
|
|
||||||
async def get_extend_exch_info(symbol_override: str | None = None):
|
async def get_extend_exch_info(symbol_override: str | None = None):
|
||||||
global EXTEND
|
global EXTEND
|
||||||
@@ -290,6 +304,7 @@ async def get_extend_exch_info(symbol_override: str | None = None):
|
|||||||
EXTEND.min_order_size = float(r[EXTEND.symbol].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)
|
EXTEND.min_price = float(r[EXTEND.symbol].trading_config.min_price_change)
|
||||||
|
|
||||||
|
|
||||||
### CANCEL ORDERS ###
|
### CANCEL ORDERS ###
|
||||||
async def aster_cancel_all_orders():
|
async def aster_cancel_all_orders():
|
||||||
cancel_all_open_orders = {
|
cancel_all_open_orders = {
|
||||||
@@ -367,13 +382,11 @@ async def run_algo():
|
|||||||
ASTER_FUND_RATE = ASTER_FUND_RATE * -1
|
ASTER_FUND_RATE = ASTER_FUND_RATE * -1
|
||||||
EXTEND_FUND_RATE = EXTEND_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))
|
ASTER_FUND_RATE_TIME = float(ASTER_FUND_RATE_DICT.get('next_funding_time_ts_ms', 0))
|
||||||
|
ASTER_FUND_RATE_TIME = ASTER_FUND_RATE_TIME+(60*60*1000) if ASTER_FUND_RATE_TIME < (datetime.now().timestamp()*1000) else ASTER_FUND_RATE_TIME
|
||||||
|
|
||||||
EXTEND_FUND_RATE_TIME = max([float(EXTENDED_FUND_RATE_DICT.get('next_funding_time_ts_ms', 0)), 0])
|
EXTEND_FUND_RATE_TIME = max([float(EXTENDED_FUND_RATE_DICT.get('next_funding_time_ts_ms', 0)), 0])
|
||||||
|
EXTEND_FUND_RATE_TIME = EXTEND_FUND_RATE_TIME+(60*60*1000) if EXTEND_FUND_RATE_TIME < (datetime.now().timestamp()*1000) else EXTEND_FUND_RATE_TIME
|
||||||
|
|
||||||
ASTER_TICKER_DICT: Any = VAL_KEY.get('fut_ticker_aster')
|
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 {}
|
ASTER_TICKER_DICT: dict = json.loads(s=ASTER_TICKER_DICT) if ASTER_TICKER_DICT is not None else {}
|
||||||
@@ -510,16 +523,39 @@ async def run_algo():
|
|||||||
if abs( ASTER_NOTIONAL_POSITION ) > 0.00 or abs( EXTEND_NOTIONAL_POSITION ) > 0.00:
|
if abs( ASTER_NOTIONAL_POSITION ) > 0.00 or abs( EXTEND_NOTIONAL_POSITION ) > 0.00:
|
||||||
if ALGO_CONFIG.Logging.Print_Summary_Each_Loop:
|
if ALGO_CONFIG.Logging.Print_Summary_Each_Loop:
|
||||||
print(f'Symbol switch [{ASTER.symbol} > {best_symbol_by_exchange_aster.symbol}] - Flattening Positions')
|
print(f'Symbol switch [{ASTER.symbol} > {best_symbol_by_exchange_aster.symbol}] - Flattening Positions')
|
||||||
ALGO_CONFIG.Overrides.Flatten_Open_Positions = True
|
ALGO_CONFIG.Overrides.Flatten_Open_Positions_Opportunistic = True
|
||||||
else:
|
else:
|
||||||
logging.info('Balances Flattened - Updating to Trade New Symbols:')
|
logging.info('Balances Flattened - Updating to Trade New Symbols:')
|
||||||
logging.info(f' ASTER.symbol -> {best_symbol_by_exchange_aster.symbol}')
|
logging.info(f' ASTER.symbol -> {best_symbol_by_exchange_aster.symbol}')
|
||||||
logging.info(f' EXTEND.symbol -> {best_symbol_by_exchange_extend.symbol}')
|
logging.info(f' EXTEND.symbol -> {best_symbol_by_exchange_extend.symbol}')
|
||||||
ALGO_CONFIG.Overrides.Flatten_Open_Positions = False
|
ALGO_CONFIG.Overrides.Flatten_Open_Positions_Opportunistic = False
|
||||||
if Open_Symbols:
|
if Open_Symbols:
|
||||||
logging.info(f'OPEN SYMBOLS TO CLOSE: {Open_Symbols}')
|
logging.info(f'OPEN SYMBOLS TO CLOSE: {Open_Symbols}')
|
||||||
await get_aster_exch_info(symbol_override=Open_Symbols[0])
|
master_data = json.loads(s=VAL_KEY.get(name='fr_engine_best_fund_rate_master')) # ty:ignore[invalid-argument-type]
|
||||||
await get_extend_exch_info(symbol_override=Open_Symbols[0])
|
open_symbol_to_work = Open_Symbols[0]
|
||||||
|
current_pos_master_ast = [d for d in master_data if d.get('symbol_ext') == open_symbol_to_work][0]
|
||||||
|
ASTER = structs.Perpetual_Exchange(
|
||||||
|
mult = int(current_pos_master_ast['max_leverage_ast']),
|
||||||
|
lh_asset = current_pos_master_ast['lh_asset_ast'],
|
||||||
|
rh_asset = current_pos_master_ast['rh_asset_ast'],
|
||||||
|
symbol_asset_separator = '',
|
||||||
|
initial_funding_rate=float(current_pos_master_ast['funding_rate_ast']),
|
||||||
|
min_price=float(current_pos_master_ast['min_price_ast']),
|
||||||
|
min_order_size=float(current_pos_master_ast['min_order_size_ast']),
|
||||||
|
min_lot_size=float(current_pos_master_ast['min_lot_size_ast']),
|
||||||
|
min_notional=float(current_pos_master_ast['min_notional_ast']),
|
||||||
|
)
|
||||||
|
EXTEND = structs.Perpetual_Exchange(
|
||||||
|
mult = int(current_pos_master_ast['max_leverage_ext']),
|
||||||
|
lh_asset = current_pos_master_ast['lh_asset_ext'],
|
||||||
|
rh_asset = current_pos_master_ast['rh_asset_ext'],
|
||||||
|
symbol_asset_separator = '-',
|
||||||
|
initial_funding_rate=float(current_pos_master_ast['funding_rate_ext']),
|
||||||
|
min_price=float(current_pos_master_ast['min_price_ext']),
|
||||||
|
min_order_size=float(current_pos_master_ast['min_order_size_ext']),
|
||||||
|
min_lot_size=float(current_pos_master_ast['min_lot_size_ext']),
|
||||||
|
min_notional=float(current_pos_master_ast['min_notional_ext']),
|
||||||
|
)
|
||||||
Open_Symbols.pop(0)
|
Open_Symbols.pop(0)
|
||||||
await get_aster_notional_position()
|
await get_aster_notional_position()
|
||||||
await get_extend_notional()
|
await get_extend_notional()
|
||||||
@@ -565,7 +601,13 @@ async def run_algo():
|
|||||||
# else:
|
# else:
|
||||||
# logging.info('NET FUNDING = 0.00; NO OPEN ORDERS; Waiting...')
|
# logging.info('NET FUNDING = 0.00; NO OPEN ORDERS; Waiting...')
|
||||||
# time.sleep(5)
|
# time.sleep(5)
|
||||||
|
|
||||||
|
if ALGO_CONFIG.Overrides.Flatten_Open_Positions or ALGO_CONFIG.Overrides.Flatten_Open_Positions_Opportunistic or ALPHA_TGT_NOTIONAL==0.00:
|
||||||
|
# ROUNDING = ROUND_UP
|
||||||
|
ROUNDING = ROUND_HALF_UP
|
||||||
|
else:
|
||||||
|
ROUNDING = ROUND_DOWN
|
||||||
|
|
||||||
|
|
||||||
if ALPHA_EXCH == 'EXTEND':
|
if ALPHA_EXCH == 'EXTEND':
|
||||||
ASTER_TGT_NOTIONAL = ALPHA_TGT_NOTIONAL*-1
|
ASTER_TGT_NOTIONAL = ALPHA_TGT_NOTIONAL*-1
|
||||||
@@ -603,28 +645,46 @@ async def run_algo():
|
|||||||
Expected_Alpha = ( ( ASTER_TOB_PX - EXTEND_TOB_PX ) / (( ASTER_TOB_PX + EXTEND_TOB_PX ) / 2) )
|
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 = abs(NEXT_NET_FUNDING_RATE) + Expected_Alpha
|
||||||
Expected_Alpha_Net_FR_w_Taker = Expected_Alpha_Net_FR-0.0002
|
Expected_Alpha_Net_FR_w_Taker = Expected_Alpha_Net_FR-0.00025
|
||||||
Expected_Alpha_w_Taker = Expected_Alpha-0.0002
|
Expected_Alpha_w_Taker = Expected_Alpha-0.00025
|
||||||
|
|
||||||
EXTEND_TGT_NOTIONAL = ASTER_NOTIONAL_POSITION * -1
|
EXTEND_TGT_NOTIONAL = ASTER_NOTIONAL_POSITION * -1
|
||||||
|
|
||||||
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) )
|
||||||
|
EXTEND_TGT_TAIL = EXTEND_TGT_NOTIONAL - ( float(EXTEND_NOTIONAL_POSITION) )
|
||||||
# EXTEND_TGT_TAIL = float(ASTER_NOTIONAL_POSITION)*-1
|
# EXTEND_TGT_TAIL = float(ASTER_NOTIONAL_POSITION)*-1
|
||||||
|
|
||||||
min_order_size = ASTER.min_order_size
|
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
|
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)
|
ASTER_TGT_TAIL_BASE_QTY = Decimal(str(float(ASTER_TGT_TAIL) / float(ASTER_TOB_PX))).quantize(Decimal(str(min_order_size)), rounding=ROUNDING)
|
||||||
|
if ASTER.min_lot_size:
|
||||||
|
ASTER_TGT_TAIL_BASE_QTY = float(ASTER_TGT_TAIL_BASE_QTY) - ( float(ASTER_TGT_TAIL_BASE_QTY) % ASTER.min_lot_size )
|
||||||
|
ASTER_TGT_TAIL_BASE_QTY = Decimal(str(ASTER_TGT_TAIL_BASE_QTY)).quantize(Decimal(str(min_order_size)), rounding=ROUNDING)
|
||||||
|
|
||||||
min_order_size = EXTEND.min_order_size
|
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
|
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)
|
EXTEND_TGT_TAIL_BASE_QTY = Decimal(str(float(EXTEND_TGT_TAIL) / float(EXTEND_TOB_PX))).quantize(Decimal(str(min_order_size)), rounding=ROUNDING)
|
||||||
|
if EXTEND.min_lot_size:
|
||||||
|
EXTEND_TGT_TAIL_BASE_QTY = float(EXTEND_TGT_TAIL_BASE_QTY) - ( float(EXTEND_TGT_TAIL_BASE_QTY) % EXTEND.min_lot_size )
|
||||||
|
EXTEND_TGT_TAIL_BASE_QTY = Decimal(str(EXTEND_TGT_TAIL_BASE_QTY)).quantize(Decimal(str(min_order_size)), rounding=ROUNDING)
|
||||||
|
|
||||||
# MAX_MIN_ORDER_QTY = max([ASTER.min_order_size, EXTEND.min_order_size])
|
# 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)))
|
ASTER_TGT_TAIL_ORDERABLE = ( Decimal(str(abs(ASTER_TGT_TAIL_BASE_QTY)) ) >= Decimal(str(abs(ASTER.min_order_size))) ) and ( Decimal(str(abs(ASTER_TGT_TAIL))) > Decimal(str(abs(ASTER.min_notional))) )
|
||||||
EXTEND_TGT_TAIL_ORDERABLE = Decimal(str(abs(EXTEND_TGT_TAIL_BASE_QTY))) >= Decimal(str(abs(EXTEND.min_order_size)))
|
EXTEND_TGT_TAIL_ORDERABLE = ( Decimal(str(abs(EXTEND_TGT_TAIL_BASE_QTY))) >= Decimal(str(abs(EXTEND.min_order_size))) ) and ( Decimal(str(abs(EXTEND_TGT_TAIL))) > Decimal(str(abs(EXTEND.min_notional))) )
|
||||||
# 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
|
if not ASTER_TGT_TAIL_ORDERABLE:
|
||||||
|
if abs(ASTER_TGT_TAIL_BASE_QTY) > 0:
|
||||||
|
if ALGO_CONFIG.Overrides.Flatten_Open_Positions or ALGO_CONFIG.Overrides.Flatten_Open_Positions_Opportunistic or ALPHA_TGT_NOTIONAL == 0.00:
|
||||||
|
logging.info('* Trying to flatten small Aster balance, was originally not orderable.')
|
||||||
|
ASTER_TGT_TAIL_ORDERABLE = True
|
||||||
|
if not EXTEND_TGT_TAIL_ORDERABLE:
|
||||||
|
if abs(EXTEND_TGT_TAIL_BASE_QTY) > 0:
|
||||||
|
if ALGO_CONFIG.Overrides.Flatten_Open_Positions or ALGO_CONFIG.Overrides.Flatten_Open_Positions_Opportunistic or ALPHA_TGT_NOTIONAL == 0.00:
|
||||||
|
logging.info('* Trying to flatten small Extend balance, was originally not orderable.')
|
||||||
|
EXTEND_TGT_TAIL_ORDERABLE = True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 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(( 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 ) / max([ASTER_NOTIONAL_POSITION, 0.01]) ) * 100
|
Hedge_Ratio = abs( ( EXTEND_NOTIONAL_POSITION + ASTER_NOTIONAL_POSITION ) / max([ASTER_NOTIONAL_POSITION, 0.01]) ) * 100
|
||||||
@@ -652,7 +712,7 @@ async def run_algo():
|
|||||||
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} ]
|
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:_.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} *
|
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}]
|
FEES : TAKER: {0.00025:.6%}; Expected Alpha w Taker = {Expected_Alpha_Net_FR_w_Taker:.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}]
|
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})
|
||||||
@@ -674,11 +734,16 @@ async def run_algo():
|
|||||||
|
|
||||||
### ROUTES ###
|
### ROUTES ###
|
||||||
# Just_Rejected_Or_Expired
|
# Just_Rejected_Or_Expired
|
||||||
# MIN_EXPECTED_ALPHA_TO_TRADE = 0.0001
|
MIN_EXPECTED_ALPHA_TO_TRADE = 0.0000
|
||||||
MIN_EXPECTED_ALPHA_TO_TRADE = abs(NEXT_NET_FUNDING_RATE)*-1
|
if ALGO_CONFIG.Overrides.Flatten_Open_Positions_Opportunistic:
|
||||||
|
exp_alpha = Expected_Alpha_w_Taker
|
||||||
|
else:
|
||||||
|
exp_alpha = Expected_Alpha_Net_FR_w_Taker
|
||||||
|
# MIN_EXPECTED_ALPHA_TO_TRADE = abs(NEXT_NET_FUNDING_RATE)*-1
|
||||||
# MIN_EXPECTED_ALPHA_TO_TRADE = -0.000001
|
# MIN_EXPECTED_ALPHA_TO_TRADE = -0.000001
|
||||||
# ALPHA RATIO CHECK
|
# 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 ALGO_CONFIG.Overrides.Flatten_Open_Positions) ) and Currently_Hedged:
|
if not( ( exp_alpha > MIN_EXPECTED_ALPHA_TO_TRADE ) or ( ASTER_OPEN_ORDERS or EXTEND_OPEN_ORDERS or ALGO_CONFIG.Overrides.Flatten_Open_Positions) ) and Currently_Hedged:
|
||||||
|
# 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:
|
if ALGO_CONFIG.Logging.Print_Summary_Each_Loop:
|
||||||
print(f'Alpha Ratio too low ({ALPHA_RATIO:.8f}) and no Open Orders...')
|
print(f'Alpha Ratio too low ({ALPHA_RATIO:.8f}) and no Open Orders...')
|
||||||
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):
|
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):
|
||||||
@@ -732,14 +797,18 @@ async def run_algo():
|
|||||||
if ASTER_TGT_TAIL_BASE_QTY == 0.00:
|
if ASTER_TGT_TAIL_BASE_QTY == 0.00:
|
||||||
place_order = False
|
place_order = False
|
||||||
logging.info('ASTER TRYNG TO ORDER 0.00 BASE QTY, SKIPPING')
|
logging.info('ASTER TRYNG TO ORDER 0.00 BASE QTY, SKIPPING')
|
||||||
|
|
||||||
|
|
||||||
if place_order:
|
if place_order:
|
||||||
min_price = ASTER.min_price
|
min_price = ASTER.min_price
|
||||||
min_price = int(min_price) if min_price == int(min_price) else 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)
|
price: Decimal = Decimal(str(price)).quantize(Decimal(str(min_price)), rounding=ROUND_HALF_UP)
|
||||||
|
|
||||||
|
if price == Decimal(str(0.00)).quantize(Decimal(str(min_price)), rounding=ROUND_HALF_UP):
|
||||||
|
logging.info('ASTER TRYNG TO ORDER with A PRICE OF 0.00, SKIPPING')
|
||||||
|
continue
|
||||||
|
|
||||||
|
if qty >= ASTER.min_order_size and (qty*price) > ASTER.min_notional:
|
||||||
if qty >= ASTER.min_order_size:
|
|
||||||
reduceOnly = False
|
reduceOnly = False
|
||||||
else:
|
else:
|
||||||
reduceOnly = True
|
reduceOnly = True
|
||||||
@@ -763,7 +832,7 @@ async def run_algo():
|
|||||||
order_resp['order_status'] = order_resp['status']
|
order_resp['order_status'] = order_resp['status']
|
||||||
ASTER_OPEN_ORDERS.append(order_resp)
|
ASTER_OPEN_ORDERS.append(order_resp)
|
||||||
Just_Rejected_Or_Expired = False
|
Just_Rejected_Or_Expired = False
|
||||||
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}')
|
utils.send_tg_alert(f'FR_ALGO - ASTER Order ({order_resp['orderId']}). Start_$: {ASTER_NOTIONAL_POSITION:.4f}; Value: {float(ASTER_TGT_TAIL_BASE_QTY)*float(price):.4f}; Price: {float(price):.4f}')
|
||||||
logging.info(f'ASTER ORDER PLACED SUCCESS: {order_resp}')
|
logging.info(f'ASTER ORDER PLACED SUCCESS: {order_resp}')
|
||||||
print_summary(use_logging=True)
|
print_summary(use_logging=True)
|
||||||
else:
|
else:
|
||||||
@@ -777,13 +846,22 @@ async def run_algo():
|
|||||||
### Add code to flatten small balances
|
### Add code to flatten small balances
|
||||||
logging.info('ASTER HAS NO TAIL BUT OPEN ORDERS - CANCELLING OPEN ORDERS')
|
logging.info('ASTER HAS NO TAIL BUT OPEN ORDERS - CANCELLING OPEN ORDERS')
|
||||||
await aster_cancel_all_orders()
|
await aster_cancel_all_orders()
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
# if (float(ALPHA_TGT_NOTIONAL) < float(EXTEND_NOTIONAL_POSITION)) and ((float(EXTEND_NOTIONAL_POSITION) + float(EXTEND_TGT_TAIL)) > float(EXTEND_NOTIONAL_POSITION)):
|
||||||
|
# EXTEND_TGT_TAIL_ORDERABLE= False
|
||||||
|
# print('ASTER ordering in the wrong directiion - Should be selling, but its buying - skipping')
|
||||||
|
# elif (float(ALPHA_TGT_NOTIONAL) > float(EXTEND_NOTIONAL_POSITION)) and ((float(EXTEND_NOTIONAL_POSITION) + float(EXTEND_TGT_TAIL)) < float(EXTEND_NOTIONAL_POSITION)):
|
||||||
|
# EXTEND_TGT_TAIL_ORDERABLE= False
|
||||||
|
# print('ASTER ordering in the wrong directiion - Should be buying, but its selling - skipping')
|
||||||
|
|
||||||
# EXTEND
|
# EXTEND
|
||||||
if EXTEND_TGT_TAIL_ORDERABLE and ALGO_CONFIG.Overrides.Allow_Ordering_Extend:
|
if (EXTEND_TGT_TAIL_ORDERABLE and ALGO_CONFIG.Overrides.Allow_Ordering_Extend):
|
||||||
# if 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
|
side = OrderSide.BUY if EXTEND_TGT_TAIL_BASE_QTY > 0.00 else OrderSide.SELL
|
||||||
symbol = EXTEND.symbol
|
symbol = EXTEND.symbol
|
||||||
qty = Decimal(value=str(abs(EXTEND_TGT_TAIL_BASE_QTY)))
|
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
|
Time_Since_Last_Aster_Fill_ms = ( datetime.now().timestamp()*1000 ) - Last_Aster_Fill_Time_Ts
|
||||||
min_price = EXTEND.min_price
|
min_price = EXTEND.min_price
|
||||||
min_price = int(min_price) if min_price == int(min_price) else min_price
|
min_price = int(min_price) if min_price == int(min_price) else min_price
|
||||||
@@ -791,10 +869,10 @@ async def run_algo():
|
|||||||
post_only = False
|
post_only = False
|
||||||
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)
|
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:
|
else:
|
||||||
post_only = True
|
# post_only = True
|
||||||
|
post_only = False
|
||||||
price: Decimal = Decimal(value=str(EXTEND_TOB_PX)).quantize(Decimal(str(min_price)), rounding=ROUND_HALF_UP)
|
price: Decimal = Decimal(value=str(EXTEND_TOB_PX)).quantize(Decimal(str(min_price)), rounding=ROUND_HALF_UP)
|
||||||
|
|
||||||
|
|
||||||
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:
|
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})')
|
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()
|
await kill_algo()
|
||||||
@@ -802,28 +880,19 @@ async def run_algo():
|
|||||||
open_order_dict = dict(EXTEND_OPEN_ORDERS[0])
|
open_order_dict = dict(EXTEND_OPEN_ORDERS[0])
|
||||||
open_order_id = str(open_order_dict['external_id'])
|
open_order_id = str(open_order_dict['external_id'])
|
||||||
open_order_px = float(open_order_dict['price'])
|
open_order_px = float(open_order_dict['price'])
|
||||||
open_order_filled_qty = float(open_order_dict['filled_qty'])
|
|
||||||
|
|
||||||
if qty >= EXTEND.min_order_size:
|
# if int(qty) == 0:
|
||||||
place_order = True
|
# place_order = False
|
||||||
place_residual_order = False
|
# place_residual_order = False
|
||||||
else:
|
# logging.info(f'EXTEND NOT ORDERING DUE TO NOTIONAL QTY == 0; Filled: {float(open_order_filled_qty):.4f}; Residual: {qty:.4f}')
|
||||||
if int(qty) == 0:
|
# else:
|
||||||
place_order = False
|
# place_order = True
|
||||||
place_residual_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}')
|
# logging.info(f'Ordering RESIDUAL market order for remaining small amount: {qty}')
|
||||||
else:
|
|
||||||
place_order = True
|
|
||||||
place_residual_order = True
|
|
||||||
logging.info(f'Ordering RESIDUAL market order for remaining small amount: {qty}')
|
|
||||||
else:
|
else:
|
||||||
open_order_id = None
|
open_order_id = None
|
||||||
open_order_px = 0
|
open_order_px = 0
|
||||||
place_order = True
|
place_order = True
|
||||||
if qty >= EXTEND.min_order_size:
|
|
||||||
place_residual_order = False
|
|
||||||
else:
|
|
||||||
place_residual_order = True
|
|
||||||
if place_order:
|
if place_order:
|
||||||
price: Decimal = Decimal(str(price)).quantize(Decimal(str(min_price)), rounding=ROUND_HALF_UP)
|
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 round(open_order_px - float(price), len(str(min_price)) - 2 ) == 0.00:
|
||||||
@@ -831,14 +900,13 @@ async def run_algo():
|
|||||||
print('EXTEND OPEN ORDER NO PX CHG; SKIPPING')
|
print('EXTEND OPEN ORDER NO PX CHG; SKIPPING')
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
if place_residual_order:
|
if abs(float(EXTEND_NOTIONAL_POSITION) + (float(qty)*float(price))) < abs(float(EXTEND_NOTIONAL_POSITION)):
|
||||||
post_only = False
|
|
||||||
reduce_only = True
|
reduce_only = True
|
||||||
else:
|
else:
|
||||||
# post_only = SEE ABOVE
|
|
||||||
reduce_only = False
|
reduce_only = False
|
||||||
|
|
||||||
taker_fee = taker_fee=Decimal("0.00000") if post_only else Decimal("0.00025")
|
# taker_fee = taker_fee=Decimal("0.00000") if post_only else Decimal("0.00025")
|
||||||
|
taker_fee = Decimal("0.00025")
|
||||||
order_resp: WrappedApiResponse[PlacedOrderModel] = await EXTEND_CLIENT.place_order(
|
order_resp: WrappedApiResponse[PlacedOrderModel] = await EXTEND_CLIENT.place_order(
|
||||||
market_name=symbol,
|
market_name=symbol,
|
||||||
amount_of_synthetic=Decimal(str(qty)),
|
amount_of_synthetic=Decimal(str(qty)),
|
||||||
@@ -846,14 +914,14 @@ async def run_algo():
|
|||||||
side=side,
|
side=side,
|
||||||
taker_fee=taker_fee,
|
taker_fee=taker_fee,
|
||||||
previous_order_id=open_order_id,
|
previous_order_id=open_order_id,
|
||||||
post_only=post_only
|
post_only=post_only,
|
||||||
# reduce_only=reduce_only
|
reduce_only=reduce_only
|
||||||
)
|
)
|
||||||
except Exception as e:
|
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: {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}; reduce_only:{reduce_only}')
|
logging.error(f'EXTEND ORDER PLACEMENT FAILED - POSTED: market_name:{symbol}, side: {side} 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())
|
logging.error(traceback.format_exc())
|
||||||
|
logging.error(f'EXTEND ORDER PLACEMENT FAILED - RESP: {order_resp}')
|
||||||
|
|
||||||
order_resp_dict = dict(order_resp)
|
order_resp_dict = dict(order_resp)
|
||||||
|
|
||||||
@@ -888,7 +956,8 @@ async def run_algo():
|
|||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
time.sleep(ALGO_CONFIG.Config.Loop_Sleep_Sec)
|
time.sleep(ALGO_CONFIG.Config.Loop_Sleep_Sec)
|
||||||
# print(f'_____ End No Open Orders _____ (Algo Engine ms: {(time.time() - loop_start)*1000:.2f}); Sleeping for sec: {ALGO_CONFIG.Config.Loop_Sleep_Sec:.0f}')
|
if ALGO_CONFIG.Logging.Print_Summary_Each_Loop:
|
||||||
|
print(f'_____ End No Open Orders _____ (Algo Engine ms: {(time.time() - loop_start)*1000:.2f}); Sleeping for sec: {ALGO_CONFIG.Config.Loop_Sleep_Sec:.0f}')
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
logging.info('CANCELLING OPEN ORDERS')
|
logging.info('CANCELLING OPEN ORDERS')
|
||||||
@@ -916,23 +985,50 @@ async def main():
|
|||||||
VAL_KEY = valkey.Valkey(host='localhost', port=6379, db=0, decode_responses=True)
|
VAL_KEY = valkey.Valkey(host='localhost', port=6379, db=0, decode_responses=True)
|
||||||
engine = create_async_engine('mysql+asyncmy://root:pwd@localhost/fund_rate')
|
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()
|
await set_comb_open_symbols()
|
||||||
|
|
||||||
|
best_symbol_by_exchange: dict = json.loads(s=VAL_KEY.get(name='fr_engine_best_fund_rate_output')) # ty:ignore[invalid-argument-type]
|
||||||
if Open_Symbols:
|
if Open_Symbols:
|
||||||
logging.info(f'OPEN SYMBOLS TO CLOSE: {Open_Symbols}')
|
logging.info(f'OPEN SYMBOLS: {Open_Symbols}')
|
||||||
await get_aster_exch_info(symbol_override=Open_Symbols[0])
|
master_data = json.loads(s=VAL_KEY.get(name='fr_engine_best_fund_rate_master')) # ty:ignore[invalid-argument-type]
|
||||||
await get_extend_exch_info(symbol_override=Open_Symbols[0])
|
open_symbol_to_work = Open_Symbols[0]
|
||||||
|
current_pos_master_ast = [d for d in master_data if d.get('symbol_ext') == open_symbol_to_work][0]
|
||||||
|
ASTER = structs.Perpetual_Exchange(
|
||||||
|
mult = int(current_pos_master_ast['max_leverage_ast']),
|
||||||
|
lh_asset = current_pos_master_ast['lh_asset_ast'],
|
||||||
|
rh_asset = current_pos_master_ast['rh_asset_ast'],
|
||||||
|
symbol_asset_separator = '',
|
||||||
|
initial_funding_rate=float(current_pos_master_ast['funding_rate_ast']),
|
||||||
|
min_price=float(current_pos_master_ast['min_price_ast']),
|
||||||
|
min_order_size=float(current_pos_master_ast['min_order_size_ast']),
|
||||||
|
min_lot_size=float(current_pos_master_ast['min_lot_size_ast']),
|
||||||
|
min_notional=float(current_pos_master_ast['min_notional_ast']),
|
||||||
|
)
|
||||||
|
EXTEND = structs.Perpetual_Exchange(
|
||||||
|
mult = int(current_pos_master_ast['max_leverage_ext']),
|
||||||
|
lh_asset = current_pos_master_ast['lh_asset_ext'],
|
||||||
|
rh_asset = current_pos_master_ast['rh_asset_ext'],
|
||||||
|
symbol_asset_separator = '-',
|
||||||
|
initial_funding_rate=float(current_pos_master_ast['funding_rate_ext']),
|
||||||
|
min_price=float(current_pos_master_ast['min_price_ext']),
|
||||||
|
min_order_size=float(current_pos_master_ast['min_order_size_ext']),
|
||||||
|
min_lot_size=float(current_pos_master_ast['min_lot_size_ext']),
|
||||||
|
min_notional=float(current_pos_master_ast['min_notional_ext']),
|
||||||
|
)
|
||||||
Open_Symbols.pop(0)
|
Open_Symbols.pop(0)
|
||||||
|
else:
|
||||||
|
ASTER = structs.Perpetual_Exchange(**best_symbol_by_exchange['ASTER'])
|
||||||
|
EXTEND = structs.Perpetual_Exchange(**best_symbol_by_exchange['EXTEND'])
|
||||||
|
|
||||||
|
# await get_aster_exch_info(symbol_override=Open_Symbols[0])
|
||||||
|
# await get_extend_exch_info(symbol_override=Open_Symbols[0])
|
||||||
|
|
||||||
with open('algo_config.json', mode='r', encoding='utf-8') as file:
|
with open('algo_config.json', mode='r', encoding='utf-8') as file:
|
||||||
ALGO_CONFIG = json.load(file)
|
ALGO_CONFIG = json.load(file)
|
||||||
ALGO_CONFIG = structs.Algo_Config(**ALGO_CONFIG)
|
ALGO_CONFIG = structs.Algo_Config(**ALGO_CONFIG)
|
||||||
|
|
||||||
ALGO_CONFIG.Config.Max_Target_Notional = float(min([ASTER.mult, EXTEND.mult]) * ALGO_CONFIG.Config.Target_Open_Cash_Position)
|
ALGO_CONFIG.Config.Max_Target_Notional = float(min([ASTER.mult, EXTEND.mult]) * ALGO_CONFIG.Config.Target_Open_Cash_Position)
|
||||||
|
# logging.info(f'Initial Algo Config: {ALGO_CONFIG}')
|
||||||
|
|
||||||
VAL_KEY.set(name='fr_orchestrator_output', value=json.dumps(obj=ALGO_CONFIG.model_dump()))
|
VAL_KEY.set(name='fr_orchestrator_output', value=json.dumps(obj=ALGO_CONFIG.model_dump()))
|
||||||
VAL_KEY.set(name='fr_algo_working_symbol', value=json.dumps(obj={'ASTER': asdict(obj=ASTER), 'EXTEND': asdict(obj=EXTEND)}))
|
VAL_KEY.set(name='fr_algo_working_symbol', value=json.dumps(obj={'ASTER': asdict(obj=ASTER), 'EXTEND': asdict(obj=EXTEND)}))
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import requests
|
|||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
|
import logging
|
||||||
import threading
|
import threading
|
||||||
from urllib import parse
|
from urllib import parse
|
||||||
|
|
||||||
@@ -90,7 +91,7 @@ async def post_authenticated_url(req: dict) -> list | dict:
|
|||||||
|
|
||||||
if method == 'GET':
|
if method == 'GET':
|
||||||
res: requests.Response = requests.get(url=full_url, headers=headers)
|
res: requests.Response = requests.get(url=full_url, headers=headers)
|
||||||
# print(res.status_code, res.text)
|
# logging.warning(res.status_code, res.text)
|
||||||
return res.json()
|
return res.json()
|
||||||
elif method == 'POST':
|
elif method == 'POST':
|
||||||
res: requests.Response = requests.post(url=full_url, headers=headers)
|
res: requests.Response = requests.post(url=full_url, headers=headers)
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ LEVERAGE_BY_EXCH: list[Asset_Leverage] = [
|
|||||||
Asset_Leverage('ASTER', 'SUI' , 'USDT', 75 , 5_416 ), Asset_Leverage('EXTEND', 'SUI' , 'USD', 50, 500_000 ),
|
Asset_Leverage('ASTER', 'SUI' , 'USDT', 75 , 5_416 ), Asset_Leverage('EXTEND', 'SUI' , 'USD', 50, 500_000 ),
|
||||||
Asset_Leverage('ASTER', 'TRUMP', 'USDT', 10 , 60_000 ), Asset_Leverage('EXTEND', 'TRUMP', 'USD', 25, 400_000 ),
|
Asset_Leverage('ASTER', 'TRUMP', 'USDT', 10 , 60_000 ), Asset_Leverage('EXTEND', 'TRUMP', 'USD', 25, 400_000 ),
|
||||||
Asset_Leverage('ASTER', 'WLFI' , 'USDT', 25 , 104_869), Asset_Leverage('EXTEND', 'WLFI' , 'USD', 10, 250_000 ),
|
Asset_Leverage('ASTER', 'WLFI' , 'USDT', 25 , 104_869), Asset_Leverage('EXTEND', 'WLFI' , 'USD', 10, 250_000 ),
|
||||||
Asset_Leverage('ASTER', 'XAG' , 'USDT', 100, 50_000 ), Asset_Leverage('EXTEND', 'XAG' , 'USD', 10, 1_000_000),
|
# Asset_Leverage('ASTER', 'XAG' , 'USDT', 100, 50_000 ), Asset_Leverage('EXTEND', 'XAG' , 'USD', 10, 1_000_000),
|
||||||
Asset_Leverage('ASTER', 'XAU' , 'USDT', 75 , 2_500 ), Asset_Leverage('EXTEND', 'XAU' , 'USD', 25, 2_000_000),
|
# Asset_Leverage('ASTER', 'XAU' , 'USDT', 75 , 2_500 ), Asset_Leverage('EXTEND', 'XAU' , 'USD', 25, 2_000_000),
|
||||||
Asset_Leverage('ASTER', 'XMR' , 'USDT', 50 , 10_000 ), Asset_Leverage('EXTEND', 'XMR' , 'USD', 25, 400_000 ),
|
Asset_Leverage('ASTER', 'XMR' , 'USDT', 50 , 10_000 ), Asset_Leverage('EXTEND', 'XMR' , 'USD', 25, 400_000 ),
|
||||||
Asset_Leverage('ASTER', 'XPT' , 'USDT', 3 , 30_000 ), Asset_Leverage('EXTEND', 'XPT' , 'USD', 5 , 1_000_000),
|
Asset_Leverage('ASTER', 'XPT' , 'USDT', 3 , 30_000 ), Asset_Leverage('EXTEND', 'XPT' , 'USD', 5 , 1_000_000),
|
||||||
Asset_Leverage('ASTER', 'XRP' , 'USDT', 100, 40_000 ), Asset_Leverage('EXTEND', 'XRP' , 'USD', 50, 500_000 ),
|
Asset_Leverage('ASTER', 'XRP' , 'USDT', 100, 40_000 ), Asset_Leverage('EXTEND', 'XRP' , 'USD', 50, 500_000 ),
|
||||||
|
|||||||
@@ -169,6 +169,8 @@ class Perpetual_Exchange:
|
|||||||
initial_funding_rate: float = 0
|
initial_funding_rate: float = 0
|
||||||
min_price: float = 0
|
min_price: float = 0
|
||||||
min_order_size: float = 0
|
min_order_size: float = 0
|
||||||
|
min_lot_size: float = 0
|
||||||
|
min_notional: float = 0
|
||||||
|
|
||||||
# async def update(self):
|
# async def update(self):
|
||||||
# await self.Collateral_Updates.update()
|
# await self.Collateral_Updates.update()
|
||||||
|
|||||||
619
pnl.ipynb
619
pnl.ipynb
@@ -2,7 +2,7 @@
|
|||||||
"cells": [
|
"cells": [
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 109,
|
"execution_count": 1,
|
||||||
"id": "44ff5c50",
|
"id": "44ff5c50",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
@@ -33,7 +33,38 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 111,
|
"execution_count": 19,
|
||||||
|
"id": "d3206fe9",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"start_ts = (round(datetime.now().timestamp()*1000)-(60*60*24*1000))"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 20,
|
||||||
|
"id": "9847869c",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"Timestamp('2026-05-01 22:56:30.744000')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 20,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"pd.to_datetime(start_ts, unit='ms')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 21,
|
||||||
"id": "ca48e11c",
|
"id": "ca48e11c",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
@@ -57,7 +88,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 112,
|
"execution_count": 22,
|
||||||
"id": "ec8f5d67",
|
"id": "ec8f5d67",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
@@ -82,7 +113,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 113,
|
"execution_count": 23,
|
||||||
"id": "1cb4869a",
|
"id": "1cb4869a",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
@@ -108,7 +139,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 119,
|
"execution_count": 24,
|
||||||
"id": "0ebf54b3",
|
"id": "0ebf54b3",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
@@ -140,7 +171,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 120,
|
"execution_count": 25,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
@@ -268,194 +299,168 @@
|
|||||||
"type": "float"
|
"type": "float"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"ref": "ba489ddb-f098-469d-8584-5f1564160359",
|
"ref": "4fed1e21-7dd2-454b-b923-48d479d7aa72",
|
||||||
"rows": [
|
"rows": [
|
||||||
[
|
[
|
||||||
"0",
|
"0",
|
||||||
"17371700930",
|
"328652716",
|
||||||
"2026-04-30 08:46:33.100000",
|
"2026-05-02 01:00:01.450000",
|
||||||
"FILLED",
|
"FILLED",
|
||||||
"BUY",
|
"BUY",
|
||||||
"0.441",
|
"551.0",
|
||||||
"0.0",
|
"0.0",
|
||||||
"2260.01",
|
"0.9059",
|
||||||
"True",
|
"True",
|
||||||
"2049778331801128960",
|
"2050627894673694720",
|
||||||
"2026-04-30 09:10:12.149000",
|
"2026-05-02 17:26:03.721000",
|
||||||
"FILLED",
|
"FILLED",
|
||||||
"SELL",
|
"SELL",
|
||||||
"0.441",
|
"273.0",
|
||||||
"0.24869",
|
"0.06208",
|
||||||
"2255.7",
|
"0.8957",
|
||||||
"False",
|
"False",
|
||||||
"2260.01",
|
"0.9059",
|
||||||
"2255.7",
|
"0.8957",
|
||||||
"0.441",
|
"551.0",
|
||||||
"0.441",
|
"273.0",
|
||||||
"ASTER",
|
"ASTER",
|
||||||
"-2.1494000000001763",
|
"-2.8466799999999965",
|
||||||
"-0.0019070712076496412"
|
"-0.5101158787853532"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"1",
|
"1",
|
||||||
"17372582002",
|
"329066650",
|
||||||
"2026-04-30 13:59:05",
|
"2026-05-02 17:25:57.700000",
|
||||||
"FILLED",
|
"FILLED",
|
||||||
"SELL",
|
"SELL",
|
||||||
"0.439",
|
"277.0",
|
||||||
"0.0",
|
"0.1007726",
|
||||||
"2262.5",
|
"0.9095",
|
||||||
"True",
|
"False",
|
||||||
"2049851052585218048",
|
"2050627894673694720",
|
||||||
"2026-04-30 13:59:15.023000",
|
"2026-05-02 17:26:03.721000",
|
||||||
"FILLED",
|
"FILLED",
|
||||||
"BUY",
|
"SELL",
|
||||||
"0.438",
|
"273.0",
|
||||||
"0.0",
|
"0.06208",
|
||||||
"2261.7",
|
"0.8957",
|
||||||
"True",
|
"False",
|
||||||
"2261.7",
|
"0.8957",
|
||||||
"2262.5",
|
"0.9095",
|
||||||
"0.438",
|
"273.0",
|
||||||
"0.439",
|
"277.0",
|
||||||
"EXTEND",
|
"EXTEND",
|
||||||
"0.35120000000007984",
|
"3.659747399999979",
|
||||||
"0.0026376288252886937"
|
"0.030284701714868006"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"2",
|
"2",
|
||||||
"17372999630",
|
"329183551",
|
||||||
"2026-04-30 15:32:12.700000",
|
"2026-05-02 21:42:27.900000",
|
||||||
"FILLED",
|
|
||||||
"BUY",
|
|
||||||
"0.438",
|
|
||||||
"0.0",
|
|
||||||
"2274.09",
|
|
||||||
"True",
|
|
||||||
"2049881470860271616",
|
|
||||||
"2026-04-30 16:00:02.415000",
|
|
||||||
"FILLED",
|
"FILLED",
|
||||||
"SELL",
|
"SELL",
|
||||||
"0.438",
|
"273.0",
|
||||||
"0.247886",
|
"0.0",
|
||||||
"2263.7",
|
"0.9126",
|
||||||
|
"True",
|
||||||
|
"2050694154048565248",
|
||||||
|
"2026-05-02 21:49:21.186000",
|
||||||
|
"FILLED",
|
||||||
|
"BUY",
|
||||||
|
"273.0",
|
||||||
|
"0.062319",
|
||||||
|
"0.9131",
|
||||||
"False",
|
"False",
|
||||||
"2274.09",
|
"0.9131",
|
||||||
"2263.7",
|
"0.9126",
|
||||||
"0.438",
|
"273.0",
|
||||||
"0.438",
|
"273.0",
|
||||||
"ASTER",
|
"EXTEND",
|
||||||
"-4.798706000000144",
|
"-0.1988190000000153",
|
||||||
"-0.00456886051123762"
|
"-0.0005475851494907951"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"3",
|
"3",
|
||||||
"17373094474",
|
"329195229",
|
||||||
"2026-04-30 16:00:02.050000",
|
"2026-05-02 22:08:49.450000",
|
||||||
"FILLED",
|
"FILLED",
|
||||||
"SELL",
|
"BUY",
|
||||||
"0.439",
|
"273.0",
|
||||||
"0.0",
|
"0.0",
|
||||||
"2264.61",
|
"0.9136",
|
||||||
"True",
|
"True",
|
||||||
"2049881470860271616",
|
"2050699055663546368",
|
||||||
"2026-04-30 16:00:02.415000",
|
"2026-05-02 22:08:49.823000",
|
||||||
"FILLED",
|
"FILLED",
|
||||||
"SELL",
|
"SELL",
|
||||||
"0.438",
|
"272.0",
|
||||||
"0.247886",
|
"0.062056",
|
||||||
"2263.7",
|
"0.9123",
|
||||||
"False",
|
"False",
|
||||||
"2263.7",
|
"0.9136",
|
||||||
"2264.61",
|
"0.9123",
|
||||||
"0.438",
|
"273.0",
|
||||||
"0.439",
|
"272.0",
|
||||||
"EXTEND",
|
"ASTER",
|
||||||
"0.15160400000013574",
|
"-0.41565599999999125",
|
||||||
"0.002686019554602488"
|
"-0.005080733627143444"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"4",
|
"4",
|
||||||
"17373547036",
|
"329206619",
|
||||||
"2026-04-30 19:06:50.200000",
|
"2026-05-02 22:33:28.550000",
|
||||||
"FILLED",
|
|
||||||
"BUY",
|
|
||||||
"0.442",
|
|
||||||
"0.0",
|
|
||||||
"2260.48",
|
|
||||||
"True",
|
|
||||||
"2049929626042335232",
|
|
||||||
"2026-04-30 19:11:23.505000",
|
|
||||||
"FILLED",
|
"FILLED",
|
||||||
"SELL",
|
"SELL",
|
||||||
"0.441",
|
"274.0",
|
||||||
"0.24944",
|
"0.0",
|
||||||
"2262.5",
|
"0.9106",
|
||||||
"False",
|
"True",
|
||||||
"2260.48",
|
"2050705268467499008",
|
||||||
"2262.5",
|
"2026-05-02 22:33:52.752000",
|
||||||
"0.442",
|
"FILLED",
|
||||||
"0.441",
|
"BUY",
|
||||||
"ASTER",
|
"274.0",
|
||||||
"0.641379999999992",
|
"0.0",
|
||||||
"-0.0013708496781846692"
|
"0.9105",
|
||||||
|
"True",
|
||||||
|
"0.9105",
|
||||||
|
"0.9106",
|
||||||
|
"274.0",
|
||||||
|
"274.0",
|
||||||
|
"EXTEND",
|
||||||
|
"0.027399999999996982",
|
||||||
|
"0.00010982976386600805"
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"5",
|
"5",
|
||||||
"17373827670",
|
"329210143",
|
||||||
"2026-04-30 21:48:38.550000",
|
"2026-05-02 22:41:58.300000",
|
||||||
"FILLED",
|
"FILLED",
|
||||||
"SELL",
|
"SELL",
|
||||||
"0.221",
|
"274.0",
|
||||||
"0.0",
|
"0.0",
|
||||||
"2257.17",
|
"0.912",
|
||||||
"True",
|
"True",
|
||||||
"2049969423813185536",
|
"2050707405608058880",
|
||||||
"2026-04-30 21:49:32.034000",
|
"2026-05-02 22:42:05.138000",
|
||||||
"FILLED",
|
"FILLED",
|
||||||
"BUY",
|
"BUY",
|
||||||
"0.22",
|
"274.0",
|
||||||
"0.124041",
|
|
||||||
"2255.4",
|
|
||||||
"False",
|
|
||||||
"2255.4",
|
|
||||||
"2257.17",
|
|
||||||
"0.22",
|
|
||||||
"0.221",
|
|
||||||
"EXTEND",
|
|
||||||
"0.26712899999999595",
|
|
||||||
"0.0053338049287769895"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"6",
|
|
||||||
"17373941409",
|
|
||||||
"2026-04-30 23:01:21.150000",
|
|
||||||
"FILLED",
|
|
||||||
"SELL",
|
|
||||||
"0.221",
|
|
||||||
"0.0",
|
"0.0",
|
||||||
"2253.58",
|
"0.9117",
|
||||||
"True",
|
"True",
|
||||||
"2049987504752680960",
|
"0.9117",
|
||||||
"2026-04-30 23:03:53.771000",
|
"0.912",
|
||||||
"FILLED",
|
"274.0",
|
||||||
"BUY",
|
"274.0",
|
||||||
"0.221",
|
|
||||||
"0.0",
|
|
||||||
"2252.6",
|
|
||||||
"True",
|
|
||||||
"2252.6",
|
|
||||||
"2253.58",
|
|
||||||
"0.221",
|
|
||||||
"0.221",
|
|
||||||
"EXTEND",
|
"EXTEND",
|
||||||
"0.21658000000000402",
|
"0.08220000000002137",
|
||||||
"0.0004350528278434247"
|
"0.0003290556103982722"
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"shape": {
|
"shape": {
|
||||||
"columns": 23,
|
"columns": 23,
|
||||||
"rows": 7
|
"rows": 6
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"text/html": [
|
"text/html": [
|
||||||
@@ -503,227 +508,198 @@
|
|||||||
" <tbody>\n",
|
" <tbody>\n",
|
||||||
" <tr>\n",
|
" <tr>\n",
|
||||||
" <th>0</th>\n",
|
" <th>0</th>\n",
|
||||||
" <td>17371700930</td>\n",
|
" <td>328652716</td>\n",
|
||||||
" <td>2026-04-30 08:46:33.100</td>\n",
|
" <td>2026-05-02 01:00:01.450</td>\n",
|
||||||
" <td>FILLED</td>\n",
|
" <td>FILLED</td>\n",
|
||||||
" <td>BUY</td>\n",
|
" <td>BUY</td>\n",
|
||||||
" <td>0.441</td>\n",
|
" <td>551.0</td>\n",
|
||||||
" <td>0.0</td>\n",
|
" <td>0.000000</td>\n",
|
||||||
" <td>2260.01</td>\n",
|
" <td>0.9059</td>\n",
|
||||||
" <td>True</td>\n",
|
" <td>True</td>\n",
|
||||||
" <td>2049778331801128960</td>\n",
|
" <td>2050627894673694720</td>\n",
|
||||||
" <td>2026-04-30 09:10:12.149</td>\n",
|
" <td>2026-05-02 17:26:03.721</td>\n",
|
||||||
" <td>...</td>\n",
|
" <td>...</td>\n",
|
||||||
" <td>0.248690</td>\n",
|
" <td>0.062080</td>\n",
|
||||||
" <td>2255.7</td>\n",
|
" <td>0.8957</td>\n",
|
||||||
" <td>False</td>\n",
|
" <td>False</td>\n",
|
||||||
" <td>2260.01</td>\n",
|
" <td>0.9059</td>\n",
|
||||||
" <td>2255.70</td>\n",
|
" <td>0.8957</td>\n",
|
||||||
" <td>0.441</td>\n",
|
" <td>551.0</td>\n",
|
||||||
" <td>0.441</td>\n",
|
" <td>273.0</td>\n",
|
||||||
" <td>ASTER</td>\n",
|
" <td>ASTER</td>\n",
|
||||||
" <td>-2.149400</td>\n",
|
" <td>-2.846680</td>\n",
|
||||||
" <td>-0.001907</td>\n",
|
" <td>-0.510116</td>\n",
|
||||||
" </tr>\n",
|
" </tr>\n",
|
||||||
" <tr>\n",
|
" <tr>\n",
|
||||||
" <th>1</th>\n",
|
" <th>1</th>\n",
|
||||||
" <td>17372582002</td>\n",
|
" <td>329066650</td>\n",
|
||||||
" <td>2026-04-30 13:59:05.000</td>\n",
|
" <td>2026-05-02 17:25:57.700</td>\n",
|
||||||
" <td>FILLED</td>\n",
|
" <td>FILLED</td>\n",
|
||||||
" <td>SELL</td>\n",
|
" <td>SELL</td>\n",
|
||||||
" <td>0.439</td>\n",
|
" <td>277.0</td>\n",
|
||||||
" <td>0.0</td>\n",
|
" <td>0.100773</td>\n",
|
||||||
" <td>2262.50</td>\n",
|
" <td>0.9095</td>\n",
|
||||||
" <td>True</td>\n",
|
" <td>False</td>\n",
|
||||||
" <td>2049851052585218048</td>\n",
|
" <td>2050627894673694720</td>\n",
|
||||||
" <td>2026-04-30 13:59:15.023</td>\n",
|
" <td>2026-05-02 17:26:03.721</td>\n",
|
||||||
" <td>...</td>\n",
|
" <td>...</td>\n",
|
||||||
" <td>0.000000</td>\n",
|
" <td>0.062080</td>\n",
|
||||||
" <td>2261.7</td>\n",
|
" <td>0.8957</td>\n",
|
||||||
" <td>True</td>\n",
|
" <td>False</td>\n",
|
||||||
" <td>2261.70</td>\n",
|
" <td>0.8957</td>\n",
|
||||||
" <td>2262.50</td>\n",
|
" <td>0.9095</td>\n",
|
||||||
" <td>0.438</td>\n",
|
" <td>273.0</td>\n",
|
||||||
" <td>0.439</td>\n",
|
" <td>277.0</td>\n",
|
||||||
" <td>EXTEND</td>\n",
|
" <td>EXTEND</td>\n",
|
||||||
" <td>0.351200</td>\n",
|
" <td>3.659747</td>\n",
|
||||||
" <td>0.002638</td>\n",
|
" <td>0.030285</td>\n",
|
||||||
" </tr>\n",
|
" </tr>\n",
|
||||||
" <tr>\n",
|
" <tr>\n",
|
||||||
" <th>2</th>\n",
|
" <th>2</th>\n",
|
||||||
" <td>17372999630</td>\n",
|
" <td>329183551</td>\n",
|
||||||
" <td>2026-04-30 15:32:12.700</td>\n",
|
" <td>2026-05-02 21:42:27.900</td>\n",
|
||||||
" <td>FILLED</td>\n",
|
" <td>FILLED</td>\n",
|
||||||
" <td>BUY</td>\n",
|
" <td>SELL</td>\n",
|
||||||
" <td>0.438</td>\n",
|
" <td>273.0</td>\n",
|
||||||
" <td>0.0</td>\n",
|
" <td>0.000000</td>\n",
|
||||||
" <td>2274.09</td>\n",
|
" <td>0.9126</td>\n",
|
||||||
" <td>True</td>\n",
|
" <td>True</td>\n",
|
||||||
" <td>2049881470860271616</td>\n",
|
" <td>2050694154048565248</td>\n",
|
||||||
" <td>2026-04-30 16:00:02.415</td>\n",
|
" <td>2026-05-02 21:49:21.186</td>\n",
|
||||||
" <td>...</td>\n",
|
" <td>...</td>\n",
|
||||||
" <td>0.247886</td>\n",
|
" <td>0.062319</td>\n",
|
||||||
" <td>2263.7</td>\n",
|
" <td>0.9131</td>\n",
|
||||||
" <td>False</td>\n",
|
" <td>False</td>\n",
|
||||||
" <td>2274.09</td>\n",
|
" <td>0.9131</td>\n",
|
||||||
" <td>2263.70</td>\n",
|
" <td>0.9126</td>\n",
|
||||||
" <td>0.438</td>\n",
|
" <td>273.0</td>\n",
|
||||||
" <td>0.438</td>\n",
|
" <td>273.0</td>\n",
|
||||||
" <td>ASTER</td>\n",
|
" <td>EXTEND</td>\n",
|
||||||
" <td>-4.798706</td>\n",
|
" <td>-0.198819</td>\n",
|
||||||
" <td>-0.004569</td>\n",
|
" <td>-0.000548</td>\n",
|
||||||
" </tr>\n",
|
" </tr>\n",
|
||||||
" <tr>\n",
|
" <tr>\n",
|
||||||
" <th>3</th>\n",
|
" <th>3</th>\n",
|
||||||
" <td>17373094474</td>\n",
|
" <td>329195229</td>\n",
|
||||||
" <td>2026-04-30 16:00:02.050</td>\n",
|
" <td>2026-05-02 22:08:49.450</td>\n",
|
||||||
" <td>FILLED</td>\n",
|
" <td>FILLED</td>\n",
|
||||||
" <td>SELL</td>\n",
|
" <td>BUY</td>\n",
|
||||||
" <td>0.439</td>\n",
|
" <td>273.0</td>\n",
|
||||||
" <td>0.0</td>\n",
|
" <td>0.000000</td>\n",
|
||||||
" <td>2264.61</td>\n",
|
" <td>0.9136</td>\n",
|
||||||
" <td>True</td>\n",
|
" <td>True</td>\n",
|
||||||
" <td>2049881470860271616</td>\n",
|
" <td>2050699055663546368</td>\n",
|
||||||
" <td>2026-04-30 16:00:02.415</td>\n",
|
" <td>2026-05-02 22:08:49.823</td>\n",
|
||||||
" <td>...</td>\n",
|
" <td>...</td>\n",
|
||||||
" <td>0.247886</td>\n",
|
" <td>0.062056</td>\n",
|
||||||
" <td>2263.7</td>\n",
|
" <td>0.9123</td>\n",
|
||||||
" <td>False</td>\n",
|
" <td>False</td>\n",
|
||||||
" <td>2263.70</td>\n",
|
" <td>0.9136</td>\n",
|
||||||
" <td>2264.61</td>\n",
|
" <td>0.9123</td>\n",
|
||||||
" <td>0.438</td>\n",
|
" <td>273.0</td>\n",
|
||||||
" <td>0.439</td>\n",
|
" <td>272.0</td>\n",
|
||||||
" <td>EXTEND</td>\n",
|
" <td>ASTER</td>\n",
|
||||||
" <td>0.151604</td>\n",
|
" <td>-0.415656</td>\n",
|
||||||
" <td>0.002686</td>\n",
|
" <td>-0.005081</td>\n",
|
||||||
" </tr>\n",
|
" </tr>\n",
|
||||||
" <tr>\n",
|
" <tr>\n",
|
||||||
" <th>4</th>\n",
|
" <th>4</th>\n",
|
||||||
" <td>17373547036</td>\n",
|
" <td>329206619</td>\n",
|
||||||
" <td>2026-04-30 19:06:50.200</td>\n",
|
" <td>2026-05-02 22:33:28.550</td>\n",
|
||||||
" <td>FILLED</td>\n",
|
" <td>FILLED</td>\n",
|
||||||
" <td>BUY</td>\n",
|
" <td>SELL</td>\n",
|
||||||
" <td>0.442</td>\n",
|
" <td>274.0</td>\n",
|
||||||
" <td>0.0</td>\n",
|
" <td>0.000000</td>\n",
|
||||||
" <td>2260.48</td>\n",
|
" <td>0.9106</td>\n",
|
||||||
" <td>True</td>\n",
|
" <td>True</td>\n",
|
||||||
" <td>2049929626042335232</td>\n",
|
" <td>2050705268467499008</td>\n",
|
||||||
" <td>2026-04-30 19:11:23.505</td>\n",
|
" <td>2026-05-02 22:33:52.752</td>\n",
|
||||||
" <td>...</td>\n",
|
" <td>...</td>\n",
|
||||||
" <td>0.249440</td>\n",
|
" <td>0.000000</td>\n",
|
||||||
" <td>2262.5</td>\n",
|
" <td>0.9105</td>\n",
|
||||||
" <td>False</td>\n",
|
" <td>True</td>\n",
|
||||||
" <td>2260.48</td>\n",
|
" <td>0.9105</td>\n",
|
||||||
" <td>2262.50</td>\n",
|
" <td>0.9106</td>\n",
|
||||||
" <td>0.442</td>\n",
|
" <td>274.0</td>\n",
|
||||||
" <td>0.441</td>\n",
|
" <td>274.0</td>\n",
|
||||||
" <td>ASTER</td>\n",
|
" <td>EXTEND</td>\n",
|
||||||
" <td>0.641380</td>\n",
|
" <td>0.027400</td>\n",
|
||||||
" <td>-0.001371</td>\n",
|
" <td>0.000110</td>\n",
|
||||||
" </tr>\n",
|
" </tr>\n",
|
||||||
" <tr>\n",
|
" <tr>\n",
|
||||||
" <th>5</th>\n",
|
" <th>5</th>\n",
|
||||||
" <td>17373827670</td>\n",
|
" <td>329210143</td>\n",
|
||||||
" <td>2026-04-30 21:48:38.550</td>\n",
|
" <td>2026-05-02 22:41:58.300</td>\n",
|
||||||
" <td>FILLED</td>\n",
|
" <td>FILLED</td>\n",
|
||||||
" <td>SELL</td>\n",
|
" <td>SELL</td>\n",
|
||||||
" <td>0.221</td>\n",
|
" <td>274.0</td>\n",
|
||||||
" <td>0.0</td>\n",
|
" <td>0.000000</td>\n",
|
||||||
" <td>2257.17</td>\n",
|
" <td>0.9120</td>\n",
|
||||||
" <td>True</td>\n",
|
" <td>True</td>\n",
|
||||||
" <td>2049969423813185536</td>\n",
|
" <td>2050707405608058880</td>\n",
|
||||||
" <td>2026-04-30 21:49:32.034</td>\n",
|
" <td>2026-05-02 22:42:05.138</td>\n",
|
||||||
" <td>...</td>\n",
|
|
||||||
" <td>0.124041</td>\n",
|
|
||||||
" <td>2255.4</td>\n",
|
|
||||||
" <td>False</td>\n",
|
|
||||||
" <td>2255.40</td>\n",
|
|
||||||
" <td>2257.17</td>\n",
|
|
||||||
" <td>0.220</td>\n",
|
|
||||||
" <td>0.221</td>\n",
|
|
||||||
" <td>EXTEND</td>\n",
|
|
||||||
" <td>0.267129</td>\n",
|
|
||||||
" <td>0.005334</td>\n",
|
|
||||||
" </tr>\n",
|
|
||||||
" <tr>\n",
|
|
||||||
" <th>6</th>\n",
|
|
||||||
" <td>17373941409</td>\n",
|
|
||||||
" <td>2026-04-30 23:01:21.150</td>\n",
|
|
||||||
" <td>FILLED</td>\n",
|
|
||||||
" <td>SELL</td>\n",
|
|
||||||
" <td>0.221</td>\n",
|
|
||||||
" <td>0.0</td>\n",
|
|
||||||
" <td>2253.58</td>\n",
|
|
||||||
" <td>True</td>\n",
|
|
||||||
" <td>2049987504752680960</td>\n",
|
|
||||||
" <td>2026-04-30 23:03:53.771</td>\n",
|
|
||||||
" <td>...</td>\n",
|
" <td>...</td>\n",
|
||||||
" <td>0.000000</td>\n",
|
" <td>0.000000</td>\n",
|
||||||
" <td>2252.6</td>\n",
|
" <td>0.9117</td>\n",
|
||||||
" <td>True</td>\n",
|
" <td>True</td>\n",
|
||||||
" <td>2252.60</td>\n",
|
" <td>0.9117</td>\n",
|
||||||
" <td>2253.58</td>\n",
|
" <td>0.9120</td>\n",
|
||||||
" <td>0.221</td>\n",
|
" <td>274.0</td>\n",
|
||||||
" <td>0.221</td>\n",
|
" <td>274.0</td>\n",
|
||||||
" <td>EXTEND</td>\n",
|
" <td>EXTEND</td>\n",
|
||||||
" <td>0.216580</td>\n",
|
" <td>0.082200</td>\n",
|
||||||
" <td>0.000435</td>\n",
|
" <td>0.000329</td>\n",
|
||||||
" </tr>\n",
|
" </tr>\n",
|
||||||
" </tbody>\n",
|
" </tbody>\n",
|
||||||
"</table>\n",
|
"</table>\n",
|
||||||
"<p>7 rows × 23 columns</p>\n",
|
"<p>6 rows × 23 columns</p>\n",
|
||||||
"</div>"
|
"</div>"
|
||||||
],
|
],
|
||||||
"text/plain": [
|
"text/plain": [
|
||||||
" order_id_ast timestamp_ts_ast status_ast side_ast filled_qty_ast \\\n",
|
" order_id_ast timestamp_ts_ast status_ast side_ast filled_qty_ast \\\n",
|
||||||
"0 17371700930 2026-04-30 08:46:33.100 FILLED BUY 0.441 \n",
|
"0 328652716 2026-05-02 01:00:01.450 FILLED BUY 551.0 \n",
|
||||||
"1 17372582002 2026-04-30 13:59:05.000 FILLED SELL 0.439 \n",
|
"1 329066650 2026-05-02 17:25:57.700 FILLED SELL 277.0 \n",
|
||||||
"2 17372999630 2026-04-30 15:32:12.700 FILLED BUY 0.438 \n",
|
"2 329183551 2026-05-02 21:42:27.900 FILLED SELL 273.0 \n",
|
||||||
"3 17373094474 2026-04-30 16:00:02.050 FILLED SELL 0.439 \n",
|
"3 329195229 2026-05-02 22:08:49.450 FILLED BUY 273.0 \n",
|
||||||
"4 17373547036 2026-04-30 19:06:50.200 FILLED BUY 0.442 \n",
|
"4 329206619 2026-05-02 22:33:28.550 FILLED SELL 274.0 \n",
|
||||||
"5 17373827670 2026-04-30 21:48:38.550 FILLED SELL 0.221 \n",
|
"5 329210143 2026-05-02 22:41:58.300 FILLED SELL 274.0 \n",
|
||||||
"6 17373941409 2026-04-30 23:01:21.150 FILLED SELL 0.221 \n",
|
|
||||||
"\n",
|
"\n",
|
||||||
" payed_fee_ast price_ast is_mkt_maker_ast order_id_ext \\\n",
|
" payed_fee_ast price_ast is_mkt_maker_ast order_id_ext \\\n",
|
||||||
"0 0.0 2260.01 True 2049778331801128960 \n",
|
"0 0.000000 0.9059 True 2050627894673694720 \n",
|
||||||
"1 0.0 2262.50 True 2049851052585218048 \n",
|
"1 0.100773 0.9095 False 2050627894673694720 \n",
|
||||||
"2 0.0 2274.09 True 2049881470860271616 \n",
|
"2 0.000000 0.9126 True 2050694154048565248 \n",
|
||||||
"3 0.0 2264.61 True 2049881470860271616 \n",
|
"3 0.000000 0.9136 True 2050699055663546368 \n",
|
||||||
"4 0.0 2260.48 True 2049929626042335232 \n",
|
"4 0.000000 0.9106 True 2050705268467499008 \n",
|
||||||
"5 0.0 2257.17 True 2049969423813185536 \n",
|
"5 0.000000 0.9120 True 2050707405608058880 \n",
|
||||||
"6 0.0 2253.58 True 2049987504752680960 \n",
|
|
||||||
"\n",
|
"\n",
|
||||||
" timestamp_ts_ext ... payed_fee_ext price_ext is_mkt_maker_ext \\\n",
|
" timestamp_ts_ext ... payed_fee_ext price_ext is_mkt_maker_ext \\\n",
|
||||||
"0 2026-04-30 09:10:12.149 ... 0.248690 2255.7 False \n",
|
"0 2026-05-02 17:26:03.721 ... 0.062080 0.8957 False \n",
|
||||||
"1 2026-04-30 13:59:15.023 ... 0.000000 2261.7 True \n",
|
"1 2026-05-02 17:26:03.721 ... 0.062080 0.8957 False \n",
|
||||||
"2 2026-04-30 16:00:02.415 ... 0.247886 2263.7 False \n",
|
"2 2026-05-02 21:49:21.186 ... 0.062319 0.9131 False \n",
|
||||||
"3 2026-04-30 16:00:02.415 ... 0.247886 2263.7 False \n",
|
"3 2026-05-02 22:08:49.823 ... 0.062056 0.9123 False \n",
|
||||||
"4 2026-04-30 19:11:23.505 ... 0.249440 2262.5 False \n",
|
"4 2026-05-02 22:33:52.752 ... 0.000000 0.9105 True \n",
|
||||||
"5 2026-04-30 21:49:32.034 ... 0.124041 2255.4 False \n",
|
"5 2026-05-02 22:42:05.138 ... 0.000000 0.9117 True \n",
|
||||||
"6 2026-04-30 23:03:53.771 ... 0.000000 2252.6 True \n",
|
|
||||||
"\n",
|
"\n",
|
||||||
" buy_price sell_price buy_qty sell_qty buy_side per_trade_pnl \\\n",
|
" buy_price sell_price buy_qty sell_qty buy_side per_trade_pnl \\\n",
|
||||||
"0 2260.01 2255.70 0.441 0.441 ASTER -2.149400 \n",
|
"0 0.9059 0.8957 551.0 273.0 ASTER -2.846680 \n",
|
||||||
"1 2261.70 2262.50 0.438 0.439 EXTEND 0.351200 \n",
|
"1 0.8957 0.9095 273.0 277.0 EXTEND 3.659747 \n",
|
||||||
"2 2274.09 2263.70 0.438 0.438 ASTER -4.798706 \n",
|
"2 0.9131 0.9126 273.0 273.0 EXTEND -0.198819 \n",
|
||||||
"3 2263.70 2264.61 0.438 0.439 EXTEND 0.151604 \n",
|
"3 0.9136 0.9123 273.0 272.0 ASTER -0.415656 \n",
|
||||||
"4 2260.48 2262.50 0.442 0.441 ASTER 0.641380 \n",
|
"4 0.9105 0.9106 274.0 274.0 EXTEND 0.027400 \n",
|
||||||
"5 2255.40 2257.17 0.220 0.221 EXTEND 0.267129 \n",
|
"5 0.9117 0.9120 274.0 274.0 EXTEND 0.082200 \n",
|
||||||
"6 2252.60 2253.58 0.221 0.221 EXTEND 0.216580 \n",
|
|
||||||
"\n",
|
"\n",
|
||||||
" per_trade_pnl_pct \n",
|
" per_trade_pnl_pct \n",
|
||||||
"0 -0.001907 \n",
|
"0 -0.510116 \n",
|
||||||
"1 0.002638 \n",
|
"1 0.030285 \n",
|
||||||
"2 -0.004569 \n",
|
"2 -0.000548 \n",
|
||||||
"3 0.002686 \n",
|
"3 -0.005081 \n",
|
||||||
"4 -0.001371 \n",
|
"4 0.000110 \n",
|
||||||
"5 0.005334 \n",
|
"5 0.000329 \n",
|
||||||
"6 0.000435 \n",
|
|
||||||
"\n",
|
"\n",
|
||||||
"[7 rows x 23 columns]"
|
"[6 rows x 23 columns]"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 120,
|
"execution_count": 25,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
@@ -734,7 +710,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 116,
|
"execution_count": 18,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
@@ -760,17 +736,13 @@
|
|||||||
"showlegend": false,
|
"showlegend": false,
|
||||||
"type": "scatter",
|
"type": "scatter",
|
||||||
"x": [
|
"x": [
|
||||||
"2026-04-30T09:10:12.149000",
|
"2026-05-02T22:08:49.823000",
|
||||||
"2026-04-30T13:59:15.023000",
|
"2026-05-02T22:33:52.752000",
|
||||||
"2026-04-30T16:00:02.415000",
|
"2026-05-02T22:42:05.138000"
|
||||||
"2026-04-30T16:00:02.415000",
|
|
||||||
"2026-04-30T19:11:23.505000",
|
|
||||||
"2026-04-30T21:49:32.034000",
|
|
||||||
"2026-04-30T23:03:53.771000"
|
|
||||||
],
|
],
|
||||||
"xaxis": "x",
|
"xaxis": "x",
|
||||||
"y": {
|
"y": {
|
||||||
"bdata": "bS+QoPgxAcA3wZaQD3rWP3d6VPzfMRPAQMD4hsJnwz/J3olZL4bkP+wKtDukGNE/gd17uOS4yz8=",
|
"bdata": "fraYnxua2r+APKTfvg6cP/A1uycPC7U/",
|
||||||
"dtype": "f8"
|
"dtype": "f8"
|
||||||
},
|
},
|
||||||
"yaxis": "y"
|
"yaxis": "y"
|
||||||
@@ -1608,16 +1580,41 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": null,
|
"execution_count": 27,
|
||||||
"id": "1827a1ca",
|
"id": "1827a1ca",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"j = \"[{'timestamp_arrival': 1777762804677, 'timestamp_msg': 1777762804673, 'timestamp_transaction': 1777762804650, 'event_reason_type': 'ORDER', 'symbol': 'LITUSDT', 'position_amount': 0.0, 'entry_price': 0.0, 'accumulated_realized_pre_fees': 2.0749, 'unrealized_pnl': 0.0, 'margin_type': 'cross', 'isolated_wallet': 0.0, 'position_side': 'BOTH'}]\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "77f27d2f",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "6bd8f38d",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "f1a0e1a1",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
"source": []
|
"source": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": null,
|
"execution_count": null,
|
||||||
"id": "a0380428",
|
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [],
|
||||||
"source": []
|
"source": []
|
||||||
|
|||||||
Reference in New Issue
Block a user