Skip to main content
GET
/
analytics
curl -X GET "https://api.strike.markets/analytics"
{
  "totalVolume": "157500000.50",
  "totalFees": "315000.75",
  "treasuryBalance": "2847650.25",
  "activeUsers": 1247,
  "totalPositions": 3891
}
curl -X GET "https://api.strike.markets/analytics"
{
  "totalVolume": "157500000.50",
  "totalFees": "315000.75",
  "treasuryBalance": "2847650.25",
  "activeUsers": 1247,
  "totalPositions": 3891
}

Overview

Get comprehensive protocol-wide analytics and metrics for Strike Protocol. This endpoint provides key performance indicators, financial metrics, and user activity statistics that give insight into the overall health and growth of the protocol.
This endpoint does NOT require authentication and provides public protocol analytics for transparency and research purposes.

Response Fields

totalVolume
string
Cumulative trading volume across all markets since protocol inception (USD)
totalFees
string
Total trading fees collected by the protocol (USD)
treasuryBalance
string
Current protocol treasury balance available for payouts and operations (USD)
activeUsers
integer
Number of unique wallet addresses that have traded in the last 30 days
totalPositions
integer
Total number of positions ever created on the protocol (open + closed + settled)

Metrics Explained

Trading Volume

  • Definition: Cumulative USD value of all positions opened
  • Calculation: Sum of all position sizes across all markets and time periods
  • Significance: Indicates overall protocol activity and adoption
  • Growth: Higher volume suggests increasing usage and liquidity

Fee Revenue

  • Definition: Total fees collected from trading operations
  • Sources: Position opening fees, closing fees, dynamic fees
  • Protocol share: Fees fund treasury, development, and rewards
  • Sustainability: Fee revenue indicates protocol’s economic viability

Treasury Balance

  • Definition: Current funds available for position payouts
  • Purpose: Ensures immediate settlement of winning positions
  • Management: Automatically managed through fee collection and payouts
  • Health indicator: Higher balance = better ability to handle large payouts

Active Users

  • Time window: Users who traded within last 30 days
  • Metric: Unique wallet addresses with at least one position
  • Engagement: Indicates current user retention and activity
  • Growth trends: Rising active users suggests healthy adoption

Position Count

  • Scope: All positions created since protocol launch
  • Categories: Includes open, closed, liquidated, and settled positions
  • Activity measure: Higher count indicates more trading activity
  • Historical data: Shows protocol usage trends over time

Use Cases

Protocol Health Assessment

  • Treasury adequacy: Ensure sufficient funds for payouts
  • User engagement: Monitor active user trends
  • Revenue growth: Track fee collection over time
  • Volume trends: Assess trading activity patterns

Investment Analysis

  • Due diligence: Evaluate protocol fundamentals for investment
  • Market comparison: Compare metrics with other protocols
  • Growth tracking: Monitor key performance indicators
  • Risk assessment: Evaluate financial stability

Market Research

  • Industry analysis: Understand perpetual futures market size
  • Competitive positioning: Compare Strike Protocol to competitors
  • Adoption metrics: Track protocol growth and adoption
  • Market trends: Identify broader DeFi trading patterns

Business Intelligence

  • Strategic planning: Use metrics for business decisions
  • Performance monitoring: Track against business objectives
  • Forecasting: Use historical data for projections
  • Reporting: Regular reporting to stakeholders

Error Responses

503 Service Unavailable
object
Analytics service temporarily unavailable
{
  "error": 503,
  "message": "Analytics service temporarily unavailable"
}

Usage Examples

Basic Analytics Dashboard

async function getProtocolMetrics() {
  try {
    const response = await fetch('https://api.strike.markets/analytics');
    
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }
    
    const data = await response.json();
    
    return {
      volume: {
        total: parseFloat(data.totalVolume),
        formatted: formatCurrency(data.totalVolume)
      },
      fees: {
        total: parseFloat(data.totalFees),
        formatted: formatCurrency(data.totalFees)
      },
      treasury: {
        balance: parseFloat(data.treasuryBalance),
        formatted: formatCurrency(data.treasuryBalance)
      },
      users: {
        active: data.activeUsers,
        formatted: data.activeUsers.toLocaleString()
      },
      positions: {
        total: data.totalPositions,
        formatted: data.totalPositions.toLocaleString()
      }
    };
  } catch (error) {
    console.error('Failed to fetch protocol metrics:', error);
    throw error;
  }
}

