# 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) ```