feat: Add real-time price tracking and P/L calculations using yfinance

This commit is contained in:
Bobby (aider) 2025-02-10 11:06:46 -08:00
parent 8ea233ff7c
commit 1416d1b912
2 changed files with 74 additions and 7 deletions

View File

@ -14,3 +14,6 @@ pytest
# Time zone handling
pytz
tzdata
# Real-time data
yfinance

View File

@ -3,6 +3,7 @@ from dataclasses import dataclass
from typing import Optional
import pytz
from zoneinfo import ZoneInfo
import yfinance as yf
from db.db_connection import create_client
from trading.position_calculator import PositionCalculator
from utils.data_utils import get_user_input
@ -401,6 +402,31 @@ def get_open_trades():
'exit_date', 'exit_reason', 'notes', 'created_at']
return [dict(zip(columns, row)) for row in result]
def get_current_prices(tickers: list) -> dict:
"""Get current prices for multiple tickers using yfinance"""
try:
# Create a space-separated string of tickers
ticker_str = " ".join(tickers)
# Get data for all tickers at once
data = yf.download(ticker_str, period="1d", interval="1m", group_by='ticker')
prices = {}
if len(tickers) == 1:
# Handle single ticker case
ticker = tickers[0]
if not data.empty:
prices[ticker] = data['Close'].iloc[-1]
else:
# Handle multiple tickers
for ticker in tickers:
if (ticker, 'Close') in
prices[ticker] = data[ticker]['Close'].iloc[-1]
return prices
except Exception as e:
print(f"Error fetching current prices: {e}")
return {}
def get_trade_history(limit: int = 50):
with create_client() as client:
query = f"""
@ -608,26 +634,57 @@ def journal_menu():
if not open_trades:
print("No open trades found.")
else:
# Get current prices for all open positions
unique_tickers = list(set(summary['ticker'] for summary in open_summary))
current_prices = get_current_prices(unique_tickers)
print("\n=== Open Trades Summary ===")
total_portfolio_value = 0
total_paper_pl = 0
for summary in open_summary:
ticker = summary['ticker']
avg_entry = summary['avg_entry_price']
stop_loss = avg_entry * 0.93 # 7% stop loss
total_value = avg_entry * summary['total_shares']
max_loss = (avg_entry - stop_loss) * summary['total_shares']
current_price = current_prices.get(ticker)
print(f"\n{summary['ticker']} Summary:")
print(f"Total Shares: {summary['total_shares']}")
stop_loss = avg_entry * 0.93 # 7% stop loss
total_shares = summary['total_shares']
position_value = avg_entry * total_shares
max_loss = (avg_entry - stop_loss) * total_shares
print(f"\n{ticker} Summary:")
print(f"Total Shares: {total_shares}")
print(f"Average Entry: ${avg_entry:.2f}")
print(f"Total Position Value: ${total_value:.2f}")
print(f"Total Position Value: ${position_value:.2f}")
print(f"Combined Stop Loss (7%): ${stop_loss:.2f}")
print(f"Maximum Loss at Stop: ${max_loss:.2f}")
if current_price:
current_value = current_price * total_shares
paper_pl = (current_price - avg_entry) * total_shares
pl_percentage = (paper_pl / position_value) * 100
total_portfolio_value += current_value
total_paper_pl += paper_pl
print(f"Current Price: ${current_price:.2f}")
print(f"Current Value: ${current_value:.2f}")
print(f"Paper P/L: ${paper_pl:.2f} ({pl_percentage:.2f}%)")
print(f"Number of Orders: {summary['num_orders']}")
print(f"Position Duration: {summary['last_entry'] - summary['first_entry']}")
print("-" * 50)
if total_portfolio_value > 0:
print(f"\nTotal Portfolio Value: ${total_portfolio_value:.2f}")
print(f"Total Paper P/L: ${total_paper_pl:.2f}")
print(f"Overall P/L %: {(total_paper_pl / (total_portfolio_value - total_paper_pl)) * 100:.2f}%")
print("\n=== Individual Trades ===")
for trade in open_trades:
print(f"\nTicker: {trade['ticker']}")
ticker = trade['ticker']
current_price = current_prices.get(ticker)
print(f"\nTicker: {ticker}")
print(f"Position ID: {trade['position_id']}")
print(f"Entry Date: {trade['entry_date']}")
print(f"Shares: {trade['shares']}")
@ -636,6 +693,13 @@ def journal_menu():
print(f"Stop Loss: ${trade['stop_loss']}")
print(f"Strategy: {trade['strategy']}")
print(f"Order Type: {trade['order_type']}")
if current_price:
paper_pl = (current_price - trade['entry_price']) * trade['shares']
pl_percentage = (paper_pl / (trade['entry_price'] * trade['shares'])) * 100
print(f"Current Price: ${current_price:.2f}")
print(f"Paper P/L: ${paper_pl:.2f} ({pl_percentage:.2f}%)")
if trade['entry_reason']:
print(f"Entry Reason: {trade['entry_reason']}")
if trade['notes']: