linxus fs fixes
This commit is contained in:
parent
ac23b70146
commit
0b7846fe67
292 changed files with 41947 additions and 41947 deletions
|
|
@ -1,159 +1,159 @@
|
|||
import { Component, signal, OnInit, OnDestroy, inject } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatSnackBarModule, MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { ApiService } from '../../services/api.service';
|
||||
import { interval, Subscription } from 'rxjs';
|
||||
|
||||
export interface Position {
|
||||
symbol: string;
|
||||
quantity: number;
|
||||
avgPrice: number;
|
||||
currentPrice: number;
|
||||
marketValue: number;
|
||||
unrealizedPnL: number;
|
||||
unrealizedPnLPercent: number;
|
||||
dayChange: number;
|
||||
dayChangePercent: number;
|
||||
}
|
||||
|
||||
export interface PortfolioSummary {
|
||||
totalValue: number;
|
||||
totalCost: number;
|
||||
totalPnL: number;
|
||||
totalPnLPercent: number;
|
||||
dayChange: number;
|
||||
dayChangePercent: number;
|
||||
cash: number;
|
||||
positionsCount: number;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-portfolio',
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatCardModule,
|
||||
MatIconModule,
|
||||
MatButtonModule,
|
||||
MatTableModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatSnackBarModule,
|
||||
MatTabsModule
|
||||
],
|
||||
templateUrl: './portfolio.component.html',
|
||||
styleUrl: './portfolio.component.css'
|
||||
})
|
||||
export class PortfolioComponent implements OnInit, OnDestroy {
|
||||
private apiService = inject(ApiService);
|
||||
private snackBar = inject(MatSnackBar);
|
||||
private subscriptions: Subscription[] = [];
|
||||
|
||||
protected portfolioSummary = signal<PortfolioSummary>({
|
||||
totalValue: 0,
|
||||
totalCost: 0,
|
||||
totalPnL: 0,
|
||||
totalPnLPercent: 0,
|
||||
dayChange: 0,
|
||||
dayChangePercent: 0,
|
||||
cash: 0,
|
||||
positionsCount: 0
|
||||
});
|
||||
|
||||
protected positions = signal<Position[]>([]);
|
||||
protected isLoading = signal<boolean>(true);
|
||||
protected error = signal<string | null>(null);
|
||||
protected displayedColumns = ['symbol', 'quantity', 'avgPrice', 'currentPrice', 'marketValue', 'unrealizedPnL', 'dayChange'];
|
||||
|
||||
ngOnInit() {
|
||||
this.loadPortfolioData();
|
||||
|
||||
// Refresh portfolio data every 30 seconds
|
||||
const portfolioSubscription = interval(30000).subscribe(() => {
|
||||
this.loadPortfolioData();
|
||||
});
|
||||
this.subscriptions.push(portfolioSubscription);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscriptions.forEach(sub => sub.unsubscribe());
|
||||
}
|
||||
|
||||
private loadPortfolioData() {
|
||||
// Since we don't have a portfolio endpoint yet, let's create mock data
|
||||
// In a real implementation, this would call this.apiService.getPortfolio()
|
||||
|
||||
setTimeout(() => {
|
||||
const mockPositions: Position[] = [
|
||||
{
|
||||
symbol: 'AAPL',
|
||||
quantity: 100,
|
||||
avgPrice: 180.50,
|
||||
currentPrice: 192.53,
|
||||
marketValue: 19253,
|
||||
unrealizedPnL: 1203,
|
||||
unrealizedPnLPercent: 6.67,
|
||||
dayChange: 241,
|
||||
dayChangePercent: 1.27
|
||||
},
|
||||
{
|
||||
symbol: 'MSFT',
|
||||
quantity: 50,
|
||||
avgPrice: 400.00,
|
||||
currentPrice: 415.26,
|
||||
marketValue: 20763,
|
||||
unrealizedPnL: 763,
|
||||
unrealizedPnLPercent: 3.82,
|
||||
dayChange: 436.50,
|
||||
dayChangePercent: 2.15
|
||||
},
|
||||
{
|
||||
symbol: 'GOOGL',
|
||||
quantity: 10,
|
||||
avgPrice: 2900.00,
|
||||
currentPrice: 2847.56,
|
||||
marketValue: 28475.60,
|
||||
unrealizedPnL: -524.40,
|
||||
unrealizedPnLPercent: -1.81,
|
||||
dayChange: -123.40,
|
||||
dayChangePercent: -0.43
|
||||
}
|
||||
];
|
||||
|
||||
const summary: PortfolioSummary = {
|
||||
totalValue: mockPositions.reduce((sum, pos) => sum + pos.marketValue, 0) + 25000, // + cash
|
||||
totalCost: mockPositions.reduce((sum, pos) => sum + (pos.avgPrice * pos.quantity), 0),
|
||||
totalPnL: mockPositions.reduce((sum, pos) => sum + pos.unrealizedPnL, 0),
|
||||
totalPnLPercent: 0,
|
||||
dayChange: mockPositions.reduce((sum, pos) => sum + pos.dayChange, 0),
|
||||
dayChangePercent: 0,
|
||||
cash: 25000,
|
||||
positionsCount: mockPositions.length
|
||||
};
|
||||
|
||||
summary.totalPnLPercent = (summary.totalPnL / summary.totalCost) * 100;
|
||||
summary.dayChangePercent = (summary.dayChange / (summary.totalValue - summary.dayChange)) * 100;
|
||||
|
||||
this.positions.set(mockPositions);
|
||||
this.portfolioSummary.set(summary);
|
||||
this.isLoading.set(false);
|
||||
this.error.set(null);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
refreshData() {
|
||||
this.isLoading.set(true);
|
||||
this.loadPortfolioData();
|
||||
}
|
||||
|
||||
getPnLColor(value: number): string {
|
||||
if (value > 0) return 'text-green-600';
|
||||
if (value < 0) return 'text-red-600';
|
||||
return 'text-gray-600';
|
||||
}
|
||||
}
|
||||
import { Component, signal, OnInit, OnDestroy, inject } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatSnackBarModule, MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { ApiService } from '../../services/api.service';
|
||||
import { interval, Subscription } from 'rxjs';
|
||||
|
||||
export interface Position {
|
||||
symbol: string;
|
||||
quantity: number;
|
||||
avgPrice: number;
|
||||
currentPrice: number;
|
||||
marketValue: number;
|
||||
unrealizedPnL: number;
|
||||
unrealizedPnLPercent: number;
|
||||
dayChange: number;
|
||||
dayChangePercent: number;
|
||||
}
|
||||
|
||||
export interface PortfolioSummary {
|
||||
totalValue: number;
|
||||
totalCost: number;
|
||||
totalPnL: number;
|
||||
totalPnLPercent: number;
|
||||
dayChange: number;
|
||||
dayChangePercent: number;
|
||||
cash: number;
|
||||
positionsCount: number;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-portfolio',
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatCardModule,
|
||||
MatIconModule,
|
||||
MatButtonModule,
|
||||
MatTableModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatSnackBarModule,
|
||||
MatTabsModule
|
||||
],
|
||||
templateUrl: './portfolio.component.html',
|
||||
styleUrl: './portfolio.component.css'
|
||||
})
|
||||
export class PortfolioComponent implements OnInit, OnDestroy {
|
||||
private apiService = inject(ApiService);
|
||||
private snackBar = inject(MatSnackBar);
|
||||
private subscriptions: Subscription[] = [];
|
||||
|
||||
protected portfolioSummary = signal<PortfolioSummary>({
|
||||
totalValue: 0,
|
||||
totalCost: 0,
|
||||
totalPnL: 0,
|
||||
totalPnLPercent: 0,
|
||||
dayChange: 0,
|
||||
dayChangePercent: 0,
|
||||
cash: 0,
|
||||
positionsCount: 0
|
||||
});
|
||||
|
||||
protected positions = signal<Position[]>([]);
|
||||
protected isLoading = signal<boolean>(true);
|
||||
protected error = signal<string | null>(null);
|
||||
protected displayedColumns = ['symbol', 'quantity', 'avgPrice', 'currentPrice', 'marketValue', 'unrealizedPnL', 'dayChange'];
|
||||
|
||||
ngOnInit() {
|
||||
this.loadPortfolioData();
|
||||
|
||||
// Refresh portfolio data every 30 seconds
|
||||
const portfolioSubscription = interval(30000).subscribe(() => {
|
||||
this.loadPortfolioData();
|
||||
});
|
||||
this.subscriptions.push(portfolioSubscription);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscriptions.forEach(sub => sub.unsubscribe());
|
||||
}
|
||||
|
||||
private loadPortfolioData() {
|
||||
// Since we don't have a portfolio endpoint yet, let's create mock data
|
||||
// In a real implementation, this would call this.apiService.getPortfolio()
|
||||
|
||||
setTimeout(() => {
|
||||
const mockPositions: Position[] = [
|
||||
{
|
||||
symbol: 'AAPL',
|
||||
quantity: 100,
|
||||
avgPrice: 180.50,
|
||||
currentPrice: 192.53,
|
||||
marketValue: 19253,
|
||||
unrealizedPnL: 1203,
|
||||
unrealizedPnLPercent: 6.67,
|
||||
dayChange: 241,
|
||||
dayChangePercent: 1.27
|
||||
},
|
||||
{
|
||||
symbol: 'MSFT',
|
||||
quantity: 50,
|
||||
avgPrice: 400.00,
|
||||
currentPrice: 415.26,
|
||||
marketValue: 20763,
|
||||
unrealizedPnL: 763,
|
||||
unrealizedPnLPercent: 3.82,
|
||||
dayChange: 436.50,
|
||||
dayChangePercent: 2.15
|
||||
},
|
||||
{
|
||||
symbol: 'GOOGL',
|
||||
quantity: 10,
|
||||
avgPrice: 2900.00,
|
||||
currentPrice: 2847.56,
|
||||
marketValue: 28475.60,
|
||||
unrealizedPnL: -524.40,
|
||||
unrealizedPnLPercent: -1.81,
|
||||
dayChange: -123.40,
|
||||
dayChangePercent: -0.43
|
||||
}
|
||||
];
|
||||
|
||||
const summary: PortfolioSummary = {
|
||||
totalValue: mockPositions.reduce((sum, pos) => sum + pos.marketValue, 0) + 25000, // + cash
|
||||
totalCost: mockPositions.reduce((sum, pos) => sum + (pos.avgPrice * pos.quantity), 0),
|
||||
totalPnL: mockPositions.reduce((sum, pos) => sum + pos.unrealizedPnL, 0),
|
||||
totalPnLPercent: 0,
|
||||
dayChange: mockPositions.reduce((sum, pos) => sum + pos.dayChange, 0),
|
||||
dayChangePercent: 0,
|
||||
cash: 25000,
|
||||
positionsCount: mockPositions.length
|
||||
};
|
||||
|
||||
summary.totalPnLPercent = (summary.totalPnL / summary.totalCost) * 100;
|
||||
summary.dayChangePercent = (summary.dayChange / (summary.totalValue - summary.dayChange)) * 100;
|
||||
|
||||
this.positions.set(mockPositions);
|
||||
this.portfolioSummary.set(summary);
|
||||
this.isLoading.set(false);
|
||||
this.error.set(null);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
refreshData() {
|
||||
this.isLoading.set(true);
|
||||
this.loadPortfolioData();
|
||||
}
|
||||
|
||||
getPnLColor(value: number): string {
|
||||
if (value > 0) return 'text-green-600';
|
||||
if (value < 0) return 'text-red-600';
|
||||
return 'text-gray-600';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue