Ora aver introdotto l’idea alla base di un securities master database, vediamo è ora come implementarne uno. Per questo faremo uso di due tecnologie open source: il database MySQL e il linguaggio di programmazione Python. Alla fine di questo articolo avrete un vero e proprio database master di titoli azionari con cui condurre ulteriori analisi alla ricerca di una strategia di trading quantitativo.

I vantaggi di un Securities Master Database

Prima di iniziare, ricapitoliamo i vantaggi che si ottengo grazie all’introduzione di un securities master database nel nostro sistema di trading quantitativo:

  • Velocità – con i dati azionari memorazzati su un rigido locale, qualsiasi applicazione di analisi dati (come pandas) può accedere rapidamente ai dati senza dover eseguire lente operazioni di input / output (I / O) attraverso un collegamento di rete latente.
  • Fonti Multiple: i securities master database consentono la memorizzazione diretta da più sorgenti dati per lo stesso ticker. Quindi possiamo aggiungere un codice personalizzato per la correzione degli errori e / o tracciare i dati che devono essere controllati manualmente.
  • Tempo di inattività – Se ci affidiamo a una connessione Internet per i nostri dati, nel caso il fornitore (per qualsiasi motivo) stia affrontando un  periodo di inattività, non sarà possibile effettuare ricerche. Un database locale, con un sistema di backup, è sempre disponibile.
  • Meta-dati: un securities master database permette di memorizzare metadati sulle informazioni del nostro ticker. Possiamo includere tabelle degli exchange, fornitori e simboli di corrispondenza, aiutandoci a minimizzare gli errori dalle sorgenti dati.
 Esistono molti altri motivi per archiviare i dati localmente (o almeno su un server remoto) anziché fare affidamento sulle connessioni API ad un fornitore di dati. Un securities master fornisce il modello su cui costruire l’intero archivio dati delle nostre applicazioni di trading algoritmico. Tuttavia, ai fini di questo articolo ci concentreremo sulla memorizzazione dei dati storici giornalieri.
 

MySQL per i Securities Master Database

Per costruire ed interagire con un securities master database si può utilizzare MySQL e Python/pandas. Non mi soffermerò sulle specifiche di installazione di ciascuno di questi strumenti, poiché la procedura di installazione è piuttosto specifica per ogni piattaforma. Tuttavia, ti indicherò alcune guide che ti saranno sicuramente di aiuto per installare il software.

Installare MySQL

Per installare MySQL, è necessario selezionare la piattaforma appropriata:

  • Windows – Per le informazioni sulla procedura di installazione  di MySQL su Microsoft Windows, si può consultare la documentazione di MySQL. Se vuoi scaricare i file binari disponibili per Windows, puoi consultare questa pagina.
  • Mac OSX: è possibile scaricare i file binari per Mac OSX nella pagina dei download di MySQL. In alternativa, puoi installare MySQL tramite homebrew.
  • Linux / UNIX: puoi scegliere se scaricare un file binario dalla tua distribuzione o compilare dai codici sorgente. Su un sistema Debian / Ubuntu puoi digitare sudo apt-get install mysql-server. Se si utilizza una distribuzione basata su RPM come Fedora o Cent OS, è possibile digitare yum install mysql-server.

Creare un nuovo database e utente

Ora che MySQL è installato sul tuo sistema, possiamo creare un nuovo database e un utente per interagire con esso. All’installazione ti verrà richiesta una password di root. Per accedere a MySQL dalla riga di comando, si può utilizzare il seguente comando e inserire la password:

$ mysql -u root -p

Una volta effettuato l’accesso a MySQL, puoi creare un nuovo database chiamato securities_master e selezionarlo:

mysql> CREATE DATABASE securities_master; 
mysql> USE securities_master;
I database documentali/NoSQL, sebbene non siano un nuovo concetto, negli ultimi anni hanno acquisito una notevole importanza grazie a loro utilizzo da parte dei giganti del web come Google, Facebook e Twitter. Differiscono sostanzialmente dai sistemi RDBMS in quanto non esiste alcun concetto di schemi di tabelle. Invece, ci sono collezioni e documenti, che sono le analogie più vicine, rispettivamente, alle tabelle e ai record. Esiste un’ampia tassonomia di archivi documentali, la cui discussione è ben al di fuori di questo articolo! Tuttavia, alcuni delle soluzioni più popolari sono MongoDBCassandra e CouchDB. I database documentali, nelle applicazioni finanziarie, sono adatti principalmente ai dati fondamentali o ai metadati. I dati fondamentali per le attività finanziarie sono disponibili in molte forme, come azioni aziendali, dichiarazioni di guadagni, archivi SEC ecc. Pertanto, la natura senza schema dei DB NoSQL è particolarmente adatta. Tuttavia, i DB NoSQL non sono ben progettati per le serie temporali come i dati sui prezzi ad alta risoluzione e quindi non li prenderemo in considerazione per tale scopo.

