From d13540757c366e8a146050c2007d2ce3651a5dd6 Mon Sep 17 00:00:00 2001 From: Giulio De Pasquale Date: Sat, 18 Oct 2025 11:46:40 +0100 Subject: [PATCH] feat(cli): add show script to display OHLCV and indicators --- show.py | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100755 show.py diff --git a/show.py b/show.py new file mode 100755 index 0000000..26f74ff --- /dev/null +++ b/show.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python + +from sys import exit +from dotenv import load_dotenv +from typing import NoReturn +import argparse +from datetime import datetime +from paperone.database import TradingDataCRUD +from rich.console import Console +from rich.table import Table + +load_dotenv() + +DB_FILE = "trading_data.db" + + +def parse_args(): + """Parse command line arguments.""" + parser = argparse.ArgumentParser( + description="Fetch and display OHLCV and indicators for a ticker and date" + ) + parser.add_argument("ticker", type=str, help="Ticker symbol (e.g., AAPL)") + parser.add_argument( + "date", type=str, help="Date in YYYYMMDD format (e.g., 20251017)" + ) + return parser.parse_args() + + +def format_ohlcv_table(ticker: str, date: datetime, ohlcv) -> Table: + """Create a rich table for OHLCV data.""" + table = Table(title=f"OHLCV Data for {ticker} on {date.strftime('%Y-%m-%d')}") + + table.add_column("Metric", style="cyan", no_wrap=True) + table.add_column("Value", style="magenta") + + table.add_row("Open", f"${ohlcv.open:.2f}") + table.add_row("High", f"${ohlcv.high:.2f}") + table.add_row("Low", f"${ohlcv.low:.2f}") + table.add_row("Close", f"${ohlcv.close:.2f}") + table.add_row("Average", f"${ohlcv.avg:.2f}") + table.add_row("Volume", f"{ohlcv.volume:,}") + + return table + + +def format_indicators_table(ticker: str, date: datetime, indicators) -> Table: + """Create a rich table for technical indicators.""" + table = Table( + title=f"Technical Indicators for {ticker} on {date.strftime('%Y-%m-%d')}" + ) + + table.add_column("Category", style="cyan", no_wrap=True) + table.add_column("Indicator", style="green") + table.add_column("Value", style="magenta") + + # Momentum Indicators + table.add_row("Momentum", "RSI (14)", f"{indicators.rsi_14:.2f}") + table.add_row("", "RSI (20)", f"{indicators.rsi_20:.2f}") + table.add_row("", "MACD Line", f"{indicators.macd_line:.4f}") + table.add_row("", "MACD Signal", f"{indicators.macd_signal:.4f}") + table.add_row("", "MACD Histogram", f"{indicators.macd_histogram:.4f}") + table.add_row("", "Stochastic %K", f"{indicators.stoch_k:.2f}") + table.add_row("", "Stochastic %D", f"{indicators.stoch_d:.2f}") + + # Volatility Indicators + table.add_row("Volatility", "BB Upper", f"${indicators.bb_upper:.2f}") + table.add_row("", "BB Middle", f"${indicators.bb_middle:.2f}") + table.add_row("", "BB Lower", f"${indicators.bb_lower:.2f}") + table.add_row("", "BB Width", f"{indicators.bb_width:.2f}") + table.add_row("", "BB Percent", f"{indicators.bb_percent:.4f}") + table.add_row("", "ATR (14)", f"{indicators.atr_14:.2f}") + + # Trend Indicators + table.add_row("Trend", "ADX (14)", f"{indicators.adx_14:.2f}") + table.add_row("", "+DI", f"{indicators.di_plus:.2f}") + table.add_row("", "-DI", f"{indicators.di_minus:.2f}") + table.add_row("", "Parabolic SAR", f"${indicators.sar:.2f}") + + # Volume Indicators + table.add_row("Volume", "OBV", f"{indicators.obv:,.0f}") + table.add_row("", "OBV SMA (20)", f"{indicators.obv_sma_20:,.0f}") + table.add_row("", "Volume ROC (5)", f"{indicators.volume_roc_5:.2f}%") + + # Support/Resistance + table.add_row("Support/Resistance", "Fib 23.6%", f"${indicators.fib_236:.2f}") + table.add_row("", "Fib 38.2%", f"${indicators.fib_382:.2f}") + table.add_row("", "Fib 61.8%", f"${indicators.fib_618:.2f}") + table.add_row("", "Pivot Point", f"${indicators.pivot_point:.2f}") + table.add_row("", "Resistance 1", f"${indicators.resistance_1:.2f}") + table.add_row("", "Support 1", f"${indicators.support_1:.2f}") + + # Market Regime + table.add_row("Market Regime", "CCI (20)", f"{indicators.cci_20:.2f}") + table.add_row("", "Williams %R (14)", f"{indicators.williams_r_14:.2f}") + + return table + + +def main() -> NoReturn: + """Main execution function.""" + args = parse_args() + console = Console() + + # Parse date + try: + target_date = datetime.strptime(args.date, "%Y%m%d") + except ValueError: + console.print( + f"[red]Error:[/red] Invalid date format '{args.date}'. " + "Please use YYYYMMDD (e.g., 20251017)" + ) + exit(1) + + # Initialize database connection + crud = TradingDataCRUD(f"sqlite:///{DB_FILE}") + + # Fetch OHLCV data + ohlcv = crud.get_ohlcv(args.ticker, target_date) + if not ohlcv: + console.print( + f"[red]Error:[/red] No OHLCV data found for {args.ticker} " + f"on {target_date.strftime('%Y-%m-%d')}" + ) + exit(1) + + # Fetch indicators + indicators = crud.get_indicators(args.ticker, target_date) + + # Display OHLCV table + console.print() + console.print(format_ohlcv_table(args.ticker, target_date, ohlcv)) + + # Display indicators table if available + if indicators: + console.print() + console.print(format_indicators_table(args.ticker, target_date, indicators)) + else: + console.print() + console.print( + f"[yellow]Warning:[/yellow] No indicator data found for {args.ticker} " + f"on {target_date.strftime('%Y-%m-%d')}" + ) + + exit(0) + + +if __name__ == "__main__": + main()