liquidity-analysis について
Solana トークンの DEX プールを分析するスキルです。深度、スリッページ、プール構成から約定と退出のリスクを評価し、スコアリングやリスク検出のスクリプトを備えています。
主な機能
- 01トークンの DEX プールを検索
- 02流動性の深度とスリッページを測定
- 03集中流動性とプール構成を評価
- 04流動性リスクの兆候を検出
- 05スコアとポジション上限を算出
活用シーン
- 01取引前に売買の実行可能性を確認
- 02DEX プール間の流動性を比較
- 03推定スリッページからポジション上限を設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ agiprolabs/ claude-trading-skills --skill liquidity-analysisインストール後、Claude Code で/liquidity-analysisを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/data_sources.mdpool_types.mdslippage_curves.mdscripts/analyze_liquidity.pypool_comparison.py詳細
流動性分析 — Solana トークンの DEX 深度評価
流動性分析では、取引のたびに次の3つの重要な問いに答えます。妥当な価格で取引に入れますか? 必要なときに取引から退出できますか? このプールは安全ですか? 分析しなければ、過度なスリッページ、退出の失敗、ラグプルのリスクがあります。
流動性分析が重要な理由
ポジションサイズ:最大ポジションサイズは、利用可能な流動性によって制限されます。TVL が $20K のプールで $10K のポジションを取ると、価格が大きく動きます。目安として、スリッページを1%未満に抑えるには、取引サイズをプールの深度の2%未満にしてください。
執行コスト:スリッページは直接的なコストです。5 SOL の買いで、スリッページが0.3%の場合と3%の場合の差は、エントリーとエグジットのたびに実際の損失となります。
ラグリスクの検出:流動性が薄いこと、プールが1つしかないこと、LP トークンがロックされていないこと、新しく作成されたプールは警告サインです。流動性分析を行えば、取引に入る前にこれらを検出できます。
エグジット計画:エントリー時の流動性とエグジット時の流動性は異なる場合があります。LP がロックされておらず、1つのウォレットが所有している場合、いつでも引き出される可能性があります。
主な概念
ロックされた合計価値(TVL)
プールに預け入れられた資産の合計価値です。100 SOL と、1枚あたり $0.01 の 1M TOKEN がある SOL/TOKEN プールの場合、TVL = 100 * SOL_price + 1M * $0.01 です。TVL だけでは不十分です。現在の価格帯における深度を確認する必要があります。
流動性深度
価格を X% 動かす前に、どれだけの量を取引できるかを示します。定積 AMM では、深度は均一です。集中流動性(CLMM)では、深度は価格帯によって変わり、現在価格の近くでは厚く、アクティブな価格帯の外では薄いか、ゼロになります。
集中係数(CLMM)
集中流動性プールでは、資本を狭い価格帯に集中させます。その価格帯内では流動性が深くなりますが、帯域外には流動性がありません。TVL が $50K で +/-5% の範囲に集中したプールは、その範囲内では $500K の定積プールと同等の深度を提供しますが、範囲外では深度がゼロです。
スリッページ曲線
スリッページは線形ではありません。取引サイズに対するスリッページをプロットすると、小さな取引では緩やかで、大きな取引では急になる曲線が得られます。曲線の形状は、プールの種類、TVL、流動性の集中度によって異なります。
プール構成
流動性の提供者は重要です。ロックされた LP トークンは引き出せないため、より安全です。片側のみの流動性は、プールのバランスが崩れていることを意味します。プールの経過日数は安定性の目安です。TVL が一貫している7日以上のプールのほうが信頼できます。
データソース
無料のものから包括的なものまで、相互に補完する4つのデータソースがあります。
| ソース | 認証 | 最適な用途 | 制限事項 |
|---|---|---|---|
| DexScreener | なし | プールの簡易検索、liquidity.usd | オンチェーンのプール詳細なし |
| Jupiter Quote API | なし | 任意のサイズでの実測スリッページ | 複数プールの集計値 |
| Birdeye | API キー | 詳細なプールデータ、取引履歴 | 無料プランではレート制限あり |
| オンチェーン | RPC のみ | LP ロック状態、正確な準備金 | プログラムに関する知識が必要 |
エンドポイントの完全なドキュメントと使用例については、references/data_sources.md を参照してください。
分析の基本パイプライン
ステップ 1:プールを特定する
トークンのすべてのプールを取得します。ほとんどの Solana トークンには、Raydium、Orca、Meteora にまたがる複数のプールがあります。
import httpx
def get_pools(mint: str) -> list[dict]:
"""Fetch all DEX pools for a token from DexScreener."""
resp = httpx.get(f"https://api.dexscreener.com/tokens/v1/solana/{mint}")
resp.raise_for_status()
pairs = resp.json()
return [p for p in pairs if p.get("liquidity", {}).get("usd", 0) > 0]
ステップ 2:深度を測定する
各プールから流動性指標を抽出します。
def extract_depth(pool: dict) -> dict:
"""Extract liquidity metrics from a DexScreener pool."""
return {
"dex": pool.get("dexId", "unknown"),
"liquidity_usd": pool.get("liquidity", {}).get("usd", 0),
"volume_24h": pool.get("volume", {}).get("h24", 0),
"pool_age_hours": _pool_age_hours(pool.get("pairCreatedAt", 0)),
"pair_address": pool.get("pairAddress", ""),
}
ステップ 3:スリッページを推定する
複数のサイズで Jupiter のクオートを使い、実測のスリッページ曲線を作成します。これにより、すべてのプールをまたいだ実際のルーティングを把握できます。
import httpx
SOL_MINT = "So11111111111111111111111111111111111111112"
LAMPORTS = 1_000_000_000
async def estimate_slippage(token_mint: str, sol_amounts: list[float]) -> list[dict]:
"""Query Jupiter for slippage at multiple trade sizes.
Args:
token_mint: Token mint address to buy.
sol_amounts: List of SOL amounts to test (e.g., [0.1, 0.5, 1, 5, 10]).
Returns:
List of dicts with sol_amount, output_tokens, price_per_token, slippage_bps.
"""
results = []
base_price = None
async with httpx.AsyncClient() as client:
for sol in sol_amounts:
lamports = int(sol * LAMPORTS)
resp = await client.get(
"https://api.jup.ag/quote/v1",
params={
"inputMint": SOL_MINT,
"outputMint": token_mint,
"amount": str(lamports),
"slippageBps": 5000,
},
)
if resp.status_code != 200:
continue
data = resp.json()
out_amount = int(data["outAmount"])
price = sol / out_amount if out_amount > 0 else 0
if base_price is None:
base_price = price
slippage_bps = int((price - base_price) / base_price * 10000) if base_price > 0 else 0
results.append({
"sol_amount": sol,
"output_tokens": out_amount,
"price_per_token": price,
"slippage_bps": max(0, slippage_bps),
})
return results
ステップ 4:集中度を評価する
CLMM プール(Orca Whirlpool、Raydium CLMM、Meteora DLMM)では、流動性が狭い価格帯に集中している場合があります。現在価格がアクティブな価格帯内にあるか、また流動性がどこまで深く続いているかを確認します。
def assess_concentration(pools: list[dict]) -> dict:
"""Assess concentration risk from pool data."""
clmm_pools = [p for p in pools if p.get("dexId") in ("raydium", "orca") and "clmm" in p.get("labels", [])]
cpmm_pools = [p for p in pools if p not in clmm_pools]
total_clmm = sum(p.get("liquidity", {}).get("usd", 0) for p in clmm_pools)
total_cpmm = sum(p.get("liquidity", {}).get("usd", 0) for p in cpmm_pools)
total = total_clmm + total_cpmm
return {
"clmm_ratio": total_clmm / total if total > 0 else 0,
"cpmm_liquidity": total_cpmm,
"clmm_liquidity": total_clmm,
"concentration_risk": "high" if total_clmm / total > 0.8 and total > 0 else "low",
}
ステップ 5:流動性スコアを算出する
0(危険)から100(深く安全な流動性)までの複合スコアを算出します。
def compute_liquidity_score(
total_liquidity_usd: float,
pool_count: int,
largest_pool_pct: float,
oldest_pool_hours: float,
max_slippage_bps_at_1sol: int,
) -> int:
"""Compute composite liquidity score (0-100).
Components:
Depth (40%): log-scaled TVL from $1K (0) to $1M+ (40)
Diversity (15%): more pools = more resilient
Concentration (15%): penalty if one pool dominates
Age (15%): older pools are more reliable
Slippage (15%): lower slippage = better
"""
import math
# Depth: 0-40 points
depth = min(40, int(40 * math.log10(max(total_liquidity_usd, 1)) / 6))
# Diversity: 0-15 points
diversity = min(15, pool_count * 3)
# Concentration: 0-15 points (penalty for single-pool dominance)
concentration = int(15 * (1 - largest_pool_pct))
# Age: 0-15 points (7+ days = full marks)
age = min(15, int(15 * oldest_pool_hours / 168))
# Slippage: 0-15 points
slippage = max(0, 15 - max_slippage_bps_at_1sol // 10)
return max(0, min(100, depth + diversity + concentration + age + slippage))
リスクフラグ
ポジションを建てる前に、以下の条件に該当するか確認してください。
| フラグ | 条件 | リスクレベル |
|---|---|---|
| 単一プール | DEX プールが 1 つしかない | 高 |
| 流動性が低い | 合計 TVL < $10,000 | 重大 |
| 新しいプール | プール作成から 2 時間未満 | 高 |
| LP がロックされていない | LP トークンがバーンまたはロックされていない | 中 |
| 出来高の不一致 | 出来高 >> TVL(ウォッシュトレード) | 中 |
| 価格乖離 | プール間の価格差が >5% | 高 |
| CLMM への流動性集中 | 狭いレンジの CLMM に流動性の >80% が集中 | 中 |
def detect_risk_flags(pools: list[dict]) -> list[str]:
"""Detect liquidity risk flags from pool data."""
flags = []
if len(pools) < 2:
flags.append("SINGLE_POOL: Only 1 pool exists — exit may be difficult")
total_liq = sum(p.get("liquidity", {}).get("usd", 0) for p in pools)
if total_liq < 10_000:
flags.append(f"THIN_LIQUIDITY: Total TVL ${total_liq:,.0f} < $10,000")
for p in pools:
age_ms = p.get("pairCreatedAt", 0)
if age_ms > 0:
import time
age_hours = (time.time() * 1000 - age_ms) / 3_600_000
if age_hours < 2:
flags.append(f"NEW_POOL: {p.get('dexId')} pool is {age_hours:.1f}h old")
volumes = [p.get("volume", {}).get("h24", 0) for p in pools]
liqs = [p.get("liquidity", {}).get("usd", 0) for p in pools]
for v, l, p in zip(volumes, liqs, pools):
if l > 0 and v / l > 10:
flags.append(f"VOLUME_MISMATCH: {p.get('dexId')} volume/TVL = {v/l:.1f}x")
prices = [float(p.get("priceUsd", 0)) for p in pools if float(p.get("priceUsd", 0)) > 0]
if len(prices) >= 2:
deviation = (max(prices) - min(prices)) / min(prices)
if deviation > 0.05:
flags.append(f"PRICE_DEVIATION: {deviation:.1%} across pools")
return flags
流動性に基づくポジションサイズ
スリッページを設定したしきい値未満に抑えられるよう、最大ポジションサイズを決めてください。
| 取引タイプ | 最大スリッページ | TVL に対する最大ポジション割合 |
|---|---|---|
| スキャルプ | 0.5%(50 bps) | 1% |
| スイング | 2%(200 bps) | 2-5% |
| ポジション | 5%(500 bps) | 5-10% |
def max_position_from_liquidity(
total_liquidity_usd: float,
max_slippage_pct: float = 1.0,
trade_type: str = "swing",
) -> float:
"""Estimate maximum position size in USD based on liquidity.
Uses rule-of-thumb: max_position = tvl_fraction * total_liquidity.
For constant-product AMM, 1% of TVL produces ~2% slippage.
Args:
total_liquidity_usd: Total liquidity across all pools.
max_slippage_pct: Maximum acceptable slippage percentage.
trade_type: "scalp", "swing", or "position".
Returns:
Maximum position size in USD.
"""
fractions = {"scalp": 0.01, "swing": 0.03, "position": 0.07}
base_fraction = fractions.get(trade_type, 0.03)
adjusted = base_fraction * (max_slippage_pct / 2.0)
return total_liquidity_usd * adjusted
スリッページの推定
定積積方式の数式、CLMM モデル、実測データに基づく曲線フィッティングなど、詳細なスリッページ計算については、references/slippage_curves.md を参照してください。
定積積 AMM の主要な数式:
slippage = Δx / (x + Δx)
ここで、Δx は取引サイズ、x はプール内の入力トークンのリザーブです。リザーブが 100 SOL のプールで 1 SOL を取引する場合、スリッページは 1/101 = 0.99% です。
プールの種類
Solana DEX では、流動性の特性が異なるさまざまな AMM 設計が使われています。以下を含む詳しい説明については、references/pool_types.md を参照してください。
- 定積積(Raydium V4、Orca Legacy):流動性が均一で、スリッページを予測しやすい
- 集中流動性(Raydium CLMM、Orca Whirlpool):現在の価格では流動性が厚く、レンジ外ではゼロ
- 動的 AMM(Meteora DLMM):手数料が適応し、ビン単位で流動性を管理
他のスキルとの連携
token-holder-analysis:ポジションを建てる前に LP トークンの保有者分布を確認してください。1 つのウォレットが LP トークンの >50% を保有し、それらがロックされていない場合、退出リスクが高くなります。
position-sizing:max_position_from_liquidity() の出力を上限として、ポジションサイズのモデルに入力してください。
slippage-modeling:このスキルの実測スリッページ曲線を、執行コストモデルの入力として使用してください。
birdeye-api:取引履歴や LP イベントを含む詳細なプールデータを取得します。
dexscreener-api:無料でプールを検索し、基本的な流動性指標を取得します。
ワークフローの例
# Full liquidity assessment for a token
import httpx
TOKEN = "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263" # BONK
# 1. Get pools
resp = httpx.get(f"https://api.dexscreener.com/tokens/v1/solana/{TOKEN}")
pools = [p for p in resp.json() if p.get("liquidity", {}).get("usd", 0) > 0]
# 2. Analyze
total_liq = sum(p["liquidity"]["usd"] for p in pools)
largest = max(p["liquidity"]["usd"] for p in pools)
largest_pct = largest / total_liq if total_liq > 0 else 1.0
# 3. Risk flags
flags = detect_risk_flags(pools)
# 4. Score
score = compute_liquidity_score(total_liq, len(pools), largest_pct, 1000, 50)
# 5. Position sizing
max_pos = max_position_from_liquidity(total_liq, max_slippage_pct=1.0, trade_type="swing")
print(f"Total Liquidity: ${total_liq:,.0f}")
print(f"Pools: {len(pools)}")
print(f"Score: {score}/100")
print(f"Max Position (swing, 1% slip): ${max_pos:,.0f}")
for f in flags:
print(f" WARNING: {f}")
ファイル
| ファイル | 説明 |
|---|---|
references/slippage_curves.md | 定積積プールと CLMM プールのスリッページ計算、実測データに基づく曲線フィッティング |
references/pool_types.md | Solana の AMM 設計:定積積、集中流動性、動的 |
references/data_sources.md | 流動性データの取得に使用する API エンドポイントとオンチェーン方式 |
scripts/analyze_liquidity.py | スコアリングとリスクフラグを含む、流動性の総合評価 |
scripts/pool_comparison.py | トークンの DEX 間でプールを比較 |