FinancialData: quando non trovi una libreria, il grafico te lo costruisci da solo

Ricostruzione illustrativa di una postazione con ambiente Visual Basic, grafico candlestick e schizzi delle candele su un taccuino.

Come un progetto universitario in Visual Basic 6 mi portò a realizzare artigianalmente un grafico candlestick, trasformando un limite tecnico nella parte più interessante dell’applicazione.

Tempo di lettura: circa 5 minuti

Un esame di informatica e un progetto ambizioso

Durante il secondo anno di università, per sostenere l’esame di Informatica Generale, sviluppai un’applicazione che chiamai FinancialData.

Il progetto prevedeva la realizzazione di un software per la gestione e l’analisi di dati finanziari. Non bastava visualizzare una tabella di quotazioni: bisognava consentire all’utente di interrogare i dati, elaborarli, calcolare indicatori e rappresentare graficamente l’andamento dei titoli.

Per realizzarlo decisi di studiare Visual Basic 6, un linguaggio che permetteva di sviluppare applicazioni Windows combinando interfacce grafiche, accesso ai database e logica di programmazione.

Il lavoro comprendeva diversi elementi:

  • Gestione e interrogazione dei dati finanziari.
  • Selezione dei titoli e degli intervalli temporali.
  • Elaborazione di indicatori e indici di analisi.
  • Visualizzazione delle serie storiche.
  • Produzione di grafici a barre, lineari e tridimensionali.
  • Realizzazione di un grafico finanziario candlestick.

Quest’ultimo punto sarebbe diventato la parte più interessante dell’intero progetto.

Il problema: come realizzare un grafico candlestick?

Per buona parte delle rappresentazioni grafiche potevo utilizzare i componenti disponibili nell’ambiente di sviluppo, tra cui Microsoft Chart.

Ma il candlestick era diverso.

Si tratta di un grafico particolarmente utilizzato nell’analisi tecnica dei mercati finanziari, perché permette di rappresentare quattro valori contemporaneamente per ogni seduta di contrattazione:

  • Apertura: il primo prezzo registrato.
  • Chiusura: l’ultimo prezzo registrato.
  • Massimo: il prezzo più alto raggiunto.
  • Minimo: il prezzo più basso raggiunto.

Ogni candela è composta da un corpo rettangolare, che rappresenta la distanza tra apertura e chiusura, e da due possibili estensioni verticali, chiamate ombre, che indicano i valori massimo e minimo.

Il colore del corpo permette inoltre di distinguere immediatamente una seduta positiva da una negativa.

Il problema era che non riuscivo a trovare una libreria o un componente disponibile che generasse quel grafico.

Oggi siamo abituati a utilizzare librerie grafiche specializzate, spesso capaci di produrre visualizzazioni complesse con poche istruzioni. Allora, almeno con gli strumenti che avevo a disposizione, non era così semplice.

Avrei potuto rinunciare a quella funzionalità, concentrandomi sugli altri grafici.

Ma il candlestick faceva parte degli obiettivi del progetto e non volevo eliminarlo soltanto perché non disponevo di uno strumento già pronto.

Così mi venne un’idea: se non potevo generare automaticamente le candele, avrei potuto disegnarle io, una per una.

La soluzione artigianale: trasformare i prezzi in pixel

Il primo problema da affrontare non era il disegno delle candele, ma la conversione dei valori finanziari in coordinate grafiche.

Un prezzo, ad esempio 125,50, è un numero. Lo schermo, invece, lavora con posizioni orizzontali e verticali.

Dovevo quindi costruire un sistema capace di trasformare ogni quotazione nella corretta posizione all’interno del grafico.

La soluzione consisteva nell’individuare il valore massimo e quello minimo della serie selezionata, calcolare l’intervallo complessivo e distribuirlo sull’altezza disponibile.

Nel codice originale, contenuto nel modulo SerieStoriche.frm, troviamo:

dblCandleUnit = (recCandle(0) - recCandle(1)) / 400
dblCandleMin = recCandle(1)

Il valore massimo meno il minimo viene diviso per 400, cioè l’ampiezza verticale in pixel destinata alla rappresentazione dei prezzi.

Una volta stabilita questa unità di misura, ogni valore viene convertito nella propria coordinata verticale:

udtCandle(i).Apertura = 430 - CInt( _
    (recSerie(1) - recCandle(1)) / dblCandleUnit)

udtCandle(i).Alto = 430 - CInt( _
    (recSerie(2) - recCandle(1)) / dblCandleUnit)

udtCandle(i).Basso = 430 - CInt( _
    (recSerie(3) - recCandle(1)) / dblCandleUnit)

udtCandle(i).Ultimo = 430 - CInt( _
    (recSerie(4) - recCandle(1)) / dblCandleUnit)

Il valore 430 rappresenta il riferimento verticale inferiore del grafico.

La sottrazione è necessaria perché, nelle coordinate grafiche di Visual Basic, l’asse verticale cresce dall’alto verso il basso, mentre in un grafico finanziario i prezzi maggiori devono apparire più in alto.

In altre parole, avevo realizzato una trasformazione matematica che permetteva di passare dal valore finanziario alla sua posizione sullo schermo.

Era il primo passo per costruire autonomamente il grafico.

Disegnare una candela con due istruzioni

Una volta ottenute le coordinate, bisognava rappresentare graficamente ogni seduta.

Ed è qui che entra in gioco la parte del codice che, ancora oggi, considero la più interessante.

Nel file originale CandleStick.frm avevo scritto:

If udtCandle(i).Apertura > udtCandle(i).Ultimo Then
    intColore = 15
Else
    intColore = 0
End If

Line ((intCol + intCandleMezzo), udtCandle(i).Alto)- _
     ((intCol + intCandleMezzo), udtCandle(i).Basso), QBColor(0)

Line (intCol, udtCandle(i).Apertura)- _
     ((intCol + intCandleLargh), udtCandle(i).Ultimo), _
     QBColor(intColore), BF

Il funzionamento è sorprendentemente semplice.

Prima fase: determinare il colore.

Il programma confronta le coordinate verticali già calcolate per apertura e chiusura, non i prezzi originali. Poiché l’asse verticale dello schermo cresce verso il basso, udtCandle(i).Apertura > udtCandle(i).Ultimo significa che il prezzo di chiusura è superiore a quello di apertura: la seduta è positiva e il corpo della candela viene disegnato in bianco (QBColor(15)). In caso contrario viene scelto il nero (QBColor(0)); se apertura e chiusura coincidono, il corpo ha altezza nulla.

Seconda fase: disegnare l’ombra.

La prima istruzione Line traccia un segmento verticale tra il massimo e il minimo della giornata.

Terza fase: disegnare il corpo.

La seconda istruzione Line sfrutta l’opzione BF, abbreviazione di Box Filled, per generare un rettangolo pieno tra le coordinate di apertura e chiusura.

Ed ecco la candela.

Niente componente specializzato, niente libreria finanziaria, niente generatore automatico: soltanto coordinate, segmenti e rettangoli.

Naturalmente una candela non basta. Bisognava ripetere il procedimento per tutte le osservazioni, calcolando anche lo spazio occupato da ciascuna.

Adattare il grafico al numero di osservazioni

Un altro problema era la distribuzione delle candele sull’asse orizzontale.

Se l’utente selezionava poche sedute, le candele potevano essere più larghe. Se ne selezionava molte, dovevano diventare più strette.

Anche questa parte era calcolata direttamente dal programma:

intCandleLargh = Int((700 / intAmpiezza) * (3 / 5))
intCandleDist = Int((700 / intAmpiezza) * (2 / 5))

L’area orizzontale disponibile veniva suddivisa tra le osservazioni, destinando tre quinti dello spazio alla larghezza di ogni candela e due quinti alla distanza dalla successiva.

Il programma costruiva inoltre gli assi, le etichette temporali e la scala dei valori. Avevo previsto controlli sui dati incompleti e limitazioni sul numero di osservazioni rappresentabili per mantenere il grafico leggibile.

Non era quindi soltanto una sequenza di rettangoli: era un piccolo sistema di visualizzazione finanziaria.

Quando il professore rimase sorpreso

Durante la presentazione del progetto, il grafico candlestick attirò particolarmente l’attenzione del professore.

Rimase stupito dal modo in cui ero riuscito a realizzarlo.

Credo che l’aspetto interessante fosse proprio questo: non avevo trovato un componente capace di svolgere il lavoro e, invece di rinunciare alla funzionalità, avevo affrontato il problema scomponendolo nei suoi elementi fondamentali.

Un candlestick, osservato dal punto di vista di chi deve programmarlo, non è altro che un insieme di linee, rettangoli, colori e coordinate.

Compreso questo, il problema diventava risolvibile.

Per me fu una soddisfazione particolare. Avevo studiato Visual Basic per sostenere un esame, ma mi ero ritrovato a realizzare qualcosa che richiedeva anche inventiva e capacità di ragionamento.

La lezione che mi porto dietro

A distanza di anni, riguardando il sorgente di FinancialData, mi colpisce soprattutto il metodo con cui avevo affrontato il problema.

Oggi utilizzo tecnologie molto diverse: Excel, Power Query, VBA, Python e strumenti di intelligenza artificiale. Spesso posso contare su librerie, framework e servizi che rendono più semplice realizzare funzionalità anche molto sofisticate.

Ma il principio rimane lo stesso.

Quando una soluzione pronta non esiste, oppure non è adatta al problema che devo risolvere, bisogna capire come funziona ciò che vogliamo ottenere e provare a costruirlo con gli strumenti disponibili.

Il grafico candlestick di FinancialData rappresenta bene questo approccio.

Non era necessariamente la soluzione più elegante secondo gli standard attuali, ma era una soluzione concreta, costruita attraverso un ragionamento che trasformava un problema apparentemente complesso in una serie di operazioni elementari.

Non avevo trovato la libreria che mi serviva. Così, invece di rinunciare al grafico, ho trovato il modo di disegnarlo da solo.

Ed è probabilmente questa la parte del progetto che ricordo con maggiore soddisfazione.


Il codice sorgente originale

Il progetto FinancialData è ancora disponibile su GitHub, completo dei sorgenti Visual Basic 6.

FinancialData — progetto realizzato per l’esame di Informatica Generale, secondo anno di università. Linguaggio: Microsoft Visual Basic 6.

Commenti

Lascia un commento

Scopri di più da Gianluca Tavella

Abbonati ora per continuare a leggere e avere accesso all'archivio completo.

Continua a leggere