99 lines
3.3 KiB
Python
Executable File
99 lines
3.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Daily runner for Market Watch - scans, trades (as Case), snapshots, alerts."""
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
import requests
|
|
from datetime import datetime
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
import game_engine
|
|
from scanner import run_scan
|
|
from trader import run_trading_logic
|
|
|
|
CREDS_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", ".credentials", "telegram-bot.env")
|
|
CHAT_ID = "6443752046"
|
|
|
|
|
|
def load_telegram_token():
|
|
if os.path.exists(CREDS_FILE):
|
|
with open(CREDS_FILE) as f:
|
|
for line in f:
|
|
if line.startswith("TELEGRAM_BOT_TOKEN="):
|
|
return line.strip().split("=", 1)[1]
|
|
return os.environ.get("TELEGRAM_BOT_TOKEN")
|
|
|
|
|
|
def send_telegram(message, token):
|
|
if not token:
|
|
return
|
|
try:
|
|
url = f"https://api.telegram.org/bot{token}/sendMessage"
|
|
requests.post(url, json={"chat_id": CHAT_ID, "text": message, "parse_mode": "HTML"}, timeout=10)
|
|
except Exception as e:
|
|
print(f"Telegram error: {e}")
|
|
|
|
|
|
def main():
|
|
print(f"📊 Market Watch Daily Run — {datetime.now().strftime('%Y-%m-%d %H:%M')}")
|
|
|
|
token = load_telegram_token()
|
|
game_id = game_engine.ensure_default_game()
|
|
game = game_engine.get_game(game_id)
|
|
|
|
# 1. Run GARP scan
|
|
print("\n[1/3] Running GARP scan...")
|
|
candidates = run_scan() # returns list of candidates directly
|
|
print(f" Found {len(candidates)} candidates")
|
|
|
|
# 2. Run trading logic for Case
|
|
print("\n[2/3] Running trading logic for Case...")
|
|
result = run_trading_logic(game_id, "case", candidates)
|
|
|
|
# 3. Snapshots for all players
|
|
print("\n[3/3] Taking snapshots...")
|
|
for username in game["players"]:
|
|
snap = game_engine.daily_snapshot(game_id, username)
|
|
if snap:
|
|
print(f" {username}: ${snap['total_value']:,.2f} ({snap['pnl_pct']:+.2f}%)")
|
|
|
|
# Telegram summary
|
|
p = game_engine.get_portfolio(game_id, "case")
|
|
pnl_emoji = "📈" if p["total_pnl"] >= 0 else "📉"
|
|
|
|
summary = f"📊 <b>Market Watch Daily</b>\n"
|
|
summary += f"{pnl_emoji} Portfolio: ${p['total_value']:,.2f} ({p['pnl_pct']:+.2f}%)\n"
|
|
summary += f"💰 Cash: ${p['cash']:,.2f} | Positions: {p['num_positions']}\n"
|
|
|
|
num_trades = len(result.get("sells", [])) + len(result.get("buys", []))
|
|
if num_trades:
|
|
summary += f"\n<b>{num_trades} trades executed</b>\n"
|
|
for s in result.get("sells", []):
|
|
summary += f"🔴 SELL {s['ticker']} — {s['reason'][:50]}\n"
|
|
for b in result.get("buys", []):
|
|
summary += f"🟢 BUY {b['ticker']} — {b['reason'][:50]}\n"
|
|
else:
|
|
summary += "\nNo trades today."
|
|
|
|
if candidates:
|
|
top5 = ", ".join(c["ticker"] for c in candidates[:5])
|
|
summary += f"\n🔍 Top picks: {top5}"
|
|
|
|
# Leaderboard
|
|
board = game_engine.get_leaderboard(game_id)
|
|
if len(board) > 1:
|
|
summary += "\n\n<b>Leaderboard:</b>\n"
|
|
medals = ["🥇", "🥈", "🥉"]
|
|
for i, entry in enumerate(board[:5]):
|
|
medal = medals[i] if i < 3 else f"#{i+1}"
|
|
summary += f"{medal} {entry['username']}: {entry['pnl_pct']:+.2f}%\n"
|
|
|
|
send_telegram(summary, token)
|
|
print("\n✅ Daily run complete")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|