linting
This commit is contained in:
parent
9d38f9a7b6
commit
eeae192872
26 changed files with 532 additions and 186 deletions
|
|
@ -82,11 +82,17 @@ 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,12 @@ 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,9 @@ 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,9 @@ 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,45 @@ 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,9 @@ 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,9 @@ 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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -172,8 +172,12 @@ 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 +404,9 @@ 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(':');
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@
|
|||
"@stock-bot/shutdown#build"
|
||||
],
|
||||
"outputs": ["dist/**"],
|
||||
"inputs": ["src/**", "package.json", "tsconfig.json", "!**/*.test.ts", "!**/*.spec.ts", "!**/test/**", "!**/tests/**", "!**/__tests__/**"]
|
||||
"inputs": ["src/**",
|
||||
"package.json",
|
||||
"tsconfig.json", "!**/*.test.ts", "!**/*.spec.ts", "!**/test/**", "!**/tests/**", "!**/__tests__/**"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,9 @@ export class PerformanceAnalyzer {
|
|||
}
|
||||
|
||||
private calculateReturns(_period: 'daily' | 'weekly' | 'monthly'): number[] {
|
||||
if (this.snapshots.length < 2) {return [];}
|
||||
if (this.snapshots.length < 2) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const returns: number[] = [];
|
||||
|
||||
|
|
@ -83,7 +85,9 @@ 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 +96,18 @@ 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 +117,25 @@ 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 +153,9 @@ 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 +173,9 @@ 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 +184,22 @@ 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 +211,9 @@ 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 +222,17 @@ 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
|
||||
|
|
|
|||
|
|
@ -172,7 +172,9 @@ 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 =>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue