feat: Enhance trade history display with position-based grouping and comprehensive trade details
This commit is contained in:
parent
3f0b10ed41
commit
8d76d820fe
@ -280,40 +280,52 @@ def trading_journal_page():
|
|||||||
history = get_trade_history()
|
history = get_trade_history()
|
||||||
|
|
||||||
if history:
|
if history:
|
||||||
|
# Group trades by position_id
|
||||||
|
positions = {}
|
||||||
|
for trade in history:
|
||||||
|
if trade['position_id'] not in positions:
|
||||||
|
positions[trade['position_id']] = []
|
||||||
|
positions[trade['position_id']].append(trade)
|
||||||
|
|
||||||
# Add P/L chart
|
# Add P/L chart
|
||||||
fig = plot_trade_history(history)
|
fig = plot_trade_history(history)
|
||||||
if fig:
|
if fig:
|
||||||
st.plotly_chart(fig, use_container_width=True)
|
st.plotly_chart(fig, use_container_width=True)
|
||||||
|
|
||||||
for trade in history:
|
# Display trades grouped by position
|
||||||
# Determine if this is a sell order or a closed trade
|
for position_id, trades in positions.items():
|
||||||
is_sell = trade.get('direction') == 'sell'
|
# Sort trades by entry_date
|
||||||
|
trades.sort(key=lambda x: x['entry_date'])
|
||||||
|
first_trade = trades[0]
|
||||||
|
|
||||||
with st.expander(f"{trade['ticker']} - {format_datetime(trade['entry_date'])}"):
|
with st.expander(f"{first_trade['ticker']} - Position {position_id}"):
|
||||||
if is_sell:
|
for trade in trades:
|
||||||
profit_loss = (trade['entry_price'] - trade.get('exit_price', 0)) * trade['shares']
|
st.markdown(f"**{format_datetime(trade['entry_date'])}**")
|
||||||
else:
|
|
||||||
profit_loss = (trade.get('exit_price', 0) - trade['entry_price']) * trade['shares'] if trade.get('exit_price') else None
|
|
||||||
|
|
||||||
col1, col2 = st.columns(2)
|
col1, col2 = st.columns(2)
|
||||||
with col1:
|
with col1:
|
||||||
if is_sell:
|
if trade['direction'] == 'sell':
|
||||||
st.metric("Sell Price", f"${trade['entry_price']:.2f}")
|
st.metric("Sell Price", f"${trade['entry_price']:.2f}")
|
||||||
else:
|
else:
|
||||||
st.metric("Entry Price", f"${trade['entry_price']:.2f}")
|
st.metric("Entry Price", f"${trade['entry_price']:.2f}")
|
||||||
st.metric("Shares", trade['shares'])
|
st.metric("Shares", trade['shares'])
|
||||||
if profit_loss is not None:
|
st.metric("Type", trade['direction'].capitalize())
|
||||||
st.metric("P/L", f"${profit_loss:.2f}")
|
|
||||||
|
|
||||||
with col2:
|
with col2:
|
||||||
if not is_sell and trade.get('exit_price'):
|
if trade['direction'] == 'buy':
|
||||||
st.metric("Exit Price", f"${trade['exit_price']:.2f}")
|
if trade.get('target_price'):
|
||||||
st.metric("Exit Date", format_datetime(trade['exit_date']))
|
st.metric("Target", f"${trade['target_price']:.2f}")
|
||||||
|
if trade.get('stop_loss'):
|
||||||
|
st.metric("Stop Loss", f"${trade['stop_loss']:.2f}")
|
||||||
|
if trade.get('exit_price'):
|
||||||
|
st.metric("Exit Price", f"${trade['exit_price']:.2f}")
|
||||||
|
st.metric("Exit Date", format_datetime(trade['exit_date']))
|
||||||
|
|
||||||
if trade.get('strategy'):
|
if trade.get('strategy'):
|
||||||
st.text(f"Strategy: {trade['strategy']}")
|
st.text(f"Strategy: {trade['strategy']}")
|
||||||
if trade.get('notes'):
|
if trade.get('notes'):
|
||||||
st.text(f"Notes: {trade['notes']}")
|
st.text(f"Notes: {trade['notes']}")
|
||||||
st.text(f"Type: {'Sell Order' if is_sell else 'Buy'}")
|
|
||||||
|
st.markdown("---")
|
||||||
else:
|
else:
|
||||||
st.info("No trade history found")
|
st.info("No trade history found")
|
||||||
|
|||||||
@ -524,16 +524,18 @@ def delete_trade(trade_id: int) -> bool:
|
|||||||
def get_trade_history(limit: int = 50):
|
def get_trade_history(limit: int = 50):
|
||||||
with create_client() as client:
|
with create_client() as client:
|
||||||
query = f"""
|
query = f"""
|
||||||
SELECT * FROM stock_db.trades
|
SELECT
|
||||||
WHERE exit_price IS NOT NULL
|
*,
|
||||||
OR direction = 'sell'
|
groupArray(ticker) OVER (PARTITION BY position_id) as related_tickers,
|
||||||
ORDER BY COALESCE(exit_date, entry_date) DESC
|
groupArray(id) OVER (PARTITION BY position_id) as related_ids
|
||||||
|
FROM stock_db.trades
|
||||||
|
ORDER BY entry_date DESC
|
||||||
LIMIT {limit}
|
LIMIT {limit}
|
||||||
"""
|
"""
|
||||||
result = client.query(query).result_rows
|
result = client.query(query).result_rows
|
||||||
columns = ['id', 'position_id', 'ticker', 'entry_date', 'shares', 'entry_price', 'target_price',
|
columns = ['id', 'position_id', 'ticker', 'entry_date', 'shares', 'entry_price', 'target_price',
|
||||||
'stop_loss', 'strategy', 'order_type', 'followed_rules', 'entry_reason', 'exit_price',
|
'stop_loss', 'strategy', 'order_type', 'followed_rules', 'entry_reason', 'exit_price',
|
||||||
'exit_date', 'exit_reason', 'notes', 'created_at', 'direction']
|
'exit_date', 'exit_reason', 'notes', 'created_at', 'direction', 'related_tickers', 'related_ids']
|
||||||
return [dict(zip(columns, row)) for row in result]
|
return [dict(zip(columns, row)) for row in result]
|
||||||
|
|
||||||
def journal_menu():
|
def journal_menu():
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user