Created
February 10, 2026 02:52
-
-
Save svalordev/b97eb190a2ee7b96c678a0bdf7d20a3b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import sys | |
| import time | |
| import signal | |
| import getpass | |
| import requests | |
| import math | |
| from datetime import datetime | |
| from rich.live import Live | |
| from rich.table import Table | |
| from rich.layout import Layout | |
| from rich.panel import Panel | |
| from rich.text import Text | |
| from rich.console import Console | |
| from rich import box | |
| # --- CONFIGURATION --- | |
| BASE_URL = "https://wcpngaxotgxyjjdujarf.supabase.co" | |
| ANON_KEY = "INSERT_KEY" | |
| # --- TUNING --- | |
| MAX_POSITIONS = 3 | |
| MAX_TX_LIMIT = 300 | |
| SCARCITY_TRIGGER = 500 | |
| SWAP_THRESHOLD = 1.1 | |
| POLL_INTERVAL = 0.5 | |
| SAFETY_BUFFER = 0.90 | |
| console = Console() | |
| class ZenithTrader: | |
| def __init__(self): | |
| self.session = requests.Session() | |
| self.session.headers.update({ | |
| "apikey": ANON_KEY, | |
| "content-type": "application/json", | |
| "origin": "https://bet-jee.vercel.app", | |
| "user-agent": "Zenith-Debug/2.1" | |
| }) | |
| self.user_token = None | |
| self.username = "" | |
| self.secret = "" | |
| self.positions = {} | |
| self.share_tracker = {} | |
| self.start_net_worth = 0.0 | |
| self.running = True | |
| self.log_messages = [] | |
| signal.signal(signal.SIGINT, self.handle_exit) | |
| signal.signal(signal.SIGTERM, self.handle_exit) | |
| def handle_exit(self, signum, frame): | |
| self.running = False | |
| def log(self, message): | |
| timestamp = datetime.now().strftime("%H:%M:%S") | |
| self.log_messages.append(f"[{timestamp}] {message}") | |
| if len(self.log_messages) > 12: # Increased log history | |
| self.log_messages.pop(0) | |
| def get_credentials(self): | |
| console.clear() | |
| console.print(Panel.fit("[bold cyan]Zenith Trader[/bold cyan]", border_style="cyan")) | |
| self.username = input("Username: ").strip().replace("<", "") | |
| self.secret = getpass.getpass("Password: ").strip() | |
| def login(self): | |
| try: | |
| url = f"{BASE_URL}/functions/v1/login" | |
| payload = {"username": self.username, "secret": self.secret} | |
| resp = self.session.post(url, json=payload, headers={"authorization": f"Bearer {ANON_KEY}"}) | |
| if resp.status_code != 200: | |
| self.log(f"[bold red]Login Failed: {resp.status_code} - {resp.text}[/bold red]") | |
| return False | |
| data = resp.json() | |
| if "token" in data: | |
| self.user_token = data["token"] | |
| self.session.headers.update({"authorization": f"Bearer {self.user_token}"}) | |
| return True | |
| return False | |
| except Exception as e: | |
| self.log(f"[bold red]Login Exception: {e}[/bold red]") | |
| return False | |
| def fetch_data(self): | |
| try: | |
| m_resp = self.session.get(f"{BASE_URL}/rest/v1/markets?select=*", headers={"authorization": f"Bearer {ANON_KEY}"}) | |
| u_resp = self.session.post(f"{BASE_URL}/functions/v1/load_user") | |
| if m_resp.status_code != 200: | |
| self.log(f"[yellow]Market Data Error: {m_resp.status_code}[/yellow]") | |
| return None, None | |
| if u_resp.status_code != 200: | |
| self.log(f"[yellow]User Data Error: {u_resp.status_code}[/yellow]") | |
| return None, None | |
| return m_resp.json(), u_resp.json() | |
| except Exception as e: | |
| self.log(f"[red]Fetch Exception: {e}[/red]") | |
| return None, None | |
| def execute_trade(self, action, shift_id, shares, ticker="UNKNOWN"): | |
| remaining = shares | |
| while remaining > 0 and self.running: | |
| chunk = min(remaining, MAX_TX_LIMIT) | |
| attempts = 0 | |
| success = False | |
| while attempts < 3 and chunk >= 1: | |
| try: | |
| url = f"{BASE_URL}/functions/v1/{action}" | |
| payload = {"shift_id": shift_id, "shares": int(chunk)} | |
| resp = self.session.post(url, json=payload) | |
| if resp.status_code == 200: | |
| remaining -= chunk | |
| success = True | |
| break | |
| else: | |
| # --- DEBUGGING LOGIC --- | |
| error_msg = resp.text.lower() | |
| self.log(f"[red]FAIL {action.upper()} {ticker} ({chunk}): {resp.status_code} - {resp.text[:30]}[/red]") | |
| if "liquidity" in error_msg or "shares" in error_msg or "insufficient" in error_msg: | |
| chunk = int(chunk / 2) | |
| attempts += 1 | |
| time.sleep(0.1) | |
| elif "balance" in error_msg: | |
| # Critical: Stop trying to buy if broke | |
| self.log("[bold red]CRITICAL: INSUFFICIENT FUNDS[/bold red]") | |
| return | |
| else: | |
| return # Unknown error, abort trade | |
| except Exception as e: | |
| self.log(f"[red]Trade Exception: {e}[/red]") | |
| break | |
| if not success: | |
| self.log(f"[yellow]Aborting trade for {ticker} after retries.[/yellow]") | |
| break | |
| time.sleep(0.05) | |
| if remaining < shares: | |
| filled = shares - remaining | |
| color = "green" if action == "buy" else "red" | |
| self.log(f"[{color}]{action.upper()} FILLED: {filled} shares of {ticker}[/{color}]") | |
| def liquidator(self): | |
| if not self.positions: return | |
| self.log("[bold red]INITIATING LIQUIDATION SEQUENCE[/bold red]") | |
| for sid, pos in list(self.positions.items()): | |
| self.execute_trade("sell", sid, pos['shares'], "LIQUIDATION") | |
| def generate_ui(self, cash, net_worth, pnl, pnl_pct, markets): | |
| layout = Layout() | |
| layout.split_column( | |
| Layout(name="header", size=3), | |
| Layout(name="body", ratio=1), | |
| Layout(name="footer", size=12) | |
| ) | |
| pnl_color = "green" if pnl >= 0 else "red" | |
| header_text = Text.from_markup( | |
| f"💰 Cash: [bold]₹{cash:,.2f}[/bold] | " | |
| f"💎 Net Worth: [bold]₹{net_worth:,.2f}[/bold] | " | |
| f"📈 PnL: [{pnl_color}]₹{pnl:+,.2f} ({pnl_pct:+.2f}%)[/{pnl_color}]" | |
| ) | |
| layout["header"].update(Panel(header_text, style="white on blue")) | |
| pos_table = Table(title="Active Portfolio", box=box.SIMPLE_HEAD, expand=True) | |
| pos_table.add_column("Ticker", style="cyan", no_wrap=True) | |
| pos_table.add_column("Price", justify="right") | |
| pos_table.add_column("Shares", justify="right") | |
| pos_table.add_column("Value", justify="right") | |
| pos_table.add_column("PnL %", justify="right") | |
| pos_table.add_column("Strategy", style="magenta") | |
| market_map = {m['shift_id']: m for m in markets} if markets else {} | |
| for sid, pos in self.positions.items(): | |
| m = market_map.get(sid) | |
| if not m: continue | |
| curr_price = 10000.0 / max(m['remaining_shares'], 1) | |
| value = curr_price * pos['shares'] | |
| trade_pnl = (curr_price - pos['entry']) / pos['entry'] * 100 | |
| color = "green" if trade_pnl >= 0 else "red" | |
| pos_table.add_row( | |
| m['code'], | |
| f"₹{curr_price:,.0f}", | |
| str(pos['shares']), | |
| f"₹{value:,.0f}", | |
| f"[{color}]{trade_pnl:+.1f}%[/{color}]", | |
| pos.get('reason', 'HOLD') | |
| ) | |
| layout["body"].update(Panel(pos_table, title="Portfolio Overview")) | |
| log_text = "\n".join(self.log_messages) | |
| layout["footer"].update(Panel(log_text, title="Debug Logs", style="dim")) | |
| return layout | |
| def run(self): | |
| self.get_credentials() | |
| if not self.login(): | |
| console.print("[red]Authentication Failed - Check Credentials[/red]") | |
| return | |
| with Live(console=console, refresh_per_second=4) as live: | |
| while self.running: | |
| try: | |
| markets, user = self.fetch_data() | |
| if not isinstance(markets, list) or not user: | |
| self.log("[yellow]API returned invalid data[/yellow]") | |
| time.sleep(POLL_INTERVAL) | |
| continue | |
| cash = float(user.get("balance", 0)) | |
| market_map = {m['shift_id']: m for m in markets} | |
| equity_val = 0.0 | |
| for sid, pos in self.positions.items(): | |
| m = market_map.get(sid) | |
| if m: | |
| price = 10000.0 / max(m['remaining_shares'], 1) | |
| equity_val += price * pos['shares'] | |
| curr_nw = cash + equity_val | |
| if self.start_net_worth == 0: self.start_net_worth = curr_nw | |
| pnl = curr_nw - self.start_net_worth | |
| pnl_pct = (pnl / self.start_net_worth * 100) if self.start_net_worth else 0 | |
| opportunities = [] | |
| scarcity_active = False | |
| for m in markets: | |
| sid = m['shift_id'] | |
| rem = m['remaining_shares'] | |
| if rem <= 0: continue | |
| prev = self.share_tracker.get(sid, rem) | |
| vol = prev - rem | |
| self.share_tracker[sid] = rem | |
| score = 0 | |
| reason = "" | |
| if rem < SCARCITY_TRIGGER: | |
| score = 10000 + (1000 - rem) | |
| reason = "SCARCITY" | |
| scarcity_active = True | |
| elif vol > 0: | |
| score = vol * 100 | |
| reason = "MOMENTUM" | |
| if score > 0: | |
| opportunities.append({ | |
| 'sid': sid, 'score': score, 'reason': reason, | |
| 'price': 10000.0/rem, 'rem': rem, 'code': m['code'] | |
| }) | |
| opportunities.sort(key=lambda x: x['score'], reverse=True) | |
| active_count = len(self.positions) | |
| for sid in list(self.positions.keys()): | |
| pos = self.positions[sid] | |
| m = market_map.get(sid) | |
| if not m: continue | |
| curr_p = 10000.0 / max(m['remaining_shares'], 1) | |
| if curr_p > pos['high']: pos['high'] = curr_p | |
| sell = False | |
| reason = "" | |
| if scarcity_active and pos.get('reason') != "SCARCITY": | |
| sell = True; reason = "REALLOCATION" | |
| elif opportunities and opportunities[0]['sid'] != sid: | |
| if opportunities[0]['score'] > (pos.get('score', 1) * SWAP_THRESHOLD): | |
| sell = True; reason = f"BETTER OPP: {opportunities[0]['code']}" | |
| drawdown = (pos['high'] - curr_p) / pos['high'] | |
| if drawdown > 0.15: sell = True; reason = "STOP LOSS" | |
| if sell: | |
| self.execute_trade("sell", sid, pos['shares'], m['code']) | |
| del self.positions[sid] | |
| active_count -= 1 | |
| cash += (pos['shares'] * curr_p) | |
| limit = 1 if scarcity_active else MAX_POSITIONS | |
| slots = limit - active_count | |
| if slots > 0 and cash > 5 and opportunities: | |
| target = opportunities[0] | |
| sid = target['sid'] | |
| if sid not in self.positions: | |
| budget = cash if scarcity_active else (cash / slots) | |
| can_afford = int(budget / target['price']) | |
| available = int(target['rem'] * SAFETY_BUFFER) | |
| amount = min(can_afford, available, MAX_TX_LIMIT) | |
| if amount > 0: | |
| self.execute_trade("buy", sid, amount, target['code']) | |
| self.positions[sid] = { | |
| 'entry': target['price'], 'shares': amount, | |
| 'high': target['price'], 'score': target['score'], | |
| 'reason': target['reason'] | |
| } | |
| else: | |
| # Log why we didn't buy even though we found a target | |
| if can_afford == 0: | |
| # self.log(f"[dim]Skipped {target['code']}: Too expensive for budget[/dim]") | |
| pass | |
| live.update(self.generate_ui(cash, curr_nw, pnl, pnl_pct, markets)) | |
| time.sleep(POLL_INTERVAL) | |
| except Exception as e: | |
| self.log(f"[bold red]CRITICAL LOOP ERROR: {e}[/bold red]") | |
| time.sleep(1) | |
| console.print("[bold yellow]Shutting down...[/bold yellow]") | |
| self.liquidator() | |
| console.print("[bold green]Shutdown Complete.[/bold green]") | |
| if __name__ == "__main__": | |
| ZenithTrader().run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment