refactor: rewrite Coin Hunter as short-term trading framework with auto-trading architecture

This commit is contained in:
2026-04-16 03:03:25 +08:00
parent 73a3cb6952
commit a4ba9bb64e
5 changed files with 716 additions and 256 deletions

380
SKILL.md
View File

@@ -1,296 +1,164 @@
---
name: Coin Hunter
description: Hunt, triage, and compare speculative crypto coins — especially meme coins, 妖币-style runners, fake-hype pumps, and possible rug/scam setups. Use when a user wants to actively search for coins with breakout potential, rank a shortlist, ask whether a coin still has "妖性", or check whether a token looks late, fragile, manipulated, or likely to be a scam.
description: Hybrid short-term crypto trading system — combining mainstream coin scalping with meme-coin opportunistic rotation, backed by hourly review and continuous strategy iteration.
---
# Coin Hunter
## Overview
Use this skill to help a user search for and judge **high-volatility crypto setups** without pretending certainty.
Coin Hunter is a **short-term trading framework**, not just a meme-coin scanner.
Default buckets:
- **candidate runner** — has ingredients for further speculative expansion
- **watch-only / incomplete** — interesting, but not clean enough yet
- **late / overheated** — may still move, but entry quality is already poor
- **avoid / scam-risk** — liquidity, distribution, credibility, or structure is too weak
It operates on two tracks:
1. **Mainstream Short-Term (70%)**Trade liquid, high-volume coins (BTC, ETH, SOL, DOGE, PEPE, etc.) based on technical momentum, support/resistance, and market structure.
2. **Meme / 妖币 Rotation (30%)** — Opportunistically rotate into breakout meme coins when narrative heat, volume, and timing align.
Frame the work as **speculative pattern recognition**, not investment advice.
Core principle:
- **Profit maximization through concentration + discipline.**
- **妖币可遇不可求** — when a runner appears, capture it. When none exists, do not force trades; instead, scalp mainstream coins or sit in USDT.
- Every decision is logged, and every hour is reviewed for quality and parameter tuning.
## Core rule
## Portfolio-first rule
Judge a coin by **attention + liquidity + distribution + timing** first. Narrative matters, but only when it can attract and hold money.
Always check the user's actual portfolio state under `~/.coinhunter/` before giving trade advice or executing orders.
A technically weak project can still become a runner. A sophisticated-looking project can still be dead money.
Files to inspect:
- `positions.json`
- `accounts.json`
- `logs/decisions_YYYYMMDD.jsonl`
- `logs/trades_YYYYMMDD.jsonl`
- `reviews/review_YYYYMMDD_HHMMSS.json`
## Supported request types
Anchor all advice to the user's real balances, average costs, exchange, and current exposure.
Use this skill for four common modes:
- **single-coin triage** — "look at this coin"
- **active discovery** — "find me coins that could become 妖币"
- **shortlist ranking** — "which of these 5 is most interesting"
- **scam / rug check** — "is this coin just fake hype"
## Supported modes
If the request is broad, ask at most **one compact clarifying question**. Prefer:
- chain
- theme / narrative
- risk level
- whether the user accepts microcaps or wants only reasonably tradable names
1. **Single-coin triage** — analyze a specific holding (mainstream or meme).
2. **Active discovery** — scan for the best short-term opportunity across both mainstream and meme sectors.
3. **Execution** — run the auto-trader, evaluate whether to hold, sell, or rebalance.
4. **Review** — generate an hourly report on decision quality, PnL, and recommended parameter adjustments.
If no preference is given, default to: **liquid speculative candidates, not ultra-illiquid microcaps**.
## Scientific analysis checklist (mandatory before every trade decision)
Before executing or recommending any action, answer:
1. **Trend posture** — Is price above/below short-term MAs (1h/4h)?
2. **Volume-price fit** — Is volume expanding with the move or diverging?
3. **Key levels** — Where is the next support/resistance? How much room to run?
4. **Market context** — Is BTC/ETH supportive or contradictory?
5. **Opportunity cost** — Is holding current coin better than switching to new coin or sitting in USDT?
6. **Time window** — Is this a good entry/exit time (liquidity, session, news flow)?
Read `references/short-term-trading-framework.md` before every active decision pass.
## Workflow
### 1. Identify the mode
### Discovery & Scanning
1. **Mainstream scan** — Use `market_probe.py bybit-ticker` or ccxt for liquid coins.
- Look for: breakouts, volume spikes, S/R flips, trend alignment.
2. **Meme scan** — Use `web_search` + `dex-search` / `gecko-search` for narrative heat.
- Look for: accelerating attention, DEX flow, CEX listing rumors, social spread.
3. **Cross-compare** — Score the top 3-5 candidates against current holdings.
Decide whether the user wants:
- discovery
- triage
- comparison
- scam-check
### Execution
1. Read balances and positions.
2. Pull market data for holdings and candidates.
3. Run the 6-question scientific checklist.
4. Decide: **HOLD** / **SELL_ALL** / **REBALANCE** / **BUY**.
5. Execute via `smart_executor.py`.
6. Log the full decision context with `logger.py`.
Then bias the workflow accordingly.
### Review (every hour)
1. Run `review_engine.py` to analyze all decisions from the past hour.
2. Compare decision prices to current prices.
3. Flag patterns: missed runs, bad entries, over-trading, hesitation.
4. Output recommendations for parameter or blacklist adjustments.
5. Save the review report to `~/.coinhunter/reviews/`.
### 2. Choose the data path
## Auto-trading architecture
Use **structured market data first** when available. Use web search to discover names and collect context, not as the only source of truth.
| Component | Path | Purpose |
|-----------|------|---------|
| `smart_executor.py` | `~/.coinhunter/smart_executor.py` | Order execution layer (market buy/sell/rebalance) |
| `logger.py` | `~/.coinhunter/logger.py` | Records decisions, trades, and market snapshots |
| `review_engine.py` | `~/.coinhunter/review_engine.py` | Hourly quality review and optimization suggestions |
| `market_probe.py` | `~/.hermes/skills/coinhunter/scripts/market_probe.py` | Market data fetcher |
Preferred source order:
- **Bybit** for real-time-ish price, 24h turnover, and tradability on a major venue
- **DexScreener** for meme-coin pair discovery, DEX liquidity, and small-cap flow
- **Birdeye** for Solana token activity and confirmation
- **CoinGecko** for market-cap, rank, and metadata cross-check
- **web_search** for discovery, narratives, and scam-discussion context
### Execution schedule
- **Trade bot** — runs every 15-30 minutes via `cronjob`.
- **Review bot** — runs every 1-12 hours via `cronjob`, depending on how much manual oversight is needed.
Private user state must live outside the skill directory under `~/.coinhunter/`, not inside `skills/coinhunter/`.
Read `references/provider-playbook.md` when choosing which source to trust first.
Read `references/user-data-layout.md` when adding or updating personal accounts, positions, watchlists, or notes.
Use `scripts/market_probe.py` for deterministic provider lookups.
Use `scripts/init_user_state.py` to initialize the private user-data directory.
### Low-cost cron architecture
When model cost or quota is tight, do not let every cron run perform full analysis from scratch.
### 3. Discovery mode: build a candidate list
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.
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)
- per-position price/PnL moves beyond thresholds that widen for micro-capital / dust accounts and narrow during higher-volatility sessions
- top candidate leadership changes materially, but discount this signal when free USDT is below actionable exchange minimums
- BTC/ETH regime changes (hard trigger)
- a max staleness timer forces refresh, with longer refresh windows for micro accounts to avoid pointless re-analysis
4. In the cron prompt, if the injected context says `should_analyze=false`, respond with exactly `[SILENT]` and do not call tools.
5. After a triggered deep-analysis pass completes, acknowledge it from the agent (for example by running the precheck script with an `--ack` flag) so the trigger is cleared.
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>`
- store a `run_requested_at` marker in `~/.coinhunter/state/precheck_state.json` and clear it when the analysis acknowledges completion
When the user wants active search rather than analysis of a known ticker, use public web sources to build a shortlist.
This pattern preserves Telegram auto-delivery from Hermes cron while reducing model wakeups to trigger-only events.
Look for evidence of:
- rising attention
- listing or venue expansion
- narrative/theme alignment
- market-cap and liquidity context
- breakout discussion or unusual participation
### 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.
- Keep the Hermes trading cron job on a low-frequency fallback schedule (for example once daily at 05:00 local time) so the main execution path remains trigger-driven.
- Add a file lock around the external gate script so overlapping system-cron invocations cannot double-trigger.
- Rotate `~/.coinhunter/logs/external_gate.log` with `logrotate` (daily, keep ~14 compressed copies, `copytruncate`) and schedule the rotation a few minutes after the fallback Hermes cron run so they do not overlap.
Useful search patterns include:
- `<theme> meme coin trending`
- `<chain> meme coin watchlist`
- `new meme coin listed`
- `<coin> market cap liquidity`
- `<coin> holders tokenomics`
- `<coin> rug risk`
### 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.
2. **Exchange reconciliation** — before every run, pull real Binance balances and recent trades to sync `positions.json`. Do not trust local state alone.
3. **File locking + atomic writes**`positions.json` and `executions.json` are updated under a file lock and written to a temp file before atomic rename.
4. **Order precision validation** — read Binance `lotSize`, `stepSize`, and `minNotional` filters via ccxt before any order. Round quantities correctly and reject orders below minimums.
5. **Fee buffer** — keep ~2%-5% USDT unallocated so that slippage and fees do not cause "insufficient balance" rejections.
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.
Do not trust a single source or a single viral thread. Build the list first, then vet the names.
## Safety rules
- No leverage/futures when capital < $200.
- When capital < $50, concentrate into **1 position only**.
- Always leave 2%-5% USDT buffer for fees and slippage.
- Blacklist updates should be driven by review findings.
Read `references/search-workflow.md` for the detailed discovery flow.
## Position sizing
### 4. Triage mode: score the coin on six dimensions
Assess each coin qualitatively across these dimensions.
#### A. Narrative fit
Ask:
- Is the story attached to a live theme?
- Is the idea easy to repeat in one sentence?
- Does the symbol / meme / framing have social spread potential?
Strong examples:
- obvious meme identity
- attached to a live chain or hot sector
- easy cultural hook
Weak examples:
- vague utility story
- no memorable angle
- cold or stale narrative
#### B. Attention acceleration
Ask:
- Is visibility rising now?
- Is the coin spreading beyond its original niche?
- Are larger accounts, aggregators, or trading communities starting to notice it?
Treat **acceleration** as more important than absolute popularity.
#### C. Liquidity quality
Ask:
- Can a normal user realistically enter and exit?
- Is volume believable relative to market cap and attention?
- Are spreads or venue quality obviously problematic?
If the user can probably buy but may not be able to exit cleanly, score this harshly.
#### D. Distribution / holder risk
Ask:
- Is ownership too concentrated?
- Are deployer or team wallets still dangerous?
- Is there an obvious unlock or dump overhang?
Ugly distribution does not automatically kill a trade, but it makes the setup fragile.
#### E. Timing / chart state
Ask:
- Is it emerging from a base or already vertical?
- Has participation expanded recently?
- Do pullbacks hold, or do they collapse?
Prefer:
- fresh breakout from longer consolidation
- early or mid-stage expansion
- resilient retraces
Be cautious when:
- it already went parabolic
- volume fades after the first mania burst
- price action is mostly wick-and-dump behavior
#### F. Rug / scam risk
Check for:
- fake partnerships or fake listing claims
- unverifiable team paired with aggressive promotion
- suspicious contract / public warning signals
- impossible tokenomics promises
- unverified liquidity-lock claims
- nothing but shill posts and no independent discussion
One severe scam signal can outweigh several bullish ones.
Read `references/scam-signals.md` when the user specifically asks about rugs, scams, fake hype, manipulation, or exit-liquidity bait.
### 5. Classify the result
Use these buckets:
#### Candidate runner
Use when most are true:
- narrative is live
- attention is accelerating
- liquidity is usable
- timing is not obviously exhausted
- no fatal scam / exit-risk signal is present
#### Watch-only / incomplete
Use when:
- something is interesting, but evidence is incomplete
- narrative is decent but timing is unclear
- liquidity or distribution is acceptable but not clean
- it deserves monitoring more than action
#### Late / overheated
Use when:
- the move is already widely noticed
- chart is extended or near blow-off behavior
- upside may remain, but entry quality is poor
- new buyers are at risk of becoming exit liquidity
#### Avoid / scam-risk
Use when:
- liquidity quality is bad
- exit risk is high
- holder concentration is dangerous
- legitimacy claims are weak or fake
- the setup feels more fabricated than organic
## Provider execution patterns
### Known tradable coin
If the user gives a Bybit-listed ticker or asks for current price/tradability:
1. run `python3 scripts/market_probe.py bybit-ticker <SYMBOL>`
2. optionally run `python3 scripts/market_probe.py bybit-klines <SYMBOL> --interval 60 --limit 10`
3. cross-check with CoinGecko when market-cap context matters
### Meme / 妖币 discovery
If the user wants runners, meme coins, or small-cap candidates:
1. use `web_search` to gather names
2. run `python3 scripts/market_probe.py dex-search <name>` for the strongest candidates
3. if Solana, run Birdeye when API access is configured
4. use CoinGecko to verify market-cap and ranking
5. only use Bybit if the coin is also on a major CEX
### Birdeye requirement
`market_probe.py birdeye-token <address>` requires `BIRDEYE_API_KEY` in the environment. If it is not configured, say so briefly and continue with DexScreener + CoinGecko + web search.
### Private portfolio state
If the user wants account, position, watchlist, or thesis tracking for coinhunter:
1. initialize `~/.coinhunter/` with `python3 scripts/init_user_state.py`
2. store private data only there
3. never place personal holdings inside the skill folder
4. treat the skill folder as logic only, and the user-data directory as state only
| Total Capital | Strategy |
|---------------|----------|
| < $50 | Single-coin concentration (mainstream or meme) |
| $50 $200 | 60% mainstream + 40% meme, max 2 positions |
| > $200 | Up to 3 positions with stricter risk per position |
## Output style
Default to **compact, decision-first** answers.
### For live decisions
Concise Telegram-style report:
- Current holdings + live PnL
- Top 1-2 opportunities found
- Decision and exact reasoning
- Action confirmation (or [DRY RUN] note)
For a single coin, include:
- **Verdict**
- **Radar score** — use the 0-12 checklist when evidence is sufficient
- **Why it could run** — 2-4 bullets
- **Why it could fail** — 2-4 bullets
- **What confirms strength**
- **What kills the thesis**
- **Risk line** — clearly state this is speculative, not investment advice
For multiple coins:
1. rank the shortlist
2. mark each as candidate runner / watch-only / late / avoid
3. state the main attraction and main flaw for each
Prefer bullets, short sections, and hard judgments over long essays.
Use `references/output-templates.md` when you want a reusable answer skeleton.
## Practical heuristics
### Often bullish for speculative expansion
- the meme or story is instantly repeatable
- attention is accelerating, not just present
- volume expands with the move
- pullbacks are bought
- exchange accessibility improves
- more mainstream crypto accounts begin to mention it
### Often a sign it is late
- everyone is already talking about it
- the chart has been vertical for days
- promotion is everywhere after the main move already happened
- price keeps spiking while structure gets messier
### Often a sign to avoid
- no trustworthy liquidity information
- suspicious ownership concentration
- clearly manufactured chart behavior
- incoherent or constantly shifting explanation
- obviously botted or repetitive social activity
## What not to do
- Do not describe a coin as safe.
- Do not confuse a polished whitepaper with breakout potential.
- Do not imply expected returns.
- Do not recommend leverage.
- Do not ignore slippage and exit risk.
- Do not push microcaps on beginners unless the user explicitly asks for extreme risk.
## Optional deeper pass
If the user wants more depth, expand in this order:
1. narrative and timing
2. liquidity and market structure
3. holder / tokenomics risk
4. why it could become a runner
5. why it probably will not
6. watch triggers
### For hourly reviews
Use `references/review-template.md` structure:
- Decision quality breakdown
- Market context
- Strategy adjustments recommended
- Action items for next hour
## References
Read `references/provider-playbook.md` for source selection and provider roles.
Read `references/user-data-layout.md` for private state layout under `~/.coinhunter/`.
Read `references/radar-checklist.md` for a quick scoring framework.
Read `references/search-workflow.md` for active discovery.
Read `references/output-templates.md` for compact response structure.
Read `references/scam-signals.md` for sharper scam / fake-hype judgment.
Read `references/provider-playbook.md` for data source selection.
Read `references/user-data-layout.md` for private state management.
Read `references/short-term-trading-framework.md` for the hybrid trading framework.
Read `references/review-template.md` for hourly report formatting.
Read `references/scam-signals.md` when evaluating meme coins.

View File

@@ -0,0 +1,197 @@
# Automated Trading Guide for Coin Hunter
Complete guide for building and running a hands-off meme-coin trading bot using the Binance Spot API.
## Scope
This guide covers:
- Creating a safe Binance API key
- Installing dependencies (ccxt, pandas, numpy)
- Setting up `auto_trader.py`
- Testing in `DRY_RUN` mode
- Scheduling execution with `cronjob`
- Critical safety rules and troubleshooting
## What the bot does
1. **Monitors existing positions** for stop-loss (-7%) and take-profit (+15% / +30%) levels
2. **Scans the market** for new meme-coin candidates (price < $1, 24h volume > $1M, 24h change > 5%)
3. **Dynamically sizes orders** based on the user's total USDT balance and a configurable allocation percentage
4. **Runs on a schedule** (default every 15 minutes) and reports actions back via Telegram
## Architecture
```
~/.coinhunter/
├── auto_trader.py # Main trading logic
├── run_trader.sh # Shell wrapper (venv + env vars + logging)
├── check_api.py # Quick API connectivity validator
├── logs/trader.log # Execution logs
└── positions.json # Portfolio state (shared with coinhunter)
```
## Step 1: Binance API Key setup
1. Log in to Binance → **API Management**
2. Create a new API Key
3. Enable permissions:
-**Enable Reading**
-**Enable Spot & Margin Trading**
-**Disable Withdrawal** (security red line)
4. Add an **IP whitelist** (strongly recommended):
- Use the public IP of the machine that will run the bot
- This prevents key reuse if the credential is ever leaked
**Security reminder:** never paste API keys into chat messages. Write them directly into `~/.hermes/.env`.
## Step 2: Store credentials
Append to `~/.hermes/.env`:
```env
BINANCE_API_KEY=your_api_key_here
BINANCE_API_SECRET=your_api_secret_here
```
## Step 3: Install dependencies
The bot uses `ccxt` for exchange connectivity and `pandas`/`numpy` for data handling.
```bash
uv pip install ccxt pandas numpy
```
Or if using a venv:
```bash
source venv/bin/activate
pip install ccxt pandas numpy
```
## Step 4: Deploy the bot
Use `scripts/auto_trader.py` from the coinhunter skill as the template. Copy it into the user's `~/.coinhunter/` directory and customize:
- `MAX_POSITIONS` — max concurrent meme-coin positions (default 2)
- `CAPITAL_ALLOCATION_PCT` — fraction of total USDT to use (default 0.95; leave ~5% buffer for fees/slippage)
- `MIN_POSITION_USDT` — minimum single order size (default 50)
- `STOP_LOSS_PCT` / `TAKE_PROFIT_1_PCT` / `TAKE_PROFIT_2_PCT` — risk levels
Create `run_trader.sh`:
```bash
#!/bin/bash
set -e
cd "$(dirname "$0")"
python3 check_api.py
source /path/to/venv/bin/activate
export DRY_RUN=${DRY_RUN:-true}
python3 auto_trader.py >> logs/trader.log 2>&1
```
Make executable:
```bash
chmod +x run_trader.sh check_api.py
mkdir -p logs
```
## Step 5: Validate API connectivity
```bash
python3 check_api.py
```
Expected output: `✅ API 配置正常`
If this fails, the bot will exit immediately on each run.
## Step 6: Run a DRY_RUN test
```bash
DRY_RUN=true python3 auto_trader.py
```
Expected behavior:
- Reads current positions from `positions.json`
- Fetches live Binance prices
- Prints PnL for each position
- Prints `[DRY RUN]` instead of real trades
- Does **not** move money
Only proceed to live trading after at least one dry-run cycle completes without errors.
## Step 7: Schedule with cronjob
Use the `cronjob` tool to run the bot every 15 minutes:
```json
{
"action": "create",
"name": "Coin Hunter Auto Trader",
"schedule": "*/15 * * * *",
"deliver": "telegram",
"prompt": "Run the Coin Hunter automatic meme-coin trading bot.\n1. cd /home/<user>/.coinhunter\n2. ./run_trader.sh\n3. Summarize actions and report back."
}
```
## Step 8: Switch to live trading
Once DRY_RUN validation succeeds and the user confirms:
1. Edit `run_trader.sh`
2. Change `DRY_RUN=${DRY_RUN:-true}` to `DRY_RUN=${DRY_RUN:-false}`
3. The next cron run will execute real orders
**You must always obtain explicit user confirmation before enabling live trading.**
## Key safety rules
1. **Never enable Withdrawal permission** on the API key.
2. **Always bind an IP whitelist** if possible.
3. **Never accept API keys in plaintext chat.** Ask the user to write them into `~/.hermes/.env`.
4. **Do not set allocation to exactly 100%.** Leave at least 35% buffer for fees and slippage.
5. **Start with DRY_RUN.** Run at least one full cycle before going live.
6. **Check the account balance first.** If USDT is 0 (or held in Earn/Margin/Futures), the bot cannot trade.
7. **Educate the user about risks.** Automated bots can and will lose money during flash crashes, API errors, or black-swan events.
## Common pitfalls
### Ticker symbol mismatch
ccxt returns tickers with a slash (e.g., `PENGU/USDT`), but `positions.json` may store symbols without a slash (`PENGUUSDT`). If the bot looks up `tickers.get("PENGUUSDT")`, it will get `None` and silently skip stop-loss/take-profit checks.
**Fix:** normalize symbols before lookup:
```python
sym_ccxt = sym.replace("USDT", "/USDT") if "/" not in sym else sym
ticker = tickers.get(sym_ccxt)
```
### .env file is protected
The `patch` tool may reject edits to `~/.hermes/.env`. Use terminal redirection instead:
```bash
cat >> ~/.hermes/.env << 'EOF'
BINANCE_API_KEY=xxx
BINANCE_API_SECRET=yyy
EOF
```
### Zero balance surprises
The bot reads **Spot free balance**. If the user holds USDT in:
- Flexible Savings / Earn
- Margin account
- Futures wallet
- Another sub-account
…it will see $0 and fail to open new positions. Ask the user to transfer funds to Spot before going live.
## Customization ideas
- **Chain bias:** restrict candidate scanning to Solana-only or Base-only by filtering `cand["base"]` or integrating DexScreener chain filters.
- **Social signal integration:** add a Twitter/X sentiment check before opening a position.
- **Tiered stops:** replace fixed -7% with trailing stops using recent ATR or swing lows.
- **Blacklist expansion:** add recently rugged tickers to `BLACKLIST` based on on-chain data.

View File

@@ -0,0 +1,40 @@
# Review Report Template
## Header
- Review Period: [Start] — [End]
- Total Decisions: N
- Total Trades Executed: N
- Portfolio Value Change: +X% / -X%
## Decision Quality Breakdown
### 1. Hold Decisions
- Count: N
- Outcome: [mostly correct / neutral / mostly wrong]
- Key Insight: …
### 2. Sell Decisions
- Count: N
- Good exits (avoided further drop): N
- Missed runs (sold too early): N
- Avg opportunity cost of early exits: X%
### 3. Buy / Rebalance Decisions
- Count: N
- Profitable entries: N
- Losing entries: N
- Avg estimated PnL: X%
## Market Context During Period
- BTC trend: [up / down / sideways]
- Dominant narrative: …
- Liquidity condition: [high / normal / low]
## Strategy Adjustments Recommended
1.
2.
3.
## Action Items for Next Hour
- [ ]
- [ ]

View File

@@ -0,0 +1,78 @@
# Short-Term Trading Framework
## Philosophy
不要只狩猎妖币。短线复利的核心是**在高确率/高赔付比的机会上重仓,在不确定时观望**。
妖币是可遇不可求的赚钱机会,遇到了不要错过,没遇到也不要强求。当市场缺乏明确的超短线热点时,主流币的短线波动率交易往往更稳定。
---
## Strategy Mix
### 1. Mainstream Short-Term (70% of focus)
**Target coins:** BTC, ETH, SOL, BNB, DOGE, PEPE, WIF, BONK 等 Binance 高流动性币种
**Entry triggers:**
- 突破关键阻力/支撑位,并且放量
- 1h / 4h 级别出现明确的趋势转折信号
- 超卖/超买指标出现极端值且开始回归
- 量价齐升Volume 放大 + 价格突破)
**Exit triggers:**
- 达到预设盈亏目标(主流币 +8% 至 +15%
- 趋势转弱信号(量缩价跌、失守关键支撑)
- 出现更好的机会成本(换仓)
**Risk management:**
- 单次下注不超过总资产的 50%
- 主流币硬止损放宽至 -5% 至 -8%
- 使用支撑阻力作为活止损,不用固定百分比
### 2. Meme / 妖币 Rotation (30% of focus)
**Target coins:** 新兴 meme、热点小币
**Entry triggers:**
- 社交媒体关注度快速上升
- 24h 成交量 > $1M
- 币安可交易(确保能进能出)
- 故事/narrative 简单易传播
**Exit triggers:**
- 涨幅过快(+50% in 24h且量缩
- 舆论出现转凇信号
- 新币出现更强势代替
---
## Scientific Analysis Checklist
每次决策前,必须回答以下问题:
1. **趋势态势**价格在短期均线1h/4h MA的上方还是下方
2. **量能配合**:最近几个 K 线的成交量是否配合价格走势?
3. **关键位置**:下一个支撑和阻力在哪里?空间有多大?
4. **市场情绪**大盘BTC/ETH是否配合还是独立行情
5. **机会成本**:持有现币 vs 换到新币 vs 持有现金,三者中谁的风险收益比最优?
6. **时间窗口**:现在是否是合适的入市/出市时间点?(注意交易所交易时间段的流动性变化)
---
## Position Sizing
根据总资产动态调整:
- 当总资产 < $50**单币重仓**,放弃多元化
- 当总资产 $50-$200主流币 60% + 妖币 40%
- 当总资产 > $200可考虑 3 个币的轮动
不论资金大小,都要留出至少 2%-5% 的 USDT 缓冲以应对手续费和滑点。
---
## Continuous Improvement
每小时复盘一次,重点关注:
- 是否有连续出现同类型的决策失误
- 是否过于频繁交易(摩擦成本过高)
- 是否在明显的指标背离时仍然入市
- 新闻/市场视角是否需要更新到黑名单或基准条件中

277
scripts/auto_trader.py Normal file
View File

@@ -0,0 +1,277 @@
#!/usr/bin/env python3
"""
Coin Hunter Auto Trader Template
全自动妖币猎人 + 币安执行器
运行前请在 ~/.hermes/.env 配置:
BINANCE_API_KEY=你的API_KEY
BINANCE_API_SECRET=你的API_SECRET
首次运行必须先用 DRY_RUN=true 测试逻辑!
"""
import json
import os
import sys
from datetime import datetime, timezone
from pathlib import Path
import ccxt
# ============== 配置 ==============
COINS_DIR = Path.home() / ".coinhunter"
POSITIONS_FILE = COINS_DIR / "positions.json"
ENV_FILE = Path.home() / ".hermes" / ".env"
# 风控参数
DRY_RUN = os.getenv("DRY_RUN", "true").lower() == "true" # 默认测试模式
MAX_POSITIONS = 2 # 最大同时持仓数
# 资金配置(根据总资产动态计算)
CAPITAL_ALLOCATION_PCT = 0.95 # 用总资产95%玩这个策略留95%缓冲给手续费和滑点)
MIN_POSITION_USDT = 50 # 单次最小下单金额(避免过小)
MIN_VOLUME_24H = 1_000_000 # 最小24h成交额 ($)
MIN_PRICE_CHANGE_24H = 0.05 # 最小涨幅 5%
MAX_PRICE = 1.0 # 只玩低价币meme特征
STOP_LOSS_PCT = -0.07 # 止损 -7%
TAKE_PROFIT_1_PCT = 0.15 # 止盈1 +15%
TAKE_PROFIT_2_PCT = 0.30 # 止盈2 +30%
BLACKLIST = {"USDC", "BUSD", "TUSD", "FDUSD", "USTC", "PAXG", "XRP", "ETH", "BTC"}
# ============== 工具函数 ==============
def log(msg: str):
print(f"[{datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S')} UTC] {msg}")
def load_positions() -> list:
if POSITIONS_FILE.exists():
return json.loads(POSITIONS_FILE.read_text(encoding="utf-8")).get("positions", [])
return []
def save_positions(positions: list):
COINS_DIR.mkdir(parents=True, exist_ok=True)
POSITIONS_FILE.write_text(json.dumps({"positions": positions}, indent=2, ensure_ascii=False), encoding="utf-8")
def load_env():
if ENV_FILE.exists():
for line in ENV_FILE.read_text(encoding="utf-8").splitlines():
line = line.strip()
if line and not line.startswith("#") and "=" in line:
key, val = line.split("=", 1)
os.environ.setdefault(key.strip(), val.strip())
def calculate_position_size(total_usdt: float, available_usdt: float, open_slots: int) -> float:
"""
根据总资产动态计算每次下单金额。
逻辑:先确定策略总上限,再按剩余开仓位均分。
"""
strategy_cap = total_usdt * CAPITAL_ALLOCATION_PCT
used_in_strategy = max(0, strategy_cap - available_usdt)
remaining_strategy_cap = max(0, strategy_cap - used_in_strategy)
if open_slots <= 0 or remaining_strategy_cap < MIN_POSITION_USDT:
return 0
size = remaining_strategy_cap / open_slots
size = min(size, available_usdt)
size = max(0, round(size, 2))
return size if size >= MIN_POSITION_USDT else 0
# ============== 币安客户端 ==============
class BinanceTrader:
def __init__(self):
api_key = os.getenv("BINANCE_API_KEY")
secret = os.getenv("BINANCE_API_SECRET")
if not api_key or not secret:
raise RuntimeError("缺少 BINANCE_API_KEY 或 BINANCE_API_SECRET请配置 ~/.hermes/.env")
self.exchange = ccxt.binance({
"apiKey": api_key,
"secret": secret,
"options": {"defaultType": "spot"},
"enableRateLimit": True,
})
self.exchange.load_markets()
def get_balance(self, asset: str = "USDT") -> float:
bal = self.exchange.fetch_balance()["free"].get(asset, 0)
return float(bal)
def fetch_tickers(self) -> dict:
return self.exchange.fetch_tickers()
def create_market_buy_order(self, symbol: str, amount_usdt: float):
if DRY_RUN:
log(f"[DRY RUN] 模拟买入 {symbol},金额 ${amount_usdt}")
return {"id": "dry-run-buy", "price": None, "amount": amount_usdt}
ticker = self.exchange.fetch_ticker(symbol)
price = float(ticker["last"])
qty = amount_usdt / price
order = self.exchange.create_market_buy_order(symbol, qty)
log(f"✅ 买入 {symbol} | 数量 {qty:.4f} | 价格 ~${price}")
return order
def create_market_sell_order(self, symbol: str, qty: float):
if DRY_RUN:
log(f"[DRY RUN] 模拟卖出 {symbol},数量 {qty}")
return {"id": "dry-run-sell"}
order = self.exchange.create_market_sell_order(symbol, qty)
log(f"✅ 卖出 {symbol} | 数量 {qty:.4f}")
return order
# ============== 选币引擎 ==============
class CoinPicker:
def __init__(self, exchange: ccxt.binance):
self.exchange = exchange
def scan(self) -> list:
tickers = self.exchange.fetch_tickers()
candidates = []
for symbol, t in tickers.items():
if not symbol.endswith("/USDT"):
continue
base = symbol.replace("/USDT", "")
if base in BLACKLIST:
continue
price = float(t["last"] or 0)
change = float(t.get("percentage", 0)) / 100
volume = float(t.get("quoteVolume", 0))
if price <= 0 or price > MAX_PRICE:
continue
if volume < MIN_VOLUME_24H:
continue
if change < MIN_PRICE_CHANGE_24H:
continue
score = change * (volume / MIN_VOLUME_24H)
candidates.append({
"symbol": symbol,
"base": base,
"price": price,
"change_24h": change,
"volume_24h": volume,
"score": score,
})
candidates.sort(key=lambda x: x["score"], reverse=True)
return candidates[:5]
# ============== 主控制器 ==============
def run_cycle():
load_env()
trader = BinanceTrader()
picker = CoinPicker(trader.exchange)
positions = load_positions()
log(f"当前持仓数: {len(positions)} | 最大允许: {MAX_POSITIONS} | DRY_RUN={DRY_RUN}")
# 1. 检查现有持仓(止盈止损)
tickers = trader.fetch_tickers()
new_positions = []
for pos in positions:
sym = pos["symbol"]
qty = float(pos["quantity"])
cost = float(pos["avg_cost"])
# ccxt tickers 使用 slash 格式,如 PENGU/USDT
sym_ccxt = sym.replace("USDT", "/USDT") if "/" not in sym else sym
ticker = tickers.get(sym_ccxt)
if not ticker:
new_positions.append(pos)
continue
price = float(ticker["last"])
pnl_pct = (price - cost) / cost
log(f"监控 {sym} | 现价 ${price:.8f} | 成本 ${cost:.8f} | 盈亏 {pnl_pct:+.2%}")
action = None
if pnl_pct <= STOP_LOSS_PCT:
action = "STOP_LOSS"
elif pnl_pct >= TAKE_PROFIT_2_PCT:
action = "TAKE_PROFIT_2"
elif pnl_pct >= TAKE_PROFIT_1_PCT:
sold_pct = float(pos.get("take_profit_1_sold_pct", 0))
if sold_pct == 0:
action = "TAKE_PROFIT_1"
if action == "STOP_LOSS":
trader.create_market_sell_order(sym, qty)
log(f"🛑 {sym} 触发止损,全部清仓")
continue
if action == "TAKE_PROFIT_1":
sell_qty = qty * 0.5
trader.create_market_sell_order(sym, sell_qty)
pos["quantity"] = qty - sell_qty
pos["take_profit_1_sold_pct"] = 50
pos["updated_at"] = datetime.now(timezone.utc).isoformat()
log(f"🎯 {sym} 触发止盈1卖出50%,剩余 {pos['quantity']:.4f}")
new_positions.append(pos)
continue
if action == "TAKE_PROFIT_2":
trader.create_market_sell_order(sym, float(pos["quantity"]))
log(f"🚀 {sym} 触发止盈2全部清仓")
continue
new_positions.append(pos)
# 2. 开新仓
if len(new_positions) < MAX_POSITIONS:
candidates = picker.scan()
held_bases = {p["base_asset"] for p in new_positions}
total_usdt = trader.get_balance("USDT")
available_usdt = total_usdt
open_slots = MAX_POSITIONS - len(new_positions)
position_size = calculate_position_size(total_usdt, available_usdt, open_slots)
log(f"总资产 USDT: ${total_usdt:.2f} | 策略上限({CAPITAL_ALLOCATION_PCT:.0%}): ${total_usdt*CAPITAL_ALLOCATION_PCT:.2f} | 每仓建议金额: ${position_size:.2f}")
for cand in candidates:
if len(new_positions) >= MAX_POSITIONS:
break
base = cand["base"]
if base in held_bases:
continue
if position_size <= 0:
log("策略资金已用完或余额不足,停止开新仓")
break
symbol = cand["symbol"]
order = trader.create_market_buy_order(symbol, position_size)
avg_price = float(order.get("price") or cand["price"])
qty = position_size / avg_price if avg_price else 0
new_positions.append({
"account_id": "binance-main",
"symbol": symbol.replace("/", ""),
"base_asset": base,
"quote_asset": "USDT",
"market_type": "spot",
"quantity": qty,
"avg_cost": avg_price,
"opened_at": datetime.now(timezone.utc).isoformat(),
"updated_at": datetime.now(timezone.utc).isoformat(),
"note": "Auto-trader entry",
})
held_bases.add(base)
available_usdt -= position_size
position_size = calculate_position_size(total_usdt, available_usdt, MAX_POSITIONS - len(new_positions))
log(f"📈 新开仓 {symbol} | 买入价 ${avg_price:.8f} | 数量 {qty:.2f}")
save_positions(new_positions)
log("周期结束,持仓已保存")
if __name__ == "__main__":
try:
run_cycle()
except Exception as e:
log(f"❌ 错误: {e}")
sys.exit(1)