refactor: Enhance trade history display with performance metrics and detailed trade information
This commit is contained in:
parent
b1b22ac026
commit
47b58faddd
@ -9,6 +9,39 @@ from trading.journal import (
|
|||||||
get_position_summary, get_latest_portfolio_value, update_portfolio_value
|
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):
|
def format_datetime(dt):
|
||||||
"""Format datetime for display"""
|
"""Format datetime for display"""
|
||||||
if dt:
|
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))
|
trades.sort(key=lambda x: (x['entry_date'], 0 if x.get('direction') == 'buy' else 1))
|
||||||
first_trade = trades[0]
|
first_trade = trades[0]
|
||||||
|
|
||||||
|
# Calculate position performance
|
||||||
|
performance = calculate_position_performance(trades)
|
||||||
|
|
||||||
with st.expander(f"{first_trade['ticker']} - Position {position_id}"):
|
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:
|
for trade in trades:
|
||||||
st.markdown(f"**{format_datetime(trade['entry_date'])}**")
|
if trade['direction'] == 'buy':
|
||||||
|
col1, col2, col3 = st.columns(3)
|
||||||
col1, col2 = st.columns(2)
|
with col1:
|
||||||
with col1:
|
st.text(f"Date: {format_datetime(trade['entry_date'])}")
|
||||||
try:
|
st.text(f"Shares: {trade['shares']}")
|
||||||
if trade['direction'] == 'sell':
|
with col2:
|
||||||
# For sells, use entry_price as the exit price
|
st.text(f"Price: ${float(trade['entry_price']):.2f}")
|
||||||
exit_price = float(trade['entry_price'])
|
st.text(f"Order: {trade['order_type']}")
|
||||||
st.metric("Exit Price", f"${exit_price:.2f}")
|
with col3:
|
||||||
# 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.get('target_price'):
|
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'):
|
if trade.get('stop_loss'):
|
||||||
st.metric("Stop Loss", f"${trade['stop_loss']:.2f}")
|
st.text(f"Stop: ${float(trade['stop_loss']):.2f}")
|
||||||
|
if trade.get('entry_reason'):
|
||||||
if trade.get('strategy'):
|
st.text(f"Reason: {trade['entry_reason']}")
|
||||||
st.text(f"Strategy: {trade['strategy']}")
|
st.markdown("---")
|
||||||
if trade.get('notes'):
|
|
||||||
st.text(f"Notes: {trade['notes']}")
|
# Show sell trades
|
||||||
|
st.subheader("Sell Orders")
|
||||||
st.markdown("---")
|
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:
|
else:
|
||||||
st.info("No trade history found")
|
st.info("No trade history found")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user