Una volta creato un database è necessario aggiungere un nuovo utente per interagire con il database. Anche se è possibile utilizzare l’utente root, è considerato una cattiva pratica dal punto di vista della sicurezza, in quanto garantisce troppe autorizzazioni e può portare a un sistema compromesso. Su una macchina locale questo è per lo più irrilevante, ma in un ambiente di produzione remoto sarà certamente necessario creare un utente con autorizzazioni ridotte. In questo caso il nostro utente verrà chiamato sec_user. Ricordarsi di sostituire ‘password’ con una password sicura:

mysql> CREATE USER 'sec_user'@'localhost' IDENTIFIED BY 'password'; 
mysql> GRANT ALL PRIVILEGES ON securities_master.* TO 'sec_user'@'localhost'; 
mysql> FLUSH PRIVILEGES;

Con le tre righe precedenti si crea e si autorizza l’utente ad usare il db ‘securities_master’ e si applica tali privilegi. D’ora in poi qualsiasi interazione che si verifica con il database si dovrà far uso dell’utente ‘sec_user’.

Progettare lo schema per i Securities Master Azionari

Dopo aver installato MySQL e configurato un utente con cui interagire con il nostro database. In questa fase siamo pronti a costruire le tabelle necessarie per memorizzare i nostri dati finanziari. Per un semplice e diretto securities master azionario sono sufficienti quattro tabelle:
  • Exchange – La tabella elenca gli exchange da cui vogliamo ottenere le informazioni sui prezzi delle azioni. In questo caso sarà quasi esclusivamente la Borsa di New York (NYSE) e la National Association of Securities Dealers Automated Quotations (NASDAQ).
  • DataVendor – questa tabella elenca le informazioni sui fornitori di dati dei prezzi storici. Useremo Yahoo Finance per trovare i nostri dati di fine giornata (EOD). Introducendo questa tabella, rendiamo semplice aggiungere altri fornitori, se necessario, come ad esempio Google Finance.
  • Symbol: la tabella dei simboli memorizza l’elenco dei simboli dei ticker e delle informazioni aziendali. In questo momento eviteremo problemi come classi di azioni differenti e nomi di simboli multipli. Tratteremo tali questioni in articoli successivi!
  • DailyPrice – Questa tabella memorizza le informazioni dei prezzo giornaliero per ogni security. Può diventare molto grande se vengono aggiunti molti titoli. Quindi è necessario ottimizzare le prestazioni.
