Full sync - all projects, memory, configs

This commit is contained in:
2026-03-21 20:27:59 -05:00
parent 2447677d4a
commit b33de10902
395 changed files with 1635300 additions and 459211 deletions

1
projects/ava-kmls Submodule

Submodule projects/ava-kmls added at 2a51bad93b

Submodule projects/coinex-dashboard added at 82522feee1

Submodule projects/coinex-market-data added at 827105b46a

Submodule projects/coinex-trader added at 9fa8085f59

11
projects/control-panel/.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
node_modules/
.next/
__pycache__/
*.pyc
.env
*.db
*.sqlite
*.log
venv/
dist/
.credentials/

View File

@ -4,44 +4,62 @@
"url": "https://mail.proton.me",
"username": "case-lgn@protonmail.com",
"status": "active",
"notes": "Primary email account",
"created": "2026-02-08T09:57:59.243980",
"last_accessed": "Never"
"notes": "Primary email. Creds in .credentials/email.env",
"created": "2026-02-08",
"last_accessed": "2026-02-15"
},
{
"service": "Polymarket",
"url": "https://polymarket.com",
"username": "",
"status": "inactive",
"notes": "Not yet registered",
"created": "2026-02-08T09:57:59.243987",
"last_accessed": "Never"
"service": "CoinEx",
"url": "https://www.coinex.com",
"username": "D J's account (API key only)",
"status": "active",
"notes": "Futures-only API key. No spot/withdraw/transfer. Creds in .credentials/coinex.env",
"created": "2026-02-20",
"last_accessed": "2026-03-01"
},
{
"service": "Feed Hunter Portal",
"url": "http://localhost:8888",
"service": "Gitea",
"url": "https://git.letsgetnashty.com",
"username": "case",
"status": "active",
"notes": "Private repos: workspace, knowledge-builder, coinex-dashboard, coinex-trader, coinex-ta-service",
"created": "2026-01-30",
"last_accessed": "2026-03-01"
},
{
"service": "Coolify",
"url": "http://192.168.86.44:8000",
"username": "",
"status": "active",
"notes": "Local service",
"created": "2026-02-08T09:57:59.243989",
"last_accessed": "Never"
"notes": "Deployment platform. Project: dz-studio. API token in .credentials/coolify.env",
"created": "2026-02-26",
"last_accessed": "2026-03-01"
},
{
"service": "Chrome Debug",
"url": "http://localhost:9222",
"username": "",
"service": "Telegram Bot",
"url": "https://t.me/dzclaw_bot",
"username": "@dzclaw_bot",
"status": "active",
"notes": "Browser debugging interface",
"created": "2026-02-08T09:57:59.243991",
"last_accessed": "Never"
"notes": "Case's Telegram bot. D J chat ID: 6443752046",
"created": "2026-02-08",
"last_accessed": "2026-03-01"
},
{
"service": "OpenClaw Gateway",
"url": "http://localhost:18789",
"username": "",
"service": "Google Voice",
"url": "https://voice.google.com",
"username": "+1 (615) 933-1968",
"status": "active",
"notes": "OpenClaw main service",
"created": "2026-02-08T09:57:59.243993",
"last_accessed": "Never"
"notes": "D J's number, shared for service registrations/verification codes",
"created": "2026-02-08",
"last_accessed": "2026-02-08"
},
{
"service": "Craigslist",
"url": "https://nashville.craigslist.org",
"username": "case-lgn@protonmail.com",
"status": "active",
"notes": "CL_USERID=405642144, Nashville area. Passwordless login.",
"created": "2026-02-08",
"last_accessed": "2026-02-24"
}
]
]

View File

@ -1 +1,107 @@
[]
[
{
"timestamp": "2026-02-26T17:05:47.342833",
"action": "API Key Added",
"details": "Added key for Coolify"
},
{
"date": "2026-02-26",
"event": "CoinEx Dashboard rebuild assigned to Glitch (Next.js 15 stack)",
"type": "build"
},
{
"date": "2026-02-26",
"event": "Polymarket Sports Scanner v1 built and archived (premature)",
"type": "build"
},
{
"date": "2026-02-26",
"event": "auto-memory-indexer cron model fixed (haiku\u2192sonnet)",
"type": "fix"
},
{
"date": "2026-02-26",
"event": "Orphaned tax-prep-portal (port 3002) killed",
"type": "cleanup"
},
{
"date": "2026-02-25",
"event": "ChromaDB re-indexed: 137 documents in openclaw-memory",
"type": "infra"
},
{
"date": "2026-02-25",
"event": "CoinEx trader amount bug fixed (close_avbl fallback)",
"type": "fix"
},
{
"date": "2026-02-25",
"event": "Knowledge Builder archived to Gitea, service stopped",
"type": "cleanup"
},
{
"date": "2026-02-25",
"event": "22 stale Chrome tabs closed",
"type": "cleanup"
},
{
"date": "2026-02-25",
"event": "Disabled: kch123-monitor, crypto-watch, anoin123-monitor timers",
"type": "cleanup"
},
{
"date": "2026-02-24",
"event": "Craigslist bed listing sold (Facebook Marketplace)",
"type": "misc"
},
{
"date": "2026-02-24",
"event": "Medium article analysis: 'Anthropic is Killing Bitcoin'",
"type": "research"
},
{
"date": "2026-02-21",
"event": "CoinEx trader lockfile cleared (funding fee API outage)",
"type": "fix"
},
{
"date": "2026-02-20",
"event": "CoinEx live trading enabled. PUMP SHORT opened.",
"type": "trading"
},
{
"date": "2026-02-20",
"event": "Paper trader (leverage-trader) disabled",
"type": "cleanup"
},
{
"date": "2026-02-15",
"event": "Hawk hired. Full dev pipeline established.",
"type": "team"
},
{
"date": "2026-02-15",
"event": "Knowledge Builder v3 refactor completed (14/14 tests)",
"type": "build"
},
{
"date": "2026-02-15",
"event": "NotebookLM 3-panel layout built and QA'd",
"type": "build"
},
{
"date": "2026-02-15",
"event": "AVA KML email sent to Meg",
"type": "misc"
},
{
"date": "2026-02-14",
"event": "ARI completed 10 SPARK ideas research (batch 1)",
"type": "research"
},
{
"date": "2026-02-13",
"event": "Nexus virtual office built (v1\u2192v2.4)",
"type": "build"
}
]

View File

@ -1 +1,50 @@
[]
[
{
"service": "Anthropic (Claude)",
"key_location": "~/.openclaw/agents/main/agent/auth-profiles.json",
"type": "OAuth token (sk-ant-oat01-...)",
"status": "active",
"notes": "Primary AI model. Opus for Case, Sonnet for agents.",
"created": "2026-01-30"
},
{
"service": "CoinEx",
"key_location": "~/.openclaw/workspace/.credentials/coinex.env",
"type": "HMAC API key (COINEX_ACCESS_ID + COINEX_SECRET_KEY)",
"status": "active",
"notes": "Futures-only. No spot, no withdraw, no transfer.",
"created": "2026-02-20"
},
{
"service": "Telegram Bot",
"key_location": "~/.openclaw/workspace/.credentials/telegram-bot.env",
"type": "Bot token (BOT_TOKEN + CHAT_ID)",
"status": "active",
"notes": "Used by CoinEx trader and other scripts for alerts.",
"created": "2026-02-08"
},
{
"service": "Gitea",
"key_location": "~/.git-credentials",
"type": "HTTP credentials",
"status": "active",
"notes": "User: case. For git push to git.letsgetnashty.com.",
"created": "2026-01-30"
},
{
"service": "Brave Search",
"key_location": "NOT CONFIGURED",
"type": "API key",
"status": "missing",
"notes": "web_search tool needs this. Run: openclaw configure --section web",
"created": null
},
{
"service": "Coolify",
"key_location": "1|KfeWUGJLTpDlWiPrjsUoTRiLUBiike7eHD0qtR6347526a37",
"type": "Coolify",
"status": "active",
"notes": "http://192.168.86.44:8000/",
"created": "2026-02-26"
}
]

View File

@ -1 +1,50 @@
[]
[
{
"category": "AI Models",
"item": "Anthropic Claude API",
"monthly_cost": 200,
"currency": "USD",
"notes": "~$200/mo estimated. Opus (Case) + Sonnet (agents) + cron jobs.",
"status": "active"
},
{
"category": "Infrastructure",
"item": "Proxmox VM (self-hosted)",
"monthly_cost": 0,
"currency": "USD",
"notes": "192.168.86.45 — runs OpenClaw, all agents, web apps. D J's hardware.",
"status": "active"
},
{
"category": "Infrastructure",
"item": "GPU Box (self-hosted)",
"monthly_cost": 0,
"currency": "USD",
"notes": "192.168.86.40 — RTX 3080+3060, Ollama, Whisper. Electricity only.",
"status": "active"
},
{
"category": "Infrastructure",
"item": "ChromaDB LXC (self-hosted)",
"monthly_cost": 0,
"currency": "USD",
"notes": "192.168.86.25 — vector storage.",
"status": "active"
},
{
"category": "Trading",
"item": "CoinEx Futures Account",
"monthly_cost": 0,
"currency": "USD",
"notes": "~$125 USDT balance. Live trading. Fees per trade only.",
"status": "active"
},
{
"category": "Infrastructure",
"item": "D J's VPS",
"monthly_cost": null,
"currency": "USD",
"notes": "Runs odds aggregation Postgres DB. Access pending.",
"status": "pending"
}
]

View File

@ -0,0 +1 @@
[]

View File

@ -0,0 +1,131 @@
{
"local": [
{
"name": "OpenClaw Gateway",
"systemd": "openclaw-gateway.service",
"port": 18789,
"description": "Main agent gateway. WebSocket + HTTP, token auth."
},
{
"name": "Nexus (Virtual Office)",
"systemd": "nexus.service",
"port": 3000,
"description": "Next.js 14.2 virtual office dashboard."
},
{
"name": "Case Control Panel",
"systemd": "case-control-panel.service",
"port": 8000,
"description": "Admin dashboard — accounts, API keys, budget, notes."
},
{
"name": "Agent Monitor",
"systemd": "agent-monitor.service",
"port": 8001,
"description": "Agent team status tracking."
},
{
"name": "CoinEx Dashboard",
"systemd": "coinex-dashboard.service",
"port": 8891,
"description": "Futures scanner. Next.js 16 + WebSocket."
},
{
"name": "CoinEx TA Service",
"systemd": "coinex-ta-dev.service",
"port": 8894,
"description": "Technical analysis engine — EMA ribbons, TTM Squeeze, Stoch RSI. Redis pub/sub."
},
{
"name": "Ticker",
"systemd": "ticker.service",
"port": 8890,
"description": "ESPN-style todo display. Tabs: Daily, Work, Personal, Case, KIPP."
},
{
"name": "Feed Hunter Portal",
"systemd": "feed-hunter-portal.service",
"port": 8888,
"description": "Feed scraping pipeline portal."
},
{
"name": "Chrome CDP",
"systemd": "chrome-debug.service",
"port": 9222,
"description": "Headless Chrome debug port for browser automation."
},
{
"name": "Redis",
"systemd": null,
"port": 6379,
"description": "Local Redis server. OHLCV caching and signal pub/sub."
}
],
"timers": [
{
"name": "CoinEx Live Trader",
"systemd": "coinex-live-trader.timer",
"interval": "every 5 min",
"description": "Live futures trading bot. ~$125 USDT."
},
{
"name": "Polymarket Arb Scanner",
"systemd": "polymarket-arb-scanner.timer",
"interval": "every 2 min",
"description": "Sports arb scanner during market hours."
},
{
"name": "Market Watch (GARP)",
"systemd": "market-watch.timer",
"interval": "weekdays",
"description": "GARP paper trading scanner."
},
{
"name": "Feed Monitor",
"systemd": "feed-monitor.timer",
"interval": "every 30 min",
"description": "Feed scraping pipeline."
}
],
"deployed": [
{
"name": "CoinEx Dashboard",
"url": "https://fcs04o8w0sccookkw44sck8c.host.letsgetnashty.com",
"platform": "Coolify",
"app_uuid": "fcs04o8w0sccookkw44sck8c",
"description": "Futures scanner — deployed via Coolify on 192.168.86.44"
}
],
"infrastructure": [
{
"name": "ChromaDB",
"host": "192.168.86.25",
"port": 8000,
"description": "Vector storage LXC. API v2 ONLY. Collections: openclaw-memory, skool-courses."
},
{
"name": "Ollama (GPU Box)",
"host": "192.168.86.40",
"port": 11434,
"description": "Debian LXC. RTX 3080 + 3060. Models: nomic-embed-text, qwen3:8b, glm-4.7-flash."
},
{
"name": "Coolify Server",
"host": "192.168.86.44",
"port": 8000,
"description": "Deployment platform. Project: dz-studio."
},
{
"name": "KIPP VM",
"host": "192.168.86.100",
"port": null,
"description": "KIPP assistant VM. Ubuntu 24.04."
},
{
"name": "NAS",
"host": "192.168.86.244",
"port": null,
"description": "NFS storage. Mounts at /mnt/nas on GPU box."
}
]
}

View File

@ -1,17 +1,74 @@
[
{
"title": "Set up DNS for .case remote access",
"description": "Configure DNS so feedhunter.case and admin.case resolve to 192.168.86.45 from all devices on the network.",
"category": "dns",
"title": "Get VPS Postgres credentials from D J",
"description": "Need host/IP, port, read-only user/pass, schema dump. Unlocks Polymarket sports arb scanner Phase 2.",
"category": "trading",
"priority": "high",
"status": "blocked",
"source": "D J",
"created": "2026-02-24"
},
{
"title": "Configure Brave Search API key",
"description": "web_search tool is non-functional without it. Run: openclaw configure --section web",
"category": "infra",
"priority": "medium",
"status": "pending",
"source": "Case",
"created": "2026-02-08 10:06",
"steps": [
"Option A: Add entries to your router's DNS settings (if supported)",
"Option B: Add to /etc/hosts on each device you want access from",
"Option C: Set up a local DNS server (Pi-hole, dnsmasq, etc.)",
"Entries needed: 192.168.86.45 feedhunter.case admin.case"
]
"created": "2026-02-26"
},
{
"title": "Audit CoinEx futures pairs vs scanner coins",
"description": "29 coins scanned from Binance US — verify which actually have CoinEx futures pairs. Remove phantom pairs.",
"category": "trading",
"priority": "medium",
"status": "pending",
"source": "Case",
"created": "2026-02-25"
},
{
"title": "Add exchange-side TP/SL orders on CoinEx",
"description": "Bot only checks every 5min. Exchange-side orders would be instant safety net.",
"category": "trading",
"priority": "medium",
"status": "pending",
"source": "Case",
"created": "2026-02-25"
},
{
"title": "Reduce auto-memory-indexer frequency",
"description": "Currently every 15min = 96 Sonnet calls/day. Consider 1h or 2h.",
"category": "cost",
"priority": "low",
"status": "pending",
"source": "Case",
"created": "2026-02-26"
},
{
"title": "Research remaining SPARK ideas",
"description": "61+ unresearched ideas. ARI completed batch 1 (10 ideas). Queue up batch 2.",
"category": "strategy",
"priority": "low",
"status": "pending",
"source": "Case",
"created": "2026-02-15"
},
{
"title": "CoinEx Dashboard rebuild",
"description": "Glitch rebuilding in Next.js 15 stack. Forge handles Gitea repo + deployment. Jinx+Pixel QA after.",
"category": "build",
"priority": "high",
"status": "in-progress",
"source": "D J",
"created": "2026-02-26"
},
{
"title": "Polymarket Sports Arb Scanner",
"description": "Phase 1 archived. Rebuild properly after VPS Postgres access. Highest priority money project.",
"category": "trading",
"priority": "high",
"status": "blocked",
"source": "D J",
"created": "2026-02-24"
}
]

View File

@ -48,6 +48,8 @@ class ControlPanelHandler(BaseHTTPRequestHandler):
self.serve_activity()
elif self.path == '/todos':
self.serve_todos()
elif self.path == '/notes':
self.serve_notes()
else:
self.send_error(404, "Not found")
@ -64,6 +66,8 @@ class ControlPanelHandler(BaseHTTPRequestHandler):
self.handle_budget_post(form_data)
elif self.path == '/todos':
self.handle_todos_post(form_data)
elif self.path == '/notes':
self.handle_notes_post(form_data)
else:
self.send_error(404, "Not found")
@ -217,12 +221,16 @@ class ControlPanelHandler(BaseHTTPRequestHandler):
width: 100%;
border-collapse: collapse;
margin-top: 1rem;
table-layout: fixed;
}}
th, td {{
padding: 12px;
text-align: left;
border-bottom: 1px solid #30363d;
word-break: break-word;
overflow: hidden;
text-overflow: ellipsis;
}}
th {{
@ -351,6 +359,7 @@ class ControlPanelHandler(BaseHTTPRequestHandler):
<a href="/services">Services</a>
<a href="/budget">Budget</a>
<a href="/activity">Activity</a>
<a href="/notes">📝 Notes</a>
<a href="/todos">⚡ Action Required</a>
</nav>
</div>
@ -358,15 +367,72 @@ class ControlPanelHandler(BaseHTTPRequestHandler):
<div class="container">
{content}
</div>
<div id="editModal" style="display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);z-index:1000;justify-content:center;align-items:center;">
<div style="background:#21262d;border:1px solid #30363d;border-radius:8px;padding:2rem;width:500px;max-width:90%;">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem;">
<h3 style="color:#58a6ff;">Edit Account</h3>
<button onclick="closeEdit()" style="background:none;border:none;color:#8b949e;font-size:1.5em;cursor:pointer;">&times;</button>
</div>
<form method="POST" action="/accounts" id="editForm">
<input type="hidden" name="action" value="edit">
<input type="hidden" name="index" id="editIndex">
<div class="form-group">
<label>Service Name:</label>
<input type="text" name="service" id="editService" required>
</div>
<div class="form-group">
<label>URL:</label>
<input type="url" name="url" id="editUrl">
</div>
<div class="form-group">
<label>Username/Email:</label>
<input type="text" name="username" id="editUsername">
</div>
<div class="form-group">
<label>Status:</label>
<select name="status" id="editStatus">
<option value="active">Active</option>
<option value="inactive">Inactive</option>
<option value="rebuilding">Rebuilding</option>
<option value="pending">Pending</option>
</select>
</div>
<div class="form-group">
<label>Notes:</label>
<textarea name="notes" id="editNotes" rows="3"></textarea>
</div>
<button type="submit" class="btn">Save Changes</button>
<button type="button" class="btn btn-secondary" onclick="closeEdit()">Cancel</button>
</form>
</div>
</div>
<script>
var accountsData = {{}};
function toggleKey(element) {{
const key = element.getAttribute('data-key');
if (element.textContent.includes('*')) {{
element.textContent = key;
}} else {{
element.textContent = '*'.repeat(key.length);
element.textContent = '*'.repeat(Math.min(key.length, 30));
}}
}}
function editAccount(idx) {{
var a = accountsData[idx];
if (!a) return;
document.getElementById('editIndex').value = idx;
document.getElementById('editService').value = a.service || '';
document.getElementById('editUrl').value = a.url || '';
document.getElementById('editUsername').value = a.username || '';
document.getElementById('editStatus').value = a.status || 'active';
document.getElementById('editNotes').value = a.notes || '';
document.getElementById('editModal').style.display = 'flex';
}}
function closeEdit() {{
document.getElementById('editModal').style.display = 'none';
}}
document.getElementById('editModal').addEventListener('click', function(e) {{
if (e.target === this) closeEdit();
}});
</script>
</body>
</html>"""
@ -427,17 +493,24 @@ class ControlPanelHandler(BaseHTTPRequestHandler):
accounts_table = ""
for i, account in enumerate(accounts):
status_class = "status-active" if account.get('status') == 'active' else "status-inactive"
login_btn = f'<a href="{account.get("url", "#")}" target="_blank" class="btn btn-secondary">Login</a>' if account.get('url') else ""
url = account.get('url', '')
service_name = account.get('service', 'N/A')
service_link = f'<a href="{url}" target="_blank" style="color:#58a6ff;">{service_name}</a>' if url else service_name
accounts_table += f"""
<tr>
<td>{account.get('service', 'N/A')}</td>
<td><a href="{account.get('url', '#')}" target="_blank">{account.get('url', 'N/A')}</a></td>
<tr id="row-{i}">
<td>{service_link}</td>
<td>{account.get('username', 'N/A')}</td>
<td><span class="{status_class}">{account.get('status', 'unknown')}</span></td>
<td>{account.get('last_accessed', 'Never')}</td>
<td>{account.get('notes', '')}</td>
<td>{login_btn}</td>
<td style="font-size:0.85em;">{account.get('notes', '')}</td>
<td style="width:120px;white-space:nowrap;">
<button class="btn btn-secondary" style="padding:4px 10px;font-size:12px;" onclick="editAccount({i})">✏️ Edit</button>
<form method="POST" style="display:inline;">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="index" value="{i}">
<button type="submit" class="btn btn-danger" style="padding:4px 10px;font-size:12px;" onclick="return confirm('Delete {service_name}?')">🗑</button>
</form>
</td>
</tr>
"""
@ -476,13 +549,11 @@ class ControlPanelHandler(BaseHTTPRequestHandler):
<table>
<thead>
<tr>
<th>Service</th>
<th>URL</th>
<th>Username/Email</th>
<th>Status</th>
<th>Last Accessed</th>
<th>Notes</th>
<th>Actions</th>
<th style="width:18%;">Service</th>
<th style="width:20%;">Username/Email</th>
<th style="width:8%;">Status</th>
<th style="width:40%;">Notes</th>
<th style="width:14%;">Actions</th>
</tr>
</thead>
<tbody>
@ -490,6 +561,7 @@ class ControlPanelHandler(BaseHTTPRequestHandler):
</tbody>
</table>
</div>
<script>accountsData = {json.dumps(accounts)};</script>
"""
html = self.get_base_template("Accounts", content)
@ -502,18 +574,30 @@ class ControlPanelHandler(BaseHTTPRequestHandler):
api_keys = self.load_data('api-keys.json')
keys_table = ""
for key in api_keys:
masked_key = f'<span class="masked-key" onclick="toggleKey(this)" data-key="{key.get("key", "")}">' + \
('*' * len(key.get('key', ''))) + '</span>'
for i, key in enumerate(api_keys):
key_val = key.get('key', key.get('key_location', ''))
key_type = key.get('type', '')
status = key.get('status', 'active')
status_class = "status-active" if status == 'active' else ("status-inactive" if status in ['missing','inactive'] else "")
display_val = key_val if key_val else 'N/A'
masked = '*' * min(len(display_val), 30) if display_val not in ['N/A', 'NOT CONFIGURED'] else display_val
notes = key.get('notes', '')
keys_table += f"""
<tr>
<td>{key.get('service', 'N/A')}</td>
<td>{key.get('name', 'N/A')}</td>
<td>{masked_key}</td>
<td>{key.get('created', 'N/A')}</td>
<td>{key.get('expires', 'Never')}</td>
<td>{key.get('usage', 0)}</td>
<td style="font-size:0.85em;color:#8b949e;">{key_type}</td>
<td><span class="masked-key" onclick="toggleKey(this)" data-key="{display_val}">{masked}</span></td>
<td><span class="{status_class}">{status}</span></td>
<td style="font-size:0.85em;">{notes}</td>
<td style="width:120px;white-space:nowrap;">
<button class="btn btn-secondary" style="padding:4px 10px;font-size:12px;" onclick="editApiKey({i})">✏️ Edit</button>
<form method="POST" style="display:inline;">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="index" value="{i}">
<button type="submit" class="btn btn-danger" style="padding:4px 10px;font-size:12px;" onclick="return confirm('Delete {key.get("service", "")}?')">🗑</button>
</form>
</td>
</tr>
"""
@ -522,21 +606,31 @@ class ControlPanelHandler(BaseHTTPRequestHandler):
<div class="card-header">API Key Management</div>
<form method="POST" style="margin-bottom: 2rem;">
<div class="form-group">
<label>Service:</label>
<input type="text" name="service" required>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:1rem;">
<div class="form-group">
<label>Service:</label>
<input type="text" name="service" required placeholder="e.g. Anthropic">
</div>
<div class="form-group">
<label>Type:</label>
<input type="text" name="type" placeholder="e.g. API key, OAuth token">
</div>
<div class="form-group">
<label>Key Location / Value:</label>
<input type="text" name="key_location" required placeholder="e.g. ~/.credentials/key.env">
</div>
<div class="form-group">
<label>Status:</label>
<select name="status">
<option value="active">Active</option>
<option value="missing">Missing</option>
<option value="inactive">Inactive</option>
</select>
</div>
</div>
<div class="form-group">
<label>Key Name:</label>
<input type="text" name="name" required>
</div>
<div class="form-group">
<label>API Key:</label>
<input type="text" name="key" required>
</div>
<div class="form-group">
<label>Expires (optional):</label>
<input type="date" name="expires">
<label>Notes:</label>
<input type="text" name="notes" placeholder="Additional details">
</div>
<input type="hidden" name="action" value="add">
<button type="submit" class="btn">Add API Key</button>
@ -545,12 +639,12 @@ class ControlPanelHandler(BaseHTTPRequestHandler):
<table>
<thead>
<tr>
<th>Service</th>
<th>Name</th>
<th>Key (click to reveal)</th>
<th>Created</th>
<th>Expires</th>
<th>Usage Count</th>
<th style="width:18%;">Service</th>
<th style="width:15%;">Type</th>
<th style="width:22%;">Location (click to reveal)</th>
<th style="width:8%;">Status</th>
<th style="width:25%;">Notes</th>
<th style="width:12%;">Actions</th>
</tr>
</thead>
<tbody>
@ -558,6 +652,22 @@ class ControlPanelHandler(BaseHTTPRequestHandler):
</tbody>
</table>
</div>
<script>
var apiKeysData = {json.dumps(api_keys)};
function editApiKey(idx) {{
var k = apiKeysData[idx];
if (!k) return;
document.getElementById('editIndex').value = idx;
document.getElementById('editService').value = k.service || '';
document.getElementById('editUrl').value = k.key_location || k.key || '';
document.getElementById('editUsername').value = k.type || '';
document.getElementById('editStatus').value = k.status || 'active';
document.getElementById('editNotes').value = k.notes || '';
document.getElementById('editForm').action = '/api-keys';
document.getElementById('editModal').querySelector('h3').textContent = 'Edit API Key';
document.getElementById('editModal').style.display = 'flex';
}}
</script>
"""
html = self.get_base_template("API Keys", content)
@ -566,52 +676,165 @@ class ControlPanelHandler(BaseHTTPRequestHandler):
self.end_headers()
self.wfile.write(html.encode())
def check_remote_health(self, host, port):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2)
result = sock.connect_ex((host, port))
sock.close()
return result == 0
except:
return False
def serve_services(self):
services = [
{"name": "Feed Hunter Portal", "port": 8888, "path": ""},
{"name": "Chrome Debug", "port": 9222, "path": ""},
{"name": "OpenClaw Gateway", "port": 18789, "path": ""},
{"name": "Case Control Panel", "port": 8000, "path": ""},
]
services_table = ""
for service in services:
is_healthy = self.check_service_health(service["port"])
svc_data = self.load_data('services.json')
if not svc_data:
svc_data = {"local": [], "timers": [], "deployed": [], "infrastructure": []}
# --- Local Services ---
local_rows = ""
running_count = 0
for svc in svc_data.get('local', []):
port = svc.get('port')
is_healthy = self.check_service_health(port) if port else False
if is_healthy:
running_count += 1
status = "Running" if is_healthy else "Stopped"
status_class = "status-active" if is_healthy else "status-inactive"
url = f"http://localhost:{service['port']}{service['path']}"
link = f'<a href="{url}" target="_blank" style="color:#58a6ff;">{service["name"]}</a>'
services_table += f"""
url = f"http://192.168.86.45:{port}" if port else ""
name_cell = f'<a href="{url}" target="_blank" style="color:#58a6ff;">{svc["name"]}</a>' if url else svc["name"]
systemd = svc.get('systemd', '') or ''
local_rows += f"""
<tr>
<td>{link}</td>
<td><a href="{url}" target="_blank" style="color:#c9d1d9;">{service['port']}</a></td>
<td><span class="{status_class}">{status}</span></td>
<td>N/A</td>
</tr>
"""
<td>{name_cell}</td>
<td style="color:#8b949e;">{port or ''}</td>
<td><span class="{status_class}">{status}</span></td>
<td style="font-size:0.85em;color:#8b949e;">{systemd}</td>
<td style="font-size:0.85em;">{svc.get('description', '')}</td>
</tr>"""
# --- Timers ---
timer_rows = ""
for t in svc_data.get('timers', []):
timer_rows += f"""
<tr>
<td style="color:#f0f6fc;">{t['name']}</td>
<td style="color:#8b949e;">{t.get('interval', '')}</td>
<td style="font-size:0.85em;color:#8b949e;">{t.get('systemd', '')}</td>
<td style="font-size:0.85em;">{t.get('description', '')}</td>
</tr>"""
# --- Deployed Apps ---
deployed_cards = ""
for app in svc_data.get('deployed', []):
deployed_cards += f"""
<div style="display:flex;align-items:center;gap:1rem;padding:12px;border:1px solid #30363d;border-radius:8px;margin-bottom:8px;background:#161b22;">
<div style="flex:1;">
<a href="{app['url']}" target="_blank" style="color:#58a6ff;font-weight:bold;font-size:1.1em;">{app['name']}</a>
<div style="color:#8b949e;font-size:0.85em;margin-top:4px;">{app.get('description', '')}</div>
</div>
<span style="background:#21262d;border:1px solid #30363d;border-radius:4px;padding:4px 10px;font-size:0.8em;color:#a371f7;">{app.get('platform', '')}</span>
</div>"""
if not deployed_cards:
deployed_cards = '<p style="color:#484f58;">No deployed apps yet.</p>'
# --- Infrastructure ---
infra_rows = ""
for inf in svc_data.get('infrastructure', []):
host = inf.get('host', '')
port = inf.get('port')
is_healthy = self.check_remote_health(host, port) if host and port else False
status = "Reachable" if is_healthy else ("Unknown" if not port else "Unreachable")
status_class = "status-active" if is_healthy else ("" if not port else "status-inactive")
url = f"http://{host}:{port}" if port else ""
name_cell = f'<a href="{url}" target="_blank" style="color:#58a6ff;">{inf["name"]}</a>' if url else inf["name"]
infra_rows += f"""
<tr>
<td>{name_cell}</td>
<td style="color:#8b949e;">{host}</td>
<td style="color:#8b949e;">{port or ''}</td>
<td><span class="{status_class}">● {status}</span></td>
<td style="font-size:0.85em;">{inf.get('description', '')}</td>
</tr>"""
total_local = len(svc_data.get('local', []))
total_timers = len(svc_data.get('timers', []))
content = f"""
<div class="stats-grid">
<div class="stat-card">
<span class="stat-number">{running_count}/{total_local}</span>
<div class="stat-label">Services Running</div>
</div>
<div class="stat-card">
<span class="stat-number">{total_timers}</span>
<div class="stat-label">Active Timers</div>
</div>
<div class="stat-card">
<span class="stat-number">{len(svc_data.get('deployed', []))}</span>
<div class="stat-label">Deployed Apps</div>
</div>
<div class="stat-card">
<span class="stat-number">{len(svc_data.get('infrastructure', []))}</span>
<div class="stat-label">Infrastructure</div>
</div>
</div>
<div class="card">
<div class="card-header">Running Services</div>
<div class="card-header">🖥️ Local Services (192.168.86.45)</div>
<table>
<thead>
<tr>
<th>Service Name</th>
<th>Port</th>
<th>Status</th>
<th>Uptime</th>
<th style="width:20%;">Service</th>
<th style="width:8%;">Port</th>
<th style="width:10%;">Status</th>
<th style="width:22%;">Systemd Unit</th>
<th style="width:40%;">Description</th>
</tr>
</thead>
<tbody>
{services_table}
</tbody>
<tbody>{local_rows}</tbody>
</table>
<div style="margin-top: 1rem;">
<button onclick="location.reload()" class="btn">Refresh Status</button>
</div>
</div>
<div class="card">
<div class="card-header">⏱️ Scheduled Timers</div>
<table>
<thead>
<tr>
<th style="width:20%;">Name</th>
<th style="width:15%;">Interval</th>
<th style="width:25%;">Systemd Unit</th>
<th style="width:40%;">Description</th>
</tr>
</thead>
<tbody>{timer_rows}</tbody>
</table>
</div>
<div class="card">
<div class="card-header">🚀 Deployed Applications</div>
{deployed_cards}
</div>
<div class="card">
<div class="card-header">🏗️ Infrastructure</div>
<table>
<thead>
<tr>
<th style="width:18%;">Service</th>
<th style="width:15%;">Host</th>
<th style="width:8%;">Port</th>
<th style="width:12%;">Status</th>
<th style="width:47%;">Description</th>
</tr>
</thead>
<tbody>{infra_rows}</tbody>
</table>
</div>
<div style="margin-top:1rem;">
<button onclick="location.reload()" class="btn">🔄 Refresh Status</button>
</div>
"""
@ -812,6 +1035,123 @@ class ControlPanelHandler(BaseHTTPRequestHandler):
self.end_headers()
self.wfile.write(html.encode())
def serve_notes(self):
notes = self.load_data('notes.json')
notes_html = ""
for i, note in enumerate(notes):
color = note.get('color', '#30363d')
notes_html += f"""
<div class="card" style="border-left: 3px solid {color};">
<div style="display:flex;justify-content:space-between;align-items:flex-start;">
<div style="flex:1;">
<strong style="color:#f0f6fc;font-size:1.1em;">{note.get('title', 'Untitled')}</strong>
<span style="color:#484f58;font-size:0.8em;margin-left:8px;">{note.get('created', '')}</span>
</div>
<div style="white-space:nowrap;">
<button class="btn btn-secondary" style="padding:4px 10px;font-size:12px;" onclick="editNote({i})">✏️</button>
<form method="POST" style="display:inline;">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="index" value="{i}">
<button type="submit" class="btn btn-danger" style="padding:4px 10px;font-size:12px;" onclick="return confirm('Delete this note?')">🗑</button>
</form>
</div>
</div>
<div style="color:#c9d1d9;margin-top:8px;white-space:pre-wrap;line-height:1.6;">{note.get('content', '')}</div>
</div>
"""
content = f"""
<div class="card">
<div class="card-header">📝 Add Note</div>
<form method="POST">
<div style="display:grid;grid-template-columns:1fr auto;gap:1rem;">
<div class="form-group">
<label>Title:</label>
<input type="text" name="title" required placeholder="Note title">
</div>
<div class="form-group">
<label>Color:</label>
<select name="color">
<option value="#58a6ff">🔵 Blue</option>
<option value="#40c463">🟢 Green</option>
<option value="#f59e0b">🟡 Yellow</option>
<option value="#f85149">🔴 Red</option>
<option value="#a371f7">🟣 Purple</option>
<option value="#30363d">⚫ Gray</option>
</select>
</div>
</div>
<div class="form-group">
<label>Content:</label>
<textarea name="content" rows="4" placeholder="Write your note..."></textarea>
</div>
<input type="hidden" name="action" value="add">
<button type="submit" class="btn">Add Note</button>
</form>
</div>
{notes_html if notes_html else '<div class="card"><p style="color:#484f58;">No notes yet. Add one above.</p></div>'}
<script>
var notesData = {json.dumps(notes)};
function editNote(idx) {{
var n = notesData[idx];
if (!n) return;
document.getElementById('editIndex').value = idx;
document.getElementById('editService').value = n.title || '';
document.getElementById('editUrl').value = '';
document.getElementById('editUsername').value = '';
document.getElementById('editStatus').value = 'active';
document.getElementById('editNotes').value = n.content || '';
document.getElementById('editForm').action = '/notes';
document.getElementById('editModal').querySelector('h3').textContent = 'Edit Note';
document.getElementById('editModal').style.display = 'flex';
}}
</script>
"""
html = self.get_base_template("Notes", content)
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(html.encode())
def handle_notes_post(self, form_data):
action = form_data.get('action', [''])[0]
notes = self.load_data('notes.json')
if action == 'add':
new_note = {
"title": form_data.get('title', [''])[0],
"content": form_data.get('content', [''])[0],
"color": form_data.get('color', ['#30363d'])[0],
"created": datetime.now().strftime('%Y-%m-%d %H:%M')
}
notes.insert(0, new_note)
self.save_data('notes.json', notes)
self.log_activity("Note Added", f"Added: {new_note['title']}")
elif action == 'edit':
idx = int(form_data.get('index', ['0'])[0])
if 0 <= idx < len(notes):
# Edit modal: service=title, notes=content
notes[idx]['title'] = form_data.get('service', [notes[idx].get('title', '')])[0]
notes[idx]['content'] = form_data.get('notes', [notes[idx].get('content', '')])[0]
self.save_data('notes.json', notes)
self.log_activity("Note Updated", f"Updated: {notes[idx]['title']}")
elif action == 'delete':
idx = int(form_data.get('index', ['0'])[0])
if 0 <= idx < len(notes):
deleted = notes.pop(idx)
self.save_data('notes.json', notes)
self.log_activity("Note Deleted", f"Deleted: {deleted.get('title', 'unknown')}")
self.send_response(302)
self.send_header('Location', '/notes')
self.end_headers()
def handle_todos_post(self, form_data):
action = form_data.get('action', [''])[0]
todos = self.load_data('todos.json')
@ -831,8 +1171,10 @@ class ControlPanelHandler(BaseHTTPRequestHandler):
self.end_headers()
def handle_accounts_post(self, form_data):
if form_data.get('action', [''])[0] == 'add':
accounts = self.load_data('accounts.json')
action = form_data.get('action', [''])[0]
accounts = self.load_data('accounts.json')
if action == 'add':
new_account = {
"service": form_data.get('service', [''])[0],
"url": form_data.get('url', [''])[0],
@ -846,27 +1188,64 @@ class ControlPanelHandler(BaseHTTPRequestHandler):
self.save_data('accounts.json', accounts)
self.log_activity("Account Added", f"Added {new_account['service']}")
# Redirect back to accounts page
elif action == 'edit':
idx = int(form_data.get('index', ['0'])[0])
if 0 <= idx < len(accounts):
accounts[idx]['service'] = form_data.get('service', [accounts[idx].get('service', '')])[0]
accounts[idx]['url'] = form_data.get('url', [accounts[idx].get('url', '')])[0]
accounts[idx]['username'] = form_data.get('username', [accounts[idx].get('username', '')])[0]
accounts[idx]['status'] = form_data.get('status', [accounts[idx].get('status', 'active')])[0]
accounts[idx]['notes'] = form_data.get('notes', [accounts[idx].get('notes', '')])[0]
self.save_data('accounts.json', accounts)
self.log_activity("Account Updated", f"Updated {accounts[idx]['service']}")
elif action == 'delete':
idx = int(form_data.get('index', ['0'])[0])
if 0 <= idx < len(accounts):
deleted = accounts.pop(idx)
self.save_data('accounts.json', accounts)
self.log_activity("Account Deleted", f"Deleted {deleted.get('service', 'unknown')}")
self.send_response(302)
self.send_header('Location', '/accounts')
self.end_headers()
def handle_api_keys_post(self, form_data):
if form_data.get('action', [''])[0] == 'add':
api_keys = self.load_data('api-keys.json')
action = form_data.get('action', [''])[0]
api_keys = self.load_data('api-keys.json')
if action == 'add':
new_key = {
"service": form_data.get('service', [''])[0],
"name": form_data.get('name', [''])[0],
"key": form_data.get('key', [''])[0],
"created": datetime.now().strftime('%Y-%m-%d'),
"expires": form_data.get('expires', ['Never'])[0] or "Never",
"usage": 0
"key_location": form_data.get('key_location', [''])[0],
"type": form_data.get('type', [''])[0],
"status": form_data.get('status', ['active'])[0],
"notes": form_data.get('notes', [''])[0],
"created": datetime.now().strftime('%Y-%m-%d')
}
api_keys.append(new_key)
self.save_data('api-keys.json', api_keys)
self.log_activity("API Key Added", f"Added key for {new_key['service']}")
# Redirect back to api-keys page
elif action == 'edit':
idx = int(form_data.get('index', ['0'])[0])
if 0 <= idx < len(api_keys):
# The edit modal reuses account fields: service=service, url=key_location, username=type, status=status, notes=notes
api_keys[idx]['service'] = form_data.get('service', [api_keys[idx].get('service', '')])[0]
api_keys[idx]['key_location'] = form_data.get('url', [api_keys[idx].get('key_location', '')])[0]
api_keys[idx]['type'] = form_data.get('username', [api_keys[idx].get('type', '')])[0]
api_keys[idx]['status'] = form_data.get('status', [api_keys[idx].get('status', 'active')])[0]
api_keys[idx]['notes'] = form_data.get('notes', [api_keys[idx].get('notes', '')])[0]
self.save_data('api-keys.json', api_keys)
self.log_activity("API Key Updated", f"Updated {api_keys[idx]['service']}")
elif action == 'delete':
idx = int(form_data.get('index', ['0'])[0])
if 0 <= idx < len(api_keys):
deleted = api_keys.pop(idx)
self.save_data('api-keys.json', api_keys)
self.log_activity("API Key Deleted", f"Deleted {deleted.get('service', 'unknown')}")
self.send_response(302)
self.send_header('Location', '/api-keys')
self.end_headers()

11
projects/crypto-signals/.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
node_modules/
.next/
__pycache__/
*.pyc
.env
*.db
*.sqlite
*.log
venv/
dist/
.credentials/

View File

@ -0,0 +1,433 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CoinEx Futures Scanner</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #0a0e17; color: #e1e5eb; font-family: 'SF Mono', 'Fira Code', monospace; font-size: 13px; }
.header { background: #111827; padding: 12px 20px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #1f2937; }
.header h1 { font-size: 16px; color: #60a5fa; }
.header .status { font-size: 11px; color: #6b7280; }
.header .status .live { color: #10b981; }
.controls { background: #111827; padding: 8px 20px; display: flex; gap: 12px; align-items: center; border-bottom: 1px solid #1f2937; }
.controls label { color: #9ca3af; font-size: 11px; }
.controls select, .controls input { background: #1f2937; border: 1px solid #374151; color: #e5e7eb; padding: 4px 8px; border-radius: 4px; font-size: 12px; font-family: inherit; }
.thresholds { background: #0d1321; padding: 10px 20px; display: flex; gap: 20px; border-bottom: 1px solid #1f2937; font-size: 11px; }
.thresholds .th-item { display: flex; gap: 6px; align-items: center; }
.thresholds .th-label { color: #6b7280; }
.thresholds .th-long { color: #10b981; }
.thresholds .th-short { color: #ef4444; }
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 1px; background: #1f2937; padding: 1px; }
.coin-card { background: #111827; padding: 12px; }
.coin-card.signal-long { border-left: 3px solid #10b981; }
.coin-card.signal-short { border-left: 3px solid #ef4444; }
.coin-card.signal-none { border-left: 3px solid #374151; }
.coin-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.coin-name { font-size: 14px; font-weight: 700; }
.coin-price { font-size: 13px; color: #9ca3af; }
.coin-change { font-size: 12px; padding: 2px 6px; border-radius: 3px; }
.coin-change.up { background: #064e3b; color: #34d399; }
.coin-change.down { background: #7f1d1d; color: #fca5a5; }
.indicators { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-bottom: 8px; }
.ind { background: #0a0e17; padding: 6px 8px; border-radius: 4px; }
.ind-label { font-size: 10px; color: #6b7280; text-transform: uppercase; letter-spacing: 0.5px; }
.ind-value { font-size: 14px; font-weight: 600; margin-top: 2px; }
.ind-pts { font-size: 10px; margin-top: 1px; }
.ind-pts.pts-high { color: #10b981; }
.ind-pts.pts-med { color: #f59e0b; }
.ind-pts.pts-low { color: #6b7280; }
.score-bar { margin-top: 8px; }
.score-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 4px; }
.score-label { font-size: 11px; color: #9ca3af; }
.score-value { font-size: 13px; font-weight: 700; }
.score-value.above { color: #10b981; }
.score-value.below { color: #6b7280; }
.bar-bg { background: #1f2937; height: 6px; border-radius: 3px; overflow: hidden; position: relative; }
.bar-fill { height: 100%; border-radius: 3px; transition: width 0.5s; }
.bar-fill.long { background: linear-gradient(90deg, #065f46, #10b981); }
.bar-fill.short { background: linear-gradient(90deg, #7f1d1d, #ef4444); }
.bar-fill.neutral { background: #374151; }
.bar-threshold { position: absolute; top: -2px; height: 10px; width: 2px; background: #f59e0b; }
.signal-badge { display: inline-block; padding: 2px 8px; border-radius: 3px; font-size: 11px; font-weight: 700; margin-top: 6px; }
.signal-badge.long { background: #064e3b; color: #34d399; }
.signal-badge.short { background: #7f1d1d; color: #fca5a5; }
.signal-badge.neutral { background: #1f2937; color: #6b7280; }
.position-tag { display: inline-block; padding: 2px 6px; border-radius: 3px; font-size: 10px; font-weight: 700; margin-left: 6px; }
.position-tag.live-long { background: #10b981; color: #000; }
.position-tag.live-short { background: #ef4444; color: #fff; }
.rsi-gauge { position: relative; height: 8px; background: linear-gradient(90deg, #10b981 0%, #10b981 30%, #f59e0b 30%, #f59e0b 70%, #ef4444 70%, #ef4444 100%); border-radius: 4px; margin-top: 4px; }
.rsi-needle { position: absolute; top: -3px; width: 4px; height: 14px; background: #fff; border-radius: 2px; transform: translateX(-50%); transition: left 0.5s; }
.loading { text-align: center; padding: 60px; color: #6b7280; }
.error { text-align: center; padding: 60px; color: #ef4444; }
.summary { background: #111827; padding: 10px 20px; border-bottom: 1px solid #1f2937; display: flex; gap: 20px; font-size: 12px; }
.summary .s-item { display: flex; gap: 4px; }
.summary .s-label { color: #6b7280; }
.summary .s-val { font-weight: 600; }
.summary .s-val.green { color: #10b981; }
.summary .s-val.red { color: #ef4444; }
.summary .s-val.yellow { color: #f59e0b; }
</style>
</head>
<body>
<div class="header">
<h1>⚡ CoinEx Futures Scanner</h1>
<div class="status">
<span class="live">● LIVE</span> |
Last scan: <span id="lastScan"></span> |
Auto-refresh: <span id="refreshCountdown">30</span>s
</div>
</div>
<div class="thresholds">
<div class="th-item"><span class="th-label">LONG threshold:</span> <span class="th-long">45 pts</span></div>
<div class="th-item"><span class="th-label">SHORT threshold:</span> <span class="th-short">50 pts</span></div>
<div class="th-item"><span class="th-label">TP:</span> <span style="color:#10b981">+5%</span></div>
<div class="th-item"><span class="th-label">SL:</span> <span style="color:#ef4444">-3%</span></div>
<div class="th-item"><span class="th-label">Leverage:</span> <span style="color:#60a5fa">5x / 7x (score≥60)</span></div>
</div>
<div class="controls">
<label>Sort:</label>
<select id="sortBy" onchange="renderCoins()">
<option value="longScore">Long Score ↓</option>
<option value="shortScore">Short Score ↓</option>
<option value="name">Name A-Z</option>
<option value="change">24h Change</option>
<option value="rsi">RSI</option>
</select>
<label>Filter:</label>
<select id="filterBy" onchange="renderCoins()">
<option value="all">All Coins</option>
<option value="longSignal">Long Signals Only</option>
<option value="shortSignal">Short Signals Only</option>
<option value="anySignal">Any Signal</option>
</select>
</div>
<div class="summary" id="summary"></div>
<div class="grid" id="grid"><div class="loading">Scanning 29 coins...</div></div>
<script>
const COINS = [
"BTCUSDT","ETHUSDT","SOLUSDT","XRPUSDT","DOGEUSDT",
"ADAUSDT","AVAXUSDT","LINKUSDT","DOTUSDT","MATICUSDT",
"NEARUSDT","ATOMUSDT","LTCUSDT","UNIUSDT","AAVEUSDT",
"FILUSDT","ALGOUSDT","XLMUSDT","VETUSDT","ICPUSDT",
"APTUSDT","SUIUSDT","ARBUSDT","OPUSDT","SEIUSDT",
"HYPEUSDT","TRUMPUSDT","PUMPUSDT","ASTERUSDT"
];
const LONG_THRESHOLD = 45;
const SHORT_THRESHOLD = 50;
let coinData = [];
let refreshTimer = 30;
function calcRSI(closes, period=14) {
if (closes.length < period + 1) return 50;
let gains = [], losses = [];
for (let i = 1; i < closes.length; i++) {
let d = closes[i] - closes[i-1];
gains.push(d > 0 ? d : 0);
losses.push(d < 0 ? -d : 0);
}
let avgGain = gains.slice(0, period).reduce((a,b)=>a+b,0) / period;
let avgLoss = losses.slice(0, period).reduce((a,b)=>a+b,0) / period;
for (let i = period; i < gains.length; i++) {
avgGain = (avgGain * (period-1) + gains[i]) / period;
avgLoss = (avgLoss * (period-1) + losses[i]) / period;
}
if (avgLoss === 0) return 100;
return Math.round((100 - 100/(1 + avgGain/avgLoss)) * 10) / 10;
}
function calcVWAP(klines) {
let cumVP = 0, cumVol = 0;
for (let k of klines) {
let typical = (k.high + k.low + k.close) / 3;
cumVP += typical * k.volume;
cumVol += k.volume;
}
return cumVol > 0 ? cumVP / cumVol : klines[klines.length-1].close;
}
function calcBB(closes, period=20) {
if (closes.length < period) return { lower: closes[closes.length-1], mid: closes[closes.length-1], upper: closes[closes.length-1] };
let slice = closes.slice(-period);
let sma = slice.reduce((a,b)=>a+b,0) / period;
let std = Math.sqrt(slice.reduce((a,b)=>a+(b-sma)**2,0) / period);
return { lower: sma - 2*std, mid: sma, upper: sma + 2*std };
}
function scoreLong(rsi, vwapPct, change24h, bbPos) {
let score = 0, breakdown = {};
if (rsi < 25) { score += 30; breakdown.rsi = 30; }
else if (rsi < 30) { score += 25; breakdown.rsi = 25; }
else if (rsi < 35) { score += 15; breakdown.rsi = 15; }
else if (rsi < 40) { score += 5; breakdown.rsi = 5; }
else { breakdown.rsi = 0; }
if (vwapPct < -3) { score += 20; breakdown.vwap = 20; }
else if (vwapPct < -1.5) { score += 15; breakdown.vwap = 15; }
else if (vwapPct < 0) { score += 8; breakdown.vwap = 8; }
else { breakdown.vwap = 0; }
if (change24h < -10) { score += 15; breakdown.change = 15; }
else if (change24h < -5) { score += 10; breakdown.change = 10; }
else if (change24h < -2) { score += 5; breakdown.change = 5; }
else { breakdown.change = 0; }
if (bbPos < 0) { score += 15; breakdown.bb = 15; }
else if (bbPos < 0.2) { score += 10; breakdown.bb = 10; }
else { breakdown.bb = 0; }
breakdown.total = score;
return breakdown;
}
function scoreShort(rsi, vwapPct, change24h, bbPos) {
let score = 0, breakdown = {};
if (rsi > 75) { score += 30; breakdown.rsi = 30; }
else if (rsi > 70) { score += 25; breakdown.rsi = 25; }
else if (rsi > 65) { score += 15; breakdown.rsi = 15; }
else if (rsi > 60) { score += 5; breakdown.rsi = 5; }
else { breakdown.rsi = 0; }
if (vwapPct > 3) { score += 20; breakdown.vwap = 20; }
else if (vwapPct > 1.5) { score += 15; breakdown.vwap = 15; }
else if (vwapPct > 0) { score += 8; breakdown.vwap = 8; }
else { breakdown.vwap = 0; }
if (change24h > 10) { score += 15; breakdown.change = 15; }
else if (change24h > 5) { score += 10; breakdown.change = 10; }
else if (change24h > 2) { score += 5; breakdown.change = 5; }
else { breakdown.change = 0; }
if (bbPos > 1) { score += 15; breakdown.bb = 15; }
else if (bbPos > 0.8) { score += 10; breakdown.bb = 10; }
else { breakdown.bb = 0; }
breakdown.total = score;
return breakdown;
}
async function fetchCoin(symbol) {
try {
let url = `https://api.binance.us/api/v3/klines?symbol=${symbol}&interval=1h&limit=100`;
let resp = await fetch(url);
let raw = await resp.json();
if (!Array.isArray(raw) || raw.length < 30) return null;
let klines = raw.map(k => ({
open: parseFloat(k[1]),
high: parseFloat(k[2]),
low: parseFloat(k[3]),
close: parseFloat(k[4]),
volume: parseFloat(k[5])
}));
let closes = klines.map(k => k.close);
let price = closes[closes.length - 1];
let price24hAgo = closes[Math.max(0, closes.length - 25)];
let change24h = ((price - price24hAgo) / price24hAgo) * 100;
let rsi = calcRSI(closes);
let vwap = calcVWAP(klines.slice(-24));
let vwapPct = ((price - vwap) / vwap) * 100;
let bb = calcBB(closes);
let bbRange = bb.upper - bb.lower || 1;
let bbPos = (price - bb.lower) / bbRange;
let longBreakdown = scoreLong(rsi, vwapPct, change24h, bbPos);
let shortBreakdown = scoreShort(rsi, vwapPct, change24h, bbPos);
return {
symbol,
name: symbol.replace('USDT',''),
price,
change24h,
rsi,
vwap,
vwapPct,
bbPos,
bbLower: bb.lower,
bbMid: bb.mid,
bbUpper: bb.upper,
longScore: longBreakdown,
shortScore: shortBreakdown,
isLongSignal: longBreakdown.total >= LONG_THRESHOLD,
isShortSignal: shortBreakdown.total >= SHORT_THRESHOLD,
leverage: Math.max(longBreakdown.total, shortBreakdown.total) >= 60 ? '7x' : '5x'
};
} catch(e) {
return null;
}
}
function ptsClass(pts, max) {
if (pts >= max * 0.6) return 'pts-high';
if (pts >= max * 0.3) return 'pts-med';
return 'pts-low';
}
function formatPrice(p) {
if (p >= 100) return p.toFixed(2);
if (p >= 1) return p.toFixed(4);
if (p >= 0.01) return p.toFixed(5);
return p.toFixed(7);
}
function renderCoins() {
let sorted = [...coinData];
let sortBy = document.getElementById('sortBy').value;
let filterBy = document.getElementById('filterBy').value;
if (filterBy === 'longSignal') sorted = sorted.filter(c => c.isLongSignal);
else if (filterBy === 'shortSignal') sorted = sorted.filter(c => c.isShortSignal);
else if (filterBy === 'anySignal') sorted = sorted.filter(c => c.isLongSignal || c.isShortSignal);
if (sortBy === 'longScore') sorted.sort((a,b) => b.longScore.total - a.longScore.total);
else if (sortBy === 'shortScore') sorted.sort((a,b) => b.shortScore.total - a.shortScore.total);
else if (sortBy === 'name') sorted.sort((a,b) => a.name.localeCompare(b.name));
else if (sortBy === 'change') sorted.sort((a,b) => a.change24h - b.change24h);
else if (sortBy === 'rsi') sorted.sort((a,b) => a.rsi - b.rsi);
let longSignals = coinData.filter(c => c.isLongSignal).length;
let shortSignals = coinData.filter(c => c.isShortSignal).length;
let avgRSI = (coinData.reduce((a,c) => a + c.rsi, 0) / coinData.length).toFixed(1);
document.getElementById('summary').innerHTML = `
<div class="s-item"><span class="s-label">Coins:</span> <span class="s-val">${coinData.length}</span></div>
<div class="s-item"><span class="s-label">Long signals:</span> <span class="s-val green">${longSignals}</span></div>
<div class="s-item"><span class="s-label">Short signals:</span> <span class="s-val red">${shortSignals}</span></div>
<div class="s-item"><span class="s-label">Avg RSI:</span> <span class="s-val ${avgRSI < 40 ? 'green' : avgRSI > 60 ? 'red' : 'yellow'}">${avgRSI}</span></div>
`;
let html = '';
for (let c of sorted) {
let signalClass = c.isLongSignal ? 'signal-long' : c.isShortSignal ? 'signal-short' : 'signal-none';
let changeClass = c.change24h >= 0 ? 'up' : 'down';
let bestScore = Math.max(c.longScore.total, c.shortScore.total);
let bestDir = c.longScore.total >= c.shortScore.total ? 'long' : 'short';
html += `
<div class="coin-card ${signalClass}">
<div class="coin-top">
<div>
<span class="coin-name">${c.name}</span>
${c.isLongSignal ? '<span class="position-tag live-long">LONG ✓</span>' : ''}
${c.isShortSignal ? '<span class="position-tag live-short">SHORT ✓</span>' : ''}
</div>
<span class="coin-change ${changeClass}">${c.change24h >= 0 ? '+' : ''}${c.change24h.toFixed(2)}%</span>
</div>
<div class="coin-price">$${formatPrice(c.price)}</div>
<div class="indicators">
<div class="ind">
<div class="ind-label">RSI (14)</div>
<div class="ind-value" style="color:${c.rsi < 30 ? '#10b981' : c.rsi > 70 ? '#ef4444' : '#f59e0b'}">${c.rsi}</div>
<div class="rsi-gauge"><div class="rsi-needle" style="left:${Math.min(100, Math.max(0, c.rsi))}%"></div></div>
<div class="ind-pts ${ptsClass(Math.max(c.longScore.rsi, c.shortScore.rsi), 30)}">
L:+${c.longScore.rsi} / S:+${c.shortScore.rsi}
</div>
</div>
<div class="ind">
<div class="ind-label">VWAP</div>
<div class="ind-value" style="color:${c.vwapPct < -1.5 ? '#10b981' : c.vwapPct > 1.5 ? '#ef4444' : '#9ca3af'}">${c.vwapPct >= 0 ? '+' : ''}${c.vwapPct.toFixed(2)}%</div>
<div class="ind-pts ${ptsClass(Math.max(c.longScore.vwap, c.shortScore.vwap), 20)}">
L:+${c.longScore.vwap} / S:+${c.shortScore.vwap}
</div>
</div>
<div class="ind">
<div class="ind-label">24h Change</div>
<div class="ind-value" style="color:${c.change24h < -5 ? '#10b981' : c.change24h > 5 ? '#ef4444' : '#9ca3af'}">${c.change24h >= 0 ? '+' : ''}${c.change24h.toFixed(2)}%</div>
<div class="ind-pts ${ptsClass(Math.max(c.longScore.change, c.shortScore.change), 15)}">
L:+${c.longScore.change} / S:+${c.shortScore.change}
</div>
</div>
<div class="ind">
<div class="ind-label">BB Position</div>
<div class="ind-value" style="color:${c.bbPos < 0.2 ? '#10b981' : c.bbPos > 0.8 ? '#ef4444' : '#9ca3af'}">${c.bbPos.toFixed(3)}</div>
<div class="ind-pts ${ptsClass(Math.max(c.longScore.bb, c.shortScore.bb), 15)}">
L:+${c.longScore.bb} / S:+${c.shortScore.bb}
</div>
</div>
</div>
<div class="score-bar">
<div class="score-row">
<span class="score-label">LONG</span>
<span class="score-value ${c.longScore.total >= LONG_THRESHOLD ? 'above' : 'below'}">${c.longScore.total}/80</span>
</div>
<div class="bar-bg">
<div class="bar-fill ${c.longScore.total >= LONG_THRESHOLD ? 'long' : 'neutral'}" style="width:${(c.longScore.total/80)*100}%"></div>
<div class="bar-threshold" style="left:${(LONG_THRESHOLD/80)*100}%"></div>
</div>
</div>
<div class="score-bar" style="margin-top:4px">
<div class="score-row">
<span class="score-label">SHORT</span>
<span class="score-value ${c.shortScore.total >= SHORT_THRESHOLD ? 'above' : 'below'}">${c.shortScore.total}/80</span>
</div>
<div class="bar-bg">
<div class="bar-fill ${c.shortScore.total >= SHORT_THRESHOLD ? 'short' : 'neutral'}" style="width:${(c.shortScore.total/80)*100}%"></div>
<div class="bar-threshold" style="left:${(SHORT_THRESHOLD/80)*100}%"></div>
</div>
</div>
${bestScore >= Math.min(LONG_THRESHOLD, SHORT_THRESHOLD) ?
`<span class="signal-badge ${bestDir}">${bestDir.toUpperCase()} ${bestScore}pts → ${c.leverage}</span>` :
`<span class="signal-badge neutral">No signal</span>`}
</div>`;
}
document.getElementById('grid').innerHTML = html || '<div class="loading">No coins match filter</div>';
}
async function scanAll() {
document.getElementById('grid').innerHTML = '<div class="loading">Scanning 29 coins...</div>';
// Fetch in batches of 5 to avoid rate limits
coinData = [];
for (let i = 0; i < COINS.length; i += 5) {
let batch = COINS.slice(i, i+5);
let results = await Promise.all(batch.map(fetchCoin));
coinData.push(...results.filter(r => r !== null));
renderCoins();
if (i + 5 < COINS.length) await new Promise(r => setTimeout(r, 500));
}
document.getElementById('lastScan').textContent = new Date().toLocaleTimeString();
renderCoins();
}
// Auto-refresh countdown
setInterval(() => {
refreshTimer--;
document.getElementById('refreshCountdown').textContent = refreshTimer;
if (refreshTimer <= 0) {
refreshTimer = 30;
scanAll();
}
}, 1000);
scanAll();
</script>
</body>
</html>

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
"""Simple HTTP server for the CoinEx Futures Scanner dashboard."""
import http.server
import os
import socketserver
PORT = 8891
DIR = os.path.dirname(os.path.abspath(__file__))
class Handler(http.server.SimpleHTTPRequestHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, directory=DIR, **kwargs)
def log_message(self, format, *args):
pass # Quiet
with socketserver.TCPServer(("", PORT), Handler) as httpd:
print(f"CoinEx Scanner dashboard at http://localhost:{PORT}")
httpd.serve_forever()

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,59 @@
{
"mode": "dry-run",
"position_size_pct": 5,
"max_positions": 2,
"max_leverage": 10,
"kill_switch_drawdown_pct": 50,
"tp_pct": 5,
"sl_pct": -3,
"trailing_stop_pct": 2,
"circuit_breaker_threshold": 3,
"scan_interval_minutes": 5,
"long_threshold": 45,
"short_threshold": 50,
"coin_blacklist": [],
"coin_whitelist": [],
"leverage_tiers": [
{
"min_score": 45,
"leverage": 5
},
{
"min_score": 60,
"leverage": 7
}
],
"scan_interval_seconds": 30,
"coin_watchlist": [
"BTCUSDT",
"ETHUSDT",
"SOLUSDT",
"XRPUSDT",
"DOGEUSDT",
"ADAUSDT",
"AVAXUSDT",
"LINKUSDT",
"DOTUSDT",
"MATICUSDT",
"NEARUSDT",
"ATOMUSDT",
"LTCUSDT",
"UNIUSDT",
"AAVEUSDT",
"FILUSDT",
"ALGOUSDT",
"XLMUSDT",
"VETUSDT",
"ICPUSDT",
"APTUSDT",
"SUIUSDT",
"ARBUSDT",
"OPUSDT",
"SEIUSDT",
"HYPEUSDT",
"TRUMPUSDT",
"PUMPUSDT",
"ASTERUSDT"
],
"last_updated": "2026-03-02T02:38:26.430Z"
}

View File

@ -0,0 +1,8 @@
{
"peak_pnl": {
"TRUMPUSDT_short": 0.88,
"PUMPUSDT_short": -2.7966
},
"last_alert": null,
"starting_balance": 146.83821322
}

View File

@ -1,78 +1,50 @@
{
"cash": 10548.59340884497,
"cash": 14573.327156868609,
"positions": {
"SEI_long_f875": {
"symbol": "SEI",
"direction": "long",
"leverage": 15,
"margin_usd": 200,
"notional": 3000,
"entry_price": 0.0702,
"current_price": 0.0702,
"liquidation_price": 0.0655,
"unrealized_pnl": 0.0,
"entry_fee": 1.5,
"opened_at": "2026-02-11T15:15:18.869862+00:00",
"reason": "Long scanner score:70"
},
"OP_long_133e": {
"symbol": "OP",
"direction": "long",
"leverage": 7,
"margin_usd": 200,
"notional": 1400,
"entry_price": 0.172,
"current_price": 0.172,
"liquidation_price": 0.1474,
"unrealized_pnl": 0.0,
"entry_fee": 0.7,
"opened_at": "2026-02-12T03:15:17.913748+00:00",
"reason": "Long scanner score:50"
},
"ARB_short_f35e": {
"symbol": "ARB",
"PUMP_short_cb54": {
"symbol": "PUMP",
"direction": "short",
"leverage": 7,
"margin_usd": 200,
"notional": 1400,
"entry_price": 0.1107,
"current_price": 0.1107,
"liquidation_price": 0.1265,
"entry_price": 0.002103,
"current_price": 0.002103,
"liquidation_price": 0.0024,
"unrealized_pnl": 0.0,
"entry_fee": 0.7,
"opened_at": "2026-02-12T04:15:18.517576+00:00",
"opened_at": "2026-02-20T03:31:00.752399+00:00",
"reason": "Short scanner score:58"
},
"FIL_short_9d66": {
"symbol": "FIL",
"direction": "short",
"ARB_long_0f74": {
"symbol": "ARB",
"direction": "long",
"leverage": 7,
"margin_usd": 200,
"notional": 1400,
"entry_price": 0.93,
"current_price": 0.93,
"liquidation_price": 1.0629,
"entry_price": 0.0981,
"current_price": 0.0981,
"liquidation_price": 0.0841,
"unrealized_pnl": 0.0,
"entry_fee": 0.7,
"opened_at": "2026-02-12T06:00:17.937727+00:00",
"reason": "Short scanner score:50"
"opened_at": "2026-02-20T03:31:01.354884+00:00",
"reason": "Long scanner score:55"
},
"VET_short_1776": {
"symbol": "VET",
"direction": "short",
"FIL_long_0c5f": {
"symbol": "FIL",
"direction": "long",
"leverage": 7,
"margin_usd": 200,
"notional": 1400,
"entry_price": 0.00785,
"current_price": 0.00785,
"liquidation_price": 0.009,
"entry_price": 0.9,
"current_price": 0.9,
"liquidation_price": 0.7714,
"unrealized_pnl": 0,
"entry_fee": 0.7,
"opened_at": "2026-02-12T06:15:18.429636+00:00",
"reason": "Short scanner score:55"
"opened_at": "2026-02-20T05:31:00.537230+00:00",
"reason": "Long scanner score:53"
}
},
"total_realized_pnl": 1820.693408845038,
"total_fees_paid": 272.0999999999996,
"total_realized_pnl": 6925.227156868812,
"total_fees_paid": 1751.9000000000133,
"total_funding_paid": 0
}

View File

@ -1,9 +1,7 @@
{
"peak_pnl": {
"SEI_long_f875": 0.0,
"OP_long_133e": 0.0,
"ARB_short_f35e": 0.0,
"FIL_short_9d66": 0.0
"PUMP_short_cb54": 0.0,
"ARB_long_0f74": 0.0
},
"last_alert": null
}

View File

@ -0,0 +1,189 @@
# CoinEx Live Futures Trader
**⚠️ REAL MONEY TRADING - EXTREME CAUTION REQUIRED ⚠️**
This is a live futures trading bot that connects to CoinEx and trades real money based on the paper trading strategy. Multiple safety mechanisms are implemented.
## 🛡️ Safety Features
### Kill Switch
- **Automatic Stop**: Bot automatically stops if account drops below 50% of starting balance
- **Position Closure**: Attempts to close all positions when kill switch triggers
- **Telegram Alert**: Sends immediate notification when triggered
- **Cannot be bypassed**: Checked before EVERY trading cycle
### Position Management
- **Max 3 positions** (down from 10 in paper trader)
- **Max 10x leverage** (no 15x trades allowed)
- **5% position sizing** (of current equity, ~$7.30 on $146 balance)
- **Futures only** - never touches spot trading
### Risk Controls
- **Stop Loss**: -3% on margin
- **Take Profit**: +5% on margin
- **Trailing Stop**: 2% from peak
- **Complete logging** of every trade
- **Error handling** - never crashes silently
## 📁 Files Created
- `coinex_live_trader.py` - Main trading bot
- `test_coinex_api.py` - API connection test
- `~/.config/systemd/user/coinex-live-trader.service` - Systemd service
- `~/.config/systemd/user/coinex-live-trader.timer` - 5-minute timer
- `COINEX_LIVE_TRADER.md` - This documentation
## 🚀 Getting Started
### 1. Test API Connection First
```bash
cd /home/wdjones/.openclaw/workspace/projects/crypto-signals/scripts
python3 test_coinex_api.py
```
This verifies:
- Credentials are loaded correctly
- API authentication works
- Balance, market data, and positions endpoints respond
### 2. Run Dry Run Mode
```bash
python3 coinex_live_trader.py --dry-run
```
Dry run mode does everything except place actual orders:
- ✅ Runs scanners
- ✅ Calculates position sizes
- ✅ Checks kill switch
- ✅ Logs all decisions
- ❌ No real orders placed
### 3. Live Trading (REAL MONEY)
```bash
python3 coinex_live_trader.py
```
**Only run this after thorough testing with dry-run mode!**
## 🔧 Systemd Service (DISABLED by default)
Service files are created but NOT enabled. To enable:
```bash
# Reload systemd configuration
systemctl --user daemon-reload
# Enable and start the timer
systemctl --user enable coinex-live-trader.timer
systemctl --user start coinex-live-trader.timer
# Check status
systemctl --user status coinex-live-trader.timer
```
To disable:
```bash
systemctl --user stop coinex-live-trader.timer
systemctl --user disable coinex-live-trader.timer
```
## 📊 Monitoring & Logs
### Log Files (in `/home/wdjones/.openclaw/workspace/projects/crypto-signals/data/coinex-live/`)
- `trades.log` - All trading activity
- `errors.log` - Error messages
- `trader_state.json` - Bot state (peak PnL tracking, starting balance)
### Systemd Logs
```bash
# View recent logs
journalctl --user -u coinex-live-trader.service -f
# View timer logs
journalctl --user -u coinex-live-trader.timer -f
```
### Telegram Alerts
- Position opens/closes
- Kill switch triggers
- Error notifications
- Periodic summaries
## ⚙️ Configuration
### Trading Parameters (in `coinex_live_trader.py`)
```python
POSITION_SIZE_PCT = 5.0 # 5% of equity per position
MAX_OPEN_POSITIONS = 3 # Max simultaneous positions
MAX_LEVERAGE = 10 # Leverage cap
SHORT_SCORE_THRESHOLD = 50 # Min score for shorts
LONG_SCORE_THRESHOLD = 45 # Min score for longs
TP_PCT = 5.0 # Take profit %
SL_PCT = -3.0 # Stop loss %
TRAILING_STOP_PCT = 2.0 # Trailing stop %
KILL_SWITCH_DRAWDOWN = 0.50 # 50% drawdown kill switch
```
### Scanning Logic
Uses the same short_scanner and spot scanner logic as the paper trader:
- **Short signals**: High RSI, above VWAP, overbought conditions
- **Long signals**: Low RSI, below VWAP, oversold conditions
- **Same coin list** as paper trader
## 🚨 Emergency Procedures
### Stop the Bot Immediately
```bash
# Stop the timer
systemctl --user stop coinex-live-trader.timer
# Kill any running instance
pkill -f coinex_live_trader.py
```
### Manual Position Closure
If you need to manually close positions, use the CoinEx web interface or API directly.
## 🔍 Key Differences from Paper Trader
| Feature | Paper Trader | Live Trader |
|---------|-------------|-------------|
| Position Size | Fixed $200 | 5% of equity (~$7.30) |
| Max Positions | 10 | 3 |
| Max Leverage | 15x | 10x |
| Kill Switch | None | 50% drawdown |
| Logging | Basic | Complete trade/error logs |
| Dry Run Mode | N/A | Available for testing |
## 📋 Pre-Launch Checklist
- [ ] API test passes (`test_coinex_api.py`)
- [ ] Dry run mode tested extensively
- [ ] Telegram alerts working
- [ ] Starting balance recorded in state file
- [ ] Log files created and writable
- [ ] Kill switch drawdown level confirmed (50%)
- [ ] Position sizing validated (5% = ~$7.30)
- [ ] Max positions confirmed (3)
- [ ] Leverage capped at 10x
## ⚠️ Important Warnings
1. **Real Money**: This trades with real money on real markets
2. **No Guarantees**: No strategy guarantees profits
3. **Monitor Closely**: Especially during first days of operation
4. **Market Risk**: Crypto futures are highly volatile
5. **API Risk**: Exchange issues could affect trading
6. **Kill Switch**: May not prevent all losses
7. **Test First**: Always test thoroughly in dry-run mode
## 📞 Support
- Check logs first: `trades.log` and `errors.log`
- Telegram alerts for real-time issues
- Systemd logs: `journalctl --user -u coinex-live-trader.service`
- Kill switch info in state file: `trader_state.json`
---
**Remember: This is real money trading. Start small, monitor closely, and never risk more than you can afford to lose.**

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,101 @@
#!/usr/bin/env python3
"""
Test script to verify CoinEx API connection and credentials.
Run this before using the live trader to ensure everything works.
"""
import sys
from pathlib import Path
# Add parent to path for imports
sys.path.insert(0, str(Path(__file__).parent))
from coinex_live_trader import CoinExAPI, load_coinex_credentials, setup_logging
def test_api():
"""Test CoinEx API connection and basic functionality."""
try:
print("=== CoinEx API Test ===")
# Setup logging directories
setup_logging()
print("Log directories created")
# Load credentials
print("Loading credentials...")
access_id, secret_key = load_coinex_credentials()
print(f"Access ID: {access_id[:8]}...")
# Initialize API
api = CoinExAPI(access_id, secret_key)
print("API client initialized")
# Test balance endpoint
print("\nTesting futures balance endpoint...")
balance = api.get_futures_balance()
print(f"Raw balance response: {balance}")
# Handle different response formats
if isinstance(balance, list):
if balance:
balance_data = balance[0] # Take first item if it's a list
# CoinEx uses different field names
total_balance = float(balance_data.get("available", 0)) + float(balance_data.get("frozen", 0))
available_balance = float(balance_data.get("available", 0))
else:
print("⚠️ Empty balance list returned")
total_balance = available_balance = 0
elif isinstance(balance, dict):
total_balance = float(balance.get("available", 0)) + float(balance.get("frozen", 0))
available_balance = float(balance.get("available", 0))
else:
print(f"⚠️ Unexpected balance format: {type(balance)}")
total_balance = available_balance = 0
print(f"✅ Balance retrieved successfully")
print(f" Total Balance: ${total_balance:.2f}")
print(f" Available Balance: ${available_balance:.2f}")
# Test market data endpoint
print("\nTesting market data endpoint...")
market_data = api.get_market_price("BTCUSDT")
if market_data:
print(f"✅ Market data retrieved successfully")
if isinstance(market_data, list):
print(f" Market data is a list with {len(market_data)} items")
if market_data:
print(f" First item keys: {list(market_data[0].keys()) if market_data[0] else 'Empty'}")
else:
print(f" Market data keys: {list(market_data.keys())}")
# Test positions endpoint
print("\nTesting positions endpoint...")
positions = api.get_positions()
if isinstance(positions, list):
print(f"✅ Positions retrieved successfully")
print(f" Number of open positions: {len(positions)}")
if positions:
for pos in positions[:3]: # Show first 3
market = pos.get("market", "Unknown")
side = pos.get("side", "Unknown")
amount = pos.get("amount", "0")
print(f" {market} {side} {amount}")
else:
print(f"✅ Positions endpoint working (empty/different format)")
print("\n🎉 All tests passed! API is working correctly.")
print("\nYou can now run the live trader with:")
print(" python3 coinex_live_trader.py --dry-run (for testing)")
print(" python3 coinex_live_trader.py (for live trading)")
return True
except Exception as e:
print(f"\n❌ Test failed: {e}")
# Just print error instead of using log_error which isn't available in this context
print(f"API test failed: {e}")
return False
if __name__ == "__main__":
success = test_api()
sys.exit(0 if success else 1)

11
projects/crypto-watch/.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
node_modules/
.next/
__pycache__/
*.pyc
.env
*.db
*.sqlite
*.log
venv/
dist/
.credentials/

View File

@ -1,65 +1,35 @@
{
"cash": 49536.06609469336,
"cash": 80635.95095568206,
"positions": {
"SEI": {
"qty": 67125.80718783144,
"avg_price": 0.074487,
"ASTER": {
"qty": 7017.051434987018,
"avg_price": 0.71255,
"total_cost": 5000,
"last_buy": "2026-02-10T02:17:32.521805+00:00"
"last_buy": "2026-02-14T06:00:20.221774+00:00"
},
"ICP": {
"qty": 2057.6131687242796,
"avg_price": 2.43,
"USD1": {
"qty": 5004.949895446597,
"avg_price": 0.9990109999999999,
"total_cost": 5000,
"last_buy": "2026-02-10T02:17:32.522284+00:00"
"last_buy": "2026-02-21T18:01:02.458258+00:00"
},
"PUMP": {
"qty": 2496068.691810399,
"avg_price": 0.00200315,
"total_cost": 5000,
"last_buy": "2026-02-10T02:17:32.522670+00:00"
"BCH": {
"qty": 2.5467065990261393,
"avg_price": 490.83000000000004,
"total_cost": 1250.0,
"last_buy": "2026-02-24T02:01:02.060987+00:00"
},
"TRUMP": {
"qty": 1492.5373134328358,
"avg_price": 3.35,
"ATOM": {
"qty": 2415.458937198068,
"avg_price": 2.07,
"total_cost": 5000,
"last_buy": "2026-02-10T02:17:32.524179+00:00"
"last_buy": "2026-02-24T06:00:45.466588+00:00"
},
"VET": {
"qty": 644186.2832126343,
"avg_price": 0.0077617300000000005,
"ONDO": {
"qty": 18217.12628476283,
"avg_price": 0.274467,
"total_cost": 5000,
"last_buy": "2026-02-10T06:00:19.532599+00:00"
},
"ARB": {
"qty": 45447.521746639155,
"avg_price": 0.110017,
"total_cost": 5000,
"last_buy": "2026-02-10T06:00:19.533357+00:00"
},
"ADA": {
"qty": 18835.584185643518,
"avg_price": 0.265455,
"total_cost": 5000,
"last_buy": "2026-02-10T06:00:19.534362+00:00"
},
"AAVE": {
"qty": 45.21613311629589,
"avg_price": 110.58,
"total_cost": 5000,
"last_buy": "2026-02-10T06:00:19.535031+00:00"
},
"NEAR": {
"qty": 4995.004995004995,
"avg_price": 1.001,
"total_cost": 5000,
"last_buy": "2026-02-10T06:00:19.535701+00:00"
},
"BNB": {
"qty": 8.434690193829182,
"avg_price": 592.79,
"total_cost": 5000,
"last_buy": "2026-02-11T10:00:19.285241+00:00"
"last_buy": "2026-02-26T02:01:01.931615+00:00"
}
},
"starting_balance": 100000.0,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

11
projects/feed-hunter/.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
node_modules/
.next/
__pycache__/
*.pyc
.env
*.db
*.sqlite
*.log
venv/
dist/
.credentials/

File diff suppressed because one or more lines are too long

View File

@ -1,3 +1,3 @@
{
"last_check": "2026-02-12T06:14:23.639458+00:00"
"last_check": "2026-02-26T04:20:30.583193+00:00"
}

View File

@ -0,0 +1,26 @@
{
"timestamp": "2026-02-12T06:42:59.251699+00:00",
"total_scraped": 28,
"new_posts": 17,
"money_posts": 3,
"posts": [
{
"text": "Prepare for the greatest bull market of your life.\n\nIt's about to get parabolic.\n\nAre you listening?",
"userName": " Wei Zhao \u8d75\u4f1f\n@antmillionsbot\n\u00b7\n22h",
"timestamp": "2026-02-11T08:15:39.000Z",
"link": "/antmillionsbot/status/2021498351347175876"
},
{
"text": "7 Ways Retirees with $1M+ Can Cut Their Lifetime Tax Bill in Half\n\nAfter 25 years of retirement planning, I've seen $1M+ portfolios pay $400K in lifetime taxes.\n\nAnd I've seen identical $1M+ portfolios pay $180K.\n\nThe difference? These 7 strategies most CPAs never mention:",
"userName": "Kurt Supe, CPA & Retirement Planner\n@KurtSupeCPA\n\u00b7\nFeb 10",
"timestamp": "2026-02-10T18:03:40.000Z",
"link": "/KurtSupeCPA/status/2021283943715074495"
},
{
"text": "These 3 collectibles honor America's upcoming 250th Anniversary. You can now own the Golden USA 250 coin, the Nickel Silver USA 250 coin, and the Independence Day $2 bill.\n\nOrder all 3 together for a discounted price. Each includes their own certificate of authenticity.",
"userName": "Proud Patriots\n@ProudPatriots1",
"timestamp": "",
"link": "/ProudPatriots1/status/2019247139604558250/analytics"
}
]
}

View File

@ -0,0 +1,32 @@
{
"timestamp": "2026-02-12T07:14:59.247408+00:00",
"total_scraped": 29,
"new_posts": 18,
"money_posts": 4,
"posts": [
{
"text": " New GPT crypto price predictions:\n\n$DOGE +0.011% => $0.09115\n\n$ZRO -1.006% => $2.088\n\n$TRX +0.036% => $0.2785\n\n$LINEA +0.831% => $0.00361\n\n$BERA +1.185% => $0.928\n\n$TAO +0.273% => $146.5\n\n$SOL +0.364% => $79.63\n\n$DOT 0.0% => $1.256",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n7h",
"timestamp": "2026-02-12T00:01:07.000Z",
"link": "/OctoBotGPT/status/2021736287892341127"
},
{
"text": "Tired of the same old grocery store? Misfits Market brings you high-quality produce and unique finds that make shopping feel like an adventure. Discover new flavors, support farms and small makers, and get groceries you actually look forward to using.",
"userName": "Misfits Market\n@misfitsmarket",
"timestamp": "",
"link": "/misfitsmarket/status/1993118302571577653/analytics"
},
{
"text": " New GPT crypto price predictions:\n\n$ETH -0.285% => $1945.73\n\n$ZRO +0.086% => $2.329\n\n$UNI 0.0% => $3.492\n\n$BTC -0.116% => $67481.29\n\n$XRP +0.181% => $1.3796\n\n$PENGU +0.116% => $0.006021\n\n$SOL +0.063% => $79.72\n\n$TRUMP +0.094% => $3.195",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n11h",
"timestamp": "2026-02-11T20:00:50.000Z",
"link": "/OctoBotGPT/status/2021675819580481813"
},
{
"text": "Get 30% off when you commit to your routine. Make liver support your 2026 resolution.",
"userName": "Dose\n@dosedaily_co",
"timestamp": "",
"link": "/dosedaily_co/status/2004754861619851497/analytics"
}
]
}

View File

@ -0,0 +1,20 @@
{
"timestamp": "2026-02-12T07:46:59.253689+00:00",
"total_scraped": 24,
"new_posts": 20,
"money_posts": 2,
"posts": [
{
"text": "Prepare for the greatest bull market of your life.\n\nIt's about to get parabolic.\n\nAre you listening?",
"userName": " Wei Zhao \u8d75\u4f1f\n@antmillionsbot\n\u00b7\n23h",
"timestamp": "2026-02-11T08:15:39.000Z",
"link": "/antmillionsbot/status/2021498351347175876"
},
{
"text": "Scoop: AJ Brown might be on the trade market, but the possibility of him reuniting with the \n@Titans\n is ZERO",
"userName": "Jared Stillman\n@JaredStillman\n\u00b7\nFeb 10",
"timestamp": "2026-02-10T21:41:35.000Z",
"link": "/JaredStillman/status/2021338782709199073"
}
]
}

View File

@ -0,0 +1,44 @@
{
"timestamp": "2026-02-12T08:17:59.257165+00:00",
"total_scraped": 24,
"new_posts": 21,
"money_posts": 6,
"posts": [
{
"text": " New GPT crypto price predictions:\n\n$DOGE +0.086% => $0.09309\n\n$HBAR +0.118% => $0.09359\n\n$SUI +0.054% => $0.9344\n\n$SOL 0.0% => $80.82\n\n$BNB +0.024% => $615.6\n\n$ADA +0.379% => $0.2637\n\n$ZAMA -0.214% => $0.01868\n\n$TAO -0.332% => $150.5",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n17m",
"timestamp": "2026-02-12T08:00:51.000Z",
"link": "/OctoBotGPT/status/2021857016734437400"
},
{
"text": "$PENGU -0.207% => $0.00629\n\n$ZRO +0.329% => $2.129\n\n$BTC -0.066% => $67190.23\n\n$SHIB -0.329% => $6.08e-06\n\n$XRP -0.472% => $1.3758\n\n$LINEA -1.366% => $0.00366\n\n$UNI -0.147% => $3.405\n\n$USD1 0.0% => $1.0",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n17m",
"timestamp": "2026-02-12T08:00:51.000Z",
"link": "/OctoBotGPT/status/2021857017850114289"
},
{
"text": "$ETH 0.0% => $1971.06\n\n$TRX +0.072% => $0.2796\n\n$BERA -0.121% => $0.828",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n17m",
"timestamp": "2026-02-12T08:00:52.000Z",
"link": "/OctoBotGPT/status/2021857019150426505"
},
{
"text": "Superior Protein for the Human Body. \n\nDavid delivers 28g of protein, 150 calories, and 0g of sugar, the highest protein-to-calorie ratio of any leading bar on the market. Available in 8 core indulgent flavors.\n\nBuy 4 cartons on our site, and get the 5th free.",
"userName": "David Protein\n@david_protein",
"timestamp": "",
"link": "/david_protein/status/2006088500421222498/analytics"
},
{
"text": "DVD discusses how much money would you be willing to throw at Super Bowl MVP Kenneth Walker in free agency?\n\nYouTube: \nhttps://\nyoutube.com/watch?v=Ht-gR5\nP81vY\n\u2026\n\nX:",
"userName": "102.5 The Game\n@1025TheGame\n\u00b7\n8h",
"timestamp": "2026-02-11T23:26:30.000Z",
"link": "/1025TheGame/status/2021727577119842536"
},
{
"text": "Retail is no longer just about transactions, it's about intelligence.\n\nSupermicro and NVIDIA deliver scalable AI solutions that help retailers boost efficiency, personalize experiences, and drive smarter decisions. See how top brands are transforming their stores with AI.",
"userName": "Supermicro\n@Supermicro",
"timestamp": "",
"link": "/Supermicro/status/2019207951119224998/analytics"
}
]
}

View File

@ -0,0 +1,20 @@
{
"timestamp": "2026-02-12T08:49:59.248855+00:00",
"total_scraped": 26,
"new_posts": 21,
"money_posts": 2,
"posts": [
{
"text": " New GPT crypto price predictions:\n\n$DOGE +0.086% => $0.09309\n\n$HBAR +0.118% => $0.09359\n\n$SUI +0.054% => $0.9344\n\n$SOL 0.0% => $80.82\n\n$BNB +0.024% => $615.6\n\n$ADA +0.379% => $0.2637\n\n$ZAMA -0.214% => $0.01868\n\n$TAO -0.332% => $150.5",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n49m",
"timestamp": "2026-02-12T08:00:51.000Z",
"link": "/OctoBotGPT/status/2021857016734437400"
},
{
"text": "How is the NFL offseason QB market shaping up this year? Who could be on the move?\n\nDiscussing the latest on \n@RStanleyNHL\n & \n@joerexrode\n. 615-737-1025\n\n\nhttps://\nyoutube.com/watch?v=-csGdr\ngQfFM\n\u2026\n\n\nhttps://\nx.com/i/broadcasts/1\nZkKzZYAEdgKv\n\u2026",
"userName": "102.5 The Game\n@1025TheGame\n\u00b7\n19h",
"timestamp": "2026-02-11T13:05:18.000Z",
"link": "/1025TheGame/status/2021571245377024212"
}
]
}

View File

@ -0,0 +1,14 @@
{
"timestamp": "2026-02-12T09:20:12.499541+00:00",
"total_scraped": 27,
"new_posts": 22,
"money_posts": 1,
"posts": [
{
"text": "DVD discusses how much money would you be willing to throw at Super Bowl MVP Kenneth Walker in free agency?\n\nYouTube: \nhttps://\nyoutube.com/watch?v=Ht-gR5\nP81vY\n\u2026\n\nX:",
"userName": "102.5 The Game\n@1025TheGame\n\u00b7\n9h",
"timestamp": "2026-02-11T23:26:30.000Z",
"link": "/1025TheGame/status/2021727577119842536"
}
]
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-12T09:51:59.250130+00:00",
"total_scraped": 34,
"new_posts": 25,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,20 @@
{
"timestamp": "2026-02-12T10:22:09.498736+00:00",
"total_scraped": 31,
"new_posts": 23,
"money_posts": 2,
"posts": [
{
"text": "More than $24 million was wagered on Kalshi as to the question of whether Mark Wahlberg would attend the Super Bowl.",
"userName": "ProFootballTalk\n@ProFootballTalk\n\u00b7\nFeb 10",
"timestamp": "2026-02-10T19:16:47.000Z",
"link": "/ProFootballTalk/status/2021302345561170356"
},
{
"text": "As MCP adoption grows, teams are moving quickly to secure how LLMs connect to tools and data. We put together 7 best practices to help you:\n- Lock down supply chains\n- Enforce least privilege\n- Add human oversight",
"userName": "Wiz\n@wiz_io",
"timestamp": "",
"link": "/wiz_io/status/2009272630956970109/analytics"
}
]
}

View File

@ -0,0 +1,26 @@
{
"timestamp": "2026-02-12T10:53:59.254117+00:00",
"total_scraped": 34,
"new_posts": 22,
"money_posts": 3,
"posts": [
{
"text": "Buy credits, jumpstart your apps, and track usage in real-time \u2014 all from the sleek new Developer Console.",
"userName": "Developers\n@XDevelopers",
"timestamp": "",
"link": "/XDevelopers/status/2011744742636470303/analytics"
},
{
"text": "DVD discusses how much money would you be willing to throw at Super Bowl MVP Kenneth Walker in free agency?\n\nYouTube: \nhttps://\nyoutube.com/watch?v=Ht-gR5\nP81vY\n\u2026\n\nX:",
"userName": "102.5 The Game\n@1025TheGame\n\u00b7\n11h",
"timestamp": "2026-02-11T23:26:30.000Z",
"link": "/1025TheGame/status/2021727577119842536"
},
{
"text": "zosia looking carol up and down like a goddamn snack whilst no other member of the hive was doing all this meanwhile carol\u2019s in an absolute abomination of a fit like on some molecular level she was down BAD. i\u2019m contradicting my own personal show bible here but come onnnn dave",
"userName": "kit\n@lesbian_fleabag\n\u00b7\nFeb 10",
"timestamp": "2026-02-11T01:48:02.000Z",
"link": "/lesbian_fleabag/status/2021400805719597421"
}
]
}

View File

@ -0,0 +1,14 @@
{
"timestamp": "2026-02-12T11:25:59.248519+00:00",
"total_scraped": 29,
"new_posts": 20,
"money_posts": 1,
"posts": [
{
"text": "plurb struggles went private is it because of rhea ",
"userName": "eddie\n@mutantzosia\n\u00b7\n21h",
"timestamp": "2026-02-11T14:15:44.000Z",
"link": "/mutantzosia/status/2021588970048508080"
}
]
}

View File

@ -0,0 +1,14 @@
{
"timestamp": "2026-02-12T11:57:59.252563+00:00",
"total_scraped": 34,
"new_posts": 27,
"money_posts": 1,
"posts": [
{
"text": "DVD discusses how much money would you be willing to throw at Super Bowl MVP Kenneth Walker in free agency?\n\nYouTube: \nhttps://\nyoutube.com/watch?v=Ht-gR5\nP81vY\n\u2026\n\nX:",
"userName": "102.5 The Game\n@1025TheGame\n\u00b7\n12h",
"timestamp": "2026-02-11T23:26:30.000Z",
"link": "/1025TheGame/status/2021727577119842536"
}
]
}

View File

@ -0,0 +1,26 @@
{
"timestamp": "2026-02-12T12:29:59.251528+00:00",
"total_scraped": 34,
"new_posts": 23,
"money_posts": 3,
"posts": [
{
"text": " New GPT crypto price predictions:\n\n$ONDO -1.978% => $0.2528\n\n$BTC +0.012% => $68131.99\n\n$ETH -0.053% => $1988.61\n\n$UNI -0.088% => $3.41\n\n$SUI -0.222% => $0.9465\n\n$AAVE -0.173% => $109.72\n\n$TAO -0.889% => $157.5\n\n$BNB +0.305% => $619.85",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n28m",
"timestamp": "2026-02-12T12:01:14.000Z",
"link": "/OctoBotGPT/status/2021917509629141201"
},
{
"text": "DVD discusses how much money would you be willing to throw at Super Bowl MVP Kenneth Walker in free agency?\n\nYouTube: \nhttps://\nyoutube.com/watch?v=Ht-gR5\nP81vY\n\u2026\n\nX:",
"userName": "102.5 The Game\n@1025TheGame\n\u00b7\n13h",
"timestamp": "2026-02-11T23:26:30.000Z",
"link": "/1025TheGame/status/2021727577119842536"
},
{
"text": "plurb struggles went private is it because of rhea ",
"userName": "eddie\n@mutantzosia\n\u00b7\n22h",
"timestamp": "2026-02-11T14:15:44.000Z",
"link": "/mutantzosia/status/2021588970048508080"
}
]
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-12T13:01:59.260005+00:00",
"total_scraped": 24,
"new_posts": 14,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-12T13:33:59.249324+00:00",
"total_scraped": 13,
"new_posts": 4,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,20 @@
{
"timestamp": "2026-02-12T14:04:59.252523+00:00",
"total_scraped": 15,
"new_posts": 13,
"money_posts": 2,
"posts": [
{
"text": "And still... not enough results.\n\nWhat if learning PLO was as easy as NLH?\n\nThe future of PLO training is here. One platform. Solver, Tracker, Replayer.\n\nWatch how it works ",
"userName": "FlopHero\n@Flophero_GTO",
"timestamp": "",
"link": "/Flophero_GTO/status/2021200006209040605/analytics"
},
{
"text": "Canada/Czechia is two hours away\n\nDarcy Kuemper, Travis Sanheim & Seth Jarvis skated this morning...indicating they will not dress this afternoon.\n\nWe are expecting Jordan Binnington in goal, but will see for sure",
"userName": "Elliotte Friedman\n@FriedgeHNIC\n\u00b7\n17m",
"timestamp": "2026-02-12T13:47:05.000Z",
"link": "/FriedgeHNIC/status/2021944148069392553"
}
]
}

View File

@ -0,0 +1,20 @@
{
"timestamp": "2026-02-12T14:36:22.504074+00:00",
"total_scraped": 17,
"new_posts": 14,
"money_posts": 2,
"posts": [
{
"text": "Canada/Czechia is two hours away\n\nDarcy Kuemper, Travis Sanheim & Seth Jarvis skated this morning...indicating they will not dress this afternoon.\n\nWe are expecting Jordan Binnington in goal, but will see for sure",
"userName": "Elliotte Friedman\n@FriedgeHNIC\n\u00b7\n49m",
"timestamp": "2026-02-12T13:47:05.000Z",
"link": "/FriedgeHNIC/status/2021944148069392553"
},
{
"text": "Don\u2019t be the dad without life insurance.\n\nGet same-day coverage with Ethos life insurance.",
"userName": "Ethos\n@get_Ethos",
"timestamp": "",
"link": "/get_Ethos/status/2013709090699255870/analytics"
}
]
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-12T15:07:59.248126+00:00",
"total_scraped": 8,
"new_posts": 5,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,20 @@
{
"timestamp": "2026-02-12T15:38:04.143788+00:00",
"total_scraped": 18,
"new_posts": 16,
"money_posts": 2,
"posts": [
{
"text": "Fairly obvious at this point that both parties stand to benefit for #Smashville to prioritize trading Jonathan Marchessault once the trade freeze lifts. \n\nLatest for \n@PredlinesNSH",
"userName": "Chad Minton\n@chad_minton\n\u00b7\n6m",
"timestamp": "2026-02-12T15:31:51.000Z",
"link": "/chad_minton/status/2021970513317499050"
},
{
"text": "Meet the AI-powered wearable over 1.2 million users rely on Hume Band continuously scans your biomarkers, catches health issues early, and guides you to smarter choices for a longer life.\n\nClick now to get 40% OFF + free shipping for a limited time only!",
"userName": "HumeHealth\n@myhumehealth",
"timestamp": "",
"link": "/myhumehealth/status/2016463981918208420/analytics"
}
]
}

View File

@ -0,0 +1,50 @@
{
"timestamp": "2026-02-12T16:09:59.254769+00:00",
"total_scraped": 25,
"new_posts": 23,
"money_posts": 7,
"posts": [
{
"text": "$BTC WILL NEVER TRADE BELOW $66,000 \n\nTODAY IS LAST PAIN DAY \n\nTODAY IS START OF THE BULL RUN \n\nEASY ROAD TO 200K BEGINS",
"userName": " Wei Zhao \u8d75\u4f1f\n@antmillionsbot\n\u00b7\n54s",
"timestamp": "2026-02-12T16:09:07.000Z",
"link": "/antmillionsbot/status/2021979890736877794"
},
{
"text": "This template helps you align stakeholders and prove the impact of your work. Learn how to: \n- Position cloud security as a business enabler \n- Report the right KPIs \n- Communicate risks and incidents\n- Make stronger asks\n- Use real-world examples to gain buy-in fast",
"userName": "Wiz\n@wiz_io",
"timestamp": "",
"link": "/wiz_io/status/2019595074062172399/analytics"
},
{
"text": "Psychology in markets.\n\nAfter a big drop, the same pattern happens:\nFear turns into impatience.\n\nA quick bounce and everyone says \u201cthat was the bottom\u201d.\n\nAny pullback and people yell \u201cmanipulation\u201d.\n\nThat emotional flip-flop is why choppy markets kill accounts.\nPeople trade their",
"userName": "Invest with GPT\n@InvestWithGPT\n\u00b7\n8m",
"timestamp": "2026-02-12T16:01:35.000Z",
"link": "/InvestWithGPT/status/2021977997339730399"
},
{
"text": "Fairly obvious at this point that both parties stand to benefit for #Smashville to prioritize trading Jonathan Marchessault once the trade freeze lifts. \n\nLatest for \n@PredlinesNSH",
"userName": "Chad Minton\n@chad_minton\n\u00b7\n38m",
"timestamp": "2026-02-12T15:31:51.000Z",
"link": "/chad_minton/status/2021970513317499050"
},
{
"text": " New GPT crypto price predictions:\n\n$DOGE +0.235% => $0.0936\n\n$LIT -1.642% => $0.731\n\n$XRP +0.145% => $1.3789\n\n$ZEC -0.093% => $235.51\n\n$ZAMA -1.235% => $0.017\n\n$TRX 0.0% => $0.2775\n\n$SOL -0.338% => $79.9\n\n$ADA 0.0% => $0.2628",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n9m",
"timestamp": "2026-02-12T16:01:03.000Z",
"link": "/OctoBotGPT/status/2021977860420825169"
},
{
"text": "Start the new year properly with HexClad\u2019s Winter Sale.\n\nFor a limited time, get 42% OFF The Bundle Up Bundle and reset for how you cook\u2014now and all year long.\n\nNew year. Higher standards.",
"userName": "HexClad\n@hexclad",
"timestamp": "",
"link": "/hexclad/status/2020977758411870473/analytics"
},
{
"text": "Bring the whole family out for a morning of fresh air and fun. The Kidsville Family Walk at \n@conservancynash\n on February 14 features games, crafts, storybook walks, and local bites everyone can enjoy together. \n\nhttp://\nkidsvilleonline.org/familywalk",
"userName": "Nashville Tennessee\n@visitmusiccity\n\u00b7\n31m",
"timestamp": "2026-02-12T15:39:06.000Z",
"link": "/visitmusiccity/status/2021972340054098236"
}
]
}

View File

@ -0,0 +1,14 @@
{
"timestamp": "2026-02-12T16:41:59.259981+00:00",
"total_scraped": 25,
"new_posts": 21,
"money_posts": 1,
"posts": [
{
"text": "Psychology in markets.\n\nAfter a big drop, the same pattern happens:\nFear turns into impatience.\n\nA quick bounce and everyone says \u201cthat was the bottom\u201d.\n\nAny pullback and people yell \u201cmanipulation\u201d.\n\nThat emotional flip-flop is why choppy markets kill accounts.\nPeople trade their",
"userName": "Invest with GPT\n@InvestWithGPT\n\u00b7\n40m",
"timestamp": "2026-02-12T16:01:35.000Z",
"link": "/InvestWithGPT/status/2021977997339730399"
}
]
}

View File

@ -0,0 +1,26 @@
{
"timestamp": "2026-02-12T17:13:59.260335+00:00",
"total_scraped": 27,
"new_posts": 23,
"money_posts": 3,
"posts": [
{
"text": "Guys are staying in college longer now than ever before. \n\nSo how does that impact the quality and amount of talent available in the #NFLDraft?\n\nFormer NFL player & current scout \n@BuckyBrooks\n joined \n@YahooSports\n Daily to explain the trickle up effect from college to the pros ",
"userName": "Caroline Fenton\n@carolinefenton1\n\u00b7\n1m",
"timestamp": "2026-02-12T17:12:04.000Z",
"link": "/carolinefenton1/status/2021995734107927012"
},
{
"text": "Fairly obvious at this point that both parties stand to benefit for #Smashville to prioritize trading Jonathan Marchessault once the trade freeze lifts. \n\nLatest for \n@PredlinesNSH",
"userName": "Chad Minton\n@chad_minton\n\u00b7\n1h",
"timestamp": "2026-02-12T15:31:51.000Z",
"link": "/chad_minton/status/2021970513317499050"
},
{
"text": "VID SOLD! MORE PEE FOR YOU Check it out! \nhttp://\nmanyvids.com/Video/7268655/\nMORE-PEE-FOR-YOU?utm_source=X&utm_medium=1007801525&utm_campaign=Blaster+Video\n\u2026 #MVSales \n@manyvids",
"userName": "Eila Adams\n@flexapeeler\n\u00b7\n9m",
"timestamp": "2026-02-12T17:04:49.000Z",
"link": "/flexapeeler/status/2021993910818497001"
}
]
}

View File

@ -0,0 +1,20 @@
{
"timestamp": "2026-02-12T17:44:59.246789+00:00",
"total_scraped": 14,
"new_posts": 6,
"money_posts": 2,
"posts": [
{
"text": " HURRY Seats for this #DineNashville collaboration between \n@Oak_Steak_Nash\n and #IndacoNashville are going quickly. Experience a thoughtfully crafted five-course menu that brings both kitchens together for one unforgettable night. \n\nhttp://\nvisitmusiccity.com/nashville-even\nts/chef-josh-keeler-oak-steakhouse-chef-josh-begley-indaco-nashville\n\u2026",
"userName": "Nashville Tennessee\n@visitmusiccity\n\u00b7\n15m",
"timestamp": "2026-02-12T17:29:11.000Z",
"link": "/visitmusiccity/status/2022000041775255894"
},
{
"text": "Get same-day coverage with Ethos life insurance.",
"userName": "Ethos\n@get_Ethos",
"timestamp": "",
"link": "/get_Ethos/status/2012271705344065982/analytics"
}
]
}

View File

@ -0,0 +1,20 @@
{
"timestamp": "2026-02-12T18:16:05.251191+00:00",
"total_scraped": 25,
"new_posts": 23,
"money_posts": 2,
"posts": [
{
"text": "we don\u2019t talk enough about how being a lesbian is so isolating irl",
"userName": "ely\n@lesbianaism\n\u00b7\nFeb 11",
"timestamp": "2026-02-11T16:46:05.000Z",
"link": "/lesbianaism/status/2021626806357700642"
},
{
"text": "it's such a struggle, especially if you don't have a community.. i literally have only oomfs and thank god for them",
"userName": "sono io\n@etuchi6\n\u00b7\n11h",
"timestamp": "2026-02-12T06:57:21.000Z",
"link": "/etuchi6/status/2021841037438722455"
}
]
}

View File

@ -0,0 +1,26 @@
{
"timestamp": "2026-02-12T18:46:21.751283+00:00",
"total_scraped": 30,
"new_posts": 28,
"money_posts": 3,
"posts": [
{
"text": "On my new book, I just wanted to thank everyone for the kind compliments so far \n\nAn incredible number of people have downloaded it (maybe because its FREE! lol) \n\nDownload my new 52-page eBook today: \nhttps://\ninfo.hedgeye.com/keith-master-t\nhe-market?twclid=2-9gszj71pw3y0pq3uf352tauj\n\u2026\u2026",
"userName": "Keith McCullough\n@KeithMcCullough",
"timestamp": "",
"link": "/KeithMcCullough/status/1846970778253676959/photo/1"
},
{
"text": "Whether you\u2019re shopping for yourself or someone special, this month\u2019s Nashville FINDS from \n@StyleBlueprint\n are packed with local gems you'll fall in love with!",
"userName": "Nashville Tennessee\n@visitmusiccity\n\u00b7\n21m",
"timestamp": "2026-02-12T18:25:03.000Z",
"link": "/visitmusiccity/status/2022014102562914723"
},
{
"text": "Don\u2019t try to outrun the 1099-DA.\n\nCoinTracker connects your wallets and exchanges, tracks your crypto portfolio, and generates tax-ready reports \u2014 all in one place.",
"userName": "CoinTracker\n@CoinTracker",
"timestamp": "",
"link": "/CoinTracker/status/2021241999706423369/analytics"
}
]
}

View File

@ -0,0 +1,26 @@
{
"timestamp": "2026-02-12T19:17:59.243648+00:00",
"total_scraped": 23,
"new_posts": 21,
"money_posts": 3,
"posts": [
{
"text": "I love the Pump Club, because AI can do a lot, but machines can never replace real human connection.",
"userName": "Arnold Schwarzenegger\n@Schwarzenegger\n\u00b7\n13m",
"timestamp": "2026-02-12T19:04:14.000Z",
"link": "/Schwarzenegger/status/2022023960762949761"
},
{
"text": "they take SO MANY drugs on industry jesus fuck",
"userName": "alla bear zosiing out\n@sublicent\n\u00b7\n25m",
"timestamp": "2026-02-12T18:52:41.000Z",
"link": "/sublicent/status/2022021055578259909"
},
{
"text": "really, as a former junkie - no such thing as taking too many drugs, it's kind of accurate actually (at least to me)",
"userName": "sono io\n@etuchi6\n\u00b7\n12m",
"timestamp": "2026-02-12T19:05:25.000Z",
"link": "/etuchi6/status/2022024260915749271"
}
]
}

View File

@ -0,0 +1,20 @@
{
"timestamp": "2026-02-12T19:49:59.247104+00:00",
"total_scraped": 27,
"new_posts": 26,
"money_posts": 2,
"posts": [
{
"text": "Analogue 3D - Prototype Limited Editions\n\nAvailable now. Shipping in 24-48hrs.\n\nA reimagining of the N64. In 4K resolution.",
"userName": "Analogue\n@analogue",
"timestamp": "",
"link": "/analogue/status/2020890437217628456/photo/1"
},
{
"text": "I love the Pump Club, because AI can do a lot, but machines can never replace real human connection.",
"userName": "Arnold Schwarzenegger\n@Schwarzenegger\n\u00b7\n45m",
"timestamp": "2026-02-12T19:04:14.000Z",
"link": "/Schwarzenegger/status/2022023960762949761"
}
]
}

View File

@ -0,0 +1,38 @@
{
"timestamp": "2026-02-12T20:21:59.257541+00:00",
"total_scraped": 28,
"new_posts": 24,
"money_posts": 5,
"posts": [
{
"text": "https://\nfinance.yahoo.com/news/coinbase-\ntakes-fresh-blows-crypto-184539558.html\n\u2026\n\nStandard Chartered taking the 2026 BTC target from $300k to $150k to $100k tells you everything about where we are psychologically.\n\nNot because they\u2019re \u201cright\u201d, but because this is what happens when price stops rewarding narratives. The same people who",
"userName": "Invest with GPT\n@InvestWithGPT\n\u00b7\n20m",
"timestamp": "2026-02-12T20:02:00.000Z",
"link": "/InvestWithGPT/status/2022038497457025138"
},
{
"text": " New GPT crypto price predictions:\n\n$SHIB +0.332% => $6.02e-06\n\n$ZRO -0.404% => $1.979\n\n$AAVE +0.099% => $110.87\n\n$ADA +0.381% => $0.2626\n\n$SOL -0.168% => $77.55\n\n$BNB -0.32% => $606.5\n\n$DOGE 0.0% => $0.0917\n\n$ONDO -0.608% => $0.2468",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n21m",
"timestamp": "2026-02-12T20:00:53.000Z",
"link": "/OctoBotGPT/status/2022038220171550838"
},
{
"text": "$ASTER +0.828% => $0.725\n\n$ZEC -0.095% => $230.77\n\n$BTC 0.0% => $65823.56\n\n$XRP -0.081% => $1.3647\n\n$ENA 0.0% => $0.1162\n\n$TRX +0.036% => $0.2778\n\n$USD1 -0.01% => $1.0\n\n$BERA +0.552% => $0.725",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n21m",
"timestamp": "2026-02-12T20:00:54.000Z",
"link": "/OctoBotGPT/status/2022038221262115294"
},
{
"text": "$SUI 0.0% => $0.9128\n\n$PENGU +0.321% => $0.006235\n\n$ESP -0.419% => $0.07155\n\n$UNI -0.031% => $3.223\n\n$ETH +0.55% => $1936.28",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n21m",
"timestamp": "2026-02-12T20:00:54.000Z",
"link": "/OctoBotGPT/status/2022038222381928504"
},
{
"text": "$COSM Needs to be on your radar ASAP.\n\n\u2022 Under $15M market cap\n\u2022 Zacks initiated with $4.50 valuation\n\u2022 Gross margins expanding \u2014 record 15.21%\n\nAdd $COSM to your watchlist ASAP.\n\nClick for more details\n\nDisclaimer: Do your own research. Not financial advice, paid ad.",
"userName": "StockVerse\n@StockVerseAI",
"timestamp": "",
"link": "/StockVerseAI/status/2021832612529197343/analytics"
}
]
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-12T20:52:59.283620+00:00",
"total_scraped": 30,
"new_posts": 26,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,14 @@
{
"timestamp": "2026-02-12T21:23:59.255623+00:00",
"total_scraped": 27,
"new_posts": 22,
"money_posts": 1,
"posts": [
{
"text": "Watch out legacy planning tools, \n@altruist\n's Hazel tax planning model is pretty amazing. I just used it to mock up a Roth conversion plan using \n@RightCapitalHQ\n's report outputs. It did a fantastic job of solving for my exact question, which was...",
"userName": "Trent Grzegorczyk\n@grzczyk\n\u00b7\n10m",
"timestamp": "2026-02-12T21:13:12.000Z",
"link": "/grzczyk/status/2022056415385493575"
}
]
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-12T21:55:59.255581+00:00",
"total_scraped": 16,
"new_posts": 14,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-12T22:27:59.255750+00:00",
"total_scraped": 21,
"new_posts": 18,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,14 @@
{
"timestamp": "2026-02-12T22:59:59.247888+00:00",
"total_scraped": 15,
"new_posts": 13,
"money_posts": 1,
"posts": [
{
"text": "Just an absolute passing clinic and Brock Nelson finishes it for goal No. 2 of the night #WinterOlympics",
"userName": "USA Hockey\n@usahockey\n\u00b7\n57m",
"timestamp": "2026-02-12T22:02:39.000Z",
"link": "/usahockey/status/2022068862460866863"
}
]
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-12T23:31:59.242039+00:00",
"total_scraped": 15,
"new_posts": 12,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-13T00:03:59.248877+00:00",
"total_scraped": 1,
"new_posts": 1,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-13T00:35:59.247627+00:00",
"total_scraped": 0,
"new_posts": 0,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-13T01:07:59.258649+00:00",
"total_scraped": 1,
"new_posts": 1,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-13T01:38:59.251999+00:00",
"total_scraped": 2,
"new_posts": 2,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-13T02:10:59.256065+00:00",
"total_scraped": 2,
"new_posts": 2,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-13T02:42:59.253183+00:00",
"total_scraped": 4,
"new_posts": 4,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,14 @@
{
"timestamp": "2026-02-13T03:14:59.256758+00:00",
"total_scraped": 3,
"new_posts": 3,
"money_posts": 1,
"posts": [
{
"text": "Remember -> bull markets can make you rich\u2026 but bear markets can make you WEALTHY \n\nThe moves you make in 2026 can set you up for a very long time.",
"userName": "Jolly Green Investor \n@jollygreenmoney\n\u00b7\n19m",
"timestamp": "2026-02-13T02:55:32.000Z",
"link": "/jollygreenmoney/status/2022142569938137259"
}
]
}

View File

@ -0,0 +1,14 @@
{
"timestamp": "2026-02-13T03:45:59.244427+00:00",
"total_scraped": 3,
"new_posts": 3,
"money_posts": 1,
"posts": [
{
"text": "Bittensor just became even more decentralized \n\nimo this makes $TAO even more attractive for institutional and high net worth individuals.\n\n\n@const_reborn\n helped create something truly incredible.\n\nNow it can fully blossom into a global phenomenon.\n\nAll roads lead to $TAO",
"userName": "Jolly Green Investor \n@jollygreenmoney\n\u00b7\n9m",
"timestamp": "2026-02-13T03:36:54.000Z",
"link": "/jollygreenmoney/status/2022152976765526343"
}
]
}

View File

@ -0,0 +1,26 @@
{
"timestamp": "2026-02-13T04:17:59.254931+00:00",
"total_scraped": 6,
"new_posts": 5,
"money_posts": 3,
"posts": [
{
"text": " New GPT crypto price predictions:\n\n$SOL -0.356% => $78.75\n\n$TAO -0.128% => $155.7\n\n$TRX +0.036% => $0.2791\n\n$ASTER -0.563% => $0.711\n\n$DOGE -0.011% => $0.09293\n\n$BNB +0.026% => $608.85\n\n$XRP +0.146% => $1.3665\n\n$BTC +0.318% => $66788.87",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n16m",
"timestamp": "2026-02-13T04:01:02.000Z",
"link": "/OctoBotGPT/status/2022159051400851825"
},
{
"text": "$SUI +0.262% => $0.9175\n\n$AAVE +0.08% => $112.33\n\n$SHIB +0.166% => $6.01e-06\n\n$ZEC -0.618% => $229.85\n\n$USD1 +0.01% => $1.0002\n\n$ADA +0.076% => $0.2632\n\n$ETH 0.0% => $1954.19\n\n$PENGU 0.0% => $0.00621",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n16m",
"timestamp": "2026-02-13T04:01:02.000Z",
"link": "/OctoBotGPT/status/2022159052764013001"
},
{
"text": "Here is a great example of why the Bittensor ecosystem will become a phenomenon and $TAO a top 10 global asset\n\nSubnet 93 - Bitcast \n\nRe-imagining how brands engage creators for marketing purposes with verified engagement and quantifiable attention.\n\nIn an era where creators",
"userName": "Jolly Green Investor \n@jollygreenmoney\n\u00b7\n25m",
"timestamp": "2026-02-13T03:52:09.000Z",
"link": "/jollygreenmoney/status/2022156814423408716"
}
]
}

View File

@ -0,0 +1,14 @@
{
"timestamp": "2026-02-13T04:49:59.239916+00:00",
"total_scraped": 1,
"new_posts": 1,
"money_posts": 1,
"posts": [
{
"text": " New GPT crypto price predictions:\n\n$SOL -0.356% => $78.75\n\n$TAO -0.128% => $155.7\n\n$TRX +0.036% => $0.2791\n\n$ASTER -0.563% => $0.711\n\n$DOGE -0.011% => $0.09293\n\n$BNB +0.026% => $608.85\n\n$XRP +0.146% => $1.3665\n\n$BTC +0.318% => $66788.87",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n48m",
"timestamp": "2026-02-13T04:01:02.000Z",
"link": "/OctoBotGPT/status/2022159051400851825"
}
]
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-13T05:20:59.247448+00:00",
"total_scraped": 0,
"new_posts": 0,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-13T05:51:59.252868+00:00",
"total_scraped": 0,
"new_posts": 0,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-13T06:22:59.239975+00:00",
"total_scraped": 0,
"new_posts": 0,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-13T06:54:59.251572+00:00",
"total_scraped": 5,
"new_posts": 5,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-13T07:25:59.255052+00:00",
"total_scraped": 2,
"new_posts": 1,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-13T07:57:59.251711+00:00",
"total_scraped": 0,
"new_posts": 0,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,26 @@
{
"timestamp": "2026-02-13T08:28:13.004291+00:00",
"total_scraped": 3,
"new_posts": 3,
"money_posts": 3,
"posts": [
{
"text": " New GPT crypto price predictions:\n\n$UNI +0.06% => $3.306\n\n$PAXG -0.166% => $4974.32\n\n$DOGE -0.011% => $0.09306\n\n$SUI +0.294% => $0.9187\n\n$ADA 0.0% => $0.2622\n\n$ESP -0.859% => $0.06288\n\n$SHIB +0.331% => $6.04e-06\n\n$ASTER +0.417% => $0.719",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n27m",
"timestamp": "2026-02-13T08:01:09.000Z",
"link": "/OctoBotGPT/status/2022219477614498186"
},
{
"text": "$TAO +0.835% => $155.6\n\n$ZAMA -0.115% => $0.01734\n\n$JUP -0.283% => $0.1415\n\n$BNB +0.02% => $598.23\n\n$BTC +0.457% => $66541.97\n\n$XRP +0.784% => $1.3648\n\n$ETH 0.0% => $1936.2\n\n$AXS -0.755% => $1.325",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n27m",
"timestamp": "2026-02-13T08:01:09.000Z",
"link": "/OctoBotGPT/status/2022219478717567308"
},
{
"text": "$SOL -0.19% => $78.85\n\n$USD1 0.0% => $1.0001\n\n$AAVE -0.072% => $110.75\n\n$TRX +0.251% => $0.2789",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n27m",
"timestamp": "2026-02-13T08:01:09.000Z",
"link": "/OctoBotGPT/status/2022219480214929739"
}
]
}

View File

@ -0,0 +1,14 @@
{
"timestamp": "2026-02-13T08:59:29.257681+00:00",
"total_scraped": 1,
"new_posts": 1,
"money_posts": 1,
"posts": [
{
"text": "Do Not buy a house.\n\nUnless you are a billionaire.\n\nRent for now.\n\nWait for 6 months for a 2008 type market crash to buy your first house.\n\nUnderstand?",
"userName": " Wei Zhao \u8d75\u4f1f\n@antmillionsbot\n\u00b7\n31m",
"timestamp": "2026-02-13T08:28:18.000Z",
"link": "/antmillionsbot/status/2022226309594960087"
}
]
}

View File

@ -0,0 +1,14 @@
{
"timestamp": "2026-02-13T09:30:06.995382+00:00",
"total_scraped": 1,
"new_posts": 1,
"money_posts": 1,
"posts": [
{
"text": "Do Not buy a house.\n\nUnless you are a billionaire.\n\nRent for now.\n\nWait for 6 months for a 2008 type market crash to buy your first house.\n\nUnderstand?",
"userName": " Wei Zhao \u8d75\u4f1f\n@antmillionsbot\n\u00b7\n1h",
"timestamp": "2026-02-13T08:28:18.000Z",
"link": "/antmillionsbot/status/2022226309594960087"
}
]
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-13T10:00:08.247635+00:00",
"total_scraped": 2,
"new_posts": 2,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-13T10:31:59.247940+00:00",
"total_scraped": 1,
"new_posts": 1,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,14 @@
{
"timestamp": "2026-02-13T11:03:59.253671+00:00",
"total_scraped": 6,
"new_posts": 6,
"money_posts": 1,
"posts": [
{
"text": "Sleep in perfect harmony. Dual-zone technology keeps each partner at their ideal temperature, ending thermostat battles and helping you both rest better together.",
"userName": "Eight Sleep\n@eightsleep",
"timestamp": "",
"link": "/eightsleep/status/2018855734122103269/analytics"
}
]
}

View File

@ -0,0 +1,7 @@
{
"timestamp": "2026-02-13T11:34:33.248509+00:00",
"total_scraped": 7,
"new_posts": 7,
"money_posts": 0,
"posts": []
}

View File

@ -0,0 +1,20 @@
{
"timestamp": "2026-02-13T12:06:29.256129+00:00",
"total_scraped": 9,
"new_posts": 7,
"money_posts": 2,
"posts": [
{
"text": " New GPT crypto price predictions:\n\n$BTC -0.048% => $67095.0\n\n$XRP 0.0% => $1.3669\n\n$SOL +0.273% => $80.48\n\n$ADA +0.265% => $0.2643\n\n$ZRO -0.216% => $1.855\n\n$JUP +0.693% => $0.1442\n\n$TAO +0.762% => $157.4\n\n$BERA -0.935% => $0.642",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n5m",
"timestamp": "2026-02-13T12:00:55.000Z",
"link": "/OctoBotGPT/status/2022279816687333839"
},
{
"text": "$DOGE +0.032% => $0.09388\n\n$TRX +0.108% => $0.2775\n\n$ESP -0.77% => $0.05972\n\n$AAVE 0.0% => $112.35\n\n$ETH +0.01% => $1960.19\n\n$SHIB -0.493% => $6.08e-06\n\n$OM -0.868% => $0.0576\n\n$PENGU -0.464% => $0.00625",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n5m",
"timestamp": "2026-02-13T12:00:55.000Z",
"link": "/OctoBotGPT/status/2022279817895305325"
}
]
}

View File

@ -0,0 +1,26 @@
{
"timestamp": "2026-02-13T12:37:59.256509+00:00",
"total_scraped": 12,
"new_posts": 9,
"money_posts": 3,
"posts": [
{
"text": "Forsberg definitely getting more of a look today, but still a shockingly minor role for Sweden.",
"userName": "Alex Daugherty\n@AlexDaugherty1\n\u00b7\n12m",
"timestamp": "2026-02-13T12:25:39.000Z",
"link": "/AlexDaugherty1/status/2022286041072161152"
},
{
"text": "An assist for Predators' forward Erik Haula on Armia's shorthanded goal. His first Olympic point for Finland.",
"userName": "Alex Daugherty\n@AlexDaugherty1\n\u00b7\n7m",
"timestamp": "2026-02-13T12:30:53.000Z",
"link": "/AlexDaugherty1/status/2022287358868005307"
},
{
"text": "Erik Haula was 1-on-3 along the boards but impressively managed to get a pass out to Joel Armia for a shorthanded goal - and a 3-1 Finland lead over Sweden in the second stanza. #Preds",
"userName": "Brooks Bratten\n@brooksbratten\n\u00b7\n3m",
"timestamp": "2026-02-13T12:34:11.000Z",
"link": "/brooksbratten/status/2022288190598414647"
}
]
}

View File

@ -0,0 +1,26 @@
{
"timestamp": "2026-02-13T13:09:59.257790+00:00",
"total_scraped": 11,
"new_posts": 9,
"money_posts": 3,
"posts": [
{
"text": "Institutions are buying.\nClarity Act is coming.\nStablecoin supply at ATH.\nCrypto laws turning favorable.\nETF flows still strong.\nSentiment at rock bottom.\nFear index at 5.\nEveryone calling for 45k BTC.\nNo one holding alts.\n\nEveryone knows what about to happen next...",
"userName": " Wei Zhao \u8d75\u4f1f\n@antmillionsbot\n\u00b7\n28m",
"timestamp": "2026-02-13T12:42:00.000Z",
"link": "/antmillionsbot/status/2022290155554373777"
},
{
"text": "An assist for Predators' forward Erik Haula on Armia's shorthanded goal. His first Olympic point for Finland.",
"userName": "Alex Daugherty\n@AlexDaugherty1\n\u00b7\n39m",
"timestamp": "2026-02-13T12:30:53.000Z",
"link": "/AlexDaugherty1/status/2022287358868005307"
},
{
"text": "Use advanced tools, and AI-powered insights to make informed investing decisions. Learn why a stock is moving. Invest for the long haul.",
"userName": "Public\n@public",
"timestamp": "",
"link": "/public/status/2018828442566033687/analytics"
}
]
}

View File

@ -0,0 +1,14 @@
{
"timestamp": "2026-02-13T13:40:28.257119+00:00",
"total_scraped": 12,
"new_posts": 12,
"money_posts": 1,
"posts": [
{
"text": "An assist for Predators' forward Erik Haula on Armia's shorthanded goal. His first Olympic point for Finland.",
"userName": "Alex Daugherty\n@AlexDaugherty1\n\u00b7\n1h",
"timestamp": "2026-02-13T12:30:53.000Z",
"link": "/AlexDaugherty1/status/2022287358868005307"
}
]
}

View File

@ -0,0 +1,20 @@
{
"timestamp": "2026-02-13T14:12:23.993259+00:00",
"total_scraped": 19,
"new_posts": 15,
"money_posts": 2,
"posts": [
{
"text": "Juuse Saros makes 34 saves, Erik Haula records a shorthanded assist and Finland beats Sweden by a 4-1 final in Milan. Filip Forsberg finishes with two shots in 9:31 of ice time for the Swedes. #Preds",
"userName": "Brooks Bratten\n@brooksbratten\n\u00b7\n21m",
"timestamp": "2026-02-13T13:50:48.000Z",
"link": "/brooksbratten/status/2022307471683949007"
},
{
"text": "Secure your spot to experience #BastionNashville and \n@TwoTenJack\n come together for a unique culinary experience. This collaborative dinner is part of #DineNashville on February 16th. Mark your calendars, and grab your tickets, friends! \n\nhttp://\nvisitmusiccity.com/nashville-even\nts/bastion-two-ten-jack/d32ca26e079e11f1b563\n\u2026",
"userName": "Nashville Tennessee\n@visitmusiccity\n\u00b7\n11m",
"timestamp": "2026-02-13T14:00:43.000Z",
"link": "/visitmusiccity/status/2022309965952647216"
}
]
}

View File

@ -0,0 +1,14 @@
{
"timestamp": "2026-02-13T14:42:33.004541+00:00",
"total_scraped": 10,
"new_posts": 10,
"money_posts": 1,
"posts": [
{
"text": "An assist for Predators' forward Erik Haula on Armia's shorthanded goal. His first Olympic point for Finland.",
"userName": "Alex Daugherty\n@AlexDaugherty1\n\u00b7\n2h",
"timestamp": "2026-02-13T12:30:53.000Z",
"link": "/AlexDaugherty1/status/2022287358868005307"
}
]
}

View File

@ -0,0 +1,20 @@
{
"timestamp": "2026-02-13T15:13:59.257995+00:00",
"total_scraped": 12,
"new_posts": 8,
"money_posts": 2,
"posts": [
{
"text": "We just released a new kind of youtube shorts made with our AI agent team, what do you think about it?\n\nDo you want to know more about our stack?",
"userName": "Paul\n@PaulOctoBot\n\u00b7\n22m",
"timestamp": "2026-02-13T14:51:12.000Z",
"link": "/PaulOctoBot/status/2022322670239404230"
},
{
"text": "Art lovers, this one\u2019s for you! The Impressionist Revolution: Monet to Matisse opens Feb. 26 at the \n@FristArtMuseum\n with works that helped define a movement. Make your plans to experience it in person. ",
"userName": "Nashville Tennessee\n@visitmusiccity\n\u00b7\n13m",
"timestamp": "2026-02-13T15:00:49.000Z",
"link": "/visitmusiccity/status/2022325093678862357"
}
]
}

View File

@ -0,0 +1,20 @@
{
"timestamp": "2026-02-13T15:44:32.752265+00:00",
"total_scraped": 15,
"new_posts": 12,
"money_posts": 2,
"posts": [
{
"text": "Music City side quests \n\nWe're excited to announce ROR as a member of music duo Mac N Cheeze, a music-first kids\u2019 project dreamed up by two longtime friends, Ryan O\u2019Reilly and Kelly James!",
"userName": "Nashville Predators\n@PredsNHL\n\u00b7\n3m",
"timestamp": "2026-02-13T15:40:59.000Z",
"link": "/PredsNHL/status/2022335199196094592"
},
{
"text": "An assist for Predators' forward Erik Haula on Armia's shorthanded goal. His first Olympic point for Finland.",
"userName": "Alex Daugherty\n@AlexDaugherty1\n\u00b7\n3h",
"timestamp": "2026-02-13T12:30:53.000Z",
"link": "/AlexDaugherty1/status/2022287358868005307"
}
]
}

View File

@ -0,0 +1,20 @@
{
"timestamp": "2026-02-13T16:16:21.000499+00:00",
"total_scraped": 7,
"new_posts": 5,
"money_posts": 2,
"posts": [
{
"text": " New GPT crypto price predictions:\n\n$BTC -0.358% => $68422.5\n\n$XRP 0.0% => $1.4034\n\n$ZRO +0.052% => $1.935\n\n$PAXG 0.0% => $4990.69\n\n$SUI -1.06% => $0.9437\n\n$SHIB -0.32% => $6.25e-06\n\n$ZEC 0.0% => $245.56\n\n$ADA -0.074% => $0.2689",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n15m",
"timestamp": "2026-02-13T16:01:06.000Z",
"link": "/OctoBotGPT/status/2022340260592562442"
},
{
"text": "$OM +0.945% => $0.0635\n\n$UNI +0.117% => $3.41\n\n$ESP -0.915% => $0.059\n\n$ETH +0.146% => $2036.15\n\n$BNB -0.579% => $606.1\n\n$USD1 +0.02% => $1.0\n\n$AAVE +0.307% => $117.25\n\n$SOL +1.575% => $84.45",
"userName": "OctoBot - GPT crypto price predictions\n@OctoBotGPT\n\u00b7\n15m",
"timestamp": "2026-02-13T16:01:06.000Z",
"link": "/OctoBotGPT/status/2022340261867573725"
}
]
}

View File

@ -0,0 +1,20 @@
{
"timestamp": "2026-02-13T16:47:59.249819+00:00",
"total_scraped": 15,
"new_posts": 12,
"money_posts": 2,
"posts": [
{
"text": "An assist for Predators' forward Erik Haula on Armia's shorthanded goal. His first Olympic point for Finland.",
"userName": "Alex Daugherty\n@AlexDaugherty1\n\u00b7\n4h",
"timestamp": "2026-02-13T12:30:53.000Z",
"link": "/AlexDaugherty1/status/2022287358868005307"
},
{
"text": "Juuse Saros vs Sweden:\n\n35 shots against\n34 saves\n15 shorthanded saves\n.971 SV%\n\nHis first win at the Olympics.",
"userName": "StatMuse\n@statmuse\n\u00b7\n3h",
"timestamp": "2026-02-13T13:41:35.000Z",
"link": "/statmuse/status/2022305152376459328"
}
]
}

View File

@ -0,0 +1,20 @@
{
"timestamp": "2026-02-13T17:18:52.000054+00:00",
"total_scraped": 10,
"new_posts": 8,
"money_posts": 2,
"posts": [
{
"text": "EVERYONE calling for $45K.\nEVERYONE waiting for the dump.\nEVERYONE positioned bearish.\n\nAnd what if\u2026\n\nBITCOIN RIPS STRAIGHT TO $100,000.\n\nWhat happens if we print a new ATH in the next 60 days?\n\nGold pumping.\nSilver pumping.\nStocks at highs.\n\nWhy would crypto sit out?\nCrypto is",
"userName": " Wei Zhao \u8d75\u4f1f\n@antmillionsbot\n\u00b7\n25m",
"timestamp": "2026-02-13T16:53:20.000Z",
"link": "/antmillionsbot/status/2022353407760052721"
},
{
"text": "Looking for the perfect gift, or just a little retail therapy? You\u2019re in the right city! Explore Nashville\u2019s local shops and find something special this February. \n\nhttp://\nvisitmusiccity.com/things-to-do-i\nn-nashville/shopping-nashville\n\u2026",
"userName": "Nashville Tennessee\n@visitmusiccity\n\u00b7\n18m",
"timestamp": "2026-02-13T17:00:51.000Z",
"link": "/visitmusiccity/status/2022355301081432205"
}
]
}

View File

@ -0,0 +1,14 @@
{
"timestamp": "2026-02-13T17:50:42.752801+00:00",
"total_scraped": 14,
"new_posts": 13,
"money_posts": 1,
"posts": [
{
"text": "Juuse Saros vs Sweden:\n\n35 shots against\n34 saves\n15 shorthanded saves\n.971 SV%\n\nHis first win at the Olympics.",
"userName": "StatMuse\n@statmuse\n\u00b7\n4h",
"timestamp": "2026-02-13T13:41:35.000Z",
"link": "/statmuse/status/2022305152376459328"
}
]
}

Some files were not shown because too many files have changed in this diff Show More