import streamlit as st import ccxt import pandas as pd import numpy as np import time from datetime import datetime import os from dotenv import load_dotenv from rich.console import Console # Set page config st.set_page_config( page_title="Gate.io Market Making Dashboard", page_icon="📊", layout="wide", initial_sidebar_state="expanded" ) # Custom CSS for enhanced neumorphism st.markdown(""" """, unsafe_allow_html=True) # Load environment variables load_dotenv() # Initialize Gate.io exchange try: exchange = ccxt.gateio({ 'apiKey': st.secrets["GATE_API_KEY"], 'secret': st.secrets["GATE_API_SECRET"], 'enableRateLimit': True, 'options': { 'defaultType': 'swap', 'defaultSettle': 'usdt', }, 'urls': { 'api': { 'rest': st.secrets["GATE_API_BASE"] } } }) # Test API connection exchange.load_markets() st.success("✅ Successfully connected to Gate.io API") except Exception as e: st.error(f"❌ Failed to connect to Gate.io API: {str(e)}") st.stop() st.title("Gate.io Futures Live Data") # Position Control Parameters col1, col2, col3 = st.columns(3) with col1: min_spread = st.slider("Minimum Spread %", 0.3, 5.0, 0.5, 0.1) min_volume = st.slider("Minimum 24h Volume (USDT)", 100000, 1000000, 200000, 10000) with col2: max_positions = st.slider("Max Active Positions", 1, 10, 3, 1) dca_multiplier = st.slider("DCA Size Multiplier", 1.0, 5.0, 2.0, 0.5) with col3: hedge_ratio = st.slider("Hedge Ratio", 0.5, 2.0, 1.0, 0.1) leverage = st.slider("Leverage", 1, 10, 3, 1) def fetch_market_data(): try: markets = exchange.load_markets() usdt_pairs = [symbol for symbol in markets.keys() if "/USDT" in symbol and markets[symbol].get("type") == "swap"] data = [] for symbol in usdt_pairs: try: ticker = exchange.fetch_ticker(symbol) price = ticker['last'] volume_24h = ticker['quoteVolume'] orderbook = exchange.fetch_order_book(symbol) if orderbook['asks'] and orderbook['bids']: spread = orderbook['asks'][0][0] - orderbook['bids'][0][0] spread_pct = (spread / price) * 100 # Calculate liquidity metrics bid_depth = sum(bid[1] for bid in orderbook['bids'][:5]) ask_depth = sum(ask[1] for ask in orderbook['asks'][:5]) total_depth = bid_depth + ask_depth # Calculate volatility ohlcv = exchange.fetch_ohlcv(symbol, timeframe='1h', limit=24) if len(ohlcv) > 0: prices = [x[4] for x in ohlcv] # Close prices volatility = np.std(prices) / np.mean(prices) * 100 else: volatility = 0 # Calculate market making score (0-100) spread_score = max(0, 100 - (spread_pct * 20)) # Lower spread = higher score volume_score = min(100, volume_24h / min_volume * 100) # Higher volume = higher score depth_score = min(100, total_depth / 100) # Higher depth = higher score volatility_score = max(0, 100 - (volatility * 10)) # Lower volatility = higher score mm_score = (spread_score + volume_score + depth_score + volatility_score) / 4 if volume_24h >= min_volume and spread_pct >= min_spread: data.append({ 'Symbol': symbol, 'Price': price, 'Spread %': spread_pct, '24h Volume (USDT)': volume_24h, 'Total Depth': total_depth, 'Volatility %': volatility, 'MM Score': mm_score }) except Exception as e: st.error(f"Error fetching data for {symbol}: {str(e)}") continue if not data: st.warning("No market data available matching the criteria") return None df = pd.DataFrame(data) df = df.dropna() return df except Exception as e: st.error(f"Error fetching market data: {str(e)}") return None # Create containers for tables spread_container = st.empty() position_container = st.empty() while True: try: df = fetch_market_data() if df is not None and not df.empty: # Sort by market making score (highest first) df_sorted = df.sort_values(by='MM Score', ascending=False) # Update spread data with spread_container.container(): st.markdown("### 📈 Best Market Making Opportunities") st.dataframe( df_sorted[['Symbol', 'Price', 'Spread %', '24h Volume (USDT)', 'MM Score']].head(33), use_container_width=True ) # Update position data with position_container.container(): st.markdown("### 💰 Active Positions") st.dataframe( df_sorted[['Symbol', 'Price', 'Spread %', 'Total Depth', 'Volatility %']].head(max_positions), use_container_width=True ) time.sleep(3) # Update every 3 seconds except Exception as e: st.error(f"Error in main loop: {str(e)}") time.sleep(3) continue