Files
gfil-blog/deploy_scripts/daily_market_update.py

171 lines
7.2 KiB
Python
Raw Normal View History

2026-06-28 17:19:47 +00:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Daily Market Update fetches live prices, generates SEO page, uploads to server.
Usage:
python daily_market_update.py # fetch + generate
python daily_market_update.py --no-fetch # demo data
python daily_market_update.py --upload # generate + upload to server
python daily_market_update.py --schedule # print Windows Task Scheduler instructions
"""
import os, sys, io, json, argparse, urllib.request, subprocess
from datetime import datetime
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
OUTPUT_DIR = os.path.join(BASE_DIR, 'output')
SITE_URL = 'https://blog.quant-view.xyz'
SYMBOLS = [
('XAUUSD', 'Gold', 'XAU/USD'),
('EURUSD', 'EUR/USD', 'EUR/USD'),
('GBPUSD', 'GBP/USD', 'GBP/USD'),
('BTCUSD', 'Bitcoin', 'BTC/USD'),
('WTI', 'Crude Oil', 'WTI/CL'),
]
def fetch_prices():
prices = {}
# Forex via exchangerate-api
try:
req = urllib.request.Request('https://open.er-api.com/v6/latest/USD',
headers={'User-Agent': 'Mozilla/5.0'})
data = json.loads(urllib.request.urlopen(req, timeout=10).read())
r = data['rates']
prices['EURUSD'] = 1 / r['EUR']
prices['GBPUSD'] = 1 / r['GBP']
except: pass
# BTC via CoinGecko
try:
req = urllib.request.Request('https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd',
headers={'User-Agent': 'Mozilla/5.0'})
data = json.loads(urllib.request.urlopen(req, timeout=10).read())
prices['BTCUSD'] = data['bitcoin']['usd']
except: pass
# Gold via GoldAPI (free tier)
gold_key = os.environ.get('GOLD_API_KEY', '')
if gold_key:
try:
req = urllib.request.Request('https://www.goldapi.io/api/XAU/USD',
headers={'x-access-token': gold_key, 'User-Agent': 'Mozilla/5.0'})
data = json.loads(urllib.request.urlopen(req, timeout=10).read())
prices['XAUUSD'] = data.get('price')
except: pass
return prices
def generate_html(prices):
now = datetime.utcnow().strftime('%Y-%m-%d %H:%M UTC')
rows = ''
for key, label, pair in SYMBOLS:
p = prices.get(key)
price_str = f'${p:,.2f}' if p else '<span style="color:#666;">unavailable</span>'
rows += f'<tr><td style="padding:10px 12px;border-bottom:1px solid #222;">{label}</td>'
rows += f'<td style="padding:10px 12px;border-bottom:1px solid #222;text-align:right;font-family:monospace;">{price_str}</td>'
rows += f'<td style="padding:10px 12px;border-bottom:1px solid #222;text-align:center;">—</td></tr>\n'
html = f'''<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Daily Market Update {now[:10]} Gold, Forex, Bitcoin | GFIL Trading Insights</title>
<meta name="description" content="Live market prices for XAUUSD, EUR/USD, GBP/USD, Bitcoin and WTI Crude Oil. Updated {now}.">
<meta name="robots" content="index, follow">
<link rel="canonical" href="{SITE_URL}/market-update.html">
<style>
*{{margin:0;padding:0;box-sizing:border-box;}}
body{{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;background:#0a0a0f;color:#e0e0e0;max-width:800px;margin:0 auto;padding:20px;}}
h1{{color:#ffcc00;border-bottom:1px solid #333;padding-bottom:10px;font-size:24px;}}
.subtitle{{color:#888;font-size:13px;margin:10px 0 20px;}}
table{{width:100%;border-collapse:collapse;}}
th{{text-align:left;padding:10px 12px;border-bottom:2px solid #ffcc00;color:#ffcc00;font-size:12px;text-transform:uppercase;}}
td{{font-size:14px;}}
tr:hover{{background:#0f0f15;}}
.note{{color:#666;font-size:12px;margin-top:15px;}}
.cta{{background:#111;border:1px solid #333;border-radius:8px;padding:20px;margin:25px 0;text-align:center;}}
.cta a{{color:#ffcc00;font-weight:bold;text-decoration:none;}}
.footer{{margin-top:30px;padding-top:15px;border-top:1px solid #333;text-align:center;color:#555;font-size:12px;}}
.footer a{{color:#ffcc00;text-decoration:none;}}
</style></head>
<body>
<h1>Daily Market Update</h1>
<p class="subtitle">{now}</p>
<table><thead><tr><th>Instrument</th><th style="text-align:right;">Price</th><th style="text-align:center;">Signal</th></tr></thead>
<tbody>{rows}</tbody></table>
<p class="note">Data from public APIs. For institutional-grade real-time data visit <a href="http://gold-node.xyz/" style="color:#ffcc00;">GFIL BOSS PANEL</a>.</p>
<div class="cta"><p><a href="http://gold-node.xyz/">Access GFIL Terminal </a> | <a href="https://t.me/GFIL_Trading">Telegram</a> | <a href="/">Blog Home</a></p></div>
<div class="footer"><p>&copy; {datetime.now().year} GFIL Trading Insights | <a href="/">Home</a> | <a href="https://t.me/GFIL_Trading">Telegram</a></p></div>
</body></html>'''
os.makedirs(OUTPUT_DIR, exist_ok=True)
path = os.path.join(OUTPUT_DIR, 'market-update.html')
with open(path, 'w', encoding='utf-8') as f:
f.write(html)
print(f'[ok] market-update.html ({len(html)} bytes)')
return path
def upload():
try:
import paramiko, socket, time
HOST = os.environ.get('GFIL_SSH_HOST', '')
PASS = os.environ.get('GFIL_SSH_PASS', '')
PROXY = os.environ.get('GFIL_HTTP_PROXY', '127.0.0.1:7890')
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(30)
sock.connect(tuple(PROXY.split(':')))
sock.sendall(f'CONNECT {HOST}:22 HTTP/1.1\r\nHost: {HOST}:22\r\n\r\n'.encode())
resp = b''
while b'\r\n\r\n' not in resp:
resp += sock.recv(4096)
if b'200' not in resp:
raise Exception('proxy failed')
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(HOST, port=22, username='root', password=PASS, sock=sock, timeout=30, banner_timeout=120)
sftp = ssh.open_sftp()
sftp.put(os.path.join(OUTPUT_DIR, 'market-update.html'), '/var/www/blog/market-update.html')
sftp.close(); ssh.close(); sock.close()
print('[ok] uploaded to server')
except Exception as e:
print(f'[warn] upload failed: {e}')
def print_schedule():
print('''
=== Windows Task Scheduler Setup ===
1. Open Task Scheduler
2. Create Basic Task "GFIL Market Update"
3. Trigger: Daily, repeat every 1 hour
4. Action: Start a program
Program: python
Arguments: D:\\GFIL_BLOG\\deploy_scripts\\daily_market_update.py --upload
Start in: D:\\GFIL_BLOG
''')
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--no-fetch', action='store_true')
parser.add_argument('--upload', action='store_true')
parser.add_argument('--schedule', action='store_true')
args = parser.parse_args()
if args.schedule:
print_schedule()
sys.exit(0)
print('=== Daily Market Update ===')
if args.no_fetch:
prices = {'XAUUSD': 2350.45, 'EURUSD': 1.0825, 'GBPUSD': 1.2734, 'BTCUSD': 87650.00}
print('[demo mode]')
else:
prices = fetch_prices()
print(f'fetched {len(prices)} symbols')
generate_html(prices)
if args.upload:
upload()
print('=== done ===')