# DCA Yield Filter Pattern

When user wants to filter DCA positions by minimum dividend yield, add this block to the monitor script **after** loading positions but **before** fetching quotes.

## Code Pattern

```python
positions = config['positions']

# === Yield filter: skip positions below threshold ===
MIN_YIELD = 7.0  # user-configurable
filtered_out = []
for sym in list(positions.keys()):
    if positions[sym].get('yield', 0) < MIN_YIELD:
        filtered_out.append(f"{sym}({positions[sym]['name']} {positions[sym]['yield']}%)")
        del positions[sym]
```

## Budget Reallocation

When filtering removes positions, redistribute budget evenly among remaining:

```python
n = len(positions)
per_stock_hkd = round(7500 / n)  # monthly budget / remaining count
usd_hkd = config['budget']['usd_hkd']

for sym, pos in positions.items():
    pos['monthly_budget_hkd'] = per_stock_hkd
    if pos['market'] == 'US':
        pos['monthly_budget_local'] = round(per_stock_hkd / usd_hkd, 2)
    else:
        pos['monthly_budget_local'] = per_stock_hkd
```

## Config File Structure (dca_positions.json)

Each position has a `yield` field used for filtering:

```json
{
  "positions": {
    "NLY.US": {
      "name": "Annaly Capital",
      "yield": 13.2,
      "market": "US",
      "ladder": [...],
      "monthly_budget_hkd": 2500,
      "monthly_budget_local": 320.51
    }
  },
  "alert_settings": { "trigger_pct": 2.0 },
  "budget": { "monthly_mid_hkd": 7500, "usd_hkd": 7.8 }
}
```

## Key Points

- Filter runs in-memory at script start; the JSON file retains all positions (including filtered ones) for future reference
- User can change `MIN_YIELD` threshold without editing the JSON
- When adding new positions to the JSON, the filter automatically enforces the threshold
- `filtered_out` list can be logged for transparency
