eslint
This commit is contained in:
parent
d85cd58acd
commit
597c6efc9b
91 changed files with 2224 additions and 1400 deletions
81
.eslintignore
Normal file
81
.eslintignore
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# Dependencies
|
||||
node_modules/
|
||||
**/node_modules/
|
||||
|
||||
# Build outputs
|
||||
dist/
|
||||
build/
|
||||
**/dist/
|
||||
**/build/
|
||||
.next/
|
||||
**/.next/
|
||||
|
||||
# Cache directories
|
||||
.turbo/
|
||||
**/.turbo/
|
||||
.cache/
|
||||
**/.cache/
|
||||
|
||||
# Environment files
|
||||
.env
|
||||
.env.local
|
||||
.env.production
|
||||
.env.staging
|
||||
**/.env*
|
||||
|
||||
# Lock files
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
bun.lockb
|
||||
pnpm-lock.yaml
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
logs/
|
||||
**/logs/
|
||||
|
||||
# Database files
|
||||
*.db
|
||||
*.sqlite
|
||||
*.sqlite3
|
||||
|
||||
# Temporary files
|
||||
*.tmp
|
||||
*.temp
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Generated files
|
||||
*.d.ts
|
||||
**/*.d.ts
|
||||
|
||||
# JavaScript files (we're focusing on TypeScript)
|
||||
*.js
|
||||
*.mjs
|
||||
!.eslintrc.js
|
||||
!eslint.config.js
|
||||
|
||||
# Scripts and config directories
|
||||
scripts/
|
||||
monitoring/
|
||||
database/
|
||||
docker-compose*.yml
|
||||
Dockerfile*
|
||||
|
||||
# Documentation
|
||||
*.md
|
||||
docs/
|
||||
|
||||
# Test coverage
|
||||
coverage/
|
||||
**/coverage/
|
||||
|
||||
# IDE/Editor files
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Angular specific
|
||||
**/.angular/
|
||||
**/src/polyfills.ts
|
||||
1
.eslintrc.json
Normal file
1
.eslintrc.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
// This file is deprecated in ESLint v9. Use eslint.config.js instead.
|
||||
22
.vscode/settings.json
vendored
22
.vscode/settings.json
vendored
|
|
@ -26,13 +26,31 @@
|
|||
"editor.formatOnPaste": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll": "explicit",
|
||||
"source.fixAll.eslint": "explicit",
|
||||
"source.organizeImports": "explicit"
|
||||
},
|
||||
"eslint.enable": true,
|
||||
"eslint.validate": [
|
||||
"typescript",
|
||||
"javascript"
|
||||
],
|
||||
"eslint.run": "onType",
|
||||
"eslint.workingDirectories": [
|
||||
{
|
||||
"mode": "auto"
|
||||
}
|
||||
],
|
||||
"[typescript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
}
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
}
|
||||
},
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"plugins": {
|
||||
"@tailwindcss/postcss": {}
|
||||
}
|
||||
}
|
||||
{
|
||||
"plugins": {
|
||||
"@tailwindcss/postcss": {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
8
apps/dashboard/.vscode/extensions.json
vendored
8
apps/dashboard/.vscode/extensions.json
vendored
|
|
@ -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"]
|
||||
}
|
||||
|
|
|
|||
40
apps/dashboard/.vscode/launch.json
vendored
40
apps/dashboard/.vscode/launch.json
vendored
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
84
apps/dashboard/.vscode/tasks.json
vendored
84
apps/dashboard/.vscode/tasks.json
vendored
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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`;
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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(':');
|
||||
|
|
|
|||
|
|
@ -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({
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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> = {};
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}...`);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
77
eslint.config.js
Normal file
77
eslint.config.js
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
import js from '@eslint/js';
|
||||
import tseslint from '@typescript-eslint/eslint-plugin';
|
||||
import tsparser from '@typescript-eslint/parser';
|
||||
|
||||
export default [
|
||||
// Global ignores first
|
||||
{
|
||||
ignores: [
|
||||
'dist/**',
|
||||
'build/**',
|
||||
'node_modules/**',
|
||||
'**/*.js',
|
||||
'**/*.mjs',
|
||||
'**/*.d.ts',
|
||||
'.turbo/**',
|
||||
'coverage/**',
|
||||
'scripts/**',
|
||||
'monitoring/**',
|
||||
'database/**',
|
||||
'**/.angular/**',
|
||||
'**/src/polyfills.ts',
|
||||
],
|
||||
},
|
||||
|
||||
// Base JavaScript configuration
|
||||
js.configs.recommended,
|
||||
|
||||
// TypeScript configuration
|
||||
{
|
||||
files: ['**/*.{ts,tsx}'],
|
||||
languageOptions: {
|
||||
parser: tsparser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 2022,
|
||||
sourceType: 'module',
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
'@typescript-eslint': tseslint,
|
||||
},
|
||||
rules: {
|
||||
// Disable base rules that are covered by TypeScript equivalents
|
||||
'no-unused-vars': 'off',
|
||||
'no-undef': 'off',
|
||||
|
||||
// TypeScript specific rules
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'error',
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_',
|
||||
destructuredArrayIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/no-explicit-any': 'warn',
|
||||
'@typescript-eslint/no-non-null-assertion': 'warn',
|
||||
|
||||
// General rules
|
||||
'no-console': 'warn',
|
||||
'no-debugger': 'error',
|
||||
'no-var': 'error',
|
||||
'prefer-const': 'error',
|
||||
eqeqeq: ['error', 'always'],
|
||||
curly: ['error', 'all'],
|
||||
},
|
||||
},
|
||||
|
||||
// Test files configuration
|
||||
{
|
||||
files: ['**/*.test.ts', '**/*.spec.ts', '**/test/**/*', '**/tests/**/*'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
'no-console': 'off',
|
||||
},
|
||||
},
|
||||
];
|
||||
64
libs/cache/package.json
vendored
64
libs/cache/package.json
vendored
|
|
@ -1,32 +1,32 @@
|
|||
{
|
||||
"name": "@stock-bot/cache",
|
||||
"version": "1.0.0",
|
||||
"description": "Caching library for Redis and in-memory providers",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"clean": "rimraf dist",
|
||||
"test": "bun test"
|
||||
},
|
||||
"dependencies": {
|
||||
"ioredis": "^5.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
{
|
||||
"name": "@stock-bot/cache",
|
||||
"version": "1.0.0",
|
||||
"description": "Caching library for Redis and in-memory providers",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"clean": "rimraf dist",
|
||||
"test": "bun test"
|
||||
},
|
||||
"dependencies": {
|
||||
"ioredis": "^5.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
4
libs/cache/src/connection-manager.ts
vendored
4
libs/cache/src/connection-manager.ts
vendored
|
|
@ -173,7 +173,7 @@ export class RedisConnectionManager {
|
|||
try {
|
||||
await connection.ping();
|
||||
details[`shared:${name}`] = true;
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
details[`shared:${name}`] = false;
|
||||
allHealthy = false;
|
||||
}
|
||||
|
|
@ -184,7 +184,7 @@ export class RedisConnectionManager {
|
|||
try {
|
||||
await connection.ping();
|
||||
details[`unique:${name}`] = true;
|
||||
} catch (error) {
|
||||
} catch (_error) {
|
||||
details[`unique:${name}`] = false;
|
||||
allHealthy = false;
|
||||
}
|
||||
|
|
|
|||
2
libs/cache/src/redis-cache.ts
vendored
2
libs/cache/src/redis-cache.ts
vendored
|
|
@ -87,7 +87,7 @@ export class RedisCache implements CacheProvider {
|
|||
}
|
||||
|
||||
private updateStats(hit: boolean, error = false): void {
|
||||
if (!this.enableMetrics) return;
|
||||
if (!this.enableMetrics) {return;}
|
||||
|
||||
if (error) {
|
||||
this.stats.errors++;
|
||||
|
|
|
|||
22
libs/cache/tsconfig.json
vendored
22
libs/cache/tsconfig.json
vendored
|
|
@ -1,13 +1,9 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [
|
||||
{ "path": "../types" },
|
||||
{ "path": "../config" },
|
||||
{ "path": "../logger" }
|
||||
]
|
||||
}
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [{ "path": "../types" }, { "path": "../config" }, { "path": "../logger" }]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,44 +1,44 @@
|
|||
{
|
||||
"name": "@stock-bot/config",
|
||||
"version": "1.0.0",
|
||||
"description": "Configuration management library for Stock Bot platform",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"type-check": "tsc --noEmit",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"dotenv": "^16.5.0",
|
||||
"yup": "^1.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"eslint": "^8.56.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
||||
"@typescript-eslint/parser": "^6.19.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"keywords": [
|
||||
"configuration",
|
||||
"settings",
|
||||
"env",
|
||||
"stock-bot"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
{
|
||||
"name": "@stock-bot/config",
|
||||
"version": "1.0.0",
|
||||
"description": "Configuration management library for Stock Bot platform",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"type-check": "tsc --noEmit",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"dotenv": "^16.5.0",
|
||||
"yup": "^1.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"eslint": "^8.56.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
||||
"@typescript-eslint/parser": "^6.19.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"keywords": [
|
||||
"configuration",
|
||||
"settings",
|
||||
"env",
|
||||
"stock-bot"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts", "**/test/**/*", "**/tests/**/*"],
|
||||
"references": [
|
||||
{ "path": "../types" }
|
||||
]
|
||||
}
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.ts",
|
||||
"**/test/**/*",
|
||||
"**/tests/**/*"
|
||||
],
|
||||
"references": [{ "path": "../types" }]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,24 @@
|
|||
{
|
||||
"name": "@stock-bot/data-adjustments",
|
||||
"version": "1.0.0",
|
||||
"description": "Stock split and dividend adjustment utilities for market data",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"test:watch": "bun test --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/types": "*",
|
||||
"@stock-bot/logger": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.4.5",
|
||||
"bun-types": "^1.1.12"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5.0.0"
|
||||
}
|
||||
}
|
||||
{
|
||||
"name": "@stock-bot/data-adjustments",
|
||||
"version": "1.0.0",
|
||||
"description": "Stock split and dividend adjustment utilities for market data",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"test:watch": "bun test --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/types": "*",
|
||||
"@stock-bot/logger": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.4.5",
|
||||
"bun-types": "^1.1.12"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,33 +1,33 @@
|
|||
{
|
||||
"name": "@stock-bot/data-frame",
|
||||
"version": "1.0.0",
|
||||
"description": "DataFrame library for time series data manipulation",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/logger": "*",
|
||||
"@stock-bot/utils": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
{
|
||||
"name": "@stock-bot/data-frame",
|
||||
"version": "1.0.0",
|
||||
"description": "DataFrame library for time series data manipulation",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/logger": "*",
|
||||
"@stock-bot/utils": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ export class DataFrame {
|
|||
}
|
||||
|
||||
private inferColumns(): string[] {
|
||||
if (this.data.length === 0) return [];
|
||||
if (this.data.length === 0) {return [];}
|
||||
|
||||
const columns = new Set<string>();
|
||||
for (const row of this.data) {
|
||||
|
|
@ -46,7 +46,7 @@ export class DataFrame {
|
|||
}
|
||||
|
||||
private validateAndCleanData(): void {
|
||||
if (this.data.length === 0) return;
|
||||
if (this.data.length === 0) {return;}
|
||||
|
||||
// Ensure all rows have the same columns
|
||||
for (let i = 0; i < this.data.length; i++) {
|
||||
|
|
@ -224,7 +224,7 @@ export class DataFrame {
|
|||
const aVal = a[column];
|
||||
const bVal = b[column];
|
||||
|
||||
if (aVal === bVal) return 0;
|
||||
if (aVal === bVal) {return 0;}
|
||||
|
||||
const comparison = aVal > bVal ? 1 : -1;
|
||||
return ascending ? comparison : -comparison;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [
|
||||
{ "path": "../types" },
|
||||
{ "path": "../logger" },
|
||||
{ "path": "../utils" }
|
||||
]
|
||||
}
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [{ "path": "../types" }, { "path": "../logger" }, { "path": "../utils" }]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,35 +1,35 @@
|
|||
{
|
||||
"name": "@stock-bot/event-bus",
|
||||
"version": "1.0.0",
|
||||
"description": "Event bus library for inter-service communication",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/logger": "*",
|
||||
"@stock-bot/config": "*",
|
||||
"ioredis": "^5.3.2",
|
||||
"eventemitter3": "^5.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
{
|
||||
"name": "@stock-bot/event-bus",
|
||||
"version": "1.0.0",
|
||||
"description": "Event bus library for inter-service communication",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/logger": "*",
|
||||
"@stock-bot/config": "*",
|
||||
"ioredis": "^5.3.2",
|
||||
"eventemitter3": "^5.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [
|
||||
{ "path": "../types" },
|
||||
{ "path": "../config" },
|
||||
{ "path": "../logger" }
|
||||
]
|
||||
}
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [{ "path": "../types" }, { "path": "../config" }, { "path": "../logger" }]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,44 +1,44 @@
|
|||
{
|
||||
"name": "@stock-bot/http",
|
||||
"version": "1.0.0",
|
||||
"description": "HTTP client library with proxy support, rate limiting, and timeout for Stock Bot platform",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"test:watch": "bun test --watch",
|
||||
"test:coverage": "bun test --coverage",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"type-check": "tsc --noEmit",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/logger": "*",
|
||||
"@stock-bot/types": "*",
|
||||
"axios": "^1.9.0",
|
||||
"http-proxy-agent": "^7.0.2",
|
||||
"https-proxy-agent": "^7.0.6",
|
||||
"socks-proxy-agent": "^8.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"eslint": "^8.56.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
||||
"@typescript-eslint/parser": "^6.19.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
{
|
||||
"name": "@stock-bot/http",
|
||||
"version": "1.0.0",
|
||||
"description": "HTTP client library with proxy support, rate limiting, and timeout for Stock Bot platform",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"test:watch": "bun test --watch",
|
||||
"test:coverage": "bun test --coverage",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"type-check": "tsc --noEmit",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/logger": "*",
|
||||
"@stock-bot/types": "*",
|
||||
"axios": "^1.9.0",
|
||||
"http-proxy-agent": "^7.0.2",
|
||||
"https-proxy-agent": "^7.0.6",
|
||||
"socks-proxy-agent": "^8.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"eslint": "^8.56.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
||||
"@typescript-eslint/parser": "^6.19.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import type { Logger } from '@stock-bot/logger';
|
||||
import { AdapterFactory } from './adapters/index';
|
||||
import { ProxyManager } from './proxy-manager';
|
||||
import type { HttpClientConfig, HttpResponse, RequestConfig } from './types';
|
||||
import { HttpError } from './types';
|
||||
|
||||
|
|
@ -144,7 +143,7 @@ export class HttpClient {
|
|||
const elapsed = Date.now() - startTime;
|
||||
this.logger?.debug('Adapter failed successful', {
|
||||
url: config.url,
|
||||
elapsedMs: Date.now() - startTime,
|
||||
elapsedMs: elapsed,
|
||||
});
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import axios, { AxiosRequestConfig, type AxiosInstance } from 'axios';
|
||||
import { AxiosRequestConfig } from 'axios';
|
||||
import { HttpProxyAgent } from 'http-proxy-agent';
|
||||
import { HttpsProxyAgent } from 'https-proxy-agent';
|
||||
import { SocksProxyAgent } from 'socks-proxy-agent';
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts", "**/test/**/*", "**/tests/**/*"],
|
||||
"references": [
|
||||
{ "path": "../types" },
|
||||
{ "path": "../logger" }
|
||||
]
|
||||
}
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist",
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.ts",
|
||||
"**/test/**/*",
|
||||
"**/tests/**/*"
|
||||
],
|
||||
"references": [{ "path": "../types" }, { "path": "../logger" }]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,9 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [
|
||||
{ "path": "../types" },
|
||||
{ "path": "../config" }
|
||||
]
|
||||
}
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [{ "path": "../types" }, { "path": "../config" }]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,51 +1,54 @@
|
|||
{
|
||||
"name": "@stock-bot/mongodb-client",
|
||||
"version": "1.0.0",
|
||||
"description": "MongoDB client library for Stock Bot platform",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"type-check": "tsc --noEmit",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/config": "*",
|
||||
"@stock-bot/logger": "*",
|
||||
"@stock-bot/types": "*",
|
||||
"@types/mongodb": "^4.0.7",
|
||||
"mongodb": "^6.17.0",
|
||||
"yup": "^1.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"eslint": "^8.56.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
||||
"@typescript-eslint/parser": "^6.19.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"keywords": [
|
||||
"mongodb",
|
||||
"database",
|
||||
"client",
|
||||
"stock-bot"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
],
|
||||
"paths": {
|
||||
"*": ["node_modules/*", "../../node_modules/*"]
|
||||
}
|
||||
}
|
||||
{
|
||||
"name": "@stock-bot/mongodb-client",
|
||||
"version": "1.0.0",
|
||||
"description": "MongoDB client library for Stock Bot platform",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"type-check": "tsc --noEmit",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/config": "*",
|
||||
"@stock-bot/logger": "*",
|
||||
"@stock-bot/types": "*",
|
||||
"@types/mongodb": "^4.0.7",
|
||||
"mongodb": "^6.17.0",
|
||||
"yup": "^1.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"eslint": "^8.56.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
||||
"@typescript-eslint/parser": "^6.19.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"keywords": [
|
||||
"mongodb",
|
||||
"database",
|
||||
"client",
|
||||
"stock-bot"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
],
|
||||
"paths": {
|
||||
"*": [
|
||||
"node_modules/*",
|
||||
"../../node_modules/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ export class MongoDBAggregationBuilder {
|
|||
this.from('sentiment_data');
|
||||
|
||||
const matchConditions: any = {};
|
||||
if (symbol) matchConditions.symbol = symbol;
|
||||
if (symbol) {matchConditions.symbol = symbol;}
|
||||
if (timeframe) {
|
||||
matchConditions.timestamp = {
|
||||
$gte: timeframe.start,
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [
|
||||
{ "path": "../types" },
|
||||
{ "path": "../config" },
|
||||
{ "path": "../logger" }
|
||||
]
|
||||
}
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [{ "path": "../types" }, { "path": "../config" }, { "path": "../logger" }]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +1,48 @@
|
|||
{
|
||||
"name": "@stock-bot/postgres-client",
|
||||
"version": "1.0.0",
|
||||
"description": "PostgreSQL client library for Stock Bot platform",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"type-check": "tsc --noEmit",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": { "@stock-bot/config": "*",
|
||||
"@stock-bot/logger": "*",
|
||||
"@stock-bot/types": "*",
|
||||
"pg": "^8.11.3",
|
||||
"yup": "^1.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"@types/pg": "^8.10.7",
|
||||
"typescript": "^5.3.0",
|
||||
"eslint": "^8.56.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
||||
"@typescript-eslint/parser": "^6.19.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"keywords": [
|
||||
"postgresql",
|
||||
"database",
|
||||
"client",
|
||||
"stock-bot"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
{
|
||||
"name": "@stock-bot/postgres-client",
|
||||
"version": "1.0.0",
|
||||
"description": "PostgreSQL client library for Stock Bot platform",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"type-check": "tsc --noEmit",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/config": "*",
|
||||
"@stock-bot/logger": "*",
|
||||
"@stock-bot/types": "*",
|
||||
"pg": "^8.11.3",
|
||||
"yup": "^1.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"@types/pg": "^8.10.7",
|
||||
"typescript": "^5.3.0",
|
||||
"eslint": "^8.56.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
||||
"@typescript-eslint/parser": "^6.19.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"keywords": [
|
||||
"postgresql",
|
||||
"database",
|
||||
"client",
|
||||
"stock-bot"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -327,7 +327,7 @@ export class PostgreSQLClient {
|
|||
}
|
||||
|
||||
private setupErrorHandlers(): void {
|
||||
if (!this.pool) return;
|
||||
if (!this.pool) {return;}
|
||||
|
||||
this.pool.on('error', error => {
|
||||
this.logger.error('PostgreSQL pool error:', error);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [
|
||||
{ "path": "../types" },
|
||||
{ "path": "../config" },
|
||||
{ "path": "../logger" }
|
||||
]
|
||||
}
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [{ "path": "../types" }, { "path": "../config" }, { "path": "../logger" }]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,45 +1,45 @@
|
|||
{
|
||||
"name": "@stock-bot/questdb-client",
|
||||
"version": "1.0.0",
|
||||
"description": "QuestDB client library for Stock Bot platform",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"type-check": "tsc --noEmit",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/config": "*",
|
||||
"@stock-bot/logger": "*",
|
||||
"@stock-bot/types": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"eslint": "^8.56.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
||||
"@typescript-eslint/parser": "^6.19.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"keywords": [
|
||||
"questdb",
|
||||
"database",
|
||||
"client",
|
||||
"stock-bot"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
{
|
||||
"name": "@stock-bot/questdb-client",
|
||||
"version": "1.0.0",
|
||||
"description": "QuestDB client library for Stock Bot platform",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"type-check": "tsc --noEmit",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/config": "*",
|
||||
"@stock-bot/logger": "*",
|
||||
"@stock-bot/types": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"eslint": "^8.56.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
||||
"@typescript-eslint/parser": "^6.19.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"keywords": [
|
||||
"questdb",
|
||||
"database",
|
||||
"client",
|
||||
"stock-bot"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [
|
||||
{ "path": "../types" },
|
||||
{ "path": "../config" },
|
||||
{ "path": "../logger" }
|
||||
]
|
||||
}
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [{ "path": "../types" }, { "path": "../config" }, { "path": "../logger" }]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,26 +1,27 @@
|
|||
{
|
||||
"name": "@stock-bot/shutdown",
|
||||
"version": "1.0.0",
|
||||
"description": "Graceful shutdown management for Stock Bot platform",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts", "scripts": {
|
||||
"build": "tsc",
|
||||
"clean": "rm -rf dist",
|
||||
"test": "bun test"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.0.0",
|
||||
"@types/node": "^20.0.0"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
{
|
||||
"name": "@stock-bot/shutdown",
|
||||
"version": "1.0.0",
|
||||
"description": "Graceful shutdown management for Stock Bot platform",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"clean": "rm -rf dist",
|
||||
"test": "bun test"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.0.0",
|
||||
"@types/node": "^20.0.0"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [
|
||||
{ "path": "../types" },
|
||||
{ "path": "../config" },
|
||||
{ "path": "../logger" }
|
||||
]
|
||||
}
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [{ "path": "../types" }, { "path": "../config" }, { "path": "../logger" }]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"], "references": [
|
||||
{ "path": "../types" },
|
||||
{ "path": "../logger" },
|
||||
{ "path": "../utils" },
|
||||
{ "path": "../event-bus" },
|
||||
{ "path": "../data-frame" },
|
||||
{ "path": "../vector-engine" }
|
||||
]
|
||||
}
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [
|
||||
{ "path": "../types" },
|
||||
{ "path": "../logger" },
|
||||
{ "path": "../utils" },
|
||||
{ "path": "../event-bus" },
|
||||
{ "path": "../data-frame" },
|
||||
{ "path": "../vector-engine" }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,35 +1,35 @@
|
|||
{
|
||||
"name": "@stock-bot/types",
|
||||
"version": "1.0.0",
|
||||
"description": "Shared type definitions for Stock Bot platform",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"type-check": "tsc --noEmit",
|
||||
"clean": "rimraf dist",
|
||||
"test": "bun test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"keywords": [
|
||||
"types",
|
||||
"typescript",
|
||||
"stock-bot"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
{
|
||||
"name": "@stock-bot/types",
|
||||
"version": "1.0.0",
|
||||
"description": "Shared type definitions for Stock Bot platform",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"type-check": "tsc --noEmit",
|
||||
"clean": "rimraf dist",
|
||||
"test": "bun test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"keywords": [
|
||||
"types",
|
||||
"typescript",
|
||||
"stock-bot"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": []
|
||||
}
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": []
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,33 +1,33 @@
|
|||
{
|
||||
"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",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"clean": "rimraf dist",
|
||||
"test": "bun test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/types": "*",
|
||||
"date-fns": "^2.30.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
{
|
||||
"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",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"clean": "rimraf dist",
|
||||
"test": "bun test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/types": "*",
|
||||
"date-fns": "^2.30.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Calculate percentage change between two values
|
||||
*/
|
||||
export function percentageChange(oldValue: number, newValue: number): number {
|
||||
if (oldValue === 0) return 0;
|
||||
if (oldValue === 0) {return 0;}
|
||||
return ((newValue - oldValue) / oldValue) * 100;
|
||||
}
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ export function percentageChange(oldValue: number, newValue: number): number {
|
|||
* Calculate simple return
|
||||
*/
|
||||
export function simpleReturn(initialPrice: number, finalPrice: number): number {
|
||||
if (initialPrice === 0) return 0;
|
||||
if (initialPrice === 0) {return 0;}
|
||||
return (finalPrice - initialPrice) / initialPrice;
|
||||
}
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ export function simpleReturn(initialPrice: number, finalPrice: number): number {
|
|||
* Calculate logarithmic return
|
||||
*/
|
||||
export function logReturn(initialPrice: number, finalPrice: number): number {
|
||||
if (initialPrice <= 0 || finalPrice <= 0) return 0;
|
||||
if (initialPrice <= 0 || finalPrice <= 0) {return 0;}
|
||||
return Math.log(finalPrice / initialPrice);
|
||||
}
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ export function logReturn(initialPrice: number, finalPrice: number): number {
|
|||
* Calculate compound annual growth rate (CAGR)
|
||||
*/
|
||||
export function cagr(startValue: number, endValue: number, years: number): number {
|
||||
if (years <= 0 || startValue <= 0 || endValue <= 0) return 0;
|
||||
if (years <= 0 || startValue <= 0 || endValue <= 0) {return 0;}
|
||||
return Math.pow(endValue / startValue, 1 / years) - 1;
|
||||
}
|
||||
|
||||
|
|
@ -91,8 +91,8 @@ export function internalRateOfReturn(
|
|||
dnpv += (-j * cashFlows[j]) / Math.pow(1 + rate, j + 1);
|
||||
}
|
||||
|
||||
if (Math.abs(npv) < 1e-10) break;
|
||||
if (Math.abs(dnpv) < 1e-10) break;
|
||||
if (Math.abs(npv) < 1e-10) {break;}
|
||||
if (Math.abs(dnpv) < 1e-10) {break;}
|
||||
|
||||
rate = rate - npv / dnpv;
|
||||
}
|
||||
|
|
@ -186,7 +186,7 @@ export function bondYield(
|
|||
);
|
||||
const diff = calculatedPrice - price;
|
||||
|
||||
if (Math.abs(diff) < tolerance) break;
|
||||
if (Math.abs(diff) < tolerance) {break;}
|
||||
|
||||
// Numerical derivative
|
||||
const delta = 0.0001;
|
||||
|
|
@ -199,7 +199,7 @@ export function bondYield(
|
|||
);
|
||||
const derivative = (priceUp - calculatedPrice) / delta;
|
||||
|
||||
if (Math.abs(derivative) < tolerance) break;
|
||||
if (Math.abs(derivative) < tolerance) {break;}
|
||||
|
||||
yield_ = yield_ - diff / derivative;
|
||||
}
|
||||
|
|
@ -358,7 +358,7 @@ export function dividendDiscountModel(
|
|||
growthRate: number,
|
||||
discountRate: number
|
||||
): number {
|
||||
if (discountRate <= growthRate) return NaN; // Indeterminate
|
||||
if (discountRate <= growthRate) {return NaN;} // Indeterminate
|
||||
return (currentDividend * (1 + growthRate)) / (discountRate - growthRate);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -488,7 +488,7 @@ export function dccModel(
|
|||
const T = data[0].length;
|
||||
|
||||
// Initialize parameters [alpha, beta]
|
||||
let params = [0.01, 0.95];
|
||||
const params = [0.01, 0.95];
|
||||
|
||||
// Standardize data (assume unit variance for simplicity)
|
||||
const standardizedData = data.map(series => {
|
||||
|
|
@ -918,7 +918,7 @@ function shuffleArray<T>(array: T[]): T[] {
|
|||
* Helper function to calculate the average of an array of numbers
|
||||
*/
|
||||
function average(arr: number[]): number {
|
||||
if (arr.length === 0) return 0;
|
||||
if (arr.length === 0) {return 0;}
|
||||
return arr.reduce((a, b) => a + b, 0) / arr.length;
|
||||
}
|
||||
|
||||
|
|
@ -963,8 +963,8 @@ function erf(x: number): number {
|
|||
|
||||
function betaIncomplete(a: number, b: number, x: number): number {
|
||||
// Better approximation of incomplete beta function
|
||||
if (x === 0) return 0;
|
||||
if (x === 1) return 1;
|
||||
if (x === 0) {return 0;}
|
||||
if (x === 1) {return 1;}
|
||||
|
||||
// Use continued fraction approximation (Lentz's algorithm)
|
||||
const fpmin = 1e-30;
|
||||
|
|
@ -984,7 +984,7 @@ function betaIncomplete(a: number, b: number, x: number): number {
|
|||
function betaContinuedFraction(a: number, b: number, x: number): number {
|
||||
let c = 1;
|
||||
let d = 1 - ((a + b) * x) / (a + 1);
|
||||
if (Math.abs(d) < fpmin) d = fpmin;
|
||||
if (Math.abs(d) < fpmin) {d = fpmin;}
|
||||
d = 1 / d;
|
||||
let h = d;
|
||||
|
||||
|
|
@ -992,22 +992,22 @@ function betaIncomplete(a: number, b: number, x: number): number {
|
|||
const m2 = 2 * m;
|
||||
const aa = (m * (b - m) * x) / ((a + m2 - 1) * (a + m2));
|
||||
d = 1 + aa * d;
|
||||
if (Math.abs(d) < fpmin) d = fpmin;
|
||||
if (Math.abs(d) < fpmin) {d = fpmin;}
|
||||
c = 1 + aa / c;
|
||||
if (Math.abs(c) < fpmin) c = fpmin;
|
||||
if (Math.abs(c) < fpmin) {c = fpmin;}
|
||||
d = 1 / d;
|
||||
h *= d * c;
|
||||
|
||||
const bb = (-(a + m) * (a + b + m) * x) / ((a + m2) * (a + m2 + 1));
|
||||
d = 1 + bb * d;
|
||||
if (Math.abs(d) < fpmin) d = fpmin;
|
||||
if (Math.abs(d) < fpmin) {d = fpmin;}
|
||||
c = 1 + bb / c;
|
||||
if (Math.abs(c) < fpmin) c = fpmin;
|
||||
if (Math.abs(c) < fpmin) {c = fpmin;}
|
||||
d = 1 / d;
|
||||
const del = d * c;
|
||||
h *= del;
|
||||
|
||||
if (Math.abs(del - 1) < eps) break;
|
||||
if (Math.abs(del - 1) < eps) {break;}
|
||||
}
|
||||
|
||||
return h;
|
||||
|
|
@ -1055,11 +1055,11 @@ function eigenDecomposition(matrix: number[][]): {
|
|||
const newLambda = Av.reduce((sum, val, i) => sum + val * v[i], 0);
|
||||
const norm = Math.sqrt(Av.reduce((sum, val) => sum + val * val, 0));
|
||||
|
||||
if (norm === 0) break;
|
||||
if (norm === 0) {break;}
|
||||
|
||||
v = Av.map(val => val / norm);
|
||||
|
||||
if (Math.abs(newLambda - lambda) < 1e-10) break;
|
||||
if (Math.abs(newLambda - lambda) < 1e-10) {break;}
|
||||
lambda = newLambda;
|
||||
}
|
||||
|
||||
|
|
@ -1215,8 +1215,8 @@ function arModel(y: number[], lag: number): { rss: number } {
|
|||
|
||||
function fCDF(f: number, df1: number, df2: number): number {
|
||||
// Approximation for F distribution CDF
|
||||
if (f <= 0) return 0;
|
||||
if (f === Infinity) return 1;
|
||||
if (f <= 0) {return 0;}
|
||||
if (f === Infinity) {return 1;}
|
||||
|
||||
const x = df2 / (df2 + df1 * f);
|
||||
return 1 - betaIncomplete(df2 / 2, df1 / 2, x);
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ export interface MarketRegime {
|
|||
* Volume Weighted Average Price (VWAP)
|
||||
*/
|
||||
export function VWAP(ohlcv: OHLCVData[]): number[] {
|
||||
if (ohlcv.length === 0) return [];
|
||||
if (ohlcv.length === 0) {return [];}
|
||||
|
||||
const vwap: number[] = [];
|
||||
let cumulativeVolumePrice = 0;
|
||||
|
|
@ -76,7 +76,7 @@ export function VWAP(ohlcv: OHLCVData[]): number[] {
|
|||
* Time Weighted Average Price (TWAP)
|
||||
*/
|
||||
export function TWAP(prices: number[], timeWeights?: number[]): number {
|
||||
if (prices.length === 0) return 0;
|
||||
if (prices.length === 0) {return 0;}
|
||||
|
||||
if (!timeWeights) {
|
||||
return prices.reduce((sum, price) => sum + price, 0) / prices.length;
|
||||
|
|
@ -227,9 +227,9 @@ export function identifyMarketRegime(
|
|||
|
||||
// Determine volatility level
|
||||
let volatilityLevel: 'low' | 'medium' | 'high';
|
||||
if (volatility < 0.01) volatilityLevel = 'low';
|
||||
else if (volatility < 0.03) volatilityLevel = 'medium';
|
||||
else volatilityLevel = 'high';
|
||||
if (volatility < 0.01) {volatilityLevel = 'low';}
|
||||
else if (volatility < 0.03) {volatilityLevel = 'medium';}
|
||||
else {volatilityLevel = 'high';}
|
||||
|
||||
// Determine regime
|
||||
let regime: 'trending' | 'ranging' | 'volatile' | 'quiet';
|
||||
|
|
@ -281,7 +281,7 @@ export function OrderBookImbalance(
|
|||
|
||||
const totalVolume = totalBidVolume + totalAskVolume;
|
||||
|
||||
if (totalVolume === 0) return 0;
|
||||
if (totalVolume === 0) {return 0;}
|
||||
|
||||
return (totalBidVolume - totalAskVolume) / totalVolume;
|
||||
}
|
||||
|
|
@ -452,10 +452,10 @@ export function MarketStress(
|
|||
const overallStress = volatilityStress * 0.4 + liquidityStress * 0.3 + correlationStress * 0.3;
|
||||
|
||||
let stressLevel: 'low' | 'medium' | 'high' | 'extreme';
|
||||
if (overallStress < 0.25) stressLevel = 'low';
|
||||
else if (overallStress < 0.5) stressLevel = 'medium';
|
||||
else if (overallStress < 0.75) stressLevel = 'high';
|
||||
else stressLevel = 'extreme';
|
||||
if (overallStress < 0.25) {stressLevel = 'low';}
|
||||
else if (overallStress < 0.5) {stressLevel = 'medium';}
|
||||
else if (overallStress < 0.75) {stressLevel = 'high';}
|
||||
else {stressLevel = 'extreme';}
|
||||
|
||||
return {
|
||||
stressLevel,
|
||||
|
|
@ -474,7 +474,7 @@ export function RealizedSpread(
|
|||
midPrices: number[],
|
||||
timeWindow: number = 5 // minutes
|
||||
): number {
|
||||
if (trades.length === 0 || midPrices.length === 0) return 0;
|
||||
if (trades.length === 0 || midPrices.length === 0) {return 0;}
|
||||
|
||||
let totalSpread = 0;
|
||||
let count = 0;
|
||||
|
|
@ -541,7 +541,7 @@ export function ImplementationShortfall(
|
|||
* Amihud Illiquidity Measure (price impact per unit of volume)
|
||||
*/
|
||||
export function amihudIlliquidity(ohlcv: OHLCVData[], lookbackPeriod: number = 252): number {
|
||||
if (ohlcv.length < lookbackPeriod) return 0;
|
||||
if (ohlcv.length < lookbackPeriod) {return 0;}
|
||||
|
||||
const recentData = ohlcv.slice(-lookbackPeriod);
|
||||
let illiquiditySum = 0;
|
||||
|
|
@ -566,7 +566,7 @@ export function amihudIlliquidity(ohlcv: OHLCVData[], lookbackPeriod: number = 2
|
|||
* Roll's Spread Estimator (effective spread from serial covariance)
|
||||
*/
|
||||
export function rollSpreadEstimator(prices: number[]): number {
|
||||
if (prices.length < 3) return 0;
|
||||
if (prices.length < 3) {return 0;}
|
||||
|
||||
// Calculate price changes
|
||||
const priceChanges: number[] = [];
|
||||
|
|
@ -594,7 +594,7 @@ export function kyleLambda(
|
|||
priceChanges: number[],
|
||||
orderFlow: number[] // Signed order flow (positive for buys, negative for sells)
|
||||
): number {
|
||||
if (priceChanges.length !== orderFlow.length || priceChanges.length < 2) return 0;
|
||||
if (priceChanges.length !== orderFlow.length || priceChanges.length < 2) {return 0;}
|
||||
|
||||
// Calculate regression: priceChange = lambda * orderFlow + error
|
||||
const n = priceChanges.length;
|
||||
|
|
@ -623,7 +623,7 @@ export function probabilityInformedTrading(
|
|||
sellVolumes: number[],
|
||||
period: number = 20
|
||||
): number {
|
||||
if (buyVolumes.length !== sellVolumes.length || buyVolumes.length < period) return 0;
|
||||
if (buyVolumes.length !== sellVolumes.length || buyVolumes.length < period) {return 0;}
|
||||
|
||||
const recentBuys = buyVolumes.slice(-period);
|
||||
const recentSells = sellVolumes.slice(-period);
|
||||
|
|
@ -647,11 +647,11 @@ export function probabilityInformedTrading(
|
|||
* Herfindahl-Hirschman Index for Volume Concentration
|
||||
*/
|
||||
export function volumeConcentrationHHI(exchanges: Array<{ name: string; volume: number }>): number {
|
||||
if (exchanges.length === 0) return 0;
|
||||
if (exchanges.length === 0) {return 0;}
|
||||
|
||||
const totalVolume = exchanges.reduce((sum, exchange) => sum + exchange.volume, 0);
|
||||
|
||||
if (totalVolume === 0) return 0;
|
||||
if (totalVolume === 0) {return 0;}
|
||||
|
||||
let hhi = 0;
|
||||
for (const exchange of exchanges) {
|
||||
|
|
@ -670,7 +670,7 @@ export function volumeProfile(
|
|||
): { [price: number]: number } {
|
||||
const profile: { [price: number]: number } = {};
|
||||
|
||||
if (ohlcv.length === 0) return profile;
|
||||
if (ohlcv.length === 0) {return profile;}
|
||||
|
||||
const minPrice = Math.min(...ohlcv.map(candle => candle.low));
|
||||
const maxPrice = Math.max(...ohlcv.map(candle => candle.high));
|
||||
|
|
@ -814,11 +814,11 @@ export function garmanKlassVolatility(
|
|||
openPrices.length !== closePrices.length ||
|
||||
openPrices.length < 2
|
||||
)
|
||||
return 0;
|
||||
{return 0;}
|
||||
|
||||
let sumSquaredTerm1 = 0;
|
||||
let sumSquaredTerm2 = 0;
|
||||
let sumSquaredTerm3 = 0;
|
||||
const sumSquaredTerm3 = 0;
|
||||
|
||||
for (let i = 0; i < openPrices.length; i++) {
|
||||
const logHO = Math.log(highPrices[i] / openPrices[i]);
|
||||
|
|
@ -850,7 +850,7 @@ export function yangZhangVolatility(
|
|||
openPrices.length !== previousClosePrices.length ||
|
||||
openPrices.length < 2
|
||||
)
|
||||
return 0;
|
||||
{return 0;}
|
||||
|
||||
const k = 0.34 / (1.34 + (openPrices.length + 1) / (previousClosePrices.length - 1));
|
||||
|
||||
|
|
@ -877,7 +877,7 @@ export function yangZhangVolatility(
|
|||
* Volume Order Imbalance (VOI)
|
||||
*/
|
||||
export function volumeOrderImbalance(buyVolumes: number[], sellVolumes: number[]): number[] {
|
||||
if (buyVolumes.length !== sellVolumes.length) return [];
|
||||
if (buyVolumes.length !== sellVolumes.length) {return [];}
|
||||
|
||||
const voi: number[] = [];
|
||||
for (let i = 0; i < buyVolumes.length; i++) {
|
||||
|
|
@ -890,7 +890,7 @@ export function volumeOrderImbalance(buyVolumes: number[], sellVolumes: number[]
|
|||
* Cumulative Volume Delta (CVD)
|
||||
*/
|
||||
export function cumulativeVolumeDelta(buyVolumes: number[], sellVolumes: number[]): number[] {
|
||||
if (buyVolumes.length !== sellVolumes.length) return [];
|
||||
if (buyVolumes.length !== sellVolumes.length) {return [];}
|
||||
|
||||
const cvd: number[] = [];
|
||||
let cumulativeDelta = 0;
|
||||
|
|
@ -905,7 +905,7 @@ export function cumulativeVolumeDelta(buyVolumes: number[], sellVolumes: number[
|
|||
* Market Order Ratio
|
||||
*/
|
||||
export function marketOrderRatio(marketOrders: number[], limitOrders: number[]): number[] {
|
||||
if (marketOrders.length !== limitOrders.length) return [];
|
||||
if (marketOrders.length !== limitOrders.length) {return [];}
|
||||
|
||||
const ratios: number[] = [];
|
||||
for (let i = 0; i < marketOrders.length; i++) {
|
||||
|
|
@ -920,12 +920,12 @@ export function marketOrderRatio(marketOrders: number[], limitOrders: number[]):
|
|||
*/
|
||||
|
||||
function average(arr: number[]): number {
|
||||
if (arr.length === 0) return 0;
|
||||
if (arr.length === 0) {return 0;}
|
||||
return arr.reduce((a, b) => a + b, 0) / arr.length;
|
||||
}
|
||||
|
||||
function calculateVolatility(returns: number[]): number {
|
||||
if (returns.length < 2) return 0;
|
||||
if (returns.length < 2) {return 0;}
|
||||
|
||||
const mean = returns.reduce((sum, ret) => sum + ret, 0) / returns.length;
|
||||
const variance =
|
||||
|
|
@ -935,7 +935,7 @@ function calculateVolatility(returns: number[]): number {
|
|||
}
|
||||
|
||||
function calculateCorrelation(x: number[], y: number[]): number {
|
||||
if (x.length !== y.length || x.length < 2) return 0;
|
||||
if (x.length !== y.length || x.length < 2) {return 0;}
|
||||
|
||||
const n = x.length;
|
||||
const meanX = x.reduce((sum, val) => sum + val, 0) / n;
|
||||
|
|
@ -960,14 +960,14 @@ function calculateCorrelation(x: number[], y: number[]): number {
|
|||
}
|
||||
|
||||
function calculateVariance(values: number[]): number {
|
||||
if (values.length < 2) return 0;
|
||||
if (values.length < 2) {return 0;}
|
||||
|
||||
const mean = values.reduce((sum, val) => sum + val, 0) / values.length;
|
||||
return values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / (values.length - 1);
|
||||
}
|
||||
|
||||
function calculateCovariance(x: number[], y: number[]): number {
|
||||
if (x.length !== y.length || x.length < 2) return 0;
|
||||
if (x.length !== y.length || x.length < 2) {return 0;}
|
||||
|
||||
const n = x.length;
|
||||
const meanX = x.reduce((sum, val) => sum + val, 0) / n;
|
||||
|
|
|
|||
|
|
@ -605,7 +605,7 @@ function erf(x: number): number {
|
|||
*/
|
||||
function boxMullerTransform(): number {
|
||||
let u1 = Math.random();
|
||||
let u2 = Math.random();
|
||||
const u2 = Math.random();
|
||||
|
||||
// Ensure u1 is not zero
|
||||
while (u1 === 0) {
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ export function analyzeDrawdowns(
|
|||
}> = [];
|
||||
|
||||
let currentDrawdownStart: Date | null = null;
|
||||
let drawdowns: number[] = [];
|
||||
const drawdowns: number[] = [];
|
||||
|
||||
for (let i = 1; i < equityCurve.length; i++) {
|
||||
const current = equityCurve[i];
|
||||
|
|
@ -297,7 +297,7 @@ export function calculateRollingMetrics(
|
|||
windowSize: number,
|
||||
metricType: 'sharpe' | 'volatility' | 'return' = 'sharpe'
|
||||
): number[] {
|
||||
if (returns.length < windowSize) return [];
|
||||
if (returns.length < windowSize) {return [];}
|
||||
|
||||
const rollingMetrics: number[] = [];
|
||||
|
||||
|
|
@ -377,7 +377,7 @@ export function strategyPerformanceAttribution(
|
|||
* Calculate Omega ratio
|
||||
*/
|
||||
export function omegaRatio(returns: number[], threshold: number = 0): number {
|
||||
if (returns.length === 0) return 0;
|
||||
if (returns.length === 0) {return 0;}
|
||||
|
||||
const gains = returns
|
||||
.filter(ret => ret > threshold)
|
||||
|
|
@ -393,7 +393,7 @@ export function omegaRatio(returns: number[], threshold: number = 0): number {
|
|||
* Calculate gain-to-pain ratio
|
||||
*/
|
||||
export function gainToPainRatio(returns: number[]): number {
|
||||
if (returns.length === 0) return 0;
|
||||
if (returns.length === 0) {return 0;}
|
||||
|
||||
const totalGain = returns.reduce((sum, ret) => sum + ret, 0);
|
||||
const totalPain = returns.filter(ret => ret < 0).reduce((sum, ret) => sum + Math.abs(ret), 0);
|
||||
|
|
@ -405,12 +405,12 @@ export function gainToPainRatio(returns: number[]): number {
|
|||
* Calculate Martin ratio (modified Sharpe with downside deviation)
|
||||
*/
|
||||
export function martinRatio(returns: number[], riskFreeRate: number = 0): number {
|
||||
if (returns.length === 0) return 0;
|
||||
if (returns.length === 0) {return 0;}
|
||||
|
||||
const averageReturn = returns.reduce((sum, ret) => sum + ret, 0) / returns.length;
|
||||
const downsideReturns = returns.filter(ret => ret < riskFreeRate);
|
||||
|
||||
if (downsideReturns.length === 0) return Infinity;
|
||||
if (downsideReturns.length === 0) {return Infinity;}
|
||||
|
||||
const downsideDeviation = Math.sqrt(
|
||||
downsideReturns.reduce((sum, ret) => sum + Math.pow(ret - riskFreeRate, 2), 0) / returns.length
|
||||
|
|
@ -610,7 +610,7 @@ export function tailRatio(returns: number[], tailPercent: number = 0.1): number
|
|||
const numReturns = returns.length;
|
||||
const tailSize = Math.floor(numReturns * tailPercent);
|
||||
|
||||
if (tailSize === 0) return 0;
|
||||
if (tailSize === 0) {return 0;}
|
||||
|
||||
const sortedReturns = [...returns].sort((a, b) => a - b);
|
||||
const worstTail = sortedReturns.slice(0, tailSize);
|
||||
|
|
@ -631,7 +631,7 @@ export function calculateRollingBeta(
|
|||
windowSize: number
|
||||
): number[] {
|
||||
if (portfolioReturns.length !== marketReturns.length || portfolioReturns.length < windowSize)
|
||||
return [];
|
||||
{return [];}
|
||||
|
||||
const rollingBetas: number[] = [];
|
||||
|
||||
|
|
@ -668,7 +668,7 @@ export function calculateRollingAlpha(
|
|||
windowSize: number
|
||||
): number[] {
|
||||
if (portfolioReturns.length !== marketReturns.length || portfolioReturns.length < windowSize)
|
||||
return [];
|
||||
{return [];}
|
||||
|
||||
const rollingAlphas: number[] = [];
|
||||
|
||||
|
|
@ -728,7 +728,7 @@ export function moneyWeightedRateOfReturn(
|
|||
// Helper functions
|
||||
|
||||
function calculateSharpeRatio(returns: number[], riskFreeRate: number = 0): number {
|
||||
if (returns.length < 2) return 0;
|
||||
if (returns.length < 2) {return 0;}
|
||||
|
||||
const avgReturn = returns.reduce((sum, ret) => sum + ret, 0) / returns.length;
|
||||
const variance =
|
||||
|
|
@ -739,7 +739,7 @@ function calculateSharpeRatio(returns: number[], riskFreeRate: number = 0): numb
|
|||
}
|
||||
|
||||
function calculateVolatility(returns: number[]): number {
|
||||
if (returns.length < 2) return 0;
|
||||
if (returns.length < 2) {return 0;}
|
||||
|
||||
const mean = returns.reduce((sum, ret) => sum + ret, 0) / returns.length;
|
||||
const variance =
|
||||
|
|
@ -749,7 +749,7 @@ function calculateVolatility(returns: number[]): number {
|
|||
}
|
||||
|
||||
function calculateBeta(portfolioReturns: number[], marketReturns: number[]): number {
|
||||
if (portfolioReturns.length !== marketReturns.length || portfolioReturns.length < 2) return 0;
|
||||
if (portfolioReturns.length !== marketReturns.length || portfolioReturns.length < 2) {return 0;}
|
||||
|
||||
const portfolioMean =
|
||||
portfolioReturns.reduce((sum, ret) => sum + ret, 0) / portfolioReturns.length;
|
||||
|
|
@ -786,13 +786,13 @@ function calculateAlpha(
|
|||
}
|
||||
|
||||
function calculateSkewness(returns: number[]): number {
|
||||
if (returns.length < 3) return 0;
|
||||
if (returns.length < 3) {return 0;}
|
||||
|
||||
const mean = returns.reduce((sum, ret) => sum + ret, 0) / returns.length;
|
||||
const variance = returns.reduce((sum, ret) => sum + Math.pow(ret - mean, 2), 0) / returns.length;
|
||||
const stdDev = Math.sqrt(variance);
|
||||
|
||||
if (stdDev === 0) return 0;
|
||||
if (stdDev === 0) {return 0;}
|
||||
|
||||
const skew =
|
||||
returns.reduce((sum, ret) => sum + Math.pow((ret - mean) / stdDev, 3), 0) / returns.length;
|
||||
|
|
@ -801,13 +801,13 @@ function calculateSkewness(returns: number[]): number {
|
|||
}
|
||||
|
||||
function calculateKurtosis(returns: number[]): number {
|
||||
if (returns.length < 4) return 0;
|
||||
if (returns.length < 4) {return 0;}
|
||||
|
||||
const mean = returns.reduce((sum, ret) => sum + ret, 0) / returns.length;
|
||||
const variance = returns.reduce((sum, ret) => sum + Math.pow(ret - mean, 2), 0) / returns.length;
|
||||
const stdDev = Math.sqrt(variance);
|
||||
|
||||
if (stdDev === 0) return 0;
|
||||
if (stdDev === 0) {return 0;}
|
||||
|
||||
const kurt =
|
||||
returns.reduce((sum, ret) => sum + Math.pow((ret - mean) / stdDev, 4), 0) / returns.length;
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ export function riskParityOptimization(covarianceMatrix: number[][]): PortfolioO
|
|||
const sum = newWeights.reduce((s, w) => s + w, 0);
|
||||
weights = newWeights.map(w => w / sum);
|
||||
|
||||
if (converged) break;
|
||||
if (converged) {break;}
|
||||
}
|
||||
|
||||
const portfolioVariance = calculatePortfolioVariance(weights, covarianceMatrix);
|
||||
|
|
@ -402,7 +402,7 @@ export function calculateEfficientFrontier(
|
|||
volatility: number;
|
||||
sharpeRatio: number;
|
||||
}> {
|
||||
if (returns.length !== symbols.length || returns.length < 2) return [];
|
||||
if (returns.length !== symbols.length || returns.length < 2) {return [];}
|
||||
|
||||
const n = returns.length;
|
||||
const results: Array<{
|
||||
|
|
@ -456,7 +456,7 @@ export function findMinimumVariancePortfolio(
|
|||
returns: number[][],
|
||||
symbols: string[]
|
||||
): PortfolioOptimizationResult | null {
|
||||
if (returns.length !== symbols.length || returns.length < 2) return null;
|
||||
if (returns.length !== symbols.length || returns.length < 2) {return null;}
|
||||
|
||||
const covarianceMatrix = calculateCovarianceMatrix(returns);
|
||||
const n = returns.length;
|
||||
|
|
@ -517,7 +517,7 @@ function calculateCovarianceMatrix(returns: number[][]): number[][] {
|
|||
}
|
||||
|
||||
function calculateCovariance(x: number[], y: number[]): number {
|
||||
if (x.length !== y.length || x.length < 2) return 0;
|
||||
if (x.length !== y.length || x.length < 2) {return 0;}
|
||||
|
||||
const n = x.length;
|
||||
const meanX = x.reduce((sum, val) => sum + val, 0) / n;
|
||||
|
|
@ -559,7 +559,7 @@ function findMinimumVarianceWeights(
|
|||
const currentReturn = weights.reduce((sum, w, i) => sum + w * expectedReturns[i], 0);
|
||||
const returnDiff = targetReturn - currentReturn;
|
||||
|
||||
if (Math.abs(returnDiff) < 0.001) break;
|
||||
if (Math.abs(returnDiff) < 0.001) {break;}
|
||||
|
||||
// Adjust weights proportionally to expected returns
|
||||
const totalExpectedReturn = expectedReturns.reduce((sum, r) => sum + Math.abs(r), 0);
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ export function fixedRiskPositionSize(params: PositionSizeParams): number {
|
|||
const { accountSize, riskPercentage, entryPrice, stopLoss, leverage = 1 } = params;
|
||||
|
||||
// Input validation
|
||||
if (accountSize <= 0 || riskPercentage <= 0 || entryPrice <= 0 || leverage <= 0) return 0;
|
||||
if (entryPrice === stopLoss) return 0;
|
||||
if (accountSize <= 0 || riskPercentage <= 0 || entryPrice <= 0 || leverage <= 0) {return 0;}
|
||||
if (entryPrice === stopLoss) {return 0;}
|
||||
|
||||
const riskAmount = accountSize * (riskPercentage / 100);
|
||||
const riskPerShare = Math.abs(entryPrice - stopLoss);
|
||||
|
|
@ -48,7 +48,7 @@ export function kellyPositionSize(params: KellyParams, accountSize: number): num
|
|||
const { winRate, averageWin, averageLoss } = params;
|
||||
|
||||
// Validate inputs
|
||||
if (averageLoss === 0 || winRate <= 0 || winRate >= 1 || averageWin <= 0) return 0;
|
||||
if (averageLoss === 0 || winRate <= 0 || winRate >= 1 || averageWin <= 0) {return 0;}
|
||||
|
||||
const lossRate = 1 - winRate;
|
||||
const winLossRatio = averageWin / Math.abs(averageLoss);
|
||||
|
|
@ -72,7 +72,7 @@ export function fractionalKellyPositionSize(
|
|||
fraction: number = 0.25
|
||||
): number {
|
||||
// Input validation
|
||||
if (fraction <= 0 || fraction > 1) return 0;
|
||||
if (fraction <= 0 || fraction > 1) {return 0;}
|
||||
|
||||
const fullKelly = kellyPositionSize(params, accountSize);
|
||||
return fullKelly * fraction;
|
||||
|
|
@ -88,7 +88,7 @@ export function volatilityTargetPositionSize(
|
|||
const { price, volatility, targetVolatility } = params;
|
||||
|
||||
// Input validation
|
||||
if (volatility <= 0 || price <= 0 || targetVolatility <= 0 || accountSize <= 0) return 0;
|
||||
if (volatility <= 0 || price <= 0 || targetVolatility <= 0 || accountSize <= 0) {return 0;}
|
||||
|
||||
const volatilityRatio = targetVolatility / volatility;
|
||||
const basePositionValue = accountSize * Math.min(volatilityRatio, 2); // Cap at 2x leverage
|
||||
|
|
@ -105,7 +105,7 @@ export function equalWeightPositionSize(
|
|||
price: number
|
||||
): number {
|
||||
// Input validation
|
||||
if (numberOfPositions <= 0 || price <= 0 || accountSize <= 0) return 0;
|
||||
if (numberOfPositions <= 0 || price <= 0 || accountSize <= 0) {return 0;}
|
||||
|
||||
const positionValue = accountSize / numberOfPositions;
|
||||
return Math.floor(positionValue / price);
|
||||
|
|
@ -121,7 +121,7 @@ export function atrBasedPositionSize(
|
|||
atrMultiplier: number = 2,
|
||||
price: number
|
||||
): number {
|
||||
if (atrValue === 0 || price === 0) return 0;
|
||||
if (atrValue === 0 || price === 0) {return 0;}
|
||||
|
||||
const riskAmount = accountSize * (riskPercentage / 100);
|
||||
const stopDistance = atrValue * atrMultiplier;
|
||||
|
|
@ -143,11 +143,11 @@ export function expectancyPositionSize(
|
|||
): number {
|
||||
// Input validation
|
||||
if (accountSize <= 0 || winRate <= 0 || winRate >= 1 || averageWin <= 0 || averageLoss === 0)
|
||||
return 0;
|
||||
{return 0;}
|
||||
|
||||
const expectancy = winRate * averageWin - (1 - winRate) * Math.abs(averageLoss);
|
||||
|
||||
if (expectancy <= 0) return 0;
|
||||
if (expectancy <= 0) {return 0;}
|
||||
|
||||
// Scale position size based on expectancy relative to average loss
|
||||
// Higher expectancy relative to risk allows for larger position
|
||||
|
|
@ -167,7 +167,7 @@ export function monteCarloPositionSize(
|
|||
simulations: number = 1000,
|
||||
confidenceLevel: number = 0.95
|
||||
): number {
|
||||
if (historicalReturns.length === 0) return 0;
|
||||
if (historicalReturns.length === 0) {return 0;}
|
||||
|
||||
const outcomes: number[] = [];
|
||||
const mean = historicalReturns.reduce((sum, ret) => sum + ret, 0) / historicalReturns.length;
|
||||
|
|
@ -230,7 +230,7 @@ export function sharpeOptimizedPositionSize(
|
|||
): number {
|
||||
// Input validation
|
||||
if (volatility <= 0 || accountSize <= 0 || expectedReturn <= riskFreeRate || maxLeverage <= 0)
|
||||
return 0;
|
||||
{return 0;}
|
||||
// Kelly criterion with Sharpe ratio optimization
|
||||
const excessReturn = expectedReturn - riskFreeRate;
|
||||
const kellyFraction = excessReturn / (volatility * volatility);
|
||||
|
|
@ -251,7 +251,7 @@ export function fixedFractionalPositionSize(
|
|||
price: number
|
||||
): number {
|
||||
// Input validation
|
||||
if (stopLossPercentage <= 0 || price <= 0 || riskPercentage <= 0 || accountSize <= 0) return 0;
|
||||
if (stopLossPercentage <= 0 || price <= 0 || riskPercentage <= 0 || accountSize <= 0) {return 0;}
|
||||
|
||||
const riskAmount = accountSize * (riskPercentage / 100);
|
||||
const stopLossAmount = price * (stopLossPercentage / 100);
|
||||
|
|
@ -269,7 +269,7 @@ export function volatilityAdjustedPositionSize(
|
|||
price: number
|
||||
): number {
|
||||
// Input validation
|
||||
if (assetVolatility <= 0 || price <= 0 || targetVolatility <= 0 || accountSize <= 0) return 0;
|
||||
if (assetVolatility <= 0 || price <= 0 || targetVolatility <= 0 || accountSize <= 0) {return 0;}
|
||||
|
||||
const volatilityRatio = targetVolatility / assetVolatility;
|
||||
const cappedRatio = Math.min(volatilityRatio, 3); // Cap at 3x leverage
|
||||
|
|
@ -286,7 +286,7 @@ export function correlationAdjustedPositionSize(
|
|||
existingPositions: Array<{ size: number; correlation: number }>,
|
||||
maxCorrelationRisk: number = 0.3
|
||||
): number {
|
||||
if (existingPositions.length === 0 || basePositionSize <= 0) return basePositionSize;
|
||||
if (existingPositions.length === 0 || basePositionSize <= 0) {return basePositionSize;}
|
||||
|
||||
// Calculate portfolio correlation risk
|
||||
// This should consider the correlation between the new position and existing ones
|
||||
|
|
@ -310,7 +310,7 @@ export function calculatePortfolioHeat(
|
|||
accountSize: number
|
||||
): number {
|
||||
// Input validation
|
||||
if (accountSize <= 0 || positions.length === 0) return 0;
|
||||
if (accountSize <= 0 || positions.length === 0) {return 0;}
|
||||
|
||||
const totalRisk = positions.reduce((sum, position) => {
|
||||
// Ensure risk values are positive
|
||||
|
|
@ -331,8 +331,8 @@ export function dynamicPositionSize(
|
|||
maxDrawdownThreshold: number = 0.1
|
||||
): number {
|
||||
// Input validation
|
||||
if (basePositionSize <= 0 || marketVolatility <= 0 || normalVolatility <= 0) return 0;
|
||||
if (drawdownLevel < 0 || maxDrawdownThreshold <= 0) return basePositionSize;
|
||||
if (basePositionSize <= 0 || marketVolatility <= 0 || normalVolatility <= 0) {return 0;}
|
||||
if (drawdownLevel < 0 || maxDrawdownThreshold <= 0) {return basePositionSize;}
|
||||
|
||||
// Volatility adjustment - reduce size when volatility is high
|
||||
const volatilityAdjustment = Math.min(normalVolatility / marketVolatility, 2); // Cap at 2x
|
||||
|
|
@ -354,7 +354,7 @@ export function liquidityConstrainedPositionSize(
|
|||
maxVolumePercentage: number = 0.05,
|
||||
price: number
|
||||
): number {
|
||||
if (averageDailyVolume === 0 || price === 0) return 0;
|
||||
if (averageDailyVolume === 0 || price === 0) {return 0;}
|
||||
|
||||
const maxShares = averageDailyVolume * maxVolumePercentage;
|
||||
|
||||
|
|
@ -372,7 +372,7 @@ export function multiTimeframePositionSize(
|
|||
baseRiskPercentage: number = 1
|
||||
): number {
|
||||
// Input validation
|
||||
if (accountSize <= 0 || baseRiskPercentage <= 0) return 0;
|
||||
if (accountSize <= 0 || baseRiskPercentage <= 0) {return 0;}
|
||||
|
||||
// Clamp signals to valid range
|
||||
const clampedShort = Math.max(-1, Math.min(1, shortTermSignal));
|
||||
|
|
@ -396,18 +396,18 @@ export function riskParityPositionSize(
|
|||
targetRisk: number,
|
||||
accountSize: number
|
||||
): number[] {
|
||||
if (assets.length === 0) return [];
|
||||
if (assets.length === 0) {return [];}
|
||||
|
||||
// Calculate inverse volatility weights
|
||||
const totalInverseVol = assets.reduce((sum, asset) => {
|
||||
if (asset.volatility === 0) return sum;
|
||||
if (asset.volatility === 0) {return sum;}
|
||||
return sum + 1 / asset.volatility;
|
||||
}, 0);
|
||||
|
||||
if (totalInverseVol === 0) return assets.map(() => 0);
|
||||
if (totalInverseVol === 0) {return assets.map(() => 0);}
|
||||
|
||||
return assets.map(asset => {
|
||||
if (asset.volatility === 0 || asset.price === 0) return 0;
|
||||
if (asset.volatility === 0 || asset.price === 0) {return 0;}
|
||||
// Calculate weight based on inverse volatility
|
||||
const weight = 1 / asset.volatility / totalInverseVol;
|
||||
|
||||
|
|
@ -468,7 +468,7 @@ export function optimalFPositionSize(
|
|||
historicalReturns: number[],
|
||||
maxIterations: number = 100
|
||||
): number {
|
||||
if (historicalReturns.length === 0 || accountSize <= 0) return 0;
|
||||
if (historicalReturns.length === 0 || accountSize <= 0) {return 0;}
|
||||
|
||||
// Convert returns to P&L per unit
|
||||
const pnlValues = historicalReturns.map(ret => ret * 1000); // Assuming $1000 per unit
|
||||
|
|
@ -512,7 +512,7 @@ export function secureFPositionSize(
|
|||
historicalReturns: number[],
|
||||
confidenceLevel: number = 0.95
|
||||
): number {
|
||||
if (historicalReturns.length === 0 || accountSize <= 0) return 0;
|
||||
if (historicalReturns.length === 0 || accountSize <= 0) {return 0;}
|
||||
|
||||
// Sort returns to find worst-case scenarios
|
||||
const sortedReturns = [...historicalReturns].sort((a, b) => a - b);
|
||||
|
|
@ -523,7 +523,7 @@ export function secureFPositionSize(
|
|||
const maxLoss = Math.abs(worstCaseReturn);
|
||||
const maxRiskPercentage = 0.02; // Never risk more than 2% on worst case
|
||||
|
||||
if (maxLoss === 0) return accountSize * 0.1; // Default to 10% if no historical losses
|
||||
if (maxLoss === 0) {return accountSize * 0.1;} // Default to 10% if no historical losses
|
||||
|
||||
const secureF = Math.min(maxRiskPercentage / maxLoss, 0.25); // Cap at 25%
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { RiskMetrics, treynorRatio } from './index';
|
|||
* Calculate Value at Risk (VaR) using historical simulation
|
||||
*/
|
||||
export function valueAtRisk(returns: number[], confidenceLevel: number = 0.95): number {
|
||||
if (returns.length === 0) return 0;
|
||||
if (returns.length === 0) {return 0;}
|
||||
|
||||
const sortedReturns = [...returns].sort((a, b) => a - b);
|
||||
const index = Math.floor((1 - confidenceLevel) * sortedReturns.length);
|
||||
|
|
@ -21,12 +21,12 @@ export function valueAtRisk(returns: number[], confidenceLevel: number = 0.95):
|
|||
* Calculate Conditional Value at Risk (CVaR/Expected Shortfall)
|
||||
*/
|
||||
export function conditionalValueAtRisk(returns: number[], confidenceLevel: number = 0.95): number {
|
||||
if (returns.length === 0) return 0;
|
||||
if (returns.length === 0) {return 0;}
|
||||
|
||||
const sortedReturns = [...returns].sort((a, b) => a - b);
|
||||
const cutoffIndex = Math.floor((1 - confidenceLevel) * sortedReturns.length);
|
||||
|
||||
if (cutoffIndex === 0) return sortedReturns[0];
|
||||
if (cutoffIndex === 0) {return sortedReturns[0];}
|
||||
|
||||
const tailReturns = sortedReturns.slice(0, cutoffIndex);
|
||||
return tailReturns.reduce((sum, ret) => sum + ret, 0) / tailReturns.length;
|
||||
|
|
@ -40,7 +40,7 @@ export function parametricVaR(
|
|||
confidenceLevel: number = 0.95,
|
||||
portfolioValue: number = 1
|
||||
): number {
|
||||
if (returns.length === 0) return 0;
|
||||
if (returns.length === 0) {return 0;}
|
||||
|
||||
const mean = returns.reduce((sum, ret) => sum + ret, 0) / returns.length;
|
||||
const variance =
|
||||
|
|
@ -57,7 +57,7 @@ export function parametricVaR(
|
|||
* Calculate maximum drawdown
|
||||
*/
|
||||
export function maxDrawdown(equityCurve: number[]): number {
|
||||
if (equityCurve.length < 2) return 0;
|
||||
if (equityCurve.length < 2) {return 0;}
|
||||
|
||||
let maxDD = 0;
|
||||
let peak = equityCurve[0];
|
||||
|
|
@ -78,11 +78,11 @@ export function maxDrawdown(equityCurve: number[]): number {
|
|||
* Calculate downside deviation
|
||||
*/
|
||||
export function downsideDeviation(returns: number[], targetReturn: number = 0): number {
|
||||
if (returns.length === 0) return 0;
|
||||
if (returns.length === 0) {return 0;}
|
||||
|
||||
const downsideReturns = returns.filter(ret => ret < targetReturn);
|
||||
|
||||
if (downsideReturns.length === 0) return 0;
|
||||
if (downsideReturns.length === 0) {return 0;}
|
||||
|
||||
const sumSquaredDownside = downsideReturns.reduce(
|
||||
(sum, ret) => sum + Math.pow(ret - targetReturn, 2),
|
||||
|
|
@ -96,14 +96,14 @@ export function downsideDeviation(returns: number[], targetReturn: number = 0):
|
|||
* Calculate Sharpe ratio
|
||||
*/
|
||||
export function sharpeRatio(returns: number[], riskFreeRate: number = 0): number {
|
||||
if (returns.length < 2) return 0;
|
||||
if (returns.length < 2) {return 0;}
|
||||
|
||||
const mean = returns.reduce((sum, ret) => sum + ret, 0) / returns.length;
|
||||
const variance =
|
||||
returns.reduce((sum, ret) => sum + Math.pow(ret - mean, 2), 0) / (returns.length - 1);
|
||||
const stdDev = Math.sqrt(variance);
|
||||
|
||||
if (stdDev === 0) return 0;
|
||||
if (stdDev === 0) {return 0;}
|
||||
|
||||
return (mean - riskFreeRate) / stdDev;
|
||||
}
|
||||
|
|
@ -172,7 +172,7 @@ export function trackingError(portfolioReturns: number[], benchmarkReturns: numb
|
|||
* Calculate volatility (standard deviation of returns)
|
||||
*/
|
||||
export function volatility(returns: number[]): number {
|
||||
if (returns.length < 2) return 0;
|
||||
if (returns.length < 2) {return 0;}
|
||||
|
||||
const mean = returns.reduce((sum, ret) => sum + ret, 0) / returns.length;
|
||||
const variance =
|
||||
|
|
@ -192,13 +192,13 @@ export function annualizedVolatility(returns: number[], periodsPerYear: number =
|
|||
* Calculate skewness (measure of asymmetry)
|
||||
*/
|
||||
export function skewness(returns: number[]): number {
|
||||
if (returns.length < 3) return 0;
|
||||
if (returns.length < 3) {return 0;}
|
||||
|
||||
const mean = returns.reduce((sum, ret) => sum + ret, 0) / returns.length;
|
||||
const variance = returns.reduce((sum, ret) => sum + Math.pow(ret - mean, 2), 0) / returns.length;
|
||||
const stdDev = Math.sqrt(variance);
|
||||
|
||||
if (stdDev === 0) return 0;
|
||||
if (stdDev === 0) {return 0;}
|
||||
|
||||
const skew =
|
||||
returns.reduce((sum, ret) => sum + Math.pow((ret - mean) / stdDev, 3), 0) / returns.length;
|
||||
|
|
@ -210,13 +210,13 @@ export function skewness(returns: number[]): number {
|
|||
* Calculate kurtosis (measure of tail heaviness)
|
||||
*/
|
||||
export function kurtosis(returns: number[]): number {
|
||||
if (returns.length < 4) return 0;
|
||||
if (returns.length < 4) {return 0;}
|
||||
|
||||
const mean = returns.reduce((sum, ret) => sum + ret, 0) / returns.length;
|
||||
const variance = returns.reduce((sum, ret) => sum + Math.pow(ret - mean, 2), 0) / returns.length;
|
||||
const stdDev = Math.sqrt(variance);
|
||||
|
||||
if (stdDev === 0) return 0;
|
||||
if (stdDev === 0) {return 0;}
|
||||
|
||||
const kurt =
|
||||
returns.reduce((sum, ret) => sum + Math.pow((ret - mean) / stdDev, 4), 0) / returns.length;
|
||||
|
|
@ -317,12 +317,12 @@ function getZScore(confidenceLevel: number): number {
|
|||
};
|
||||
|
||||
const key = confidenceLevel.toString();
|
||||
if (zScores[key]) return zScores[key];
|
||||
if (zScores[key]) {return zScores[key];}
|
||||
|
||||
// For arbitrary confidence levels, use approximation
|
||||
if (confidenceLevel < 0.5) return -getZScore(1 - confidenceLevel);
|
||||
if (confidenceLevel < 0.5) {return -getZScore(1 - confidenceLevel);}
|
||||
|
||||
if (confidenceLevel >= 0.999) return 3.09; // Cap at 99.9% for numerical stability
|
||||
if (confidenceLevel >= 0.999) {return 3.09;} // Cap at 99.9% for numerical stability
|
||||
|
||||
// Approximation of inverse normal CDF
|
||||
const y = Math.sqrt(-2.0 * Math.log(1.0 - confidenceLevel));
|
||||
|
|
@ -382,6 +382,6 @@ export function riskAdjustedReturn(
|
|||
portfolioRisk: number,
|
||||
riskFreeRate: number = 0
|
||||
): number {
|
||||
if (portfolioRisk === 0) return 0;
|
||||
if (portfolioRisk === 0) {return 0;}
|
||||
return (portfolioReturn - riskFreeRate) / portfolioRisk;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { OHLCVData } from './index';
|
|||
* Simple Moving Average
|
||||
*/
|
||||
export function sma(values: number[], period: number): number[] {
|
||||
if (period > values.length) return [];
|
||||
if (period > values.length) {return [];}
|
||||
|
||||
const result: number[] = [];
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ export function sma(values: number[], period: number): number[] {
|
|||
* Exponential Moving Average
|
||||
*/
|
||||
export function ema(values: number[], period: number): number[] {
|
||||
if (period > values.length) return [];
|
||||
if (period > values.length) {return [];}
|
||||
|
||||
const result: number[] = [];
|
||||
const multiplier = 2 / (period + 1);
|
||||
|
|
@ -46,7 +46,7 @@ export function ema(values: number[], period: number): number[] {
|
|||
* Relative Strength Index (RSI)
|
||||
*/
|
||||
export function rsi(prices: number[], period: number = 14): number[] {
|
||||
if (period >= prices.length) return [];
|
||||
if (period >= prices.length) {return [];}
|
||||
|
||||
const gains: number[] = [];
|
||||
const losses: number[] = [];
|
||||
|
|
@ -141,7 +141,7 @@ export function bollingerBands(
|
|||
* Average True Range (ATR)
|
||||
*/
|
||||
export function atr(ohlcv: OHLCVData[], period: number = 14): number[] {
|
||||
if (period >= ohlcv.length) return [];
|
||||
if (period >= ohlcv.length) {return [];}
|
||||
|
||||
const trueRanges: number[] = [];
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ export function stochastic(
|
|||
kPeriod: number = 14,
|
||||
dPeriod: number = 3
|
||||
): { k: number[]; d: number[] } {
|
||||
if (kPeriod >= ohlcv.length) return { k: [], d: [] };
|
||||
if (kPeriod >= ohlcv.length) {return { k: [], d: [] };}
|
||||
|
||||
const kValues: number[] = [];
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ export function stochastic(
|
|||
* Williams %R
|
||||
*/
|
||||
export function williamsR(ohlcv: OHLCVData[], period: number = 14): number[] {
|
||||
if (period >= ohlcv.length) return [];
|
||||
if (period >= ohlcv.length) {return [];}
|
||||
|
||||
const result: number[] = [];
|
||||
|
||||
|
|
@ -218,7 +218,7 @@ export function williamsR(ohlcv: OHLCVData[], period: number = 14): number[] {
|
|||
* Commodity Channel Index (CCI)
|
||||
*/
|
||||
export function cci(ohlcv: OHLCVData[], period: number = 20): number[] {
|
||||
if (period >= ohlcv.length) return [];
|
||||
if (period >= ohlcv.length) {return [];}
|
||||
|
||||
const typicalPrices = ohlcv.map(d => (d.high + d.low + d.close) / 3);
|
||||
const smaTP = sma(typicalPrices, period);
|
||||
|
|
@ -244,7 +244,7 @@ export function cci(ohlcv: OHLCVData[], period: number = 20): number[] {
|
|||
* Momentum
|
||||
*/
|
||||
export function momentum(prices: number[], period: number = 10): number[] {
|
||||
if (period >= prices.length) return [];
|
||||
if (period >= prices.length) {return [];}
|
||||
|
||||
const result: number[] = [];
|
||||
|
||||
|
|
@ -260,7 +260,7 @@ export function momentum(prices: number[], period: number = 10): number[] {
|
|||
* Rate of Change (ROC)
|
||||
*/
|
||||
export function roc(prices: number[], period: number = 10): number[] {
|
||||
if (period >= prices.length) return [];
|
||||
if (period >= prices.length) {return [];}
|
||||
|
||||
const result: number[] = [];
|
||||
|
||||
|
|
@ -280,7 +280,7 @@ export function roc(prices: number[], period: number = 10): number[] {
|
|||
* Money Flow Index (MFI)
|
||||
*/
|
||||
export function mfi(ohlcv: OHLCVData[], period: number = 14): number[] {
|
||||
if (period >= ohlcv.length) return [];
|
||||
if (period >= ohlcv.length) {return [];}
|
||||
|
||||
const typicalPrices = ohlcv.map(d => (d.high + d.low + d.close) / 3);
|
||||
const moneyFlows = ohlcv.map((d, i) => typicalPrices[i] * d.volume);
|
||||
|
|
@ -317,7 +317,7 @@ export function mfi(ohlcv: OHLCVData[], period: number = 14): number[] {
|
|||
* On-Balance Volume (OBV)
|
||||
*/
|
||||
export function obv(ohlcv: OHLCVData[]): number[] {
|
||||
if (ohlcv.length === 0) return [];
|
||||
if (ohlcv.length === 0) {return [];}
|
||||
|
||||
const result: number[] = [ohlcv[0].volume];
|
||||
|
||||
|
|
@ -341,7 +341,7 @@ export function obv(ohlcv: OHLCVData[]): number[] {
|
|||
* Accumulation/Distribution Line
|
||||
*/
|
||||
export function accumulationDistribution(ohlcv: OHLCVData[]): number[] {
|
||||
if (ohlcv.length === 0) return [];
|
||||
if (ohlcv.length === 0) {return [];}
|
||||
|
||||
const result: number[] = [];
|
||||
let adLine = 0;
|
||||
|
|
@ -367,7 +367,7 @@ export function accumulationDistribution(ohlcv: OHLCVData[]): number[] {
|
|||
* Chaikin Money Flow (CMF)
|
||||
*/
|
||||
export function chaikinMoneyFlow(ohlcv: OHLCVData[], period: number = 20): number[] {
|
||||
if (period >= ohlcv.length) return [];
|
||||
if (period >= ohlcv.length) {return [];}
|
||||
|
||||
const adValues: number[] = [];
|
||||
|
||||
|
|
@ -406,7 +406,7 @@ export function parabolicSAR(
|
|||
step: number = 0.02,
|
||||
maxStep: number = 0.2
|
||||
): number[] {
|
||||
if (ohlcv.length < 2) return [];
|
||||
if (ohlcv.length < 2) {return [];}
|
||||
|
||||
const result: number[] = [];
|
||||
let trend = 1; // 1 for uptrend, -1 for downtrend
|
||||
|
|
@ -467,7 +467,7 @@ export function parabolicSAR(
|
|||
* Aroon Indicator
|
||||
*/
|
||||
export function aroon(ohlcv: OHLCVData[], period: number = 14): { up: number[]; down: number[] } {
|
||||
if (period >= ohlcv.length) return { up: [], down: [] };
|
||||
if (period >= ohlcv.length) {return { up: [], down: [] };}
|
||||
|
||||
const up: number[] = [];
|
||||
const down: number[] = [];
|
||||
|
|
@ -505,7 +505,7 @@ export function adx(
|
|||
ohlcv: OHLCVData[],
|
||||
period: number = 14
|
||||
): { adx: number[]; plusDI: number[]; minusDI: number[] } {
|
||||
if (period >= ohlcv.length) return { adx: [], plusDI: [], minusDI: [] };
|
||||
if (period >= ohlcv.length) {return { adx: [], plusDI: [], minusDI: [] };}
|
||||
|
||||
const trueRanges: number[] = [];
|
||||
const plusDM: number[] = [];
|
||||
|
|
@ -572,7 +572,7 @@ export function adx(
|
|||
* Volume Weighted Moving Average (VWMA)
|
||||
*/
|
||||
export function vwma(ohlcv: OHLCVData[], period: number = 20): number[] {
|
||||
if (period >= ohlcv.length) return [];
|
||||
if (period >= ohlcv.length) {return [];}
|
||||
|
||||
const result: number[] = [];
|
||||
|
||||
|
|
@ -607,7 +607,7 @@ export function pivotPoints(ohlcv: OHLCVData[]): Array<{
|
|||
support2: number;
|
||||
support3: number;
|
||||
}> {
|
||||
if (ohlcv.length === 0) return [];
|
||||
if (ohlcv.length === 0) {return [];}
|
||||
|
||||
const result: Array<{
|
||||
pivot: number;
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ export function identifyVolatilityRegimes(
|
|||
// Classify returns into regimes
|
||||
const regimeSequence = absReturns.map(absRet => {
|
||||
for (let i = 0; i < thresholds.length; i++) {
|
||||
if (absRet <= thresholds[i]) return i;
|
||||
if (absRet <= thresholds[i]) {return i;}
|
||||
}
|
||||
return numRegimes - 1;
|
||||
});
|
||||
|
|
@ -537,7 +537,7 @@ export function calculateYangZhangVolatility(
|
|||
* Parkinson volatility estimator
|
||||
*/
|
||||
export function parkinsonVolatility(ohlcv: OHLCVData[], annualizationFactor: number = 252): number {
|
||||
if (ohlcv.length < 2) return 0;
|
||||
if (ohlcv.length < 2) {return 0;}
|
||||
const sum = ohlcv.slice(1).reduce((acc, curr) => {
|
||||
const range = Math.log(curr.high / curr.low);
|
||||
return acc + range * range;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [
|
||||
{ "path": "../types" },
|
||||
{ "path": "../config" },
|
||||
{ "path": "../logger" }
|
||||
]
|
||||
}
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [{ "path": "../types" }, { "path": "../config" }, { "path": "../logger" }]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,34 +1,34 @@
|
|||
{
|
||||
"name": "@stock-bot/vector-engine",
|
||||
"version": "1.0.0",
|
||||
"description": "Vectorized computation engine for high-performance backtesting",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/logger": "*",
|
||||
"@stock-bot/utils": "*",
|
||||
"@stock-bot/data-frame": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
{
|
||||
"name": "@stock-bot/vector-engine",
|
||||
"version": "1.0.0",
|
||||
"description": "Vectorized computation engine for high-performance backtesting",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "bun test",
|
||||
"clean": "rimraf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stock-bot/logger": "*",
|
||||
"@stock-bot/utils": "*",
|
||||
"@stock-bot/data-frame": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"typescript": "^5.3.0",
|
||||
"bun-types": "^1.2.15"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"README.md"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -326,7 +326,7 @@ export class VectorEngine {
|
|||
let peak = equity[0];
|
||||
|
||||
for (const eq of equity) {
|
||||
if (eq > peak) peak = eq;
|
||||
if (eq > peak) {peak = eq;}
|
||||
drawdown.push((peak - eq) / peak);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [
|
||||
{ "path": "../types" },
|
||||
{ "path": "../logger" },
|
||||
{ "path": "../utils" },
|
||||
{ "path": "../data-frame" }
|
||||
]
|
||||
}
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"references": [
|
||||
{ "path": "../types" },
|
||||
{ "path": "../logger" },
|
||||
{ "path": "../utils" },
|
||||
{ "path": "../data-frame" }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
13
package.json
13
package.json
|
|
@ -18,7 +18,11 @@
|
|||
"test:e2e": "bun test test/e2e",
|
||||
"test:libs": "turbo run test --filter='./libs/*'",
|
||||
"test:apps": "turbo run test --filter=./apps/*/*",
|
||||
"lint": "turbo run lint",
|
||||
"lint": "eslint apps libs --ext .ts,.tsx",
|
||||
"lint:fix": "eslint apps libs --ext .ts,.tsx --fix",
|
||||
"lint:check": "eslint apps libs --ext .ts,.tsx --max-warnings 0",
|
||||
"lint:apps": "eslint apps --ext .ts,.tsx",
|
||||
"lint:libs": "eslint libs --ext .ts,.tsx",
|
||||
"format": "./scripts/format.sh",
|
||||
"format:check": "prettier --check 'apps/**/*.{ts,json}' 'libs/**/*.{ts,json}' '*.json'",
|
||||
"format:ts": "prettier --write 'apps/**/*.ts' 'libs/**/*.ts'",
|
||||
|
|
@ -53,6 +57,7 @@
|
|||
"apps/*"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.28.0",
|
||||
"@ianvs/prettier-plugin-sort-imports": "^4.4.2",
|
||||
"@testcontainers/mongodb": "^10.7.2",
|
||||
"@testcontainers/postgresql": "^10.7.2",
|
||||
|
|
@ -60,7 +65,13 @@
|
|||
"@types/node": "^22.15.30",
|
||||
"@types/supertest": "^6.0.2",
|
||||
"@types/yup": "^0.32.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.34.0",
|
||||
"@typescript-eslint/parser": "^8.34.0",
|
||||
"bun-types": "^1.2.15",
|
||||
"eslint": "^9.28.0",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^7.2.1",
|
||||
"mongodb-memory-server": "^9.1.6",
|
||||
"pg-mem": "^2.8.1",
|
||||
"prettier": "^3.5.3",
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"types": ["bun-types"]
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"types": ["bun-types"]
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
|
|
|
|||
139
tsconfig.json
139
tsconfig.json
|
|
@ -1,71 +1,68 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
// JavaScript output target version
|
||||
"target": "ES2022",
|
||||
// Module configuration for different project types
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"composite": true,
|
||||
|
||||
// Type checking
|
||||
"strict": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"noImplicitThis": true,
|
||||
"alwaysStrict": true,
|
||||
"declarationMap": true,
|
||||
|
||||
// Module interoperability
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
|
||||
// Additional features
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"sourceMap": false,
|
||||
"declaration": true,
|
||||
"disableReferencedProjectLoad": true,
|
||||
"disableSourceOfProjectReferenceRedirect": false,
|
||||
|
||||
// Paths and output
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@stock-bot/*": ["libs/*/src"]
|
||||
}
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist"
|
||||
],
|
||||
"references": [
|
||||
// Core libraries first
|
||||
{ "path": "./libs/types" },
|
||||
{ "path": "./libs/config" },
|
||||
{ "path": "./libs/logger" },
|
||||
{ "path": "./libs/utils" },
|
||||
|
||||
// Database clients
|
||||
{ "path": "./libs/postgres-client" },
|
||||
{ "path": "./libs/mongodb-client" },
|
||||
{ "path": "./libs/questdb-client" },
|
||||
|
||||
// Service libraries
|
||||
{ "path": "./libs/cache" },
|
||||
{ "path": "./libs/http" },
|
||||
{ "path": "./libs/event-bus" },
|
||||
{ "path": "./libs/shutdown" },
|
||||
// Engine libraries
|
||||
{ "path": "./libs/data-frame" },
|
||||
{ "path": "./libs/vector-engine" },
|
||||
{ "path": "./libs/strategy-engine" },
|
||||
|
||||
// Applications
|
||||
{ "path": "./apps/data-service" },
|
||||
{ "path": "./apps/execution-service" },
|
||||
{ "path": "./apps/portfolio-service" },
|
||||
{ "path": "./apps/processing-service" },
|
||||
{ "path": "./apps/strategy-service" }
|
||||
]
|
||||
}
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
// JavaScript output target version
|
||||
"target": "ES2022",
|
||||
// Module configuration for different project types
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"composite": true,
|
||||
|
||||
// Type checking
|
||||
"strict": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true,
|
||||
"noImplicitThis": true,
|
||||
"alwaysStrict": true,
|
||||
"declarationMap": true,
|
||||
|
||||
// Module interoperability
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
|
||||
// Additional features
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"sourceMap": false,
|
||||
"declaration": true,
|
||||
"disableReferencedProjectLoad": true,
|
||||
"disableSourceOfProjectReferenceRedirect": false,
|
||||
|
||||
// Paths and output
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@stock-bot/*": ["libs/*/src"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "dist"],
|
||||
"references": [
|
||||
// Core libraries first
|
||||
{ "path": "./libs/types" },
|
||||
{ "path": "./libs/config" },
|
||||
{ "path": "./libs/logger" },
|
||||
{ "path": "./libs/utils" },
|
||||
|
||||
// Database clients
|
||||
{ "path": "./libs/postgres-client" },
|
||||
{ "path": "./libs/mongodb-client" },
|
||||
{ "path": "./libs/questdb-client" },
|
||||
|
||||
// Service libraries
|
||||
{ "path": "./libs/cache" },
|
||||
{ "path": "./libs/http" },
|
||||
{ "path": "./libs/event-bus" },
|
||||
{ "path": "./libs/shutdown" },
|
||||
// Engine libraries
|
||||
{ "path": "./libs/data-frame" },
|
||||
{ "path": "./libs/vector-engine" },
|
||||
{ "path": "./libs/strategy-engine" },
|
||||
|
||||
// Applications
|
||||
{ "path": "./apps/data-service" },
|
||||
{ "path": "./apps/execution-service" },
|
||||
{ "path": "./apps/portfolio-service" },
|
||||
{ "path": "./apps/processing-service" },
|
||||
{ "path": "./apps/strategy-service" }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"declaration": true,
|
||||
"composite": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
|
||||
}
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"declaration": true,
|
||||
"composite": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
|
||||
}
|
||||
|
|
|
|||
11
turbo.json
11
turbo.json
|
|
@ -22,7 +22,16 @@
|
|||
"dependsOn": ["build"],
|
||||
"outputs": []
|
||||
}, "lint": {
|
||||
"dependsOn": ["^lint"]
|
||||
"dependsOn": [],
|
||||
"outputs": []
|
||||
},
|
||||
"lint:fix": {
|
||||
"dependsOn": [],
|
||||
"outputs": []
|
||||
},
|
||||
"lint:check": {
|
||||
"dependsOn": [],
|
||||
"outputs": []
|
||||
},
|
||||
"format": {
|
||||
"dependsOn": [],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue