gate_dash / app.py
luguog's picture
Update app.py
dbcee54 verified
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("""
<style>
.stApp {
background: linear-gradient(145deg, #1a1a1a, #2d2d2d);
color: #ffffff;
}
.stButton>button {
background: linear-gradient(145deg, #ff6b00, #ff8533);
border: none;
border-radius: 10px;
box-shadow: 5px 5px 10px rgba(0,0,0,0.3),
-5px -5px 10px rgba(255,255,255,0.1);
color: white;
padding: 10px 20px;
transition: all 0.3s ease;
}
.stButton>button:hover {
transform: translateY(-2px);
box-shadow: 6px 6px 12px rgba(0,0,0,0.4),
-6px -6px 12px rgba(255,255,255,0.15);
}
.stSelectbox>div>div>select {
background: linear-gradient(145deg, #2d2d2d, #1a1a1a);
color: white;
border-radius: 10px;
box-shadow: inset 3px 3px 6px rgba(0,0,0,0.3),
inset -3px -3px 6px rgba(255,255,255,0.1);
}
.stSlider>div>div>div {
background: linear-gradient(145deg, #ff6b00, #ff8533);
}
.stMarkdown {
color: #ffffff;
}
.stDataFrame {
background: linear-gradient(145deg, #2d2d2d, #1a1a1a);
border-radius: 15px;
padding: 20px;
box-shadow: 5px 5px 10px rgba(0,0,0,0.3),
-5px -5px 10px rgba(255,255,255,0.1);
}
.error-message {
color: #ff4444;
background: rgba(255,68,68,0.1);
padding: 10px;
border-radius: 10px;
margin: 10px 0;
}
</style>
""", 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