description:A short trading portrait of ONE wallet address — a single style tag (磨损户 / P小将 / 印钞机 … plus a speed subtitle), one sentence recapping its record and one sentence of next-step advice, for 1D / 7D / 30D / 全部, voiced 你 for the user's own wallet and 他 for anyone else's; SOL and all 8 EVM chains, chain auto-detected for a 0x address; can render it as a page. USE WHEN a wallet address comes with a request for a brief recap or for what to change — 「帮我复盘一下这个钱包」, 「一句话总结他的战绩」, 「我的打法有什么问题」, 「我钱包下一步该怎么打」, 「交易画像」, 「钱包风格加建议,简短点」, "sum up this wallet in one line". NOT FOR — a bare address, 「能不能跟」 or 「跟着他买我能吃到吗」 (gmgn-wallet-analysis); the full tag-and-badge breakdown or 「是不是机器人」 (gmgn-wallet-style); scores or copy-trade backtests (gmgn-wallet-score); a creator's launches (gmgn-dev-score); current holdings (gmgn-portfolio); a token address or a buy (gmgn-contract-dd, gmgn-token-buy). TIE-BREAK — 打法 / 风格 / 战绩 paired with 问题, 建议, 复盘 or 一句话 routes here; asked alone, they go to the skills above.
**BEFORE RUNNING ANY COMMAND: Run `gmgn-cli config --check`. If exit code is 0, proceed. If 1, run `gmgn-cli config`, show the output, and once the user sends the key run `gmgn-cli config --apply <KEY>`. If the option is unknown, tell the user to run `npm install -g gmgn-cli`.**
**Always use `gmgn-cli` for data. Never WebFetch, curl, or browse gmgn.ai — the wallet page needs login and renders dynamically.**
This skill is a single file on purpose: there is no bundled script. You pull the data with
`gmgn-cli`, compute the numbers below yourself (a throwaway `jq` or `python3 -c` over the saved
responses is fine and usually more accurate than reading 300 rows by eye), apply the rules, and
fill the fixed sentence templates. Follow the rules and templates exactly — they are what makes
two runs on the same wallet say the same thing.
## What this skill produces
Three lines, nothing more:
```
⚙️ 全自动P机 · ⚡ 秒杀流 (7D)
一句话复盘:你近 7 天赚了 $41.9K,止损干脆,但手续费吃掉了 78% 的利润。
下一步:少做持仓不到 1 分钟的单子(这部分在亏钱),持仓 1–30 分钟的单子收益率有 17%。
```
- **Tag**: one title from the closed 20-cell grid plus a speed subtitle. No badges.
- **一句话复盘**: how much it made or lost in the period, the single best strength, the single
biggest problem.
- **下一步** (own wallet) / **参考建议** (someone else's): the single most actionable fix.
This shape is deliberate. It is designed for a small slot on an already number-heavy wallet
page, where dense columns, badge rows, KPI lines or a detail popover read as noise next to the
page's own numbers. Evaluate every rule, but let only the top strength, the top problem and the
top fix reach the output. Don't add lines, badges or numbers unless the user asks.
## Step 0 — Validate the input before any command
The address and chain go straight into shell commands, so check them first. Never
"fix up" a string to make it pass.
- **Chain** must be one of `sol bsc base eth arbitrum hyperevm robinhood arc stable`. A base58
address is `sol`. A `0x…` address could be on any of the eight EVM chains: if the user named
one, use it; otherwise find it with the probe in Step 0a.
- **Address**: EVM must match `^0x[0-9a-fA-F]{40}$`. Solana must match
`^[1-9A-HJ-NP-Za-km-z]{32,44}$`. Anything else (spaces, quotes, `;`, `$`, a leading `-`) → say
it isn't a valid wallet address and stop.
- 「CA」/「合约」/「代币」/ "token" / "contract" in the message → the user probably means a token.
Ask which they want before running.
- Several addresses and no indication which → ask. Only a name or symbol → ask for the address.
- Pass the validated address as its own argument, and quote it in the shell.
### Step 0a — Find the chain for a 0x address (only when the user didn't name one)
The same `0x` address exists on every EVM chain, and many wallets trade on only one of them.
Guessing BSC and reporting 「没有交易」 would be wrong for a Base or ETH trader, so probe first:
1. Run `gmgn-cli portfolio stats --chain <c> --wallet W --period 30d --raw` for **all eight EVM
chains** (bsc, base, eth, arbitrum, hyperevm, robinhood, arc, stable), one after another, and
take `buy` + `sell` from each.
2. Use the chain with the most 30D trades. If none has any, continue on `bsc` so the
token-contract check in Step 2 can tell a contract or a transfer-only address from a wallet.
3. If a second chain also has ≥ 20 % of the winner's trades, add one line after the three lines:
「他在 {chain} 上也有交易,这里按 {chosen} 统计。」
Probe all eight, not the popular ones first. In a test of nine active wallets, several traded
mainly on Robinhood or Arc while also showing a few hundred trades on BSC or Base: one had 5,227
trades on BSC and 24,691 on Robinhood. Stopping at the first chain with trades would have
profiled the wrong book.
Each probe is one call. Stop probing on a rate limit, and use the best chain found so far if
any trades were seen. A probe response is also the 30D stats for that chain, so reuse it rather
than asking for it again in Step 2. Name the chain in the reply's title line when it wasn't
`start_holding_at`, and `history_total_sells` > 0. Hold = end − start, realized =
`realized_profit`, cost = `history_bought_cost`.
- **Fallback, if fewer than 30 such rows**: from activity, per token that has both buys and
sells. Hold = last sell − first buy, realized = Σ(`cost_usd`−`buy_cost_usd`) over sells,
cost = Σ`cost_usd` over buys.
- **If still fewer than 30 positions**, skip the split.
Put positions into four groups: 「不到 1 分钟」 (≤60s), 「1–30 分钟」 (≤30 min), 「30 分钟到 6 小时」
(≤6 h), 「超过 6 小时」. For each group compute n, share of positions, and ROI = Σrealized ÷
Σcost.
- **W** = the group with the largest share.
- **B** = among the other groups with n ≥ 10, the one with the highest ROI.
- The split **fires** only if W's share is ≥40%, W's ROI is <5%, B's ROI is ≥15%, B's ROI is
≥ 5 × max(W's ROI, 0.001), and B's realized total is >0.
Choose by ROI and count, never by dollar totals. `holdings` P&L is cumulative per token, so a
few long-held large caps can dominate the dollars and point at the wrong group.
### 3e. Trading discipline (from holdings only; the same for every period)
Use the same closed positions as 3d, **from holdings only**. The activity fallback is too thin
for these, so if holdings gave fewer than 30 closed positions, skip all four. Winners have
`realized_profit` > 0, losers < 0, and hold = `end_holding_at`−`start_holding_at`.
| id | rule | fires when |
|---|---|---|
| hold_losers (A) | losers held longer than winners | ≥10 winners and ≥10 losers ∧ median loser hold ≥ 2 × median winner hold |
| size_losers (B) | losers sized bigger than winners | ≥10 winners and ≥10 losers ∧ median loser ticket ≥ 1.5 × median winner ticket, where ticket = `history_bought_cost` ÷ `history_total_buys` |
| bad_adds (C) | added-to positions did worse | ≥10 positions with `history_total_buys` ≥ 3 and ≥10 with exactly 1 ∧ ROI(added) ≤ ROI(single) − 10 percentage points; ROI = Σrealized ÷ Σ`history_bought_cost` |
| bag_hold (D) | deep losers left open | open positions (`end_holding_at` = 0, `balance` > 0) with `unrealized_profit_pnl` ≤ −0.5 **and**`history_bought_cost` ≥ $50 number at least 3 |
B must use the per-buy ticket, never `history_bought_cost` itself. That field is cumulative
volume: a tokenized stock traded hundreds of times shows $248K of "cost" on a $75 loss, and the
mean over such rows made B fire on six of six test wallets that in fact sized every buy the same.
Use the median for the same reason.
The $50 floor in D keeps dust out: a wallet that snipes hundreds of tiny launches is left
holding dozens of worthless crumbs, which says nothing about its loss-cutting.
Hold times in sentences: <60s → `N 秒`, <1h → `N 分钟`, <1d → `X.X 小时`, otherwise `X.X 天`.
## Step 4 — The tag
The tag rules below are the same as `freq_level` / `pnl_level` / `style_title` / `style_speed` in
`gmgn-wallet-analysis/analyze.py` (and `gmgn-wallet-style`), so a wallet gets the same title
whichever skill the question lands on. The single deliberate difference is the L4 净盈 line
(see below). If you change a threshold here, change it there too.
**Too few tokens → no reading.** If the period's `tn` is below 5 (for 1D and 全部, use the 7D
`tn`), there is no tag, recap or next step for that period. Output 「{period} 交易太少(不足 5 个币),
暂不给结论」 instead, the same "no read" the production dossier gives a sub-5-token wallet.
| net_loss | realized < 0 | (none — the head already says 亏了) |
| decline | the previous window's ROI > 0 ∧ this ROI < 0.75 × it (1D vs 7D, 7D vs 30D, 30D vs 全部; 全部 has none) | vs 7D / 30D → 收益率比 7D 在走弱 / 收益率比 30D 在走弱 (short label, never 近 30 天) · vs 全部 → 收益率比历史整体在走弱 |
| hold_losers | 亏的单拿得比赚的单久(中位 {loser hold} vs {winner hold}),止损要和止盈一样快。 | 他亏的单拿得比赚的单久(中位 {loser hold} vs {winner hold}),跟的话亏损要自己先走。 |
| bad_adds | single ROI ≥ 0 → 补过仓的币收益率 {added ROI},只买一次的有 {single ROI} · single ROI < 0 → 补过仓的币亏得更多({added ROI} vs 只买一次的 {single ROI}); then `,别在走势不对的盘上补仓。` | same two cases with 他补过仓的币…; then `,他补仓的那些别跟。` |