This commit is contained in:
Boki 2025-06-11 10:35:15 -04:00
parent 8955544593
commit 9d38f9a7b6
91 changed files with 2224 additions and 1400 deletions

View file

@ -1,38 +1,38 @@
{
"name": "@stock-bot/portfolio-service",
"version": "1.0.0",
"description": "Portfolio service for stock trading bot - handles portfolio tracking and performance analytics",
"main": "dist/index.js",
"type": "module",
"scripts": {
"build": "tsc",
"devvvvv": "bun --watch src/index.ts",
"start": "bun src/index.ts",
"test": "bun test",
"lint": "eslint src --ext .ts",
"type-check": "tsc --noEmit"
},
"dependencies": {
"@hono/node-server": "^1.12.0",
"hono": "^4.6.1",
"@stock-bot/config": "*",
"@stock-bot/logger": "*",
"@stock-bot/types": "*",
"@stock-bot/questdb-client": "*",
"@stock-bot/utils": "*",
"@stock-bot/data-frame": "*"
},
"devDependencies": {
"@types/node": "^22.5.0",
"typescript": "^5.5.4"
},
"keywords": [
"trading",
"portfolio",
"performance",
"analytics",
"stock-bot"
],
"author": "Stock Bot Team",
"license": "MIT"
}
{
"name": "@stock-bot/portfolio-service",
"version": "1.0.0",
"description": "Portfolio service for stock trading bot - handles portfolio tracking and performance analytics",
"main": "dist/index.js",
"type": "module",
"scripts": {
"build": "tsc",
"devvvvv": "bun --watch src/index.ts",
"start": "bun src/index.ts",
"test": "bun test",
"lint": "eslint src --ext .ts",
"type-check": "tsc --noEmit"
},
"dependencies": {
"@hono/node-server": "^1.12.0",
"hono": "^4.6.1",
"@stock-bot/config": "*",
"@stock-bot/logger": "*",
"@stock-bot/types": "*",
"@stock-bot/questdb-client": "*",
"@stock-bot/utils": "*",
"@stock-bot/data-frame": "*"
},
"devDependencies": {
"@types/node": "^22.5.0",
"typescript": "^5.5.4"
},
"keywords": [
"trading",
"portfolio",
"performance",
"analytics",
"stock-bot"
],
"author": "Stock Bot Team",
"license": "MIT"
}

View file

