Sono stati aggiunti tutti i file principali di Bootstrap 5.3.3, inclusi CSS, JavaScript (bundle, ESM, UMD, minificati), versioni RTL, utility, reboot, griglia e relative mappe delle sorgenti. Questi file abilitano un sistema di design moderno, responsive e accessibile, con supporto per layout LTR e RTL, debugging avanzato tramite source map e tutte le funzionalità di Bootstrap per lo sviluppo dell’interfaccia utente. Nessuna modifica ai file esistenti.
239 lines
9.0 KiB
Plaintext
239 lines
9.0 KiB
Plaintext
@page "/market"
|
|
@using TradingBot.Models
|
|
@using TradingBot.Services
|
|
@using TradingBot.Components.Shared
|
|
@inject TradingBotService BotService
|
|
@implements IDisposable
|
|
@rendermode InteractiveServer
|
|
|
|
<PageTitle>Analisi Mercato - TradingBot</PageTitle>
|
|
|
|
<div class="market-page">
|
|
<div class="page-header">
|
|
<div>
|
|
<h1>Analisi Mercato</h1>
|
|
<p class="subtitle">Monitora le tendenze di mercato e gli indicatori tecnici in tempo reale</p>
|
|
</div>
|
|
<select class="asset-selector" @bind="selectedSymbol" @bind:after="OnAssetChanged">
|
|
@foreach (var symbol in BotService.AssetConfigurations.Keys.OrderBy(s => s))
|
|
{
|
|
<option value="@symbol">@symbol - @BotService.AssetConfigurations[symbol].Name</option>
|
|
}
|
|
</select>
|
|
</div>
|
|
|
|
@if (selectedConfig != null && currentPrice != null)
|
|
{
|
|
<div class="market-overview">
|
|
<div class="price-card">
|
|
<div class="price-header">
|
|
<div class="asset-info">
|
|
<span class="asset-icon">@selectedSymbol.Substring(0, 1)</span>
|
|
<div>
|
|
<h2>@selectedConfig.Name</h2>
|
|
<span class="asset-symbol">@selectedSymbol</span>
|
|
</div>
|
|
</div>
|
|
<div class="price-main">
|
|
<div class="current-price">$@currentPrice.Price.ToString("N2")</div>
|
|
<div class="price-change @(currentPrice.Change24h >= 0 ? "positive" : "negative")">
|
|
<span class="bi @(currentPrice.Change24h >= 0 ? "bi-arrow-up" : "bi-arrow-down")"></span>
|
|
@Math.Abs(currentPrice.Change24h).ToString("F2")% (24h)
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="price-stats">
|
|
<div class="stat">
|
|
<span class="stat-label">Volume 24h</span>
|
|
<span class="stat-value">$@currentPrice.Volume24h.ToString("N0")</span>
|
|
</div>
|
|
<div class="stat">
|
|
<span class="stat-label">Holdings</span>
|
|
<span class="stat-value">@selectedConfig.CurrentHoldings.ToString("F6")</span>
|
|
</div>
|
|
<div class="stat">
|
|
<span class="stat-label">Valore Posizione</span>
|
|
<span class="stat-value">$@((selectedConfig.CurrentHoldings * currentPrice.Price).ToString("N2"))</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@if (currentIndicators != null)
|
|
{
|
|
<div class="indicators-grid">
|
|
<div class="indicator-card">
|
|
<div class="indicator-header">
|
|
<span class="indicator-icon">
|
|
<span class="bi bi-activity"></span>
|
|
</span>
|
|
<span class="indicator-name">RSI (14)</span>
|
|
</div>
|
|
<div class="indicator-value @GetRSIClass()">
|
|
@currentIndicators.RSI.ToString("F2")
|
|
</div>
|
|
<div class="indicator-status @GetRSIClass()">
|
|
@GetRSIStatus()
|
|
</div>
|
|
</div>
|
|
|
|
<div class="indicator-card">
|
|
<div class="indicator-header">
|
|
<span class="indicator-icon">
|
|
<span class="bi bi-graph-up"></span>
|
|
</span>
|
|
<span class="indicator-name">MACD</span>
|
|
</div>
|
|
<div class="indicator-value">
|
|
@currentIndicators.MACD.ToString("F2")
|
|
</div>
|
|
<div class="indicator-status">
|
|
Signal: @currentIndicators.Signal.ToString("F2")
|
|
</div>
|
|
</div>
|
|
|
|
<div class="indicator-card">
|
|
<div class="indicator-header">
|
|
<span class="indicator-icon">
|
|
<span class="bi bi-graph-down"></span>
|
|
</span>
|
|
<span class="indicator-name">Histogram</span>
|
|
</div>
|
|
<div class="indicator-value @(currentIndicators.Histogram >= 0 ? "positive" : "negative")">
|
|
@currentIndicators.Histogram.ToString("F4")
|
|
</div>
|
|
<div class="indicator-status">
|
|
@(currentIndicators.Histogram >= 0 ? "Bullish" : "Bearish")
|
|
</div>
|
|
</div>
|
|
|
|
<div class="indicator-card">
|
|
<div class="indicator-header">
|
|
<span class="indicator-icon">
|
|
<span class="bi bi-bezier2"></span>
|
|
</span>
|
|
<span class="indicator-name">EMA</span>
|
|
</div>
|
|
<div class="indicator-value">
|
|
@currentIndicators.EMA12.ToString("F2")
|
|
</div>
|
|
<div class="indicator-status">
|
|
EMA26: @currentIndicators.EMA26.ToString("F2")
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
<div class="chart-section">
|
|
<div class="chart-header">
|
|
<h3>Andamento Prezzi</h3>
|
|
<div class="chart-controls">
|
|
<button class="time-btn active">1H</button>
|
|
<button class="time-btn">4H</button>
|
|
<button class="time-btn">1D</button>
|
|
<button class="time-btn">1W</button>
|
|
</div>
|
|
</div>
|
|
<div class="chart-container">
|
|
<AdvancedChart
|
|
PriceData="@GetPriceList(selectedSymbol)"
|
|
Color="#6366f1"
|
|
Indicators="@currentIndicators" />
|
|
</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
@code {
|
|
[SupplyParameterFromQuery(Name = "symbol")]
|
|
public string? QuerySymbol { get; set; }
|
|
|
|
private string selectedSymbol = "BTC";
|
|
private AssetConfiguration? selectedConfig => BotService.AssetConfigurations.TryGetValue(selectedSymbol, out var c) ? c : null;
|
|
private MarketPrice? currentPrice => BotService.GetLatestPrice(selectedSymbol);
|
|
private TechnicalIndicators? currentIndicators;
|
|
|
|
protected override void OnInitialized()
|
|
{
|
|
// Set initial symbol from query string if available
|
|
if (!string.IsNullOrEmpty(QuerySymbol) && BotService.AssetConfigurations.ContainsKey(QuerySymbol))
|
|
{
|
|
selectedSymbol = QuerySymbol;
|
|
}
|
|
|
|
BotService.OnPriceUpdated += HandlePriceUpdate;
|
|
BotService.OnIndicatorsUpdated += HandleIndicatorsUpdate;
|
|
|
|
UpdateIndicators();
|
|
}
|
|
|
|
protected override void OnParametersSet()
|
|
{
|
|
// Update symbol if query parameter changes
|
|
if (!string.IsNullOrEmpty(QuerySymbol) &&
|
|
QuerySymbol != selectedSymbol &&
|
|
BotService.AssetConfigurations.ContainsKey(QuerySymbol))
|
|
{
|
|
selectedSymbol = QuerySymbol;
|
|
UpdateIndicators();
|
|
}
|
|
}
|
|
|
|
private void OnAssetChanged()
|
|
{
|
|
UpdateIndicators();
|
|
StateHasChanged();
|
|
}
|
|
|
|
private void UpdateIndicators()
|
|
{
|
|
currentIndicators = BotService.GetIndicators(selectedSymbol);
|
|
}
|
|
|
|
private List<decimal>? GetPriceList(string symbol)
|
|
{
|
|
var history = BotService.GetPriceHistory(symbol);
|
|
return history?.Select(p => p.Price).ToList();
|
|
}
|
|
|
|
private string GetRSIClass()
|
|
{
|
|
if (currentIndicators == null) return "neutral";
|
|
if (currentIndicators.RSI > 70) return "overbought";
|
|
if (currentIndicators.RSI < 30) return "oversold";
|
|
return "neutral";
|
|
}
|
|
|
|
private string GetRSIStatus()
|
|
{
|
|
if (currentIndicators == null) return "Neutral";
|
|
if (currentIndicators.RSI > 70) return "Overbought";
|
|
if (currentIndicators.RSI < 30) return "Oversold";
|
|
return "Neutral";
|
|
}
|
|
|
|
private void HandlePriceUpdate(string symbol, MarketPrice price)
|
|
{
|
|
if (symbol == selectedSymbol)
|
|
{
|
|
InvokeAsync(StateHasChanged);
|
|
}
|
|
}
|
|
|
|
private void HandleIndicatorsUpdate(string symbol, TechnicalIndicators indicators)
|
|
{
|
|
if (symbol == selectedSymbol)
|
|
{
|
|
currentIndicators = indicators;
|
|
InvokeAsync(StateHasChanged);
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
BotService.OnPriceUpdated -= HandlePriceUpdate;
|
|
BotService.OnIndicatorsUpdated -= HandleIndicatorsUpdate;
|
|
}
|
|
}
|