diff --git a/SKILL.md b/SKILL.md index 58685b7..09eebbe 100644 --- a/SKILL.md +++ b/SKILL.md @@ -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 ` + - 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: -- ` meme coin trending` -- ` meme coin watchlist` -- `new meme coin listed` -- ` market cap liquidity` -- ` holders tokenomics` -- ` 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 ` -2. optionally run `python3 scripts/market_probe.py bybit-klines --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 ` 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
` 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. diff --git a/references/auto-trading-guide.md b/references/auto-trading-guide.md new file mode 100644 index 0000000..bd0dc5a --- /dev/null +++ b/references/auto-trading-guide.md @@ -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//.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 3–5% 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. diff --git a/references/review-template.md b/references/review-template.md new file mode 100644 index 0000000..02e5c3b --- /dev/null +++ b/references/review-template.md @@ -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 +- [ ] … +- [ ] … diff --git a/references/short-term-trading-framework.md b/references/short-term-trading-framework.md new file mode 100644 index 0000000..0dd8b44 --- /dev/null +++ b/references/short-term-trading-framework.md @@ -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 + +每小时复盘一次,重点关注: +- 是否有连续出现同类型的决策失误 +- 是否过于频繁交易(摩擦成本过高) +- 是否在明显的指标背离时仍然入市 +- 新闻/市场视角是否需要更新到黑名单或基准条件中 diff --git a/scripts/auto_trader.py b/scripts/auto_trader.py new file mode 100644 index 0000000..707ddff --- /dev/null +++ b/scripts/auto_trader.py @@ -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)