diff --git a/src/pages/journal/trading_journal_page.py b/src/pages/journal/trading_journal_page.py index 1ed3f9f..95e8cbd 100644 --- a/src/pages/journal/trading_journal_page.py +++ b/src/pages/journal/trading_journal_page.py @@ -9,6 +9,39 @@ from trading.journal import ( get_position_summary, get_latest_portfolio_value, update_portfolio_value ) +def calculate_position_performance(trades): + """Calculate performance metrics for a group of trades""" + total_bought = 0 + total_cost = 0 + total_sold = 0 + total_proceeds = 0 + + for trade in trades: + if trade['direction'] == 'buy': + shares = float(trade['shares']) + price = float(trade['entry_price']) + total_bought += shares + total_cost += shares * price + elif trade['direction'] == 'sell': + shares = float(trade['shares']) + price = float(trade['entry_price']) # For sells, entry_price is the exit price + total_sold += shares + total_proceeds += shares * price + + avg_entry = total_cost / total_bought if total_bought > 0 else 0 + avg_exit = total_proceeds / total_sold if total_sold > 0 else 0 + realized_pl = total_proceeds - (total_sold / total_bought * total_cost) if total_bought > 0 else 0 + remaining_shares = total_bought - total_sold + + return { + 'total_bought': total_bought, + 'total_sold': total_sold, + 'avg_entry': avg_entry, + 'avg_exit': avg_exit, + 'realized_pl': realized_pl, + 'remaining_shares': remaining_shares + } + def format_datetime(dt): """Format datetime for display""" if dt: @@ -310,45 +343,59 @@ def trading_journal_page(): trades.sort(key=lambda x: (x['entry_date'], 0 if x.get('direction') == 'buy' else 1)) first_trade = trades[0] + # Calculate position performance + performance = calculate_position_performance(trades) + with st.expander(f"{first_trade['ticker']} - Position {position_id}"): + # Show position summary + col1, col2, col3 = st.columns(3) + with col1: + st.metric("Total Shares Bought", f"{int(performance['total_bought']):,}") + st.metric("Avg Entry", f"${performance['avg_entry']:.2f}") + with col2: + st.metric("Total Shares Sold", f"{int(performance['total_sold']):,}") + st.metric("Avg Exit", f"${performance['avg_exit']:.2f}") + with col3: + st.metric("Remaining Shares", f"{int(performance['remaining_shares']):,}") + st.metric("Realized P/L", + f"${performance['realized_pl']:.2f}", + f"{(performance['realized_pl'] / (performance['total_sold'] * performance['avg_entry']) * 100):.2f}%" if performance['total_sold'] > 0 else None) + + st.markdown("---") + + # Show buy trades + st.subheader("Buy Orders") for trade in trades: - st.markdown(f"**{format_datetime(trade['entry_date'])}**") - - col1, col2 = st.columns(2) - with col1: - try: - if trade['direction'] == 'sell': - # For sells, use entry_price as the exit price - exit_price = float(trade['entry_price']) - st.metric("Exit Price", f"${exit_price:.2f}") - # Update the trade's exit_price and exit_date - trade['exit_price'] = exit_price - trade['exit_date'] = trade['entry_date'] - else: - entry_price = float(trade['entry_price']) - st.metric("Entry Price", f"${entry_price:.2f}") - except (ValueError, TypeError): - price_label = "Exit Price" if trade['direction'] == 'sell' else "Entry Price" - st.metric(price_label, "N/A") - st.metric("Shares", trade['shares']) - direction = trade.get('direction', 'buy') - if isinstance(direction, str): - st.metric("Type", direction.capitalize()) - else: - st.metric("Type", "Buy") # Default value if direction is not a string - - with col2: - if trade['direction'] == 'buy': + if trade['direction'] == 'buy': + col1, col2, col3 = st.columns(3) + with col1: + st.text(f"Date: {format_datetime(trade['entry_date'])}") + st.text(f"Shares: {trade['shares']}") + with col2: + st.text(f"Price: ${float(trade['entry_price']):.2f}") + st.text(f"Order: {trade['order_type']}") + with col3: if trade.get('target_price'): - st.metric("Target", f"${trade['target_price']:.2f}") + st.text(f"Target: ${float(trade['target_price']):.2f}") if trade.get('stop_loss'): - st.metric("Stop Loss", f"${trade['stop_loss']:.2f}") - - if trade.get('strategy'): - st.text(f"Strategy: {trade['strategy']}") - if trade.get('notes'): - st.text(f"Notes: {trade['notes']}") - - st.markdown("---") + st.text(f"Stop: ${float(trade['stop_loss']):.2f}") + if trade.get('entry_reason'): + st.text(f"Reason: {trade['entry_reason']}") + st.markdown("---") + + # Show sell trades + st.subheader("Sell Orders") + for trade in trades: + if trade['direction'] == 'sell': + col1, col2 = st.columns(2) + with col1: + st.text(f"Date: {format_datetime(trade['entry_date'])}") + st.text(f"Shares: {trade['shares']}") + with col2: + st.text(f"Price: ${float(trade['entry_price']):.2f}") + st.text(f"Order: {trade['order_type']}") + if trade.get('exit_reason'): + st.text(f"Reason: {trade['exit_reason']}") + st.markdown("---") else: st.info("No trade history found")