• Se avete bisogno di importare le quotazioni dei vostri titoli azionari o ETF in Google Sheets in modo che si aggiornino automaticamente, potete usare l’apps script qua sotto.
  • Per farlo funzionare occorre semplicemente aprire un foglio di lavoro su https://docs.google.com/spreadsheets/ e andare su Estensioni e Apps Script.
  • Cliccare sul + a fianco di File e selezionare Script.
  • Dare un titolo a piacere al file (non implica nulla sul funzionamento).
  • Elimina il contenuto già presente e incolla lo script che trovi qua di seguito.
  • Salva cliccando sull’icona del floppydisk o premi ctrl+s.
  • Ora torna nel tuo foglio di spreadsheets e utilizzando le varie funzioni di esempio, avrai il risultato voluto.
/*************************************************
 * FUNZIONI FINANZA – VERSIONE 12/01/2026
 *
 * =ULTIMO("SWDA.MI")
 * =VARGIORN("SWDA.MI")
 * =YTD("SWDA.MI")
 * =VARPER("SWDA.MI"; 30)
 * =MAXDATE("SWDA.MI"; "1y")
 * =MAXVAL("SWDA.MI"; "5y")
 * =MAXINFO("SWDA.MI"; "7y")
 * =FORZA_REFRESH()
 *************************************************/

function _fetchChart(ticker, range, interval) {
  const url =
    "https://query1.finance.yahoo.com/v8/finance/chart/" +
    encodeURIComponent(ticker) +
    "?range=" + range +
    "&interval=" + interval +
    "&includePrePost=false";

  const res = UrlFetchApp.fetch(url, {
    muteHttpExceptions: true,
    headers: { "User-Agent": "Mozilla/5.0" }
  });

  const json = JSON.parse(res.getContentText());
  return json?.chart?.result?.[0] || null;
}

/***********************
 * ULTIMO PREZZO
 ***********************/
function ULTIMO(ticker) {
  if (!ticker) return "Ticker?";
  const r = _fetchChart(ticker, "5d", "1d");
  const prices = r?.indicators?.quote?.[0]?.close;
  if (!prices) return "Dati non disponibili";

  for (let i = prices.length - 1; i >= 0; i--) {
    if (prices[i] != null) return Number(prices[i].toFixed(4));
  }
  return "No prezzi";
}

/***********************
 * VARIAZIONE GIORNALIERA %
 ***********************/
function VARGIORN(ticker) {
  if (!ticker) return "Ticker?";
  const r = _fetchChart(ticker, "5d", "1d");
  const p = r?.indicators?.quote?.[0]?.close;
  if (!p || p.length < 2) return "Dati incompleti";

  let last = null, prev = null;
  for (let i = p.length - 1; i >= 0; i--) {
    if (p[i] != null) {
      if (last === null) last = p[i];
      else { prev = p[i]; break; }
    }
  }
  if (last === null || prev === null) return "Dati incompleti";
  return Number((((last - prev) / prev) * 100).toFixed(2));
}

/***********************
 * VARIAZIONE YTD %
 ***********************/
function YTD(ticker) {
  if (!ticker) return "Ticker?";
  const r = _fetchChart(ticker, "ytd", "1d");
  const p = r?.indicators?.quote?.[0]?.close;
  if (!p) return "Dati incompleti";

  let first = null, last = null;
  for (let v of p) {
    if (v != null) {
      if (first === null) first = v;
      last = v;
    }
  }
  if (first === null || last === null) return "Dati incompleti";
  return Number((((last - first) / first) * 100).toFixed(2));
}

/***********************
 * VARIAZIONE % SU N GIORNI
 ***********************/
