Nuove: multi-strategy, indicatori avanzati, posizioni
- Sidebar portfolio con metriche dettagliate (Totale, Investito, Disponibile, P&L, ROI) e aggiornamento real-time - Sistema multi-strategia: 8 strategie assegnabili per asset, voting decisionale, pagina Trading Control - Nuova pagina Posizioni: gestione, chiusura manuale, P&L non realizzato, notifiche - Sistema indicatori tecnici: 7+ indicatori configurabili, segnali real-time, raccomandazioni, storico segnali - Refactoring TradingBotService per capitale, P&L, ROI, eventi - Nuovi modelli e servizi per strategie/indicatori, persistenza configurazioni - UI/UX: navigazione aggiornata, widget, modali, responsive - Aggiornamento README e CHANGELOG con tutte le novità
This commit is contained in:
@@ -41,6 +41,22 @@
|
||||
}
|
||||
</NavLink>
|
||||
|
||||
<NavLink class="menu-item" href="/trading-control" title="Trading Control">
|
||||
<span class="item-icon bi bi-sliders"></span>
|
||||
@if (!sidebarCollapsed)
|
||||
{
|
||||
<span class="item-text">Trading Control</span>
|
||||
}
|
||||
</NavLink>
|
||||
|
||||
<NavLink class="menu-item" href="/positions" title="Posizioni">
|
||||
<span class="item-icon bi bi-wallet2"></span>
|
||||
@if (!sidebarCollapsed)
|
||||
{
|
||||
<span class="item-text">Posizioni</span>
|
||||
}
|
||||
</NavLink>
|
||||
|
||||
<NavLink class="menu-item" href="/strategies" title="Strategie">
|
||||
<span class="item-icon bi bi-diagram-3"></span>
|
||||
@if (!sidebarCollapsed)
|
||||
@@ -49,6 +65,14 @@
|
||||
}
|
||||
</NavLink>
|
||||
|
||||
<NavLink class="menu-item" href="/indicators" title="Indicatori">
|
||||
<span class="item-icon bi bi-graph-down-arrow"></span>
|
||||
@if (!sidebarCollapsed)
|
||||
{
|
||||
<span class="item-text">Indicatori</span>
|
||||
}
|
||||
</NavLink>
|
||||
|
||||
<NavLink class="menu-item" href="/assets" title="Asset">
|
||||
<span class="item-icon bi bi-coin"></span>
|
||||
@if (!sidebarCollapsed)
|
||||
@@ -103,16 +127,51 @@
|
||||
{
|
||||
<div class="sidebar-summary">
|
||||
<div class="summary-card">
|
||||
<div class="summary-row">
|
||||
<span class="summary-title">Portfolio</span>
|
||||
<span class="summary-amount">$@portfolioValue.ToString("N0")</span>
|
||||
<div class="summary-header">
|
||||
<span class="summary-section-title">Portfolio</span>
|
||||
</div>
|
||||
|
||||
<div class="summary-row">
|
||||
<span class="summary-title">Profitto</span>
|
||||
<span class="summary-amount @(totalProfit >= 0 ? "profit" : "loss")">
|
||||
$@totalProfit.ToString("N2")
|
||||
<span class="summary-title">Capitale Totale</span>
|
||||
<span class="summary-amount">$@totalCapital.ToString("N2")</span>
|
||||
</div>
|
||||
|
||||
<div class="summary-row">
|
||||
<span class="summary-title">Investito</span>
|
||||
<span class="summary-amount invested">$@investedCapital.ToString("N2")</span>
|
||||
</div>
|
||||
|
||||
<div class="summary-row">
|
||||
<span class="summary-title">Disponibile</span>
|
||||
<span class="summary-amount available">$@availableCapital.ToString("N2")</span>
|
||||
</div>
|
||||
|
||||
<div class="summary-divider"></div>
|
||||
|
||||
<div class="summary-row highlight">
|
||||
<span class="summary-title">P&L Corrente</span>
|
||||
<span class="summary-amount @(currentPL >= 0 ? "profit" : "loss")">
|
||||
@(currentPL >= 0 ? "+" : "")$@currentPL.ToString("N2")
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="summary-row">
|
||||
<span class="summary-title">ROI</span>
|
||||
<span class="summary-amount @(roiPercentage >= 0 ? "profit" : "loss")">
|
||||
@(roiPercentage >= 0 ? "+" : "")@roiPercentage.ToString("F2")%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Version Footer -->
|
||||
<div class="sidebar-footer">
|
||||
<div class="version-info">
|
||||
<span class="version-label">TradingBot</span>
|
||||
<span class="version-number">v1.5.2</span>
|
||||
</div>
|
||||
<div class="build-info">
|
||||
<span class="build-date">Build: @DateTime.Now.ToString("yyyy-MM-dd")</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -148,6 +207,11 @@
|
||||
private bool isRunning => BotService.Status.IsRunning;
|
||||
private decimal portfolioValue = 0;
|
||||
private decimal totalProfit = 0;
|
||||
private decimal totalCapital = 0;
|
||||
private decimal investedCapital = 0;
|
||||
private decimal availableCapital = 0;
|
||||
private decimal currentPL = 0;
|
||||
private decimal roiPercentage = 0;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
@@ -155,6 +219,7 @@
|
||||
sidebarCollapsed = settings.SidebarCollapsed;
|
||||
|
||||
BotService.OnStatusChanged += HandleUpdate;
|
||||
BotService.OnTradeExecuted += HandleTradeExecuted;
|
||||
BotService.OnPriceUpdated += HandlePriceUpdate;
|
||||
SettingsService.OnSettingsChanged += HandleSettingsChanged;
|
||||
|
||||
@@ -184,34 +249,69 @@
|
||||
|
||||
private void UpdateStats()
|
||||
{
|
||||
portfolioValue = BotService.AssetConfigurations.Values.Sum(c =>
|
||||
c.CurrentBalance + (c.CurrentHoldings * (BotService.GetLatestPrice(c.Symbol)?.Price ?? 0)));
|
||||
|
||||
totalProfit = BotService.AssetConfigurations.Values.Sum(c => c.TotalProfit);
|
||||
totalCapital = 0;
|
||||
investedCapital = 0;
|
||||
availableCapital = 0;
|
||||
currentPL = 0;
|
||||
totalProfit = 0;
|
||||
|
||||
foreach (var config in BotService.AssetConfigurations.Values)
|
||||
{
|
||||
if (!config.IsEnabled) continue;
|
||||
|
||||
// Capitale disponibile (cash)
|
||||
availableCapital += config.CurrentBalance;
|
||||
|
||||
// Capitale investito in posizioni aperte
|
||||
var currentPrice = BotService.GetLatestPrice(config.Symbol)?.Price ?? 0;
|
||||
var positionValue = config.CurrentHoldings * currentPrice;
|
||||
investedCapital += positionValue;
|
||||
|
||||
// P&L non realizzato sulle posizioni aperte
|
||||
if (config.CurrentHoldings > 0 && config.AverageEntryPrice > 0)
|
||||
{
|
||||
var entryValue = config.CurrentHoldings * config.AverageEntryPrice;
|
||||
currentPL += (positionValue - entryValue);
|
||||
}
|
||||
|
||||
// Totale profitti/perdite realizzati
|
||||
totalProfit += config.TotalProfit;
|
||||
}
|
||||
|
||||
// Capitale totale = Disponibile + Investito
|
||||
totalCapital = availableCapital + investedCapital;
|
||||
|
||||
// Portfolio value include anche i profitti realizzati
|
||||
portfolioValue = totalCapital + totalProfit;
|
||||
|
||||
// ROI basato sul capitale iniziale
|
||||
var initialCapital = BotService.AssetConfigurations.Values
|
||||
.Where(c => c.IsEnabled)
|
||||
.Sum(c => c.InitialBalance);
|
||||
|
||||
if (initialCapital > 0)
|
||||
{
|
||||
var totalGain = currentPL + totalProfit;
|
||||
roiPercentage = (totalGain / initialCapital) * 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
roiPercentage = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleUpdate()
|
||||
{
|
||||
UpdateStats();
|
||||
InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private void HandlePriceUpdate(string symbol, MarketPrice price)
|
||||
{
|
||||
UpdateStats();
|
||||
InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private void HandleSettingsChanged()
|
||||
{
|
||||
var settings = SettingsService.GetSettings();
|
||||
sidebarCollapsed = settings.SidebarCollapsed;
|
||||
InvokeAsync(StateHasChanged);
|
||||
}
|
||||
private void HandleUpdate() => InvokeAsync(() => { UpdateStats(); StateHasChanged(); });
|
||||
|
||||
private void HandleTradeExecuted(Trade trade) => InvokeAsync(() => { UpdateStats(); StateHasChanged(); });
|
||||
|
||||
private void HandlePriceUpdate(string symbol, MarketPrice price) => InvokeAsync(() => { UpdateStats(); StateHasChanged(); });
|
||||
|
||||
private void HandleSettingsChanged() => InvokeAsync(StateHasChanged);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
BotService.OnStatusChanged -= HandleUpdate;
|
||||
BotService.OnTradeExecuted -= HandleTradeExecuted;
|
||||
BotService.OnPriceUpdated -= HandlePriceUpdate;
|
||||
SettingsService.OnSettingsChanged -= HandleSettingsChanged;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user