feedhandlers extended

This commit is contained in:
2026-04-23 03:11:52 +00:00
parent 408a63fe58
commit 539e6004cf
22 changed files with 1340 additions and 205 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

147
modules/aster_db.py Normal file
View File

@@ -0,0 +1,147 @@
import logging
from typing import AsyncContextManager
from sqlalchemy import text
### Orders and Trades Tables ####
async def create_fr_aster_user_order_trade_table(
CON: AsyncContextManager,
engine: str = 'mysql', # mysql | duckdb
) -> None:
if CON is None:
logging.info("NO DB CONNECTION, SKIPPING Create Statements")
else:
if engine == 'mysql':
logging.info('Creating Table if Does Not Exist: fr_aster_user_order_trade')
await CON.execute(text("""
CREATE TABLE IF NOT EXISTS fr_aster_user_order_trade (
timestamp_arrival BIGINT,
timestamp_msg BIGINT,
timestamp_value BIGINT,
symbol VARCHAR(20),
client_order_id VARCHAR(100),
side VARCHAR(20),
order_type VARCHAR(100),
time_in_force VARCHAR(20),
original_qty DOUBLE,
original_price DOUBLE,
avg_price DOUBLE,
stop_price DOUBLE,
execution_type VARCHAR(100),
order_status VARCHAR(100),
order_id BIGINT,
last_filled_qty DOUBLE,
filled_accumulated_qty DOUBLE,
last_filled_price DOUBLE,
commission_asset VARCHAR(20),
commission DOUBLE,
order_trade_time_ts BIGINT,
trade_id VARCHAR(100),
bid_notional DOUBLE,
ask_notional DOUBLE,
trade_is_maker BOOL,
trade_is_reduce_only BOOL,
stop_px_working_type VARCHAR(100),
original_order_type VARCHAR(100),
position_side VARCHAR(100),
pushed_w_conditional_order BOOL,
activation_price DOUBLE,
callback_rate DOUBLE,
realized_profit DOUBLE
);
"""))
await CON.commit()
else:
raise ValueError('Only MySQL engine is implemented')
### Margin Calls Table ####
async def create_fr_aster_user_margin_table(
CON: AsyncContextManager,
engine: str = 'mysql', # mysql | duckdb
) -> None:
if CON is None:
logging.info("NO DB CONNECTION, SKIPPING Create Statements")
else:
if engine == 'mysql':
logging.info('Creating Table if Does Not Exist: fr_aster_user_margin')
await CON.execute(text("""
CREATE TABLE IF NOT EXISTS fr_aster_user_margin (
timestamp_arrival BIGINT,
timestamp_msg BIGINT,
cross_wallet_balance DOUBLE,
symbol VARCHAR(20),
position_side VARCHAR(20),
position_amount DOUBLE,
margin_type VARCHAR(20),
isolated_wallet DOUBLE,
mark_price DOUBLE,
unrealized_pnl DOUBLE,
maint_margin_required DOUBLE
);
"""))
await CON.commit()
else:
raise ValueError('Only MySQL engine is implemented')
### Account Balance Table ####
async def create_fr_aster_user_account_bal(
CON: AsyncContextManager,
engine: str = 'mysql', # mysql | duckdb
) -> None:
if CON is None:
logging.info("NO DB CONNECTION, SKIPPING Create Statements")
else:
if engine == 'mysql':
logging.info('Creating Table if Does Not Exist: fr_aster_user_account_bal')
await CON.execute(text("""
CREATE TABLE IF NOT EXISTS fr_aster_user_account_bal (
timestamp_arrival BIGINT,
timestamp_msg BIGINT,
timestamp_transaction BIGINT,
event_reason_type VARCHAR(20),
asset VARCHAR(20),
wallet_balance DOUBLE,
cross_wallet_balance DOUBLE,
balance_change_excl_pnl_comms DOUBLE
);
"""))
await CON.commit()
else:
raise ValueError('Only MySQL engine is implemented')
### Account Positions Table ####
async def create_fr_aster_user_account_pos(
CON: AsyncContextManager,
engine: str = 'mysql', # mysql | duckdb
) -> None:
if CON is None:
logging.info("NO DB CONNECTION, SKIPPING Create Statements")
else:
if engine == 'mysql':
logging.info('Creating Table if Does Not Exist: fr_aster_user_account_pos')
await CON.execute(text("""
CREATE TABLE IF NOT EXISTS fr_aster_user_account_pos (
timestamp_arrival BIGINT,
timestamp_msg BIGINT,
timestamp_transaction BIGINT,
event_reason_type VARCHAR(20),
symbol VARCHAR(20),
position_amount DOUBLE,
entry_price DOUBLE,
accumulated_realized_pre_fees DOUBLE,
unrealized_pnl DOUBLE,
margin_type VARCHAR(20),
isolated_wallet DOUBLE,
position_side VARCHAR(20)
);
"""))
await CON.commit()
else:
raise ValueError('Only MySQL engine is implemented')

27
modules/db.py Normal file
View File

@@ -0,0 +1,27 @@
### Database Funcs ###
import logging
from typing import AsyncContextManager
import pandas as pd
async def insert_df_to_mysql(
table_name: str,
params: dict | list | pd.DataFrame,
CON: AsyncContextManager,
engine: str = 'mysql', # mysql | duckdb
) -> None:
if CON is None:
logging.info("NO DB CONNECTION, SKIPPING Insert Statements")
else:
if engine == 'mysql':
if not isinstance(params, pd.DataFrame):
if isinstance(params, dict):
params = [params]
df = pd.DataFrame(params)
await CON.run_sync(
lambda sync_conn: df.to_sql(name=table_name, con=sync_conn, if_exists='append', index=False)
)
await CON.commit()
else:
raise ValueError('Only MySQL engine is implemented')

30
modules/extended_auth.py Normal file
View File

@@ -0,0 +1,30 @@
import os
from dotenv import load_dotenv
from x10.config import MAINNET_CONFIG
from x10.core.stark_account import StarkPerpetualAccount
from x10.perpetual.trading_client import PerpetualTradingClient
import logging
async def create_auth_account_and_trading_client() -> tuple[StarkPerpetualAccount, PerpetualTradingClient]:
load_dotenv()
API_KEY = os.getenv('EXTENDED_API_KEY')
PUBLIC_KEY = os.getenv('EXTENDED_STARK_KEY_PUBLIC')
PRIVATE_KEY = os.getenv('EXTENDED_STARK_KEY_PRIVATE')
VAULT = int(os.getenv('EXTENDED_VAULT_NUMBER'))
stark_account = StarkPerpetualAccount(
vault=VAULT,
private_key=PRIVATE_KEY,
public_key=PUBLIC_KEY,
api_key=API_KEY,
)
trading_client = PerpetualTradingClient(MAINNET_CONFIG, stark_account)
try:
await trading_client.account.get_balance()
except ValueError as e:
logging.critical(f'Failed to get balance after creation of trading account: {e}')
return stark_account, trading_client

152
modules/extended_db.py Normal file
View File

@@ -0,0 +1,152 @@
import logging
from typing import AsyncContextManager
from sqlalchemy import text
### Orders Table ####
async def create_fr_extended_user_order(
CON: AsyncContextManager,
engine: str = 'mysql', # mysql | duckdb
) -> None:
if CON is None:
logging.info("NO DB CONNECTION, SKIPPING Create Statements")
else:
if engine == 'mysql':
logging.info('Creating Table if Does Not Exist: fr_extended_user_order')
await CON.execute(text("""
CREATE TABLE IF NOT EXISTS fr_extended_user_order (
sequence_id INT,
timestamp_arrival BIGINT,
timestamp_msg BIGINT,
order_id VARCHAR(100),
account_id VARCHAR(100),
external_id VARCHAR(100),
market VARCHAR(20),
type VARCHAR(20),
side VARCHAR(20),
status VARCHAR(20),
status_reason VARCHAR(100),
price DOUBLE,
averagePrice DOUBLE,
qty DOUBLE,
filled_qty DOUBLE,
payed_fee DOUBLE,
tp_sl_type VARCHAR(20),
reduce_only BOOL,
post_only BOOL,
created_time_ts BIGINT,
updated_time_ts BIGINT,
expire_time_ts BIGINT
);
"""))
await CON.commit()
else:
raise ValueError('Only MySQL engine is implemented')
### Orders Table ####
async def create_fr_extended_user_trade(
CON: AsyncContextManager,
engine: str = 'mysql', # mysql | duckdb
) -> None:
if CON is None:
logging.info("NO DB CONNECTION, SKIPPING Create Statements")
else:
if engine == 'mysql':
logging.info('Creating Table if Does Not Exist: fr_extended_user_trade')
await CON.execute(text("""
CREATE TABLE IF NOT EXISTS fr_extended_user_trade (
sequence_id INT,
timestamp_arrival BIGINT,
timestamp_msg BIGINT,
trade_id VARCHAR(100),
account_id VARCHAR(100),
market VARCHAR(20),
order_id VARCHAR(100),
external_order_id VARCHAR(100),
side VARCHAR(20),
price DOUBLE,
qty DOUBLE,
value DOUBLE,
fee DOUBLE,
trade_type VARCHAR(20),
created_time_ts BIGINT,
is_taker BOOL
);
"""))
await CON.commit()
else:
raise ValueError('Only MySQL engine is implemented')
### Balance Table ####
async def create_fr_extended_user_balance(
CON: AsyncContextManager,
engine: str = 'mysql', # mysql | duckdb
) -> None:
if CON is None:
logging.info("NO DB CONNECTION, SKIPPING Create Statements")
else:
if engine == 'mysql':
logging.info('Creating Table if Does Not Exist: fr_extended_user_balance')
await CON.execute(text("""
CREATE TABLE IF NOT EXISTS fr_extended_user_balance (
sequence_id INT,
timestamp_arrival BIGINT,
timestamp_msg BIGINT,
collateral_name VARCHAR(20),
balance DOUBLE,
equity DOUBLE,
available_for_trade DOUBLE,
available_for_withdrawal DOUBLE,
unrealised_pnl DOUBLE,
initial_margin DOUBLE,
margin_ratio DOUBLE,
updated_time_ts BIGINT,
exposure DOUBLE,
leverage DOUBLE
);
"""))
await CON.commit()
else:
raise ValueError('Only MySQL engine is implemented')
### Balance Table ####
async def create_fr_extended_user_position(
CON: AsyncContextManager,
engine: str = 'mysql', # mysql | duckdb
) -> None:
if CON is None:
logging.info("NO DB CONNECTION, SKIPPING Create Statements")
else:
if engine == 'mysql':
logging.info('Creating Table if Does Not Exist: fr_extended_user_position')
await CON.execute(text("""
CREATE TABLE IF NOT EXISTS fr_extended_user_position (
sequence_id INT,
timestamp_arrival BIGINT,
timestamp_msg BIGINT,
position_id VARCHAR(100),
account_id VARCHAR(100),
market VARCHAR(20),
side VARCHAR(20),
leverage DOUBLE,
size DOUBLE,
value DOUBLE,
open_price DOUBLE,
mark_price DOUBLE,
liquidation_price DOUBLE,
margin DOUBLE,
unrealised_pnl DOUBLE,
realised_pnl DOUBLE,
tp_trigger_price DOUBLE,
tp_limit_price DOUBLE,
sl_trigger_price DOUBLE,
sl_limit_price DOUBLE,
adl_percentile INT,
created_at_ts BIGINT,
updated_at_ts BIGINT
);
"""))
await CON.commit()
else:
raise ValueError('Only MySQL engine is implemented')