function formatCurrency(value, decimals = 2) {
  const num = parseFloat(value);
  
  if (num >= 1000000000) {
    return `$${(num / 1000000000).toFixed(decimals)}B`;
  } else if (num >= 1000000) {
    return `$${(num / 1000000).toFixed(decimals)}M`;
  } else if (num >= 1000) {
    return `$${(num / 1000).toFixed(decimals)}K`;
  } else {
    return `$${num.toFixed(decimals)}`;
  }
}

// Usage
const metrics = await getProtocolMetrics();
console.log(`Total Volume: ${metrics.volume.formatted}`);
console.log(`Active Users: ${metrics.users.formatted}`);
console.log(`Treasury: ${metrics.treasury.formatted}`);

Historical Analytics Tracker

class ProtocolAnalyticsTracker {
  constructor() {
    this.history = [];
    this.loadFromStorage();
  }
  
  async recordSnapshot() {
    try {
      const metrics = await getProtocolMetrics();
      
      const snapshot = {
        timestamp: Date.now(),
        date: new Date().toISOString(),
        ...metrics
      };
      
      this.history.push(snapshot);
      
      // Keep only last 90 days of data
      const ninetyDaysAgo = Date.now() - (90 * 24 * 60 * 60 * 1000);
      this.history = this.history.filter(s => s.timestamp > ninetyDaysAgo);
      
      this.saveToStorage();
      return snapshot;
    } catch (error) {
      console.error('Failed to record analytics snapshot:', error);
      return null;
    }
  }
  
  getGrowthMetrics(days = 30) {
    if (this.history.length < 2) {
      return { message: "Insufficient historical data" };
    }
    
    const cutoff = Date.now() - (days * 24 * 60 * 60 * 1000);
    const recentData = this.history
      .filter(s => s.timestamp > cutoff)
      .sort((a, b) => a.timestamp - b.timestamp);
    
    if (recentData.length < 2) {
      return { message: `Insufficient data for ${days}-day analysis` };
    }
    
    const first = recentData[0];
    const last = recentData[recentData.length - 1];
    const timeSpan = (last.timestamp - first.timestamp) / (1000 * 60 * 60 * 24);
    
    const volumeGrowth = last.volume.total - first.volume.total;
    const feesGrowth = last.fees.total - first.fees.total;
    const treasuryGrowth = last.treasury.balance - first.treasury.balance;
    const usersGrowth = last.users.active - first.users.active;
    const positionsGrowth = last.positions.total - first.positions.total;
    
    return {
      period: `${days} days`,
      timeSpan: timeSpan.toFixed(1),
      growth: {
        volume: {
          absolute: volumeGrowth,
          percentage: ((volumeGrowth / first.volume.total) * 100).toFixed(2),
          daily: (volumeGrowth / timeSpan).toFixed(2)
        },
        fees: {
          absolute: feesGrowth,
          percentage: ((feesGrowth / first.fees.total) * 100).toFixed(2),
          daily: (feesGrowth / timeSpan).toFixed(2)
        },
        treasury: {
          absolute: treasuryGrowth,
          percentage: ((treasuryGrowth / first.treasury.balance) * 100).toFixed(2),
          daily: (treasuryGrowth / timeSpan).toFixed(2)
        },
        users: {
          absolute: usersGrowth,
          percentage: ((usersGrowth / first.users.active) * 100).toFixed(2),
          daily: (usersGrowth / timeSpan).toFixed(2)
        },
        positions: {
          absolute: positionsGrowth,
          percentage: ((positionsGrowth / first.positions.total) * 100).toFixed(2),
          daily: (positionsGrowth / timeSpan).toFixed(2)
        }
      }
    };
  }
  