@ -1,4 +1,4 @@
import { PortfolioSnapshot, Trade } from '../portfolio/portfolio-manager.ts';
import { PortfolioSnapshot } from '../portfolio/portfolio-manager';
export interface PerformanceMetrics {
totalReturn: number;
@ -67,8 +67,8 @@ export class PerformanceAnalyzer {
};
}
private calculateReturns(period: 'daily' | 'weekly' | 'monthly'): number[] {
if (this.snapshots.length < 2) return [];
private calculateReturns(_period: 'daily' | 'weekly' | 'monthly'): number[] {
if (this.snapshots.length < 2) {return [];}
const returns: number[] = [];
@ -83,7 +83,7 @@ export class PerformanceAnalyzer {
}
private calculateTotalReturn(): number {
if (this.snapshots.length < 2) return 0;
if (this.snapshots.length < 2) {return 0;}
const firstValue = this.snapshots[0].totalValue;
const lastValue = this.snapshots[this.snapshots.length - 1].totalValue;
@ -92,14 +92,14 @@ export class PerformanceAnalyzer {
}
private calculateAnnualizedReturn(returns: number[]): number {
if (returns.length === 0) return 0;
if (returns.length === 0) {return 0;}
const avgReturn = returns.reduce((sum, ret) => sum + ret, 0) / returns.length;
return Math.pow(1 + avgReturn, 252) - 1; // 252 trading days per year
}
private calculateVolatility(returns: number[]): number {
if (returns.length === 0) return 0;
if (returns.length === 0) {return 0;}
const avgReturn = returns.reduce((sum, ret) => sum + ret, 0) / returns.length;
const variance =
@ -109,19 +109,19 @@ export class PerformanceAnalyzer {
}
private calculateSharpeRatio(returns: number[], riskFreeRate: number): number {
if (returns.length === 0) return 0;
if (returns.length === 0) {return 0;}
const avgReturn = returns.reduce((sum, ret) => sum + ret, 0) / returns.length;
const annualizedReturn = Math.pow(1 + avgReturn, 252) - 1;
const volatility = this.calculateVolatility(returns);
if (volatility === 0) return 0;
if (volatility === 0) {return 0;}
return (annualizedReturn - riskFreeRate) / volatility;
}
private calculateMaxDrawdown(): number {
if (this.snapshots.length === 0) return 0;
if (this.snapshots.length === 0) {return 0;}
let maxDrawdown = 0;
let peak = this.snapshots[0].totalValue;
@ -139,7 +139,7 @@ export class PerformanceAnalyzer {
}
private calculateBeta(returns: number[]): number {
if (returns.length === 0 || this.benchmarkReturns.length === 0) return 1.0;
if (returns.length === 0 || this.benchmarkReturns.length === 0) {return 1.0;}
// Simple beta calculation - would need actual benchmark data
return 1.0; // Placeholder
@ -157,7 +157,7 @@ export class PerformanceAnalyzer {
const annualizedReturn = this.calculateAnnualizedReturn(returns);
const maxDrawdown = this.calculateMaxDrawdown();
if (maxDrawdown === 0) return 0;
if (maxDrawdown === 0) {return 0;}
return annualizedReturn / maxDrawdown;
}
@ -166,16 +166,16 @@ export class PerformanceAnalyzer {
const annualizedReturn = this.calculateAnnualizedReturn(returns);
const downsideDeviation = this.calculateDownsideDeviation(returns);
if (downsideDeviation === 0) return 0;
if (downsideDeviation === 0) {return 0;}
return (annualizedReturn - riskFreeRate) / downsideDeviation;
}
private calculateDownsideDeviation(returns: number[]): number {
if (returns.length === 0) return 0;
if (returns.length === 0) {return 0;}
const negativeReturns = returns.filter(ret => ret < 0);
if (negativeReturns.length === 0) return 0;
if (negativeReturns.length === 0) {return 0;}
const avgNegativeReturn =
negativeReturns.reduce((sum, ret) => sum + ret, 0) / negativeReturns.length;
@ -187,7 +187,7 @@ export class PerformanceAnalyzer {
}
private calculateVaR(returns: number[], confidence: number): number {
if (returns.length === 0) return 0;
if (returns.length === 0) {return 0;}
const sortedReturns = returns.slice().sort((a, b) => a - b);
const index = Math.floor((1 - confidence) * sortedReturns.length);
@ -196,13 +196,13 @@ export class PerformanceAnalyzer {
}
private calculateCVaR(returns: number[], confidence: number): number {
if (returns.length === 0) return 0;
if (returns.length === 0) {return 0;}
const sortedReturns = returns.slice().sort((a, b) => a - b);
const cutoffIndex = Math.floor((1 - confidence) * sortedReturns.length);
const tailReturns = sortedReturns.slice(0, cutoffIndex + 1);
if (tailReturns.length === 0) return 0;
if (tailReturns.length === 0) {return 0;}
const avgTailReturn = tailReturns.reduce((sum, ret) => sum + ret, 0) / tailReturns.length;
return -avgTailReturn; // Return as positive value

View file

@ -2,8 +2,6 @@ import { serve } from '@hono/node-server';
import { Hono } from 'hono';
import { config } from '@stock-bot/config';
import { getLogger } from '@stock-bot/logger';
import { PerformanceAnalyzer } from './analytics/performance-analyzer.ts';
import { PortfolioManager } from './portfolio/portfolio-manager.ts';
const app = new Hono();
const logger = getLogger('portfolio-service');

View file

@ -1,18 +1,26 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts", "**/test/**", "**/tests/**", "**/__tests__/**"],
"references": [
{ "path": "../../libs/types" },
{ "path": "../../libs/config" },
{ "path": "../../libs/logger" },
{ "path": "../../libs/utils" },
{ "path": "../../libs/postgres-client" },
{ "path": "../../libs/event-bus" },
{ "path": "../../libs/shutdown" }
]
}
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": [
"node_modules",
"dist",
"**/*.test.ts",
"**/*.spec.ts",
"**/test/**",
"**/tests/**",
"**/__tests__/**"
],
"references": [
{ "path": "../../libs/types" },
{ "path": "../../libs/config" },
{ "path": "../../libs/logger" },
{ "path": "../../libs/utils" },
{ "path": "../../libs/postgres-client" },
{ "path": "../../libs/event-bus" },
{ "path": "../../libs/shutdown" }
]
}