From ca4ceabc40dec104260182be915ea9a0a1ba51e6 Mon Sep 17 00:00:00 2001 From: "Bobby (aider)" Date: Tue, 11 Feb 2025 17:38:11 -0800 Subject: [PATCH] feat: Add trading plan model and database schema for managing trading strategies --- src/trading/trading_plan.py | 209 ++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 src/trading/trading_plan.py diff --git a/src/trading/trading_plan.py b/src/trading/trading_plan.py new file mode 100644 index 0000000..bd039f0 --- /dev/null +++ b/src/trading/trading_plan.py @@ -0,0 +1,209 @@ +from datetime import datetime +from enum import Enum +from typing import Optional, Dict, Any +from dataclasses import dataclass +from db.db_connection import create_client + +class PlanStatus(Enum): + ACTIVE = 'active' + ARCHIVED = 'archived' + TESTING = 'testing' + DEPRECATED = 'deprecated' + +class Timeframe(Enum): + DAILY = 'daily' + WEEKLY = 'weekly' + HOURLY = 'hourly' + MIN_15 = '15-min' + MIN_30 = '30-min' + MIN_5 = '5-min' + +class MarketFocus(Enum): + STOCKS = 'stocks' + CRYPTO = 'crypto' + FOREX = 'forex' + OPTIONS = 'options' + FUTURES = 'futures' + +class TradeFrequency(Enum): + DAILY = 'daily' + WEEKLY = 'weekly' + MONTHLY = 'monthly' + AS_NEEDED = 'as-needed' + +@dataclass +class TradingPlan: + # General Info + plan_name: str + status: PlanStatus + created_at: datetime = None + updated_at: datetime = None + id: int = None + + # Strategy Definition + timeframe: Timeframe + market_focus: MarketFocus + entry_criteria: str + exit_criteria: str + stop_loss: float + profit_target: float + risk_reward_ratio: float + trade_frequency: TradeFrequency + market_conditions: str + indicators_used: str + + # Trade Execution Rules + entry_confirmation: str + position_sizing: float + maximum_drawdown: float + max_trades_per_day: int + max_trades_per_week: int + + # Risk Management + total_risk_per_trade: float + max_portfolio_risk: float + adjustments_for_drawdown: str + risk_controls: str + + # Performance Tracking + win_rate: Optional[float] = None + average_return_per_trade: Optional[float] = None + profit_factor: Optional[float] = None + historical_backtest_results: Optional[str] = None + real_trade_performance: Optional[str] = None + + # Notes & Evolution + improvements_needed: Optional[str] = None + strategy_version: int = 1 + plan_author: str + trade_review_notes: Optional[str] = None + future_testing_ideas: Optional[str] = None + + # Optional fields + sector_focus: Optional[str] = None + fundamental_criteria: Optional[str] = None + options_strategy_details: Optional[str] = None + +def create_trading_plan_table(): + """Create the trading plans table if it doesn't exist""" + with create_client() as client: + query = """ + CREATE TABLE IF NOT EXISTS trading_plans ( + id Int32, + plan_name String, + status String, + created_at DateTime, + updated_at DateTime, + + timeframe String, + market_focus String, + entry_criteria String, + exit_criteria String, + stop_loss Float64, + profit_target Float64, + risk_reward_ratio Float64, + trade_frequency String, + market_conditions String, + indicators_used String, + + entry_confirmation String, + position_sizing Float64, + maximum_drawdown Float64, + max_trades_per_day Int32, + max_trades_per_week Int32, + + total_risk_per_trade Float64, + max_portfolio_risk Float64, + adjustments_for_drawdown String, + risk_controls String, + + win_rate Nullable(Float64), + average_return_per_trade Nullable(Float64), + profit_factor Nullable(Float64), + historical_backtest_results Nullable(String), + real_trade_performance Nullable(String), + + improvements_needed Nullable(String), + strategy_version Int32, + plan_author String, + trade_review_notes Nullable(String), + future_testing_ideas Nullable(String), + + sector_focus Nullable(String), + fundamental_criteria Nullable(String), + options_strategy_details Nullable(String) + ) + ENGINE = MergeTree() + ORDER BY (id, created_at) + """ + client.execute(query) + +def save_trading_plan(plan: TradingPlan) -> int: + """Save a trading plan to the database""" + with create_client() as client: + if not plan.id: + # Generate new ID for new plans + result = client.execute("SELECT max(id) FROM trading_plans") + plan.id = (result[0][0] or 0) + 1 + plan.created_at = datetime.now() + + plan.updated_at = datetime.now() + + query = """ + INSERT INTO trading_plans VALUES ( + %(id)s, %(plan_name)s, %(status)s, %(created_at)s, %(updated_at)s, + %(timeframe)s, %(market_focus)s, %(entry_criteria)s, %(exit_criteria)s, + %(stop_loss)s, %(profit_target)s, %(risk_reward_ratio)s, %(trade_frequency)s, + %(market_conditions)s, %(indicators_used)s, %(entry_confirmation)s, + %(position_sizing)s, %(maximum_drawdown)s, %(max_trades_per_day)s, + %(max_trades_per_week)s, %(total_risk_per_trade)s, %(max_portfolio_risk)s, + %(adjustments_for_drawdown)s, %(risk_controls)s, %(win_rate)s, + %(average_return_per_trade)s, %(profit_factor)s, %(historical_backtest_results)s, + %(real_trade_performance)s, %(improvements_needed)s, %(strategy_version)s, + %(plan_author)s, %(trade_review_notes)s, %(future_testing_ideas)s, + %(sector_focus)s, %(fundamental_criteria)s, %(options_strategy_details)s + ) + """ + + params = { + 'id': plan.id, + 'plan_name': plan.plan_name, + 'status': plan.status.value, + 'created_at': plan.created_at, + 'updated_at': plan.updated_at, + 'timeframe': plan.timeframe.value, + 'market_focus': plan.market_focus.value, + 'entry_criteria': plan.entry_criteria, + 'exit_criteria': plan.exit_criteria, + 'stop_loss': plan.stop_loss, + 'profit_target': plan.profit_target, + 'risk_reward_ratio': plan.risk_reward_ratio, + 'trade_frequency': plan.trade_frequency.value, + 'market_conditions': plan.market_conditions, + 'indicators_used': plan.indicators_used, + 'entry_confirmation': plan.entry_confirmation, + 'position_sizing': plan.position_sizing, + 'maximum_drawdown': plan.maximum_drawdown, + 'max_trades_per_day': plan.max_trades_per_day, + 'max_trades_per_week': plan.max_trades_per_week, + 'total_risk_per_trade': plan.total_risk_per_trade, + 'max_portfolio_risk': plan.max_portfolio_risk, + 'adjustments_for_drawdown': plan.adjustments_for_drawdown, + 'risk_controls': plan.risk_controls, + 'win_rate': plan.win_rate, + 'average_return_per_trade': plan.average_return_per_trade, + 'profit_factor': plan.profit_factor, + 'historical_backtest_results': plan.historical_backtest_results, + 'real_trade_performance': plan.real_trade_performance, + 'improvements_needed': plan.improvements_needed, + 'strategy_version': plan.strategy_version, + 'plan_author': plan.plan_author, + 'trade_review_notes': plan.trade_review_notes, + 'future_testing_ideas': plan.future_testing_ideas, + 'sector_focus': plan.sector_focus, + 'fundamental_criteria': plan.fundamental_criteria, + 'options_strategy_details': plan.options_strategy_details + } + + client.execute(query, params) + return plan.id