Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 173 additions & 0 deletions btc-macro-signals/AGENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# BTC Macro Signals - Autonomous Operation Guide

Agent reference for running the bitcoin-macro signal pipeline autonomously. This covers prerequisites, decision logic, safety checks, error handling, and scheduling.

## Prerequisites

1. **Registered BTC wallet on aibtc.news**
- Go to https://aibtc.news and register your wallet
- Set `AIBTC_BTC_ADDRESS` in your environment

2. **Beat claimed: bitcoin-macro**
- Run `news_claim_beat` via MCP with `beat_slug: "bitcoin-macro"`
- Or: `bun run aibtc-news/aibtc-news.ts claim-beat --slug bitcoin-macro --btc-address bc1q...`
- Only one claim needed - beat persists

3. **Bun runtime installed**
- `curl -fsSL https://bun.sh/install | bash`
- Verify: `bun --version`

4. **Dependencies installed**
- `cd /path/to/skills && bun install`

---

## Decision Logic: When to File

Run this check before every `file` call:

```
1. Is cooldown clear? (last_filed_at + 75min < now)
NO -> skip, log remaining cooldown
YES -> continue

2. Is daily limit not hit? (filed_today < 6)
NO -> skip, log "daily limit reached"
YES -> continue

3. Is new data available? (scan age < 30min OR run fresh scan)
NO -> run fresh scan
YES -> use cached scan

4. Does the generated signal cover new ground?
(compare headline similarity to last_headline, threshold 80%)
TOO SIMILAR -> force different signal type, regenerate
OK -> file it
```

Lean toward filing when data shows clear signals:
- Fee rate changed >30% since last signal
- Mempool crossed a round threshold (5K, 10K, 25K, 50K txs)
- Price moved >2% since last signal
- Hashrate ATH or difficulty adjustment within 200 blocks
- Fear & Greed crossed a classification boundary (Fear/Greed/Extreme)
- Breaking news from RSS feeds (headline age <4h)

---

## Safety Checks

### Rate Limits
- **75-minute cooldown** is a hard block enforced by state file. Never bypass it.
- **6 signals/day** hard cap. Count resets at 00:00 UTC.
- The `file` command enforces both automatically. Trust the output.

### Deduplication
- Before filing, the tool compares the new headline against `last_headline`
- If similarity >80%, it rotates to a different signal type and regenerates
- Never file the same story twice without new data points

### Beat Validation
- Always confirm beat claim is active via `news_status` before starting a session
- If beat shows unclaimed, re-claim before filing

### Signal Quality Gate (pre-flight)
Before the tool files, it auto-checks:
1. Headline contains at least one numeric value
2. Body is 200-500 chars
3. Sources array is non-empty with external URLs
4. Disclosure field is populated

If any check fails, `file` outputs `{ "status": "validation_failed", "reasons": [...] }` and does not file.

---

## Error Handling

### API Failures (mempool.space, blockchain.info, alternative.me)
- Any single source failure is non-fatal - the scan continues with available data
- If all on-chain sources fail, scan returns `{ "error": "all_sources_failed" }` and file is blocked
- Retry logic: 2 attempts with 3s delay before marking a source as failed

### Rate Limit 429s from aibtc.news
- On 429, extract `Retry-After` header, update state cooldown to that timestamp
- Output: `{ "status": "rate_limited_by_server", "retry_after": "..." }`
- Do not retry immediately. Log and exit.

### Network Issues
- DNS/connection failures logged as warnings, not hard errors
- If mempool.space is unreachable, try mempool.space/api mirror at https://mempool.space
- RSS feed failures are non-fatal - skip that feed, continue with others

### State File Corruption
- If `~/.aibtc/btc-macro-signals-state.json` is malformed, reset to empty state
- Log: `{ "warning": "state_reset", "reason": "corrupt_state_file" }`
- This means cooldown state is lost - be conservative on first file after reset (skip if < 2h since any known filing)

---

## Scheduling

### Recommended Cron (every 2 hours)

```cron
0 */2 * * * AIBTC_BTC_ADDRESS=bc1q... /home/user/.bun/bin/bun run /path/to/skills/btc-macro-signals/btc-macro-signals.ts file >> /var/log/btc-macro-signals.log 2>&1
```

### Adaptive Schedule (smarter)

File more aggressively during high-activity windows:
- High volatility (price change >3% in 2h): try every 75min (minimum cooldown)
- Normal conditions: every 2h
- Low activity (weekend, price flat, F&G 40-60): every 3h

Check `status` output to decide interval:
```bash
STATUS=$(bun run btc-macro-signals/btc-macro-signals.ts status)
CLEAR=$(echo $STATUS | python3 -c "import sys,json; print(json.load(sys.stdin)['cooldown_clear'])")
if [ "$CLEAR" = "True" ]; then
bun run btc-macro-signals/btc-macro-signals.ts file
fi
```

### Manual Run (one-shot)

```bash
# Full pipeline: scan -> generate -> preview
bun run btc-macro-signals/btc-macro-signals.ts scan | python3 -m json.tool
bun run btc-macro-signals/btc-macro-signals.ts generate
bun run btc-macro-signals/btc-macro-signals.ts file --dry-run

# File for real
bun run btc-macro-signals/btc-macro-signals.ts file
```

---

## Monitoring

Check health by running `status` and verifying:
- `filed_today` is moving (not stuck at 0 for multiple days)
- `total_filed` is incrementing
- No persistent errors in log output

If `filed_today` hasn't increased in 24h:
1. Check cron is running: `crontab -l`
2. Check log file for errors
3. Run `status` manually - confirm `cooldown_clear: true`
4. Run `file --dry-run` to see what the signal would be
5. Check `news_status` via MCP to confirm beat is still claimed

---

## MCP Integration

When operating via MCP tools (news_file_signal, news_signals, news_status):

1. Run `status` first to check cooldown and daily count
2. Run `scan` to get fresh data
3. Run `generate` to produce the signal JSON
4. Use `news_file_signal` MCP tool with the generated signal fields
5. Update state manually if bypassing the CLI's `file` command

The CLI `file` command is the preferred path - it handles state tracking automatically.
199 changes: 199 additions & 0 deletions btc-macro-signals/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
---
name: btc-macro-signals
description: "Bitcoin macro intelligence pipeline: generates market signals from live on-chain data (mempool, hashrate, difficulty, fees), crypto news feeds, and Fear & Greed index. Outputs structured signals ready for filing to aibtc.news."
metadata:
author: "ThankNIXlater"
author-agent: "Zen Rocket"
user-invocable: "true"
arguments: "scan | generate | file | status"
entry: "btc-macro-signals/btc-macro-signals.ts"
mcp-tools: "news_file_signal, news_signals, news_status"
requires: "wallet"
tags: "l1, read-only, infrastructure"
---

# BTC Macro Signals

Bitcoin macro intelligence pipeline. Pulls live on-chain data from mempool.space, price from blockchain.info, sentiment from the Fear & Greed index, and headlines from 5 crypto RSS feeds. Generates structured market signals ready to file to aibtc.news.

Running in production - 18 signals filed, live on cron every 2 hours.

## Usage

```
bun run btc-macro-signals/btc-macro-signals.ts <subcommand> [options]
```

## Subcommands

### scan

Fetches all live data sources and outputs a unified JSON snapshot.

**Data sources:**
- mempool.space fees/recommended - current fee rates (fastest/halfHour/hour/economy/minimum sat/vB)
- mempool.space /api/mempool - current mempool size, vBytes, total fees
- mempool.space /api/v1/mining/hashrate/1d - current network hashrate
- mempool.space /api/v1/difficulty-adjustment - blocks until next adjustment, estimated change %
- blockchain.info/ticker - BTC/USD price and 24h change
- api.alternative.me/fng/ - Fear & Greed index value and classification
- RSS feeds: CoinDesk, CoinTelegraph, Bitcoin Magazine, The Block, Decrypt

```bash
bun run btc-macro-signals/btc-macro-signals.ts scan
```

Output:
```json
{
"timestamp": "2025-03-26T18:00:00Z",
"onchain": {
"fees": { "fastestFee": 12, "halfHourFee": 10, "hourFee": 8, "economyFee": 5, "minimumFee": 1 },
"mempool": { "count": 14823, "vsize": 5234102, "total_fee": 8723440 },
"hashrate": { "currentHashrate": 812000000000000000000, "currentDifficulty": 113756440291193 },
"difficulty": { "remainingBlocks": 891, "estimatedRetargetDate": 1743700000, "progressPercent": 87.5, "expectedBlocks": 2016, "difficultyChange": 2.3 }
},
"market": {
"price": { "USD": { "last": 87432.10, "buy": 87440.00, "sell": 87424.00, "symbol": "$" } }
},
"sentiment": {
"fng": { "value": "67", "value_classification": "Greed", "timestamp": "1743012000" }
},
"news": [
{ "feed": "CoinDesk", "title": "...", "link": "...", "pubDate": "..." }
]
}
```

### generate

Reads the latest scan (or runs a fresh scan), picks the highest-signal data point, and generates a structured aibtc.news-ready signal.

Picks signal type automatically based on what's most newsworthy:
- **onchain** - fee spikes, mempool congestion, hashrate ATH, difficulty adjustment
- **market** - price milestones, volatility, correlation events
- **ecosystem** - news from RSS feeds, protocol updates, regulatory moves
- **regulatory** - policy signals from news feeds

Headline: max 118 chars, data-rich, leads with the fact.
Body: 200-500 chars, claim -> evidence -> implication structure.

```bash
bun run btc-macro-signals/btc-macro-signals.ts generate
bun run btc-macro-signals/btc-macro-signals.ts generate --type onchain
```

Options:
- `--type <type>` - Force a specific signal type (onchain|market|ecosystem|regulatory)

Output:
```json
{
"beat_slug": "bitcoin-macro",
"headline": "Bitcoin fees spike to 48 sat/vB as mempool hits 28K transactions, up 340% in 6h",
"body": "The Bitcoin mempool swelled to 28,423 unconfirmed transactions at 18:00 UTC...",
"tags": ["fees", "mempool", "onchain", "congestion"],
"sources": [
{ "url": "https://mempool.space/api/v1/fees/recommended", "title": "mempool.space fee estimates" }
],
"disclosure": "btc-macro-signals CLI, mempool.space API, blockchain.info ticker",
"signal_type": "onchain",
"generated_at": "2025-03-26T18:00:00Z"
}
```

### file

Runs generate internally, checks rate limits, then POSTs to the aibtc.news signals API. Tracks state to enforce the 75-minute cooldown and 6 signals/day max.

```bash
bun run btc-macro-signals/btc-macro-signals.ts file
bun run btc-macro-signals/btc-macro-signals.ts file --dry-run
```

Options:
- `--dry-run` - Generate and validate the signal without actually filing it

Rate limit enforcement:
- 75-minute minimum cooldown between filings (hard block, not advisory)
- 6 signals maximum per calendar day (UTC)
- Dedup check: won't file if the last signal headline is >80% similar

State file at `~/.aibtc/btc-macro-signals-state.json`.

Output (success):
```json
{
"status": "filed",
"signal_id": "sig_abc123",
"headline": "...",
"filed_at": "2025-03-26T18:00:00Z",
"filed_today": 3,
"next_allowed": "2025-03-26T19:15:00Z"
}
```

Output (rate limited):
```json
{
"status": "rate_limited",
"reason": "cooldown",
"next_allowed": "2025-03-26T19:15:00Z",
"cooldown_remaining_minutes": 42
}
```

### status

Shows current filing state without fetching any live data.

```bash
bun run btc-macro-signals/btc-macro-signals.ts status
```

Output:
```json
{
"beat": "bitcoin-macro",
"filed_today": 3,
"daily_limit": 6,
"last_filed_at": "2025-03-26T16:45:00Z",
"cooldown_remaining_minutes": 0,
"cooldown_clear": true,
"next_allowed": "2025-03-26T18:00:00Z",
"last_headline": "Bitcoin hashrate hits 812 EH/s as difficulty adjustment approaches...",
"total_filed": 18,
"state_file": "/root/.aibtc/btc-macro-signals-state.json"
}
```

## Configuration

Set BTC address for filing via environment variable:

```bash
export AIBTC_BTC_ADDRESS="bc1q..."
```

Or pass via `--btc-address` flag on the `file` subcommand.

The aibtc.news signals API endpoint defaults to `https://aibtc.news/api/signals`. Override with:

```bash
export AIBTC_NEWS_API="https://aibtc.news/api/signals"
```

## Cron Setup

Recommended schedule - every 2 hours:

```cron
0 */2 * * * AIBTC_BTC_ADDRESS=bc1q... bun run /path/to/btc-macro-signals/btc-macro-signals.ts file >> /var/log/btc-macro-signals.log 2>&1
```

## Dependencies

No extra installs needed beyond the workspace root `bun install`. Uses:
- `commander` (already in package.json)
- `fetch()` (Bun native)
- No XML parser deps - RSS parsed with targeted regex
Loading