refactor: decouple Coin Hunter from Hermes for cross-platform usage

- Add unified coinhunter_shim.py that accepts subcommands (pre/gate/review/rotate-log)
- Update SKILL.md gate pseudocode to read optional ~/.coinhunter/platform.json
- Split cron/setup examples into Hermes and OpenClaw variants across docs
- Introduce platform.json schema in user-data-layout.md
- Remove stale auto_trader.py/run_trader.sh references from auto-trading-guide.md
- Keep legacy shims as backward-compatible wrappers
This commit is contained in:
2026-04-16 03:03:25 +08:00
parent 863d10b872
commit c07b9c1ae5
12 changed files with 409 additions and 110 deletions

View File

@@ -76,6 +76,12 @@ Read `references/short-term-trading-framework.md` before every active decision p
## Auto-trading architecture
Install the executable CLI first:
```bash
pipx install coinhunter
# or: pip install coinhunter
```
| CLI Command | Purpose |
|-------------|---------|
| `coinhunter exec` | Order execution layer (buy / flat / rotate / hold) |
@@ -92,7 +98,7 @@ Read `references/short-term-trading-framework.md` before every active decision p
When model cost or quota is tight, do not let every cron run perform full analysis from scratch.
Recommended pattern:
1. Attach a lightweight Python `script` to the cron job (under `~/.hermes/scripts/`) that fetches balances/tickers, computes hashes, and emits compact JSON context.
1. Attach a lightweight Python `script` to the cron job (under your platform's scripts directory, e.g. `~/.hermes/scripts/` or `~/.openclaw/scripts/`) that fetches balances/tickers, computes hashes, and emits compact JSON context.
2. Cache the last observed positions, top candidates, market regime, and `last_deep_analysis_at` under `~/.coinhunter/state/`.
3. Trigger full analysis only when one of these changes materially. Make the thresholds adaptive instead of fixed:
- position structure changes (hard trigger)
@@ -105,10 +111,10 @@ Recommended pattern:
7. For even lower spend, move the high-frequency cadence outside Hermes cron entirely:
- install a system `crontab` entry that runs a local gate script every 5-10 minutes
- let that gate script run the lightweight precheck
- only when `should_analyze=true` and no run is already queued, trigger the Hermes cron job via `hermes cron run <job_id>`
- only when `should_analyze=true` and no run is already queued, trigger your platform's cron job (e.g. `hermes cron run <job_id>` or `openclaw trigger <job_id>`)
- store a `run_requested_at` marker in `~/.coinhunter/state/precheck_state.json` and clear it when the analysis acknowledges completion
This pattern preserves Telegram auto-delivery from Hermes cron while reducing model wakeups to trigger-only events.
This pattern preserves auto-delivery from your platform's cron system while reducing model wakeups to trigger-only events.
### Practical production notes for external gate mode
- Put the external gate itself on system `crontab` (for example every 5 minutes) rather than on Hermes cron. That keeps the high-frequency loop completely local and model-free.
@@ -214,31 +220,51 @@ if __name__ == "__main__":
print(json.dumps(result))
```
#### 4. Hermes cron job configuration
Attach the precheck script as the `script` field of the cron job so its JSON output is injected into the prompt:
#### 4. Cron job configuration
Attach the precheck script as the `script` field of the cron job so its JSON output is injected into the prompt.
**Hermes example:**
```json
{
"id": "coinhunter-trade",
"schedule": "*/15 * * * *",
"prompt": "You are Coin Hunter. If the injected context says should_analyze=false, respond with exactly [SILENT] and do nothing. Otherwise, read ~/.coinhunter/positions.json, run the scientific checklist, decide HOLD/SELL/REBALANCE/BUY, and execute via the `coinhunter` CLI. After finishing, run `coinhunter pre --ack` to clear the trigger.",
"script": "coinhunter_precheck.py",
"script": "coinhunter_shim.py pre",
"deliver": "telegram",
"model": "kimi-for-coding"
}
```
Add an `--ack` handler to the precheck script (or a separate ack script) that sets `run_acknowledged_at` and clears `run_requested_at` so the gate does not re-fire until the next true trigger.
**OpenClaw example:**
```json
{
"id": "coinhunter-trade",
"schedule": "*/15 * * * *",
"prompt": "You are Coin Hunter. If the injected context says should_analyze=false, respond with exactly [SILENT] and do nothing. Otherwise, read ~/.coinhunter/positions.json, run the scientific checklist, decide HOLD/SELL/REBALANCE/BUY, and execute via the `coinhunter` CLI. After finishing, run `coinhunter pre --ack` to clear the trigger.",
"script": "coinhunter_shim.py pre",
"deliver": "webhook"
}
```
Acknowledge completion by running `coinhunter pre --ack` so the gate clears `run_requested_at` and does not re-fire until the next true trigger.
#### 5. External gate (optional, for even lower cost)
If you want to run the precheck every 5 minutes without waking Hermes at all:
External gate pseudocode (run from `~/.hermes/scripts/`):
External gate pseudocode (run from your platform's scripts directory):
```python
import fcntl, os, subprocess, json, sys
LOCK_PATH = os.path.expanduser("~/.coinhunter/state/external_gate.lock")
PRECHECK = os.path.expanduser("~/.hermes/scripts/coinhunter_precheck.py")
JOB_ID = "coinhunter-trade"
PLATFORM_PATH = os.path.expanduser("~/.coinhunter/platform.json")
# Load platform config if it exists; default to Hermes behavior
platform = {"cron_command": ["hermes", "cron", "run"]}
if os.path.exists(PLATFORM_PATH):
platform.update(json.load(open(PLATFORM_PATH)))
cron_command = platform.get("cron_command", ["hermes", "cron", "run"])
with open(LOCK_PATH, "w") as f:
try:
@@ -246,22 +272,37 @@ with open(LOCK_PATH, "w") as f:
except BlockingIOError:
sys.exit(0) # another instance is running
result = json.loads(os.popen(f"python {PRECHECK}").read())
result = json.loads(os.popen("coinhunter pre").read())
if result.get("should_analyze"):
# Trigger Hermes cron only if not already requested
# Trigger platform cron only if not already requested
state_path = os.path.expanduser("~/.coinhunter/state/precheck_state.json")
state = json.load(open(state_path))
if not state.get("run_requested_at"):
subprocess.run(["hermes", "cron", "run", JOB_ID], check=False)
subprocess.run([*cron_command, JOB_ID], check=False)
```
System crontab entry:
```cron
*/5 * * * * /usr/bin/python3 /home/user/.hermes/scripts/coinhunter_external_gate.py >> /home/user/.coinhunter/logs/external_gate.log 2>&1
*/5 * * * * /usr/bin/env coinhunter gate >> /home/user/.coinhunter/logs/external_gate.log 2>&1
```
With this setup, the model is only invoked when a material market change occurs—preserving intelligence while cutting routine cost by 80-95%.
### Troubleshooting common precheck errors
When `coinhunter pre` fails with `status: deep_analysis_required` and `reasons: ["precheck-error"]`, inspect the `details` field and apply these known fixes:
1. **`'PosixPath' object has no attribute 'env_file'`**
- Location: inside the installed `coinhunter` package (`src/coinhunter/services/market_data.py` in the PyPI source)
- Cause: `load_env_file(ENV_FILE)` is passed a `Path` object, but `load_env_file()` expects either a `RuntimePaths` dataclass or no arguments.
- Fix: Update `coinhunter` to the latest version from PyPI. If the bug persists, patch the installed package and submit an issue to the `coinhunter` project.
2. **`name 'BASE_PN_L_TRIGGER_PCT' is not defined`**
- Location: inside the installed `coinhunter` package (`src/coinhunter/services/adaptive_profile.py` in the PyPI source)
- Cause: Typo `BASE_PN_L_TRIGGER_PCT` instead of `BASE_PNL_TRIGGER_PCT`.
- Fix: Update `coinhunter` to the latest version from PyPI. If the bug persists, patch the installed package and submit an issue to the `coinhunter` project.
After updating, rerun `coinhunter pre` to verify the gate clears before executing the trading decision.
### Production hardening (mandatory)
The live trading stack must include these safeguards:
1. **Idempotency** — every decision carries a `decision_id`. The executor checks `~/.coinhunter/executions.json` before submitting orders to prevent duplicate trades.
@@ -272,6 +313,21 @@ The live trading stack must include these safeguards:
6. **Structured logging** — every decision, trade, error, and balance snapshot is written as JSONL under `~/.coinhunter/logs/` with `schema_version` and `decision_id`.
7. **Error logging** — failed API calls, rejected orders, and reconciliation mismatches are captured in `logs/errors_YYYYMMDD.jsonl` and fed into the hourly review.
## Cross-platform deployment
Coin Hunter is runtime-agnostic. It works on Hermes, OpenClaw, and any compatible cron-based platform.
1. **Install the CLI** (same everywhere):
```bash
pipx install coinhunter
```
2. **Place the shim** in your platform's scripts directory:
- Hermes: `~/.hermes/scripts/coinhunter_shim.py`
- OpenClaw: `~/.openclaw/scripts/coinhunter_shim.py`
3. *(Optional)* Create `~/.coinhunter/platform.json` if you want the external gate to use a non-default trigger command. When absent, the gate falls back to Hermes behavior (`hermes cron run`).
## Safety rules
- No leverage/futures when capital < $200.
- When capital < $50, concentrate into **1 position only**.