Dumb.io commited on
Commit
7a18a8b
Β·
1 Parent(s): 95fedd7

Add API base URL and enhance error handling

Browse files
Files changed (2) hide show
  1. .streamlit/secrets.toml +3 -2
  2. gate_tracker.py +213 -1
.streamlit/secrets.toml CHANGED
@@ -1,6 +1,7 @@
1
  # API Credentials
2
- GATE_API_KEY = "your_api_key_here"
3
- GATE_API_SECRET = "your_api_secret_here"
 
4
 
5
  # Theme Configuration
6
  [theme]
 
1
  # API Credentials
2
+ GATE_API_KEY = "4efbe203fbac0e4bcd0003a0910c801b"
3
+ GATE_API_SECRET = "8b0e9cf47fdd97f2a42bca571a74105c53a5f906cd4ada125938d05115d063a0"
4
+ GATE_API_BASE = "https://api.gate.io/api/v4"
5
 
6
  # Theme Configuration
7
  [theme]
gate_tracker.py CHANGED
@@ -1 +1,213 @@
1
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import ccxt
3
+ import pandas as pd
4
+ import numpy as np
5
+ import time
6
+ from datetime import datetime
7
+ import os
8
+ from dotenv import load_dotenv
9
+ from rich.console import Console
10
+
11
+ # Set page config
12
+ st.set_page_config(
13
+ page_title="Gate.io Market Making Dashboard",
14
+ page_icon="πŸ“Š",
15
+ layout="wide",
16
+ initial_sidebar_state="expanded"
17
+ )
18
+
19
+ # Custom CSS for enhanced neumorphism
20
+ st.markdown("""
21
+ <style>
22
+ .stApp {
23
+ background: linear-gradient(145deg, #1a1a1a, #2d2d2d);
24
+ color: #ffffff;
25
+ }
26
+ .stButton>button {
27
+ background: linear-gradient(145deg, #ff6b00, #ff8533);
28
+ border: none;
29
+ border-radius: 10px;
30
+ box-shadow: 5px 5px 10px rgba(0,0,0,0.3),
31
+ -5px -5px 10px rgba(255,255,255,0.1);
32
+ color: white;
33
+ padding: 10px 20px;
34
+ transition: all 0.3s ease;
35
+ }
36
+ .stButton>button:hover {
37
+ transform: translateY(-2px);
38
+ box-shadow: 6px 6px 12px rgba(0,0,0,0.4),
39
+ -6px -6px 12px rgba(255,255,255,0.15);
40
+ }
41
+ .stSelectbox>div>div>select {
42
+ background: linear-gradient(145deg, #2d2d2d, #1a1a1a);
43
+ color: white;
44
+ border-radius: 10px;
45
+ box-shadow: inset 3px 3px 6px rgba(0,0,0,0.3),
46
+ inset -3px -3px 6px rgba(255,255,255,0.1);
47
+ }
48
+ .stSlider>div>div>div {
49
+ background: linear-gradient(145deg, #ff6b00, #ff8533);
50
+ }
51
+ .stMarkdown {
52
+ color: #ffffff;
53
+ }
54
+ .stDataFrame {
55
+ background: linear-gradient(145deg, #2d2d2d, #1a1a1a);
56
+ border-radius: 15px;
57
+ padding: 20px;
58
+ box-shadow: 5px 5px 10px rgba(0,0,0,0.3),
59
+ -5px -5px 10px rgba(255,255,255,0.1);
60
+ }
61
+ .error-message {
62
+ color: #ff4444;
63
+ background: rgba(255,68,68,0.1);
64
+ padding: 10px;
65
+ border-radius: 10px;
66
+ margin: 10px 0;
67
+ }
68
+ </style>
69
+ """, unsafe_allow_html=True)
70
+
71
+ # Load environment variables
72
+ load_dotenv()
73
+
74
+ # Initialize Gate.io exchange
75
+ try:
76
+ exchange = ccxt.gateio({
77
+ 'apiKey': st.secrets["GATE_API_KEY"],
78
+ 'secret': st.secrets["GATE_API_SECRET"],
79
+ 'enableRateLimit': True,
80
+ 'options': {
81
+ 'defaultType': 'swap',
82
+ 'defaultSettle': 'usdt',
83
+ },
84
+ 'urls': {
85
+ 'api': {
86
+ 'rest': st.secrets["GATE_API_BASE"]
87
+ }
88
+ }
89
+ })
90
+
91
+ # Test API connection
92
+ exchange.load_markets()
93
+ st.success("βœ… Successfully connected to Gate.io API")
94
+ except Exception as e:
95
+ st.error(f"❌ Failed to connect to Gate.io API: {str(e)}")
96
+ st.stop()
97
+
98
+ st.title("Gate.io Futures Live Data")
99
+
100
+ # Position Control Parameters
101
+ col1, col2, col3 = st.columns(3)
102
+
103
+ with col1:
104
+ min_spread = st.slider("Minimum Spread %", 0.3, 5.0, 0.5, 0.1)
105
+ min_volume = st.slider("Minimum 24h Volume (USDT)", 100000, 1000000, 200000, 10000)
106
+
107
+ with col2:
108
+ max_positions = st.slider("Max Active Positions", 1, 10, 3, 1)
109
+ dca_multiplier = st.slider("DCA Size Multiplier", 1.0, 5.0, 2.0, 0.5)
110
+
111
+ with col3:
112
+ hedge_ratio = st.slider("Hedge Ratio", 0.5, 2.0, 1.0, 0.1)
113
+ leverage = st.slider("Leverage", 1, 10, 3, 1)
114
+
115
+ def fetch_market_data():
116
+ try:
117
+ markets = exchange.load_markets()
118
+ usdt_pairs = [symbol for symbol in markets.keys()
119
+ if "/USDT" in symbol and markets[symbol].get("type") == "swap"]
120
+
121
+ data = []
122
+ for symbol in usdt_pairs:
123
+ try:
124
+ ticker = exchange.fetch_ticker(symbol)
125
+ price = ticker['last']
126
+ volume_24h = ticker['quoteVolume']
127
+
128
+ orderbook = exchange.fetch_order_book(symbol)
129
+ if orderbook['asks'] and orderbook['bids']:
130
+ spread = orderbook['asks'][0][0] - orderbook['bids'][0][0]
131
+ spread_pct = (spread / price) * 100
132
+
133
+ # Calculate liquidity metrics
134
+ bid_depth = sum(bid[1] for bid in orderbook['bids'][:5])
135
+ ask_depth = sum(ask[1] for ask in orderbook['asks'][:5])
136
+ total_depth = bid_depth + ask_depth
137
+
138
+ # Calculate volatility
139
+ ohlcv = exchange.fetch_ohlcv(symbol, timeframe='1h', limit=24)
140
+ if len(ohlcv) > 0:
141
+ prices = [x[4] for x in ohlcv] # Close prices
142
+ volatility = np.std(prices) / np.mean(prices) * 100
143
+ else:
144
+ volatility = 0
145
+
146
+ # Calculate market making score (0-100)
147
+ spread_score = max(0, 100 - (spread_pct * 20)) # Lower spread = higher score
148
+ volume_score = min(100, volume_24h / min_volume * 100) # Higher volume = higher score
149
+ depth_score = min(100, total_depth / 100) # Higher depth = higher score
150
+ volatility_score = max(0, 100 - (volatility * 10)) # Lower volatility = higher score
151
+
152
+ mm_score = (spread_score + volume_score + depth_score + volatility_score) / 4
153
+
154
+ if volume_24h >= min_volume and spread_pct >= min_spread:
155
+ data.append({
156
+ 'Symbol': symbol,
157
+ 'Price': price,
158
+ 'Spread %': spread_pct,
159
+ '24h Volume (USDT)': volume_24h,
160
+ 'Total Depth': total_depth,
161
+ 'Volatility %': volatility,
162
+ 'MM Score': mm_score
163
+ })
164
+ except Exception as e:
165
+ st.error(f"Error fetching data for {symbol}: {str(e)}")
166
+ continue
167
+
168
+ if not data:
169
+ st.warning("No market data available matching the criteria")
170
+ return None
171
+
172
+ df = pd.DataFrame(data)
173
+ df = df.dropna()
174
+ return df
175
+
176
+ except Exception as e:
177
+ st.error(f"Error fetching market data: {str(e)}")
178
+ return None
179
+
180
+ # Create containers for tables
181
+ spread_container = st.empty()
182
+ position_container = st.empty()
183
+
184
+ while True:
185
+ try:
186
+ df = fetch_market_data()
187
+
188
+ if df is not None and not df.empty:
189
+ # Sort by market making score (highest first)
190
+ df_sorted = df.sort_values(by='MM Score', ascending=False)
191
+
192
+ # Update spread data
193
+ with spread_container.container():
194
+ st.markdown("### πŸ“ˆ Best Market Making Opportunities")
195
+ st.dataframe(
196
+ df_sorted[['Symbol', 'Price', 'Spread %', '24h Volume (USDT)', 'MM Score']].head(33),
197
+ use_container_width=True
198
+ )
199
+
200
+ # Update position data
201
+ with position_container.container():
202
+ st.markdown("### πŸ’° Active Positions")
203
+ st.dataframe(
204
+ df_sorted[['Symbol', 'Price', 'Spread %', 'Total Depth', 'Volatility %']].head(max_positions),
205
+ use_container_width=True
206
+ )
207
+
208
+ time.sleep(3) # Update every 3 seconds
209
+
210
+ except Exception as e:
211
+ st.error(f"Error in main loop: {str(e)}")
212
+ time.sleep(3)
213
+ continue