  calculateKPIs() {
    if (this.history.length === 0) {
      return { message: "No historical data available" };
    }
    
    const latest = this.history[this.history.length - 1];
    
    // Calculate key performance indicators
    const avgVolumePerUser = latest.volume.total / latest.users.active;
    const avgPositionsPerUser = latest.positions.total / latest.users.active;
    const avgVolumePerPosition = latest.volume.total / latest.positions.total;
    const feeRate = (latest.fees.total / latest.volume.total) * 100;
    const treasuryRatio = (latest.treasury.balance / latest.volume.total) * 100;
    
    return {
      timestamp: latest.date,
      kpis: {
        avgVolumePerUser: avgVolumePerUser.toFixed(2),
        avgPositionsPerUser: avgPositionsPerUser.toFixed(2),
        avgVolumePerPosition: avgVolumePerPosition.toFixed(2),
        feeRate: feeRate.toFixed(3) + '%',
        treasuryRatio: treasuryRatio.toFixed(2) + '%'
      },
      efficiency: this.assessEfficiency(latest),
      health: this.assessProtocolHealth(latest)
    };
  }
  
  assessEfficiency(metrics) {
    const scores = [];
    
    // Volume per user efficiency
    const avgVolumePerUser = metrics.volume.total / metrics.users.active;
    if (avgVolumePerUser > 100000) scores.push({ metric: 'High volume per user', score: 25 });
    else if (avgVolumePerUser > 50000) scores.push({ metric: 'Good volume per user', score: 15 });
    else scores.push({ metric: 'Low volume per user', score: 5 });
    
    // Fee efficiency
    const feeRate = (metrics.fees.total / metrics.volume.total) * 100;
    if (feeRate > 0.5) scores.push({ metric: 'High fee collection rate', score: 25 });
    else if (feeRate > 0.2) scores.push({ metric: 'Good fee collection rate', score: 15 });
    else scores.push({ metric: 'Low fee collection rate', score: 5 });
    
    // Treasury management
    const treasuryRatio = (metrics.treasury.balance / metrics.volume.total) * 100;
    if (treasuryRatio > 2) scores.push({ metric: 'Strong treasury reserves', score: 25 });
    else if (treasuryRatio > 1) scores.push({ metric: 'Adequate treasury reserves', score: 15 });
    else scores.push({ metric: 'Low treasury reserves', score: 5 });
    
    // User engagement
    const positionsPerUser = metrics.positions.total / metrics.users.active;
    if (positionsPerUser > 5) scores.push({ metric: 'High user engagement', score: 25 });
    else if (positionsPerUser > 2) scores.push({ metric: 'Good user engagement', score: 15 });
    else scores.push({ metric: 'Low user engagement', score: 5 });
    
    const totalScore = scores.reduce((sum, s) => sum + s.score, 0);
    
    let rating = 'POOR';
    if (totalScore >= 80) rating = 'EXCELLENT';
    else if (totalScore >= 60) rating = 'GOOD';
    else if (totalScore >= 40) rating = 'FAIR';
    
    return {
      totalScore,
      rating,
      factors: scores
    };
  }
  
  assessProtocolHealth(metrics) {
    const healthFactors = [];
    let healthScore = 0;
    
    // Treasury health
    const treasuryRatio = (metrics.treasury.balance / metrics.volume.total) * 100;
    if (treasuryRatio > 2) {
      healthFactors.push({ factor: 'Treasury Health', status: 'EXCELLENT', impact: 30 });
      healthScore += 30;
    } else if (treasuryRatio > 1) {
      healthFactors.push({ factor: 'Treasury Health', status: 'GOOD', impact: 20 });
      healthScore += 20;
    } else {
      healthFactors.push({ factor: 'Treasury Health', status: 'CONCERNING', impact: 10 });
      healthScore += 10;
    }
    
    // User growth
    if (metrics.users.active > 1000) {
      healthFactors.push({ factor: 'User Base', status: 'STRONG', impact: 25 });
      healthScore += 25;
    } else if (metrics.users.active > 500) {
      healthFactors.push({ factor: 'User Base', status: 'GROWING', impact: 15 });
      healthScore += 15;
    } else {
      healthFactors.push({ factor: 'User Base', status: 'SMALL', impact: 5 });
      healthScore += 5;
    }
    
    // Volume activity
    if (metrics.volume.total > 100000000) { // 100M USD+
      healthFactors.push({ factor: 'Trading Activity', status: 'HIGH', impact: 25 });
      healthScore += 25;
    } else if (metrics.volume.total > 10000000) { // 10M USD+
      healthFactors.push({ factor: 'Trading Activity', status: 'MODERATE', impact: 15 });
      healthScore += 15;
    } else {
      healthFactors.push({ factor: 'Trading Activity', status: 'LOW', impact: 5 });
      healthScore += 5;
    }
    
    // Fee generation
    const feeRate = (metrics.fees.total / metrics.volume.total) * 100;
    if (feeRate > 0.3) {
      healthFactors.push({ factor: 'Revenue Generation', status: 'STRONG', impact: 20 });
      healthScore += 20;
    } else if (feeRate > 0.1) {
      healthFactors.push({ factor: 'Revenue Generation', status: 'ADEQUATE', impact: 10 });
      healthScore += 10;
    } else {
      healthFactors.push({ factor: 'Revenue Generation', status: 'WEAK', impact: 0 });
    }
    
    let overallHealth = 'CRITICAL';
    if (healthScore >= 80) overallHealth = 'EXCELLENT';
    else if (healthScore >= 60) overallHealth = 'GOOD';
    else if (healthScore >= 40) overallHealth = 'FAIR';
    else if (healthScore >= 20) overallHealth = 'POOR';
    
    return {
      overallHealth,
      healthScore,
      factors: healthFactors
    };
  }
  
