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

View file

@ -1,5 +1,5 @@
{
"plugins": {
"@tailwindcss/postcss": {}
}
}
{
"plugins": {
"@tailwindcss/postcss": {}
}
}

View file

@ -1,4 +1,4 @@
{
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
"recommendations": ["angular.ng-template"]
}
{
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
"recommendations": ["angular.ng-template"]
}

View file

@ -1,20 +1,20 @@
{
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "ng serve",
"type": "chrome",
"request": "launch",
"preLaunchTask": "npm: start",
"url": "http://localhost:4200/"
},
{
"name": "ng test",
"type": "chrome",
"request": "launch",
"preLaunchTask": "npm: test",
"url": "http://localhost:9876/debug.html"
}
]
}
{
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "ng serve",
"type": "chrome",
"request": "launch",
"preLaunchTask": "npm: start",
"url": "http://localhost:4200/"
},
{
"name": "ng test",
"type": "chrome",
"request": "launch",
"preLaunchTask": "npm: test",
"url": "http://localhost:9876/debug.html"
}
]
}

View file

@ -1,42 +1,42 @@
{
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "start",
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"pattern": "$tsc",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "(.*?)"
},
"endsPattern": {
"regexp": "bundle generation complete"
}
}
}
},
{
"type": "npm",
"script": "test",
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"pattern": "$tsc",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "(.*?)"
},
"endsPattern": {
"regexp": "bundle generation complete"
}
}
}
}
]
}
{
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "start",
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"pattern": "$tsc",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "(.*?)"
},
"endsPattern": {
"regexp": "bundle generation complete"
}
}
}
},
{
"type": "npm",
"script": "test",
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"pattern": "$tsc",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "(.*?)"
},
"endsPattern": {
"regexp": "bundle generation complete"
}
}
}
}
]
}

View file

@ -1,44 +1,44 @@
{
"name": "trading-dashboard",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"devvvv": "ng serve --port 5173 --host 0.0.0.0",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"dependencies": {
"@angular/animations": "^20.0.0",
"@angular/cdk": "^20.0.1",
"@angular/common": "^20.0.0",
"@angular/compiler": "^20.0.0",
"@angular/core": "^20.0.0",
"@angular/forms": "^20.0.0",
"@angular/material": "^20.0.1",
"@angular/platform-browser": "^20.0.0",
"@angular/router": "^20.0.0",
"rxjs": "~7.8.2",
"tslib": "^2.8.1",
"zone.js": "~0.15.1"
},
"devDependencies": {
"@angular/build": "^20.0.0",
"@angular/cli": "^20.0.0",
"@angular/compiler-cli": "^20.0.0",
"@tailwindcss/postcss": "^4.1.8",
"@types/jasmine": "~5.1.8",
"autoprefixer": "^10.4.21",
"jasmine-core": "~5.7.1",
"karma": "~6.4.4",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.1",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"postcss": "^8.5.4",
"tailwindcss": "^4.1.8",
"typescript": "~5.8.3"
}
}
{
"name": "trading-dashboard",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"devvvv": "ng serve --port 5173 --host 0.0.0.0",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"dependencies": {
"@angular/animations": "^20.0.0",
"@angular/cdk": "^20.0.1",
"@angular/common": "^20.0.0",
"@angular/compiler": "^20.0.0",
"@angular/core": "^20.0.0",
"@angular/forms": "^20.0.0",
"@angular/material": "^20.0.1",
"@angular/platform-browser": "^20.0.0",
"@angular/router": "^20.0.0",
"rxjs": "~7.8.2",
"tslib": "^2.8.1",
"zone.js": "~0.15.1"
},
"devDependencies": {
"@angular/build": "^20.0.0",
"@angular/cli": "^20.0.0",
"@angular/compiler-cli": "^20.0.0",
"@tailwindcss/postcss": "^4.1.8",
"@types/jasmine": "~5.1.8",
"autoprefixer": "^10.4.21",
"jasmine-core": "~5.7.1",
"karma": "~6.4.4",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.1",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"postcss": "^8.5.4",
"tailwindcss": "^4.1.8",
"typescript": "~5.8.3"
}
}

