toanvv7 commited on
Commit
a6efac4
·
verified ·
1 Parent(s): 32fcb3d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -75
app.py CHANGED
@@ -51,9 +51,9 @@ VIETNAM_TZ = ZoneInfo("Asia/Ho_Chi_Minh")
51
  CONFIG = {
52
  "RUNNING": False,
53
  "AMOUNT": 10.0,
54
- "LEV_MAIN": 25, # Đòn bẩy riêng cho BTC/ETH
55
- "LEV_ALTS": 15, # Đòn bẩy riêng cho Alt Top
56
- "LEV_HIGHVOL": 10, # Đòn bẩy riêng cho Coin Rác/High Vol
57
  "WICK_MAIN": 0.13,
58
  "WICK_ALTS": 0.25,
59
  "WICK_NEW": 0.4,
@@ -72,10 +72,8 @@ MARKET_DATA_CACHE = {}
72
 
73
  def send_slack(msg):
74
  if SLACK_WEBHOOK_URL:
75
- try:
76
- requests.post(SLACK_WEBHOOK_URL, json={"text": msg}, timeout=5)
77
- except:
78
- pass
79
 
80
  def okx_request(method, endpoint, body=None):
81
  try:
@@ -106,15 +104,15 @@ def get_market_rules(symbol):
106
  res = requests.get(url, timeout=10).json()
107
  if res.get('code') == '0' and res['data']:
108
  inst = res['data'][0]
 
109
  data = {"lotSz": float(inst['lotSz']), "tickSz": float(inst['tickSz']),
110
- "prec": len(inst['tickSz'].split('.')[-1]) if '.' in inst['tickSz'] else 0,
111
- "ctVal": float(inst.get('ctVal', 1)), "minSz": float(inst['minSz'])}
112
  MARKET_DATA_CACHE[symbol] = data
113
  return data
114
  except: return None
115
 
116
  # ==============================================================================
117
- # ========== CORE LOGIC ==========
118
  # ==============================================================================
119
 
120
  def calculate_wick_pct(row):
@@ -126,67 +124,60 @@ def calculate_wick_pct(row):
126
  def execute_trade(symbol, side, n0_data, n_curr_data):
127
  try:
128
  rules = get_market_rules(symbol)
129
- if not rules:
130
- send_slack(f"❌ LỖI: Không lấy được thông số thị trường cho {symbol}")
131
- return
132
 
133
- # Lấy đòn bẩy tương ứng theo nhóm coin
134
- if symbol in BTC_ETH_GOLD:
135
- target_lev = int(CONFIG["LEV_MAIN"])
136
- elif symbol in ALTS_STANDARD:
137
- target_lev = int(CONFIG["LEV_ALTS"])
138
- else:
139
- target_lev = int(CONFIG["LEV_HIGHVOL"])
140
 
141
- # Set Leverage cho OKX
142
  okx_request("POST", "/api/v5/account/set-leverage", {
143
  "instId": symbol, "lever": str(target_lev), "mgnMode": "isolated", "posSide": side
144
  })
145
 
146
- # Logic Entry (Limit)
147
  curr_close, curr_high, curr_low = n_curr_data['c'], n_curr_data['h'], n_curr_data['l']
148
  if side == "long":
149
  entry = curr_close if curr_close >= curr_high else min(n0_data['o'], n0_data['c'])
150
  else:
151
  entry = curr_close if curr_close <= curr_low else max(n0_data['o'], n0_data['c'])
152
 
153
- entry = round(entry, rules['prec'])
154
  buffer = CONFIG["SL_BUFFER_PCT"] / 100
155
  sl_price = n0_data['l'] * (1 - buffer) if side == "long" else n0_data['h'] * (1 + buffer)
156
  risk = abs(entry - sl_price)
157
- if risk == 0:
158
- send_slack(f"⚠️ {symbol}: Bỏ qua lệnh do Risk = 0")
159
- return
160
 
161
- sl = round(sl_price, rules['prec'])
162
- tp = round((entry + risk * CONFIG["RR_RATIO"]) if side == "long" else (entry - risk * CONFIG["RR_RATIO"]), rules['prec'])
163
 
164
- # Tính Size = Amount * Leverage của từng nhóm
 
 
 
 
 
165
  size = math.floor((CONFIG["AMOUNT"] * target_lev / (entry * rules['ctVal'])) / rules['lotSz']) * rules['lotSz']
166
- if size < rules['minSz']:
167
- send_slack(f"⚠️ {symbol}: Size {size} nhỏ hơn min {rules['minSz']}")
168
- return
169
 
170
  body = {
171
  "instId": symbol, "tdMode": "isolated", "side": "buy" if side == "long" else "sell",
172
- "posSide": side, "ordType": "limit", "px": str(entry), "sz": str(size),
173
  "attachAlgoOrds": [
174
- {"attachAlgoOrdType": "sl", "slTriggerPx": str(sl), "slOrdPx": "-1"},
175
- {"attachAlgoOrdType": "tp", "tpTriggerPx": str(tp), "tpOrdPx": "-1"}
176
  ]
177
  }
178
  res = okx_request("POST", "/api/v5/trade/order", body)
179
 
180
  if res and res.get('code') == '0':
181
- msg = f"🚀 ✅ {side.upper()} {symbol} (x{target_lev}) | Entry: {entry} | SL: {sl} | TP: {tp}"
182
- print(f" └─ ✅ {msg}", flush=True)
183
  send_slack(msg)
 
184
  else:
185
  err_msg = res.get('msg', 'Unknown Error')
186
- err_code = res.get('code', 'N/A')
187
- msg = f"❌ ⛔ ĐẶT LỆNH LỖI: {symbol} | {side.upper()}\nLý do: {err_msg} (Code: {err_code})"
188
- print(f" └─ {msg}", flush=True)
189
  send_slack(msg)
 
190
 
191
  except Exception as e:
192
  send_slack(f"🚨 CRITICAL ERROR: {symbol} | {str(e)}")
@@ -218,8 +209,7 @@ def scan_symbol(symbol, X, Y, open_symbols, current_count):
218
  if symbol not in open_symbols:
219
  return current_count + 1
220
  return current_count
221
- except:
222
- return current_count
223
 
224
  def run_market_scan():
225
  open_symbols = get_all_open_positions()
@@ -230,10 +220,8 @@ def run_market_scan():
230
 
231
  for s in BTC_ETH_GOLD:
232
  current_count = scan_symbol(s, CONFIG["WICK_MAIN"], Y, open_symbols, current_count)
233
-
234
  for s in ALTS_STANDARD:
235
  current_count = scan_symbol(s, CONFIG["WICK_ALTS"], Y, open_symbols, current_count)
236
-
237
  for s in ALTS_HIGH_VOL:
238
  current_count = scan_symbol(s, CONFIG["WICK_NEW"], Y, open_symbols, current_count)
239
 
@@ -243,19 +231,11 @@ def run_market_scan():
243
 
244
  def update_ui(amt, lev_m, lev_a, lev_h, m_main, m_alt, m_new, sub, rr, buf, run):
245
  CONFIG.update({
246
- "AMOUNT": amt,
247
- "LEV_MAIN": lev_m,
248
- "LEV_ALTS": lev_a,
249
- "LEV_HIGHVOL": lev_h,
250
- "WICK_MAIN": m_main,
251
- "WICK_ALTS": m_alt,
252
- "WICK_NEW": m_new,
253
- "WICK_SUB": sub,
254
- "RR_RATIO": rr,
255
- "SL_BUFFER_PCT": buf,
256
- "RUNNING": run
257
  })
258
- return f"Bot: {'ON' if run else 'OFF'} | Đã cập nhật đòn bẩy: Main {lev_m}x, Alt {lev_a}x, HighVol {lev_h}x"
259
 
260
  def main_loop():
261
  while True:
@@ -269,37 +249,27 @@ def main_loop():
269
 
270
  threading.Thread(target=main_loop, daemon=True).start()
271
 
272
- with gr.Blocks(title="OKX Bot V17.8 Professional") as demo:
273
- gr.Markdown("# 🤖 OKX Bot V17.8 - Custom Leverage Groups")
274
-
275
  with gr.Tab("Cấu hình Giao dịch"):
276
  with gr.Row():
277
  n_amt = gr.Number(label="Vốn/Lệnh (USDT)", value=10)
278
  n_rr = gr.Number(label="R:R Ratio", value=1.5)
279
  n_buf = gr.Number(label="SL Buffer (%)", value=0.15)
280
-
281
- gr.Markdown("### 🎚️ Thiết lập Đòn bẩy (Leverage 1 - 100)")
282
  with gr.Row():
283
- lev_main = gr.Slider(minimum=1, maximum=100, value=25, step=1, label="Leverage BTC/ETH Group")
284
- lev_alts = gr.Slider(minimum=1, maximum=100, value=15, step=1, label="Leverage Alts Top Group")
285
- lev_highvol = gr.Slider(minimum=1, maximum=100, value=10, step=1, label="Leverage High Vol Group")
286
-
287
- with gr.Tab("Cấu hình Kỹ thuật (Râu nến)"):
288
  with gr.Row():
289
  n_main = gr.Number(label="Râu BTC/ETH", value=0.13)
290
  n_alt = gr.Number(label="Râu Alt Top", value=0.25)
291
  n_new = gr.Number(label="Râu High Vol", value=0.4)
292
  n_sub = gr.Number(label="Râu Phụ Max", value=0.05)
293
-
294
  c_run = gr.Checkbox(label="KÍCH HOẠT BOT")
295
- btn = gr.Button("LƯU CẤU HÌNH & CHẠY", variant="primary")
296
- out = gr.Textbox(label="Trạng thái hệ thống")
297
-
298
- btn.click(
299
- update_ui,
300
- [n_amt, lev_main, lev_alts, lev_highvol, n_main, n_alt, n_new, n_sub, n_rr, n_buf, c_run],
301
- out
302
- )
303
 
304
  if __name__ == "__main__":
305
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
51
  CONFIG = {
52
  "RUNNING": False,
53
  "AMOUNT": 10.0,
54
+ "LEV_MAIN": 25,
55
+ "LEV_ALTS": 15,
56
+ "LEV_HIGHVOL": 10,
57
  "WICK_MAIN": 0.13,
58
  "WICK_ALTS": 0.25,
59
  "WICK_NEW": 0.4,
 
72
 
73
  def send_slack(msg):
74
  if SLACK_WEBHOOK_URL:
75
+ try: requests.post(SLACK_WEBHOOK_URL, json={"text": msg}, timeout=5)
76
+ except: pass
 
 
77
 
78
  def okx_request(method, endpoint, body=None):
79
  try:
 
104
  res = requests.get(url, timeout=10).json()
105
  if res.get('code') == '0' and res['data']:
106
  inst = res['data'][0]
107
+ prec = len(inst['tickSz'].split('.')[-1]) if '.' in inst['tickSz'] else 0
108
  data = {"lotSz": float(inst['lotSz']), "tickSz": float(inst['tickSz']),
109
+ "prec": prec, "ctVal": float(inst.get('ctVal', 1)), "minSz": float(inst['minSz'])}
 
110
  MARKET_DATA_CACHE[symbol] = data
111
  return data
112
  except: return None
113
 
114
  # ==============================================================================
115
+ # ========== CORE LOGIC (VẬN HÀNH THEO APP.PY) ==========
116
  # ==============================================================================
117
 
118
  def calculate_wick_pct(row):
 
124
  def execute_trade(symbol, side, n0_data, n_curr_data):
125
  try:
126
  rules = get_market_rules(symbol)
127
+ if not rules: return
 
 
128
 
129
+ # 1. Chọn đòn bẩy theo nhóm
130
+ if symbol in BTC_ETH_GOLD: target_lev = int(CONFIG["LEV_MAIN"])
131
+ elif symbol in ALTS_STANDARD: target_lev = int(CONFIG["LEV_ALTS"])
132
+ else: target_lev = int(CONFIG["LEV_HIGHVOL"])
 
 
 
133
 
 
134
  okx_request("POST", "/api/v5/account/set-leverage", {
135
  "instId": symbol, "lever": str(target_lev), "mgnMode": "isolated", "posSide": side
136
  })
137
 
138
+ # 2. Logic Entry khớp 100% app.py gốc
139
  curr_close, curr_high, curr_low = n_curr_data['c'], n_curr_data['h'], n_curr_data['l']
140
  if side == "long":
141
  entry = curr_close if curr_close >= curr_high else min(n0_data['o'], n0_data['c'])
142
  else:
143
  entry = curr_close if curr_close <= curr_low else max(n0_data['o'], n0_data['c'])
144
 
145
+ # 3. Tính toán SL/TP với độ chính xác chuẩn sàn
146
  buffer = CONFIG["SL_BUFFER_PCT"] / 100
147
  sl_price = n0_data['l'] * (1 - buffer) if side == "long" else n0_data['h'] * (1 + buffer)
148
  risk = abs(entry - sl_price)
149
+ if risk == 0: return
 
 
150
 
151
+ tp_price = (entry + risk * CONFIG["RR_RATIO"]) if side == "long" else (entry - risk * CONFIG["RR_RATIO"])
 
152
 
153
+ # Format string tránh lỗi Code 1
154
+ fmt_entry = "{:.{}f}".format(entry, rules['prec'])
155
+ fmt_sl = "{:.{}f}".format(sl_price, rules['prec'])
156
+ fmt_tp = "{:.{}f}".format(tp_price, rules['prec'])
157
+
158
+ # 4. Tính Size
159
  size = math.floor((CONFIG["AMOUNT"] * target_lev / (entry * rules['ctVal'])) / rules['lotSz']) * rules['lotSz']
160
+ if size < rules['minSz']: return
 
 
161
 
162
  body = {
163
  "instId": symbol, "tdMode": "isolated", "side": "buy" if side == "long" else "sell",
164
+ "posSide": side, "ordType": "limit", "px": fmt_entry, "sz": str(size),
165
  "attachAlgoOrds": [
166
+ {"attachAlgoOrdType": "sl", "slTriggerPx": fmt_sl, "slOrdPx": "-1"},
167
+ {"attachAlgoOrdType": "tp", "tpTriggerPx": fmt_tp, "tpOrdPx": "-1"}
168
  ]
169
  }
170
  res = okx_request("POST", "/api/v5/trade/order", body)
171
 
172
  if res and res.get('code') == '0':
173
+ msg = f"🚀 ✅ {side.upper()} {symbol} (x{target_lev}) | Entry: {fmt_entry} | SL: {fmt_sl}"
 
174
  send_slack(msg)
175
+ print(f" └─ ✅ {msg}", flush=True)
176
  else:
177
  err_msg = res.get('msg', 'Unknown Error')
178
+ msg = f"❌ ĐẶT LỆNH LỖI: {symbol} | {side.upper()} | {err_msg} (Code: {res.get('code')})"
 
 
179
  send_slack(msg)
180
+ print(f" └─ {msg}", flush=True)
181
 
182
  except Exception as e:
183
  send_slack(f"🚨 CRITICAL ERROR: {symbol} | {str(e)}")
 
209
  if symbol not in open_symbols:
210
  return current_count + 1
211
  return current_count
212
+ except: return current_count
 
213
 
214
  def run_market_scan():
215
  open_symbols = get_all_open_positions()
 
220
 
221
  for s in BTC_ETH_GOLD:
222
  current_count = scan_symbol(s, CONFIG["WICK_MAIN"], Y, open_symbols, current_count)
 
223
  for s in ALTS_STANDARD:
224
  current_count = scan_symbol(s, CONFIG["WICK_ALTS"], Y, open_symbols, current_count)
 
225
  for s in ALTS_HIGH_VOL:
226
  current_count = scan_symbol(s, CONFIG["WICK_NEW"], Y, open_symbols, current_count)
227
 
 
231
 
232
  def update_ui(amt, lev_m, lev_a, lev_h, m_main, m_alt, m_new, sub, rr, buf, run):
233
  CONFIG.update({
234
+ "AMOUNT": amt, "LEV_MAIN": lev_m, "LEV_ALTS": lev_a, "LEV_HIGHVOL": lev_h,
235
+ "WICK_MAIN": m_main, "WICK_ALTS": m_alt, "WICK_NEW": m_new, "WICK_SUB": sub,
236
+ "RR_RATIO": rr, "SL_BUFFER_PCT": buf, "RUNNING": run
 
 
 
 
 
 
 
 
237
  })
238
+ return f"Bot: {'ON' if run else 'OFF'} | Logic: app.py (Synced)"
239
 
240
  def main_loop():
241
  while True:
 
249
 
250
  threading.Thread(target=main_loop, daemon=True).start()
251
 
252
+ with gr.Blocks(title="OKX Bot V18.0 Professional") as demo:
253
+ gr.Markdown("# 🤖 OKX Bot V18.0 - app.py Logic Synced")
 
254
  with gr.Tab("Cấu hình Giao dịch"):
255
  with gr.Row():
256
  n_amt = gr.Number(label="Vốn/Lệnh (USDT)", value=10)
257
  n_rr = gr.Number(label="R:R Ratio", value=1.5)
258
  n_buf = gr.Number(label="SL Buffer (%)", value=0.15)
 
 
259
  with gr.Row():
260
+ lev_main = gr.Slider(1, 100, 25, step=1, label="Leverage BTC/ETH Group")
261
+ lev_alts = gr.Slider(1, 100, 15, step=1, label="Leverage Alts Top Group")
262
+ lev_highvol = gr.Slider(1, 100, 10, step=1, label="Leverage High Vol Group")
263
+ with gr.Tab("Cấu hình Râu"):
 
264
  with gr.Row():
265
  n_main = gr.Number(label="Râu BTC/ETH", value=0.13)
266
  n_alt = gr.Number(label="Râu Alt Top", value=0.25)
267
  n_new = gr.Number(label="Râu High Vol", value=0.4)
268
  n_sub = gr.Number(label="Râu Phụ Max", value=0.05)
 
269
  c_run = gr.Checkbox(label="KÍCH HOẠT BOT")
270
+ btn = gr.Button("LƯU & CHẠY", variant="primary")
271
+ out = gr.Textbox(label="Status")
272
+ btn.click(update_ui, [n_amt, lev_main, lev_alts, lev_highvol, n_main, n_alt, n_new, n_sub, n_rr, n_buf, c_run], out)
 
 
 
 
 
273
 
274
  if __name__ == "__main__":
275
  demo.launch(server_name="0.0.0.0", server_port=7860)