feat: add ?years= param to underlying-only chart endpoint

Endpoint standalone /api/chart/underlying/{id} caricava un TOP 350
fisso; ora accetta ?years= (default 5, clamp 1-20) e la SP filtra per
data invece che per numero di righe.

Il prezzo usato resta Px_close/Px_closeadj in base ad
AdjustedPrices, senza fallback incrociato tra i due campi: quando
Px_closeadj non è backfillato prima di uno split (es. Apple, valorizzato
solo da inizio 2019), un fallback avrebbe mischiato dati adjusted/raw
creando un gradino artificiale nel grafico. La SP ora taglia lo storico
dove il campo scelto non è popolato.

Fix collaterale: skip righe con prezzo NULL prima del cast a decimal,
evitava un InvalidCastException con storici lunghi.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 17:54:25 +02:00
parent d59f5a0faa
commit e36ef3fe47
4 changed files with 35 additions and 25 deletions

View File

@@ -10,7 +10,7 @@ namespace CertReports.Syncfusion.Services.Implementations;
/// </summary>
public interface IUnderlyingChartDataService
{
Task<UnderlyingChartData?> GetChartDataAsync(int idUnderlyings);
Task<UnderlyingChartData?> GetChartDataAsync(int idUnderlyings, int years = 5);
}
public class UnderlyingChartDataService : IUnderlyingChartDataService
@@ -25,7 +25,7 @@ public class UnderlyingChartDataService : IUnderlyingChartDataService
_logger = logger;
}
public async Task<UnderlyingChartData?> GetChartDataAsync(int idUnderlyings)
public async Task<UnderlyingChartData?> GetChartDataAsync(int idUnderlyings, int years = 5)
{
await using var conn = new SqlConnection(_connectionString);
await conn.OpenAsync();
@@ -33,6 +33,7 @@ public class UnderlyingChartDataService : IUnderlyingChartDataService
await using var cmd = new SqlCommand("cedlab_Chart_UnderlyingOnly", conn)
{ CommandType = CommandType.StoredProcedure };
cmd.Parameters.AddWithValue("@IDUnderlyings", idUnderlyings);
cmd.Parameters.AddWithValue("@Years", years);
var result = new UnderlyingChartData { IDUnderlyings = idUnderlyings };
@@ -42,10 +43,14 @@ public class UnderlyingChartDataService : IUnderlyingChartDataService
if (result.Points.Count == 0)
result.Nome = ToStr(r, "Nome");
int pxOrd = r.GetOrdinal("Px");
if (r.IsDBNull(pxOrd))
continue; // riga storica con solo Px_low/high/open valorizzati, no close
result.Points.Add(new UnderlyingChartPoint
{
Date = r.GetDateTime(r.GetOrdinal("Px_date")),
Px = Convert.ToDecimal(r.GetValue(r.GetOrdinal("Px"))),
Px = Convert.ToDecimal(r.GetValue(pxOrd)),
});
}