View file

@ -82,11 +82,11 @@ export class NotificationsComponent {
const diff = now.getTime() - timestamp.getTime();
const minutes = Math.floor(diff / 60000);
if (minutes < 1) return 'Just now';
if (minutes < 60) return `${minutes}m ago`;
if (minutes < 1) {return 'Just now';}
if (minutes < 60) {return `${minutes}m ago`;}
const hours = Math.floor(minutes / 60);
if (hours < 24) return `${hours}h ago`;
if (hours < 24) {return `${hours}h ago`;}
const days = Math.floor(hours / 24);
return `${days}d ago`;

View file

@ -161,8 +161,8 @@ export class PortfolioComponent implements OnInit, OnDestroy {
}
getPnLColor(value: number): string {
if (value > 0) return 'text-green-600';
if (value < 0) return 'text-red-600';
if (value > 0) {return 'text-green-600';}
if (value < 0) {return 'text-red-600';}
return 'text-gray-600';
}
}

View file

@ -40,7 +40,7 @@ export class DrawdownChartComponent implements OnChanges {
}
private renderChart(): void {
if (!this.chartElement || !this.backtestResult) return;
if (!this.chartElement || !this.backtestResult) {return;}
// Clean up previous chart if it exists
if (this.chart) {

View file

@ -40,7 +40,7 @@ export class EquityChartComponent implements OnChanges {
}
private renderChart(): void {
if (!this.chartElement || !this.backtestResult) return;
if (!this.chartElement || !this.backtestResult) {return;}
// Clean up previous chart if it exists
if (this.chart) {

View file

@ -278,27 +278,27 @@ export class PerformanceMetricsComponent {
// Conditional classes
getReturnClass(value: number): string {
if (value > 0) return 'positive';
if (value < 0) return 'negative';
if (value > 0) {return 'positive';}
if (value < 0) {return 'negative';}
return '';
}
getRatioClass(value: number): string {
if (value >= 1.5) return 'positive';
if (value >= 1) return 'neutral';
if (value < 0) return 'negative';
if (value >= 1.5) {return 'positive';}
if (value >= 1) {return 'neutral';}
if (value < 0) {return 'negative';}
return '';
}
getWinRateClass(value: number): string {
if (value >= 0.55) return 'positive';
if (value >= 0.45) return 'neutral';
if (value >= 0.55) {return 'positive';}
if (value >= 0.45) {return 'neutral';}
return 'negative';
}
getProfitFactorClass(value: number): string {
if (value >= 1.5) return 'positive';
if (value >= 1) return 'neutral';
if (value >= 1.5) {return 'positive';}
if (value >= 1) {return 'neutral';}
return 'negative';
}
}

View file

@ -139,7 +139,7 @@ export class BacktestDialogComponent implements OnInit {
}
addSymbol(symbol: string): void {
if (!symbol || this.selectedSymbols.includes(symbol)) return;
if (!symbol || this.selectedSymbols.includes(symbol)) {return;}
this.selectedSymbols.push(symbol);
}

View file

@ -126,7 +126,7 @@ export class StrategyDialogComponent implements OnInit {
}
addSymbol(symbol: string): void {
if (!symbol || this.selectedSymbols.includes(symbol)) return;
if (!symbol || this.selectedSymbols.includes(symbol)) {return;}
this.selectedSymbols.push(symbol);
}

View file

@ -67,7 +67,9 @@ export class StrategyDetailsComponent implements OnChanges {
}
loadStrategyData(): void {
if (!this.strategy) return;
if (!this.strategy) {
return;
}
// In a real implementation, these would call API methods to fetch the data
this.loadSignals();
@ -75,7 +77,9 @@ export class StrategyDetailsComponent implements OnChanges {
this.loadPerformance();
}
loadSignals(): void {
if (!this.strategy) return;
if (!this.strategy) {
return;
}
this.isLoadingSignals = true;
@ -100,7 +104,9 @@ export class StrategyDetailsComponent implements OnChanges {
}
loadTrades(): void {
if (!this.strategy) return;
if (!this.strategy) {
return;
}
this.isLoadingTrades = true;
@ -140,7 +146,9 @@ export class StrategyDetailsComponent implements OnChanges {
};
}
listenForUpdates(): void {
if (!this.strategy) return;
if (!this.strategy) {
return;
}
// Subscribe to strategy signals
this.webSocketService.getStrategySignals(this.strategy.id).subscribe((signal: any) => {
@ -186,7 +194,9 @@ export class StrategyDetailsComponent implements OnChanges {
* Update performance metrics when new trades come in
*/
private updatePerformanceMetrics(): void {
if (!this.strategy || this.trades.length === 0) return;
if (!this.strategy || this.trades.length === 0) {
return;
}
// Calculate basic metrics
const winningTrades = this.trades.filter(t => t.pnl > 0);
@ -201,6 +211,8 @@ export class StrategyDetailsComponent implements OnChanges {
...currentPerformance,
totalTrades: this.trades.length,
winRate: winRate,
winningTrades,
losingTrades,
totalReturn: (currentPerformance.totalReturn || 0) + totalPnl / 10000, // Approximate
};
@ -242,7 +254,9 @@ export class StrategyDetailsComponent implements OnChanges {
* Open the backtest dialog to run a backtest for this strategy
*/
openBacktestDialog(): void {
if (!this.strategy) return;
if (!this.strategy) {
return;
}
const dialogRef = this.dialog.open(BacktestDialogComponent, {
width: '800px',
@ -261,7 +275,9 @@ export class StrategyDetailsComponent implements OnChanges {
* Open the strategy edit dialog
*/
openEditDialog(): void {
if (!this.strategy) return;
if (!this.strategy) {
return;
}
const dialogRef = this.dialog.open(StrategyDialogComponent, {
width: '600px',
@ -280,7 +296,9 @@ export class StrategyDetailsComponent implements OnChanges {
* Start the strategy
*/
activateStrategy(): void {
if (!this.strategy) return;
if (!this.strategy) {
return;
}
this.strategyService.startStrategy(this.strategy.id).subscribe({
next: response => {
@ -298,7 +316,9 @@ export class StrategyDetailsComponent implements OnChanges {
* Pause the strategy
*/
pauseStrategy(): void {
if (!this.strategy) return;
if (!this.strategy) {
return;
}
this.strategyService.pauseStrategy(this.strategy.id).subscribe({
next: response => {
@ -316,7 +336,9 @@ export class StrategyDetailsComponent implements OnChanges {
* Stop the strategy
*/
stopStrategy(): void {
if (!this.strategy) return;
if (!this.strategy) {
return;
}
this.strategyService.stopStrategy(this.strategy.id).subscribe({
next: response => {
@ -332,7 +354,9 @@ export class StrategyDetailsComponent implements OnChanges {
// Methods to generate mock data
private generateMockSignals(): any[] {
if (!this.strategy) return [];
if (!this.strategy) {
return [];
}
const signals = [];
const actions = ['BUY', 'SELL', 'HOLD'];
@ -358,7 +382,9 @@ export class StrategyDetailsComponent implements OnChanges {
}
private generateMockTrades(): any[] {
if (!this.strategy) return [];
if (!this.strategy) {
return [];
}
const trades = [];
const now = new Date();

View file

@ -1,5 +1,5 @@
import { Injectable, signal } from '@angular/core';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
import { Observable, Subject } from 'rxjs';
import { filter, map } from 'rxjs/operators';
export interface WebSocketMessage {
@ -204,7 +204,7 @@ export class WebSocketService {
// Cleanup
disconnect() {
this.connections.forEach((ws, serviceName) => {
this.connections.forEach((ws, _serviceName) => {
if (ws.readyState === WebSocket.OPEN) {
ws.close();
}

View file

@ -1,15 +1,11 @@
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"include": [
"src/**/*.ts"
],
"exclude": [
"src/**/*.spec.ts"
]
}
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"include": ["src/**/*.ts"],
"exclude": ["src/**/*.spec.ts"]
}

View file

@ -1,32 +1,32 @@
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
{
"extends": "../../tsconfig.json",
"compileOnSave": false,
"compilerOptions": {
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"isolatedModules": true,
"experimentalDecorators": true,
"importHelpers": true,
"module": "preserve"
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"typeCheckHostBindings": true,
"strictTemplates": true
},
"files": [],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
{
"extends": "../../tsconfig.json",
"compileOnSave": false,
"compilerOptions": {
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"isolatedModules": true,
"experimentalDecorators": true,
"importHelpers": true,
"module": "preserve"
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"typeCheckHostBindings": true,
"strictTemplates": true
},
"files": [],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}

View file

@ -1,14 +1,10 @@
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jasmine"
]
},
"include": [
"src/**/*.ts"
]
}
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": ["jasmine"]
},
"include": ["src/**/*.ts"]
}

View file

@ -16,7 +16,7 @@ const getEvery24HourCron = (): string => {
export const proxyProvider: ProviderConfig = {
name: 'proxy-provider',
operations: {
'fetch-and-check': async (payload: { sources?: string[] }) => {
'fetch-and-check': async (_payload: { sources?: string[] }) => {
const { proxyService } = await import('./proxy.tasks');
const { queueManager } = await import('../services/queue.service');
const { processItems } = await import('../utils/batch-helpers');

View file

@ -172,8 +172,8 @@ let proxyStats: ProxySource[] = PROXY_CONFIG.PROXY_SOURCES.map(source => ({
async function updateProxyStats(sourceId: string, success: boolean) {
const source = proxyStats.find(s => s.id === sourceId);
if (source !== undefined) {
if (typeof source.working !== 'number') source.working = 0;
if (typeof source.total !== 'number') source.total = 0;
if (typeof source.working !== 'number') {source.working = 0;}
if (typeof source.total !== 'number') {source.total = 0;}
source.total += 1;
if (success) {
source.working += 1;
@ -400,7 +400,7 @@ export async function fetchProxiesFromSource(source: ProxySource): Promise<Proxy
for (const line of lines) {
let trimmed = line.trim();
trimmed = cleanProxyUrl(trimmed);
if (!trimmed || trimmed.startsWith('#')) continue;
if (!trimmed || trimmed.startsWith('#')) {continue;}
// Parse formats like "host:port" or "host:port:user:pass"
const parts = trimmed.split(':');

View file

@ -82,7 +82,7 @@ export function createProviderRegistry(): ProviderRegistry {
function getAllScheduledJobs(): Array<{ provider: string; job: ScheduledJob }> {
const allJobs: Array<{ provider: string; job: ScheduledJob }> = [];
for (const [key, config] of providers) {
for (const [, config] of providers) {
if (config.scheduledJobs) {
for (const job of config.scheduledJobs) {
allJobs.push({

View file

@ -1,20 +1,28 @@
{
"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/http" },
{ "path": "../../libs/cache" },
{ "path": "../../libs/questdb-client" },
{ "path": "../../libs/mongodb-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/http" },
{ "path": "../../libs/cache" },
{ "path": "../../libs/questdb-client" },
{ "path": "../../libs/mongodb-client" },
{ "path": "../../libs/event-bus" },
{ "path": "../../libs/shutdown" }
]
}

View file

@ -1,37 +1,37 @@
{
"name": "@stock-bot/execution-service",
"version": "1.0.0",
"description": "Execution service for stock trading bot - handles order execution and broker integration",
"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/event-bus": "*",
"@stock-bot/utils": "*"
},
"devDependencies": {
"@types/node": "^22.5.0",
"typescript": "^5.5.4"
},
"keywords": [
"trading",
"execution",
"broker",
"orders",
"stock-bot"
],
"author": "Stock Bot Team",
"license": "MIT"
}
{
"name": "@stock-bot/execution-service",
"version": "1.0.0",
"description": "Execution service for stock trading bot - handles order execution and broker integration",
"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/event-bus": "*",
"@stock-bot/utils": "*"
},
"devDependencies": {
"@types/node": "^22.5.0",
"typescript": "^5.5.4"
},
"keywords": [
"trading",
"execution",
"broker",
"orders",
"stock-bot"
],
"author": "Stock Bot Team",
"license": "MIT"
}

View file

@ -1,17 +1,25 @@
{
"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/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/event-bus" },
{ "path": "../../libs/shutdown" }
]
}

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" }
]
}

View file

@ -1,26 +1,26 @@
{
"name": "@stock-bot/processing-service",
"version": "1.0.0",
"description": "Combined data processing and technical indicators service",
"main": "dist/index.js",
"type": "module",
"scripts": {
"devvvvv": "bun --watch src/index.ts",
"build": "bun build src/index.ts --outdir dist --target node",
"start": "bun dist/index.js",
"test": "bun test",
"clean": "rm -rf dist"
},
"dependencies": {
"@stock-bot/config": "*",
"@stock-bot/logger": "*",
"@stock-bot/types": "*",
"@stock-bot/utils": "*",
"@stock-bot/event-bus": "*",
"@stock-bot/vector-engine": "*",
"hono": "^4.0.0"
},
"devDependencies": {
"typescript": "^5.0.0"
}
}
{
"name": "@stock-bot/processing-service",
"version": "1.0.0",
"description": "Combined data processing and technical indicators service",
"main": "dist/index.js",
"type": "module",
"scripts": {
"devvvvv": "bun --watch src/index.ts",
"build": "bun build src/index.ts --outdir dist --target node",
"start": "bun dist/index.js",
"test": "bun test",
"clean": "rm -rf dist"
},
"dependencies": {
"@stock-bot/config": "*",
"@stock-bot/logger": "*",
"@stock-bot/types": "*",
"@stock-bot/utils": "*",
"@stock-bot/event-bus": "*",
"@stock-bot/vector-engine": "*",
"hono": "^4.0.0"
},
"devDependencies": {
"typescript": "^5.0.0"
}
}

View file

@ -33,27 +33,31 @@ export class IndicatorsService {
for (const indicator of request.indicators) {
try {
switch (indicator.toLowerCase()) {
case 'sma':
case 'sma': {
const smaPeriod = request.parameters?.smaPeriod || 20;
results.sma = sma(request.data, smaPeriod);
break;
}
case 'ema':
case 'ema': {
const emaPeriod = request.parameters?.emaPeriod || 20;
results.ema = ema(request.data, emaPeriod);
break;
}
case 'rsi':
case 'rsi': {
const rsiPeriod = request.parameters?.rsiPeriod || 14;
results.rsi = rsi(request.data, rsiPeriod);
break;
}
case 'macd':
case 'macd': {
const fast = request.parameters?.macdFast || 12;
const slow = request.parameters?.macdSlow || 26;
const signal = request.parameters?.macdSignal || 9;
results.macd = macd(request.data, fast, slow, signal).macd;
break;
}
case 'stochastic':
// TODO: Implement stochastic oscillator

View file

@ -1,20 +1,28 @@
{
"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/data-frame" },
{ "path": "../../libs/vector-engine" },
{ "path": "../../libs/mongodb-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/data-frame" },
{ "path": "../../libs/vector-engine" },
{ "path": "../../libs/mongodb-client" },
{ "path": "../../libs/event-bus" },
{ "path": "../../libs/shutdown" }
]
}

View file

@ -1,33 +1,34 @@
{
"name": "@stock-bot/strategy-service",
"version": "1.0.0",
"description": "Combined strategy execution and multi-mode backtesting service",
"main": "dist/index.js",
"type": "module",
"scripts": {
"devvvvv": "bun --watch src/index.ts",
"build": "bun build src/index.ts --outdir dist --target node",
"start": "bun dist/index.js",
"test": "bun test", "clean": "rm -rf dist",
"backtest": "bun src/cli/index.ts",
"optimize": "bun src/cli/index.ts optimize",
"cli": "bun src/cli/index.ts"
},
"dependencies": {
"@stock-bot/config": "*",
"@stock-bot/logger": "*",
"@stock-bot/types": "*",
"@stock-bot/utils": "*",
"@stock-bot/event-bus": "*",
"@stock-bot/strategy-engine": "*",
"@stock-bot/vector-engine": "*",
"@stock-bot/data-frame": "*",
"@stock-bot/questdb-client": "*",
"hono": "^4.0.0",
"commander": "^11.0.0"
},
"devDependencies": {
"@types/node": "^20.0.0",
"typescript": "^5.0.0"
}
}
{
"name": "@stock-bot/strategy-service",
"version": "1.0.0",
"description": "Combined strategy execution and multi-mode backtesting service",
"main": "dist/index.js",
"type": "module",
"scripts": {
"devvvvv": "bun --watch src/index.ts",
"build": "bun build src/index.ts --outdir dist --target node",
"start": "bun dist/index.js",
"test": "bun test",
"clean": "rm -rf dist",
"backtest": "bun src/cli/index.ts",
"optimize": "bun src/cli/index.ts optimize",
"cli": "bun src/cli/index.ts"
},
"dependencies": {
"@stock-bot/config": "*",
"@stock-bot/logger": "*",
"@stock-bot/types": "*",
"@stock-bot/utils": "*",
"@stock-bot/event-bus": "*",
"@stock-bot/strategy-engine": "*",
"@stock-bot/vector-engine": "*",
"@stock-bot/data-frame": "*",
"@stock-bot/questdb-client": "*",
"hono": "^4.0.0",
"commander": "^11.0.0"
},
"devDependencies": {
"@types/node": "^20.0.0",
"typescript": "^5.0.0"
}
}

View file

@ -1,4 +1,3 @@
import { create } from 'domain';
import { DataFrame } from '@stock-bot/data-frame';
import { EventBus } from '@stock-bot/event-bus';
import { getLogger } from '@stock-bot/logger';
@ -198,7 +197,7 @@ export class HybridMode extends ExecutionMode {
private overrideIndicatorCalculations(eventMode: EventMode): void {
// Override the event mode's indicator calculations to use pre-computed values
// This is a simplified approach - in production you'd want a more sophisticated interface
const originalCalculateIndicators = (eventMode as any).calculateIndicators;
const _originalCalculateIndicators = (eventMode as any).calculateIndicators;
(eventMode as any).calculateIndicators = (symbol: string, index: number) => {
const indicators: Record<string, number> = {};

View file

@ -19,7 +19,7 @@ export class LiveMode extends ExecutionMode {
return new Date(); // Real time
}
async getMarketData(symbol: string): Promise<MarketData> {
async getMarketData(_symbol: string): Promise<MarketData> {
// TODO: Get live market data
throw new Error('Live market data fetching not implemented yet');
}

View file

@ -82,7 +82,7 @@ async function runBacktest(options: CLIBacktestConfig): Promise<void> {
// Subscribe to progress updates
eventBus.subscribe('backtest.update', message => {
const { backtestId, progress, ...data } = message.data;
const { backtestId: _backtestId, progress, ...data } = message.data;
console.log(`Progress: ${progress}%`, data);
});
@ -172,7 +172,7 @@ async function saveResults(result: any, outputPath: string): Promise<void> {
}
function convertTradesToCSV(trades: any[]): string {
if (trades.length === 0) return 'No trades executed\n';
if (trades.length === 0) {return 'No trades executed\n';}
const headers = Object.keys(trades[0]).join(',');
const rows = trades.map(trade =>
@ -259,7 +259,7 @@ program
const strategies = options.strategies.split(',').map((s: string) => s.trim());
console.log(`Comparing strategies: ${strategies.join(', ')}`);
const results: any[] = [];
const _results: any[] = [];
for (const strategy of strategies) {
console.log(`\nRunning ${strategy}...`);

View file

@ -4,7 +4,7 @@
*/
import { getLogger } from '@stock-bot/logger';
const logger = getLogger('execution-mode');
const _logger = getLogger('execution-mode');
export interface Order {
id: string;
@ -55,7 +55,7 @@ export enum BacktestMode {
}
export class ModeFactory {
static create(mode: BacktestMode, config?: any): ExecutionMode {
static create(mode: BacktestMode, _config?: any): ExecutionMode {
switch (mode) {
case BacktestMode.LIVE:
// TODO: Import and create LiveMode

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/strategy-engine" },
{ "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/strategy-engine" },
{ "path": "../../libs/event-bus" },
{ "path": "../../libs/shutdown" }
]
}