get_asset_context
Analyze crypto assets by retrieving cycle position, price trends, volume health, holder behavior, risk levels, and positioning guidance for informed trading decisions.
Instructions
Get deep context on a specific crypto asset: cycle position, price trend, volume health, holder behavior, risk level, and positioning guidance. Pass asset name or symbol (e.g., "bitcoin", "btc", "ethereum", "sol").
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| asset | Yes | Asset name or symbol (e.g., "bitcoin", "btc", "ethereum", "sol") |
Implementation Reference
- src/tools/get-asset-context.ts:15-80 (handler)Main handler function for get_asset_context that resolves Coingecko IDs, retrieves market and chart data, calculates cycles and risks, and returns the asset context.
export async function getAssetContext(cache: CacheService, asset: string): Promise<AssetContextOutput | ErrorOutput> { const coingeckoId = resolveCoingeckoId(asset); const cacheKey = `asset_context_${coingeckoId}`; const cached = cache.get<AssetContextOutput>(cacheKey); if (cached) return cached.data; try { const [coinData, chartData] = await Promise.all([ getCoinMarket(coingeckoId), getMarketChart(coingeckoId, 90), ]); const prices = chartData.prices.map(p => p[1]); const volumes = chartData.total_volumes.map(v => v[1]); const sma30 = calculateSMA(prices, 30); const sma90 = calculateSMA(prices, prices.length); const recentHigh = Math.max(...prices.slice(-30)); const volumeTrend = determineVolumeTrend(volumes); const cyclePosition = determineCyclePosition({ currentPrice: coinData.current_price, sma30, sma90, recentHigh, volumeTrend, }); const priceTrend = determinePriceTrend(prices); const avg30dVolume = volumes.slice(-30).reduce((a, b) => a + b, 0) / Math.min(volumes.length, 30); const volumeHealth = determineVolumeHealth(coinData.total_volume, avg30dVolume); const volumeVs30d = avg30dVolume > 0 ? Math.round((coinData.total_volume / avg30dVolume) * 100) / 100 : 1; const riskLevel = assessRiskLevel(cyclePosition, priceTrend, volumeHealth, coinData.ath_change_percentage); const holderBehavior = assessHolderBehavior(cyclePosition, volumeTrend, priceTrend); const guidance = generateAssetGuidance(coinData.name, cyclePosition, priceTrend, riskLevel, volumeHealth, coinData.ath_change_percentage); const result: AssetContextOutput = { asset: coinData.name, coingecko_id: coingeckoId, price_usd: coinData.current_price, market_cap_usd: coinData.market_cap, volume_24h: coinData.total_volume, cycle_position: cyclePosition, vs_ath_percentage: Math.round(coinData.ath_change_percentage * 100) / 100, vs_atl_percentage: Math.round(coinData.atl_change_percentage * 100) / 100, volume_health: volumeHealth, volume_vs_30d_average: volumeVs30d, price_trend: priceTrend, holder_behavior: holderBehavior, risk_level: riskLevel, agent_guidance: guidance, }; cache.set(cacheKey, result, getCacheTtl(BASE_TTL)); return result; } catch (err) { return { error: true, error_source: 'get_asset_context', agent_guidance: 'Asset data unavailable. Do not make positioning decisions on this asset until data is restored. If this is a new or low-cap asset, it may not be indexed.', last_known_data: cache.get<AssetContextOutput>(cacheKey)?.data ?? null, data_warnings: ['Asset data source temporarily unavailable. Verify the asset name or symbol and retry.'], }; } }