fix: use cedlab_Chart_UL2 (new SP, don't modify UL1); add correct SQL scripts with Prices table

This commit is contained in:
2026-05-27 16:28:26 +02:00
parent 44e2098584
commit a866a2f7d5
4 changed files with 297 additions and 2 deletions

View File

@@ -33,10 +33,10 @@ public class ChartDataServiceV2 : IChartDataServiceV2
await using var conn = new SqlConnection(_connectionString);
await conn.OpenAsync();
// ── 1. Metadata sottostanti (cedlab_Chart_UL1) ─────────────────
// ── 1. Metadata sottostanti (cedlab_Chart_UL2) ─────────────────
var underlyings = new List<ChartUlMetadata>();
await using (var cmd = new SqlCommand("cedlab_Chart_UL1", conn)
await using (var cmd = new SqlCommand("cedlab_Chart_UL2", conn)
{ CommandType = CommandType.StoredProcedure })
{
cmd.Parameters.AddWithValue("@isin", isin);

View File

@@ -0,0 +1,103 @@
USE [FirstSolutionDB]
GO
-- ============================================================
-- SP: cedlab_Chart_AllSeriesV2
-- Restituisce tutte le serie (CTF + UL) in un unico round-trip.
-- Usata da ChartDataServiceV2 per il grafico V2.
--
-- Logica UL: identica a cedlab_Chart_DailyUL1, estesa a tutti i
-- sottostanti del certificato in un unico UNION ALL.
--
-- Output (ordinato IDUnderlyings ASC, Px_date ASC):
-- IDUnderlyings INT -- 0 = CTF, altrimenti UnderlyingsID
-- Px_date DATE
-- Performance DECIMAL -- % su strike/nominal
--
-- Colonne con <<< verify: adatta al tuo schema reale.
-- ============================================================
CREATE OR ALTER PROCEDURE [dbo].[cedlab_Chart_AllSeriesV2]
@isin NVARCHAR(12)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @IDCertificates INT;
DECLARE @Nominal DECIMAL(18, 6);
SELECT TOP 1
@IDCertificates = c.IDCertificates, -- <<< verify
@Nominal = c.Nominal_amount -- <<< verify: valore nominale per CTF %
FROM [dbo].[Certificates] c -- <<< verify: nome tabella certificati
WHERE c.ISIN = @isin;
IF @IDCertificates IS NULL RETURN;
-- ── CTE: calcola performance per ogni serie, TOP 350 per-serie ─────
WITH AllSeriesRaw AS
(
-- ── Serie CTF (IDUnderlyings = 0) ────────────────────────────────
-- Performance = PX_LAST_EOD / Nominal * 100
SELECT
0 AS IDUnderlyings,
pc.Px_date,
CONVERT(DECIMAL(18, 4),
pc.PX_LAST_EOD / NULLIF(@Nominal, 0) * 100
) AS Performance,
ROW_NUMBER() OVER (
PARTITION BY 0
ORDER BY pc.Px_date DESC
) AS rn
FROM dbo.Prices pc
WHERE pc.CertificatesID = @IDCertificates
AND pc.PX_LAST_EOD IS NOT NULL
AND pc.PX_LAST_EOD <> 0
UNION ALL
-- ── Serie UL (una per ogni sottostante) ──────────────────────────
-- Stessa logica di cedlab_Chart_DailyUL1, estesa a tutti gli UL.
-- Date allineate al CTF (INNER JOIN su Px_date).
SELECT
pu.UnderlyingsID AS IDUnderlyings,
pu.Px_date,
CONVERT(DECIMAL(18, 4),
CASE
WHEN ISNULL(u.AdjustedPrices, 0) = 0 THEN pu.Px_close
ELSE pu.Px_closeadj
END
/ NULLIF(u.Strike, 0) * 100
) AS Performance,
ROW_NUMBER() OVER (
PARTITION BY pu.UnderlyingsID
ORDER BY pu.Px_date DESC
) AS rn
FROM dbo.Prices pu
LEFT JOIN dbo.Underlyings u
ON u.IDUnderlyings = pu.UnderlyingsID
-- Allinea date UL al CTF (solo date presenti nel certificato)
INNER JOIN dbo.Prices pc
ON pu.Px_date = pc.Px_date
AND pc.CertificatesID = @IDCertificates
AND pc.PX_LAST_EOD IS NOT NULL
AND pc.PX_LAST_EOD <> 0
WHERE u.IDCertificates = @IDCertificates -- <<< verify: colonna FK in Underlyings
AND (
pu.px_low IS NOT NULL OR pu.Px_high IS NOT NULL OR
pu.Px_open IS NOT NULL OR pu.Px_close IS NOT NULL
)
AND pu.px_date >= u.StartDate -- <<< verify: colonna StartDate in Underlyings
)
-- ── Filtra TOP 350 per serie e reinverte in ordine ASC ───────────────
SELECT
IDUnderlyings,
Px_date,
Performance
FROM AllSeriesRaw
WHERE rn <= 350
ORDER BY IDUnderlyings ASC, Px_date ASC;
END
GO

View File

@@ -0,0 +1,90 @@
-- ============================================================
-- SP: cedlab_Chart_UL1
-- Metadata dei sottostanti per il grafico V2.
-- Estende FSWeb_Chart_UL con:
-- IsWorstOf, PriceWorst, PriceWorstPerc,
-- NumPrezziCFT, NomeCFT,
-- BarrieraCouponPerc, BarrieraCapitalePerc,
-- TriggerAutocallPerc, AutocallValue
--
-- Ordinato: IsWorstOf DESC (worst-of nella prima riga)
--
-- NOTA: se questa SP esiste già nel DB con questo nome e restituisce
-- già tutte queste colonne, questo file è solo documentazione.
-- Eseguilo solo se la SP non esiste o mancano le colonne.
--
-- ADATTAMENTO RICHIESTO: stessi nomi tabella del file cedlab_Chart_AllSeriesV2.sql
-- ============================================================
USE [FirstSolutionDB]
GO
CREATE OR ALTER PROCEDURE [dbo].[cedlab_Chart_UL1]
@isin NVARCHAR(12)
AS
BEGIN
SET NOCOUNT ON;
-- Numero prezzi CTF disponibili (usato per il sub-titolo)
DECLARE @NumPrezziCFT INT;
DECLARE @IDCertificates INT;
DECLARE @Nominal DECIMAL(18,6);
DECLARE @NomeCFT NVARCHAR(200);
SELECT TOP 1
@IDCertificates = c.IDCertificates, -- <<< adatta
@Nominal = c.Nominal_amount, -- <<< adatta
@NomeCFT = c.Descrizione + ' - ' + c.ISIN -- <<< adatta
FROM [dbo].[Certificates] c -- <<< adatta
WHERE c.ISIN = @isin;
SELECT @NumPrezziCFT = COUNT(*)
FROM [dbo].[CFT_PriceHistory] -- <<< adatta
WHERE IDCertificates = @IDCertificates;
-- Prezzo attuale worst-of (prezzo corrente / strike * 100)
-- La logica di IsWorstOf dipende dalla tua definizione (es: peggior performer)
SELECT
u.IDCertificates,
u.IDUnderlyings,
u.StartDate, -- <<< adatta
u.Strike, -- <<< adatta
-- Percentuali barriere (es: BarrieraCoupon / Nominal * 100)
u.BarrieraCouponPerc, -- <<< adatta o calcola
u.BarrieraCoupon, -- <<< adatta (valore assoluto)
u.BarrieraCapitalePerc, -- <<< adatta o calcola
u.BarrieraCapitale, -- <<< adatta (valore assoluto)
u.Name AS Sottostante, -- <<< adatta nome colonna
u.IsWorstOf, -- <<< adatta: 1=worst-of, 0=altri
-- Prezzo attuale worst-of: 0 per non-worst-of
CASE WHEN u.IsWorstOf = 1
THEN ISNULL(last_px.Px_close, 0) -- <<< adatta: ultimo prezzo disponibile
ELSE 0
END AS PriceWorst,
CASE WHEN u.IsWorstOf = 1 AND u.Strike > 0
THEN ISNULL(last_px.Px_close, 0) / u.Strike * 100
ELSE 0
END AS PriceWorstPerc,
@NumPrezziCFT AS NumPrezziCFT,
@NomeCFT AS NomeCFT,
ISNULL(u.TriggerAutocallPerc, 0) AS TriggerAutocallPerc, -- <<< adatta
ISNULL(u.AutocallValue, 0) AS AutocallValue -- <<< adatta
FROM [dbo].[Underlyings] u -- <<< adatta nome tabella
-- Join per ottenere l'ultimo prezzo disponibile
LEFT JOIN (
SELECT ul.IDCertificates, ul.IDUnderlyings,
ul.Px_close,
ROW_NUMBER() OVER (
PARTITION BY ul.IDCertificates, ul.IDUnderlyings
ORDER BY ul.Px_date DESC
) AS rn
FROM [dbo].[UL_PriceHistory] ul -- <<< adatta nome tabella
) last_px
ON last_px.IDCertificates = u.IDCertificates
AND last_px.IDUnderlyings = u.IDUnderlyings
AND last_px.rn = 1
WHERE u.IDCertificates = @IDCertificates
ORDER BY u.IsWorstOf DESC; -- worst-of prima
END
GO

View File

@@ -0,0 +1,102 @@
USE [FirstSolutionDB]
GO
-- ============================================================
-- SP: cedlab_Chart_UL2
-- Metadata dei sottostanti per il grafico V2.
-- NON modifica cedlab_Chart_UL1 (esistente, usata altrove).
--
-- Restituisce (ordinato IsWorstOf DESC, worst-of nella prima riga):
-- IDCertificates, IDUnderlyings, StartDate, Strike,
-- BarrieraCouponPerc, BarrieraCoupon,
-- BarrieraCapitalePerc, BarrieraCapitale,
-- Sottostante, IsWorstOf,
-- PriceWorst, PriceWorstPerc,
-- NumPrezziCFT, NomeCFT,
-- TriggerAutocallPerc, AutocallValue
--
-- Colonne con <<< verify: adatta al tuo schema reale.
-- ============================================================
CREATE OR ALTER PROCEDURE [dbo].[cedlab_Chart_UL2]
@isin NVARCHAR(12)
AS
BEGIN
SET NOCOUNT ON;
-- Recupera IDCertificates
DECLARE @IDCertificates INT;
SELECT TOP 1
@IDCertificates = c.IDCertificates -- <<< verify: colonna ID nel tuo Certificates
FROM [dbo].[Certificates] c -- <<< verify: nome tabella certificati
WHERE c.ISIN = @isin;
IF @IDCertificates IS NULL RETURN;
-- Conta prezzi EOD disponibili del certificato (usato per il sub-titolo "< 30 gg")
DECLARE @NumPrezziCFT INT;
SELECT @NumPrezziCFT = COUNT(*)
FROM dbo.Prices
WHERE CertificatesID = @IDCertificates
AND PX_LAST_EOD IS NOT NULL
AND PX_LAST_EOD <> 0;
SELECT
u.IDCertificates,
u.IDUnderlyings,
u.StartDate, -- <<< verify: colonna StartDate in Underlyings
u.Strike, -- <<< verify: colonna Strike in Underlyings
-- Barriere (% e assolute)
u.BarrieraCouponPerc, -- <<< verify: colonna % barriera coupon
u.BarrieraCoupon, -- <<< verify: colonna assoluta barriera coupon
u.BarrieraCapitalePerc, -- <<< verify: colonna % barriera capitale
u.BarrieraCapitale, -- <<< verify: colonna assoluta barriera capitale
u.Name AS Sottostante, -- <<< verify: colonna nome sottostante
u.IsWorstOf, -- <<< verify: colonna 1/0 worst-of in Underlyings
-- PriceWorst: ultimo Px_close per il worst-of (0 per gli altri)
CASE
WHEN u.IsWorstOf = 1 THEN ISNULL(lp.Px_close, 0)
ELSE 0
END AS PriceWorst,
-- PriceWorstPerc: PriceWorst / Strike * 100
CASE
WHEN u.IsWorstOf = 1 AND ISNULL(u.Strike, 0) > 0
THEN ISNULL(lp.Px_close, 0) / u.Strike * 100
ELSE 0
END AS PriceWorstPerc,
@NumPrezziCFT AS NumPrezziCFT,
-- NomeCFT: Descrizione + ' - ' + ISIN (adatta nomi colonne)
c.Descrizione + ' - ' + c.ISIN AS NomeCFT, -- <<< verify: colonne Descrizione e ISIN
ISNULL(u.TriggerAutocallPerc, 0) AS TriggerAutocallPerc, -- <<< verify
ISNULL(u.AutocallValue, 0) AS AutocallValue -- <<< verify
FROM dbo.Underlyings u
JOIN [dbo].[Certificates] c -- <<< verify
ON c.IDCertificates = u.IDCertificates
-- Ultimo prezzo disponibile per ogni sottostante (per PriceWorst)
LEFT JOIN (
SELECT
UnderlyingsID,
Px_close,
ROW_NUMBER() OVER (
PARTITION BY UnderlyingsID
ORDER BY Px_date DESC
) AS rn
FROM dbo.Prices
WHERE Px_close IS NOT NULL
) lp ON lp.UnderlyingsID = u.IDUnderlyings AND lp.rn = 1
WHERE u.IDCertificates = @IDCertificates
ORDER BY u.IsWorstOf DESC; -- worst-of nella prima riga
END
GO