  generateReport() {
    if (this.history.length === 0) {
      return { error: "No analytics data available" };
    }
    
    const latest = this.history[this.history.length - 1];
    const growth30d = this.getGrowthMetrics(30);
    const growth7d = this.getGrowthMetrics(7);
    const kpis = this.calculateKPIs();
    
    return {
      snapshot: {
        timestamp: latest.date,
        metrics: latest
      },
      growth: {
        last30Days: growth30d,
        last7Days: growth7d
      },
      performance: kpis,
      insights: this.generateInsights(),
      recommendations: this.generateRecommendations()
    };
  }
  
  generateInsights() {
    const insights = [];
    
    if (this.history.length < 2) {
      return [{ type: 'INFO', message: 'Insufficient data for insights generation' }];
    }
    
    const latest = this.history[this.history.length - 1];
    const growth7d = this.getGrowthMetrics(7);
    
    // Volume insights
    if (parseFloat(growth7d.growth?.volume?.percentage || 0) > 20) {
      insights.push({
        type: 'POSITIVE',
        category: 'Volume',
        message: `Trading volume increased by ${growth7d.growth.volume.percentage}% in the last week`
      });
    }
    
    // User insights
    if (parseFloat(growth7d.growth?.users?.percentage || 0) > 10) {
      insights.push({
        type: 'POSITIVE',
        category: 'Users',
        message: `Active users increased by ${growth7d.growth.users.percentage}% in the last week`
      });
    }
    
    // Treasury insights
    const treasuryRatio = (latest.treasury.balance / latest.volume.total) * 100;
    if (treasuryRatio < 1) {
      insights.push({
        type: 'WARNING',
        category: 'Treasury',
        message: 'Treasury balance is low relative to trading volume - monitor payout capacity'
      });
    }
    
    return insights;
  }
  
  generateRecommendations() {
    const recommendations = [];
    const latest = this.history[this.history.length - 1];
    
    // Treasury recommendations
    const treasuryRatio = (latest.treasury.balance / latest.volume.total) * 100;
    if (treasuryRatio < 1) {
      recommendations.push({
        priority: 'HIGH',
        category: 'Treasury Management',
        action: 'Increase treasury reserves',
        reason: 'Low treasury balance may impact payout capabilities'
      });
    }
    
    // User growth recommendations
    if (latest.users.active < 1000) {
      recommendations.push({
        priority: 'MEDIUM',
        category: 'User Acquisition',
        action: 'Focus on user growth strategies',
        reason: 'Expanding user base will drive volume and fee growth'
      });
    }
    
    // Volume recommendations
    const avgVolumePerUser = latest.volume.total / latest.users.active;
    if (avgVolumePerUser < 50000) {
      recommendations.push({
        priority: 'MEDIUM',
        category: 'User Engagement',
        action: 'Improve user retention and trading frequency',
        reason: 'Low average volume per user indicates room for engagement improvement'
      });
    }
    
    return recommendations;
  }
  
