Files
Encelado/TradingBot/Components/Shared/AdvancedChart.razor
Alberto Balbo d25b4443c0 Aggiunta Bootstrap 5.3.3 (CSS, JS, RTL, mappe) al progetto
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.
2025-12-12 23:27:28 +01:00

129 lines
4.3 KiB
Plaintext

@using TradingBot.Models
<div class="advanced-chart">
@if (PriceData == null || PriceData.Count < 2)
{
<div class="chart-loading">
<div class="loading-spinner"></div>
<span>In attesa di dati sufficienti...</span>
</div>
}
else
{
<svg viewBox="0 0 @Width @Height" class="chart-svg" preserveAspectRatio="none">
<defs>
<linearGradient id="gradient-@ColorId" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="@Color" stop-opacity="0.4" />
<stop offset="100%" stop-color="@Color" stop-opacity="0.05" />
</linearGradient>
</defs>
<!-- Grid Lines -->
@for (int i = 0; i <= 4; i++)
{
var y = (Height * i / 4.0);
<line x1="0" y1="@y" x2="@Width" y2="@y"
stroke="rgba(51, 65, 85, 0.3)" stroke-width="1" stroke-dasharray="4 4" />
}
<!-- Area Fill -->
@if (!string.IsNullOrEmpty(GetAreaPath()))
{
<path d="@GetAreaPath()" fill="url(#gradient-@ColorId)" />
}
<!-- Line Chart -->
@if (!string.IsNullOrEmpty(GetPolylinePoints()))
{
<polyline fill="none" stroke="@Color" stroke-width="3"
points="@GetPolylinePoints()"
stroke-linecap="round" stroke-linejoin="round" />
}
</svg>
@if (Indicators != null)
{
<div class="indicators-overlay">
<div class="indicator-badge">
<span class="indicator-label">RSI:</span>
<span class="indicator-value @GetRSIClass()">@Indicators.RSI.ToString("F1")</span>
</div>
<div class="indicator-badge">
<span class="indicator-label">MACD:</span>
<span class="indicator-value">@Indicators.MACD.ToString("F2")</span>
</div>
</div>
}
}
</div>
@code {
[Parameter] public List<decimal>? PriceData { get; set; }
[Parameter] public string Color { get; set; } = "#6366f1";
[Parameter] public TechnicalIndicators? Indicators { get; set; }
private int Width = 800;
private int Height = 300;
private string ColorId => Guid.NewGuid().ToString("N").Substring(0, 8);
private string GetPolylinePoints()
{
if (PriceData == null || PriceData.Count < 2) return string.Empty;
try
{
var max = PriceData.Max();
var min = PriceData.Min();
var range = max - min;
if (range == 0) range = max * 0.01m; // 1% range if all values are same
var points = new List<string>();
var padding = Height * 0.1; // 10% padding
var chartHeight = Height - (padding * 2);
for (int i = 0; i < PriceData.Count; i++)
{
var x = (i / (double)(PriceData.Count - 1)) * Width;
var normalizedValue = (double)((PriceData[i] - min) / range);
var y = padding + (chartHeight * (1 - normalizedValue));
points.Add($"{x:F2},{y:F2}");
}
return string.Join(" ", points);
}
catch
{
return string.Empty;
}
}
private string GetAreaPath()
{
var polyline = GetPolylinePoints();
if (string.IsNullOrEmpty(polyline)) return string.Empty;
try
{
var points = polyline.Split(' ');
if (points.Length < 2) return string.Empty;
var firstPoint = points[0].Split(',');
var lastPoint = points[points.Length - 1].Split(',');
return $"M {firstPoint[0]},{Height} L {polyline} L {lastPoint[0]},{Height} Z";
}
catch
{
return string.Empty;
}
}
private string GetRSIClass()
{
if (Indicators == null) return "rsi-neutral";
if (Indicators.RSI > 70) return "rsi-overbought";
if (Indicators.RSI < 30) return "rsi-oversold";
return "rsi-neutral";
}
}