refactor: Move trading plan page to dedicated module
This commit is contained in:
parent
60029268f7
commit
c5d7a96e38
483
src/pages/trading/trading_plan_page.py
Normal file
483
src/pages/trading/trading_plan_page.py
Normal file
@ -0,0 +1,483 @@
|
||||
import streamlit as st
|
||||
from db.db_connection import create_client
|
||||
from trading.trading_plan import (
|
||||
delete_trading_plan,
|
||||
TradingPlan, PlanStatus, Timeframe, MarketFocus, TradeFrequency,
|
||||
save_trading_plan, get_trading_plan, get_all_trading_plans,
|
||||
update_trading_plan, get_plan_trades,
|
||||
link_trades_to_plan, calculate_plan_metrics, unlink_trades_from_plan
|
||||
)
|
||||
|
||||
def trading_plan_page():
|
||||
st.header("Trading Plans")
|
||||
|
||||
# Create tabs for different plan operations
|
||||
list_tab, add_tab, edit_tab = st.tabs(["View Plans", "Add Plan", "Edit Plan"])
|
||||
|
||||
with list_tab:
|
||||
st.subheader("Trading Plans")
|
||||
plans = get_all_trading_plans()
|
||||
|
||||
if plans:
|
||||
for plan in plans:
|
||||
with st.expander(f"{plan.plan_name} ({plan.status.value})"):
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
st.markdown("### Basic Information")
|
||||
st.write(f"**Plan Name:** {plan.plan_name}")
|
||||
st.write(f"**Status:** {plan.status.value}")
|
||||
st.write(f"**Author:** {plan.plan_author}")
|
||||
st.write(f"**Version:** {plan.strategy_version}")
|
||||
st.write(f"**Created:** {plan.created_at}")
|
||||
st.write(f"**Updated:** {plan.updated_at}")
|
||||
|
||||
st.markdown("### Market Details")
|
||||
st.write(f"**Timeframe:** {plan.timeframe.value}")
|
||||
st.write(f"**Market:** {plan.market_focus.value}")
|
||||
st.write(f"**Frequency:** {plan.trade_frequency.value}")
|
||||
if plan.sector_focus:
|
||||
st.write(f"**Sector Focus:** {plan.sector_focus}")
|
||||
|
||||
with col2:
|
||||
st.markdown("### Risk Parameters")
|
||||
st.write(f"**Stop Loss:** {plan.stop_loss}%")
|
||||
st.write(f"**Profit Target:** {plan.profit_target}%")
|
||||
st.write(f"**Risk/Reward Ratio:** {plan.risk_reward_ratio}")
|
||||
st.write(f"**Position Size:** {plan.position_sizing}%")
|
||||
st.write(f"**Risk per Trade:** {plan.total_risk_per_trade}%")
|
||||
st.write(f"**Max Portfolio Risk:** {plan.max_portfolio_risk}%")
|
||||
st.write(f"**Max Drawdown:** {plan.maximum_drawdown}%")
|
||||
st.write(f"**Max Trades/Day:** {plan.max_trades_per_day}")
|
||||
st.write(f"**Max Trades/Week:** {plan.max_trades_per_week}")
|
||||
|
||||
st.markdown("### Performance Metrics")
|
||||
if any([plan.win_rate, plan.average_return_per_trade, plan.profit_factor]):
|
||||
col3, col4 = st.columns(2)
|
||||
with col3:
|
||||
if plan.win_rate:
|
||||
st.write(f"**Win Rate:** {plan.win_rate}%")
|
||||
if plan.average_return_per_trade:
|
||||
st.write(f"**Avg Return/Trade:** {plan.average_return_per_trade}%")
|
||||
with col4:
|
||||
if plan.profit_factor:
|
||||
st.write(f"**Profit Factor:** {plan.profit_factor}")
|
||||
|
||||
st.markdown("### Linked Trades")
|
||||
plan_trades = get_plan_trades(plan.id)
|
||||
if plan_trades:
|
||||
total_pl = 0
|
||||
winning_trades = 0
|
||||
total_trades = len(plan_trades)
|
||||
|
||||
st.markdown("#### Trade Statistics")
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
st.write(f"**Total Trades:** {total_trades}")
|
||||
st.write(f"**Winning Trades:** {winning_trades}")
|
||||
if total_trades > 0:
|
||||
st.write(f"**Win Rate:** {(winning_trades/total_trades)*100:.2f}%")
|
||||
|
||||
with col2:
|
||||
st.write(f"**Total P/L:** ${total_pl:.2f}")
|
||||
if total_trades > 0:
|
||||
st.write(f"**Average P/L per Trade:** ${total_pl/total_trades:.2f}")
|
||||
|
||||
st.markdown("#### Individual Trades")
|
||||
for trade in plan_trades:
|
||||
st.markdown("---")
|
||||
cols = st.columns(3)
|
||||
with cols[0]:
|
||||
st.write(f"**{trade['ticker']} - {trade['entry_date']}**")
|
||||
st.write(f"**Direction:** {trade['direction']}")
|
||||
if trade['strategy']:
|
||||
st.write(f"**Strategy:** {trade['strategy']}")
|
||||
|
||||
with cols[1]:
|
||||
st.write(f"**Entry:** ${trade['entry_price']:.2f}")
|
||||
st.write(f"**Shares:** {trade['shares']}")
|
||||
|
||||
with cols[2]:
|
||||
if trade['exit_price']:
|
||||
pl = (trade['exit_price'] - trade['entry_price']) * trade['shares']
|
||||
total_pl += pl
|
||||
if pl > 0:
|
||||
winning_trades += 1
|
||||
st.write(f"**Exit:** ${trade['exit_price']:.2f}")
|
||||
st.write(f"**P/L:** ${pl:.2f}")
|
||||
st.write(f"**Exit Date:** {trade['exit_date']}")
|
||||
else:
|
||||
st.write("**Status:** Open")
|
||||
else:
|
||||
st.info("No trades linked to this plan")
|
||||
|
||||
st.markdown("### Strategy Details")
|
||||
st.write("**Entry Criteria:**")
|
||||
st.write(plan.entry_criteria)
|
||||
|
||||
st.write("**Exit Criteria:**")
|
||||
st.write(plan.exit_criteria)
|
||||
|
||||
st.write("**Entry Confirmation:**")
|
||||
st.write(plan.entry_confirmation)
|
||||
|
||||
st.write("**Market Conditions:**")
|
||||
st.write(plan.market_conditions)
|
||||
|
||||
st.write("**Technical Indicators:**")
|
||||
st.write(plan.indicators_used)
|
||||
|
||||
st.markdown("### Risk Management")
|
||||
st.write("**Drawdown Adjustments:**")
|
||||
st.write(plan.adjustments_for_drawdown)
|
||||
|
||||
st.write("**Risk Controls:**")
|
||||
st.write(plan.risk_controls)
|
||||
|
||||
if plan.fundamental_criteria:
|
||||
st.markdown("### Fundamental Analysis")
|
||||
st.write(plan.fundamental_criteria)
|
||||
|
||||
if plan.options_strategy_details:
|
||||
st.markdown("### Options Strategy")
|
||||
st.write(plan.options_strategy_details)
|
||||
|
||||
if plan.improvements_needed:
|
||||
st.markdown("### Areas for Improvement")
|
||||
st.write(plan.improvements_needed)
|
||||
|
||||
if plan.trade_review_notes:
|
||||
st.markdown("### Trade Review Notes")
|
||||
st.write(plan.trade_review_notes)
|
||||
|
||||
if plan.future_testing_ideas:
|
||||
st.markdown("### Future Testing Ideas")
|
||||
st.write(plan.future_testing_ideas)
|
||||
|
||||
if plan.historical_backtest_results:
|
||||
st.markdown("### Historical Backtest Results")
|
||||
st.write(plan.historical_backtest_results)
|
||||
|
||||
if plan.real_trade_performance:
|
||||
st.markdown("### Real Trading Performance")
|
||||
st.write(plan.real_trade_performance)
|
||||
else:
|
||||
st.info("No trading plans found")
|
||||
|
||||
with add_tab:
|
||||
st.subheader("Create New Trading Plan")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
plan_name = st.text_input("Plan Name", key="add_plan_name")
|
||||
status = st.selectbox("Status", [s.value for s in PlanStatus], key="add_status")
|
||||
timeframe = st.selectbox("Timeframe", [t.value for t in Timeframe], key="add_timeframe")
|
||||
market_focus = st.selectbox("Market Focus", [m.value for m in MarketFocus], key="add_market_focus")
|
||||
|
||||
with col2:
|
||||
trade_frequency = st.selectbox("Trade Frequency", [f.value for f in TradeFrequency], key="add_trade_frequency")
|
||||
plan_author = st.text_input("Author", key="add_plan_author")
|
||||
strategy_version = st.number_input("Version", min_value=1, value=1, key="add_strategy_version")
|
||||
|
||||
st.subheader("Risk Parameters")
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
stop_loss = st.number_input("Stop Loss %", min_value=0.1, value=7.0, key="add_stop_loss")
|
||||
profit_target = st.number_input("Profit Target %", min_value=0.1, value=21.0, key="add_profit_target")
|
||||
risk_reward_ratio = profit_target / stop_loss if stop_loss > 0 else 0
|
||||
st.write(f"Risk:Reward Ratio: {risk_reward_ratio:.2f}")
|
||||
|
||||
with col2:
|
||||
position_sizing = st.number_input("Position Size %", min_value=0.1, value=5.0, key="add_position_sizing")
|
||||
total_risk_per_trade = st.number_input("Risk per Trade %", min_value=0.1, value=1.0, key="add_total_risk_per_trade")
|
||||
max_portfolio_risk = st.number_input("Max Portfolio Risk %", min_value=0.1, value=5.0, key="add_max_portfolio_risk")
|
||||
|
||||
st.subheader("Trade Rules")
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
max_trades_per_day = st.number_input("Max Trades per Day", min_value=1, value=3, key="add_max_trades_per_day")
|
||||
max_trades_per_week = st.number_input("Max Trades per Week", min_value=1, value=15, key="add_max_trades_per_week")
|
||||
maximum_drawdown = st.number_input("Maximum Drawdown %", min_value=0.1, value=20.0, key="add_maximum_drawdown")
|
||||
|
||||
st.subheader("Strategy Details")
|
||||
entry_criteria = st.text_area("Entry Criteria", key="add_entry_criteria")
|
||||
exit_criteria = st.text_area("Exit Criteria", key="add_exit_criteria")
|
||||
entry_confirmation = st.text_area("Entry Confirmation", key="add_entry_confirmation")
|
||||
market_conditions = st.text_area("Market Conditions", key="add_market_conditions")
|
||||
indicators_used = st.text_area("Technical Indicators", key="add_indicators_used")
|
||||
|
||||
st.subheader("Risk Management")
|
||||
adjustments_for_drawdown = st.text_area("Drawdown Adjustments", key="add_adjustments_for_drawdown")
|
||||
risk_controls = st.text_area("Risk Controls", key="add_risk_controls")
|
||||
|
||||
st.subheader("Additional Information")
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
sector_focus = st.text_input("Sector Focus (optional)", key="add_sector_focus")
|
||||
fundamental_criteria = st.text_area("Fundamental Criteria (optional)", key="add_fundamental_criteria")
|
||||
|
||||
with col2:
|
||||
options_strategy_details = st.text_area("Options Strategy Details (optional)", key="add_options_strategy_details")
|
||||
improvements_needed = st.text_area("Improvements Needed (optional)", key="add_improvements_needed")
|
||||
|
||||
if st.button("Create Trading Plan", key="create_plan_button"):
|
||||
try:
|
||||
plan = TradingPlan(
|
||||
plan_name=plan_name,
|
||||
status=PlanStatus(status),
|
||||
timeframe=Timeframe(timeframe),
|
||||
market_focus=MarketFocus(market_focus),
|
||||
trade_frequency=TradeFrequency(trade_frequency),
|
||||
entry_criteria=entry_criteria,
|
||||
exit_criteria=exit_criteria,
|
||||
stop_loss=stop_loss,
|
||||
profit_target=profit_target,
|
||||
risk_reward_ratio=risk_reward_ratio,
|
||||
entry_confirmation=entry_confirmation,
|
||||
position_sizing=position_sizing,
|
||||
maximum_drawdown=maximum_drawdown,
|
||||
max_trades_per_day=max_trades_per_day,
|
||||
max_trades_per_week=max_trades_per_week,
|
||||
total_risk_per_trade=total_risk_per_trade,
|
||||
max_portfolio_risk=max_portfolio_risk,
|
||||
adjustments_for_drawdown=adjustments_for_drawdown,
|
||||
risk_controls=risk_controls,
|
||||
market_conditions=market_conditions,
|
||||
indicators_used=indicators_used,
|
||||
plan_author=plan_author,
|
||||
strategy_version=strategy_version,
|
||||
sector_focus=sector_focus,
|
||||
fundamental_criteria=fundamental_criteria,
|
||||
options_strategy_details=options_strategy_details,
|
||||
improvements_needed=improvements_needed
|
||||
)
|
||||
|
||||
save_trading_plan(plan)
|
||||
st.success("Trading plan created successfully!")
|
||||
st.query_params.update(rerun=True)
|
||||
except Exception as e:
|
||||
st.error(f"Error creating trading plan: {str(e)}")
|
||||
|
||||
with edit_tab:
|
||||
st.subheader("Edit Trading Plan")
|
||||
plans = get_all_trading_plans()
|
||||
|
||||
if plans:
|
||||
selected_plan_id = st.selectbox(
|
||||
"Select Plan to Edit",
|
||||
options=[plan.id for plan in plans],
|
||||
format_func=lambda x: next(p.plan_name for p in plans if p.id == x),
|
||||
key="edit_plan_select"
|
||||
)
|
||||
|
||||
if selected_plan_id:
|
||||
plan = get_trading_plan(selected_plan_id)
|
||||
if plan:
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
plan_name = st.text_input("Plan Name", value=plan.plan_name, key="edit_plan_name")
|
||||
status = st.selectbox("Status", [s.value for s in PlanStatus], index=[s.value for s in PlanStatus].index(plan.status.value), key="edit_status")
|
||||
timeframe = st.selectbox("Timeframe", [t.value for t in Timeframe], index=[t.value for t in Timeframe].index(plan.timeframe.value), key="edit_timeframe")
|
||||
market_focus = st.selectbox("Market Focus", [m.value for m in MarketFocus], index=[m.value for m in MarketFocus].index(plan.market_focus.value), key="edit_market_focus")
|
||||
|
||||
with col2:
|
||||
trade_frequency = st.selectbox("Trade Frequency", [f.value for f in TradeFrequency], index=[f.value for f in TradeFrequency].index(plan.trade_frequency.value), key="edit_trade_frequency")
|
||||
plan_author = st.text_input("Author", value=plan.plan_author, key="edit_plan_author")
|
||||
strategy_version = st.number_input("Version", min_value=1, value=plan.strategy_version, key="edit_strategy_version")
|
||||
|
||||
st.subheader("Risk Parameters")
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
stop_loss = st.number_input("Stop Loss %", min_value=0.1, value=plan.stop_loss, key="edit_stop_loss")
|
||||
profit_target = st.number_input("Profit Target %", min_value=0.1, value=plan.profit_target, key="edit_profit_target")
|
||||
risk_reward_ratio = profit_target / stop_loss if stop_loss > 0 else 0
|
||||
st.write(f"Risk:Reward Ratio: {risk_reward_ratio:.2f}")
|
||||
|
||||
with col2:
|
||||
position_sizing = st.number_input("Position Size %", min_value=0.1, value=plan.position_sizing, key="edit_position_sizing")
|
||||
total_risk_per_trade = st.number_input("Risk per Trade %", min_value=0.1, value=plan.total_risk_per_trade, key="edit_total_risk_per_trade")
|
||||
max_portfolio_risk = st.number_input("Max Portfolio Risk %", min_value=0.1, value=plan.max_portfolio_risk, key="edit_max_portfolio_risk")
|
||||
|
||||
st.subheader("Trade Rules")
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
max_trades_per_day = st.number_input("Max Trades per Day", min_value=1, value=plan.max_trades_per_day, key="edit_max_trades_per_day")
|
||||
max_trades_per_week = st.number_input("Max Trades per Week", min_value=1, value=plan.max_trades_per_week, key="edit_max_trades_per_week")
|
||||
maximum_drawdown = st.number_input("Maximum Drawdown %", min_value=0.1, value=plan.maximum_drawdown, key="edit_maximum_drawdown")
|
||||
|
||||
st.subheader("Strategy Details")
|
||||
entry_criteria = st.text_area("Entry Criteria", value=plan.entry_criteria, key="edit_entry_criteria")
|
||||
exit_criteria = st.text_area("Exit Criteria", value=plan.exit_criteria, key="edit_exit_criteria")
|
||||
entry_confirmation = st.text_area("Entry Confirmation", value=plan.entry_confirmation, key="edit_entry_confirmation")
|
||||
market_conditions = st.text_area("Market Conditions", value=plan.market_conditions, key="edit_market_conditions")
|
||||
indicators_used = st.text_area("Technical Indicators", value=plan.indicators_used, key="edit_indicators_used")
|
||||
|
||||
st.subheader("Risk Management")
|
||||
adjustments_for_drawdown = st.text_area("Drawdown Adjustments", value=plan.adjustments_for_drawdown, key="edit_adjustments_for_drawdown")
|
||||
risk_controls = st.text_area("Risk Controls", value=plan.risk_controls, key="edit_risk_controls")
|
||||
|
||||
st.subheader("Additional Information")
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
sector_focus = st.text_input("Sector Focus (optional)", value=plan.sector_focus, key="edit_sector_focus")
|
||||
fundamental_criteria = st.text_area("Fundamental Criteria (optional)", value=plan.fundamental_criteria, key="edit_fundamental_criteria")
|
||||
|
||||
with col2:
|
||||
options_strategy_details = st.text_area("Options Strategy Details (optional)", value=plan.options_strategy_details, key="edit_options_strategy_details")
|
||||
improvements_needed = st.text_area("Improvements Needed (optional)", value=plan.improvements_needed, key="edit_improvements_needed")
|
||||
|
||||
if st.button("Update Plan", key="update_plan_button"):
|
||||
try:
|
||||
plan.plan_name = plan_name
|
||||
plan.status = PlanStatus(status)
|
||||
plan.timeframe = Timeframe(timeframe)
|
||||
plan.market_focus = MarketFocus(market_focus)
|
||||
plan.trade_frequency = TradeFrequency(trade_frequency)
|
||||
plan.plan_author = plan_author
|
||||
plan.strategy_version = strategy_version
|
||||
plan.stop_loss = stop_loss
|
||||
plan.profit_target = profit_target
|
||||
plan.position_sizing = position_sizing
|
||||
plan.total_risk_per_trade = total_risk_per_trade
|
||||
plan.max_portfolio_risk = max_portfolio_risk
|
||||
plan.max_trades_per_day = max_trades_per_day
|
||||
plan.max_trades_per_week = max_trades_per_week
|
||||
plan.maximum_drawdown = maximum_drawdown
|
||||
plan.entry_criteria = entry_criteria
|
||||
plan.exit_criteria = exit_criteria
|
||||
plan.entry_confirmation = entry_confirmation
|
||||
plan.market_conditions = market_conditions
|
||||
plan.indicators_used = indicators_used
|
||||
plan.adjustments_for_drawdown = adjustments_for_drawdown
|
||||
plan.risk_controls = risk_controls
|
||||
plan.sector_focus = sector_focus
|
||||
plan.fundamental_criteria = fundamental_criteria
|
||||
plan.options_strategy_details = options_strategy_details
|
||||
plan.improvements_needed = improvements_needed
|
||||
|
||||
update_trading_plan(plan)
|
||||
st.success("Plan updated successfully!")
|
||||
st.query_params.update(rerun=True)
|
||||
except Exception as e:
|
||||
st.error(f"Error updating plan: {str(e)}")
|
||||
|
||||
if st.button("Delete Plan", key="delete_plan_button"):
|
||||
try:
|
||||
delete_trading_plan(plan.id)
|
||||
st.success("Plan deleted successfully!")
|
||||
st.query_params.update(rerun=True)
|
||||
except Exception as e:
|
||||
st.error(f"Error deleting plan: {str(e)}")
|
||||
|
||||
st.subheader("Trade Management")
|
||||
|
||||
plan_trades = get_plan_trades(plan.id)
|
||||
|
||||
if plan_trades:
|
||||
st.write("Current Trades:")
|
||||
for trade in plan_trades:
|
||||
with st.expander(f"{trade['ticker']} - {trade['entry_date']}"):
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
st.write(f"Entry: ${trade['entry_price']:.2f}")
|
||||
st.write(f"Shares: {trade['shares']}")
|
||||
with col2:
|
||||
if trade['exit_price']:
|
||||
pl = (trade['exit_price'] - trade['entry_price']) * trade['shares']
|
||||
st.write(f"Exit: ${trade['exit_price']:.2f}")
|
||||
st.write(f"P/L: ${pl:.2f}")
|
||||
|
||||
if st.button("Unlink Trade", key=f"unlink_trade_{trade['id']}"):
|
||||
try:
|
||||
query = """
|
||||
ALTER TABLE stock_db.trades
|
||||
UPDATE plan_id = NULL
|
||||
WHERE id = %(trade_id)s
|
||||
"""
|
||||
with create_client() as client:
|
||||
client.command(query, {'trade_id': trade['id']})
|
||||
|
||||
metrics = calculate_plan_metrics(plan.id)
|
||||
plan.win_rate = metrics['win_rate']
|
||||
plan.average_return_per_trade = metrics['average_return']
|
||||
plan.profit_factor = metrics['profit_factor']
|
||||
update_trading_plan(plan)
|
||||
|
||||
st.success(f"Trade unlinked successfully!")
|
||||
st.query_params.update(rerun=True)
|
||||
except Exception as e:
|
||||
st.error(f"Error unlinking trade: {str(e)}")
|
||||
|
||||
if st.button("Unlink All Trades", key=f"unlink_all_trades_{plan.id}"):
|
||||
try:
|
||||
if unlink_trades_from_plan(plan.id):
|
||||
plan.win_rate = None
|
||||
plan.average_return_per_trade = None
|
||||
plan.profit_factor = None
|
||||
update_trading_plan(plan)
|
||||
|
||||
st.success("All trades unlinked successfully!")
|
||||
st.query_params.update(rerun=True)
|
||||
else:
|
||||
st.error("Error unlinking trades")
|
||||
except Exception as e:
|
||||
st.error(f"Error unlinking trades: {str(e)}")
|
||||
|
||||
with create_client() as client:
|
||||
query = """
|
||||
SELECT
|
||||
id,
|
||||
ticker,
|
||||
entry_date,
|
||||
entry_price,
|
||||
shares,
|
||||
exit_price,
|
||||
exit_date,
|
||||
direction,
|
||||
strategy,
|
||||
CASE
|
||||
WHEN exit_price IS NOT NULL
|
||||
THEN (exit_price - entry_price) * shares
|
||||
ELSE NULL
|
||||
END as profit_loss
|
||||
FROM stock_db.trades
|
||||
WHERE plan_id IS NULL
|
||||
ORDER BY entry_date DESC
|
||||
"""
|
||||
result = client.query(query)
|
||||
available_trades = [dict(zip(
|
||||
['id', 'ticker', 'entry_date', 'entry_price', 'shares',
|
||||
'exit_price', 'exit_date', 'direction', 'strategy', 'profit_loss'],
|
||||
row
|
||||
)) for row in result.result_rows]
|
||||
|
||||
if available_trades:
|
||||
st.write("Link Existing Trades:")
|
||||
selected_trades = st.multiselect(
|
||||
"Select trades to link to this plan",
|
||||
options=[t['id'] for t in available_trades],
|
||||
format_func=lambda x: next(
|
||||
f"{t['ticker']} - {t['entry_date']} - ${t['entry_price']:.2f} "
|
||||
f"({t['direction']}) - {t['strategy']} "
|
||||
f"{'[Closed]' if t['exit_price'] else '[Open]'} "
|
||||
f"{'P/L: $' + format(t['profit_loss'], '.2f') if t['profit_loss'] is not None else ''}"
|
||||
for t in available_trades if t['id'] == x
|
||||
),
|
||||
key=f"link_trades_{plan.id}"
|
||||
)
|
||||
|
||||
if selected_trades and st.button("Link Selected Trades", key=f"link_trades_button_{plan.id}"):
|
||||
if link_trades_to_plan(plan.id, selected_trades):
|
||||
st.success("Trades linked successfully!")
|
||||
|
||||
metrics = calculate_plan_metrics(plan.id)
|
||||
plan.win_rate = metrics['win_rate']
|
||||
plan.average_return_per_trade = metrics['average_return']
|
||||
plan.profit_factor = metrics['profit_factor']
|
||||
update_trading_plan(plan)
|
||||
|
||||
st.query_params.update(rerun=True)
|
||||
else:
|
||||
st.error("Error linking trades")
|
||||
else:
|
||||
st.info("No plans available to edit")
|
||||
@ -6,25 +6,16 @@ from db.db_connection import create_client
|
||||
from pages.journal.trading_journal_page import trading_journal_page, format_datetime
|
||||
from pages.screener.technical_scanner_page import technical_scanner_page
|
||||
from pages.trading.trading_system_page import trading_system_page
|
||||
from pages.trading.trading_plan_page import trading_plan_page
|
||||
from trading.journal import (
|
||||
create_trades_table, get_open_trades, get_trade_history,
|
||||
get_latest_portfolio_value, update_portfolio_value
|
||||
)
|
||||
from trading.trading_plan import (
|
||||
delete_trading_plan,
|
||||
TradingPlan, PlanStatus, Timeframe, MarketFocus, TradeFrequency,
|
||||
create_trading_plan_table, save_trading_plan, get_trading_plan,
|
||||
get_all_trading_plans, update_trading_plan, get_plan_trades,
|
||||
link_trades_to_plan, calculate_plan_metrics, unlink_trades_from_plan
|
||||
create_trading_plan_table,
|
||||
)
|
||||
from trading.position_calculator import PositionCalculator
|
||||
from pages.rules.strategy_guide_page import strategy_guide_page
|
||||
from screener.scanner_controller import run_technical_scanner
|
||||
from pages.screener.canslim_screener_page import canslim_screener_page, load_scanner_reports
|
||||
from trading.portfolio import Portfolio, Position
|
||||
from trading.position_calculator import PositionCalculator
|
||||
import plotly.graph_objects as go
|
||||
from plotly.subplots import make_subplots
|
||||
|
||||
def init_session_state():
|
||||
"""Initialize session state variables"""
|
||||
@ -37,506 +28,6 @@ def init_session_state():
|
||||
|
||||
|
||||
|
||||
def trading_plan_page():
|
||||
st.header("Trading Plans")
|
||||
|
||||
# Create tabs for different plan operations
|
||||
list_tab, add_tab, edit_tab = st.tabs(["View Plans", "Add Plan", "Edit Plan"])
|
||||
|
||||
with list_tab:
|
||||
st.subheader("Trading Plans")
|
||||
plans = get_all_trading_plans()
|
||||
|
||||
if plans:
|
||||
for plan in plans:
|
||||
with st.expander(f"{plan.plan_name} ({plan.status.value})"):
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
st.markdown("### Basic Information")
|
||||
st.write(f"**Plan Name:** {plan.plan_name}")
|
||||
st.write(f"**Status:** {plan.status.value}")
|
||||
st.write(f"**Author:** {plan.plan_author}")
|
||||
st.write(f"**Version:** {plan.strategy_version}")
|
||||
st.write(f"**Created:** {plan.created_at}")
|
||||
st.write(f"**Updated:** {plan.updated_at}")
|
||||
|
||||
st.markdown("### Market Details")
|
||||
st.write(f"**Timeframe:** {plan.timeframe.value}")
|
||||
st.write(f"**Market:** {plan.market_focus.value}")
|
||||
st.write(f"**Frequency:** {plan.trade_frequency.value}")
|
||||
if plan.sector_focus:
|
||||
st.write(f"**Sector Focus:** {plan.sector_focus}")
|
||||
|
||||
with col2:
|
||||
st.markdown("### Risk Parameters")
|
||||
st.write(f"**Stop Loss:** {plan.stop_loss}%")
|
||||
st.write(f"**Profit Target:** {plan.profit_target}%")
|
||||
st.write(f"**Risk/Reward Ratio:** {plan.risk_reward_ratio}")
|
||||
st.write(f"**Position Size:** {plan.position_sizing}%")
|
||||
st.write(f"**Risk per Trade:** {plan.total_risk_per_trade}%")
|
||||
st.write(f"**Max Portfolio Risk:** {plan.max_portfolio_risk}%")
|
||||
st.write(f"**Max Drawdown:** {plan.maximum_drawdown}%")
|
||||
st.write(f"**Max Trades/Day:** {plan.max_trades_per_day}")
|
||||
st.write(f"**Max Trades/Week:** {plan.max_trades_per_week}")
|
||||
|
||||
st.markdown("### Performance Metrics")
|
||||
if any([plan.win_rate, plan.average_return_per_trade, plan.profit_factor]):
|
||||
col3, col4 = st.columns(2)
|
||||
with col3:
|
||||
if plan.win_rate:
|
||||
st.write(f"**Win Rate:** {plan.win_rate}%")
|
||||
if plan.average_return_per_trade:
|
||||
st.write(f"**Avg Return/Trade:** {plan.average_return_per_trade}%")
|
||||
with col4:
|
||||
if plan.profit_factor:
|
||||
st.write(f"**Profit Factor:** {plan.profit_factor}")
|
||||
|
||||
# Add Linked Trades section
|
||||
st.markdown("### Linked Trades")
|
||||
plan_trades = get_plan_trades(plan.id)
|
||||
if plan_trades:
|
||||
total_pl = 0
|
||||
winning_trades = 0
|
||||
total_trades = len(plan_trades)
|
||||
|
||||
# Display trade statistics first
|
||||
st.markdown("#### Trade Statistics")
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
st.write(f"**Total Trades:** {total_trades}")
|
||||
st.write(f"**Winning Trades:** {winning_trades}")
|
||||
if total_trades > 0:
|
||||
st.write(f"**Win Rate:** {(winning_trades/total_trades)*100:.2f}%")
|
||||
|
||||
with col2:
|
||||
st.write(f"**Total P/L:** ${total_pl:.2f}")
|
||||
if total_trades > 0:
|
||||
st.write(f"**Average P/L per Trade:** ${total_pl/total_trades:.2f}")
|
||||
|
||||
# Display trades in a table format instead of nested expanders
|
||||
st.markdown("#### Individual Trades")
|
||||
for trade in plan_trades:
|
||||
st.markdown("---")
|
||||
cols = st.columns(3)
|
||||
with cols[0]:
|
||||
st.write(f"**{trade['ticker']} - {trade['entry_date']}**")
|
||||
st.write(f"**Direction:** {trade['direction']}")
|
||||
if trade['strategy']:
|
||||
st.write(f"**Strategy:** {trade['strategy']}")
|
||||
|
||||
with cols[1]:
|
||||
st.write(f"**Entry:** ${trade['entry_price']:.2f}")
|
||||
st.write(f"**Shares:** {trade['shares']}")
|
||||
|
||||
with cols[2]:
|
||||
if trade['exit_price']:
|
||||
pl = (trade['exit_price'] - trade['entry_price']) * trade['shares']
|
||||
total_pl += pl
|
||||
if pl > 0:
|
||||
winning_trades += 1
|
||||
st.write(f"**Exit:** ${trade['exit_price']:.2f}")
|
||||
st.write(f"**P/L:** ${pl:.2f}")
|
||||
st.write(f"**Exit Date:** {trade['exit_date']}")
|
||||
else:
|
||||
st.write("**Status:** Open")
|
||||
else:
|
||||
st.info("No trades linked to this plan")
|
||||
|
||||
st.markdown("### Strategy Details")
|
||||
st.write("**Entry Criteria:**")
|
||||
st.write(plan.entry_criteria)
|
||||
|
||||
st.write("**Exit Criteria:**")
|
||||
st.write(plan.exit_criteria)
|
||||
|
||||
st.write("**Entry Confirmation:**")
|
||||
st.write(plan.entry_confirmation)
|
||||
|
||||
st.write("**Market Conditions:**")
|
||||
st.write(plan.market_conditions)
|
||||
|
||||
st.write("**Technical Indicators:**")
|
||||
st.write(plan.indicators_used)
|
||||
|
||||
st.markdown("### Risk Management")
|
||||
st.write("**Drawdown Adjustments:**")
|
||||
st.write(plan.adjustments_for_drawdown)
|
||||
|
||||
st.write("**Risk Controls:**")
|
||||
st.write(plan.risk_controls)
|
||||
|
||||
if plan.fundamental_criteria:
|
||||
st.markdown("### Fundamental Analysis")
|
||||
st.write(plan.fundamental_criteria)
|
||||
|
||||
if plan.options_strategy_details:
|
||||
st.markdown("### Options Strategy")
|
||||
st.write(plan.options_strategy_details)
|
||||
|
||||
if plan.improvements_needed:
|
||||
st.markdown("### Areas for Improvement")
|
||||
st.write(plan.improvements_needed)
|
||||
|
||||
if plan.trade_review_notes:
|
||||
st.markdown("### Trade Review Notes")
|
||||
st.write(plan.trade_review_notes)
|
||||
|
||||
if plan.future_testing_ideas:
|
||||
st.markdown("### Future Testing Ideas")
|
||||
st.write(plan.future_testing_ideas)
|
||||
|
||||
if plan.historical_backtest_results:
|
||||
st.markdown("### Historical Backtest Results")
|
||||
st.write(plan.historical_backtest_results)
|
||||
|
||||
if plan.real_trade_performance:
|
||||
st.markdown("### Real Trading Performance")
|
||||
st.write(plan.real_trade_performance)
|
||||
else:
|
||||
st.info("No trading plans found")
|
||||
|
||||
with add_tab:
|
||||
st.subheader("Create New Trading Plan")
|
||||
|
||||
# Basic Info
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
plan_name = st.text_input("Plan Name", key="add_plan_name")
|
||||
status = st.selectbox("Status", [s.value for s in PlanStatus], key="add_status")
|
||||
timeframe = st.selectbox("Timeframe", [t.value for t in Timeframe], key="add_timeframe")
|
||||
market_focus = st.selectbox("Market Focus", [m.value for m in MarketFocus], key="add_market_focus")
|
||||
|
||||
with col2:
|
||||
trade_frequency = st.selectbox("Trade Frequency", [f.value for f in TradeFrequency], key="add_trade_frequency")
|
||||
plan_author = st.text_input("Author", key="add_plan_author")
|
||||
strategy_version = st.number_input("Version", min_value=1, value=1, key="add_strategy_version")
|
||||
|
||||
# Risk Parameters
|
||||
st.subheader("Risk Parameters")
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
stop_loss = st.number_input("Stop Loss %", min_value=0.1, value=7.0, key="add_stop_loss")
|
||||
profit_target = st.number_input("Profit Target %", min_value=0.1, value=21.0, key="add_profit_target")
|
||||
risk_reward_ratio = profit_target / stop_loss if stop_loss > 0 else 0
|
||||
st.write(f"Risk:Reward Ratio: {risk_reward_ratio:.2f}")
|
||||
|
||||
with col2:
|
||||
position_sizing = st.number_input("Position Size %", min_value=0.1, value=5.0, key="add_position_sizing")
|
||||
total_risk_per_trade = st.number_input("Risk per Trade %", min_value=0.1, value=1.0, key="add_total_risk_per_trade")
|
||||
max_portfolio_risk = st.number_input("Max Portfolio Risk %", min_value=0.1, value=5.0, key="add_max_portfolio_risk")
|
||||
|
||||
# Trade Rules
|
||||
st.subheader("Trade Rules")
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
max_trades_per_day = st.number_input("Max Trades per Day", min_value=1, value=3, key="add_max_trades_per_day")
|
||||
max_trades_per_week = st.number_input("Max Trades per Week", min_value=1, value=15, key="add_max_trades_per_week")
|
||||
maximum_drawdown = st.number_input("Maximum Drawdown %", min_value=0.1, value=20.0, key="add_maximum_drawdown")
|
||||
|
||||
# Strategy Details
|
||||
st.subheader("Strategy Details")
|
||||
entry_criteria = st.text_area("Entry Criteria", key="add_entry_criteria")
|
||||
exit_criteria = st.text_area("Exit Criteria", key="add_exit_criteria")
|
||||
entry_confirmation = st.text_area("Entry Confirmation", key="add_entry_confirmation")
|
||||
market_conditions = st.text_area("Market Conditions", key="add_market_conditions")
|
||||
indicators_used = st.text_area("Technical Indicators", key="add_indicators_used")
|
||||
|
||||
# Risk Management
|
||||
st.subheader("Risk Management")
|
||||
adjustments_for_drawdown = st.text_area("Drawdown Adjustments", key="add_adjustments_for_drawdown")
|
||||
risk_controls = st.text_area("Risk Controls", key="add_risk_controls")
|
||||
|
||||
# Optional Fields
|
||||
st.subheader("Additional Information")
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
sector_focus = st.text_input("Sector Focus (optional)", key="add_sector_focus")
|
||||
fundamental_criteria = st.text_area("Fundamental Criteria (optional)", key="add_fundamental_criteria")
|
||||
|
||||
with col2:
|
||||
options_strategy_details = st.text_area("Options Strategy Details (optional)", key="add_options_strategy_details")
|
||||
improvements_needed = st.text_area("Improvements Needed (optional)", key="add_improvements_needed")
|
||||
|
||||
if st.button("Create Trading Plan", key="create_plan_button"):
|
||||
try:
|
||||
plan = TradingPlan(
|
||||
plan_name=plan_name,
|
||||
status=PlanStatus(status),
|
||||
timeframe=Timeframe(timeframe),
|
||||
market_focus=MarketFocus(market_focus),
|
||||
trade_frequency=TradeFrequency(trade_frequency),
|
||||
entry_criteria=entry_criteria,
|
||||
exit_criteria=exit_criteria,
|
||||
stop_loss=stop_loss,
|
||||
profit_target=profit_target,
|
||||
risk_reward_ratio=risk_reward_ratio,
|
||||
entry_confirmation=entry_confirmation,
|
||||
position_sizing=position_sizing,
|
||||
maximum_drawdown=maximum_drawdown,
|
||||
max_trades_per_day=max_trades_per_day,
|
||||
max_trades_per_week=max_trades_per_week,
|
||||
total_risk_per_trade=total_risk_per_trade,
|
||||
max_portfolio_risk=max_portfolio_risk,
|
||||
adjustments_for_drawdown=adjustments_for_drawdown,
|
||||
risk_controls=risk_controls,
|
||||
market_conditions=market_conditions,
|
||||
indicators_used=indicators_used,
|
||||
plan_author=plan_author,
|
||||
strategy_version=strategy_version,
|
||||
sector_focus=sector_focus,
|
||||
fundamental_criteria=fundamental_criteria,
|
||||
options_strategy_details=options_strategy_details,
|
||||
improvements_needed=improvements_needed
|
||||
)
|
||||
|
||||
save_trading_plan(plan)
|
||||
st.success("Trading plan created successfully!")
|
||||
st.query_params.update(rerun=True)
|
||||
except Exception as e:
|
||||
st.error(f"Error creating trading plan: {str(e)}")
|
||||
|
||||
with edit_tab:
|
||||
st.subheader("Edit Trading Plan")
|
||||
plans = get_all_trading_plans()
|
||||
|
||||
if plans:
|
||||
selected_plan_id = st.selectbox(
|
||||
"Select Plan to Edit",
|
||||
options=[plan.id for plan in plans],
|
||||
format_func=lambda x: next(p.plan_name for p in plans if p.id == x),
|
||||
key="edit_plan_select"
|
||||
)
|
||||
|
||||
if selected_plan_id:
|
||||
plan = get_trading_plan(selected_plan_id)
|
||||
if plan:
|
||||
# Basic Info
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
plan_name = st.text_input("Plan Name", value=plan.plan_name, key="edit_plan_name")
|
||||
status = st.selectbox("Status", [s.value for s in PlanStatus], index=[s.value for s in PlanStatus].index(plan.status.value), key="edit_status")
|
||||
timeframe = st.selectbox("Timeframe", [t.value for t in Timeframe], index=[t.value for t in Timeframe].index(plan.timeframe.value), key="edit_timeframe")
|
||||
market_focus = st.selectbox("Market Focus", [m.value for m in MarketFocus], index=[m.value for m in MarketFocus].index(plan.market_focus.value), key="edit_market_focus")
|
||||
|
||||
with col2:
|
||||
trade_frequency = st.selectbox("Trade Frequency", [f.value for f in TradeFrequency], index=[f.value for f in TradeFrequency].index(plan.trade_frequency.value), key="edit_trade_frequency")
|
||||
plan_author = st.text_input("Author", value=plan.plan_author, key="edit_plan_author")
|
||||
strategy_version = st.number_input("Version", min_value=1, value=plan.strategy_version, key="edit_strategy_version")
|
||||
|
||||
# Risk Parameters
|
||||
st.subheader("Risk Parameters")
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
stop_loss = st.number_input("Stop Loss %", min_value=0.1, value=plan.stop_loss, key="edit_stop_loss")
|
||||
profit_target = st.number_input("Profit Target %", min_value=0.1, value=plan.profit_target, key="edit_profit_target")
|
||||
risk_reward_ratio = profit_target / stop_loss if stop_loss > 0 else 0
|
||||
st.write(f"Risk:Reward Ratio: {risk_reward_ratio:.2f}")
|
||||
|
||||
with col2:
|
||||
position_sizing = st.number_input("Position Size %", min_value=0.1, value=plan.position_sizing, key="edit_position_sizing")
|
||||
total_risk_per_trade = st.number_input("Risk per Trade %", min_value=0.1, value=plan.total_risk_per_trade, key="edit_total_risk_per_trade")
|
||||
max_portfolio_risk = st.number_input("Max Portfolio Risk %", min_value=0.1, value=plan.max_portfolio_risk, key="edit_max_portfolio_risk")
|
||||
|
||||
# Trade Rules
|
||||
st.subheader("Trade Rules")
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
max_trades_per_day = st.number_input("Max Trades per Day", min_value=1, value=plan.max_trades_per_day, key="edit_max_trades_per_day")
|
||||
max_trades_per_week = st.number_input("Max Trades per Week", min_value=1, value=plan.max_trades_per_week, key="edit_max_trades_per_week")
|
||||
maximum_drawdown = st.number_input("Maximum Drawdown %", min_value=0.1, value=plan.maximum_drawdown, key="edit_maximum_drawdown")
|
||||
|
||||
# Strategy Details
|
||||
st.subheader("Strategy Details")
|
||||
entry_criteria = st.text_area("Entry Criteria", value=plan.entry_criteria, key="edit_entry_criteria")
|
||||
exit_criteria = st.text_area("Exit Criteria", value=plan.exit_criteria, key="edit_exit_criteria")
|
||||
entry_confirmation = st.text_area("Entry Confirmation", value=plan.entry_confirmation, key="edit_entry_confirmation")
|
||||
market_conditions = st.text_area("Market Conditions", value=plan.market_conditions, key="edit_market_conditions")
|
||||
indicators_used = st.text_area("Technical Indicators", value=plan.indicators_used, key="edit_indicators_used")
|
||||
|
||||
# Risk Management
|
||||
st.subheader("Risk Management")
|
||||
adjustments_for_drawdown = st.text_area("Drawdown Adjustments", value=plan.adjustments_for_drawdown, key="edit_adjustments_for_drawdown")
|
||||
risk_controls = st.text_area("Risk Controls", value=plan.risk_controls, key="edit_risk_controls")
|
||||
|
||||
# Optional Fields
|
||||
st.subheader("Additional Information")
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
sector_focus = st.text_input("Sector Focus (optional)", value=plan.sector_focus, key="edit_sector_focus")
|
||||
fundamental_criteria = st.text_area("Fundamental Criteria (optional)", value=plan.fundamental_criteria, key="edit_fundamental_criteria")
|
||||
|
||||
with col2:
|
||||
options_strategy_details = st.text_area("Options Strategy Details (optional)", value=plan.options_strategy_details, key="edit_options_strategy_details")
|
||||
improvements_needed = st.text_area("Improvements Needed (optional)", value=plan.improvements_needed, key="edit_improvements_needed")
|
||||
|
||||
if st.button("Update Plan", key="update_plan_button"):
|
||||
try:
|
||||
# Update the plan with new values
|
||||
plan.plan_name = plan_name
|
||||
plan.status = PlanStatus(status)
|
||||
plan.timeframe = Timeframe(timeframe)
|
||||
plan.market_focus = MarketFocus(market_focus)
|
||||
plan.trade_frequency = TradeFrequency(trade_frequency)
|
||||
plan.plan_author = plan_author
|
||||
plan.strategy_version = strategy_version
|
||||
plan.stop_loss = stop_loss
|
||||
plan.profit_target = profit_target
|
||||
plan.position_sizing = position_sizing
|
||||
plan.total_risk_per_trade = total_risk_per_trade
|
||||
plan.max_portfolio_risk = max_portfolio_risk
|
||||
plan.max_trades_per_day = max_trades_per_day
|
||||
plan.max_trades_per_week = max_trades_per_week
|
||||
plan.maximum_drawdown = maximum_drawdown
|
||||
plan.entry_criteria = entry_criteria
|
||||
plan.exit_criteria = exit_criteria
|
||||
plan.entry_confirmation = entry_confirmation
|
||||
plan.market_conditions = market_conditions
|
||||
plan.indicators_used = indicators_used
|
||||
plan.adjustments_for_drawdown = adjustments_for_drawdown
|
||||
plan.risk_controls = risk_controls
|
||||
plan.sector_focus = sector_focus
|
||||
plan.fundamental_criteria = fundamental_criteria
|
||||
plan.options_strategy_details = options_strategy_details
|
||||
plan.improvements_needed = improvements_needed
|
||||
|
||||
update_trading_plan(plan)
|
||||
st.success("Plan updated successfully!")
|
||||
st.query_params.update(rerun=True)
|
||||
except Exception as e:
|
||||
st.error(f"Error updating plan: {str(e)}")
|
||||
|
||||
# Delete button (at the same level as the update button)
|
||||
if st.button("Delete Plan", key="delete_plan_button"):
|
||||
try:
|
||||
delete_trading_plan(plan.id)
|
||||
st.success("Plan deleted successfully!")
|
||||
st.query_params.update(rerun=True)
|
||||
except Exception as e:
|
||||
st.error(f"Error deleting plan: {str(e)}")
|
||||
|
||||
# Add Trade Management section
|
||||
st.subheader("Trade Management")
|
||||
|
||||
# Get current trades for this plan
|
||||
plan_trades = get_plan_trades(plan.id)
|
||||
|
||||
# Display current trades
|
||||
if plan_trades:
|
||||
st.write("Current Trades:")
|
||||
for trade in plan_trades:
|
||||
with st.expander(f"{trade['ticker']} - {trade['entry_date']}"):
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
st.write(f"Entry: ${trade['entry_price']:.2f}")
|
||||
st.write(f"Shares: {trade['shares']}")
|
||||
with col2:
|
||||
if trade['exit_price']:
|
||||
pl = (trade['exit_price'] - trade['entry_price']) * trade['shares']
|
||||
st.write(f"Exit: ${trade['exit_price']:.2f}")
|
||||
st.write(f"P/L: ${pl:.2f}")
|
||||
|
||||
# Add unlink button for each trade
|
||||
if st.button("Unlink Trade", key=f"unlink_trade_{trade['id']}"):
|
||||
try:
|
||||
# Update the single trade
|
||||
query = """
|
||||
ALTER TABLE stock_db.trades
|
||||
UPDATE plan_id = NULL
|
||||
WHERE id = %(trade_id)s
|
||||
"""
|
||||
with create_client() as client:
|
||||
client.command(query, {'trade_id': trade['id']})
|
||||
|
||||
# Recalculate metrics
|
||||
metrics = calculate_plan_metrics(plan.id)
|
||||
plan.win_rate = metrics['win_rate']
|
||||
plan.average_return_per_trade = metrics['average_return']
|
||||
plan.profit_factor = metrics['profit_factor']
|
||||
update_trading_plan(plan)
|
||||
|
||||
st.success(f"Trade unlinked successfully!")
|
||||
st.query_params.update(rerun=True)
|
||||
except Exception as e:
|
||||
st.error(f"Error unlinking trade: {str(e)}")
|
||||
|
||||
# Add button to unlink all trades
|
||||
if st.button("Unlink All Trades", key=f"unlink_all_trades_{plan.id}"):
|
||||
try:
|
||||
if unlink_trades_from_plan(plan.id):
|
||||
# Reset metrics
|
||||
plan.win_rate = None
|
||||
plan.average_return_per_trade = None
|
||||
plan.profit_factor = None
|
||||
update_trading_plan(plan)
|
||||
|
||||
st.success("All trades unlinked successfully!")
|
||||
st.query_params.update(rerun=True)
|
||||
else:
|
||||
st.error("Error unlinking trades")
|
||||
except Exception as e:
|
||||
st.error(f"Error unlinking trades: {str(e)}")
|
||||
|
||||
# Get available trades
|
||||
with create_client() as client:
|
||||
query = """
|
||||
SELECT
|
||||
id,
|
||||
ticker,
|
||||
entry_date,
|
||||
entry_price,
|
||||
shares,
|
||||
exit_price,
|
||||
exit_date,
|
||||
direction,
|
||||
strategy,
|
||||
CASE
|
||||
WHEN exit_price IS NOT NULL
|
||||
THEN (exit_price - entry_price) * shares
|
||||
ELSE NULL
|
||||
END as profit_loss
|
||||
FROM stock_db.trades
|
||||
WHERE plan_id IS NULL
|
||||
ORDER BY entry_date DESC
|
||||
"""
|
||||
result = client.query(query)
|
||||
available_trades = [dict(zip(
|
||||
['id', 'ticker', 'entry_date', 'entry_price', 'shares',
|
||||
'exit_price', 'exit_date', 'direction', 'strategy', 'profit_loss'],
|
||||
row
|
||||
)) for row in result.result_rows]
|
||||
|
||||
if available_trades:
|
||||
st.write("Link Existing Trades:")
|
||||
selected_trades = st.multiselect(
|
||||
"Select trades to link to this plan",
|
||||
options=[t['id'] for t in available_trades],
|
||||
format_func=lambda x: next(
|
||||
f"{t['ticker']} - {t['entry_date']} - ${t['entry_price']:.2f} "
|
||||
f"({t['direction']}) - {t['strategy']} "
|
||||
f"{'[Closed]' if t['exit_price'] else '[Open]'} "
|
||||
f"{'P/L: $' + format(t['profit_loss'], '.2f') if t['profit_loss'] is not None else ''}"
|
||||
for t in available_trades if t['id'] == x
|
||||
),
|
||||
key=f"link_trades_{plan.id}"
|
||||
)
|
||||
|
||||
if selected_trades and st.button("Link Selected Trades", key=f"link_trades_button_{plan.id}"):
|
||||
if link_trades_to_plan(plan.id, selected_trades):
|
||||
st.success("Trades linked successfully!")
|
||||
|
||||
# Calculate and update metrics
|
||||
metrics = calculate_plan_metrics(plan.id)
|
||||
plan.win_rate = metrics['win_rate']
|
||||
plan.average_return_per_trade = metrics['average_return']
|
||||
plan.profit_factor = metrics['profit_factor']
|
||||
update_trading_plan(plan)
|
||||
|
||||
st.query_params.update(rerun=True)
|
||||
else:
|
||||
st.error("Error linking trades")
|
||||
else:
|
||||
st.info("No plans available to edit")
|
||||
|
||||
def main():
|
||||
st.set_page_config(page_title="Trading System", layout="wide")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user