added extend symbol change for ws

This commit is contained in:
2026-04-30 04:32:49 +00:00
parent dc3409ac40
commit 1ac0909c21
20 changed files with 28960 additions and 1221 deletions

View File

@@ -4,53 +4,27 @@ import logging
import os
import time
import traceback
from dataclasses import dataclass, field
from dataclasses import asdict
from datetime import datetime
from typing import AsyncContextManager
import modules.structs as structs
import pandas as pd
import requests
import valkey
from dotenv import load_dotenv
# from sqlalchemy.ext.asyncio import create_async_engine
### Structs ###
@dataclass(kw_only=False)
class Asset_Leverage:
exchange: str
lh_asset: str
rh_asset: str
max_leverage: int
max_notional: float
# max_leverage_notional: list = field(default_factory=list)
import modules.manual_leverage as leverage
### MANUAL LEVERAGE DATA ###
LEVERAGE_BY_EXCH: list[Asset_Leverage] = [
Asset_Leverage('ASTER', 'BTC' , 'USDT', 150, 300_000), Asset_Leverage('EXTEND', 'BTC' , 'USD', 50, 4_000_000),
Asset_Leverage('ASTER', 'ETH' , 'USDT', 150, 300_000), Asset_Leverage('EXTEND', 'ETH' , 'USD', 50, 4_000_000),
Asset_Leverage('ASTER', 'LIT' , 'USDT', 50 , 2_500 ), Asset_Leverage('EXTEND', 'LIT' , 'USD', 25, 400_000 ),
Asset_Leverage('ASTER', 'CHIP' , 'USDT', 50 , 5_000 ), Asset_Leverage('EXTEND', 'CHIP' , 'USD', 5 , 100_000 ),
Asset_Leverage('ASTER', 'XAG' , 'USDT', 100, 50_000 ), Asset_Leverage('EXTEND', 'XAG' , 'USD', 10, 1_000_000),
Asset_Leverage('ASTER', '4' , 'USDT', 50 , 5_000 ), Asset_Leverage('EXTEND', '4' , 'USD', 5 , 100_000 ),
Asset_Leverage('ASTER', 'XPT' , 'USDT', 3 , 30_000 ), Asset_Leverage('EXTEND', 'XPT' , 'USD', 5 , 1_000_000),
Asset_Leverage('ASTER', 'XMR' , 'USDT', 50 , 10_000 ), Asset_Leverage('EXTEND', 'XMR' , 'USD', 25, 400_000 ),
Asset_Leverage('ASTER', 'WLFI' , 'USDT', 25 , 104_869), Asset_Leverage('EXTEND', 'WLFI' , 'USD', 10, 250_000 ),
Asset_Leverage('ASTER', 'TRUMP', 'USDT', 50 , 5_567 ), Asset_Leverage('EXTEND', 'TRUMP', 'USD', 25, 400_000 ),
Asset_Leverage('ASTER', 'INIT' , 'USDT', 50 , 5_000 ), Asset_Leverage('EXTEND', 'INIT' , 'USD', 5 , 100_000 ),
Asset_Leverage('ASTER', 'ZORA' , 'USDT', 5 , 100_000), Asset_Leverage('EXTEND', 'ZORA' , 'USD', 5 , 100_000 ),
Asset_Leverage('ASTER', 'ZEC' , 'USDT', 75 , 6_250 ), Asset_Leverage('EXTEND', 'ZEC' , 'USD', 10, 250_000 ),
]
df_leverage_by_exch = pd.DataFrame(LEVERAGE_BY_EXCH)
df_leverage_by_exch = pd.DataFrame(data=leverage.LEVERAGE_BY_EXCH)
### Database ###
# CON: AsyncContextManager | None = None
VAL_KEY = None
VK_OUT = 'fr_engine_best_fund_rate_output'
VAL_KEY: valkey.Valkey
VK_OUT: str = 'fr_engine_best_fund_rate_output'
### Logging ###
load_dotenv()
LOG_FILEPATH: str = os.getenv("LOGS_PATH") + '/Fund_Rate_Engine_BFR.log'
LOG_FILEPATH: str = f'{os.getenv(key="LOGS_PATH")}/Fund_Rate_Engine_BFR.log'
### CONSTANTS ###
LOOP_SLEEP_SEC: int = 5
@@ -65,9 +39,9 @@ Mkt_Volume_Last_Refresh_TS_ms: int
def get_extended_markets_info() -> pd.DataFrame:
global Mkt_Info_Last_Refresh_TS_ms
r = json.loads(requests.get('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)
df = pd.DataFrame(r['data'])
df: pd.DataFrame = pd.DataFrame(data=r['data'])
df['funding_rate'] = df['marketStats'].apply(lambda x: x.get('fundingRate',{}))
df['funding_rate_ts'] = df['marketStats'].apply(lambda x: x.get('nextFundingRate',{}))
df['min_order_size'] = df['tradingConfig'].apply(lambda x: x.get('minOrderSize',{}))
@@ -81,9 +55,9 @@ def get_extended_markets_info() -> pd.DataFrame:
return df
def load_aster_current_fr() -> pd.DataFrame:
df = pd.DataFrame(json.loads(VAL_KEY.get('fund_rate_aster_all')))
df = pd.DataFrame(data=json.loads(s=VAL_KEY.get(name='fund_rate_aster_all'))) # ty:ignore[invalid-argument-type]
df = df[['s','E','r','T']].rename({'s':'symbol','E':'funding_rate_updated_ts_ms','r':'funding_rate','T':'next_funding_ts'}, axis=1)
df: pd.DataFrame = df[['s','E','r','T']].rename({'s':'symbol','E':'funding_rate_updated_ts_ms','r':'funding_rate','T':'next_funding_ts'}, axis=1)
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['time_delta_to_next_funding'] = pd.to_datetime(df['next_funding_ts'], unit='ms') - pd.Timestamp.now()
@@ -91,17 +65,17 @@ def load_aster_current_fr() -> pd.DataFrame:
return df
def load_extend_current_fr(df_mkt_stats: pd.DataFrame) -> pd.DataFrame:
df = pd.DataFrame(json.loads(VAL_KEY.get('fund_rate_extended_all')))
df = pd.DataFrame(data=json.loads(s=VAL_KEY.get(name='fund_rate_extended_all'))) # ty:ignore[invalid-argument-type]
df = 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'] = df['funding_rate'].astype(float)
df = df.merge(df_mkt_stats[['name','assetName','status', 'funding_rate_ts','max_leverage']].rename({'name':'symbol','funding_rate_ts':'next_funding_ts'}, axis=1), on='symbol', how='left')
df = df.loc[df['status']=='ACTIVE',:]
df: pd.DataFrame = df.merge(df_mkt_stats[['name','assetName','status', 'funding_rate_ts']].rename({'name':'symbol','funding_rate_ts':'next_funding_ts'}, axis=1), on='symbol', how='left')
df: pd.DataFrame = df.loc[df['status']=='ACTIVE',:]
df['USDT_Symbol'] = df['assetName'] + 'USDT'
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(arg=df['next_funding_ts'], unit='ms') - pd.Timestamp.now()
return df
@@ -124,25 +98,40 @@ async def loop() -> None:
df_comb_fr['net_funding_rate_abs'] = df_comb_fr['net_funding_rate'].abs()
### NET MULT ###
df_comb_fr = df_comb_fr.merge(df_leverage_by_exch.loc[df_leverage_by_exch['exchange']=='EXTEND'], left_on='assetName', right_on='lh_asset').merge(df_leverage_by_exch.loc[df_leverage_by_exch['exchange']=='ASTER'], left_on='assetName', right_on='lh_asset', suffixes=('_ext', '_ast'))
df_comb_fr = df_comb_fr.merge(right=df_leverage_by_exch.loc[df_leverage_by_exch['exchange']=='EXTEND'], left_on='assetName', right_on='lh_asset').merge(df_leverage_by_exch.loc[df_leverage_by_exch['exchange']=='ASTER'], left_on='assetName', right_on='lh_asset', suffixes=('_ext', '_ast'))
df_comb_fr['net_mult'] = 1 / ( ( 0.5 / df_comb_fr['max_leverage_ext'] ) + ( 0.5 / df_comb_fr['max_leverage_ast'] ) )
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_best_fr_rate = df_comb_fr[['symbol_ext','symbol_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)
best_next_funding_pair = {'symbol_aster':df_best_fr_rate['symbol_ast'][0],'symbol_extended':df_best_fr_rate['symbol_ext'][0]}
df_best_fr_rate: pd.DataFrame = df_comb_fr[['symbol_ext','symbol_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)
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 = '',
)
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 = '-',
)
best_next_funding_pair: dict[str, dict] = {'ASTER': asdict(obj=ASTER), 'EXTEND': asdict(obj=EXTEND)}
VAL_KEY.set(VK_OUT, json.dumps(best_next_funding_pair))
print(best_next_funding_pair)
VAL_KEY.set(name=VK_OUT, value=json.dumps(obj=best_next_funding_pair))
# print(best_next_funding_pair)
time.sleep(LOOP_SLEEP_SEC)
continue
except valkey.exceptions.ConnectionError as e:
logging.info(f"Could not connect to Valkey. Please check the publish server is up; {e}")
except KeyboardInterrupt:
logging.info('ORCHESTRATOR SHUTTING DOWN...')
logging.info('SHUTTING DOWN...')
except Exception as e:
logging.error(traceback.format_exc())
logging.critical(f'*** ORCHESTRATOR CRASHED: {e}')
logging.critical(f'*** CRASHED: {e}')
### STARTUP ###
@@ -156,9 +145,9 @@ async def main() -> None:
await loop()
if __name__ == '__main__':
START_TIME = round(datetime.now().timestamp()*1000)
START_TIME = round(number=datetime.now().timestamp()*1000)
logging.info(f'Log FilePath: {LOG_FILEPATH}')
logging.info(msg=f'Log FilePath: {LOG_FILEPATH}')
logging.basicConfig(
force=True,
@@ -167,6 +156,6 @@ if __name__ == '__main__':
format='%(asctime)s - %(levelname)s - %(message)s',
filemode='w'
)
logging.info(f"STARTED: {START_TIME}")
logging.info(msg=f"STARTED: {START_TIME}")
asyncio.run(main())