adding data-services

This commit is contained in:
Bojan Kucera 2025-06-03 07:42:48 -04:00
parent e3bfd05b90
commit 405b818c86
139 changed files with 55943 additions and 416 deletions

51
libs/utils/README.md Normal file
View file

@ -0,0 +1,51 @@
# Utils Library
Common utility functions shared across services in the stock-bot project.
## Included Utilities
### Date Utilities
Helper functions for working with market dates:
```typescript
import { dateUtils } from '@stock-bot/utils';
// Check if a date is a trading day
const isTradingDay = dateUtils.isTradingDay(new Date());
// Get the next trading day
const nextTradingDay = dateUtils.getNextTradingDay(new Date());
```
### Financial Utilities
Mathematical functions for financial calculations:
```typescript
import { financialUtils } from '@stock-bot/utils';
// Calculate Sharpe ratio
const returns = [0.05, 0.03, -0.01, 0.04, 0.02];
const sharpeRatio = financialUtils.calculateSharpeRatio(returns, 0.02);
// Calculate maximum drawdown
const equityCurve = [10000, 10500, 10200, 10800, 10300];
const maxDrawdown = financialUtils.calculateMaxDrawdown(equityCurve);
```
### Logger
Standardized logging service:
```typescript
import { createLogger, LogLevel } from '@stock-bot/utils';
// Create a logger for your service
const logger = createLogger('strategy-orchestrator', LogLevel.INFO);
// Log at different levels
logger.info('Strategy initialized');
logger.warn('Position size exceeds recommended limit');
logger.error('Failed to execute order', { orderId: '123', reason: 'Insufficient funds' });
```

22
libs/utils/package.json Normal file
View file

@ -0,0 +1,22 @@
{
"name": "@stock-bot/utils",
"version": "1.0.0",
"description": "Common utility functions for stock-bot services",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
"dev": "tsc --watch",
"clean": "rm -rf dist",
"test": "jest"
},
"dependencies": {
"@stock-bot/shared-types": "workspace:*",
"date-fns": "^2.30.0"
},
"devDependencies": {
"@types/jest": "^29.5.2",
"jest": "^29.5.0",
"typescript": "^5.4.5"
}
}

View file

@ -0,0 +1,55 @@
/**
* Date and time utilities for working with market data
*/
export const dateUtils = {
/**
* Check if a date is a trading day (Monday-Friday, non-holiday)
* This is a simplified implementation - a real version would check market holidays
*/
isTradingDay(date: Date): boolean {
const day = date.getDay();
return day > 0 && day < 6; // Mon-Fri
},
/**
* Get the next trading day from a given date
*/
getNextTradingDay(date: Date): Date {
const nextDay = new Date(date);
nextDay.setDate(nextDay.getDate() + 1);
while (!this.isTradingDay(nextDay)) {
nextDay.setDate(nextDay.getDate() + 1);
}
return nextDay;
},
/**
* Get the previous trading day from a given date
*/
getPreviousTradingDay(date: Date): Date {
const prevDay = new Date(date);
prevDay.setDate(prevDay.getDate() - 1);
while (!this.isTradingDay(prevDay)) {
prevDay.setDate(prevDay.getDate() - 1);
}
return prevDay;
},
/**
* Format a date as YYYY-MM-DD
*/
formatDate(date: Date): string {
return date.toISOString().split('T')[0];
},
/**
* Parse a date string in YYYY-MM-DD format
*/
parseDate(dateStr: string): Date {
return new Date(dateStr);
}
};

View file

@ -0,0 +1,67 @@
/**
* Financial calculation utilities
*/
export const financialUtils = {
/**
* Calculate the Sharpe ratio
* @param returns Array of period returns
* @param riskFreeRate The risk-free rate (e.g. 0.02 for 2%)
*/
calculateSharpeRatio(returns: number[], riskFreeRate: number = 0.02): number {
if (returns.length < 2) {
return 0;
}
// Calculate average return
const avgReturn = returns.reduce((sum, val) => sum + val, 0) / returns.length;
// Calculate standard deviation
const squaredDiffs = returns.map(val => Math.pow(val - avgReturn, 2));
const avgSquaredDiff = squaredDiffs.reduce((sum, val) => sum + val, 0) / squaredDiffs.length;
const stdDev = Math.sqrt(avgSquaredDiff);
// Avoid division by zero
if (stdDev === 0) return 0;
// Calculate Sharpe ratio
return (avgReturn - riskFreeRate) / stdDev;
},
/**
* Calculate the maximum drawdown
* @param equityCurve Array of equity values over time
*/
calculateMaxDrawdown(equityCurve: number[]): number {
if (equityCurve.length < 2) {
return 0;
}
let maxDrawdown = 0;
let peak = equityCurve[0];
for (let i = 1; i < equityCurve.length; i++) {
if (equityCurve[i] > peak) {
peak = equityCurve[i];
} else {
const drawdown = (peak - equityCurve[i]) / peak;
maxDrawdown = Math.max(maxDrawdown, drawdown);
}
}
return maxDrawdown;
},
/**
* Calculate the Compound Annual Growth Rate (CAGR)
* @param startValue Initial investment value
* @param endValue Final investment value
* @param years Number of years
*/
calculateCAGR(startValue: number, endValue: number, years: number): number {
if (years <= 0 || startValue <= 0 || endValue <= 0) {
return 0;
}
return Math.pow(endValue / startValue, 1 / years) - 1;
}
};

3
libs/utils/src/index.ts Normal file
View file

@ -0,0 +1,3 @@
export * from './dateUtils';
export * from './financialUtils';
export * from './logger';

65
libs/utils/src/logger.ts Normal file
View file

@ -0,0 +1,65 @@
/**
* Logger utility with consistent formatting and log levels
*/
export class Logger {
constructor(private serviceName: string, private level: LogLevel = LogLevel.INFO) {}
debug(message: string, ...args: any[]): void {
this.log(LogLevel.DEBUG, message, ...args);
}
info(message: string, ...args: any[]): void {
this.log(LogLevel.INFO, message, ...args);
}
warn(message: string, ...args: any[]): void {
this.log(LogLevel.WARN, message, ...args);
}
error(message: string, ...args: any[]): void {
this.log(LogLevel.ERROR, message, ...args);
}
private log(level: LogLevel, message: string, ...args: any[]): void {
if (level < this.level) return;
const timestamp = new Date().toISOString();
const levelStr = LogLevel[level].padEnd(5);
const logMessage = `[${timestamp}] [${levelStr}] [${this.serviceName}] ${message}`;
switch (level) {
case LogLevel.ERROR:
console.error(logMessage, ...args);
break;
case LogLevel.WARN:
console.warn(logMessage, ...args);
break;
case LogLevel.INFO:
console.info(logMessage, ...args);
break;
case LogLevel.DEBUG:
default:
console.debug(logMessage, ...args);
break;
}
}
setLevel(level: LogLevel): void {
this.level = level;
}
}
export enum LogLevel {
DEBUG = 0,
INFO = 1,
WARN = 2,
ERROR = 3
}
/**
* Create a new logger instance
*/
export function createLogger(serviceName: string, level: LogLevel = LogLevel.INFO): Logger {
return new Logger(serviceName, level);
}

13
libs/utils/tsconfig.json Normal file
View file

@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"declaration": true,
"outDir": "dist",
"strict": true,
"sourceMap": true
},
"include": ["src/**/*"]
}