fixed all libs to be buildiable and dependency hell from removing some

This commit is contained in:
Bojan Kucera 2025-06-04 16:07:08 -04:00
parent 5c64b1ccf8
commit a282dac6cd
40 changed files with 4050 additions and 8219 deletions

View file

@ -23,29 +23,12 @@ const nextTradingDay = dateUtils.getNextTradingDay(new Date());
Mathematical functions for financial calculations:
```typescript
import { financialUtils } from '@stock-bot/utils';
import { calculateCAGR, calculateSharpeRatio } from '@stock-bot/utils';
// Calculate compound annual growth rate
const returns = [0.05, 0.03, -0.01, 0.04, 0.02];
const cagr = calculateCAGR(startValue, endValue, years);
// 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' });
const sharpeRatio = calculateSharpeRatio(returns, 0.02);
```

View file

@ -11,7 +11,6 @@
"test": "jest"
}, "dependencies": {
"@stock-bot/types": "*",
"@stock-bot/config": "*",
"date-fns": "^2.30.0"
},
"devDependencies": {

View file

@ -1,3 +1,2 @@
export * from './dateUtils';
export * from './logger';
export * from './calculations/index';

View file

@ -1,189 +0,0 @@
/**
* Logger utility with consistent formatting and log levels
* Supports console and Loki logging
*/
import { loggingConfig, lokiConfig } from '@stock-bot/config';
// Singleton Loki client
let lokiClient: LokiClient | null = null;
function getLokiClient(): LokiClient {
if (!lokiClient) {
lokiClient = new LokiClient();
}
return lokiClient;
}
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 formattedArgs = args.length ? this.formatArgs(args) : '';
const fullMessage = `${message}${formattedArgs}`;
const logMessage = `[${timestamp}] [${levelStr}] [${this.serviceName}] ${fullMessage}`;
// Console logging
if (loggingConfig.LOG_CONSOLE) {
switch (level) {
case LogLevel.ERROR:
console.error(logMessage);
break;
case LogLevel.WARN:
console.warn(logMessage);
break;
case LogLevel.INFO:
console.info(logMessage);
break;
case LogLevel.DEBUG:
default:
console.debug(logMessage);
break;
}
}
// Loki logging
try {
const loki = getLokiClient();
loki.log(LogLevel[level].toLowerCase(), fullMessage, this.serviceName);
} catch (error) {
console.error('Failed to send log to Loki:', error);
}
}
private formatArgs(args: any[]): string {
try {
return args.map(arg => {
if (arg instanceof Error) {
return ` ${arg.message}\n${arg.stack}`;
} else if (typeof arg === 'object') {
return ` ${JSON.stringify(arg)}`;
} else {
return ` ${arg}`;
}
}).join('');
} catch (error) {
return ` [Error formatting log arguments: ${error}]`;
}
}
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);
}
export class LokiClient {
private batchQueue: any[] = [];
private flushInterval: NodeJS.Timeout;
private lokiUrl: string;
private authHeader?: string;
constructor() {
const { LOKI_HOST, LOKI_PORT, LOKI_USERNAME, LOKI_PASSWORD } = lokiConfig;
this.lokiUrl = `http://${LOKI_HOST}:${LOKI_PORT}/loki/api/v1/push`;
if (LOKI_USERNAME && LOKI_PASSWORD) {
const authString = Buffer.from(`${LOKI_USERNAME}:${LOKI_PASSWORD}`).toString('base64');
this.authHeader = `Basic ${authString}`;
}
this.flushInterval = setInterval(
() => this.flush(),
lokiConfig.LOKI_FLUSH_INTERVAL_MS || 1000 // Default to 1 second if not set
);
}
async log(level: string, message: string, serviceName: string, labels: Record<string, string> = {}) {
const timestamp = Date.now() * 1000000; // Loki expects nanoseconds
this.batchQueue.push({
streams: [{
stream: {
level,
service: serviceName,
...lokiConfig.LOKI_DEFAULT_LABELS ? JSON.parse(lokiConfig.LOKI_DEFAULT_LABELS) : {},
...labels,
},
values: [[`${timestamp}`, message]],
}],
});
if (this.batchQueue.length >= lokiConfig.LOKI_BATCH_SIZE) {
await this.flush();
}
}
private async flush() {
if (this.batchQueue.length === 0) return;
try {
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
if (this.authHeader) {
headers['Authorization'] = this.authHeader;
}
const response = await fetch(this.lokiUrl, {
method: 'POST',
headers,
body: JSON.stringify({
streams: this.batchQueue.flatMap(batch => batch.streams),
}),
});
if (!response.ok) {
console.error(`Failed to send logs to Loki: ${response.status} ${response.statusText}`);
const text = await response.text();
if (text) {
console.error(text);
}
}
} catch (error) {
console.error('Error sending logs to Loki:', error);
} finally {
this.batchQueue = [];
}
}
async destroy() {
clearInterval(this.flushInterval);
return this.flush();
}
}

View file

@ -7,12 +7,5 @@
},
"include": [
"src/**/*"
],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"],
"references": [
{ "path": "../api-client" },
{ "path": "../config" },
{ "path": "../event-bus" },
{ "path": "../http-client" },
]
], "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
}