Spaces:
Running
Running
| """ | |
| 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() | |