refactor: rewrite to CoinHunter V2 flat architecture
Replace the V1 commands/services split with a flat, direct architecture: - cli.py dispatches directly to service functions - New services: account, market, trade, opportunity - Thin Binance wrappers: spot_client, um_futures_client - Add audit logging, runtime paths, and TOML config - Remove legacy V1 code: commands/, precheck, review engine, smart executor - Add ruff + mypy toolchain and fix edge cases in trade params Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
134
CLAUDE.md
134
CLAUDE.md
@@ -4,111 +4,59 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## Development commands
|
||||
|
||||
- **Editable install:** `pip install -e .`
|
||||
- **Run the CLI locally:** `python -m coinhunter --help`
|
||||
- **Install for end users:** `pipx install coinhunter` (recommended) or `./scripts/install_local.sh` for local editable install.
|
||||
- **Tests:** There is no test suite yet. The README lists next priorities as adding pytest coverage for runtime paths, state manager, and trigger analyzer.
|
||||
- **Lint / type-check:** Not configured yet.
|
||||
|
||||
## CLI command routing
|
||||
|
||||
`src/coinhunter/cli.py` is the single entrypoint. It resolves aliases to canonical commands, maps canonical commands to Python modules via `MODULE_MAP`, then imports the module and calls `module.main()` after mutating `sys.argv` to match the display name.
|
||||
|
||||
Active commands live in `src/coinhunter/commands/` and are thin adapters that delegate to `src/coinhunter/services/`. Root-level backward-compat facades (e.g., `precheck.py`, `smart_executor.py`, `review_engine.py`, `review_context.py`) re-export the moved commands.
|
||||
- **Install (dev):** `pip install -e ".[dev]"`
|
||||
- **Run CLI locally:** `python -m coinhunter --help`
|
||||
- **Run tests:** `pytest` or `python -m pytest tests/`
|
||||
- **Run single test file:** `pytest tests/test_cli.py -v`
|
||||
- **Lint:** `ruff check src tests`
|
||||
- **Format:** `ruff format src tests`
|
||||
- **Type-check:** `mypy src`
|
||||
|
||||
## Architecture
|
||||
|
||||
### Layer responsibilities
|
||||
CoinHunter V2 is a Binance-first crypto trading CLI with a flat, direct architecture:
|
||||
|
||||
- **CLI (`cli.py`)** — argument parsing, alias resolution, module dispatch.
|
||||
- **Commands (`commands/`)** — thin, stateless adapters that call into services.
|
||||
- **Services (`services/`)** — orchestration, domain logic, and exchange interaction.
|
||||
- **Runtime (`runtime.py`)** — path resolution, env loading, hermes binary discovery.
|
||||
- **Logger (`logger.py`)** — structured JSONL logging to `~/.coinhunter/logs/`.
|
||||
- **`src/coinhunter/cli.py`** — Single entrypoint (`main()`). Uses `argparse` to parse commands and directly dispatches to service functions. There is no separate `commands/` adapter layer.
|
||||
- **`src/coinhunter/services/`** — Contains all domain logic:
|
||||
- `account_service.py` — balances, positions, overview
|
||||
- `market_service.py` — tickers, klines, scan universe, symbol normalization
|
||||
- `trade_service.py` — spot and USDT-M futures order execution
|
||||
- `opportunity_service.py` — portfolio recommendations and market scanning
|
||||
- **`src/coinhunter/binance/`** — Thin wrappers around official Binance connectors:
|
||||
- `spot_client.py` wraps `binance.spot.Spot`
|
||||
- `um_futures_client.py` wraps `binance.um_futures.UMFutures`
|
||||
Both normalize request errors into `RuntimeError` and handle single/multi-symbol ticker responses.
|
||||
- **`src/coinhunter/config.py`** — `load_config()`, `get_binance_credentials()`, `ensure_init_files()`.
|
||||
- **`src/coinhunter/runtime.py`** — `RuntimePaths`, `get_runtime_paths()`, `print_json()`.
|
||||
- **`src/coinhunter/audit.py`** — Writes JSONL audit events to dated files.
|
||||
|
||||
### Runtime and environment
|
||||
## Runtime and environment
|
||||
|
||||
`runtime.py` defines `RuntimePaths` and `get_runtime_paths()`. User data lives in `~/.coinhunter/` by default (override with `COINHUNTER_HOME`). Credentials are loaded from `~/.hermes/.env` by default (override with `COINHUNTER_ENV_FILE`). Modules should call `get_runtime_paths()` at function scope rather than eagerly at import time.
|
||||
User data lives in `~/.coinhunter/` by default (override with `COINHUNTER_HOME`):
|
||||
|
||||
### Smart executor (`exec`)
|
||||
- `config.toml` — runtime, binance, trading, and opportunity settings
|
||||
- `.env` — `BINANCE_API_KEY` and `BINANCE_API_SECRET`
|
||||
- `logs/audit_YYYYMMDD.jsonl` — structured audit log
|
||||
|
||||
`commands/smart_executor.py` → `services/smart_executor_service.py` → `services/trade_execution.py`.
|
||||
Run `coinhunter init` to generate the config and env templates.
|
||||
|
||||
Supported verbs: `bal`, `overview`, `hold`, `buy SYMBOL USDT`, `flat SYMBOL`, `rotate FROM TO`.
|
||||
## Key conventions
|
||||
|
||||
- `smart_executor_parser.py` normalizes legacy argv and exposes `parse_cli_args()`.
|
||||
- `trade_common.py` holds a global dry-run flag (`set_dry_run` / `is_dry_run`).
|
||||
- `execution_state.py` tracks decision IDs in JSON to prevent duplicate executions.
|
||||
- `exchange_service.py` wraps `ccxt.binance` and handles symbol normalization.
|
||||
- `portfolio_service.py` manages `positions.json` load/save/reconcile.
|
||||
- **Symbol normalization:** `market_service.normalize_symbol()` strips `/`, `-`, `_`, and uppercases the symbol. CLI inputs like `ETH/USDT`, `eth-usdt`, and `ETHUSDT` are all normalized to `ETHUSDT`.
|
||||
- **Dry-run behavior:** Trade commands support `--dry-run`. If omitted, the default falls back to `trading.dry_run_default` in `config.toml`.
|
||||
- **Client injection:** Service functions accept `spot_client` / `futures_client` as keyword arguments. This enables easy unit testing with mocks.
|
||||
- **Error handling:** Binance client wrappers catch `requests.exceptions.SSLError` and `RequestException` and re-raise as human-readable `RuntimeError`. The CLI catches all exceptions in `main()` and prints `error: {message}` to stderr with exit code 1.
|
||||
|
||||
### Precheck
|
||||
## Testing
|
||||
|
||||
`commands/precheck.py` → `services/precheck_service.py`.
|
||||
Tests live in `tests/` and use `unittest.TestCase` with `unittest.mock.patch`. The test suite covers:
|
||||
|
||||
The precheck workflow:
|
||||
1. Load and sanitize state (`precheck_state.py` — clears stale triggers and run requests).
|
||||
2. Build a market snapshot (`precheck_snapshot.py` → `snapshot_builder.py`).
|
||||
3. Analyze whether to trigger deep analysis (`precheck_analysis.py` → `trigger_analyzer.py`).
|
||||
4. Update and save state (`precheck_state.update_state_after_observation`).
|
||||
- `test_cli.py` — parser smoke tests and dispatch behavior
|
||||
- `test_config_runtime.py` — config loading, env parsing, path resolution
|
||||
- `test_account_market_services.py` — balance/position/ticker/klines logic with mocked clients
|
||||
- `test_trade_service.py` — spot and futures trade execution paths
|
||||
- `test_opportunity_service.py` — portfolio and scan scoring logic
|
||||
|
||||
State is stored in `~/.coinhunter/state/precheck_state.json`.
|
||||
## Notes
|
||||
|
||||
### Review commands
|
||||
|
||||
- `review N` (`commands/review_context.py` → `services/review_service.py`) — generates review context for the last N hours.
|
||||
- `recap N` (`commands/review_engine.py` → `services/review_service.py`) — generates a full review report by reading JSONL decision/trade/error logs, computing PnL estimates, missed opportunities, and saving a report to `~/.coinhunter/reviews/`.
|
||||
|
||||
### Logging model
|
||||
|
||||
`logger.py` writes JSONL to dated files in `~/.coinhunter/logs/`:
|
||||
- `decisions_YYYYMMDD.jsonl`
|
||||
- `trades_YYYYMMDD.jsonl`
|
||||
- `errors_YYYYMMDD.jsonl`
|
||||
- `snapshots_YYYYMMDD.jsonl`
|
||||
|
||||
Use `get_logs_last_n_hours(log_type, hours)` to query recent entries.
|
||||
|
||||
## Common command reference
|
||||
|
||||
```bash
|
||||
# Diagnostics
|
||||
python -m coinhunter diag
|
||||
python -m coinhunter paths
|
||||
python -m coinhunter api-check
|
||||
|
||||
# Execution (dry-run)
|
||||
python -m coinhunter exec bal
|
||||
python -m coinhunter exec overview
|
||||
python -m coinhunter exec buy ENJUSDT 50 --dry-run
|
||||
python -m coinhunter exec flat ENJUSDT --dry-run
|
||||
|
||||
# Precheck
|
||||
python -m coinhunter precheck
|
||||
python -m coinhunter precheck --ack "analysis completed"
|
||||
python -m coinhunter precheck --mark-run-requested "reason"
|
||||
|
||||
# Review
|
||||
python -m coinhunter review 12
|
||||
python -m coinhunter recap 12
|
||||
```
|
||||
|
||||
## Skill routing
|
||||
|
||||
When the user's request matches an available skill, ALWAYS invoke it using the Skill
|
||||
tool as your FIRST action. Do NOT answer directly, do NOT use other tools first.
|
||||
The skill has specialized workflows that produce better results than ad-hoc answers.
|
||||
|
||||
Key routing rules:
|
||||
- Product ideas, "is this worth building", brainstorming → invoke office-hours
|
||||
- Bugs, errors, "why is this broken", 500 errors → invoke investigate
|
||||
- Ship, deploy, push, create PR → invoke ship
|
||||
- QA, test the site, find bugs → invoke qa
|
||||
- Code review, check my diff → invoke review
|
||||
- Update docs after shipping → invoke document-release
|
||||
- Weekly retro → invoke retro
|
||||
- Design system, brand → invoke design-consultation
|
||||
- Visual audit, design polish → invoke design-review
|
||||
- Architecture review → invoke plan-eng-review
|
||||
- Save progress, checkpoint, resume → invoke checkpoint
|
||||
- Code quality, health check → invoke health
|
||||
- `AGENTS.md` in this repo is stale and describes a prior V1 architecture (commands/, smart executor, precheck, review engine). Do not rely on it.
|
||||
|
||||
Reference in New Issue
Block a user