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:
@@ -0,0 +1,160 @@
|
||||
# DCA Ladder Monitoring — 阶梯买入自动监控
|
||||
|
||||
After screening candidates (see `dca-screener.md`), set up automated price monitoring so the user gets buy signals when prices hit ladder tiers.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
dca_positions.json ← config (symbols, ladder prices, budget, status)
|
||||
↓
|
||||
dca_monitor.py ← reads config + fetches prices from LongPort
|
||||
↓
|
||||
cron jobs ← runs monitor on schedule, delivers alerts
|
||||
```
|
||||
|
||||
## Step 1: Create Position Config
|
||||
|
||||
File: `~/.hermes/scripts/dca_positions.json`
|
||||
|
||||
```json
|
||||
{
|
||||
"updated": "YYYY-MM-DD",
|
||||
"positions": {
|
||||
"SYMBOL.US": {
|
||||
"name": "Display Name",
|
||||
"yield": 10.5,
|
||||
"market": "US",
|
||||
"ladder": [
|
||||
{"tier": 1, "price": 15.28, "alloc_pct": 40, "status": "pending", "shares": 3, "cost_local": 45.84},
|
||||
{"tier": 2, "price": 15.07, "alloc_pct": 30, "status": "pending", "shares": 2, "cost_local": 30.14},
|
||||
{"tier": 3, "price": 13.03, "alloc_pct": 30, "status": "pending", "shares": 3, "cost_local": 39.09}
|
||||
],
|
||||
"monthly_budget_hkd": 1071,
|
||||
"monthly_budget_local": 137,
|
||||
"notes": "PE8.5 科技BDC龙头"
|
||||
}
|
||||
},
|
||||
"budget": {
|
||||
"monthly_min_hkd": 6000,
|
||||
"monthly_max_hkd": 9000,
|
||||
"monthly_mid_hkd": 7500,
|
||||
"per_stock_hkd": 1071,
|
||||
"usd_hkd": 7.80
|
||||
},
|
||||
"alert_settings": {
|
||||
"trigger_pct": 2.0,
|
||||
"cooldown_hours": 24
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Lot Calculation
|
||||
|
||||
Given monthly budget M and N stocks:
|
||||
- `per_stock = M / N` (in HKD)
|
||||
- For US stocks: `per_stock_local = per_stock / USDHKD`
|
||||
- Per tier: `shares = floor(tier_budget / price)` where `tier_budget = per_stock_local * alloc_pct / 100`
|
||||
- Update JSON with `shares`, `cost_local`, `cost_hkd` fields
|
||||
|
||||
### Status Tracking
|
||||
|
||||
When user confirms a purchase:
|
||||
- Change `status` from `"pending"` to `"done"` in the ladder entry
|
||||
- This prevents re-alerting on already-purchased tiers
|
||||
|
||||
## Step 2: Monitor Script
|
||||
|
||||
File: `~/.hermes/scripts/dca_monitor.py`
|
||||
|
||||
Key logic:
|
||||
1. Load env vars from `~/.bashrc` (LONGBRIDGE_* → LONGPORT_*)
|
||||
2. Load `dca_positions.json`
|
||||
3. Fetch current prices via `ctx.quote(symbols)` in batches of 15
|
||||
4. For each position, compare price to each pending ladder tier
|
||||
5. If `current_price <= target * (1 + trigger_pct/100)`: emit alert
|
||||
6. If no alerts triggered: output empty (silent — no notification sent)
|
||||
|
||||
### Alert Format
|
||||
|
||||
```
|
||||
🔔 DCA买入信号 [YYYY-MM-DD HH:MM]
|
||||
|
||||
🚨 🇺🇸 HTGC.US Hercules Capital
|
||||
第1档目标: 15.28 现价: 15.20 已触达
|
||||
建议仓位: 40% 买入: 3股 股息率: 10.5%
|
||||
|
||||
🟡 🇺🇸 NLY.US Annaly Capital
|
||||
第2档目标: 21.07 现价: 21.22 差0.7%
|
||||
建议仓位: 30% 买入: 1股 股息率: 13.2%
|
||||
```
|
||||
|
||||
### Pitfalls
|
||||
|
||||
- **SecurityQuote attribute**: `SecurityQuote` may not have `change_rate` on some data tiers. Use `CalcIndex.ChangeRate` via `calc_indexes` instead.
|
||||
- **Price=0 on weekends**: LongPort returns 0 for `last_done` when markets are closed. The monitor will trigger all alerts on weekends — either skip weekends in cron schedule or handle in script.
|
||||
- **HK stock codes in python3 -c**: Codes like `0728.HK` start with digits. Always write scripts to file, never use `python3 -c`.
|
||||
- **Batch sizes**: quote 15/batch, calc_indexes 10/batch, static_info 20/batch.
|
||||
|
||||
## Step 3: Cron Jobs
|
||||
|
||||
Set up 5 jobs (all Beijing time):
|
||||
|
||||
| Schedule | Name | Purpose |
|
||||
|----------|------|---------|
|
||||
| `0 9 * * 1-6` | DCA每日晨报 | AI-driven summary with all positions status |
|
||||
| `0 10 * * 1-5` | DCA港股盘中(上午) | HK market check (1hr after open) |
|
||||
| `0 15 * * 1-5` | DCA港股盘中(下午) | HK market check (1hr before close) |
|
||||
| `30 22 * * 1-5` | DCA美股盘中(晚间) | US market check (30min after open) |
|
||||
| `0 2 * * 2-6` | DCA美股盘中(凌晨) | US market check (mid-session) |
|
||||
|
||||
### Cron Setup Pattern
|
||||
|
||||
**Script-only jobs** (no agent, just run monitor):
|
||||
```python
|
||||
cronjob(action='create', name='DCA港股盘中监控',
|
||||
schedule='0 10 * * 1-5', no_agent=True,
|
||||
script='scripts/dca_monitor.py', deliver='origin')
|
||||
```
|
||||
|
||||
**AI-driven daily summary** (with agent for richer formatting):
|
||||
```python
|
||||
cronjob(action='create', name='DCA每日晨报',
|
||||
schedule='0 9 * * 1-6',
|
||||
prompt='Run dca_monitor.py, generate morning brief...',
|
||||
enabled_toolsets=['terminal'], deliver='origin')
|
||||
```
|
||||
|
||||
## Step 4: User Interaction Commands
|
||||
|
||||
After deployment, user may say:
|
||||
|
||||
| User Says | Action |
|
||||
|-----------|--------|
|
||||
| "我买了XX T1" | Edit JSON: set tier status to `"done"` |
|
||||
| "调整XX阶梯价位" | Edit JSON: update ladder prices |
|
||||
| "设置预算XX万" | Recalculate lot sizes, update JSON |
|
||||
| "加一只XX" | Add new position to JSON |
|
||||
| "暂停DCA监控" | Pause cron jobs |
|
||||
| "DCA状态" | Run monitor script, show all positions |
|
||||
|
||||
## Full Script Template
|
||||
|
||||
See `~/.hermes/scripts/dca_monitor.py` for the production script.
|
||||
|
||||
Key env loading pattern (required for all LongPort scripts):
|
||||
```python
|
||||
import os, re
|
||||
env_vars = {}
|
||||
with open(os.path.expanduser('~/.bashrc')) as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line.startswith('export LONGBRIDGE_') or line.startswith('export LONGPORT_'):
|
||||
parts = line.replace('export ', '').split('=', 1)
|
||||
if len(parts) == 2:
|
||||
env_vars[parts[0]] = parts[1]
|
||||
for key, val in env_vars.items():
|
||||
if '${' not in val: os.environ[key] = val
|
||||
for key, val in env_vars.items():
|
||||
if '${' in val:
|
||||
os.environ[key] = re.sub(r'\$\{(\w+)\}', lambda m: os.environ.get(m.group(1), ''), val)
|
||||
```
|
||||
Reference in New Issue
Block a user