> For the complete documentation index, see [llms.txt](https://documentation.kodiak.finance/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://documentation.kodiak.finance/developers/kodiak-islands/subgraph/advanced-usage-guide.md).

# Advanced Usage Guide

This guide covers advanced topics and strategies for working with the Kodiak Islands subgraph, including complex querying patterns, integration strategies, performance optimization, and custom analytics.

#### Complex Querying Patterns

**Fragment Reuse**

For complex applications that frequently query similar fields, use GraphQL fragments to reduce duplication:

```graphql
fragment VaultBasicInfo on KodiakVault {
  id
  name
  symbol
  totalValueLockedUSD
  apr {
    averageApr
  }
}

fragment VaultDetailedInfo on KodiakVault {
  ...VaultBasicInfo
  inputToken {
    symbol
    decimals
  }
  outputToken {
    symbol
    decimals
  }
  pricePerShare
  _token0Amount
  _token1Amount
  _token0AmountUSD
  _token1AmountUSD
}

query {
  topVaults: kodiakVaults(
    first: 5
    orderBy: totalValueLockedUSD
    orderDirection: desc
  ) {
    ...VaultBasicInfo
  }
  
  specificVault: kodiakVault(id: "0x1234567890abcdef") {
    ...VaultDetailedInfo
  }
}
```

**Dynamic Querying with Variables**

Use GraphQL variables for dynamic queries:

```graphql
query GetVaultPerformance($vaultId: ID!, $startTime: BigInt!, $endTime: BigInt!) {
  snapshots: kodiakVaultDailySnapshots(
    where: {
      vault: $vaultId
      timestamp_gte: $startTime
      timestamp_lte: $endTime
    }
    orderBy: timestamp
  ) {
    timestamp
    totalValueLockedUSD
    dailyTotalFeesUSD
    apr
  }
}
```

This query can be executed with variables:

```json
{
  "vaultId": "0x1234567890abcdef",
  "startTime": "1640995200",
  "endTime": "1672531200"
}
```

**Advanced Filtering Combinations**

Combine multiple filters for complex data selection:

```graphql
query HighPerformingVaults {
  kodiakVaultDailySnapshots(
    where: {
      apr_gt: "20"                      # APR > 20%
      totalValueLockedUSD_gt: "500000"  # TVL > $500,000
      dailyTotalFeesUSD_gt: "1000"      # Daily fees > $1,000
      timestamp_gt: "1648771200"        # After April 1, 2022
    }
    orderBy: apr
    orderDirection: desc
  ) {
    vault {
      id
      name
    }
    timestamp
    apr
    totalValueLockedUSD
    dailyTotalFeesUSD
  }
}
```

#### Time Series Analysis

**Calculating Period-over-Period Changes**

To calculate weekly changes in vault performance:

```graphql
query WeeklyPerformanceChange($vaultId: ID!) {
  thisWeek: kodiakVaultDailySnapshots(
    first: 7
    orderBy: timestamp
    orderDirection: desc
    where: { vault: $vaultId }
  ) {
    timestamp
    totalValueLockedUSD
    dailyTotalFeesUSD
    volumeUSD
    apr
  }
  
  previousWeek: kodiakVaultDailySnapshots(
    first: 7
    skip: 7
    orderBy: timestamp
    orderDirection: desc
    where: { vault: $vaultId }
  ) {
    timestamp
    totalValueLockedUSD
    dailyTotalFeesUSD
    volumeUSD
    apr
  }
}
```

With this data, you can calculate week-over-week changes for key metrics in your application:

```typescript
function calculateChangePercentage(current: number, previous: number): number {
  if (previous === 0) return 0;
  return ((current - previous) / previous) * 100;
}

// Calculate aggregate values for each week
const thisWeekTVL = average(thisWeekData.map(d => parseFloat(d.totalValueLockedUSD)));
const prevWeekTVL = average(previousWeekData.map(d => parseFloat(d.totalValueLockedUSD)));

const thisWeekFees = sum(thisWeekData.map(d => parseFloat(d.dailyTotalFeesUSD)));
const prevWeekFees = sum(previousWeekData.map(d => parseFloat(d.dailyTotalFeesUSD)));

// Calculate percentage changes
const tvlChange = calculateChangePercentage(thisWeekTVL, prevWeekTVL);
const feesChange = calculateChangePercentage(thisWeekFees, prevWeekFees);
```

**Analyzing APR Trends**

Track APR trends over longer periods to identify patterns:

```graphql
query AprTrends($vaultId: ID!) {
  daily: kodiakVaultDailySnapshots(
    first: 90  # Last 90 days
    orderBy: timestamp
    orderDirection: desc
    where: { vault: $vaultId }
  ) {
    timestamp
    apr
    totalValueLockedUSD
  }
}
```

You can use this data to:

* Calculate moving averages (7-day, 30-day)
* Identify seasonal patterns
* Correlate APR changes with TVL or other metrics
* Build predictive models for APR forecasting

#### Integration Strategies

**Real-time Data Updates**

For applications requiring real-time data, implement a polling strategy:

```typescript
// Fetch latest vault data every 60 seconds
function setupPolling(vaultId: string) {
  const query = `
    query GetVaultData($id: ID!) {
      kodiakVault(id: $id) {
        totalValueLockedUSD
        pricePerShare
        apr {
          averageApr
        }
      }
    }
  `;
  
  setInterval(() => {
    executeQuery(query, { id: vaultId })
      .then(data => updateUI(data.kodiakVault))
      .catch(error => handleError(error));
  }, 60000);
}
```

**Combining with On-chain Data**

For some advanced use cases, you may need to combine subgraph data with direct on-chain calls:

```typescript
async function getCompleteVaultData(vaultId: string) {
  // Get historical and aggregated data from subgraph
  const subgraphData = await fetchFromSubgraph(vaultId);
  
  // Get real-time position data from the blockchain
  const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
  const vaultContract = new ethers.Contract(vaultId, VAULT_ABI, provider);
  const currentPosition = await vaultContract.getCurrentPosition();
  
  // Combine the data
  return {
    ...subgraphData,
    currentPosition: {
      lowerTick: currentPosition.lowerTick.toString(),
      upperTick: currentPosition.upperTick.toString(),
      liquidity: currentPosition.liquidity.toString()
    }
  };
}
```

**Building Custom Analytics**

Create custom analytics by combining multiple queries:

```typescript
async function vaultPerformanceAnalytics(vaultId: string) {
  // Fetch basic vault info
  const vaultInfo = await fetchVaultInfo(vaultId);
  
  // Fetch historical data
  const dailyData = await fetchDailySnapshots(vaultId, 90); // Last 90 days
  
  // Fetch user activity
  const deposits = await fetchDeposits(vaultId);
  const withdrawals = await fetchWithdrawals(vaultId);
  
  // Calculate custom metrics
  const userRetentionRate = calculateUserRetention(deposits, withdrawals);
  const volatilityScore = calculateVolatility(dailyData.map(d => d.apr));
  const performanceScore = calculatePerformanceScore(
    vaultInfo.apr.averageApr,
    volatilityScore,
    userRetentionRate
  );
  
  return {
    vaultInfo,
    userRetentionRate,
    volatilityScore,
    performanceScore,
    dailyTrends: processDailyTrends(dailyData)
  };
}
```

#### Performance Optimization

**Query Optimization**

Optimize your queries to reduce response time and load on the subgraph:

1. **Select only necessary fields**:

   ```graphql
   # Instead of this
   {
     kodiakVaults {
       id
       name
       symbol
       # ... many more fields
     }
   }

   # Do this
   {
     kodiakVaults {
       id
       name
       totalValueLockedUSD
       # Only the fields you need
     }
   }
   ```
2. **Limit result sizes**:

   ```graphql
   {
     kodiakVaults(first: 20) {
       # fields
     }
   }
   ```
3. **Use efficient filtering**:

   ```graphql
   # Instead of fetching all and filtering client-side
   {
     kodiakVaults(where: { totalValueLockedUSD_gt: "1000000" }) {
       # fields
     }
   }
   ```

**Client-Side Caching**

Implement caching to reduce redundant queries:

```typescript
// Simple in-memory cache example
const cache = new Map();

async function fetchWithCache(query, variables, maxAge = 60000) {
  const cacheKey = JSON.stringify({ query, variables });
  
  if (cache.has(cacheKey)) {
    const { data, timestamp } = cache.get(cacheKey);
    if (Date.now() - timestamp < maxAge) {
      return data;
    }
  }
  
  const result = await executeQuery(query, variables);
  cache.set(cacheKey, {
    data: result,
    timestamp: Date.now()
  });
  
  return result;
}
```

**Batching Queries**

For applications that need multiple related pieces of data, batch your queries:

```graphql
query BatchedData($vaultId: ID!) {
  vault: kodiakVault(id: $vaultId) {
    id
    name
    totalValueLockedUSD
    apr {
      averageApr
    }
  }
  
  recentDeposits: kodiakDeposits(
    first: 5,
    orderBy: timestamp,
    orderDirection: desc,
    where: { vault: $vaultId }
  ) {
    timestamp
    amountUSD
  }
  
  dailyStats: kodiakVaultDailySnapshots(
    first: 7,
    orderBy: timestamp,
    orderDirection: desc,
    where: { vault: $vaultId }
  ) {
    timestamp
    dailyTotalFeesUSD
  }
}
```

#### Advanced Use Cases

**Strategy Analysis**

Analyze the effectiveness of different vault strategies by tracking changes to tick ranges:

```graphql
query StrategyEffectiveness($vaultId: ID!) {
  # Get all snapshots and process client-side
  snapshots: kodiakVaultDailySnapshots(
    orderBy: timestamp
    where: { vault: $vaultId }
  ) {
    timestamp
    lowerTick
    upperTick
    # If tickChanges is available in your snapshots, include it
    tickChanges {
      timestamp
      lowerTick
      upperTick
    }
    dailyTotalFeesUSD
    apr
  }
}
```

This data can be used to:

* Compare APR before and after strategy changes
* Identify optimal tick ranges for different market conditions
* Evaluate the effectiveness of strategy adjustments

**Portfolio Analysis**

For users with positions across multiple vaults, build portfolio analytics:

```graphql
query UserPortfolio($userAddress: String!) {
  # Get all user deposits
  deposits: kodiakDeposits(
    where: { from: $userAddress }
    orderBy: timestamp
  ) {
    vault {
      id
      name
      _token0 { 
        symbol 
      }
      _token1 { 
        symbol 
      }
    }
    timestamp
    amount
    amountUSD
  }
  
  # Get all user withdrawals
  withdrawals: kodiakWithdraws(
    where: { to: $userAddress }
    orderBy: timestamp
  ) {
    vault {
      id
      name
    }
    timestamp
    amount
    amountUSD
  }
}
```

With this data, you can:

* Calculate user's net position in each vault
* Estimate their portfolio value over time
* Calculate portfolio-wide performance metrics

**Vault Comparison Tool**

Build a tool to compare performance across vaults:

```graphql
query CompareVaults($vaultIds: [ID!]!) {
  vaults: kodiakVaults(
    where: { id_in: $vaultIds }
  ) {
    id
    name
    _token0 { 
      symbol 
    }
    _token1 { 
      symbol 
    }
    totalValueLockedUSD
    apr { 
      averageApr 
    }
    weeklyFeesEarnedUSD
  }
  
  # Get daily performance for each vault (last 30 days)
  dailyPerformance: kodiakVaultDailySnapshots(
    first: 30
    orderBy: timestamp
    orderDirection: desc
    where: { vault_in: $vaultIds }
  ) {
    vault { 
      id 
    }
    timestamp
    apr
    dailyTotalFeesUSD
    totalValueLockedUSD
  }
}
```

#### Working with Time Series Data

When working with time series data from the Kodiak Islands subgraph, consider these strategies:

1. **Handling Missing Data Points**: Daily and hourly snapshots may have missing data points. Implement interpolation strategies in your application to handle these gaps.
2. **Normalizing Timestamps**: Convert Unix timestamps to your local timezone for display:

   ```typescript
   function formatTimestamp(unixTimestamp) {
     return new Date(unixTimestamp * 1000).toLocaleString();
   }
   ```
3. **Grouping Data**: For longer time ranges, group data into periods (weekly, monthly):

   ```typescript
   function groupDataByWeek(dailyData) {
     const weeklyData = {};
     dailyData.forEach(day => {
       const weekNumber = getWeekNumber(day.timestamp);
       if (!weeklyData[weekNumber]) {
         weeklyData[weekNumber] = {
           totalFeesUSD: 0,
           avgTVL: 0,
           daysCount: 0
         };
       }
       weeklyData[weekNumber].totalFeesUSD += parseFloat(day.dailyTotalFeesUSD);
       weeklyData[weekNumber].avgTVL += parseFloat(day.totalValueLockedUSD);
       weeklyData[weekNumber].daysCount += 1;
     });
     
     // Calculate averages
     Object.keys(weeklyData).forEach(week => {
       weeklyData[week].avgTVL /= weeklyData[week].daysCount;
     });
     
     return weeklyData;
   }
   ```

#### Conclusion

This advanced guide has covered complex querying patterns, integration strategies, performance optimization, and various use cases for the Kodiak Islands subgraph. By leveraging these techniques, you can build sophisticated applications that provide powerful insights into the Kodiak Islands protocol and its vaults.

Remember that subgraph queries can be resource-intensive, so always optimize your queries and implement appropriate caching strategies. For very large-scale applications, consider implementing additional middleware to handle complex data processing and caching.

For any questions or issues with the subgraph, refer to the official Kodiak Islands documentation or contact the protocol team for support.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://documentation.kodiak.finance/developers/kodiak-islands/subgraph/advanced-usage-guide.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
