stock-bot/apps/dashboard/src/app/pages/strategies/strategy-details/strategy-details.component.html
2025-06-09 22:55:51 -04:00

214 lines
8.8 KiB
HTML

<div class="space-y-6" *ngIf="strategy">
<div class="flex flex-col md:flex-row md:justify-between md:items-start gap-4">
<!-- Strategy Overview Card -->
<mat-card class="flex-1 p-4">
<div class="flex items-start justify-between">
<div>
<h2 class="text-xl font-bold">{{strategy.name}}</h2>
<p class="text-gray-600 text-sm">{{strategy.description}}</p>
</div>
<div class="flex items-center gap-2">
<button mat-raised-button color="primary" class="mr-2" (click)="openBacktestDialog()">
Run Backtest
</button>
<span class="px-3 py-1 rounded-full text-xs font-semibold"
[style.background-color]="getStatusColor(strategy.status)"
style="color: white;">
{{strategy.status}}
</span>
</div>
</div>
<div class="mt-4 grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<h3 class="font-semibold text-sm text-gray-600">Type</h3>
<p>{{strategy.type}}</p>
</div>
<div>
<h3 class="font-semibold text-sm text-gray-600">Created</h3>
<p>{{strategy.createdAt | date:'medium'}}</p>
</div>
<div>
<h3 class="font-semibold text-sm text-gray-600">Last Updated</h3>
<p>{{strategy.updatedAt | date:'medium'}}</p>
</div>
<div>
<h3 class="font-semibold text-sm text-gray-600">Symbols</h3>
<div class="flex flex-wrap gap-1 mt-1">
<mat-chip *ngFor="let symbol of strategy.symbols">{{symbol}}</mat-chip>
</div>
</div>
</div>
</mat-card>
<!-- Performance Summary Card -->
<mat-card class="md:w-1/3 p-4">
<h3 class="text-lg font-bold mb-3">Performance</h3>
<div class="grid grid-cols-2 gap-3">
<div>
<p class="text-sm text-gray-600">Return</p>
<p class="text-xl font-semibold"
[ngClass]="{'text-green-600': performance.totalReturn >= 0, 'text-red-600': performance.totalReturn < 0}">
{{performance.totalReturn | percent:'1.2-2'}}
</p>
</div>
<div>
<p class="text-sm text-gray-600">Win Rate</p>
<p class="text-xl font-semibold">{{performance.winRate | percent:'1.0-0'}}</p>
</div>
<div>
<p class="text-sm text-gray-600">Sharpe Ratio</p>
<p class="text-xl font-semibold">{{performance.sharpeRatio | number:'1.2-2'}}</p>
</div>
<div>
<p class="text-sm text-gray-600">Max Drawdown</p>
<p class="text-xl font-semibold text-red-600">{{performance.maxDrawdown | percent:'1.2-2'}}</p>
</div>
<div>
<p class="text-sm text-gray-600">Total Trades</p>
<p class="text-xl font-semibold">{{performance.totalTrades}}</p>
</div>
<div>
<p class="text-sm text-gray-600">Sortino Ratio</p>
<p class="text-xl font-semibold">{{performance.sortinoRatio | number:'1.2-2'}}</p>
</div>
</div>
<mat-divider class="my-4"></mat-divider>
<div class="flex justify-between mt-2">
<button mat-button color="primary" *ngIf="strategy.status !== 'ACTIVE'" (click)="activateStrategy()">
<mat-icon>play_arrow</mat-icon> Start
</button>
<button mat-button color="accent" *ngIf="strategy.status === 'ACTIVE'" (click)="pauseStrategy()">
<mat-icon>pause</mat-icon> Pause
</button>
<button mat-button color="warn" *ngIf="strategy.status === 'ACTIVE'" (click)="stopStrategy()">
<mat-icon>stop</mat-icon> Stop
</button>
<button mat-button (click)="openEditDialog()">
<mat-icon>edit</mat-icon> Edit
</button>
</div>
</mat-card>
</div>
<!-- Parameters Card -->
<mat-card class="p-4">
<h3 class="text-lg font-bold mb-3">Strategy Parameters</h3>
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
<div *ngFor="let param of strategy.parameters | keyvalue">
<p class="text-sm text-gray-600">{{param.key}}</p>
<p class="font-semibold">{{param.value}}</p>
</div>
</div>
</mat-card>
<!-- Backtest Results Section (only shown when a backtest has been run) -->
<div *ngIf="backtestResult" class="backtest-results space-y-6">
<h2 class="text-xl font-bold">Backtest Results</h2>
<!-- Performance Metrics Component -->
<app-performance-metrics [backtestResult]="backtestResult"></app-performance-metrics>
<!-- Equity Chart Component -->
<app-equity-chart [backtestResult]="backtestResult"></app-equity-chart>
<!-- Drawdown Chart Component -->
<app-drawdown-chart [backtestResult]="backtestResult"></app-drawdown-chart>
<!-- Trades Table Component -->
<app-trades-table [backtestResult]="backtestResult"></app-trades-table>
</div>
<!-- Tabs for Signals/Trades -->
<mat-card class="p-0">
<mat-tab-group>
<!-- Signals Tab -->
<mat-tab label="Recent Signals">
<div class="p-4">
<ng-container *ngIf="!isLoadingSignals; else loadingSignals">
<table class="min-w-full">
<thead>
<tr>
<th class="py-2 text-left">Time</th>
<th class="py-2 text-left">Symbol</th>
<th class="py-2 text-left">Action</th>
<th class="py-2 text-left">Price</th>
<th class="py-2 text-left">Quantity</th>
<th class="py-2 text-left">Confidence</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let signal of signals">
<td class="py-2">{{signal.timestamp | date:'short'}}</td>
<td class="py-2">{{signal.symbol}}</td>
<td class="py-2">
<span class="px-2 py-1 rounded text-xs font-semibold"
[style.background-color]="getSignalColor(signal.action)"
style="color: white;">
{{signal.action}}
</span>
</td>
<td class="py-2">${{signal.price | number:'1.2-2'}}</td>
<td class="py-2">{{signal.quantity}}</td>
<td class="py-2">{{signal.confidence | percent:'1.0-0'}}</td>
</tr>
</tbody>
</table>
</ng-container>
<ng-template #loadingSignals>
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
</ng-template>
</div>
</mat-tab>
<!-- Trades Tab -->
<mat-tab label="Recent Trades">
<div class="p-4">
<ng-container *ngIf="!isLoadingTrades; else loadingTrades">
<table class="min-w-full">
<thead>
<tr>
<th class="py-2 text-left">Symbol</th>
<th class="py-2 text-left">Entry</th>
<th class="py-2 text-left">Exit</th>
<th class="py-2 text-left">Quantity</th>
<th class="py-2 text-left">P&L</th>
<th class="py-2 text-left">P&L %</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let trade of trades">
<td class="py-2">{{trade.symbol}}</td>
<td class="py-2">
${{trade.entryPrice | number:'1.2-2'}} @ {{trade.entryTime | date:'short'}}
</td>
<td class="py-2">
${{trade.exitPrice | number:'1.2-2'}} @ {{trade.exitTime | date:'short'}}
</td>
<td class="py-2">{{trade.quantity}}</td>
<td class="py-2" [ngClass]="{'text-green-600': trade.pnl >= 0, 'text-red-600': trade.pnl < 0}">
${{trade.pnl | number:'1.2-2'}}
</td>
<td class="py-2" [ngClass]="{'text-green-600': trade.pnlPercent >= 0, 'text-red-600': trade.pnlPercent < 0}">
{{trade.pnlPercent | number:'1.2-2'}}%
</td>
</tr>
</tbody>
</table>
</ng-container>
<ng-template #loadingTrades>
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
</ng-template>
</div>
</mat-tab>
</mat-tab-group>
</mat-card>
</div>
<mat-card class="p-6 flex items-center" *ngIf="!strategy">
<div class="text-center text-gray-500 w-full">
<mat-icon style="font-size: 4rem; width: 4rem; height: 4rem;">psychology</mat-icon>
<p class="mb-4">No strategy selected</p>
</div>
</mat-card>