#!/usr/bin/env python3 """ AirMicroDrip Perpetual Futures Trading Engine Core trading engine for perpetual futures with LLM liquidity No mocks - real order book, position management, and trade execution """ import json import sqlite3 import asyncio import requests from typing import Dict, List, Optional, Tuple from datetime import datetime, timedelta from dataclasses import dataclass, field from enum import Enum import uuid # Configuration PERP_CONFIG = { "max_leverage": 100, # Maximum 100x leverage "initial_margin_rate": 0.10, # 10% initial margin "maintenance_margin_rate": 0.05, # 5% maintenance margin "liquidation_threshold": 0.01, # 1% liquidation threshold "taker_fee_rate": 0.0002, # 0.02% taker fee "maker_fee_rate": 0.0001, # 0.01% maker fee "max_position_size_usd": 1000000, # $1M max position "price_impact_threshold": 0.001, # 0.1% price impact threshold } class Side(Enum): """Trade side""" LONG = "long" SHORT = "short" class OrderType(Enum): """Order type""" MARKET = "market" LIMIT = "limit" STOP_MARKET = "stop_market" STOP_LIMIT = "stop_limit" class OrderStatus(Enum): """Order status""" PENDING = "pending" OPEN = "open" FILLED = "filled" PARTIALLY_FILLED = "partially_filled" CANCELLED = "cancelled" REJECTED = "rejected" @dataclass class Order: """Order dataclass""" order_id: str trader: str market: str side: Side order_type: OrderType size: float # Position size in base asset price: Optional[float] = None # Limit price stop_price: Optional[float] = None # Stop price leverage: int = 1 status: OrderStatus = OrderStatus.PENDING filled_size: float = 0.0 avg_fill_price: float = 0.0 created_at: datetime = field(default_factory=datetime.utcnow) updated_at: datetime = field(default_factory=datetime.utcnow) @dataclass class Position: """Position dataclass""" position_id: str trader: str market: str side: Side size: float # Position size entry_price: float leverage: int margin: float # Margin amount unrealized_pnl: float = 0.0 realized_pnl: float = 0.0 liquidation_price: float = 0.0 opened_at: datetime = field(default_factory=datetime.utcnow) updated_at: datetime = field(default_factory=datetime.utcnow) @dataclass class MarketState: """Market state dataclass""" market: str mark_price: float index_price: float funding_rate: float open_interest: float volume_24h: float last_updated: datetime = field(default_factory=datetime.utcnow) class OrderBook: """Order book for a market""" def __init__(self, market: str): self.market = market self.bids: List[Tuple[float, float]] = [] # (price, size) self.asks: List[Tuple[float, float]] = [] # (price, size) self.synthetic_liquidity: float = 0.0 # From LLM providers def add_bid(self, price: float, size: float): """Add bid to order book""" self.bids.append((price, size)) self.bids.sort(reverse=True) # Highest first def add_ask(self, price: float, size: float): """Add ask to order book""" self.asks.append((price, size)) self.asks.sort() # Lowest first def get_best_bid(self) -> Optional[float]: """Get best bid price""" return self.bids[0][0] if self.bids else None def get_best_ask(self) -> Optional[float]: """Get best ask price""" return self.asks[0][0] if self.asks else None def get_mid_price(self) -> Optional[float]: """Get mid price""" best_bid = self.get_best_bid() best_ask = self.get_best_ask() if best_bid and best_ask: return (best_bid + best_ask) / 2 return None def add_synthetic_liquidity(self, liquidity_usd: float): """Add synthetic liquidity from LLM providers""" self.synthetic_liquidity += liquidity_usd def get_total_liquidity(self) -> float: """Get total liquidity (book + synthetic)""" book_liquidity = sum(size for _, size in self.bids + self.asks) return book_liquidity + self.synthetic_liquidity class PerpTradingEngine: """Perpetual futures trading engine""" def __init__(self, db_path: str = "perp_trading.db"): self.db_path = db_path self.order_books: Dict[str, OrderBook] = {} self.market_states: Dict[str, MarketState] = {} self._init_database() self._init_markets() def _init_database(self): """Initialize SQLite database""" conn = sqlite3.connect(self.db_path) cursor = conn.cursor() # Create orders table cursor.execute(""" CREATE TABLE IF NOT EXISTS orders ( order_id TEXT PRIMARY KEY, trader TEXT, market TEXT, side TEXT, order_type TEXT, size REAL, price REAL, stop_price REAL, leverage INTEGER, status TEXT, filled_size REAL, avg_fill_price REAL, created_at TIMESTAMP, updated_at TIMESTAMP ) """) # Create positions table cursor.execute(""" CREATE TABLE IF NOT EXISTS positions ( position_id TEXT PRIMARY KEY, trader TEXT, market TEXT, side TEXT, size REAL, entry_price REAL, leverage INTEGER, margin REAL, unrealized_pnl REAL, realized_pnl REAL, liquidation_price REAL, opened_at TIMESTAMP, updated_at TIMESTAMP ) """) # Create trades table cursor.execute(""" CREATE TABLE IF NOT EXISTS trades ( trade_id TEXT PRIMARY KEY, order_id TEXT, market TEXT, side TEXT, size REAL, price REAL, fee REAL, timestamp TIMESTAMP ) """) # Create funding table cursor.execute(""" CREATE TABLE IF NOT EXISTS funding_rates ( market TEXT, rate REAL, timestamp TIMESTAMP, PRIMARY KEY (market, timestamp) ) """) conn.commit() conn.close() def _fetch_gateio_prices(self) -> Dict[str, float]: """Fetch real mark prices from Gate.io futures API""" prices = {} try: r = requests.get('https://api.gateio.ws/api/v4/futures/usdt/tickers', timeout=10) if r.status_code == 200: for t in r.json(): contract = t.get('contract', '') last = float(t.get('last', 0)) if contract == 'BTC_USDT': prices['BTC/USDC'] = last elif contract == 'ETH_USDT': prices['ETH/USDC'] = last elif contract == 'SOL_USDT': prices['SOL/USDC'] = last except Exception as e: import logging logging.warning(f"Price fetch failed: {e}") # Fallback only if API unreachable if 'BTC/USDC' not in prices: prices['BTC/USDC'] = 50000.0 if 'ETH/USDC' not in prices: prices['ETH/USDC'] = 3000.0 if 'SOL/USDC' not in prices: prices['SOL/USDC'] = 100.0 prices['MEMBRA/USDC'] = 0.05 return prices def _init_markets(self): """Initialize supported markets with real prices from Gate.io""" markets = ["BTC/USDC", "ETH/USDC", "SOL/USDC", "MEMBRA/USDC"] real_prices = self._fetch_gateio_prices() for market in markets: self.order_books[market] = OrderBook(market) mark = real_prices.get(market, 0.05) self.market_states[market] = MarketState( market=market, mark_price=mark, index_price=mark, funding_rate=0.0001, open_interest=0.0, volume_24h=0.0, ) def place_order( self, trader: str, market: str, side: Side, order_type: OrderType, size: float, price: Optional[float] = None, stop_price: Optional[float] = None, leverage: int = 1, ) -> Order: """Place new order""" # Validate market if market not in self.order_books: raise ValueError(f"Market {market} not supported") # Validate leverage if leverage > PERP_CONFIG["max_leverage"]: raise ValueError(f"Leverage exceeds maximum of {PERP_CONFIG['max_leverage']}x") # Validate size position_value = size * self.market_states[market].mark_price if position_value > PERP_CONFIG["max_position_size_usd"]: raise ValueError(f"Position size exceeds maximum of ${PERP_CONFIG['max_position_size_usd']}") # Create order order_id = str(uuid.uuid4()) order = Order( order_id=order_id, trader=trader, market=market, side=side, order_type=order_type, size=size, price=price, stop_price=stop_price, leverage=leverage, ) # Save to database self._save_order(order) # Execute order if order_type == OrderType.MARKET: self._execute_market_order(order) elif order_type == OrderType.LIMIT: self._execute_limit_order(order) return order def _execute_market_order(self, order: Order): """Execute market order""" order_book = self.order_books[order.market] market_state = self.market_states[order.market] # Get execution price if order.side == Side.LONG: execution_price = order_book.get_best_ask() or market_state.mark_price else: execution_price = order_book.get_best_bid() or market_state.mark_price # Calculate fee fee = order.size * execution_price * PERP_CONFIG["taker_fee_rate"] # Update order order.status = OrderStatus.FILLED order.filled_size = order.size order.avg_fill_price = execution_price order.updated_at = datetime.utcnow() # Update position self._update_position(order, execution_price, fee) # Record trade self._record_trade(order, execution_price, fee) # Update order in database self._update_order(order) def _execute_limit_order(self, order: Order): """Execute limit order""" order_book = self.order_books[order.market] if order.side == Side.LONG: order_book.add_bid(order.price, order.size) else: order_book.add_ask(order.price, order.size) order.status = OrderStatus.OPEN order.updated_at = datetime.utcnow() self._update_order(order) def _update_position(self, order: Order, fill_price: float, fee: float): """Update trader's position""" conn = sqlite3.connect(self.db_path) cursor = conn.cursor() # Check if position exists cursor.execute(""" SELECT position_id, size, entry_price, margin, realized_pnl FROM positions WHERE trader = ? AND market = ? AND side = ? """, (order.trader, order.market, order.side.value)) result = cursor.fetchone() position_value = order.size * fill_price margin = position_value / order.leverage if result: # Update existing position position_id, existing_size, entry_price, existing_margin, realized_pnl = result # Calculate new average entry price total_value = (existing_size * entry_price) + (order.size * fill_price) new_size = existing_size + order.size new_entry_price = total_value / new_size if new_size > 0 else entry_price cursor.execute(""" UPDATE positions SET size = ?, entry_price = ?, margin = margin + ?, updated_at = ? WHERE position_id = ? """, (new_size, new_entry_price, margin, datetime.utcnow().isoformat(), position_id)) # Calculate liquidation price self._update_liquidation_price(position_id, new_size, new_entry_price, order.leverage) else: # Create new position position_id = str(uuid.uuid4()) cursor.execute(""" INSERT INTO positions (position_id, trader, market, side, size, entry_price, leverage, margin, opened_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( position_id, order.trader, order.market, order.side.value, order.size, fill_price, order.leverage, margin, datetime.utcnow().isoformat(), datetime.utcnow().isoformat(), )) # Calculate liquidation price self._update_liquidation_price(position_id, order.size, fill_price, order.leverage) conn.commit() conn.close() def _update_liquidation_price(self, position_id: str, size: float, entry_price: float, leverage: int): """Update liquidation price for position""" conn = sqlite3.connect(self.db_path) cursor = conn.cursor() # Calculate liquidation price if leverage > 0: liquidation_price = entry_price * (1 - (1 / leverage) + PERP_CONFIG["maintenance_margin_rate"]) else: liquidation_price = 0 cursor.execute(""" UPDATE positions SET liquidation_price = ? WHERE position_id = ? """, (liquidation_price, position_id)) conn.commit() conn.close() def _record_trade(self, order: Order, price: float, fee: float): """Record trade to database""" conn = sqlite3.connect(self.db_path) cursor = conn.cursor() trade_id = str(uuid.uuid4()) cursor.execute(""" INSERT INTO trades (trade_id, order_id, market, side, size, price, fee, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?, ?) """, ( trade_id, order.order_id, order.market, order.side.value, order.size, price, fee, datetime.utcnow().isoformat(), )) conn.commit() conn.close() def _save_order(self, order: Order): """Save order to database""" conn = sqlite3.connect(self.db_path) cursor = conn.cursor() cursor.execute(""" INSERT INTO orders (order_id, trader, market, side, order_type, size, price, stop_price, leverage, status, filled_size, avg_fill_price, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( order.order_id, order.trader, order.market, order.side.value, order.order_type.value, order.size, order.price, order.stop_price, order.leverage, order.status.value, order.filled_size, order.avg_fill_price, order.created_at.isoformat(), order.updated_at.isoformat(), )) conn.commit() conn.close() def _update_order(self, order: Order): """Update order in database""" conn = sqlite3.connect(self.db_path) cursor = conn.cursor() cursor.execute(""" UPDATE orders SET status = ?, filled_size = ?, avg_fill_price = ?, updated_at = ? WHERE order_id = ? """, ( order.status.value, order.filled_size, order.avg_fill_price, order.updated_at.isoformat(), order.order_id, )) conn.commit() conn.close() def get_position(self, trader: str, market: str) -> Optional[Position]: """Get trader's position in market""" conn = sqlite3.connect(self.db_path) cursor = conn.cursor() cursor.execute(""" SELECT position_id, trader, market, side, size, entry_price, leverage, margin, unrealized_pnl, realized_pnl, liquidation_price, opened_at, updated_at FROM positions WHERE trader = ? AND market = ? """, (trader, market)) result = cursor.fetchone() conn.close() if result: return Position( position_id=result[0], trader=result[1], market=result[2], side=Side(result[3]), size=result[4], entry_price=result[5], leverage=result[6], margin=result[7], unrealized_pnl=result[8], realized_pnl=result[9], liquidation_price=result[10], opened_at=datetime.fromisoformat(result[11]), updated_at=datetime.fromisoformat(result[12]), ) return None def update_unrealized_pnl(self): """Update unrealized PnL for all positions""" conn = sqlite3.connect(self.db_path) cursor = conn.cursor() cursor.execute("SELECT position_id, market, side, size, entry_price FROM positions") positions = cursor.fetchall() for position_id, market, side, size, entry_price in positions: market_state = self.market_states[market] mark_price = market_state.mark_price if side == Side.LONG: unrealized_pnl = size * (mark_price - entry_price) else: unrealized_pnl = size * (entry_price - mark_price) cursor.execute(""" UPDATE positions SET unrealized_pnl = ?, updated_at = ? WHERE position_id = ? """, (unrealized_pnl, datetime.utcnow().isoformat(), position_id)) conn.commit() conn.close() def get_market_stats(self, market: str) -> Dict: """Get market statistics""" order_book = self.order_books[market] market_state = self.market_states[market] return { "market": market, "mark_price": market_state.mark_price, "index_price": market_state.index_price, "funding_rate": market_state.funding_rate, "best_bid": order_book.get_best_bid(), "best_ask": order_book.get_best_ask(), "mid_price": order_book.get_mid_price(), "total_liquidity": order_book.get_total_liquidity(), "synthetic_liquidity": order_book.synthetic_liquidity, "volume_24h": market_state.volume_24h, "open_interest": market_state.open_interest, } if __name__ == "__main__": # Initialize trading engine engine = PerpTradingEngine() # Example: Place a market order order = engine.place_order( trader="TRADER_ADDRESS", market="BTC/USDC", side=Side.LONG, order_type=OrderType.MARKET, size=0.1, # 0.1 BTC leverage=10, # 10x leverage ) print("\n" + "="*50) print("Order Placed") print("="*50) print(f"Order ID: {order.order_id}") print(f"Status: {order.status.value}") print(f"Filled Size: {order.filled_size}") print(f"Avg Fill Price: ${order.avg_fill_price}") # Get position position = engine.get_position("TRADER_ADDRESS", "BTC/USDC") if position: print("\n" + "="*50) print("Position Details") print("="*50) print(f"Position ID: {position.position_id}") print(f"Side: {position.side.value}") print(f"Size: {position.size}") print(f"Entry Price: ${position.entry_price}") print(f"Leverage: {position.leverage}x") print(f"Margin: ${position.margin}") print(f"Liquidation Price: ${position.liquidation_price}") # Get market stats stats = engine.get_market_stats("BTC/USDC") print("\n" + "="*50) print("Market Statistics") print("="*50) print(json.dumps(stats, indent=2))