#!/usr/bin/env python3 """ kch123 Trade Monitor + Game Price Tracker Zero AI tokens — pure Python, sends Telegram alerts directly. Runs as systemd timer every 5 minutes. """ import json import os import subprocess import sys import urllib.request import urllib.parse from datetime import datetime, timezone from pathlib import Path WALLET = "0x6a72f61820b26b1fe4d956e17b6dc2a1ea3033ee" PROJECT_DIR = Path(__file__).parent DATA_DIR = PROJECT_DIR / "data" / "kch123-tracking" TRADES_FILE = DATA_DIR / "all-trades.json" STATS_FILE = DATA_DIR / "stats.json" SIM_FILE = PROJECT_DIR / "data" / "simulations" / "active.json" CRED_FILE = Path("/home/wdjones/.openclaw/workspace/.credentials/telegram-bot.env") def load_creds(): creds = {} with open(CRED_FILE) as f: for line in f: if '=' in line: k, v = line.strip().split('=', 1) creds[k] = v return creds def send_telegram(text, creds): url = f"https://api.telegram.org/bot{creds['BOT_TOKEN']}/sendMessage" data = urllib.parse.urlencode({ 'chat_id': creds['CHAT_ID'], 'text': text, 'parse_mode': 'HTML' }).encode() try: req = urllib.request.Request(url, data=data) urllib.request.urlopen(req, timeout=10) except Exception as e: print(f"Telegram send failed: {e}", file=sys.stderr) def fetch_trades(limit=100): url = f"https://data-api.polymarket.com/activity?user={WALLET}&limit={limit}" req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"}) resp = urllib.request.urlopen(req, timeout=15) return json.loads(resp.read()) def fetch_positions(): url = f"https://data-api.polymarket.com/positions?user={WALLET}&sizeThreshold=100&limit=20&sortBy=current&sortOrder=desc" req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"}) resp = urllib.request.urlopen(req, timeout=15) return json.loads(resp.read()) def check_new_trades(creds): """Check for new trades and alert""" DATA_DIR.mkdir(parents=True, exist_ok=True) known_hashes = set() all_trades = [] if TRADES_FILE.exists(): with open(TRADES_FILE) as f: all_trades = json.load(f) known_hashes = {t.get("transactionHash", "") + str(t.get("outcomeIndex", "")) for t in all_trades} recent = fetch_trades(100) new_trades = [] for t in recent: key = t.get("transactionHash", "") + str(t.get("outcomeIndex", "")) if key not in known_hashes: new_trades.append(t) known_hashes.add(key) all_trades.append(t) if new_trades: with open(TRADES_FILE, "w") as f: json.dump(all_trades, f) # Format alert buys = [t for t in new_trades if t.get("type") == "TRADE" and t.get("side") == "BUY"] redeems = [t for t in new_trades if t.get("type") == "REDEEM"] lines = [f"🎯 kch123 New Activity ({len(new_trades)} trades)"] for t in buys[:10]: amt = t.get('usdcSize', 0) lines.append(f" 📈 BUY ${amt:,.2f} — {t.get('title','')} ({t.get('outcome','')})") for t in redeems[:10]: amt = t.get('usdcSize', 0) icon = "✅" if amt > 0 else "❌" lines.append(f" {icon} REDEEM ${amt:,.2f} — {t.get('title','')}") if len(new_trades) > 20: lines.append(f" ... and {len(new_trades) - 20} more") send_telegram("\n".join(lines), creds) print(f"Alerted: {len(new_trades)} new trades") else: print("No new trades") def update_sim_prices(): """Update paper trade simulation with current prices""" if not SIM_FILE.exists(): return with open(SIM_FILE) as f: sim = json.load(f) try: positions_data = fetch_positions() except: return # Build price lookup by title price_map = {} for p in positions_data: price_map[p.get('title', '')] = { 'price': p.get('curPrice', 0), 'value': p.get('currentValue', 0), } resolved = False for pos in sim.get('positions', []): title = pos.get('asset', '') if title in price_map: new_price = price_map[title]['price'] pos['current_price'] = new_price qty = pos.get('quantity', 0) entry = pos.get('entry_price', 0) pos['unrealized_pnl'] = round(qty * (new_price - entry), 2) pos['unrealized_pnl_pct'] = round((new_price - entry) / entry * 100, 2) if entry else 0 if new_price in (0, 1, 0.0, 1.0): resolved = True with open(SIM_FILE, 'w') as f: json.dump(sim, f, indent=2) return resolved def send_resolution_report(creds): """Send final P&L when game resolves""" if not SIM_FILE.exists(): return with open(SIM_FILE) as f: sim = json.load(f) total_pnl = 0 lines = ["🏈 Super Bowl Resolution — kch123 Copy-Trade\n"] for pos in sim.get('positions', []): price = pos.get('current_price', 0) entry = pos.get('entry_price', 0) size = pos.get('size', 0) qty = pos.get('quantity', 0) if price >= 0.95: # Won pnl = qty * 1.0 - size icon = "✅" else: # Lost pnl = -size icon = "❌" total_pnl += pnl lines.append(f"{icon} {pos.get('asset','')}: ${pnl:+,.2f}") lines.append(f"\nTotal P&L: ${total_pnl:+,.2f} ({total_pnl/sim.get('bankroll_used', 1000)*100:+.1f}%)") lines.append(f"Bankroll: $1,000 → ${1000 + total_pnl:,.2f}") send_telegram("\n".join(lines), creds) print(f"Resolution report sent: ${total_pnl:+,.2f}") def main(): creds = load_creds() # Check for new trades try: check_new_trades(creds) except Exception as e: print(f"Trade check error: {e}", file=sys.stderr) # Update sim prices try: resolved = update_sim_prices() if resolved: send_resolution_report(creds) except Exception as e: print(f"Sim update error: {e}", file=sys.stderr) # Update stats stats = {} if STATS_FILE.exists(): with open(STATS_FILE) as f: stats = json.load(f) stats["last_check"] = datetime.now(timezone.utc).isoformat() with open(STATS_FILE, "w") as f: json.dump(stats, f, indent=2) if __name__ == "__main__": main()