function VARPER(ticker, giorni) {
  if (!ticker) return "Ticker?";
  if (!giorni || giorni < 1) return "Periodo?";

  const range = Math.max(giorni + 5, 30) + "d";
  const r = _fetchChart(ticker, range, "1d");
  const p = r?.indicators?.quote?.[0]?.close;
  if (!p) return "Dati incompleti";

  const clean = p.filter(v => v != null);
  if (clean.length <= giorni) return "Dati incompleti";

  const last = clean[clean.length - 1];
  const past = clean[clean.length - 1 - giorni];
  return Number((((last - past) / past) * 100).toFixed(2));
}

/***********************
 * MAX VALORE DA DATA
 * Parametri: ticker, range obbligatorio, dataInizio opzionale
 ***********************/
function MAXVAL(ticker, range, dataInizio) {
  return _maxCore(ticker, dataInizio, "value", range);
}

/***********************
 * DATA DEL MASSIMO
 ***********************/
function MAXDATE(ticker, range, dataInizio) {
  return _maxCore(ticker, dataInizio, "date", range);
}

/***********************
 * MAX INFO
 ***********************/
function MAXINFO(ticker, range, dataInizio) {
  return _maxCore(ticker, dataInizio, "full", range);
}

/***********************
 * CORE MASSIMO
 ***********************/
function _maxCore(ticker, dataInizio, mode, range="1y") {
  if (!ticker || !range) return "Ticker o range mancante";
  const r = _fetchChart(ticker, range, "1d");
  if (!r) return "Errore Yahoo";

  const prices = r.indicators?.quote?.[0]?.close;
  const ts = r.timestamp;
  if (!prices || !ts) return "Dati incompleti";

  let startTs = 0;
  if (dataInizio) {
    const d = new Date(dataInizio);
    if (!isNaN(d.getTime())) startTs = Math.floor(d.getTime() / 1000);
  }

  let maxP = -Infinity, maxT = null;
  for (let i = 0; i < prices.length; i++) {
    if (prices[i] == null || ts[i] < startTs) continue;
    if (prices[i] > maxP) {
      maxP = prices[i];
      maxT = ts[i];
    }
  }
  if (maxT === null) return "No dati";

  const ultimo = ULTIMO(ticker);
  const drawdown = typeof ultimo === "number" ? Number((((ultimo - maxP) / maxP) * 100).toFixed(2)) : "—";

  const dataMax = Utilities.formatDate(new Date(maxT*1000), Session.getScriptTimeZone(), "dd/MM/yyyy");

  if (mode === "value") return Number(maxP.toFixed(4));
  if (mode === "date") return dataMax;

  return [
    ["Ticker", ticker],
    ["Prezzo attuale", ultimo],
    ["Var. oggi %", VARGIORN(ticker)],
    ["Massimo", Number(maxP.toFixed(4))],
    ["Data massimo", dataMax],
    ["Drawdown %", drawdown],
    ["YTD %", YTD(ticker)]
  ];
}

/***********************
 * FORZA REFRESH
 ***********************/
function FORZA_REFRESH() {
  const ss = SpreadsheetApp.getActive();
  let sh = ss.getSheetByName("Refresh");
  if (!sh) {
    sh = ss.insertSheet("Refresh");
    sh.hideSheet();
  }
  sh.getRange("A1").setValue(new Date());
}

Ora, sempre da Apps Script andate sull’icona ad orologio Attivatori.

  • Scegliere la funzione da eseguire, selezionando: FORZA_REFRESH
  • Selezionare l’origine dell’evento, selezionando: Evento vincolato a specifiche temporali
  • Selezionare il tipo di attivatore basato sull’orario, selezionando: Timer in minuti
  • Selezionare intervallo in minuti, selezionando: Ogni 30 minuti

Nel foglio, verrà creato in automatico un nuovo sheet che si chiamerà Refresh e nella cella A1 comparirà la data attuale che verrà refreshata ogni 30 minuti.

Sarà poi sufficiente modificare la formula così:

=ULTIMO(SWDA.MI; Refresh!A1)
=VARGIORN(SWDA.MI; Refresh!A1)