Cryptocurrency integration presents unique challenges including extreme volatility, regulatory uncertainty, and technical complexity. Building robust crypto exchange systems requires specialized approaches and risk management strategies.
Business Impact
- User experience enhancement
- Operational efficiency gains
- Cost optimization opportunities
- Risk mitigation strategies
Practical Implementation Examples
Cryptocurrency Price Feed Engine
// Production-ready cryptocurrency price feed engine with real-time data aggregation
interface PriceData {
symbol: string
price: number
change24h: number
changePercent24h: number
volume24h: number
marketCap: number
timestamp: number
source: string
confidence: number
}
interface AggregatedPrice {
symbol: string
price: number
spread: number
volume: number
sources: string[]
lastUpdated: number
volatility: number
outlierCount: number
confidence: number
}
interface PriceAlert {
id: string
symbol: string
condition: 'above' | 'below' | 'change'
threshold: number
currentValue: number
triggered: boolean
createdAt: number
triggeredAt?: number
}
interface ExchangeRate {
from: string
to: string
rate: number
inverse: number
timestamp: number
source: string
}
class CryptocurrencyPriceFeedEngine {
private priceCache: Map<string, PriceData[]> = new Map()
private aggregatedPrices: Map<string, AggregatedPrice> = new Map()
private priceAlerts: Map<string, PriceAlert> = new Map()
private exchangeRates: Map<string, Map<string, ExchangeRate>> = new Map()
private dataSources: Map<string, any> = new Map()
private circuitBreakers: Map<string, { isOpen: boolean; lastFail: number }> = new Map()
constructor() {
this.initializeDataSources()
this.startPriceAggregation()
this.startVolatilityMonitoring()
}
// Get real-time cryptocurrency price
async getPrice(symbol: string, useCache = true): Promise<AggregatedPrice | null> {
const normalizedSymbol = symbol.toUpperCase()
// Check circuit breaker
if (this.isCircuitBreakerOpen(normalizedSymbol)) {
return this.aggregatedPrices.get(normalizedSymbol) || null
}
try {
// Get prices from multiple sources
const sourcePrices = await this.fetchPricesFromSources(normalizedSymbol)
if (sourcePrices.length === 0) {
throw new Error(`No price data available for ${normalizedSymbol}`)
}
// Aggregate and validate prices
const aggregatedPrice = this.aggregatePrices(normalizedSymbol, sourcePrices)
// Cache the result
this.aggregatedPrices.set(normalizedSymbol, aggregatedPrice)
// Update exchange rates
await this.updateExchangeRates(normalizedSymbol, aggregatedPrice.price)
return aggregatedPrice
} catch (error) {
console.error(`Price fetch failed for ${normalizedSymbol}:`, error)
// Open circuit breaker on repeated failures
this.handlePriceFetchFailure(normalizedSymbol)
// Return cached price if available and within acceptable age
const cachedPrice = this.aggregatedPrices.get(normalizedSymbol)
if (cachedPrice && useCache && this.isCacheValid(cachedPrice)) {
return cachedPrice
}
return null
}
}
private async fetchPricesFromSources(symbol: string): Promise<PriceData[]> {
const sources = ['binance', 'coinbase', 'kraken', 'bybit', 'kucoin']
const pricePromises = sources.map(source => this.fetchFromSource(source, symbol))
const results = await Promise.allSettled(pricePromises)
return results
.filter((result): result is PromiseFulfilledResult<PriceData> => result.status === 'fulfilled')
.map(result => result.value)
.filter(price => this.validatePriceData(price))
}
private async fetchFromSource(source: string, symbol: string): Promise<PriceData> {
// In production, implement actual API calls to exchanges
// For demo, simulate API responses
await this.delay(Math.random() * 1000) // Simulate network latency
// Simulate occasional API failures
if (Math.random() < 0.1) {
throw new Error(`API failure for ${source}`)
}
const basePrice = this.getBasePrice(symbol)
const variance = (Math.random() - 0.5) * 0.02 // ±1% variance
const price = basePrice * (1 + variance)
return {
symbol,
price,
change24h: (Math.random() - 0.5) * 0.1 * basePrice,
changePercent24h: (Math.random() - 0.5) * 10,
volume24h: Math.random() * 1000000000,
marketCap: basePrice * (Math.random() * 1000000000 + 100000000),
timestamp: Date.now(),
source,
confidence: 0.8 + Math.random() * 0.2
}
}
private getBasePrice(symbol: string): number {
const basePrices: Record<string, number> = {
'BTC': 45000,
'ETH': 2500,
'BNB': 300,
'ADA': 0.5,
'SOL': 100,
'DOT': 8,
'AVAX': 20,
'MATIC': 0.8,
'LINK': 15,
'UNI': 6
}
return basePrices[symbol] || 1
}
private validatePriceData(price: PriceData): boolean {
return (
price.price > 0 &&
price.volume24h >= 0 &&
price.confidence > 0.5 &&
price.timestamp > Date.now() - 300000 // Within last 5 minutes
)
}
private aggregatePrices(symbol: string, prices: PriceData[]): AggregatedPrice {
// Remove outliers using IQR method
const priceValues = prices.map(p => p.price).sort((a, b) => a - b)
const q1 = priceValues[Math.floor(priceValues.length * 0.25)]
const q3 = priceValues[Math.floor(priceValues.length * 0.75)]
const iqr = q3 - q1
const lowerBound = q1 - 1.5 * iqr
const upperBound = q3 + 1.5 * iqr
const validPrices = prices.filter(p => p.price >= lowerBound && p.price <= upperBound)
const outlierCount = prices.length - validPrices.length
// Calculate weighted average price
const totalWeight = validPrices.reduce((sum, p) => sum + p.confidence, 0)
const weightedPrice = validPrices.reduce((sum, p) => sum + p.price * p.confidence, 0) / totalWeight
// Calculate spread (difference between highest and lowest valid prices)
const minPrice = Math.min(...validPrices.map(p => p.price))
const maxPrice = Math.max(...validPrices.map(p => p.price))
const spread = maxPrice - minPrice
// Calculate total volume
const totalVolume = validPrices.reduce((sum, p) => sum + p.volume24h, 0)
// Calculate volatility (coefficient of variation)
const mean = validPrices.reduce((sum, p) => sum + p.price, 0) / validPrices.length
const variance = validPrices.reduce((sum, p) => sum + Math.pow(p.price - mean, 2), 0) / validPrices.length
const volatility = Math.sqrt(variance) / mean
return {
symbol,
price: weightedPrice,
spread,
volume: totalVolume,
sources: validPrices.map(p => p.source),
lastUpdated: Date.now(),
volatility,
outlierCount,
confidence: validPrices.reduce((sum, p) => sum + p.confidence, 0) / validPrices.length
}
}
private async updateExchangeRates(symbol: string, price: number): Promise<void> {
// Update USD exchange rates
if (!this.exchangeRates.has(symbol)) {
this.exchangeRates.set(symbol, new Map())
}
const symbolRates = this.exchangeRates.get(symbol)!
// Update USD rate
symbolRates.set('USD', {
from: symbol,
to: 'USD',
rate: price,
inverse: 1 / price,
timestamp: Date.now(),
source: 'aggregated'
})
// Update cross rates with other major cryptocurrencies
const majorCryptos = ['BTC', 'ETH', 'BNB']
for (const otherSymbol of majorCryptos) {
if (otherSymbol === symbol) continue
const otherPrice = this.aggregatedPrices.get(otherSymbol)?.price || 1
const crossRate = price / otherPrice
symbolRates.set(otherSymbol, {
from: symbol,
to: otherSymbol,
rate: crossRate,
inverse: 1 / crossRate,
timestamp: Date.now(),
source: 'cross-calculated'
})
}
}
private isCircuitBreakerOpen(symbol: string): boolean {
const breaker = this.circuitBreakers.get(symbol)
return breaker?.isOpen && (Date.now() - breaker.lastFail) < 300000 // 5 minutes
}
private handlePriceFetchFailure(symbol: string): void {
const breaker = this.circuitBreakers.get(symbol) || { isOpen: false, lastFail: 0 }
if (!breaker.isOpen) {
// Open circuit breaker after first failure
breaker.isOpen = true
breaker.lastFail = Date.now()
this.circuitBreakers.set(symbol, breaker)
}
}
private isCacheValid(aggregatedPrice: AggregatedPrice): boolean {
return (Date.now() - aggregatedPrice.lastUpdated) < 60000 // 1 minute cache
}
private initializeDataSources(): void {
const sources = [
{
name: 'binance',
baseUrl: 'https://api.binance.com/api/v3',
rateLimit: 1000, // requests per minute
lastRequest: 0,
weight: 0.9
},
{
name: 'coinbase',
baseUrl: 'https://api.coinbase.com/v2',
rateLimit: 200,
lastRequest: 0,
weight: 0.8
}
]
sources.forEach(source => {
this.dataSources.set(source.name, source)
})
}
private async startPriceAggregation(): Promise<void> {
const majorCryptos = ['BTC', 'ETH', 'BNB', 'ADA', 'SOL', 'DOT']
// Aggregate prices every 30 seconds
setInterval(async () => {
for (const symbol of majorCryptos) {
try {
await this.getPrice(symbol, false)
} catch (error) {
console.error(`Price aggregation failed for ${symbol}:`, error)
}
}
}, 30000)
}
private async startVolatilityMonitoring(): Promise<void> {
// Monitor price volatility every 5 minutes
setInterval(() => {
this.updateVolatilityMetrics()
}, 300000)
}
private updateVolatilityMetrics(): void {
for (const [symbol, price] of this.aggregatedPrices) {
const historicalPrices = this.priceCache.get(symbol) || []
if (historicalPrices.length >= 20) {
// Calculate realized volatility
const returns = []
for (let i = 1; i < historicalPrices.length; i++) {
const return_pct = (historicalPrices[i].price - historicalPrices[i-1].price) / historicalPrices[i-1].price
returns.push(return_pct)
}
const meanReturn = returns.reduce((sum, r) => sum + r, 0) / returns.length
const variance = returns.reduce((sum, r) => sum + Math.pow(r - meanReturn, 2), 0) / returns.length
const volatility = Math.sqrt(variance * 365) // Annualized volatility
// Update price object with new volatility
price.volatility = volatility
}
}
}
// Set price alert
setAlert(symbol: string, condition: PriceAlert['condition'], threshold: number): string {
const alertId = `alert_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
const alert: PriceAlert = {
id: alertId,
symbol: symbol.toUpperCase(),
condition,
threshold,
currentValue: this.aggregatedPrices.get(symbol.toUpperCase())?.price || 0,
triggered: false,
createdAt: Date.now()
}
this.priceAlerts.set(alertId, alert)
// Start monitoring this alert
this.monitorAlert(alertId)
return alertId
}
private monitorAlert(alertId: string): void {
const alert = this.priceAlerts.get(alertId)
if (!alert) return
const checkInterval = setInterval(() => {
const currentPrice = this.aggregatedPrices.get(alert.symbol)?.price || 0
alert.currentValue = currentPrice
this.priceAlerts.set(alertId, alert)
if (this.shouldTriggerAlert(alert, currentPrice)) {
alert.triggered = true
alert.triggeredAt = Date.now()
this.priceAlerts.set(alertId, alert)
console.log(`Price alert triggered: ${alert.symbol} ${alert.condition} ${alert.threshold}`)
// In production, send notifications
this.sendAlertNotification(alert)
clearInterval(checkInterval)
}
}, 5000) // Check every 5 seconds
}
private shouldTriggerAlert(alert: PriceAlert, currentPrice: number): boolean {
switch (alert.condition) {
case 'above':
return currentPrice > alert.threshold
case 'below':
return currentPrice < alert.threshold
case 'change':
const changePercent = Math.abs((currentPrice - alert.threshold) / alert.threshold) * 100
return changePercent >= 1 // Trigger on 1% change
default:
return false
}
}
private sendAlertNotification(alert: PriceAlert): void {
// In production, integrate with notification systems (Slack, email, SMS, etc.)
console.log(`🚨 PRICE ALERT: ${alert.symbol} ${alert.condition} ${alert.threshold}. Current: ${alert.currentValue}`)
}
// Get exchange rate between two cryptocurrencies
getExchangeRate(from: string, to: string): ExchangeRate | null {
const fromSymbol = from.toUpperCase()
const toSymbol = to.toUpperCase()
if (fromSymbol === toSymbol) {
return {
from: fromSymbol,
to: toSymbol,
rate: 1,
inverse: 1,
timestamp: Date.now(),
source: 'identity'
}
}
// Try direct rate first
const fromRates = this.exchangeRates.get(fromSymbol)
if (fromRates) {
const directRate = fromRates.get(toSymbol)
if (directRate) return directRate
}
// Calculate cross rate via USD
const fromUsdRate = this.exchangeRates.get(fromSymbol)?.get('USD')
const toUsdRate = this.exchangeRates.get(toSymbol)?.get('USD')
if (fromUsdRate && toUsdRate) {
return {
from: fromSymbol,
to: toSymbol,
rate: fromUsdRate.inverse / toUsdRate.inverse,
inverse: toUsdRate.inverse / fromUsdRate.inverse,
timestamp: Math.max(fromUsdRate.timestamp, toUsdRate.timestamp),
source: 'cross-via-usd'
}
}
return null
}
// Batch price update for multiple symbols
async updateMultiplePrices(symbols: string[]): Promise<Map<string, AggregatedPrice>> {
const pricePromises = symbols.map(symbol => this.getPrice(symbol, false))
const results = await Promise.allSettled(pricePromises)
const priceMap = new Map<string, AggregatedPrice>()
results.forEach((result, index) => {
if (result.status === 'fulfilled' && result.value) {
priceMap.set(symbols[index], result.value)
}
})
return priceMap
}
// Get price history for analysis
getPriceHistory(symbol: string, hours: number = 24): PriceData[] {
const cachedPrices = this.priceCache.get(symbol) || []
const cutoffTime = Date.now() - (hours * 60 * 60 * 1000)
return cachedPrices.filter(price => price.timestamp >= cutoffTime)
}
// Cache price data
cachePriceData(price: PriceData): void {
const symbol = price.symbol
if (!this.priceCache.has(symbol)) {
this.priceCache.set(symbol, [])
}
const prices = this.priceCache.get(symbol)!
prices.push(price)
// Keep only last 1000 price points
if (prices.length > 1000) {
prices.shift()
}
}
private delay(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms))
}
// Get aggregated price statistics
getPriceStatistics(symbol: string, period: '1h' | '24h' | '7d'): {
high: number
low: number
average: number
volatility: number
volume: number
} | null {
const history = this.getPriceHistory(symbol, period === '1h' ? 1 : period === '24h' ? 24 : 168)
if (history.length === 0) return null
const prices = history.map(h => h.price)
const volumes = history.map(h => h.volume24h)
return {
high: Math.max(...prices),
low: Math.min(...prices),
average: prices.reduce((sum, p) => sum + p, 0) / prices.length,
volatility: this.calculateVolatility(prices),
volume: volumes.reduce((sum, v) => sum + v, 0)
}
}
private calculateVolatility(prices: number[]): number {
if (prices.length < 2) return 0
const returns = []
for (let i = 1; i < prices.length; i++) {
returns.push((prices[i] - prices[i-1]) / prices[i-1])
}
const mean = returns.reduce((sum, r) => sum + r, 0) / returns.length
const variance = returns.reduce((sum, r) => sum + Math.pow(r - mean, 2), 0) / returns.length
return Math.sqrt(variance)
}
}
// Initialize cryptocurrency price feed engine
const cryptoPriceFeed = new CryptocurrencyPriceFeedEngine()
// Price feed API endpoints
app.get('/api/crypto/price/:symbol', async (req, res) => {
try {
const { symbol } = req.params
if (!symbol) {
return res.status(400).json({ error: 'Symbol required' })
}
const price = await cryptoPriceFeed.getPrice(symbol)
if (!price) {
return res.status(404).json({ error: 'Price not available' })
}
res.json({
price,
timestamp: new Date().toISOString()
})
} catch (error) {
console.error('Price fetch error:', error)
res.status(500).json({ error: 'Failed to fetch price' })
}
})
// Batch price endpoint
app.post('/api/crypto/prices', async (req, res) => {
try {
const { symbols } = req.body
if (!Array.isArray(symbols) || symbols.length === 0) {
return res.status(400).json({ error: 'Symbols array required' })
}
const prices = await cryptoPriceFeed.updateMultiplePrices(symbols)
res.json({
prices: Array.from(prices.entries()).map(([symbol, price]) => ({ symbol, ...price })),
timestamp: new Date().toISOString()
})
} catch (error) {
console.error('Batch price fetch error:', error)
res.status(500).json({ error: 'Failed to fetch prices' })
}
})
// Price alert endpoint
app.post('/api/crypto/alert', (req, res) => {
try {
const { symbol, condition, threshold } = req.body
if (!symbol || !condition || threshold === undefined) {
return res.status(400).json({
error: 'symbol, condition, and threshold required'
})
}
if (!['above', 'below', 'change'].includes(condition)) {
return res.status(400).json({
error: 'Invalid condition. Must be above, below, or change'
})
}
const alertId = cryptoPriceFeed.setAlert(symbol, condition, threshold)
res.json({
success: true,
alertId,
message: 'Price alert set successfully',
timestamp: new Date().toISOString()
})
} catch (error) {
console.error('Set alert error:', error)
res.status(500).json({ error: 'Failed to set alert' })
}
})
// Exchange rate endpoint
app.get('/api/crypto/exchange-rate/:from/:to', (req, res) => {
try {
const { from, to } = req.params
if (!from || !to) {
return res.status(400).json({ error: 'from and to symbols required' })
}
const rate = cryptoPriceFeed.getExchangeRate(from, to)
if (!rate) {
return res.status(404).json({ error: 'Exchange rate not available' })
}
res.json({
rate,
timestamp: new Date().toISOString()
})
} catch (error) {
console.error('Exchange rate error:', error)
res.status(500).json({ error: 'Failed to get exchange rate' })
}
})
// Price statistics endpoint
app.get('/api/crypto/statistics/:symbol/:period', (req, res) => {
try {
const { symbol, period } = req.params
if (!symbol || !period) {
return res.status(400).json({ error: 'symbol and period required' })
}
if (!['1h', '24h', '7d'].includes(period)) {
return res.status(400).json({
error: 'Invalid period. Must be 1h, 24h, or 7d'
})
}
const statistics = cryptoPriceFeed.getPriceStatistics(symbol, period as any)
if (!statistics) {
return res.status(404).json({ error: 'Statistics not available' })
}
res.json({
statistics,
symbol,
period,
timestamp: new Date().toISOString()
})
} catch (error) {
console.error('Statistics error:', error)
res.status(500).json({ error: 'Failed to get statistics' })
}
})
console.log('Cryptocurrency Price Feed Engine initialized')
Volatility Management System
// Advanced volatility management system for cryptocurrency markets
interface VolatilityMetrics {
symbol: string
currentVolatility: number
historicalVolatility: number
impliedVolatility: number
volatilityRegime: 'low' | 'normal' | 'high' | 'extreme'
trend: 'increasing' | 'decreasing' | 'stable'
confidence: number
lastUpdated: number
}
interface VolatilityAlert {
id: string
symbol: string
type: 'threshold' | 'regime_change' | 'spike'
severity: 'low' | 'medium' | 'high' | 'critical'
message: string
triggered: boolean
createdAt: number
resolvedAt?: number
}
interface RiskAdjustment {
symbol: string
basePositionSize: number
adjustedPositionSize: number
volatilityMultiplier: number
confidenceAdjustment: number
recommendedHedgeRatio: number
maxDrawdown: number
timestamp: number
}
class CryptocurrencyVolatilityManager {
private volatilityMetrics: Map<string, VolatilityMetrics> = new Map()
private volatilityHistory: Map<string, number[]> = new Map()
private volatilityAlerts: Map<string, VolatilityAlert> = new Map()
private riskAdjustments: Map<string, RiskAdjustment> = new Map()
private volatilityModels: Map<string, any> = new Map()
constructor() {
this.initializeVolatilityModels()
this.startVolatilityMonitoring()
this.startRiskAdjustmentCalculation()
}
// Calculate comprehensive volatility metrics
async calculateVolatilityMetrics(symbol: string): Promise<VolatilityMetrics> {
const priceHistory = this.volatilityHistory.get(symbol) || []
if (priceHistory.length < 20) {
throw new Error(`Insufficient price history for ${symbol}`)
}
try {
// Calculate current (realized) volatility
const currentVolatility = this.calculateRealizedVolatility(priceHistory.slice(-20))
// Calculate historical volatility (longer timeframe)
const historicalVolatility = this.calculateHistoricalVolatility(priceHistory.slice(-100))
// Estimate implied volatility (using options data in production)
const impliedVolatility = this.estimateImpliedVolatility(symbol, currentVolatility)
// Determine volatility regime
const volatilityRegime = this.determineVolatilityRegime(currentVolatility)
// Analyze volatility trend
const trend = this.analyzeVolatilityTrend(symbol, currentVolatility)
// Calculate confidence level
const confidence = this.calculateVolatilityConfidence(priceHistory, currentVolatility)
const metrics: VolatilityMetrics = {
symbol,
currentVolatility,
historicalVolatility,
impliedVolatility,
volatilityRegime,
trend,
confidence,
lastUpdated: Date.now()
}
this.volatilityMetrics.set(symbol, metrics)
return metrics
} catch (error) {
console.error(`Volatility calculation failed for ${symbol}:`, error)
// Return default metrics
return {
symbol,
currentVolatility: 0.5,
historicalVolatility: 0.5,
impliedVolatility: 0.5,
volatilityRegime: 'normal',
trend: 'stable',
confidence: 0.5,
lastUpdated: Date.now()
}
}
}
private calculateRealizedVolatility(prices: number[]): number {
if (prices.length < 2) return 0
const returns = []
for (let i = 1; i < prices.length; i++) {
const dailyReturn = Math.log(prices[i] / prices[i-1])
returns.push(dailyReturn)
}
const mean = returns.reduce((sum, r) => sum + r, 0) / returns.length
const variance = returns.reduce((sum, r) => sum + Math.pow(r - mean, 2), 0) / returns.length
// Annualize daily volatility
return Math.sqrt(variance * 365)
}
private calculateHistoricalVolatility(prices: number[]): number {
return this.calculateRealizedVolatility(prices)
}
private estimateImpliedVolatility(symbol: string, realizedVol: number): number {
// In production, use actual options data
// For demo, use a simple adjustment based on market conditions
const marketAdjustment = 0.8 + Math.random() * 0.4 // 0.8 to 1.2 multiplier
const baseImpliedVol = realizedVol * marketAdjustment
// Add market stress factor
const stressFactor = this.getMarketStressFactor()
return baseImpliedVol * (1 + stressFactor)
}
private getMarketStressFactor(): number {
// In production, analyze market indicators like VIX, funding rates, etc.
return Math.random() * 0.3 // 0 to 0.3 stress factor
}
private determineVolatilityRegime(volatility: number): VolatilityMetrics['volatilityRegime'] {
if (volatility < 0.3) return 'low'
if (volatility < 0.6) return 'normal'
if (volatility < 1.0) return 'high'
return 'extreme'
}
private analyzeVolatilityTrend(symbol: string, currentVol: number): VolatilityMetrics['trend'] {
const metrics = this.volatilityMetrics.get(symbol)
if (!metrics) return 'stable'
const volChange = (currentVol - metrics.currentVolatility) / metrics.currentVolatility
if (volChange > 0.1) return 'increasing'
if (volChange < -0.1) return 'decreasing'
return 'stable'
}
private calculateVolatilityConfidence(prices: number[], volatility: number): number {
// Higher confidence with more data points and stable regime
const dataPointFactor = Math.min(prices.length / 100, 1) // Max confidence at 100+ points
const stabilityFactor = Math.max(0, 1 - Math.abs(volatility - 0.5)) // Higher confidence at moderate volatility
return (dataPointFactor + stabilityFactor) / 2
}
private initializeVolatilityModels(): void {
// Initialize GARCH, EWMA, and other volatility models
const models = [
{
name: 'GARCH(1,1)',
parameters: { alpha: 0.1, beta: 0.8, omega: 0.0001 }
},
{
name: 'EWMA',
parameters: { lambda: 0.94 }
}
]
models.forEach(model => {
this.volatilityModels.set(model.name, model)
})
}
private startVolatilityMonitoring(): void {
// Monitor volatility every 5 minutes
setInterval(async () => {
const symbols = Array.from(this.volatilityHistory.keys())
for (const symbol of symbols) {
try {
await this.calculateVolatilityMetrics(symbol)
// Check for volatility alerts
this.checkVolatilityAlerts(symbol)
} catch (error) {
console.error(`Volatility monitoring failed for ${symbol}:`, error)
}
}
}, 300000)
}
private checkVolatilityAlerts(symbol: string): void {
const metrics = this.volatilityMetrics.get(symbol)
if (!metrics) return
// Threshold alerts
if (metrics.currentVolatility > 1.2 && metrics.volatilityRegime === 'extreme') {
this.createVolatilityAlert(symbol, 'threshold', 'critical',
`Extreme volatility detected: ${(metrics.currentVolatility * 100).toFixed(1)}%`)
}
// Regime change alerts
if (metrics.trend === 'increasing' && metrics.volatilityRegime === 'high') {
this.createVolatilityAlert(symbol, 'regime_change', 'high',
'Volatility increasing towards extreme levels')
}
}
private createVolatilityAlert(symbol: string, type: string, severity: string, message: string): void {
const alertId = `vol_alert_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
const alert: VolatilityAlert = {
id: alertId,
symbol,
type: type as any,
severity: severity as any,
message,
triggered: true,
createdAt: Date.now()
}
this.volatilityAlerts.set(alertId, alert)
console.log(`🚨 VOLATILITY ALERT [${severity.toUpperCase()}]: ${symbol} - ${message}`)
}
private startRiskAdjustmentCalculation(): void {
// Calculate risk adjustments every minute
setInterval(() => {
this.calculateAllRiskAdjustments()
}, 60000)
}
private calculateAllRiskAdjustments(): void {
const symbols = Array.from(this.volatilityMetrics.keys())
for (const symbol of symbols) {
try {
const adjustment = this.calculateRiskAdjustment(symbol)
this.riskAdjustments.set(symbol, adjustment)
} catch (error) {
console.error(`Risk adjustment calculation failed for ${symbol}:`, error)
}
}
}
private calculateRiskAdjustment(symbol: string): RiskAdjustment {
const metrics = this.volatilityMetrics.get(symbol)
if (!metrics) {
throw new Error(`No volatility metrics available for ${symbol}`)
}
// Base position size (in production, use portfolio allocation)
const basePositionSize = 1000000 // $1M base position
// Volatility multiplier (inverse relationship)
const volatilityMultiplier = Math.max(0.1, 1 / (1 + metrics.currentVolatility))
// Confidence adjustment
const confidenceAdjustment = metrics.confidence
// Adjusted position size
const adjustedPositionSize = basePositionSize * volatilityMultiplier * confidenceAdjustment
// Recommended hedge ratio based on volatility
const recommendedHedgeRatio = Math.min(0.8, metrics.currentVolatility * 0.6)
// Maximum drawdown estimate
const maxDrawdown = metrics.currentVolatility * 2 // Conservative estimate
return {
symbol,
basePositionSize,
adjustedPositionSize,
volatilityMultiplier,
confidenceAdjustment,
recommendedHedgeRatio,
maxDrawdown,
timestamp: Date.now()
}
}
// Get volatility metrics for a symbol
getVolatilityMetrics(symbol: string): VolatilityMetrics | null {
return this.volatilityMetrics.get(symbol) || null
}
// Get risk adjustment for a symbol
getRiskAdjustment(symbol: string): RiskAdjustment | null {
return this.riskAdjustments.get(symbol) || null
}
// Update price history for volatility calculation
updatePriceHistory(symbol: string, price: number): void {
if (!this.volatilityHistory.has(symbol)) {
this.volatilityHistory.set(symbol, [])
}
const history = this.volatilityHistory.get(symbol)!
history.push(price)
// Keep only last 1000 data points
if (history.length > 1000) {
history.shift()
}
}
// Get volatility alerts
getActiveVolatilityAlerts(): VolatilityAlert[] {
return Array.from(this.volatilityAlerts.values())
.filter(alert => alert.triggered && !alert.resolvedAt)
}
// Resolve volatility alert
resolveVolatilityAlert(alertId: string): boolean {
const alert = this.volatilityAlerts.get(alertId)
if (!alert) return false
alert.resolvedAt = Date.now()
this.volatilityAlerts.set(alertId, alert)
return true
}
// Generate volatility report
generateVolatilityReport(): {
totalSymbols: number
extremeVolatility: string[]
highVolatility: string[]
normalVolatility: string[]
lowVolatility: string[]
alerts: number
averageVolatility: number
riskAdjustments: number
} {
const symbols = Array.from(this.volatilityMetrics.keys())
const metrics = symbols.map(s => this.volatilityMetrics.get(s)!).filter(Boolean)
const extremeVolatility = metrics.filter(m => m.volatilityRegime === 'extreme').map(m => m.symbol)
const highVolatility = metrics.filter(m => m.volatilityRegime === 'high').map(m => m.symbol)
const normalVolatility = metrics.filter(m => m.volatilityRegime === 'normal').map(m => m.symbol)
const lowVolatility = metrics.filter(m => m.volatilityRegime === 'low').map(m => m.symbol)
const averageVolatility = metrics.reduce((sum, m) => sum + m.currentVolatility, 0) / metrics.length
const activeAlerts = this.getActiveVolatilityAlerts().length
return {
totalSymbols: symbols.length,
extremeVolatility,
highVolatility,
normalVolatility,
lowVolatility,
alerts: activeAlerts,
averageVolatility,
riskAdjustments: this.riskAdjustments.size
}
}
}
// Initialize volatility management system
const volatilityManager = new CryptocurrencyVolatilityManager()
// Volatility metrics endpoint
app.get('/api/crypto/volatility/:symbol', async (req, res) => {
try {
const { symbol } = req.params
if (!symbol) {
return res.status(400).json({ error: 'Symbol required' })
}
const metrics = await volatilityManager.calculateVolatilityMetrics(symbol)
res.json({
metrics,
timestamp: new Date().toISOString()
})
} catch (error) {
console.error('Volatility metrics error:', error)
res.status(500).json({ error: 'Failed to calculate volatility metrics' })
}
})
// Risk adjustment endpoint
app.get('/api/crypto/risk-adjustment/:symbol', (req, res) => {
try {
const { symbol } = req.params
if (!symbol) {
return res.status(400).json({ error: 'Symbol required' })
}
const adjustment = volatilityManager.getRiskAdjustment(symbol)
if (!adjustment) {
return res.status(404).json({ error: 'Risk adjustment not available' })
}
res.json({
adjustment,
timestamp: new Date().toISOString()
})
} catch (error) {
console.error('Risk adjustment error:', error)
res.status(500).json({ error: 'Failed to get risk adjustment' })
}
})
// Volatility alerts endpoint
app.get('/api/crypto/volatility-alerts', (req, res) => {
try {
const alerts = volatilityManager.getActiveVolatilityAlerts()
res.json({
alerts,
count: alerts.length,
timestamp: new Date().toISOString()
})
} catch (error) {
console.error('Volatility alerts error:', error)
res.status(500).json({ error: 'Failed to get volatility alerts' })
}
})
// Volatility report endpoint
app.get('/api/crypto/volatility-report', (req, res) => {
try {
const report = volatilityManager.generateVolatilityReport()
res.json({
report,
timestamp: new Date().toISOString()
})
} catch (error) {
console.error('Volatility report error:', error)
res.status(500).json({ error: 'Failed to generate volatility report' })
}
})
console.log('Cryptocurrency Volatility Management System initialized')
Settlement and Accounting
Choosing how you settle crypto amounts impacts user pricing and PnL.
Pricing Windows and Quotes
- Quote modes: firm quote (locked n seconds) vs indicative (refreshing)
- Price sources: mid, best bid/ask, VWAP over window
- Slippage controls: max deviation %, reject if exceeded
- Fees/spread: explicit vs embedded; disclose to users
Settlement Models
- Instant convert to fiat (no crypto custody; exchange execution risk)
- Deferred batch conversion (better fees; inventory risk during window)
- Natural hedging (match in/out flows; net exposure control)
- On-chain settle (monitor mempool, confirmations; reorg handling)
Accounting Considerations
- Lot tracking (FIFO/LIFO) for inventory valuation
- PnL recognition on conversion vs at delivery
- FX triangulation: CRYPTO→USD→LOCAL; record both legs
- Reconciliation: exchange fills vs internal quotes, daily
Risk and Compliance
- Volatility limits: circuit breakers on extreme spread/vol
- Exchange failover: multi-venue routing; health/latency scoring
- Wallet hygiene: allowlist addresses, chain risk screening
- AML/KYC: Travel Rule where applicable, sanctions screening
- Geo controls: restrict unsupported jurisdictions
Monitoring and SRE
- Golden signals: price latency, spread, error rate, quote success
- SLIs/SLOs: p95 quote latency, price staleness < 10s, fill success rate
- Alerting: datasource lag, diverging sources, spread spikes, circuit open
- Runbooks: datasource failover, stale pricing, extreme volatility days
Conclusion
Crypto integration succeeds with resilient pricing, clear settlement, and strict risk controls. Start with firm quotes + instant conversion, add venues for redundancy, and continuously monitor spreads and latency.
Build robust crypto pricing with our aggregation and risk tooling: multi-venue feeds, volatility controls, and audit-ready accounting hooks.