luguog commited on
Commit
479f832
Β·
verified Β·
1 Parent(s): 6275046

Upload 5 files

Browse files
Files changed (5) hide show
  1. README.md +15 -5
  2. main.py +118 -0
  3. public/index.html +83 -0
  4. requirements.txt +4 -0
  5. trading_log.json +0 -0
README.md CHANGED
@@ -1,10 +1,20 @@
1
  ---
2
- title: Gate6
3
- emoji: πŸ“Š
4
- colorFrom: yellow
5
  colorTo: gray
6
  sdk: docker
7
- pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: gate6
3
+ emoji: πŸš€
4
+ colorFrom: red
5
  colorTo: gray
6
  sdk: docker
7
+ sdk_version: "1.0"
8
+ app_file: main.py
9
+ pinned: true
10
  ---
11
 
12
+ # Gate6: GPT + Freqtrade + CCXT + Proxy + Dashboard
13
+
14
+ - `/balance`, `/log_trade`, `/performance`, `/proxy`
15
+ - Now with πŸ”₯ orange-glass dark neuromorphic dashboard!
16
+ - UI available at `/` β€” calls live API endpoints
17
+
18
+ ## Secrets
19
+ - `GATE_API_KEY`
20
+ - `GATE_API_SECRET`
main.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, Request
2
+ from fastapi.responses import HTMLResponse, FileResponse
3
+ import os, time, hmac, hashlib, requests, json
4
+
5
+ app = FastAPI()
6
+
7
+ GATE_API_KEY = os.getenv("GATE_API_KEY")
8
+ GATE_API_SECRET = os.getenv("GATE_API_SECRET")
9
+ GATE_API_BASE = "https://api.gate.io/api/v4"
10
+
11
+ LOG_FILE = "trading_log.json"
12
+ BAL_FILE = "balance_snapshots.json"
13
+
14
+ @app.get("/")
15
+ def home():
16
+ return HTMLResponse("""
17
+ <html><body>
18
+ <h2>πŸš€ gate4: Live Gate.io GPT API</h2>
19
+ <p>Endpoints:</p>
20
+ <ul>
21
+ <li>/balance</li>
22
+ <li>/performance</li>
23
+ <li>/log_trade</li>
24
+ <li>/openapi.yaml</li>
25
+ </ul>
26
+ </body></html>
27
+ """)
28
+
29
+ @app.get("/openapi.yaml")
30
+ def get_openapi():
31
+ return FileResponse("openapi.yaml", media_type="text/yaml")
32
+
33
+ @app.get("/balance")
34
+ def get_balance():
35
+ path = "/futures/usdt/accounts"
36
+ method = "GET"
37
+ timestamp = str(int(time.time()))
38
+ body = ""
39
+ query = ""
40
+ sign = sign_request(method, path, query, body, timestamp)
41
+
42
+ headers = {
43
+ "KEY": GATE_API_KEY,
44
+ "Timestamp": timestamp,
45
+ "SIGN": sign
46
+ }
47
+
48
+ url = f"{GATE_API_BASE}{path}"
49
+ res = requests.get(url, headers=headers)
50
+ res.raise_for_status()
51
+
52
+ accounts = res.json()
53
+ total = sum(float(acc.get("available", 0)) for acc in accounts)
54
+
55
+ log_balance(total)
56
+ return {"balance": round(total, 2)}
57
+
58
+ @app.get("/performance")
59
+ def get_performance():
60
+ if not os.path.exists(LOG_FILE):
61
+ return {"summary": "No trades logged yet."}
62
+
63
+ with open(LOG_FILE, "r") as f:
64
+ trades = [json.loads(line) for line in f if line.strip()]
65
+
66
+ total_pnl = sum(t.get("pnl_estimate", 0) for t in trades)
67
+ summary = f"πŸ“Š Total PnL: ${total_pnl:.2f} from {len(trades)} trades."
68
+ for t in trades[-5:]:
69
+ summary += f"\nβ€’ {t['action']} {t['contract']} β†’ ${t['pnl_estimate']} ({t['reason']})"
70
+ return {"summary": summary}
71
+
72
+ @app.post("/proxy")
73
+ async def proxy_gateio(request: Request):
74
+ payload = await request.json()
75
+ method = payload.get("method", "GET").upper()
76
+ path = payload.get("path", "")
77
+ query = payload.get("query", "")
78
+ body = payload.get("body", "")
79
+ timestamp = str(int(time.time()))
80
+ message = f"{method}\n{path}\n{query}\n{body}\n{timestamp}"
81
+ signature = hmac.new(api_secret.encode(), message.encode(), hashlib.sha512).hexdigest()
82
+
83
+ headers = {
84
+ "KEY": api_key,
85
+ "Timestamp": timestamp,
86
+ "SIGN": signature,
87
+ "Content-Type": "application/json"
88
+ }
89
+
90
+ url = f"https://api.gate.io/api/v4{path}"
91
+ try:
92
+ if method == "GET":
93
+ response = requests.get(url, headers=headers)
94
+ elif method == "POST":
95
+ response = requests.post(url, headers=headers, data=body)
96
+ else:
97
+ return JSONResponse(status_code=400, content={"error": "Unsupported method"})
98
+
99
+ return JSONResponse(status_code=response.status_code, content=response.json())
100
+ except Exception as e:
101
+ return {"error": str(e)}
102
+
103
+
104
+ @app.post("/log_trade")
105
+ async def log_trade(request: Request):
106
+ trade = await request.json()
107
+ with open(LOG_FILE, "a") as f:
108
+ f.write(json.dumps(trade) + "\n")
109
+ return {"status": "logged", "trade": trade}
110
+
111
+ def log_balance(balance):
112
+ entry = {"timestamp": int(time.time()), "balance": balance}
113
+ with open(BAL_FILE, "a") as f:
114
+ f.write(json.dumps(entry) + "\n")
115
+
116
+ def sign_request(method, path, query_string, body, timestamp):
117
+ message = f"{method}\n{path}\n{query_string}\n{body}\n{timestamp}"
118
+ return hmac.new(GATE_API_SECRET.encode(), message.encode(), hashlib.sha512).hexdigest()
public/index.html ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
6
+ <title>Gate6 Dashboard</title>
7
+ <style>
8
+ body {
9
+ margin: 0;
10
+ font-family: 'Segoe UI', sans-serif;
11
+ background: linear-gradient(145deg, #111, #1c1c1c);
12
+ color: #fff;
13
+ display: flex;
14
+ flex-direction: column;
15
+ align-items: center;
16
+ padding: 2rem;
17
+ }
18
+
19
+ .card {
20
+ background: rgba(255, 115, 0, 0.12);
21
+ box-shadow: 0 10px 30px rgba(255, 115, 0, 0.3);
22
+ border: 1px solid rgba(255, 255, 255, 0.1);
23
+ backdrop-filter: blur(15px);
24
+ border-radius: 1rem;
25
+ padding: 1.5rem 2rem;
26
+ margin: 1rem;
27
+ width: 100%;
28
+ max-width: 600px;
29
+ text-align: center;
30
+ }
31
+
32
+ button {
33
+ padding: 0.75rem 2rem;
34
+ border-radius: 2rem;
35
+ background: orange;
36
+ color: #000;
37
+ font-weight: bold;
38
+ border: none;
39
+ margin-top: 1rem;
40
+ cursor: pointer;
41
+ }
42
+
43
+ pre {
44
+ text-align: left;
45
+ white-space: pre-wrap;
46
+ word-break: break-word;
47
+ background: rgba(255,255,255,0.05);
48
+ padding: 1rem;
49
+ border-radius: 0.75rem;
50
+ font-size: 0.9rem;
51
+ }
52
+ </style>
53
+ </head>
54
+ <body>
55
+ <h1>πŸš€ Gate6: Glass Dashboard</h1>
56
+
57
+ <div class="card">
58
+ <h2>Check Balance</h2>
59
+ <button onclick="fetchBalance()">Get Balance</button>
60
+ <pre id="balanceOut"></pre>
61
+ </div>
62
+
63
+ <div class="card">
64
+ <h2>Performance Summary</h2>
65
+ <button onclick="fetchPerformance()">Get Summary</button>
66
+ <pre id="summaryOut"></pre>
67
+ </div>
68
+
69
+ <script>
70
+ async function fetchBalance() {
71
+ const res = await fetch('/balance');
72
+ const json = await res.json();
73
+ document.getElementById('balanceOut').textContent = JSON.stringify(json, null, 2);
74
+ }
75
+
76
+ async function fetchPerformance() {
77
+ const res = await fetch('/performance');
78
+ const json = await res.json();
79
+ document.getElementById('summaryOut').textContent = JSON.stringify(json, null, 2);
80
+ }
81
+ </script>
82
+ </body>
83
+ </html>
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ ccxt
4
+ requests
trading_log.json ADDED
File without changes