stock-bot/apps/data-service/src/providers/quotemedia.provider.ts
2025-06-09 22:55:51 -04:00

175 lines
6.1 KiB
TypeScript

import { ProviderConfig } from '../services/provider-registry.service';
import { getLogger } from '@stock-bot/logger';
const logger = getLogger('quotemedia-provider');
export const quotemediaProvider: ProviderConfig = {
name: 'quotemedia',
service: 'market-data',
operations: { 'live-data': async (payload: { symbol: string; fields?: string[] }) => {
logger.info('Fetching live data from QuoteMedia', { symbol: payload.symbol });
// Simulate QuoteMedia API call
const mockData = {
symbol: payload.symbol,
price: Math.random() * 1000 + 100,
volume: Math.floor(Math.random() * 1000000),
change: (Math.random() - 0.5) * 20,
changePercent: (Math.random() - 0.5) * 5,
timestamp: new Date().toISOString(),
source: 'quotemedia',
fields: payload.fields || ['price', 'volume', 'change']
};
// Simulate network delay
await new Promise(resolve => setTimeout(resolve, 100 + Math.random() * 200));
return mockData;
},
'historical-data': async (payload: {
symbol: string;
from: Date;
to: Date;
interval?: string;
fields?: string[]; }) => {
logger.info('Fetching historical data from QuoteMedia', {
symbol: payload.symbol,
from: payload.from,
to: payload.to,
interval: payload.interval || '1d'
});
// Generate mock historical data
const days = Math.ceil((payload.to.getTime() - payload.from.getTime()) / (1000 * 60 * 60 * 24));
const data = [];
for (let i = 0; i < Math.min(days, 100); i++) {
const date = new Date(payload.from.getTime() + i * 24 * 60 * 60 * 1000);
data.push({
date: date.toISOString().split('T')[0],
open: Math.random() * 1000 + 100,
high: Math.random() * 1000 + 100,
low: Math.random() * 1000 + 100,
close: Math.random() * 1000 + 100,
volume: Math.floor(Math.random() * 1000000),
source: 'quotemedia'
});
}
// Simulate network delay
await new Promise(resolve => setTimeout(resolve, 200 + Math.random() * 300));
return {
symbol: payload.symbol,
interval: payload.interval || '1d',
data,
source: 'quotemedia',
totalRecords: data.length
};
},
'batch-quotes': async (payload: { symbols: string[]; fields?: string[] }) => {
logger.info('Fetching batch quotes from QuoteMedia', {
symbols: payload.symbols,
count: payload.symbols.length
});
const quotes = payload.symbols.map(symbol => ({
symbol,
price: Math.random() * 1000 + 100,
volume: Math.floor(Math.random() * 1000000),
change: (Math.random() - 0.5) * 20,
timestamp: new Date().toISOString(),
source: 'quotemedia'
}));
// Simulate network delay
await new Promise(resolve => setTimeout(resolve, 300 + Math.random() * 200));
return {
quotes,
source: 'quotemedia',
timestamp: new Date().toISOString(),
totalSymbols: payload.symbols.length
};
}, 'company-profile': async (payload: { symbol: string }) => {
logger.info('Fetching company profile from QuoteMedia', { symbol: payload.symbol });
// Simulate company profile data
const profile = {
symbol: payload.symbol,
companyName: `${payload.symbol} Corporation`,
sector: 'Technology',
industry: 'Software',
description: `${payload.symbol} is a leading technology company.`,
marketCap: Math.floor(Math.random() * 1000000000000),
employees: Math.floor(Math.random() * 100000),
website: `https://www.${payload.symbol.toLowerCase()}.com`,
source: 'quotemedia'
};
await new Promise(resolve => setTimeout(resolve, 150 + Math.random() * 100));
return profile;
}, 'options-chain': async (payload: { symbol: string; expiration?: string }) => {
logger.info('Fetching options chain from QuoteMedia', {
symbol: payload.symbol,
expiration: payload.expiration
});
// Generate mock options data
const strikes = Array.from({ length: 20 }, (_, i) => 100 + i * 5);
const calls = strikes.map(strike => ({
strike,
bid: Math.random() * 10,
ask: Math.random() * 10 + 0.5,
volume: Math.floor(Math.random() * 1000),
openInterest: Math.floor(Math.random() * 5000)
}));
const puts = strikes.map(strike => ({
strike,
bid: Math.random() * 10,
ask: Math.random() * 10 + 0.5,
volume: Math.floor(Math.random() * 1000),
openInterest: Math.floor(Math.random() * 5000)
}));
await new Promise(resolve => setTimeout(resolve, 400 + Math.random() * 300));
return {
symbol: payload.symbol,
expiration: payload.expiration || new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
calls,
puts,
source: 'quotemedia'
};
}
},
scheduledJobs: [
// {
// type: 'quotemedia-premium-refresh',
// operation: 'batch-quotes',
// payload: { symbols: ['AAPL', 'GOOGL', 'MSFT'] },
// cronPattern: '*/2 * * * *', // Every 2 minutes
// priority: 7,
// description: 'Refresh premium quotes with detailed market data'
// },
// {
// type: 'quotemedia-options-update',
// operation: 'options-chain',
// payload: { symbol: 'SPY' },
// cronPattern: '*/10 * * * *', // Every 10 minutes
// priority: 5,
// description: 'Update options chain data for SPY ETF'
// },
// {
// type: 'quotemedia-profiles',
// operation: 'company-profile',
// payload: { symbol: 'AAPL' },
// cronPattern: '0 9 * * 1-5', // Weekdays at 9 AM
// priority: 3,
// description: 'Update company profile data'
// }
]
};