Learn how to create a price database for crypto, forex, futures, and stocks in PostgreSQL using Python and SQLAlchemy.
You should already know how to connect to a PostgreSQL Database Using SQLAlchemy), and you can download the code for this post at the Analyzing Alpha GitHub Repo.
Steps to Create the Price Database
Below is the Python code demonstrated in the video and Jupyter notebook to create the database in the following entity-relationship diagram (ERD):
1. Get Imports
import enum
import numpy as np
import pandas as pd
from sqlalchemy import BigInteger, Boolean, Column, \
Date, DateTime, Enum, Float, ForeignKey, Integer, \
String, UniqueConstraint, and_, func
from sqlalchemy.orm import relationship
from psql import Base, db, session
Let’s create a new class that inherits from enum to create constants that we can enumerate over for each of the markets that we’ll analyze.
2. Create Market Class
class Market(enum.Enum):
crypto = 'crypto'
stock = 'stock'
forex = 'forex'
futures = 'futures'
3. Create SQLAlchemy Classes & Tables
We’ll create two tables. The first is the symbol and minute_bar tables, which have a parent/child relationship. For each table, we create a class and inherit it from Base, which lets SQLAlchemy know this is an SQLAlchemy class/table.
class Symbol(Base):
__tablename__ = 'symbol'
id = Column(Integer, primary_key=True, autoincrement=True)
ticker = Column(String(50), nullable=False)
name = Column(String(200), nullable=False)
market = Column(Enum(Market), nullable=False)
active = Column(Boolean, nullable=False)
We’ll create a relationship on the minute_bar table that utilizes backref. SQLAlchemy understands to look at the classes and identify the type of relationship that exists. In our case, it’s a one-to-many relationship. Additionally, we create UniqueConstraint on the symbol_id and date — in other words, we should only have one bar per date per symbol.
class MinuteBar(Base):
__tablename__ = 'minute_bar'
id = Column(BigInteger, primary_key=True)
date = Column(DateTime, nullable=False)
open = Column(Float)
high = Column(Float)
low = Column(Float)
close = Column(Float)
volume = Column(Float)
symbol_id = Column(Integer,
ForeignKey('symbol.id',
onupdate="CASCADE",
ondelete="CASCADE"),
nullable=False)
symbol = relationship('Symbol', backref='minute_bars')
UniqueConstraint(symbol_id, date)
4. Create the Database
With our table classes created, let’s create a function that creates our database. We use the Base metadata to create all of our classes that inherit from Base.
def create():
Base.metadata.create_all(db)
create()