-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathdatabase.py
148 lines (133 loc) · 5.8 KB
/
database.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import sqlite3
def create_connection():
"""Create or connect to the SQLite database with foreign keys enabled."""
try:
conn = sqlite3.connect("trading_data.db")
conn.execute("PRAGMA foreign_keys = ON;") # Enforce foreign key constraints
return conn
except sqlite3.Error as e:
print(f"SQLite Error: {e}")
return None
def initialize_database():
"""Creates tables and ensures schema is correct."""
conn = create_connection()
if conn is None:
print("Error: Failed to create database connection.")
return
cursor = conn.cursor()
try:
cursor.executescript("""
-- Fundamentals Table
CREATE TABLE IF NOT EXISTS fundamentals (
ticker TEXT PRIMARY KEY,
sector TEXT DEFAULT NULL,
pe_ratio REAL DEFAULT NULL,
market_cap BIGINT DEFAULT NULL,
revenue REAL DEFAULT NULL,
beta REAL DEFAULT NULL,
roa REAL DEFAULT NULL,
roe REAL DEFAULT NULL,
cluster INTEGER DEFAULT NULL
);
-- Technical Indicators Table
CREATE TABLE IF NOT EXISTS technicals (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ticker TEXT NOT NULL,
date DATE NOT NULL,
open REAL,
high REAL,
low REAL,
close REAL,
adj_close REAL,
volume BIGINT,
ma50 REAL,
ma200 REAL,
macd REAL,
signal_line REAL,
rsi REAL,
upper_band REAL,
lower_band REAL,
adx REAL,
obv BIGINT,
pivot REAL,
r1 REAL,
s1 REAL,
UNIQUE(ticker, date),
FOREIGN KEY (ticker) REFERENCES fundamentals(ticker) ON DELETE CASCADE
);
-- Macroeconomic Data Table
CREATE TABLE IF NOT EXISTS macroeconomic_data (
id INTEGER PRIMARY KEY AUTOINCREMENT,
indicator TEXT NOT NULL,
date DATE NOT NULL,
value REAL,
UNIQUE(indicator, date)
);
-- News Articles Table (Stores news per ticker)
CREATE TABLE IF NOT EXISTS news (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ticker TEXT NOT NULL, -- Ensures news is associated with the correct stock
source TEXT,
title TEXT NOT NULL,
description TEXT,
url TEXT NOT NULL UNIQUE,
published_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE(ticker, title, published_at),
FOREIGN KEY (ticker) REFERENCES fundamentals(ticker) ON DELETE CASCADE
);
-- Reddit Mentions Table (Updated to include 'content')
CREATE TABLE IF NOT EXISTS reddit_mentions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ticker TEXT NOT NULL,
title TEXT NOT NULL,
content TEXT DEFAULT '', -- Prevents KeyError
upvotes INTEGER DEFAULT 0,
upvote_ratio REAL DEFAULT 0.0,
date DATE NOT NULL DEFAULT (DATE('now')),
link TEXT DEFAULT '',
UNIQUE(ticker, title, date),
FOREIGN KEY (ticker) REFERENCES fundamentals(ticker) ON DELETE CASCADE
);
-- Trade Signals Table
CREATE TABLE IF NOT EXISTS trade_signals (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ticker TEXT NOT NULL,
signal TEXT NOT NULL CHECK(signal IN ('BUY', 'SELL', 'HOLD')),
buy_price NUMERIC(10,2),
sell_price NUMERIC(10,2),
stop_loss NUMERIC(10,2),
date_generated DATE NOT NULL DEFAULT (DATE('now')),
FOREIGN KEY (ticker) REFERENCES fundamentals(ticker) ON DELETE CASCADE
);
-- Indexes for Performance Optimization
CREATE INDEX IF NOT EXISTS idx_technicals_ticker_date ON technicals (ticker, date);
CREATE INDEX IF NOT EXISTS idx_news_ticker_date ON news (ticker, published_at);
CREATE INDEX IF NOT EXISTS idx_reddit_ticker_date ON reddit_mentions (ticker, date);
CREATE INDEX IF NOT EXISTS idx_signals_ticker ON trade_signals (ticker);
CREATE INDEX IF NOT EXISTS idx_macro_indicator_date ON macroeconomic_data (indicator, date);
""")
# Preload 100 stock tickers with default values
tickers = [
"AAPL", "MSFT", "GOOGL", "AMZN", "TSLA", "META", "NVDA", "NFLX", "JPM", "V",
"BA", "IBM", "DIS", "INTC", "WMT", "KO", "PEP", "ORCL", "MCD", "NKE",
"CVX", "XOM", "PFE", "UNH", "ABT", "AXP", "CAT", "RTX", "GS", "HD",
"PG", "SPG", "LMT", "MMM", "BMY", "MDT", "DHR", "GE", "LUV", "CSCO",
"SCHW", "COST", "TMO", "VZ", "ADBE", "CVS", "SYK", "SBUX", "TRV",
"AMT", "MO", "BAX", "T", "LRCX", "CTSH", "ISRG", "UAL", "AMGN", "REGN",
"CSX", "GILD", "FISV", "EQIX", "F", "ZM", "MRK", "ZTS", "VLO", "AIG",
"SCHW", "HCA", "MS", "KHC", "COP", "WM", "CCI", "DOW", "TGT", "STT",
"BK", "CME", "WFC", "MCK", "HUM", "CTVA", "ALL", "ICE", "MA", "CHTR",
"AMAT", "ADI", "WDC", "BKR", "NSC", "STZ", "APD", "DLR", "NOC", "CSGP",
"NEM", "FIS", "CTXS", "LVS", "EXPE", "USB", "PGR", "TFX", "MAR", "RSG"
]
cursor.executemany("""
INSERT OR IGNORE INTO fundamentals (ticker, sector, pe_ratio, market_cap, revenue, beta, roa, roe, cluster)
VALUES (?, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
""", [(t,) for t in tickers])
conn.commit()
except sqlite3.Error as e:
print(f"SQLite Error: {e}")
finally:
conn.close()
# Initialize the updated database
initialize_database()