关于 gmgn-holder-analysis
gmgn-holder-analysis 是面向代币持有者分析的技能,通过脚本生成持仓、交易、资金关联及风险评级报告。它区分数据缺失与低风险,并处理可交易流通量不足的情况。
主要功能
- 01分析代币持有者分布
- 02评估集中度与交易风险
- 03识别关联资金与开发者钱包
- 04区分未记录买入和零成本
- 05处理持有者数据缺失
- 06生成多维风险评级
适用场景
- 01检查代币持仓集中程度
- 02识别开发者关联钱包与资金
- 03评估持有者潜在抛售风险
- 04在数据不足时避免误判
MCP 相关
作为 Agent 技能,它使用 gmgn-cli 相关流程和本地分析脚本处理持有者数据;输入未说明其如何连接或管理 MCP 服务。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ gmgnai/ gmgn-skills --skill gmgn-holder-analysis安装后在 Claude Code 中输入/gmgn-holder-analysis确认已加载。
附带文件analyze.py
详细介绍
运行任何命令前:运行 gmgn-cli config --check。如果退出代码为 0,则照常继续。如果退出代码为 1,则运行 gmgn-cli config 并显示输出,然后运行 gmgn-cli config --apply <KEY> 应用密钥。如果遇到未知选项,请告知用户运行 npm install -g gmgn-cli。
重要:始终使用 gmgn-cli 命令。不要使用 curl、WebFetch,也不要访问 gmgn.ai。
当用户要求分析某个代币的持有者时,从其消息中提取 --chain 和 --address,然后运行下方的分析脚本。同时识别用户所用的语言:如果用户用中文书写,则将 LANG 设为 'zh';如果用英文书写,则设为 'en'(默认 'zh')。
分析脚本
运行以下命令,并将占位符替换为实际值:
python3 ~/.claude/skills/gmgn-holder-analysis/analyze.py <FILL_IN_TOKEN_ADDRESS> <FILL_IN_CHAIN> <FILL_IN_LANG>
- FILL_IN_CHAIN:Solana 地址使用
sol;EVM0x...地址使用auto,除非用户明确指定了链(bsc/eth/base) - FILL_IN_LANG:用户用中文书写时使用
zh,用英文书写时使用en,默认使用zh
输出规则
脚本运行完毕后,将完整的标准输出逐字粘贴到回复中——每一行、每个部分都不得省略或概括。不要在输出块之前或之后添加任何介绍、评论或总结。
字段参考
脚本打印的所有持有比例都是可交易流通量占比(1 - burn - DEX),而非总供应量占比。API 返回的 amount_percentage 是总供应量占比;脚本会重新计算。由于仅获取持有量排名前 100 的钱包,当这 100 个钱包未覆盖全部流通量时,流通量百分比为下限;页脚会报告实际覆盖率,并说明适用情形——覆盖率低于 99.5% 时为下限;前 100 个钱包覆盖全部流通量时为完整数值。
当 burn + DEX 留给可交易部分的供应量不足 2% 时(通常是迁移前的 Launchpad 代币),流通量分母会失效:所有 / float_share 都会将微量持有的钱包放大到两位数百分比或 100%。脚本会检测到这种情况,改为打印绝对代币数量和美元数值的横幅,并将评级设为 ⚪ 无法评估。
当 token holders 返回空列表时(代币已没有活跃持有者,或上游已停止为其编制索引),也会执行相同的抑制处理。所有百分比都会显示为 0.00%,所有阈值也都会通过,因此报告会错误地显示“✅ 正常 — 未发现明显的抛售风险”。脚本会改为打印无数据横幅,将每条“未发现 🟢”替换为 ⚪,并将评级设为 ⚪ 无法评估。“无数据”绝不会报告为“无风险”。
在这两种情况下,都不会打印任何流通量百分比——每项都显示为 n/a(无法评估),每个百分比标记都显示为 ⚪。仅附带说明并不足够:浮点数除以零会导致同一份报告中同时出现 hold 100.00% 和 hold 0.00%,读者如果略过横幅,就会将 Rat Trader 1 hold 100.00% 看成一项分析结果。钱包数量、代币数量、美元数值和市值仍会照常打印——它们不会经过 float_share 计算。按总供应量计算的百分比也仍会打印(burn、DEX、流通量占比本身以及代币质量分档),因为这些分母不受影响。
“零成本”必须有证据证明,不能根据买入计数缺失来推断
buy_tx_count_cur == 0 不意味着钱包免费获得了筹码。在 musebook(robinhood)上测得:38 个钱包显示 buy_tx_count_cur: 0 和 avg_cost: null,但其中 34 个有有限的 unrealized_pnl 比率(+2.7%、+76.5%、+546%)——没有成本基础就无法计算该比率;其中 32 个带有 fomo 前端标签,2 个带有 gmgn 标签,这正是活跃交易的痕迹,与收到空投恰恰相反。实际缺失的是该链上的买入交易索引,而 PnL 字段来自单独的计算,且已填充。
这个错误是按链系统性出现的,而不是按代币出现的。同一批次中,未买入部分占供应量的比例分别为:robinhood 27.0% 和 41.2%,arc 26.3%,sol 4.8%。 因此,20% 的空投警告阈值几乎会对每个 robinhood/arc 代币触发,而对 sol 代币则几乎从不触发——这是索引覆盖率的差异,而不是筹码结构的差异。把未填充字段当作风险结论,正是本技能所禁止的做法。
只有在完全不存在任何成本证据时,钱包才算零成本:
def has_cost_basis(h):
return (h.get('avg_cost') or 0) > 0 or h.get('unrealized_pnl') is not None
没有索引到买入计数、但有真实成本基础的钱包不会从报告中剔除——它们会单独显示一行中性说明:买入未记录 / Buy count unindexed,并列出其流通份额。上游没有索引到这些钱包的买入记录,这是事实,也会继续显示;但它不会触发零成本阈值。同一判断条件现在也适用于 钻石手 / Diamond 群体(其给出的理由是“从未付出成本的钱包没有成本需要承受”,而经证实的成本基础符合这一条件)、转入筹码未动 / Idle airdrop 一行(其“零成本”说明对这些钱包来说并不属实),以及 Top5 卖出风险分类(该分类曾将一个收益达 +6.6x 的钱包标记为“零成本空投 — 随时可以抛售”)。
已知局限:真正的空投钱包如果 unrealized_pnl 是相对于尘埃级成本计算出的巨大比率,这里会漏掉它。不会为此设置第二个比率阈值——目前没有经过测量的样本可用于校准。
代币自身的合约地址不是持有者钱包
上游会将它作为普通钱包返回——在 musebook(robinhood)上测得:addr_type: 0、0 笔买入、0 笔卖出、占总供应量的 15.01%、价值 $5.06M,并带有 fresh_wallet 标签。如果将其留在钱包群体中,它会同时污染 biggest、Top10/Top20、空投、新钱包、风险钱包和 Top5;单凭它自身就会触发 🔴 危险阈值,显示“最大钱包持有 16.30%——极度集中”。该代币上最大的真实钱包占供应量的 4.10%。同批次的对照项——JOLLY(robinhood)、SI(sol)、ARGUS(arc)——都没有此类记录,因此这是按代币出现的上游分类缺口,而不是链的惯例。
因此,脚本会将其从 normal 中单独划出,并在独立的一行中报告,按总供应量计算(合约自持 / Contract self-held),并为其设置单独的警告阈值:超过供应量的 10%。它不会从判断中剔除:合约持有的供应量一旦发生一笔释放交易,就会进入市场,因此必须继续显示,也仍计入评级。它被列为警告而非危险,是因为释放是一个可观察的前置步骤,不同于可以随意卖出的巨鲸;同时也没有更高的危险等级,因为目前只测量了一个样本,基于单一样本设置第二个阈值只会是猜测。
有意不从流通量分母中扣除它。销毁是永久性的,DEX 池本身就是市场,因此二者都无法抛售;自持供应量则可以抛售。从分母中将其移除,会抬高每个包含此记录的代币中其他所有钱包的占比,在修复一个问题的同时制造新的误报。
同一地址也会从开发者马甲映射中排除:筹码发回代币合约,或由代币合约支付的 Gas,都不算“转入内部钱包”。
持有者对象关键字段
| 字段 | 类型 | 含义 |
|---|---|---|
address | string | 钱包地址 |
balance | float | 当前代币余额 |
amount_percentage | float | 占总供应量的比例(0–1)。乘以 100 即为百分比。 |
buy_tx_count_cur | int | 创建以来的买入交易数。**并非每条链都会对此进行索引——此处为 0 并不能证明该钱包从未买入。**请参阅上文的成本基础部分。 |
usd_value | float | 当前持仓的美元价值 |
avg_cost | float | 每个代币的平均买入价格 |
unrealized_pnl | float | 未实现盈亏比率(0.5 = +50%) |
unrealized_profit | float | 未实现盈亏(美元) |
realized_profit | float | 已实现盈亏(美元) |
profit | float | 总盈亏(美元,已实现 + 未实现)。也是有效的 --order-by 字段。 |
sell_tx_count_cur | int | 代币创建以来的卖出交易数 |
sell_amount_percentage | float | 已卖出部分占总买入量的比例。用于判定是在累积还是分发。 |
sell_volume_cur | float | 代币创建以来卖出的美元交易量 |
sell_amount_cur | float | 代币创建以来卖出的代币数量 |
history_transfer_out_amount | float | 转出的代币数量(非卖出) |
history_transfer_out_income | float | 转出代币的美元价值 |
token_transfer_out | object | {address} — 转出的接收方。如果接收方本身位于前 100 名中,则用于检测开发者马甲钱包。 |
native_transfer | object | {from_address, amount, timestamp} — 钱包的资金来源。也是备用的马甲钱包检测方法:检查前 100 名持有者的 Gas 是否来自创建者。 |
name | string | 已知时显示的钱包名称 |
start_holding_at | int | 首次买入的 Unix 时间戳 |
addr_type | int | 0=普通钱包,1=销毁/无效地址,2=DEX/资金池 |
maker_token_tags | list | bundler、rat_trader、sniper、whale、top_holder、transfer_in、dev_team、creator |
tags | list | smart_degen、pump_smart、renowned、fresh_wallet、wash_trader、kol |
native_balance | string | 原生代币的原始余额。可能是十进制字符串——请用 float 而非 int 解析。分母仅在 sol 中为 1e9,在 bsc/eth/base 中为 1e18。 |
native_transfer | object | {from_address, amount, timestamp} — 钱包的资金来源。用于判断关联资金。 |
twitter_name | string | 已知时的 Twitter 用户名 |
已创建代币响应字段
| 字段 | 含义 |
|---|---|
inner_count | 尚未迁移的代币数量 |
open_count | 已迁移的代币数量 |
tokens[].market_cap | 当前市值(美元) |
tokens[].symbol | 代币符号 |
tokens[].is_open | true = 已迁移 |
creator_ath_info.ath_mc | 所有已创建代币的历史最高市值 |
creator_ath_info.ath_token | 达到历史最高值的代币地址 |
creator_ath_info.token_symbol | 达到历史最高值的代币符号 |
creator_ath_info.token_name | 达到历史最高值的代币名称 |
评级标准
以下所有阈值均为可交易流通量占比,与脚本一致。它们不能与 GMGN 自身的界面数据直接比较,后者显示的是占总供应量的比例——对于流动性池持有 56% 供应量的代币,同一钱包在这里显示的数值会高出 2.4 倍。
建议部分会打印所有触发的原因,而不只是第一个:⚠️ 谨慎参与评级按定义表示触发了两个或更多警告,因此只打印一条会让读者无法了解评级的依据。
入场时机压力(批次浮盈/出货)不会影响总体评级——它只影响各部分的显示。
| 评级(中文) | 评级(英文) | 表情符号 | 条件 |
|---|---|---|---|
| 无法评估 | Cannot Assess | ⚪ | 可交易流通量 <供应量的 2%,或上游返回的持有者数量为零(停用所有百分比规则;开发者马甲仍会升级为 🔴) |
| 不建议买 | Not Recommended | 🔴 | 满足任意一项:老鼠仓 >5% / 最大钱包 >10% / 开发者马甲 |
| 谨慎参与 | Caution | ⚠️ | 以下警告中 ≥2 项:开发者仍持有 >1% / 空投 >20% / 风险钱包 >35% / 关联钱包 >15% / 合约自持 >供应量的 10% | | 可轻仓 | Light Position | 🟡 | 恰好触发上述 1 项警告 | | 正常参与 | Normal | ✅ | 未触发上述任何警告 |
各项指标的标记阈值
| 指标 | 🔴 | 🟡 | 🟢 |
|---|---|---|---|
| 前 10 大持仓集中度 | >60% | >40% | ≤40% |
| 前 20 大持仓集中度 | >75% | >55% | ≤55% |
| 空投筹码(从未买入) | >25% | >10% | ≤10% |
| 风险钱包 | >35% | >15% | ≤15% |
| 关联资金 | >25% | >10% | ≤10% |
| 零余额钱包 | — | >10% | ≤10% |
钻石手的判断方向相反(比例越高越好),并使用独立的表情符号:✅ >60% / 🟡 >35% / ⚠️ ≤35%。
钻石手必须有成本基础(上文的 has_cost_basis)——从未支付过的持有者没有成本可供坚守,因此真正零成本的接收者会单独报告为“转入筹码未动 / Idle airdrop”,而不会计入钻石手。判断依据是成本基础,而不是 buy_tx_count_cur > 0:在未索引买入次数的链上,后者会漏掉大多数真正的钻石手(在 JOLLY 上测得:钱包数从 34 → 75,流通量占比从 21.1% → 55.7%)。
只要有任意一组是在 60s 内获得资金,无论规模大小,关联资金的标记至少会升级为 🟡——脚本化批量注资是结构性信号,而非规模信号。
筹码质量(页脚)
将观察到的钱包持有的筹码分为三个互斥类别(分母为 normal_pct,即基于总供应量,而非流通量):买入且无风险标签 / 零成本空投(依据上文的 has_cost_basis,而非缺少买入次数)/ 有风险标签。这些类别分别报告,而不合并为一个“健康筹码”数字,因为风险标签代表地址已被证实存在问题,而零成本空投只代表来源未知。
标题标记按优先顺序匹配:🔴 有风险标签 >30% · 🟢 干净筹码 ≥50% · 🟡 干净筹码 ≥30% · 🟡 零成本空投占非干净筹码 ≥80% · 否则为 🔴。因此,空投分发的代币会显示为 🟡 并注明其构成,而不会显示“健康筹码 0.0% 🔴”。
构成比例基于总供应量,因此即使流通量异常,三个百分比仍会显示;但当评级为 ⚪ 无法评估时,标题标记会中和为 ⚪(并附上筹码占供应量的比例),因为对尘埃级别的筹码给出 🔴/🟢 判定会与上方评级相矛盾。
支持的链
sol、bsc、base、eth、robinhood、arc、stable
Dev 查询采用双数据源
token holders --tag dev 是主要数据源,但在某些 launchpad 上会返回 {"list": []} —
在 robinhood 24 小时热门榜前 50 中的全部 5 个 bankr 代币上都观察到了这种情况,而同一条链上的
pons_v2 / longxyz 代币则会正常返回创建者。它也可能返回完全没有 creator 标签的行
(在 bsc 上的一个 flap 代币中观察到了这种情况)。无论哪种情况,整个 Dev 部分,包括 Dev 傀儡钱包
危险门槛,都会悄无声息地失效。
因此,如果没有返回带 creator 标签的行,就从 token info 的
dev.creator_address 中恢复创建者地址,并使用 dev.creator_token_balance 获取其余额。
只有在主要数据源失效时才会调用该接口,因此在标签正常工作的代币上不会产生额外开销。
token info 不包含 realized_profit 或 token_transfer_out,因此在备用路径中:
- 完全省略已实现利润数值——打印
$0会把未经测量的字段说成已测量 - 傀儡钱包判断门槛会切换判定方式:不再判断“Dev 的筹码流向了一个前 100 名钱包”,而是
检查任一前 100 名持有者的
native_transfer.from_address是否就是创建者,也就是 Dev 是否为该钱包支付了 Gas。命中时会报告为危险并列出钱包;未命中时则不会报告为安全,因为在已测代币中,只有 57% 的持有者包含该字段。
备注
balance >= 1的阈值可避免在识别 Dev 持仓时将尘埃余额误判为阳性- SOL 的
native_balance单位为 lamports(÷1e9);bsc/eth/base的单位为 wei(÷1e18)。arc/stable/robinhood的小数位数 尚未确认,因此买入力度部分会在这些链上报告“未评估”,而不会打印可能错误的换算数值。 - 持有者的买入力度需要实时原生代币价格,该价格通过对包装原生代币地址(
So111…1112/ WBNB / WETH / Base WETH)调用token info获取。该调用失败时,该部分 会退回原生单位,并且不打印 USD 数值。 total_supply通过普通钱包中balance / amount_percentage的中位数估算cur_price通过普通钱包中usd_value / balance的中位数估算- 入场 MC =
total_supply * avg_cost,并与每个 Top5 钱包的未实现 PnL 一同显示 - Top5 有 Twitter 名称时会显示该名称;否则采用
first4...last4格式 - 风险钱包小计按类别计算,可能超过去重后的总数;出现这种情况时,脚本会打印带有多个风险标签的钱包数量。
- 快速拉升后,
creator_ath_info.ath_mc可能落后于代币当前 MC(上游的ath_price曾被发现与price_24h相等)。脚本无法重新计算,因此当报告的 ATH 比当前 MC 低 5% 以上时,会在 数值旁打印过时警告,而不会将其呈现为 Dev 的峰值。