216 lines
6.7 KiB
TypeScript
216 lines
6.7 KiB
TypeScript
/**
|
|
* Example: Enhanced Data Service with Multi-Database Support
|
|
*
|
|
* This shows how to update your existing data service to leverage
|
|
* the new multi-database MongoDB client functionality.
|
|
*/
|
|
|
|
import { getLogger } from '@stock-bot/logger';
|
|
import { MongoDBClient, setDefaultDatabase } from '@stock-bot/mongodb-client';
|
|
|
|
const logger = getLogger('enhanced-data-service');
|
|
|
|
export class EnhancedDataService {
|
|
private mongoClient = MongoDBClient.getInstance();
|
|
|
|
async initialize() {
|
|
// Connect to MongoDB
|
|
await this.mongoClient.connect();
|
|
|
|
// Set stock as default database for market data operations
|
|
setDefaultDatabase('stock');
|
|
logger.info('Enhanced data service initialized with multi-database support');
|
|
}
|
|
|
|
/**
|
|
* Save Interactive Brokers data to stock database
|
|
*/
|
|
async saveIBMarketData(exchanges: any[], symbols: any[]) {
|
|
logger.info('Saving IB market data to stock database');
|
|
|
|
// These use the default 'stock' database
|
|
const exchangeResult = await this.mongoClient.batchUpsert(
|
|
'exchanges',
|
|
exchanges,
|
|
'exchange_id'
|
|
);
|
|
|
|
const symbolResult = await this.mongoClient.batchUpsert('symbols', symbols, 'symbol');
|
|
|
|
// Or use convenience method for cleaner code
|
|
// const exchangeResult = await this.mongoClient.batchUpsertStock('exchanges', exchanges, 'exchange_id');
|
|
// const symbolResult = await this.mongoClient.batchUpsertStock('symbols', symbols, 'symbol');
|
|
|
|
logger.info('IB market data saved', {
|
|
exchanges: exchangeResult,
|
|
symbols: symbolResult,
|
|
});
|
|
|
|
return { exchanges: exchangeResult, symbols: symbolResult };
|
|
}
|
|
|
|
/**
|
|
* Save real-time prices to stock database
|
|
*/
|
|
async saveRealTimePrices(priceData: any[]) {
|
|
logger.info(`Saving ${priceData.length} real-time prices to stock database`);
|
|
|
|
return await this.mongoClient.batchUpsertStock('real_time_prices', priceData, [
|
|
'symbol',
|
|
'timestamp',
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Save performance analytics to analytics database
|
|
*/
|
|
async savePerformanceAnalytics(performanceData: any[]) {
|
|
logger.info(`Saving ${performanceData.length} performance records to analytics database`);
|
|
|
|
return await this.mongoClient.batchUpsertAnalytics('performance_metrics', performanceData, [
|
|
'portfolio_id',
|
|
'date',
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Save trading logs to trading_documents database
|
|
*/
|
|
async saveTradingLogs(logs: any[]) {
|
|
logger.info(`Saving ${logs.length} trading logs to trading_documents database`);
|
|
|
|
return await this.mongoClient.batchUpsertTrading('trading_logs', logs, 'log_id');
|
|
}
|
|
|
|
/**
|
|
* Example: Cross-database analytics
|
|
*/
|
|
async generateCrossDatabaseReport() {
|
|
logger.info('Generating cross-database analytics report');
|
|
|
|
// Get data from multiple databases
|
|
const stockDb = this.mongoClient.getDatabase('stock');
|
|
const analyticsDb = this.mongoClient.getDatabase('analytics');
|
|
const tradingDb = this.mongoClient.getDatabase('trading_documents');
|
|
|
|
// Get counts from different databases
|
|
const symbolCount = await stockDb.collection('symbols').countDocuments();
|
|
const exchangeCount = await stockDb.collection('exchanges').countDocuments();
|
|
const performanceCount = await analyticsDb.collection('performance_metrics').countDocuments();
|
|
const logCount = await tradingDb.collection('trading_logs').countDocuments();
|
|
|
|
const report = {
|
|
stock_database: {
|
|
symbols: symbolCount,
|
|
exchanges: exchangeCount,
|
|
},
|
|
analytics_database: {
|
|
performance_metrics: performanceCount,
|
|
},
|
|
trading_database: {
|
|
logs: logCount,
|
|
},
|
|
generated_at: new Date(),
|
|
};
|
|
|
|
logger.info('Cross-database report generated', report);
|
|
return report;
|
|
}
|
|
|
|
/**
|
|
* Example: Database-specific operations
|
|
*/
|
|
async performDatabaseSpecificOperations() {
|
|
// Switch default database for a series of analytics operations
|
|
const originalDefault = this.mongoClient.getDefaultDatabase();
|
|
this.mongoClient.setDefaultDatabase('analytics');
|
|
|
|
try {
|
|
// Now all operations without explicit database go to 'analytics'
|
|
await this.mongoClient.batchUpsert('daily_reports', [], 'date');
|
|
await this.mongoClient.batchUpsert('portfolio_summaries', [], 'portfolio_id');
|
|
|
|
logger.info('Analytics operations completed on analytics database');
|
|
} finally {
|
|
// Restore original default database
|
|
this.mongoClient.setDefaultDatabase(originalDefault);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Example: Configuration-driven database routing
|
|
*/
|
|
async saveDataByType(dataType: string, collection: string, data: any[], uniqueKeys: string[]) {
|
|
const databaseMapping: Record<string, string> = {
|
|
market_data: 'stock',
|
|
analytics: 'analytics',
|
|
trading: 'trading_documents',
|
|
logs: 'trading_documents',
|
|
};
|
|
|
|
const targetDatabase = databaseMapping[dataType] || 'stock';
|
|
|
|
logger.info(`Saving ${data.length} records`, {
|
|
dataType,
|
|
targetDatabase,
|
|
collection,
|
|
});
|
|
|
|
return await this.mongoClient.batchUpsert(collection, data, uniqueKeys, {
|
|
database: targetDatabase,
|
|
});
|
|
}
|
|
|
|
async shutdown() {
|
|
logger.info('Shutting down enhanced data service');
|
|
await this.mongoClient.disconnect();
|
|
}
|
|
}
|
|
|
|
// Usage example for your existing data service
|
|
export async function integrateWithExistingDataService() {
|
|
const enhancedService = new EnhancedDataService();
|
|
|
|
try {
|
|
await enhancedService.initialize();
|
|
|
|
// Example market data
|
|
const exchanges = [
|
|
{ exchange_id: 'NYSE', name: 'New York Stock Exchange', mic: 'XNYS' },
|
|
{ exchange_id: 'NASDAQ', name: 'NASDAQ', mic: 'XNAS' },
|
|
];
|
|
|
|
const symbols = [
|
|
{ symbol: 'AAPL', exchange: 'NASDAQ', company_name: 'Apple Inc.' },
|
|
{ symbol: 'MSFT', exchange: 'NASDAQ', company_name: 'Microsoft Corporation' },
|
|
];
|
|
|
|
// Save to appropriate databases
|
|
await enhancedService.saveIBMarketData(exchanges, symbols);
|
|
|
|
// Save real-time prices
|
|
await enhancedService.saveRealTimePrices([
|
|
{ symbol: 'AAPL', price: 150.25, volume: 1000000, timestamp: new Date() },
|
|
]);
|
|
|
|
// Save analytics
|
|
await enhancedService.savePerformanceAnalytics([
|
|
{ portfolio_id: 'portfolio_1', date: new Date(), return: 0.15 },
|
|
]);
|
|
|
|
// Generate cross-database report
|
|
const report = await enhancedService.generateCrossDatabaseReport();
|
|
console.log('Cross-database report:', report);
|
|
|
|
// Example of configuration-driven routing
|
|
await enhancedService.saveDataByType('market_data', 'prices', [], 'symbol');
|
|
await enhancedService.saveDataByType('analytics', 'metrics', [], 'metric_id');
|
|
} catch (error) {
|
|
logger.error('Enhanced data service error:', error);
|
|
} finally {
|
|
await enhancedService.shutdown();
|
|
}
|
|
}
|
|
|
|
// Export for integration
|
|
export default EnhancedDataService;
|