  saveToStorage() {
    if (typeof localStorage !== 'undefined') {
      localStorage.setItem('protocol_analytics_history', JSON.stringify(this.history));
    }
  }
  
  loadFromStorage() {
    if (typeof localStorage !== 'undefined') {
      const stored = localStorage.getItem('protocol_analytics_history');
      if (stored) {
        this.history = JSON.parse(stored);
      }
    }
  }
}

// Usage
const tracker = new ProtocolAnalyticsTracker();

// Record snapshots regularly
setInterval(() => {
  tracker.recordSnapshot();
}, 6 * 60 * 60 * 1000); // Every 6 hours

// Generate comprehensive report
const report = tracker.generateReport();
console.log('Protocol Analytics Report:', report);

Protocol Comparison Tool

class ProtocolComparison {
  static async compareMetrics(protocolEndpoints) {
    const comparisons = [];
    
    for (const [name, endpoint] of Object.entries(protocolEndpoints)) {
      try {
        const response = await fetch(endpoint);
        
        if (response.ok) {
          const data = await response.json();
          comparisons.push({
            protocol: name,
            ...data
          });
        }
      } catch (error) {
        console.error(`Failed to fetch data for ${name}:`, error);
      }
    }
    
    if (comparisons.length === 0) {
      return { error: "No protocol data available for comparison" };
    }
    
    return this.analyzeComparison(comparisons);
  }
  
  static analyzeComparison(protocols) {
    const metrics = ['totalVolume', 'totalFees', 'treasuryBalance', 'activeUsers', 'totalPositions'];
    const analysis = {};
    
    metrics.forEach(metric => {
      const values = protocols
        .map(p => ({ name: p.protocol, value: parseFloat(p[metric] || 0) }))
        .sort((a, b) => b.value - a.value);
      
      analysis[metric] = {
        leader: values[0],
        values: values,
        totalMarket: values.reduce((sum, v) => sum + v.value, 0)
      };
    });
    
    // Calculate market share
    const marketShares = protocols.map(p => ({
      protocol: p.protocol,
      volumeShare: (parseFloat(p.totalVolume) / analysis.totalVolume.totalMarket * 100).toFixed(2),
      userShare: (parseFloat(p.activeUsers) / analysis.activeUsers.totalMarket * 100).toFixed(2)
    }));
    
    return {
      protocols: protocols.length,
      analysis: analysis,
      marketShares: marketShares,
      insights: this.generateComparisonInsights(protocols, analysis)
    };
  }
  
  static generateComparisonInsights(protocols, analysis) {
    const insights = [];
    
    // Volume leadership
    const volumeLeader = analysis.totalVolume.leader;
    insights.push({
      type: 'LEADERSHIP',
      message: `${volumeLeader.name} leads in trading volume with ${formatCurrency(volumeLeader.value)}`
    });
    
    // User concentration
    const userLeader = analysis.activeUsers.leader;
    const userShare = (userLeader.value / analysis.activeUsers.totalMarket * 100);
    
    if (userShare > 50) {
      insights.push({
        type: 'CONCENTRATION',
        message: `${userLeader.name} has ${userShare.toFixed(1)}% of all active users - high market concentration`
      });
    }
    
    // Treasury analysis
    const treasuryLeader = analysis.treasuryBalance.leader;
    insights.push({
      type: 'FINANCIAL',
      message: `${treasuryLeader.name} has the largest treasury with ${formatCurrency(treasuryLeader.value)}`
    });
    
    return insights;
  }
}

// Usage
const protocolEndpoints = {
  'Strike Protocol': 'https://api.strike.markets/analytics',
  'Competitor A': 'https://api.competitor-a.com/stats',
  'Competitor B': 'https://api.competitor-b.com/metrics'
};

const comparison = await ProtocolComparison.compareMetrics(protocolEndpoints);
console.log('Protocol Comparison:', comparison);

Analytics Monitoring

class AnalyticsMonitor {
  constructor(alertThresholds = {}) {
    this.thresholds = {
      treasuryLow: 1000000, // 1M USD minimum treasury
      volumeDropPercentage: 20, // 20% volume drop alert
      userDropCount: 50, // 50 user drop alert
      feeRateLow: 0.1, // 0.1% minimum fee rate
      ...alertThresholds
    };
    
    this.alerts = [];
    this.previousMetrics = null;
  }
  