MySQL è un database estremamente flessibile in quanto consente di personalizzare la modalità di archiviazione dei dati tramite vari tipi di tabelle.  Le più usate sono senza dubbio le MyISAM e InnoDB. Anche se non entrerò nei dettagli dei vari tipi di tabelle gestite da MySQL (ce ne sono molte!), si può dire che MyISAM è più utile per una rapida lettura (come l’interrogazione sulle grandi quantità di informazioni relative ai prezzi), ma non supporta le transazioni (necessarie per il rollback completo di un’operazione a più passaggi che può fallire durante l’elaborazione). InnoDB permette la gestione delle foreign key e della transazionalità, con le quali è possibile creare una base di dati relazionale e transazionale, ma sono più lente a causa delle funzionalità aggiuntive di cui dispongono.. InnoDB consente inoltre il blocco a livello di riga durante le operazioni di scrittura, mentre MyISAM blocca l’intera tabella durante la scrittura. Questo può avere problemi di prestazioni quando si scrivono molte informazioni su punti arbitrari nella tabella (come con le istruzioni UPDATE). Questo è un argomento molto vasto, quindi rimando la discussione per un’altro articolo. Utilizzeremo InnoDB poiché è nativamente più sicuro per le transazioni e offre il blocco a livello di riga. Nel caso una tabella fosse lenta da leggere, possiamo in prima analisi creare degli indici e solo nel caso le prestazioni fossero ancora poco soddisfacenti si procederebbe alla modifica del tipo di tabella. Tutte le nostre tabelle utilizzeranno il set di caratteri UTF-8, poiché desideriamo supportare gli exchange internazionali. Puoi leggere ulteriori informazioni sulla codifica UTF-8 in questa pagina di Wikipedia. Iniziamo con schema e l’istruzione CREATE TABLE del linguaggio SQL per creazione della tabella exchange. Questa tabella memorizza la sigla e il nome dello exchange (ad esempio NYSE – New York Stock Exchange) così come la posizione geografica. Prevede anche una valuta e una differenza di fuso orario da UTC. Per scopi interni memorizziamo anche una data di creazione e dell’ultimo aggiornamento. Infine, impostiamo la chiave dell’indice primario come un numero intero a incremento automatico (che è sufficiente per gestire i record 232):
CREATE TABLE `exchange` (
  `id` int NOT NULL AUTO_INCREMENT,
  `abbrev` varchar(32) NOT NULL,
  `name` varchar(255) NOT NULL,
  `city` varchar(255) NULL,
  `country` varchar(255) NULL,
  `currency` varchar(64) NULL,
  `timezone_offset` time NULL,
  `created_date` datetime NOT NULL,
  `last_updated_date` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
Di seguito lo schema e l’istruzione CREATE TABLE di SQL per la tabelladata_vendor. Questa memorizza il nome, il sito web e l’email del fornitore dei dati. In caso di necessità potremmo aggiungere più informazioni, come l’API endpoint URL:
CREATE TABLE `data_vendor` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(64) NOT NULL,
  `website_url` varchar(255) NULL,
  `support_email` varchar(255) NULL,
  `created_date` datetime NOT NULL,
  `last_updated_date` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

Successivamente si passa allo schema e l’istruzione CREATE TABLE di SQL per la tabella symbol. Questa tabella contiene un link alla foreign key di un exchange (in questo articolo ci focalizziamo solamente sui strumenti tradati degli exchange), un simbolo di  ticker (ad esempio GOOG), il tipo di strumento (‘azione’ o ‘indice’), il nome del titolo azionario o dell’indici del mercato, il settore e la valuta di riferimento.

CREATE TABLE `symbol` (
  `id` int NOT NULL AUTO_INCREMENT,
  `exchange_id` int NULL,
  `ticker` varchar(32) NOT NULL,
  `instrument` varchar(64) NOT NULL,
  `name` varchar(255) NULL,
  `sector` varchar(255) NULL,
  `currency` varchar(32) NULL,
  `created_date` datetime NOT NULL,
  `last_updated_date` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `index_exchange_id` (`exchange_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
Infine si riporta lo schema e l’istruzione CREATE TABLE di SQL per la tabella daily_price. In questa tabella vengono memorizzati i dati storici dei prezzi. Il nome della tabella ha il prefisso daily_ poiché potremmo voler creare dati con diverse risoluzioni temporali (come minuti o secondi) e quindi gestirli in tabelle separate, in caso successivamente si vuole implementare strategie con frequenze più elevate. La tabella contiene due chiavi esterne: una verso il fornitore di dati e l’altra verso un simbolo. In questo modo si identifica in modo univoco il dato e ci consente di memorizzare nella stessa tabella gli stessi dati di prezzo per più fornitori. Per i nostri scopi memorizziamo anche la data del prezzo (vale a dire il periodo giornaliero su cui i dati OHLC sono validi) e le date di creazione e di ‘ultima aggiornamento. I campi rimanenti memorizzano i prezzi di apertura-massimo-minimo-chiusura ti-alti-bassi e il prezzo di chiusura aggiustato. Alcuni fornitori di dati calcola anche i dividendi e scissioni, e quindi memorizziamo il prezzo corretto nella colonna adj_close_price. Da notare che il tipo di dato corrisponde a decimal(19,4). Quando si tratta di dati finanziari è assolutamente necessario essere precisi. Se avessimo usato il tipo di dati float, avremmo riscontrato errori di arrotondamento dovuti alle modalità con le quali i dati float sono archiviati internamente. Il campo finale memorizza il volume di scambi giornalieri. Questo usa il tipo di dati bigint in modo da non troncare accidentalmente giorni di volumi estremamente elevati.
CREATE TABLE `daily_price` (
  `id` int NOT NULL AUTO_INCREMENT,
  `data_vendor_id` int NOT NULL,
  `symbol_id` int NOT NULL,
  `price_date` datetime NOT NULL,
  `created_date` datetime NOT NULL,
  `last_updated_date` datetime NOT NULL,
  `open_price` decimal(19,4) NULL,
  `high_price` decimal(19,4) NULL,
  `low_price` decimal(19,4) NULL,
  `close_price` decimal(19,4) NULL,
  `adj_close_price` decimal(19,4) NULL,
  `volume` bigint NULL,
  PRIMARY KEY (`id`),
  KEY `index_data_vendor_id` (`data_vendor_id`),
  KEY `index_synbol_id` (`symbol_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

Inserendo tutti i precedenti comandi SQL nella riga di comando MySQL verranno create le quattro tabelle previste.

Usare Python/Pandas per l'interazione con i Securities Master

Per iniziare a popolare il nostro database è necessario installare Python e Panda.

Installare Python/Pandas

Il modo migliore per installare Python consiste nell’utilizzare lo strumento dell’ambiente virtuale virtualenv e il gestore di pacchetti pip. Per installare Python in questo modo, è necessario attenersi alla seguente procedura:
  • Windows: visita la pagina Download Python per scaricare una versione di Python. Raccomando di usare l’ultima versione stabile disponibile di Python3. Una volta installato Python, è necessario scaricare setuptools. I passaggi finali consistono nell’eseguire easy_install pip e pip install virtualenv nella shell dei comandi.
  • Mac OSX – Il modo migliore per installare Python su Mac è usare homebrew. Quindi puoi installare Python tramite brew install python. Quindi è necessario eseguire pip install virtualenv per installare virtualenv.
  • Linux / UNIX – Per le distribuzioni di tipo Debian / Ubuntu sudo apt-get install python3-pip python3-dev per installare pip e le librerie di sviluppo Python. Quindi eseguire pip install virtualenv per installare virtualenv a livello globale.

Una volta installato virtualenv, è possibile creare un nuovo ambiente virtuale Python in una directory separata e quindi installare pandas (comandi per un ambiente UNIX):

$ cd ~
$ mkdir -p python-apps/trading
$ cd python-apps/trading
$ virtualenv .
$ source bin/activate
$ pip install pandas
Il passaggio finale è installare la libreria Python-MySQL. Sulle macchine Debian/Ubuntu bisogna eseguire i seguenti comandi:
sudo apt-get install default-libmysqlclient-dev
pip install mysqlclient
Ora siamo pronti per iniziare a interagire con il nostro database MySQL tramite Python e Pandas.

Usare un Object-Relational Mapper

Quelli di voi che hanno un background tecnico e sono familiari con lo sviluppo e la gestione di database, si potranno chiedere se sia più ragionevole utilizzare un Object-Relational Mapper (ORM). Un ORM consente agli oggetti all’interno di un linguaggio di programmazione di essere mappati direttamente nelle tabelle nei database in modo tale che il codice del programma sia completamente inconsapevole del motore di archiviazione sottostante. Tali software non sono esenti da errori, ma sono comunque in grado di far risparmiare molto tempo. Tuttavia, il risparmio di tempo viene generalmente a discapito delle prestazioni. Un ORM popolare per Python è SQLAlchemy. Permette di specificare lo schema del database all’interno di Python stesso e quindi genera automaticamente il codice CREATE TABLE. Poiché abbiamo scelto specificamente MySQL e sono interessato alle prestazioni, ho scelto di non utilizzare un ORM per questo articolo.

Ottenere i dati dei simboli listati

Iniziamo con il recuperare i simboli associati all’elenco di Standard & Poor’s dei 500 titoli a grande capitalizzazione, ad esempio S&P500. Naturalmente, questo è semplicemente un esempio. Se stai operando sul mercato italiano e desideri utilizzare gli indici domestici dell’Italia, puoi anche ottenere l’elenco delle società FTSE MIB quotate alla Borsa di Milano (LSE).

Inoltre Wikipedia elenca le componenti del S&P500. Analizzeremo questo sito web usando la libreria lxml di Python ed aggiungeremo direttamente il contenuto direttamente al database in MySQL. Innanzitutto assicurati che la libreria sia installata:

pip install lxml

Il seguente codice utilizzerà la libreria lxml e aggiungerà i simboli direttamente al database MySQL creato in precedenza. Ricordarsi di sostituire “password” con la password scelta durante la creazione dell’utente del db:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import datetime
import lxml.html
import PyMySQL as mdb

from math import ceil


def obtain_parse_wiki_snp500():
  """Download and parse the Wikipedia list of S&P500 
  constituents using requests and libxml.

  Returns a list of tuples for to add to MySQL."""

  # Stores the current time, for the created_at record
  now = datetime.datetime.utcnow()

  # Use libxml to download the list of S&P500 companies and obtain the symbol table
  page = lxml.html.parse('http://en.wikipedia.org/wiki/List_of_S%26P_500_companies')
  symbolslist = page.xpath('//table[1]/tr')[1:]

  # Obtain the symbol information for each row in the S&P500 constituent table
  symbols = []
  for symbol in symbolslist:
    tds = symbol.getchildren()
    sd = {'ticker': tds[0].getchildren()[0].text,
        'name': tds[1].getchildren()[0].text,
        'sector': tds[3].text}
    # Create a tuple (for the DB format) and append to the grand list
    symbols.append( (sd['ticker'], 'stock', sd['name'], 
      sd['sector'], 'USD', now, now) )
  return symbols

def insert_snp500_symbols(symbols):
  """Insert the S&P500 symbols into the MySQL database."""

  # Connect to the MySQL instance
  db_host = 'localhost'
  db_user = 'sec_user'
  db_pass = 'password'
  db_name = 'securities_master'
  con = mdb.connect(host=db_host, user=db_user, passwd=db_pass, db=db_name)

  # Create the insert strings
  column_str = "ticker, instrument, name, sector, currency, created_date, last_updated_date"
  insert_str = ("%s, " * 7)[:-2]
  final_str = "INSERT INTO symbol (%s) VALUES (%s)" % (column_str, insert_str)
  print(final_str, len(symbols))

  # Using the MySQL connection, carry out an INSERT INTO for every symbol
  with con: 
    cur = con.cursor()
    # This line avoids the MySQL MAX_PACKET_SIZE
    # Although of course it could be set larger!
    for i in range(0, int(ceil(len(symbols) / 100.0))):
      cur.executemany(final_str, symbols[i*100:(i+1)*100-1])

if __name__ == "__main__":
  symbols = obtain_parse_wiki_snp500()
  insert_snp500_symbols(symbols)

A questo punto tutti gli attuali 500 simboli che compongono l’indice S&P500 sono inseriti nel database. Il nostro prossimo obiettivo sarà quello di ottenere lo storico dei prezzi da diverse fonti e collegarli ai simboli appena salvati.

Recuperare i dati storici

Per ottenere i dati storici degli attuali titoli che compongono l’S&P500, dobbiamo prima interrogare il database per farci restituire l’elenco di tutti i simboli. Una volta ottenuto l’elenco dei simboli (insieme agli ID dei simboli), è possibile richiamare l’API di Yahoo Finance e scaricare lo storico dei prezzi da ciascun simbolo. Quindi possiamo inserire i dati nel database per ogni simboli ottenuto. Ecco il codice Python che effettua queste operazioni:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import datetime
import PyMySQL as mdb
from urllib.request import urlopen

# Obtain a database connection to the MySQL instance
db_host = 'localhost'
db_user = 'sec_user'
db_pass = 'password'
db_name = 'securities_master'
con = mdb.connect(db_host, db_user, db_pass, db_name)


def obtain_list_of_db_tickers():
    """Obtains a list of the ticker symbols in the database."""
    with con:
        cur = con.cursor()
        cur.execute("SELECT id, ticker FROM symbol")
        data = cur.fetchall()
        return [(d[0], d[1]) for d in data]


def get_daily_historic_data_yahoo(ticker,
                                  start_date=(2000, 1, 1),
                                  end_date=datetime.date.today().timetuple()[0:3]):
    """Obtains data from Yahoo Finance returns and a list of tuples.

  ticker: Yahoo Finance ticker symbol, e.g. "GOOG" for Google, Inc.
  start_date: Start date in (YYYY, M, D) format
  end_date: End date in (YYYY, M, D) format"""

    # Construct the Yahoo URL with the correct integer query parameters
    # for start and end dates. Note that some parameters are zero-based!
    yahoo_url = "http://ichart.finance.yahoo.com/table.csv?s=%s&a=%s&b=%s&c=%s&d=%s&e=%s&f=%s" % \
                (ticker, start_date[1] - 1, start_date[2], start_date[0], end_date[1] - 1, end_date[2], end_date[0])

    # Try connecting to Yahoo Finance and obtaining the data
    # On failure, print an error message.
    try:
        yf_data = urlopen(yahoo_url).readlines()[1:]  # Ignore the header
        prices = []
        for y in yf_data:
            p = y.strip().split(',')
            prices.append((datetime.datetime.strptime(p[0], '%Y-%m-%d'),
                           p[1], p[2], p[3], p[4], p[5], p[6]))
    except Exception as e:
        print("Could not download Yahoo data: %s" % e)
    return prices


def insert_daily_data_into_db(data_vendor_id, symbol_id, daily_data):
    """Takes a list of tuples of daily data and adds it to the
    MySQL database. Appends the vendor ID and symbol ID to the data.

    daily_data: List of tuples of the OHLC data (with
    adj_close and volume)"""

    # Create the time now
    now = datetime.datetime.utcnow()

    # Amend the data to include the vendor ID and symbol ID
    daily_data = [(data_vendor_id, symbol_id, d[0], now, now,
                   d[1], d[2], d[3], d[4], d[5], d[6]) for d in daily_data]

    # Create the insert strings
    column_str = """data_vendor_id, symbol_id, price_date, created_date, 
          last_updated_date, open_price, high_price, low_price, 
          close_price, volume, adj_close_price"""
    insert_str = ("%s, " * 11)[:-2]
    final_str = "INSERT INTO daily_price (%s) VALUES (%s)" % (column_str, insert_str)

    # Using the MySQL connection, carry out an INSERT INTO for every symbol
    with con:
        cur = con.cursor()
        cur.executemany(final_str, daily_data)


if __name__ == "__main__":
    # Loop over the tickers and insert the daily historical
    # data into the database
    tickers = obtain_list_of_db_tickers()
    for t in tickers:
        print("Adding data for %s" % t[1])
        yf_data = get_daily_historic_data_yahoo(t[1])
        insert_daily_data_into_db('1', t[0], yf_data)

Da notare che ci sono sicuramente molti per ottimizzare questo codice. Ad esempio si può utilizzare la libreria Python ScraPy per ottenere dei download ad elevata concorrenza, dato che ScraPy è basato sul framework ad eventi chiamato Twisted

Nel nostro codice ogni download viene eseguito in sequenza.

Interfaccia Python/Pandas per i dati dei prezzi

Ora che abbiamo scaricato lo storico dei prezzi per tutti i titoli che compongono l’S&P500, vogliamo poter accedere a questi dati tramite strutture logiche implementante in Python. La libreria pandas rende passaggio questo estremamente semplice. Ecco uno script per ottiene i dati OHLC del titolo  Google in un determinato periodo di tempo dal nostro database master dei titoli e restituisce il tail del dataset:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import pandas as pd
import pandas.io.sql as psql
import PyMySQL as mdb


# Connect to the MySQL instance
db_host = 'localhost'
db_user = 'sec_user'
db_pass = 'password'
db_name = 'securities_master'
con = mdb.connect(db_host, db_user, db_pass, db_name)

# Select all of the historic Google adjusted close data
sql = """SELECT dp.price_date, dp.adj_close_price
         FROM symbol AS sym
         INNER JOIN daily_price AS dp
         ON dp.symbol_id = sym.id
         WHERE sym.ticker = 'GOOG'
         ORDER BY dp.price_date ASC;"""

# Create a pandas dataframe from the SQL query
goog = psql.frame_query(sql, con=con, index_col='price_date')    

# Output the dataframe tail
print(goog.tail())

L’output dello script è il seguente:

price_date              adj_close_price
2013-05-20            908.53
2013-05-21            906.97
2013-05-22            889.42
2013-05-23            882.79
2013-05-24            873.32

Ovviamente questo è solo un semplice script, ma mostra tutte le potenzialità di un securities master archiviato localmente. Con tale approccio è possibile testare in modo estremamente rapido alcune strategie, poiché l’I / O dal database sarà notevolmente più veloce rispetto a quello effettuato tramite una connessione Internet.

Il prossimo passo è quello di automatizzare la raccolta di dati in modo che ogni simbolo abbia i dati OHLC aggiornati dopo la chiusura di ogni giorno di negoziazione. Utilizzando un programma di pianificazione delle attività come Windows Task Scheduler o crontab, questo processo può essere programmato per essere eseguito in background. Ci porterà un passo avanti verso la creazione di un sistema di trading completamente automatizzato.

Recommended Posts