kch123 analysis, copy-trade sim, monitoring, admin panel todos, nginx proxy
This commit is contained in:
205
projects/feed-hunter/kch123-monitor.py
Normal file
205
projects/feed-hunter/kch123-monitor.py
Normal file
@ -0,0 +1,205 @@
|
||||
#!/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"🎯 <b>kch123 New Activity</b> ({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 = ["🏈 <b>Super Bowl Resolution — kch123 Copy-Trade</b>\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"\n<b>Total P&L: ${total_pnl:+,.2f} ({total_pnl/sim.get('bankroll_used', 1000)*100:+.1f}%)</b>")
|
||||
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()
|
||||
Reference in New Issue
Block a user