Files
Funding_Rate/engine_best_funding_rate.ipynb
2026-05-04 18:04:45 +00:00

1491 lines
48 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "code",
"execution_count": 2,
"id": "0b5ca901",
"metadata": {},
"outputs": [],
"source": [
"import requests\n",
"import pandas as pd\n",
"import numpy as np\n",
"from datetime import datetime\n",
"import time\n",
"import json\n",
"import valkey\n",
"from dataclasses import dataclass, field, asdict\n",
"import modules.structs as structs\n",
"import modules.aster_auth as aster_auth\n",
"import modules.manual_leverage as leverage\n",
"VAL_KEY = valkey.Valkey(host='localhost', port=6379, db=0, decode_responses=True)\n",
"df_leverage_by_exch = pd.DataFrame(data=leverage.LEVERAGE_BY_EXCH)"
]
},
{
"cell_type": "code",
"execution_count": 101,
"id": "20665e82",
"metadata": {},
"outputs": [],
"source": [
"### ********** TODO: ADD IN VOLUME DATA TO FILTER MKTS ###"
]
},
{
"cell_type": "code",
"execution_count": 102,
"id": "53647b40",
"metadata": {},
"outputs": [],
"source": [
"# ### ASTER Historical FR ###\n",
"# params = {\n",
"# 'limit': 1000,\n",
"# }\n",
"# r = json.loads(requests.get('https://fapi.asterdex.com/fapi/v3/fundingRate', params=params).text)\n",
"# df_aster_hist_fr = pd.DataFrame(r)\n",
"# df_aster_hist_fr['funding_rate_ts_dt'] = pd.to_datetime(df_aster_hist_fr['fundingTime'], unit='ms')\n",
"# df_aster_hist_fr = df_aster_hist_fr.sort_values(by='fundingTime', ascending=True).drop_duplicates(subset=['symbol'], keep='last')"
]
},
{
"cell_type": "code",
"execution_count": 103,
"id": "1f3b65ee",
"metadata": {},
"outputs": [],
"source": [
"# ### ASTER Current FR ###\n",
"# r = json.loads(requests.get('https://fapi.asterdex.com/fapi/v3/fundingInfo').text)\n",
"# df_aster_current_fr = pd.DataFrame(r)\n",
"# df_aster_current_fr['funding_rate_ts_dt'] = pd.to_datetime(df_aster_current_fr['time'], unit='ms')\n",
"# df_aster_current_fr['funding_rate'] = df_aster_current_fr['interestRate']\n"
]
},
{
"cell_type": "code",
"execution_count": 104,
"id": "5176d5b1",
"metadata": {},
"outputs": [],
"source": [
"### ASTER EXCHANGE INFO ###\n",
"fut_acct_exchangeInfo: dict = {\n",
" \"url\": \"/fapi/v3/exchangeInfo\",\n",
" \"method\": \"GET\",\n",
" \"params\": {}\n",
"}\n",
"r: dict = await aster_auth.post_authenticated_url(fut_acct_exchangeInfo) # ty:ignore[invalid-assignment]\n",
"df_aster_exch_info = pd.DataFrame(r['symbols'])\n",
"df_aster_exch_info['min_order_size'] = df_aster_exch_info['filters'].apply(lambda x: [f for f in x if f.get('filterType', None) == 'LOT_SIZE'][0]['minQty'] )\n",
"df_aster_exch_info['min_price'] = df_aster_exch_info['filters'].apply(lambda x: [f for f in x if f.get('filterType', None) == 'PRICE_FILTER'][0]['minPrice'] )\n",
"df_aster_exch_info['min_notional'] = df_aster_exch_info['filters'].apply(lambda x: [f for f in x if f.get('filterType', None) == 'MIN_NOTIONAL'][0]['notional'] )\n",
"df_aster_exch_info['min_lot_size'] = df_aster_exch_info['filters'].apply(lambda x: [f for f in x if f.get('filterType', None) == 'LOT_SIZE'][0]['stepSize'] )\n",
"\n",
"fut_acct_ticker_stats: dict = {\n",
" \"url\": \"/fapi/v3/ticker/24hr\",\n",
" \"method\": \"GET\",\n",
" \"params\": {}\n",
"}\n",
"r: dict = await aster_auth.post_authenticated_url(fut_acct_ticker_stats) # ty:ignore[invalid-assignment]\n",
"df_aster_ticker_stats = pd.DataFrame(r)\n",
"df_aster_ticker_stats['last_trade_ts_ast'] = df_aster_ticker_stats['closeTime']\n",
"\n",
"df_aster_exch_info = df_aster_exch_info.merge(df_aster_ticker_stats[['symbol','quoteVolume','last_trade_ts_ast']].rename({'quoteVolume':'daily_volume'}, axis=1), on='symbol', how='left')\n",
"df_aster_exch_info['daily_volume'] = df_aster_exch_info['daily_volume'].astype(float)"
]
},
{
"cell_type": "code",
"execution_count": 105,
"id": "e33ec721",
"metadata": {},
"outputs": [],
"source": [
"### Extended Current FR ###\n",
"r = json.loads(requests.get('https://api.starknet.extended.exchange/api/v1/info/markets').text)\n",
"df_extend_current_mkt_stats = pd.DataFrame(r['data'])\n",
"\n",
"df_extend_current_mkt_stats['funding_rate'] = df_extend_current_mkt_stats['marketStats'].apply(lambda x: x.get('fundingRate',{}))\n",
"df_extend_current_mkt_stats['funding_rate_ts'] = df_extend_current_mkt_stats['marketStats'].apply(lambda x: x.get('nextFundingRate',{}))\n",
"df_extend_current_mkt_stats['daily_volume'] = df_extend_current_mkt_stats['marketStats'].apply(lambda x: x.get('dailyVolume',{})).astype(float)\n",
"df_extend_current_mkt_stats['min_order_size'] = df_extend_current_mkt_stats['tradingConfig'].apply(lambda x: x.get('minOrderSize',{}))\n",
"df_extend_current_mkt_stats['min_price'] = df_extend_current_mkt_stats['tradingConfig'].apply(lambda x: x.get('minPriceChange',{}))\n",
"df_extend_current_mkt_stats['min_notional'] = 0\n",
"df_extend_current_mkt_stats['min_lot_size'] = df_extend_current_mkt_stats['tradingConfig'].apply(lambda x: x.get('minOrderSizeChange',{}))\n",
"\n",
"df_extend_current_mkt_stats['max_leverage'] = df_extend_current_mkt_stats['tradingConfig'].apply(lambda x: x.get('maxLeverage',{}))\n",
"\n",
"\n",
"# df_extend_current_fr = df_extend_current_mkt_stats[['status','name','assetName','collateralAssetName','category','min_order_size','min_price','max_leverage','funding_rate','funding_rate_ts']]\n",
"# df_extend_current_fr['funding_rate_ts_dt'] = pd.to_datetime(df_extend_current_fr['funding_rate_ts'], unit='ms')\n",
"# df_extend_current_fr = df_extend_current_fr.loc[df_extend_current_fr['status']=='ACTIVE',:]"
]
},
{
"cell_type": "code",
"execution_count": 106,
"id": "62815940",
"metadata": {},
"outputs": [],
"source": [
"### ASTER Current FR from Mark Price Req ###\n",
"# r = json.loads(requests.get('https://fapi.asterdex.com/fapi/v3/exchangeInfo').text)\n",
"# df_aster_current_mkt_stats = pd.DataFrame(r)\n",
"# ### ASTER Current FR from Mark Price Req ###\n",
"# r = json.loads(requests.get('https://fapi.asterdex.com/fapi/v3/premiumIndex').text)\n",
"# df_aster_current_mkt_stats = pd.DataFrame(r)"
]
},
{
"cell_type": "code",
"execution_count": 107,
"id": "271a67c1",
"metadata": {},
"outputs": [],
"source": [
"### ASTER CURRENT FR - WS ###\n",
"df_aster_current_fr = pd.DataFrame(json.loads(VAL_KEY.get('fund_rate_aster_all'))) # ty:ignore[invalid-argument-type]\n",
"df_aster_current_fr = df_aster_current_fr[['s','E','r','T']].rename({'s':'symbol','E':'funding_rate_updated_ts_ms','r':'funding_rate','T':'next_funding_ts'}, axis=1)\n",
"df_aster_current_fr['funding_rate_updated_dt'] = pd.to_datetime(df_aster_current_fr['funding_rate_updated_ts_ms'], unit='ms')\n",
"df_aster_current_fr['funding_rate'] = df_aster_current_fr['funding_rate'].astype(float)\n",
"df_aster_current_fr['time_delta_to_next_funding'] = pd.to_datetime(df_aster_current_fr['next_funding_ts'], unit='ms') - pd.Timestamp.now()\n",
"df_aster_current_fr = df_aster_current_fr.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')"
]
},
{
"cell_type": "code",
"execution_count": 108,
"id": "1ce2fde4",
"metadata": {},
"outputs": [],
"source": [
"### EXTEND CURRENT FR - WS ###\n",
"df_extended_current_fr = pd.DataFrame(json.loads(VAL_KEY.get('fund_rate_extended_all'))) # ty:ignore[invalid-argument-type]\n",
"df_extended_current_fr = df_extended_current_fr[['symbol','funding_rate_updated_ts_ms','funding_rate']]\n",
"df_extended_current_fr['funding_rate_updated_dt'] = pd.to_datetime(df_extended_current_fr['funding_rate_updated_ts_ms'], unit='ms')\n",
"df_extended_current_fr['funding_rate'] = df_extended_current_fr['funding_rate'].astype(float)\n",
"\n",
"# df_extended_current_fr = df_extended_current_fr.merge(df_extend_current_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')\n",
"df_extended_current_fr = df_extended_current_fr.merge(df_extend_current_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')\n",
"df_extended_current_fr = df_extended_current_fr.loc[df_extended_current_fr['status']=='ACTIVE',:]\n",
"df_extended_current_fr['USDT_Symbol'] = df_extended_current_fr['assetName'] + 'USDT'\n",
"df_extended_current_fr['time_delta_to_next_funding'] = pd.to_datetime(df_extended_current_fr['next_funding_ts'], unit='ms') - pd.Timestamp.now()"
]
},
{
"cell_type": "code",
"execution_count": 109,
"id": "ff88b413",
"metadata": {},
"outputs": [],
"source": [
"### COMBINED CURRENT FR - WS ###\n",
"df_comb_current_fr = df_extended_current_fr.merge(df_aster_current_fr, left_on='USDT_Symbol', right_on='symbol', how='inner', suffixes=('_ext', '_ast'))\n",
"df_comb_current_fr['next_funding_at_same_time'] = (abs(df_comb_current_fr['time_delta_to_next_funding_ext'].dt.total_seconds() - df_comb_current_fr['time_delta_to_next_funding_ast'].dt.total_seconds()) / 60) < 1\n",
"df_comb_current_fr['net_funding_rate'] = (df_comb_current_fr[['funding_rate_ext', 'funding_rate_ast']].max(axis=1) - df_comb_current_fr[['funding_rate_ext', 'funding_rate_ast']].min(axis=1)).where(df_comb_current_fr['next_funding_at_same_time'], df_comb_current_fr['funding_rate_ext'])\n",
"df_comb_current_fr['net_funding_rate_abs'] = df_comb_current_fr['net_funding_rate'].abs()\n",
"\n",
"### NET MULT ###\n",
"df_comb_current_fr_net = df_comb_current_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'))\n",
"df_comb_current_fr_net['net_mult'] = 1 / ( ( 0.5 / df_comb_current_fr_net['max_leverage_ext'] ) + ( 0.5 / df_comb_current_fr_net['max_leverage_ast'] ) )\n",
"df_comb_current_fr_net['net_mult'] = df_comb_current_fr_net['net_mult'].round(2)\n",
"df_comb_current_fr_net['net_mult_x_net_fr_abs'] = df_comb_current_fr_net['net_funding_rate_abs'] * df_comb_current_fr_net['net_mult']"
]
},
{
"cell_type": "code",
"execution_count": 110,
"id": "f5ade993",
"metadata": {},
"outputs": [],
"source": [
"df_best_fr_rate = df_comb_current_fr_net[['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)\n",
"df_best_fr_rate['hourly_dollars_per_1k'] = df_best_fr_rate['net_mult_x_net_fr_abs'] * 1000\n",
"df_best_fr_rate['hourly_dollars_per_1k'] = df_best_fr_rate['hourly_dollars_per_1k'].round(2)"
]
},
{
"cell_type": "code",
"execution_count": 111,
"id": "84bbc5a8",
"metadata": {},
"outputs": [],
"source": [
"last_trade_max_ts = []\n",
"\n",
"for index, row in df_best_fr_rate.iterrows():\n",
" r = json.loads(requests.get(f'https://api.starknet.extended.exchange/api/v1/info/markets/{row['symbol_ext']}/trades').text)\n",
" max_ts = max([t['T'] for t in r['data']])\n",
" last_trade_max_ts.append({'symbol_ext':row['symbol_ext'],'last_trade_ts_ext': max_ts})\n",
" time.sleep(0.01)\n",
"\n",
"df_best_fr_rate = df_best_fr_rate.merge(pd.DataFrame(last_trade_max_ts), on='symbol_ext', how='left')"
]
},
{
"cell_type": "code",
"execution_count": 112,
"id": "7bd849e4",
"metadata": {},
"outputs": [],
"source": [
"df_best_fr_rate['last_trade_ts_dt_ast'] = pd.to_datetime(df_best_fr_rate['last_trade_ts_ast'], unit='ms')\n",
"df_best_fr_rate['last_trade_ts_dt_ext'] = pd.to_datetime(df_best_fr_rate['last_trade_ts_ext'], unit='ms')\n",
"df_best_fr_rate = df_best_fr_rate.loc[( (datetime.now().timestamp()*1000 )-df_best_fr_rate['last_trade_ts_ast']) < (3*60*1000) ]\n",
"df_best_fr_rate = df_best_fr_rate.loc[( (datetime.now().timestamp()*1000 )-df_best_fr_rate['last_trade_ts_ext']) < (15*60*1000) ]"
]
},
{
"cell_type": "code",
"execution_count": 113,
"id": "48d093ce",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.microsoft.datawrangler.viewer.v0+json": {
"columns": [
{
"name": "index",
"rawType": "int64",
"type": "integer"
},
{
"name": "symbol_ext",
"rawType": "str",
"type": "string"
},
{
"name": "symbol_ast",
"rawType": "str",
"type": "string"
},
{
"name": "daily_volume_ext",
"rawType": "float64",
"type": "float"
},
{
"name": "daily_volume_ast",
"rawType": "float64",
"type": "float"
},
{
"name": "min_price_ext",
"rawType": "str",
"type": "string"
},
{
"name": "min_price_ast",
"rawType": "str",
"type": "string"
},
{
"name": "min_order_size_ext",
"rawType": "str",
"type": "string"
},
{
"name": "min_order_size_ast",
"rawType": "str",
"type": "string"
},
{
"name": "min_lot_size_ext",
"rawType": "str",
"type": "string"
},
{
"name": "min_lot_size_ast",
"rawType": "str",
"type": "string"
},
{
"name": "min_notional_ext",
"rawType": "float64",
"type": "float"
},
{
"name": "min_notional_ast",
"rawType": "str",
"type": "string"
},
{
"name": "funding_rate_ext",
"rawType": "float64",
"type": "float"
},
{
"name": "funding_rate_ast",
"rawType": "float64",
"type": "float"
},
{
"name": "max_leverage_ext",
"rawType": "int64",
"type": "integer"
},
{
"name": "max_leverage_ast",
"rawType": "int64",
"type": "integer"
},
{
"name": "lh_asset_ext",
"rawType": "str",
"type": "string"
},
{
"name": "lh_asset_ast",
"rawType": "str",
"type": "string"
},
{
"name": "rh_asset_ext",
"rawType": "str",
"type": "string"
},
{
"name": "rh_asset_ast",
"rawType": "str",
"type": "string"
},
{
"name": "net_mult_x_net_fr_abs",
"rawType": "float64",
"type": "float"
},
{
"name": "net_funding_rate_abs",
"rawType": "float64",
"type": "float"
},
{
"name": "net_funding_rate",
"rawType": "float64",
"type": "float"
},
{
"name": "next_funding_at_same_time",
"rawType": "bool",
"type": "boolean"
},
{
"name": "last_trade_ts_ast",
"rawType": "float64",
"type": "float"
},
{
"name": "hourly_dollars_per_1k",
"rawType": "float64",
"type": "float"
},
{
"name": "last_trade_ts_ext",
"rawType": "int64",
"type": "integer"
},
{
"name": "last_trade_ts_dt_ast",
"rawType": "datetime64[ms]",
"type": "datetime"
},
{
"name": "last_trade_ts_dt_ext",
"rawType": "datetime64[ms]",
"type": "datetime"
}
],
"ref": "fb395936-194b-4884-9460-1644ab82f860",
"rows": [
[
"0",
"LIT-USD",
"LITUSDT",
"1530863.4786",
"557344.16",
"0.0001",
"0.0001000",
"10",
"1",
"1",
"1",
"0.0",
"5",
"1.3e-05",
"7.641e-05",
"25",
"50",
"LIT",
"LIT",
"USD",
"USDT",
"0.0021134552999999994",
"6.340999999999999e-05",
"6.340999999999999e-05",
"True",
"1777838955491.0",
"2.11",
"1777838893573",
"2026-05-03 20:09:15.491000",
"2026-05-03 20:08:13.573000"
],
[
"1",
"ZEC-USD",
"ZECUSDT",
"5395747.6736",
"1986811.3",
"0.001",
"0.0100",
"0.1",
"0.001",
"0.1",
"0.001",
"0.0",
"5",
"1.3e-05",
"-7.232e-05",
"10",
"75",
"ZEC",
"ZEC",
"USD",
"USDT",
"0.0015058979999999999",
"8.532e-05",
"8.532e-05",
"True",
"1777838956400.0",
"1.51",
"1777838958681",
"2026-05-03 20:09:16.400000",
"2026-05-03 20:09:18.681000"
],
[
"2",
"ETH-USD",
"ETHUSDT",
"63794900.8984",
"215801150.77",
"0.1",
"0.01",
"0.01",
"0.001",
"0.001",
"0.001",
"0.0",
"5",
"-1.6e-05",
"5.828e-05",
"50",
"150",
"ETH",
"ETH",
"USD",
"USDT",
"0.0012",
"1.6e-05",
"-1.6e-05",
"False",
"1777838959171.0",
"1.2",
"1777838943428",
"2026-05-03 20:09:19.171000",
"2026-05-03 20:09:03.428000"
],
[
"3",
"HYPE-USD",
"HYPEUSDT",
"25572374.04134",
"3517135.54",
"0.001",
"0.00100",
"0.1",
"0.01",
"0.01",
"0.01",
"0.0",
"5",
"1.3e-05",
"-1.902e-05",
"50",
"300",
"HYPE",
"HYPE",
"USD",
"USDT",
"0.00111423",
"1.3e-05",
"1.3e-05",
"False",
"1777838926707.0",
"1.11",
"1777838941321",
"2026-05-03 20:08:46.707000",
"2026-05-03 20:09:01.321000"
],
[
"5",
"XRP-USD",
"XRPUSDT",
"5624796.8796",
"7717251.91",
"0.0001",
"0.0143",
"10",
"0.1",
"1",
"0.1",
"0.0",
"5",
"1.3e-05",
"0.0001",
"50",
"100",
"XRP",
"XRP",
"USD",
"USDT",
"0.0008667099999999999",
"1.3e-05",
"1.3e-05",
"False",
"1777838956056.0",
"0.87",
"1777838873023",
"2026-05-03 20:09:16.056000",
"2026-05-03 20:07:53.023000"
],
[
"6",
"BNB-USD",
"BNBUSDT",
"3508321.26862",
"7656349.56",
"0.01",
"0.010",
"0.01",
"0.01",
"0.001",
"0.01",
"0.0",
"5",
"1.3e-05",
"0.00013255",
"50",
"100",
"BNB",
"BNB",
"USD",
"USDT",
"0.0008667099999999999",
"1.3e-05",
"1.3e-05",
"False",
"1777838957563.0",
"0.87",
"1777838862018",
"2026-05-03 20:09:17.563000",
"2026-05-03 20:07:42.018000"
],
[
"7",
"DOGE-USD",
"DOGEUSDT",
"2224083.3516",
"13131913.36",
"0.00001",
"0.002440",
"100",
"1",
"10",
"1",
"0.0",
"5",
"1.3e-05",
"4.512e-05",
"50",
"75",
"DOGE",
"DOGE",
"USD",
"USDT",
"0.00078",
"1.3e-05",
"1.3e-05",
"False",
"1777838958745.0",
"0.78",
"1777838861853",
"2026-05-03 20:09:18.745000",
"2026-05-03 20:07:41.853000"
],
[
"9",
"ASTER-USD",
"ASTERUSDT",
"379897.4992",
"35798413.55",
"0.00001",
"0.00010",
"10",
"0.01",
"1",
"0.01",
"0.0",
"5",
"1.3e-05",
"5e-05",
"25",
"75",
"ASTER",
"ASTER",
"USD",
"USDT",
"0.0004875",
"1.3e-05",
"1.3e-05",
"False",
"1777838956077.0",
"0.49",
"1777838861663",
"2026-05-03 20:09:16.077000",
"2026-05-03 20:07:41.663000"
],
[
"10",
"CHIP-USD",
"CHIPUSDT",
"601581.80858",
"369037.94",
"0.000001",
"0.0000100",
"100",
"1",
"10",
"1",
"0.0",
"5",
"-0.000455",
"-0.00050814",
"5",
"50",
"CHIP",
"CHIP",
"USD",
"USDT",
"0.0004830426000000002",
"5.314000000000002e-05",
"5.314000000000002e-05",
"True",
"1777838833850.0",
"0.48",
"1777838894261",
"2026-05-03 20:07:13.850000",
"2026-05-03 20:08:14.261000"
],
[
"11",
"SOL-USD",
"SOLUSDT",
"10993777.163",
"28191542.03",
"0.01",
"0.4200",
"0.1",
"0.01",
"0.01",
"0.01",
"0.0",
"5",
"7e-06",
"0.0001",
"50",
"100",
"SOL",
"SOL",
"USD",
"USDT",
"0.00046669",
"7e-06",
"7e-06",
"False",
"1777838959552.0",
"0.47",
"1777838903681",
"2026-05-03 20:09:19.552000",
"2026-05-03 20:08:23.681000"
],
[
"12",
"BTC-USD",
"BTCUSDT",
"190699704.69432",
"331787901.64",
"1",
"1",
"0.0001",
"0.001",
"0.00001",
"0.001",
"0.0",
"5",
"-6e-06",
"-9.62e-06",
"50",
"150",
"BTC",
"BTC",
"USD",
"USDT",
"0.00045",
"6e-06",
"-6e-06",
"False",
"1777838959137.0",
"0.45",
"1777838940017",
"2026-05-03 20:09:19.137000",
"2026-05-03 20:09:00.017000"
],
[
"14",
"WLFI-USD",
"WLFIUSDT",
"118516.608",
"2231254.7",
"0.00001",
"0.0001000",
"100",
"1",
"10",
"1",
"0.0",
"5",
"1.3e-05",
"5e-05",
"10",
"25",
"WLFI",
"WLFI",
"USD",
"USDT",
"0.00018576999999999998",
"1.3e-05",
"1.3e-05",
"False",
"1777838920826.0",
"0.19",
"1777838640653",
"2026-05-03 20:08:40.826000",
"2026-05-03 20:04:00.653000"
]
],
"shape": {
"columns": 29,
"rows": 12
}
},
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>symbol_ext</th>\n",
" <th>symbol_ast</th>\n",
" <th>daily_volume_ext</th>\n",
" <th>daily_volume_ast</th>\n",
" <th>min_price_ext</th>\n",
" <th>min_price_ast</th>\n",
" <th>min_order_size_ext</th>\n",
" <th>min_order_size_ast</th>\n",
" <th>min_lot_size_ext</th>\n",
" <th>min_lot_size_ast</th>\n",
" <th>...</th>\n",
" <th>rh_asset_ast</th>\n",
" <th>net_mult_x_net_fr_abs</th>\n",
" <th>net_funding_rate_abs</th>\n",
" <th>net_funding_rate</th>\n",
" <th>next_funding_at_same_time</th>\n",
" <th>last_trade_ts_ast</th>\n",
" <th>hourly_dollars_per_1k</th>\n",
" <th>last_trade_ts_ext</th>\n",
" <th>last_trade_ts_dt_ast</th>\n",
" <th>last_trade_ts_dt_ext</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>LIT-USD</td>\n",
" <td>LITUSDT</td>\n",
" <td>1.530863e+06</td>\n",
" <td>5.573442e+05</td>\n",
" <td>0.0001</td>\n",
" <td>0.0001000</td>\n",
" <td>10</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>...</td>\n",
" <td>USDT</td>\n",
" <td>0.002113</td>\n",
" <td>0.000063</td>\n",
" <td>0.000063</td>\n",
" <td>True</td>\n",
" <td>1.777839e+12</td>\n",
" <td>2.11</td>\n",
" <td>1777838893573</td>\n",
" <td>2026-05-03 20:09:15.491</td>\n",
" <td>2026-05-03 20:08:13.573</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>ZEC-USD</td>\n",
" <td>ZECUSDT</td>\n",
" <td>5.395748e+06</td>\n",
" <td>1.986811e+06</td>\n",
" <td>0.001</td>\n",
" <td>0.0100</td>\n",
" <td>0.1</td>\n",
" <td>0.001</td>\n",
" <td>0.1</td>\n",
" <td>0.001</td>\n",
" <td>...</td>\n",
" <td>USDT</td>\n",
" <td>0.001506</td>\n",
" <td>0.000085</td>\n",
" <td>0.000085</td>\n",
" <td>True</td>\n",
" <td>1.777839e+12</td>\n",
" <td>1.51</td>\n",
" <td>1777838958681</td>\n",
" <td>2026-05-03 20:09:16.400</td>\n",
" <td>2026-05-03 20:09:18.681</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>ETH-USD</td>\n",
" <td>ETHUSDT</td>\n",
" <td>6.379490e+07</td>\n",
" <td>2.158012e+08</td>\n",
" <td>0.1</td>\n",
" <td>0.01</td>\n",
" <td>0.01</td>\n",
" <td>0.001</td>\n",
" <td>0.001</td>\n",
" <td>0.001</td>\n",
" <td>...</td>\n",
" <td>USDT</td>\n",
" <td>0.001200</td>\n",
" <td>0.000016</td>\n",
" <td>-0.000016</td>\n",
" <td>False</td>\n",
" <td>1.777839e+12</td>\n",
" <td>1.20</td>\n",
" <td>1777838943428</td>\n",
" <td>2026-05-03 20:09:19.171</td>\n",
" <td>2026-05-03 20:09:03.428</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>HYPE-USD</td>\n",
" <td>HYPEUSDT</td>\n",
" <td>2.557237e+07</td>\n",
" <td>3.517136e+06</td>\n",
" <td>0.001</td>\n",
" <td>0.00100</td>\n",
" <td>0.1</td>\n",
" <td>0.01</td>\n",
" <td>0.01</td>\n",
" <td>0.01</td>\n",
" <td>...</td>\n",
" <td>USDT</td>\n",
" <td>0.001114</td>\n",
" <td>0.000013</td>\n",
" <td>0.000013</td>\n",
" <td>False</td>\n",
" <td>1.777839e+12</td>\n",
" <td>1.11</td>\n",
" <td>1777838941321</td>\n",
" <td>2026-05-03 20:08:46.707</td>\n",
" <td>2026-05-03 20:09:01.321</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>XRP-USD</td>\n",
" <td>XRPUSDT</td>\n",
" <td>5.624797e+06</td>\n",
" <td>7.717252e+06</td>\n",
" <td>0.0001</td>\n",
" <td>0.0143</td>\n",
" <td>10</td>\n",
" <td>0.1</td>\n",
" <td>1</td>\n",
" <td>0.1</td>\n",
" <td>...</td>\n",
" <td>USDT</td>\n",
" <td>0.000867</td>\n",
" <td>0.000013</td>\n",
" <td>0.000013</td>\n",
" <td>False</td>\n",
" <td>1.777839e+12</td>\n",
" <td>0.87</td>\n",
" <td>1777838873023</td>\n",
" <td>2026-05-03 20:09:16.056</td>\n",
" <td>2026-05-03 20:07:53.023</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>BNB-USD</td>\n",
" <td>BNBUSDT</td>\n",
" <td>3.508321e+06</td>\n",
" <td>7.656350e+06</td>\n",
" <td>0.01</td>\n",
" <td>0.010</td>\n",
" <td>0.01</td>\n",
" <td>0.01</td>\n",
" <td>0.001</td>\n",
" <td>0.01</td>\n",
" <td>...</td>\n",
" <td>USDT</td>\n",
" <td>0.000867</td>\n",
" <td>0.000013</td>\n",
" <td>0.000013</td>\n",
" <td>False</td>\n",
" <td>1.777839e+12</td>\n",
" <td>0.87</td>\n",
" <td>1777838862018</td>\n",
" <td>2026-05-03 20:09:17.563</td>\n",
" <td>2026-05-03 20:07:42.018</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>DOGE-USD</td>\n",
" <td>DOGEUSDT</td>\n",
" <td>2.224083e+06</td>\n",
" <td>1.313191e+07</td>\n",
" <td>0.00001</td>\n",
" <td>0.002440</td>\n",
" <td>100</td>\n",
" <td>1</td>\n",
" <td>10</td>\n",
" <td>1</td>\n",
" <td>...</td>\n",
" <td>USDT</td>\n",
" <td>0.000780</td>\n",
" <td>0.000013</td>\n",
" <td>0.000013</td>\n",
" <td>False</td>\n",
" <td>1.777839e+12</td>\n",
" <td>0.78</td>\n",
" <td>1777838861853</td>\n",
" <td>2026-05-03 20:09:18.745</td>\n",
" <td>2026-05-03 20:07:41.853</td>\n",
" </tr>\n",
" <tr>\n",
" <th>9</th>\n",
" <td>ASTER-USD</td>\n",
" <td>ASTERUSDT</td>\n",
" <td>3.798975e+05</td>\n",
" <td>3.579841e+07</td>\n",
" <td>0.00001</td>\n",
" <td>0.00010</td>\n",
" <td>10</td>\n",
" <td>0.01</td>\n",
" <td>1</td>\n",
" <td>0.01</td>\n",
" <td>...</td>\n",
" <td>USDT</td>\n",
" <td>0.000487</td>\n",
" <td>0.000013</td>\n",
" <td>0.000013</td>\n",
" <td>False</td>\n",
" <td>1.777839e+12</td>\n",
" <td>0.49</td>\n",
" <td>1777838861663</td>\n",
" <td>2026-05-03 20:09:16.077</td>\n",
" <td>2026-05-03 20:07:41.663</td>\n",
" </tr>\n",
" <tr>\n",
" <th>10</th>\n",
" <td>CHIP-USD</td>\n",
" <td>CHIPUSDT</td>\n",
" <td>6.015818e+05</td>\n",
" <td>3.690379e+05</td>\n",
" <td>0.000001</td>\n",
" <td>0.0000100</td>\n",
" <td>100</td>\n",
" <td>1</td>\n",
" <td>10</td>\n",
" <td>1</td>\n",
" <td>...</td>\n",
" <td>USDT</td>\n",
" <td>0.000483</td>\n",
" <td>0.000053</td>\n",
" <td>0.000053</td>\n",
" <td>True</td>\n",
" <td>1.777839e+12</td>\n",
" <td>0.48</td>\n",
" <td>1777838894261</td>\n",
" <td>2026-05-03 20:07:13.850</td>\n",
" <td>2026-05-03 20:08:14.261</td>\n",
" </tr>\n",
" <tr>\n",
" <th>11</th>\n",
" <td>SOL-USD</td>\n",
" <td>SOLUSDT</td>\n",
" <td>1.099378e+07</td>\n",
" <td>2.819154e+07</td>\n",
" <td>0.01</td>\n",
" <td>0.4200</td>\n",
" <td>0.1</td>\n",
" <td>0.01</td>\n",
" <td>0.01</td>\n",
" <td>0.01</td>\n",
" <td>...</td>\n",
" <td>USDT</td>\n",
" <td>0.000467</td>\n",
" <td>0.000007</td>\n",
" <td>0.000007</td>\n",
" <td>False</td>\n",
" <td>1.777839e+12</td>\n",
" <td>0.47</td>\n",
" <td>1777838903681</td>\n",
" <td>2026-05-03 20:09:19.552</td>\n",
" <td>2026-05-03 20:08:23.681</td>\n",
" </tr>\n",
" <tr>\n",
" <th>12</th>\n",
" <td>BTC-USD</td>\n",
" <td>BTCUSDT</td>\n",
" <td>1.906997e+08</td>\n",
" <td>3.317879e+08</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>0.0001</td>\n",
" <td>0.001</td>\n",
" <td>0.00001</td>\n",
" <td>0.001</td>\n",
" <td>...</td>\n",
" <td>USDT</td>\n",
" <td>0.000450</td>\n",
" <td>0.000006</td>\n",
" <td>-0.000006</td>\n",
" <td>False</td>\n",
" <td>1.777839e+12</td>\n",
" <td>0.45</td>\n",
" <td>1777838940017</td>\n",
" <td>2026-05-03 20:09:19.137</td>\n",
" <td>2026-05-03 20:09:00.017</td>\n",
" </tr>\n",
" <tr>\n",
" <th>14</th>\n",
" <td>WLFI-USD</td>\n",
" <td>WLFIUSDT</td>\n",
" <td>1.185166e+05</td>\n",
" <td>2.231255e+06</td>\n",
" <td>0.00001</td>\n",
" <td>0.0001000</td>\n",
" <td>100</td>\n",
" <td>1</td>\n",
" <td>10</td>\n",
" <td>1</td>\n",
" <td>...</td>\n",
" <td>USDT</td>\n",
" <td>0.000186</td>\n",
" <td>0.000013</td>\n",
" <td>0.000013</td>\n",
" <td>False</td>\n",
" <td>1.777839e+12</td>\n",
" <td>0.19</td>\n",
" <td>1777838640653</td>\n",
" <td>2026-05-03 20:08:40.826</td>\n",
" <td>2026-05-03 20:04:00.653</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>12 rows × 29 columns</p>\n",
"</div>"
],
"text/plain": [
" symbol_ext symbol_ast daily_volume_ext daily_volume_ast min_price_ext \\\n",
"0 LIT-USD LITUSDT 1.530863e+06 5.573442e+05 0.0001 \n",
"1 ZEC-USD ZECUSDT 5.395748e+06 1.986811e+06 0.001 \n",
"2 ETH-USD ETHUSDT 6.379490e+07 2.158012e+08 0.1 \n",
"3 HYPE-USD HYPEUSDT 2.557237e+07 3.517136e+06 0.001 \n",
"5 XRP-USD XRPUSDT 5.624797e+06 7.717252e+06 0.0001 \n",
"6 BNB-USD BNBUSDT 3.508321e+06 7.656350e+06 0.01 \n",
"7 DOGE-USD DOGEUSDT 2.224083e+06 1.313191e+07 0.00001 \n",
"9 ASTER-USD ASTERUSDT 3.798975e+05 3.579841e+07 0.00001 \n",
"10 CHIP-USD CHIPUSDT 6.015818e+05 3.690379e+05 0.000001 \n",
"11 SOL-USD SOLUSDT 1.099378e+07 2.819154e+07 0.01 \n",
"12 BTC-USD BTCUSDT 1.906997e+08 3.317879e+08 1 \n",
"14 WLFI-USD WLFIUSDT 1.185166e+05 2.231255e+06 0.00001 \n",
"\n",
" min_price_ast min_order_size_ext min_order_size_ast min_lot_size_ext \\\n",
"0 0.0001000 10 1 1 \n",
"1 0.0100 0.1 0.001 0.1 \n",
"2 0.01 0.01 0.001 0.001 \n",
"3 0.00100 0.1 0.01 0.01 \n",
"5 0.0143 10 0.1 1 \n",
"6 0.010 0.01 0.01 0.001 \n",
"7 0.002440 100 1 10 \n",
"9 0.00010 10 0.01 1 \n",
"10 0.0000100 100 1 10 \n",
"11 0.4200 0.1 0.01 0.01 \n",
"12 1 0.0001 0.001 0.00001 \n",
"14 0.0001000 100 1 10 \n",
"\n",
" min_lot_size_ast ... rh_asset_ast net_mult_x_net_fr_abs \\\n",
"0 1 ... USDT 0.002113 \n",
"1 0.001 ... USDT 0.001506 \n",
"2 0.001 ... USDT 0.001200 \n",
"3 0.01 ... USDT 0.001114 \n",
"5 0.1 ... USDT 0.000867 \n",
"6 0.01 ... USDT 0.000867 \n",
"7 1 ... USDT 0.000780 \n",
"9 0.01 ... USDT 0.000487 \n",
"10 1 ... USDT 0.000483 \n",
"11 0.01 ... USDT 0.000467 \n",
"12 0.001 ... USDT 0.000450 \n",
"14 1 ... USDT 0.000186 \n",
"\n",
" net_funding_rate_abs net_funding_rate next_funding_at_same_time \\\n",
"0 0.000063 0.000063 True \n",
"1 0.000085 0.000085 True \n",
"2 0.000016 -0.000016 False \n",
"3 0.000013 0.000013 False \n",
"5 0.000013 0.000013 False \n",
"6 0.000013 0.000013 False \n",
"7 0.000013 0.000013 False \n",
"9 0.000013 0.000013 False \n",
"10 0.000053 0.000053 True \n",
"11 0.000007 0.000007 False \n",
"12 0.000006 -0.000006 False \n",
"14 0.000013 0.000013 False \n",
"\n",
" last_trade_ts_ast hourly_dollars_per_1k last_trade_ts_ext \\\n",
"0 1.777839e+12 2.11 1777838893573 \n",
"1 1.777839e+12 1.51 1777838958681 \n",
"2 1.777839e+12 1.20 1777838943428 \n",
"3 1.777839e+12 1.11 1777838941321 \n",
"5 1.777839e+12 0.87 1777838873023 \n",
"6 1.777839e+12 0.87 1777838862018 \n",
"7 1.777839e+12 0.78 1777838861853 \n",
"9 1.777839e+12 0.49 1777838861663 \n",
"10 1.777839e+12 0.48 1777838894261 \n",
"11 1.777839e+12 0.47 1777838903681 \n",
"12 1.777839e+12 0.45 1777838940017 \n",
"14 1.777839e+12 0.19 1777838640653 \n",
"\n",
" last_trade_ts_dt_ast last_trade_ts_dt_ext \n",
"0 2026-05-03 20:09:15.491 2026-05-03 20:08:13.573 \n",
"1 2026-05-03 20:09:16.400 2026-05-03 20:09:18.681 \n",
"2 2026-05-03 20:09:19.171 2026-05-03 20:09:03.428 \n",
"3 2026-05-03 20:08:46.707 2026-05-03 20:09:01.321 \n",
"5 2026-05-03 20:09:16.056 2026-05-03 20:07:53.023 \n",
"6 2026-05-03 20:09:17.563 2026-05-03 20:07:42.018 \n",
"7 2026-05-03 20:09:18.745 2026-05-03 20:07:41.853 \n",
"9 2026-05-03 20:09:16.077 2026-05-03 20:07:41.663 \n",
"10 2026-05-03 20:07:13.850 2026-05-03 20:08:14.261 \n",
"11 2026-05-03 20:09:19.552 2026-05-03 20:08:23.681 \n",
"12 2026-05-03 20:09:19.137 2026-05-03 20:09:00.017 \n",
"14 2026-05-03 20:08:40.826 2026-05-03 20:04:00.653 \n",
"\n",
"[12 rows x 29 columns]"
]
},
"execution_count": 113,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_best_fr_rate"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bbad7d21",
"metadata": {},
"outputs": [],
"source": [
"### Candles for Midpoint Dispersion ###\n",
"# Aster\n",
"import modules.aster_auth as aster_auth\n",
"symbol = 'BTCUSDT'\n",
"candles = {\n",
" \"url\": \"/fapi/v3/klines\",\n",
" \"method\": \"GET\",\n",
" \"params\": {\n",
" 'symbol': symbol,\n",
" 'interval': '1m',\n",
" 'limit':'1440'\n",
" }\n",
"}\n",
"j = await aster_auth.post_authenticated_url(candles)\n",
"df_candles_aster = pd.DataFrame(j, columns=['open_ts','open_px','high_px','low_px','close_px','volume','close_ts','quote_asset_volume','count_trades','taker_buy_base_asset_volume','taker_buy_quote_asset_volume','_drop'])\n",
"df_candles_aster"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "421577f1",
"metadata": {},
"outputs": [],
"source": [
"# Extend\n",
"symbol_ext = 'BTC-USD'\n",
"params = {\n",
" 'interval':'1m',\n",
" 'limit':1440,\n",
"}\n",
"r = json.loads(requests.get(f'https://api.starknet.extended.exchange/api/v1/info/candles/{symbol}/trades', params=params).text)\n",
"df_candles_extended = pd.DataFrame(r)\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "f83feeda",
"metadata": {},
"outputs": [
{
"data": {
"application/vnd.microsoft.datawrangler.viewer.v0+json": {
"columns": [
{
"name": "index",
"rawType": "str",
"type": "string"
},
{
"name": "status",
"rawType": "str",
"type": "string"
},
{
"name": "error",
"rawType": "object",
"type": "unknown"
}
],
"ref": "53323547-ff3c-492b-9d00-eb33883ef6b5",
"rows": [
[
"code",
"ERROR",
"1001"
],
[
"message",
"ERROR",
"Market not found"
]
],
"shape": {
"columns": 2,
"rows": 2
}
},
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>status</th>\n",
" <th>error</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>code</th>\n",
" <td>ERROR</td>\n",
" <td>1001</td>\n",
" </tr>\n",
" <tr>\n",
" <th>message</th>\n",
" <td>ERROR</td>\n",
" <td>Market not found</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" status error\n",
"code ERROR 1001\n",
"message ERROR Market not found"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_candles_extended"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 98,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'symbol_ast': 'CHIPUSDT', 'symbol_extended': 'CHIP-USD'}"
]
},
"execution_count": 98,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# min_daily_volume = 100_000\n",
"# 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)\n",
"\n",
"\n",
"best_next_funding_pair = {'symbol_ast':df_best_fr_rate['symbol_ast'][0],'symbol_extended':df_best_fr_rate['symbol_ext'][0]}\n",
"best_next_funding_pair"
]
},
{
"cell_type": "code",
"execution_count": 82,
"id": "125ee5ed",
"metadata": {},
"outputs": [],
"source": [
"ASTER = structs.Perpetual_Exchange(\n",
" mult = int(df_best_fr_rate['max_leverage_ast'][0]),\n",
" lh_asset = df_best_fr_rate['lh_asset_ast'][0],\n",
" rh_asset = df_best_fr_rate['rh_asset_ast'][0],\n",
" symbol_asset_separator = '',\n",
" initial_funding_rate=float(df_best_fr_rate['funding_rate_ast'][0]),\n",
" min_price=float(df_best_fr_rate['min_price_ast'][0]),\n",
" min_order_size=float(df_best_fr_rate['min_order_size_ast'][0]),\n",
" min_lot_size=float(df_best_fr_rate['min_lot_size_ast'][0]),\n",
" min_notional=float(df_best_fr_rate['min_notional_ast'][0]),\n",
")\n",
" \n",
"EXTEND = structs.Perpetual_Exchange(\n",
" mult = int(df_best_fr_rate['max_leverage_ext'][0]),\n",
" lh_asset = df_best_fr_rate['lh_asset_ext'][0],\n",
" rh_asset = df_best_fr_rate['rh_asset_ext'][0],\n",
" symbol_asset_separator = '-',\n",
" initial_funding_rate=float(df_best_fr_rate['funding_rate_ext'][0]),\n",
" min_price=float(df_best_fr_rate['min_price_ext'][0]),\n",
" min_order_size=float(df_best_fr_rate['min_order_size_ext'][0]),\n",
" min_lot_size=float(df_best_fr_rate['min_lot_size_ext'][0]),\n",
" min_notional=float(df_best_fr_rate['min_notional_ext'][0]),\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "185c04e9",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "b7a08468",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "ca6b3810",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "cdcda9a8",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "py_313",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.13.13"
}
},
"nbformat": 4,
"nbformat_minor": 5
}