  async checkMetrics() {
    try {
      const currentMetrics = await getProtocolMetrics();
      
      if (this.previousMetrics) {
        this.analyzeChanges(this.previousMetrics, currentMetrics);
      }
      
      this.checkAbsoluteThresholds(currentMetrics);
      
      this.previousMetrics = currentMetrics;
      
      return {
        metrics: currentMetrics,
        alerts: this.getAndClearAlerts()
      };
    } catch (error) {
      console.error('Failed to check metrics:', error);
      return {
        error: error.message,
        alerts: []
      };
    }
  }
  
  analyzeChanges(previous, current) {
    // Volume change alerts
    const volumeChange = ((current.volume.total - previous.volume.total) / previous.volume.total) * 100;
    
    if (volumeChange < -this.thresholds.volumeDropPercentage) {
      this.alerts.push({
        type: 'VOLUME_DROP',
        severity: 'HIGH',
        message: `Trading volume dropped by ${Math.abs(volumeChange).toFixed(1)}%`,
        current: current.volume.formatted,
        previous: previous.volume.formatted
      });
    }
    
    // User change alerts
    const userChange = current.users.active - previous.users.active;
    
    if (userChange < -this.thresholds.userDropCount) {
      this.alerts.push({
        type: 'USER_DROP',
        severity: 'MEDIUM',
        message: `Active users decreased by ${Math.abs(userChange)} users`,
        current: current.users.active,
        previous: previous.users.active
      });
    }
    
    // Treasury change alerts
    const treasuryChange = ((current.treasury.balance - previous.treasury.balance) / previous.treasury.balance) * 100;
    
    if (treasuryChange < -10) { // 10% treasury drop
      this.alerts.push({
        type: 'TREASURY_DROP',
        severity: 'HIGH',
        message: `Treasury balance dropped by ${Math.abs(treasuryChange).toFixed(1)}%`,
        current: current.treasury.formatted,
        previous: previous.treasury.formatted
      });
    }
  }
  
  checkAbsoluteThresholds(metrics) {
    // Low treasury alert
    if (metrics.treasury.balance < this.thresholds.treasuryLow) {
      this.alerts.push({
        type: 'LOW_TREASURY',
        severity: 'CRITICAL',
        message: `Treasury balance below threshold: ${metrics.treasury.formatted}`,
        threshold: formatCurrency(this.thresholds.treasuryLow)
      });
    }
    
    // Low fee rate alert
    const feeRate = (metrics.fees.total / metrics.volume.total) * 100;
    
    if (feeRate < this.thresholds.feeRateLow) {
      this.alerts.push({
        type: 'LOW_FEE_RATE',
        severity: 'MEDIUM',
        message: `Fee rate below threshold: ${feeRate.toFixed(3)}%`,
        threshold: `${this.thresholds.feeRateLow}%`
      });
    }
  }
  
  getAndClearAlerts() {
    const alerts = [...this.alerts];
    this.alerts = [];
    return alerts;
  }
  
  generateHealthReport() {
    if (!this.previousMetrics) {
      return { message: "Need at least one metrics check to generate health report" };
    }
    
    const metrics = this.previousMetrics;
    const healthFactors = [];
    
    // Treasury health
    const treasuryHealth = metrics.treasury.balance > this.thresholds.treasuryLow ? 'HEALTHY' : 'UNHEALTHY';
    healthFactors.push({
      factor: 'Treasury Balance',
      status: treasuryHealth,
      value: metrics.treasury.formatted
    });
    
    // User growth health
    const userHealth = metrics.users.active > 500 ? 'HEALTHY' : 'NEEDS_ATTENTION';
    healthFactors.push({
      factor: 'Active Users',
      status: userHealth,
      value: metrics.users.formatted
    });
    
    // Volume health
    const volumeHealth = metrics.volume.total > 50000000 ? 'HEALTHY' : 'MODERATE'; // 50M USD threshold
    healthFactors.push({
      factor: 'Trading Volume',
      status: volumeHealth,
      value: metrics.volume.formatted
    });
    
    // Fee efficiency
    const feeRate = (metrics.fees.total / metrics.volume.total) * 100;
    const feeHealth = feeRate > 0.2 ? 'HEALTHY' : 'NEEDS_IMPROVEMENT';
    healthFactors.push({
      factor: 'Fee Efficiency',
      status: feeHealth,
      value: `${feeRate.toFixed(3)}%`
    });
    
    const healthyFactors = healthFactors.filter(f => f.status === 'HEALTHY').length;
    const overallHealth = healthyFactors >= 3 ? 'GOOD' : healthyFactors >= 2 ? 'FAIR' : 'POOR';
    
    return {
      overallHealth,
      healthScore: `${healthyFactors}/${healthFactors.length}`,
      factors: healthFactors,
      recommendations: this.generateHealthRecommendations(healthFactors)
    };
  }
  
  generateHealthRecommendations(healthFactors) {
    const recommendations = [];
    
    healthFactors.forEach(factor => {
      if (factor.status !== 'HEALTHY') {
        switch (factor.factor) {
          case 'Treasury Balance':
            recommendations.push({
              priority: 'CRITICAL',
              action: 'Increase treasury reserves through fee optimization or external funding',
              reason: 'Low treasury balance threatens payout capabilities'
            });
            break;
          case 'Active Users':
            recommendations.push({
              priority: 'HIGH',
              action: 'Implement user acquisition and retention strategies',
              reason: 'Growing user base is essential for protocol sustainability'
            });
            break;
          case 'Trading Volume':
            recommendations.push({
              priority: 'MEDIUM',
              action: 'Improve user engagement and trading incentives',
              reason: 'Higher volume drives fee revenue and protocol growth'
            });
            break;
          case 'Fee Efficiency':
            recommendations.push({
              priority: 'MEDIUM',
              action: 'Review and optimize fee structure',
              reason: 'Better fee collection improves protocol economics'
            });
            break;
        }
      }
    });
    
    return recommendations;
  }
}

// Usage
const monitor = new AnalyticsMonitor();

// Check metrics regularly
setInterval(async () => {
  const report = await monitor.checkMetrics();
  
  if (report.alerts.length > 0) {
    console.log('⚠️ Analytics Alerts:', report.alerts);
  }
  
  // Generate health report
  const healthReport = monitor.generateHealthReport();
  console.log('📊 Protocol Health:', healthReport);
}, 15 * 60 * 1000); // Every 15 minutes

Integration Best Practices

Data Refresh Strategy

  • Update frequency: Every 5-15 minutes for dashboards
  • Caching: Cache for 5 minutes to reduce server load
  • Background updates: Refresh data in background
  • Error handling: Graceful degradation when service unavailable

Performance Considerations

// Cache analytics data
class AnalyticsCache {
  constructor(ttl = 300000) { // 5 minute TTL
    this.cache = null;
    this.timestamp = 0;
    this.ttl = ttl;
  }
  
  async getAnalytics() {
    const now = Date.now();
    
    if (this.cache && (now - this.timestamp) < this.ttl) {
      return this.cache;
    }
    
    const data = await getProtocolMetrics();
    this.cache = data;
    this.timestamp = now;
    
    return data;
  }
  
  invalidate() {
    this.cache = null;
    this.timestamp = 0;
  }
}

Monitoring and Alerts

  • Threshold monitoring: Set up alerts for critical metrics
  • Trend analysis: Monitor metrics over time
  • Anomaly detection: Identify unusual patterns
  • Automated reporting: Regular health reports
  • Get Markets - Market-specific data that contributes to protocol metrics
  • Health Check - Technical health status of the API
  • Get Positions - Individual positions that create protocol volume
  • Dashboard - User-level analytics and data
Protocol analytics provide valuable insights into overall system health and growth. Use these metrics to understand trends, identify opportunities, and monitor the protocol’s evolution over time.
Analytics data is updated continuously as users trade and interact with the protocol. Metrics may have slight delays due to data aggregation and processing requirements.

Response

200 - application/json

Analytics retrieved successfully

totalVolume
string
totalFees
string
treasuryBalance
string
activeUsers
integer
totalPositions
integer