Initial commit: Hermes Agent skills collection

- Trading skills (OKX, dividend, lottery, quantitative)
- Creative skills (ASCII art, diagrams, video)
- Development skills (GitHub, debugging, TDD)
- Research skills (arXiv, blog monitoring)
- Productivity skills (email, documents, notes)
- MCP integration skills
- Custom user skills
This commit is contained in:
Hermes Skills Manager
2026-07-05 02:31:15 -04:00
commit 6770bc9b9d
908 changed files with 239614 additions and 0 deletions
@@ -0,0 +1,336 @@
#!/usr/bin/env python3
"""
信号历史跟踪DB
记录每次确认的信号,用于对比加仓/减仓趋势。
表结构:
- confirmed_signals: 已确认的信号(用户回复Y后记录)
- position_history: 仓位变化历史
"""
import sqlite3
from pathlib import Path
from datetime import datetime
DB_PATH = Path.home() / ".hermes/trading/signal_history.db"
def get_conn():
DB_PATH.parent.mkdir(parents=True, exist_ok=True)
conn = sqlite3.connect(str(DB_PATH))
conn.row_factory = sqlite3.Row
return conn
def init_db():
conn = get_conn()
conn.executescript("""
CREATE TABLE IF NOT EXISTS confirmed_signals (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT NOT NULL,
trader TEXT NOT NULL,
symbol TEXT NOT NULL,
side TEXT NOT NULL,
leverage INTEGER,
trader_size REAL,
trader_entry REAL,
trader_pnl REAL,
our_contracts REAL,
our_margin REAL,
our_entry REAL,
outcome TEXT DEFAULT 'confirmed',
raw_text TEXT
);
CREATE TABLE IF NOT EXISTS position_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT NOT NULL,
trader TEXT NOT NULL,
symbol TEXT NOT NULL,
size REAL NOT NULL,
entry_price REAL,
pnl REAL,
signal_type TEXT
);
CREATE INDEX IF NOT EXISTS idx_confirmed_trader_symbol
ON confirmed_signals(trader, symbol, timestamp);
CREATE INDEX IF NOT EXISTS idx_history_trader_symbol
ON position_history(trader, symbol, timestamp);
""")
conn.commit()
return conn
def record_confirmed(trader, symbol, side, leverage, trader_size, trader_entry, trader_pnl, our_contracts, our_margin, our_entry, raw_text=""):
"""记录已确认的信号"""
conn = init_db()
conn.execute("""
INSERT INTO confirmed_signals
(timestamp, trader, symbol, side, leverage, trader_size, trader_entry, trader_pnl, our_contracts, our_margin, our_entry, raw_text)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (datetime.now().isoformat(), trader, symbol, side, leverage,
trader_size, trader_entry, trader_pnl, our_contracts, our_margin, our_entry, raw_text[:2000]))
conn.execute("""
INSERT INTO position_history
(timestamp, trader, symbol, size, entry_price, pnl, signal_type)
VALUES (?, ?, ?, ?, ?, ?, ?)
""", (datetime.now().isoformat(), trader, symbol, trader_size, trader_entry, trader_pnl, 'confirmed'))
conn.commit()
conn.close()
def record_signal(trader, symbol, side, leverage, trader_size, trader_entry, trader_pnl, raw_text="", outcome="pushed"):
"""记录推送的信号(不管是否确认)"""
conn = init_db()
conn.execute("""
INSERT INTO confirmed_signals
(timestamp, trader, symbol, side, leverage, trader_size, trader_entry, trader_pnl, outcome, raw_text)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""", (datetime.now().isoformat(), trader, symbol, side, leverage,
trader_size, trader_entry, trader_pnl, outcome, raw_text[:2000]))
conn.execute("""
INSERT INTO position_history
(timestamp, trader, symbol, size, entry_price, pnl, signal_type)
VALUES (?, ?, ?, ?, ?, ?, ?)
""", (datetime.now().isoformat(), trader, symbol, trader_size, trader_entry, trader_pnl, outcome))
conn.commit()
conn.close()
def get_last_confirmed(trader, symbol):
"""获取上次确认的信号"""
conn = init_db()
row = conn.execute("""
SELECT * FROM confirmed_signals
WHERE trader = ? AND symbol = ? AND outcome = 'confirmed'
ORDER BY timestamp DESC LIMIT 1
""", (trader, symbol)).fetchone()
conn.close()
return dict(row) if row else None
def get_last_signal(trader, symbol):
"""获取上次推送的信号(不管是否确认)"""
conn = init_db()
row = conn.execute("""
SELECT * FROM confirmed_signals
WHERE trader = ? AND symbol = ?
ORDER BY timestamp DESC LIMIT 1
""", (trader, symbol)).fetchone()
conn.close()
return dict(row) if row else None
def get_position_trend(trader, symbol, limit=5):
"""获取仓位变化趋势"""
conn = init_db()
rows = conn.execute("""
SELECT * FROM position_history
WHERE trader = ? AND symbol = ?
ORDER BY timestamp DESC LIMIT ?
""", (trader, symbol, limit)).fetchall()
conn.close()
return [dict(r) for r in rows]
def compare_position(trader, symbol, current_size):
"""对比当前仓位与上次,返回变化描述"""
last = get_last_signal(trader, symbol)
if not last:
return None, "首次出现"
last_size = last.get('trader_size', 0)
if not last_size or last_size == 0:
return None, "上次仓位未知"
change = current_size - last_size
change_pct = (change / last_size) * 100
if abs(change_pct) < 1:
return last_size, "仓位不变"
elif change > 0:
return last_size, f"加仓 +{change_pct:.1f}%"
else:
return last_size, f"减仓 {change_pct:.1f}%"
def format_comparison(trader, symbol, current_size):
"""格式化对比信息"""
last_size, desc = compare_position(trader, symbol, current_size)
if last_size is None:
return f"{trader} {symbol}: 首次出现,仓位 {current_size:,.0f}"
if "不变" in desc:
return f"{trader} {symbol}: 仓位不变 {current_size:,.0f}"
elif "加仓" in desc:
return f"• 📈 {trader} {symbol}: {last_size:,.0f}{current_size:,.0f}{desc}"
elif "减仓" in desc:
return f"• 📉 {trader} {symbol}: {last_size:,.0f}{current_size:,.0f}{desc}"
else:
return f"{trader} {symbol}: {last_size:,.0f}{current_size:,.0f}{desc}"
# ─── 交易员统计 ──────────────────────────────────────────────────────────
def get_trader_stats(trader=None):
"""获取交易员统计数据"""
conn = init_db()
if trader:
rows = conn.execute("""
SELECT trader, symbol, side, outcome, trader_pnl, timestamp
FROM confirmed_signals
WHERE trader = ?
ORDER BY timestamp DESC
""", (trader,)).fetchall()
else:
rows = conn.execute("""
SELECT trader, symbol, side, outcome, trader_pnl, timestamp
FROM confirmed_signals
ORDER BY trader, timestamp DESC
""").fetchall()
conn.close()
# 按交易员分组
stats = {}
for row in rows:
r = dict(row)
t = r['trader']
if t not in stats:
stats[t] = {
'trader': t,
'total': 0,
'pushed': 0,
'confirmed': 0,
'auto_executed': 0,
'cancelled': 0,
'wins': 0,
'losses': 0,
'total_pnl': 0,
'trades': [],
}
s = stats[t]
s['total'] += 1
outcome = r.get('outcome', 'pushed')
if outcome in s:
s[outcome] += 1
pnl = r.get('trader_pnl', 0) or 0
s['total_pnl'] += pnl
if pnl > 0:
s['wins'] += 1
elif pnl < 0:
s['losses'] += 1
s['trades'].append({
'symbol': r['symbol'],
'side': r['side'],
'pnl': pnl,
'outcome': outcome,
'time': r['timestamp'],
})
# 计算胜率
for t in stats:
s = stats[t]
decided = s['wins'] + s['losses']
s['win_rate'] = (s['wins'] / decided * 100) if decided > 0 else 0
s['avg_pnl'] = (s['total_pnl'] / s['total']) if s['total'] > 0 else 0
return stats
def format_trader_rating(trader):
"""格式化交易员评分(用于推送模板)"""
stats = get_trader_stats(trader)
if trader not in stats or stats[trader]['total'] < 2:
return f"📊 {trader}: 数据不足(信号<2条)"
s = stats[trader]
win_rate = s['win_rate']
total = s['total']
total_pnl = s['total_pnl']
# 评分等级
if win_rate >= 70:
rating = "⭐⭐⭐⭐⭐ 精准"
elif win_rate >= 60:
rating = "⭐⭐⭐⭐ 可靠"
elif win_rate >= 50:
rating = "⭐⭐⭐ 一般"
elif win_rate >= 40:
rating = "⭐⭐ 谨慎"
else:
rating = "⭐ 高风险"
# 最近3笔
recent = s['trades'][:3]
recent_str = "".join([
f"{t['symbol']}{'+' if t['pnl']>0 else ''}{t['pnl']:.0f}"
for t in recent
])
return f"""📊 {trader} 胜率评级: {rating}
• 胜率: {win_rate:.0f}%{s['wins']}胜/{s['losses']}负/{total}总)
• 总盈亏: {'+' if total_pnl>0 else ''}{total_pnl:.0f} USDT
• 最近: {recent_str}"""
def get_all_traders_summary():
"""获取所有交易员的汇总表"""
stats = get_trader_stats()
if not stats:
return "暂无交易员数据"
lines = ["| 交易员 | 胜率 | 总盈亏 | 信号数 |",
"|--------|------|--------|--------|"]
for t, s in sorted(stats.items(), key=lambda x: x[1]['win_rate'], reverse=True):
win_rate = s['win_rate']
total_pnl = s['total_pnl']
emoji = "" * min(5, max(1, int(win_rate / 20)))
lines.append(
f"| {t} | {emoji} {win_rate:.0f}% | {'+' if total_pnl>0 else ''}{total_pnl:.0f} | {s['total']} |"
)
return "\n".join(lines)
# CLI
if __name__ == '__main__':
import sys
if len(sys.argv) < 2:
print("用法:")
print(" python3 signal_tracker.py compare 麻吉大哥 HYPE 12000")
print(" python3 signal_tracker.py history 麻吉大哥 HYPE")
print(" python3 signal_tracker.py record 麻吉大哥 HYPE long 10 12000 70.8 -3500")
print(" python3 signal_tracker.py rating 麻吉大哥")
print(" python3 signal_tracker.py summary")
sys.exit(0)
cmd = sys.argv[1]
if cmd == 'compare' and len(sys.argv) >= 5:
trader = sys.argv[2]
symbol = sys.argv[3]
size = float(sys.argv[4])
print(format_comparison(trader, symbol, size))
elif cmd == 'history' and len(sys.argv) >= 4:
trader = sys.argv[2]
symbol = sys.argv[3]
trend = get_position_trend(trader, symbol)
for t in trend:
print(f" {t['timestamp'][:16]} | {t['size']:,.0f} | {t.get('pnl', 0):+.0f} | {t['signal_type']}")
elif cmd == 'record' and len(sys.argv) >= 8:
trader = sys.argv[2]
symbol = sys.argv[3]
side = sys.argv[4]
leverage = int(sys.argv[5])
size = float(sys.argv[6])
entry = float(sys.argv[7])
pnl = float(sys.argv[8]) if len(sys.argv) > 8 else 0
record_signal(trader, symbol, side, leverage, size, entry, pnl)
print(f"✅ 已记录: {trader} {symbol} {side} {leverage}x {size:,.0f} @{entry}")
elif cmd == 'rating' and len(sys.argv) >= 3:
trader = sys.argv[2]
print(format_trader_rating(trader))
elif cmd == 'summary':
print(get_all_traders_summary())