copper-mind / app /inspect_db.py
ifieryarrows's picture
Sync from GitHub
f64b002 verified
"""
Quick database inspection utility.
Usage:
python -m app.inspect_db
"""
import argparse
import logging
from datetime import datetime, timedelta, timezone
from sqlalchemy import func, text
from app.db import SessionLocal, init_db, get_db_type
from app.models import NewsArticle, PriceBar, NewsSentiment, DailySentiment, AnalysisSnapshot
from app.settings import get_settings
logging.basicConfig(level=logging.INFO, format="%(message)s")
logger = logging.getLogger(__name__)
def inspect_database(verbose: bool = False):
"""Print database statistics."""
init_db()
print("\n" + "=" * 60)
print("COPPERMIND DATABASE INSPECTION")
print("=" * 60)
settings = get_settings()
# Database info
print(f"\n๐Ÿ“ Database: {settings.database_url.split('?')[0]}")
print(f" Type: {get_db_type()}")
with SessionLocal() as session:
# News articles
total_news = session.query(func.count(NewsArticle.id)).scalar()
news_7d = session.query(func.count(NewsArticle.id)).filter(
NewsArticle.published_at >= datetime.now(timezone.utc) - timedelta(days=7)
).scalar()
print(f"\n๐Ÿ“ฐ News Articles: {total_news}")
print(f" Last 7 days: {news_7d}")
if verbose and total_news > 0:
# Source breakdown
sources = session.query(
NewsArticle.source,
func.count(NewsArticle.id)
).group_by(NewsArticle.source).order_by(func.count(NewsArticle.id).desc()).limit(5).all()
print(" Top sources:")
for source, count in sources:
print(f" - {source or 'Unknown'}: {count}")
# Date range
earliest = session.query(func.min(NewsArticle.published_at)).scalar()
latest = session.query(func.max(NewsArticle.published_at)).scalar()
print(f" Date range: {earliest} to {latest}")
# Sentiment scores
scored_news = session.query(func.count(NewsSentiment.id)).scalar()
unscored = total_news - scored_news
print(f"\n๐Ÿง  Sentiment Scores: {scored_news}")
print(f" Unscored articles: {unscored}")
if verbose and scored_news > 0:
avg_score = session.query(func.avg(NewsSentiment.score)).scalar()
print(f" Average score: {avg_score:.3f}" if avg_score else " Average score: N/A")
# Daily sentiment
daily_count = session.query(func.count(DailySentiment.id)).scalar()
print(f"\n๐Ÿ“Š Daily Sentiment Records: {daily_count}")
# Price bars
print("\n๐Ÿ’ฐ Price Bars:")
symbols = settings.symbols_list
for symbol in symbols:
count = session.query(func.count(PriceBar.id)).filter(
PriceBar.symbol == symbol
).scalar()
if count > 0:
latest_bar = session.query(PriceBar).filter(
PriceBar.symbol == symbol
).order_by(PriceBar.date.desc()).first()
latest_date = latest_bar.date.strftime("%Y-%m-%d") if latest_bar else "N/A"
latest_price = f"${latest_bar.close:.4f}" if latest_bar else "N/A"
print(f" {symbol}: {count} bars (latest: {latest_date} @ {latest_price})")
else:
print(f" {symbol}: 0 bars")
# Analysis snapshots
snapshot_count = session.query(func.count(AnalysisSnapshot.id)).scalar()
print(f"\n๐Ÿ“ธ Analysis Snapshots: {snapshot_count}")
if verbose and snapshot_count > 0:
latest_snapshot = session.query(AnalysisSnapshot).order_by(
AnalysisSnapshot.generated_at.desc()
).first()
if latest_snapshot:
print(f" Latest: {latest_snapshot.symbol} @ {latest_snapshot.generated_at}")
print("\n" + "=" * 60)
def main():
parser = argparse.ArgumentParser(description="Inspect CopperMind database")
parser.add_argument(
"--verbose", "-v",
action="store_true",
help="Show detailed statistics"
)
args = parser.parse_args()
inspect_database(verbose=args.verbose)
if __name__ == "__main__":
main()