139 lines
4.6 KiB
TypeScript
139 lines
4.6 KiB
TypeScript
import { CommonModule } from '@angular/common';
|
|
import { Component, inject, OnDestroy, OnInit, signal } from '@angular/core';
|
|
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
|
import { MatButtonModule } from '@angular/material/button';
|
|
import { MatCardModule } from '@angular/material/card';
|
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
import { MatIconModule } from '@angular/material/icon';
|
|
import { MatInputModule } from '@angular/material/input';
|
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
|
|
import { MatTableModule } from '@angular/material/table';
|
|
import { interval, Subscription } from 'rxjs';
|
|
import { ApiService, RiskEvaluation, RiskThresholds } from '../../services/api.service';
|
|
|
|
@Component({
|
|
selector: 'app-risk-management',
|
|
standalone: true,
|
|
imports: [
|
|
CommonModule,
|
|
MatCardModule,
|
|
MatIconModule,
|
|
MatButtonModule,
|
|
MatTableModule,
|
|
MatFormFieldModule,
|
|
MatInputModule,
|
|
MatSnackBarModule,
|
|
MatProgressSpinnerModule,
|
|
ReactiveFormsModule,
|
|
],
|
|
templateUrl: './risk-management.component.html',
|
|
styleUrl: './risk-management.component.css',
|
|
})
|
|
export class RiskManagementComponent implements OnInit, OnDestroy {
|
|
private apiService = inject(ApiService);
|
|
private snackBar = inject(MatSnackBar);
|
|
private fb = inject(FormBuilder);
|
|
private subscriptions: Subscription[] = [];
|
|
|
|
protected riskThresholds = signal<RiskThresholds | null>(null);
|
|
protected riskHistory = signal<RiskEvaluation[]>([]);
|
|
protected isLoading = signal<boolean>(true);
|
|
protected isSaving = signal<boolean>(false);
|
|
protected error = signal<string | null>(null);
|
|
|
|
protected thresholdsForm: FormGroup;
|
|
protected displayedColumns = ['symbol', 'positionValue', 'riskLevel', 'violations', 'timestamp'];
|
|
|
|
constructor() {
|
|
this.thresholdsForm = this.fb.group({
|
|
maxPositionSize: [0, [Validators.required, Validators.min(0)]],
|
|
maxDailyLoss: [0, [Validators.required, Validators.min(0)]],
|
|
maxPortfolioRisk: [0, [Validators.required, Validators.min(0), Validators.max(1)]],
|
|
volatilityLimit: [0, [Validators.required, Validators.min(0), Validators.max(1)]],
|
|
});
|
|
}
|
|
|
|
ngOnInit() {
|
|
this.loadRiskThresholds();
|
|
this.loadRiskHistory();
|
|
|
|
// Refresh risk history every 30 seconds
|
|
const historySubscription = interval(30000).subscribe(() => {
|
|
this.loadRiskHistory();
|
|
});
|
|
this.subscriptions.push(historySubscription);
|
|
}
|
|
|
|
ngOnDestroy() {
|
|
this.subscriptions.forEach(sub => sub.unsubscribe());
|
|
}
|
|
|
|
private loadRiskThresholds() {
|
|
this.apiService.getRiskThresholds().subscribe({
|
|
next: response => {
|
|
this.riskThresholds.set(response.data);
|
|
this.thresholdsForm.patchValue(response.data);
|
|
this.isLoading.set(false);
|
|
this.error.set(null);
|
|
},
|
|
error: err => {
|
|
console.error('Failed to load risk thresholds:', err);
|
|
this.error.set('Failed to load risk thresholds');
|
|
this.isLoading.set(false);
|
|
this.snackBar.open('Failed to load risk thresholds', 'Dismiss', { duration: 5000 });
|
|
},
|
|
});
|
|
}
|
|
|
|
private loadRiskHistory() {
|
|
this.apiService.getRiskHistory().subscribe({
|
|
next: response => {
|
|
this.riskHistory.set(response.data);
|
|
},
|
|
error: err => {
|
|
console.error('Failed to load risk history:', err);
|
|
this.snackBar.open('Failed to load risk history', 'Dismiss', { duration: 3000 });
|
|
},
|
|
});
|
|
}
|
|
|
|
saveThresholds() {
|
|
if (this.thresholdsForm.valid) {
|
|
this.isSaving.set(true);
|
|
const thresholds = this.thresholdsForm.value as RiskThresholds;
|
|
|
|
this.apiService.updateRiskThresholds(thresholds).subscribe({
|
|
next: response => {
|
|
this.riskThresholds.set(response.data);
|
|
this.isSaving.set(false);
|
|
this.snackBar.open('Risk thresholds updated successfully', 'Dismiss', { duration: 3000 });
|
|
},
|
|
error: err => {
|
|
console.error('Failed to save risk thresholds:', err);
|
|
this.isSaving.set(false);
|
|
this.snackBar.open('Failed to save risk thresholds', 'Dismiss', { duration: 5000 });
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
refreshData() {
|
|
this.isLoading.set(true);
|
|
this.loadRiskThresholds();
|
|
this.loadRiskHistory();
|
|
}
|
|
|
|
getRiskLevelColor(level: string): string {
|
|
switch (level) {
|
|
case 'LOW':
|
|
return 'text-green-600';
|
|
case 'MEDIUM':
|
|
return 'text-yellow-600';
|
|
case 'HIGH':
|
|
return 'text-red-600';
|
|
default:
|
|
return 'text-gray-600';
|
|
}
|
|
}
|
|
}
|