Migrate data pipeline from SQLite to PostgreSQL + Docker setup

- Add db.py PostgreSQL abstraction layer (connection, upsert, table mgmt)
- Replace sqlite3 with psycopg2 in: live_candle_fetcher, resampler,
  data_fetcher, fetch_history, import_csv, indicators, base_strategy
- Sanitize table names (colons -> underscores) for PostgreSQL compat
- Replace INSERT OR REPLACE with ON CONFLICT upserts
- Replace pandas to_sql() with batch upsert_candles()
- Add scripts: resampler_loop, gap_detector, backup_runner, cron_scheduler
- Add migrate_sqlite_to_pg.py for one-time data migration
- Add Dockerfile, docker-compose.yml, supervisord.conf
- Add postgres/postgresql.conf tuned for 4GB RAM (Synology DS1513+)
- Add .dockerignore, .env.docker.example, secrets template
- Update requirements.txt (psycopg2-binary), .gitignore
- Add MIGRATION_PLAN.md with full plan and todo list
This commit is contained in:
DiTus
2026-07-30 22:14:31 +02:00
parent ade9b708a2
commit 7d702e9cbd
24 changed files with 1013 additions and 222 deletions

View File

@ -1,10 +1,10 @@
import requests
import json
import sqlite3
import db
import time
from datetime import datetime, timezone
DB_PATH = "_data/market_data.db"
DB_PATH = os.environ.get("PG_CONN_STR", "postgresql://hyper:hyper@localhost:5432/hyper")
URL = "https://api.hyperliquid.xyz/info"
def fetch_historical_candles(coin, start_ms, end_ms, interval="1m"):
@ -37,22 +37,10 @@ def fetch_historical_candles(coin, start_ms, end_ms, interval="1m"):
def write_candles_to_db(coin, candles, interval="1m"):
"""Write candles to the database."""
table_name = coin + "_" + interval
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
# Ensure table exists
cursor.execute(f'''
CREATE TABLE IF NOT EXISTS "{table_name}" (
datetime_utc TEXT,
timestamp_ms INTEGER PRIMARY KEY,
open REAL,
high REAL,
low REAL,
close REAL,
volume REAL,
number_of_trades INTEGER
)
''')
table_name = db.sanitize_table_name(coin, interval)
conn = db.get_connection()
db.create_candle_table(conn, table_name)
records = []
for candle in candles:
record = (
datetime.fromtimestamp(candle['t'] / 1000, tz=timezone.utc).strftime('%Y-%m-%d %H:%M:%S'),
@ -60,22 +48,16 @@ def write_candles_to_db(coin, candles, interval="1m"):
candle.get('o'), candle.get('h'), candle.get('l'), candle.get('c'),
candle.get('v'), candle.get('n')
)
cursor.execute(f'''
INSERT OR REPLACE INTO "{table_name}" (datetime_utc, timestamp_ms, open, high, low, close, volume, number_of_trades)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
''', record)
conn.commit()
records.append(record)
db.upsert_candles(conn, table_name, records)
conn.close()
def get_last_timestamp(coin):
"""Get the most recent timestamp from the database."""
table_name = coin + "_1m"
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
table_name = db.sanitize_table_name(coin, "1m")
conn = db.get_connection()
try:
cursor.execute(f'SELECT MAX(timestamp_ms) FROM "{table_name}"')
result = cursor.fetchone()
return int(result[0]) if result and result[0] is not None else None
return db.get_last_timestamp(conn, table_name)
except:
return None
finally: