Team Ai
Modelpublic

ParallelLLC/algorithmic_trading

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
27likes32downloads
streamlit_app.py758 linesDownload Raw Back to ui
1"""2Streamlit UI for Algorithmic Trading System3 4A comprehensive web interface for:5- Real-time market data visualization6- Trading strategy configuration7- FinRL model training and evaluation8- Portfolio management9- Risk monitoring10"""11 12import streamlit as st13import plotly.graph_objects as go14import plotly.express as px15import pandas as pd16import numpy as np17import yaml18import os19import sys20from datetime import datetime, timedelta21from typing import Dict, Any, Optional22import asyncio23import threading24import time25 26# Add project root to path27sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))28 29# Import with error handling for deployment30try:31    from agentic_ai_system.main import load_config32    from agentic_ai_system.data_ingestion import load_data, validate_data, add_technical_indicators33    from agentic_ai_system.finrl_agent import FinRLAgent, FinRLConfig34    from agentic_ai_system.alpaca_broker import AlpacaBroker35    from agentic_ai_system.orchestrator import run_backtest, run_live_trading36    DEPLOYMENT_MODE = False37except ImportError as e:38    st.warning(f"โš ๏ธ Some modules not available in deployment mode: {e}")39    DEPLOYMENT_MODE = True40    41    # Mock functions for deployment42    def load_config(config_file):43        return {44            'trading': {'symbol': 'AAPL', 'capital': 100000, 'timeframe': '1d'},45            'execution': {'broker_api': 'alpaca_paper'},46            'finrl': {'algorithm': 'PPO'},47            'risk': {'max_drawdown': 0.1}48        }49    50    def load_data(config):51        # Generate sample data for deployment52        dates = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')53        np.random.seed(42)54        prices = 150 + np.cumsum(np.random.randn(len(dates)) * 0.5)55        56        data = pd.DataFrame({57            'timestamp': dates,58            'open': prices * 0.99,59            'high': prices * 1.02,60            'low': prices * 0.98,61            'close': prices,62            'volume': np.random.randint(1000000, 5000000, len(dates))63        })64        return data65    66    def add_technical_indicators(data):67        data['sma_20'] = data['close'].rolling(window=20).mean()68        data['sma_50'] = data['close'].rolling(window=50).mean()69        return data70    71    class FinRLAgent:72        def __init__(self, config):73            self.config = config74        75        def train(self, data, config, total_timesteps, use_real_broker=False):76            return {'success': True, 'message': 'Training completed (demo mode)'}77    78    class FinRLConfig:79        def __init__(self, **kwargs):80            for key, value in kwargs.items():81                setattr(self, key, value)82    83    class AlpacaBroker:84        def __init__(self, config):85            self.config = config86        87        def get_account_info(self):88            return {89                'portfolio_value': 100000,90                'equity': 102500,91                'cash': 50000,92                'buying_power': 5000093            }94        95        def get_positions(self):96            return []97    98    def run_backtest(config, data):99        return {100            'success': True,101            'total_return': 0.025,102            'sharpe_ratio': 1.2,103            'max_drawdown': 0.05,104            'total_trades': 15105        }106    107    def run_live_trading(config, data):108        return {'success': True, 'message': 'Live trading started (demo mode)'}109 110# Page configuration111st.set_page_config(112    page_title="Algorithmic Trading System",113    page_icon="๐Ÿ“ˆ",114    layout="wide",115    initial_sidebar_state="expanded"116)117 118# Custom CSS for better styling119st.markdown("""120<style>121    .main-header {122        font-size: 2.5rem;123        font-weight: bold;124        color: #1f77b4;125        text-align: center;126        margin-bottom: 2rem;127    }128    .metric-card {129        background-color: #f0f2f6;130        padding: 1rem;131        border-radius: 0.5rem;132        border-left: 4px solid #1f77b4;133    }134    .success-metric {135        border-left-color: #28a745;136    }137    .warning-metric {138        border-left-color: #ffc107;139    }140    .danger-metric {141        border-left-color: #dc3545;142    }143    .sidebar .sidebar-content {144        background-color: #f8f9fa;145    }146</style>147""", unsafe_allow_html=True)148 149class TradingUI:150    def __init__(self):151        self.config = None152        self.data = None153        self.alpaca_broker = None154        self.finrl_agent = None155        self.session_state = st.session_state156        157        # Initialize session state158        if 'trading_active' not in self.session_state:159            self.session_state.trading_active = False160        if 'current_portfolio' not in self.session_state:161            self.session_state.current_portfolio = {}162        if 'trading_history' not in self.session_state:163            self.session_state.trading_history = []164    165    def load_configuration(self):166        """Load and display configuration"""167        st.sidebar.header("โš™๏ธ Configuration")168        169        # Config file selector170        config_files = [f for f in os.listdir('.') if f.endswith('.yaml') or f.endswith('.yml')]171        selected_config = st.sidebar.selectbox(172            "Select Configuration File",173            config_files,174            index=0 if 'config.yaml' in config_files else 0175        )176        177        if st.sidebar.button("Load Configuration"):178            try:179                self.config = load_config(selected_config)180                st.sidebar.success(f"โœ… Configuration loaded: {selected_config}")181                return True182            except Exception as e:183                st.sidebar.error(f"โŒ Error loading config: {e}")184                return False185        186        return False187    188    def display_system_status(self):189        """Display system status and metrics"""190        st.header("๐Ÿ“Š System Status")191        192        col1, col2, col3, col4 = st.columns(4)193        194        with col1:195            st.metric(196                label="Trading Status",197                value="๐ŸŸข Active" if self.session_state.trading_active else "๐Ÿ”ด Inactive",198                delta="Running" if self.session_state.trading_active else "Stopped"199            )200        201        with col2:202            if self.config:203                st.metric(204                    label="Capital",205                    value=f"${self.config['trading']['capital']:,}",206                    delta="Available"207                )208            else:209                st.metric(label="Capital", value="Not Loaded")210        211        with col3:212            if self.alpaca_broker:213                try:214                    account_info = self.alpaca_broker.get_account_info()215                    if account_info:216                        st.metric(217                            label="Portfolio Value",218                            value=f"${float(account_info['portfolio_value']):,.2f}",219                            delta=f"{float(account_info['equity']) - float(account_info['portfolio_value']):,.2f}"220                        )221                except:222                    st.metric(label="Portfolio Value", value="Not Connected")223            else:224                st.metric(label="Portfolio Value", value="Not Connected")225        226        with col4:227            if self.data is not None:228                st.metric(229                    label="Data Points",230                    value=f"{len(self.data):,}",231                    delta=f"Latest: {self.data['timestamp'].max().strftime('%Y-%m-%d')}"232                )233            else:234                st.metric(label="Data Points", value="Not Loaded")235    236    def data_ingestion_panel(self):237        """Data ingestion and visualization panel"""238        st.header("๐Ÿ“ฅ Data Ingestion")239        240        col1, col2 = st.columns([2, 1])241        242        with col1:243            if self.config:244                if st.button("Load Market Data"):245                    with st.spinner("Loading data..."):246                        try:247                            self.data = load_data(self.config)248                            if self.data is not None and not self.data.empty:249                                st.success(f"โœ… Loaded {len(self.data)} data points")250                                251                                # Add technical indicators252                                self.data = add_technical_indicators(self.data)253                                st.info(f"โœ… Added technical indicators")254                            else:255                                st.error("โŒ Failed to load data")256                        except Exception as e:257                            st.error(f"โŒ Error loading data: {e}")258        259        with col2:260            if self.data is not None:261                st.subheader("Data Summary")262                st.write(f"**Symbol:** {self.config['trading']['symbol']}")263                st.write(f"**Timeframe:** {self.config['trading']['timeframe']}")264                st.write(f"**Date Range:** {self.data['timestamp'].min().strftime('%Y-%m-%d')} to {self.data['timestamp'].max().strftime('%Y-%m-%d')}")265                st.write(f"**Price Range:** ${self.data['close'].min():.2f} - ${self.data['close'].max():.2f}")266        267        # Data visualization268        if self.data is not None:269            st.subheader("๐Ÿ“ˆ Market Data Visualization")270            271            # Chart type selector272            chart_type = st.selectbox(273                "Chart Type",274                ["Candlestick", "Line", "OHLC", "Volume"]275            )276            277            if chart_type == "Candlestick":278                fig = go.Figure(data=[go.Candlestick(279                    x=self.data['timestamp'],280                    open=self.data['open'],281                    high=self.data['high'],282                    low=self.data['low'],283                    close=self.data['close']284                )])285                fig.update_layout(286                    title=f"{self.config['trading']['symbol']} Candlestick Chart",287                    xaxis_title="Date",288                    yaxis_title="Price ($)",289                    height=500290                )291                st.plotly_chart(fig, use_container_width=True)292            293            elif chart_type == "Line":294                fig = px.line(self.data, x='timestamp', y='close', 295                             title=f"{self.config['trading']['symbol']} Price Chart")296                fig.update_layout(height=500)297                st.plotly_chart(fig, use_container_width=True)298            299            elif chart_type == "Volume":300                fig = go.Figure()301                fig.add_trace(go.Bar(302                    x=self.data['timestamp'],303                    y=self.data['volume'],304                    name='Volume'305                ))306                fig.update_layout(307                    title=f"{self.config['trading']['symbol']} Volume Chart",308                    xaxis_title="Date",309                    yaxis_title="Volume",310                    height=500311                )312                st.plotly_chart(fig, use_container_width=True)313    314    def alpaca_integration_panel(self):315        """Alpaca broker integration panel"""316        st.header("๐Ÿฆ Alpaca Integration")317        318        col1, col2 = st.columns([1, 1])319        320        with col1:321            if st.button("Connect to Alpaca"):322                if self.config and self.config['execution']['broker_api'] in ['alpaca_paper', 'alpaca_live']:323                    with st.spinner("Connecting to Alpaca..."):324                        try:325                            self.alpaca_broker = AlpacaBroker(self.config)326                            account_info = self.alpaca_broker.get_account_info()327                            if account_info:328                                st.success("โœ… Connected to Alpaca")329                                self.session_state.alpaca_connected = True330                            else:331                                st.error("โŒ Failed to connect to Alpaca")332                        except Exception as e:333                            st.error(f"โŒ Connection error: {e}")334                else:335                    st.warning("โš ๏ธ Alpaca not configured in settings")336        337        with col2:338            if st.button("Disconnect from Alpaca"):339                self.alpaca_broker = None340                self.session_state.alpaca_connected = False341                st.success("โœ… Disconnected from Alpaca")342        343        # Account information display344        if self.alpaca_broker:345            st.subheader("Account Information")346            347            try:348                account_info = self.alpaca_broker.get_account_info()349                if account_info:350                    col1, col2, col3 = st.columns(3)351                    352                    with col1:353                        st.metric(354                            label="Buying Power",355                            value=f"${float(account_info['buying_power']):,.2f}"356                        )357                    358                    with col2:359                        st.metric(360                            label="Portfolio Value",361                            value=f"${float(account_info['portfolio_value']):,.2f}"362                        )363                    364                    with col3:365                        st.metric(366                            label="Equity",367                            value=f"${float(account_info['equity']):,.2f}"368                        )369                    370                    # Market hours371                    market_hours = self.alpaca_broker.get_market_hours()372                    if market_hours:373                        status_color = "๐ŸŸข" if market_hours['is_open'] else "๐Ÿ”ด"374                        st.info(f"{status_color} Market Status: {'OPEN' if market_hours['is_open'] else 'CLOSED'}")375                        376                        if market_hours['next_open']:377                            st.write(f"Next Open: {market_hours['next_open']}")378                        if market_hours['next_close']:379                            st.write(f"Next Close: {market_hours['next_close']}")380                381                # Current positions382                positions = self.alpaca_broker.get_positions()383                if positions:384                    st.subheader("Current Positions")385                    positions_df = pd.DataFrame(positions)386                    st.dataframe(positions_df)387                else:388                    st.info("No current positions")389                    390            except Exception as e:391                st.error(f"Error fetching account info: {e}")392    393    def finrl_training_panel(self):394        """FinRL model training panel"""395        st.header("๐Ÿง  FinRL Model Training")396        397        if not self.data is not None:398            st.warning("โš ๏ธ Please load market data first")399            return400        401        col1, col2 = st.columns([2, 1])402        403        with col1:404            st.subheader("Training Configuration")405            406            # Training parameters407            algorithm = st.selectbox(408                "Algorithm",409                ["PPO", "A2C", "DDPG", "TD3"],410                index=0411            )412            413            learning_rate = st.slider(414                "Learning Rate",415                min_value=0.0001,416                max_value=0.01,417                value=0.0003,418                step=0.0001,419                format="%.4f"420            )421            422            total_timesteps = st.slider(423                "Total Timesteps",424                min_value=1000,425                max_value=1000000,426                value=100000,427                step=1000428            )429            430            batch_size = st.selectbox(431                "Batch Size",432                [32, 64, 128, 256],433                index=1434            )435        436        with col2:437            st.subheader("Training Controls")438            439            if st.button("Start Training", type="primary"):440                if self.data is not None:441                    with st.spinner("Training FinRL model..."):442                        try:443                            # Create FinRL config444                            finrl_config = FinRLConfig(445                                algorithm=algorithm,446                                learning_rate=learning_rate,447                                batch_size=batch_size,448                                buffer_size=1000000,449                                learning_starts=100,450                                gamma=0.99,451                                tau=0.005,452                                train_freq=1,453                                gradient_steps=1,454                                verbose=1,455                                tensorboard_log='logs/finrl_tensorboard'456                            )457                            458                            # Initialize agent459                            self.finrl_agent = FinRLAgent(finrl_config)460                            461                            # Train the agent462                            result = self.finrl_agent.train(463                                data=self.data,464                                config=self.config,465                                total_timesteps=total_timesteps,466                                use_real_broker=False467                            )468                            469                            if result['success']:470                                st.success("โœ… Training completed successfully!")471                                st.write(f"Model saved: {result['model_path']}")472                                self.session_state.model_trained = True473                            else:474                                st.error("โŒ Training failed")475                                476                        except Exception as e:477                            st.error(f"โŒ Training error: {e}")478        479        # Training progress and metrics480        if hasattr(self.session_state, 'model_trained') and self.session_state.model_trained:481            st.subheader("Model Performance")482            483            if st.button("Evaluate Model"):484                if self.finrl_agent:485                    with st.spinner("Evaluating model..."):486                        try:487                            # Use last 100 data points for evaluation488                            eval_data = self.data.tail(100)489                            prediction_result = self.finrl_agent.predict(490                                data=eval_data,491                                config=self.config,492                                use_real_broker=False493                            )494                            495                            if prediction_result['success']:496                                col1, col2, col3 = st.columns(3)497                                498                                with col1:499                                    st.metric(500                                        label="Initial Value",501                                        value=f"${prediction_result['initial_value']:,.2f}"502                                    )503                                504                                with col2:505                                    st.metric(506                                        label="Final Value",507                                        value=f"${prediction_result['final_value']:,.2f}"508                                    )509                                510                                with col3:511                                    return_pct = prediction_result['total_return'] * 100512                                    st.metric(513                                        label="Total Return",514                                        value=f"{return_pct:.2f}%",515                                        delta=f"{return_pct:.2f}%"516                                    )517                                518                                st.write(f"Total Trades: {prediction_result['total_trades']}")519                            else:520                                st.error("โŒ Model evaluation failed")521                                522                        except Exception as e:523                            st.error(f"โŒ Evaluation error: {e}")524    525    def trading_controls_panel(self):526        """Trading controls and execution panel"""527        st.header("๐ŸŽฏ Trading Controls")528        529        col1, col2 = st.columns([1, 1])530        531        with col1:532            st.subheader("Backtesting")533            534            if st.button("Run Backtest"):535                if self.data is not None and self.config:536                    with st.spinner("Running backtest..."):537                        try:538                            result = run_backtest(self.config, self.data)539                            if result['success']:540                                st.success("โœ… Backtest completed")541                                542                                # Display backtest results543                                col1, col2, col3 = st.columns(3)544                                545                                with col1:546                                    st.metric(547                                        label="Total Return",548                                        value=f"{result['total_return']:.2%}"549                                    )550                                551                                with col2:552                                    st.metric(553                                        label="Sharpe Ratio",554                                        value=f"{result['sharpe_ratio']:.2f}"555                                    )556                                557                                with col3:558                                    st.metric(559                                        label="Max Drawdown",560                                        value=f"{result['max_drawdown']:.2%}"561                                    )562                                563                                # Store results in session state564                                self.session_state.backtest_results = result565                            else:566                                st.error("โŒ Backtest failed")567                                568                        except Exception as e:569                            st.error(f"โŒ Backtest error: {e}")570        571        with col2:572            st.subheader("Live Trading")573            574            if st.button("Start Live Trading", type="primary"):575                if self.config and self.alpaca_broker:576                    self.session_state.trading_active = True577                    st.success("โœ… Live trading started")578                    579                    # Start trading in background thread580                    def run_trading():581                        try:582                            run_live_trading(self.config, self.data)583                        except Exception as e:584                            st.error(f"Trading error: {e}")585                    586                    trading_thread = threading.Thread(target=run_trading)587                    trading_thread.daemon = True588                    trading_thread.start()589                else:590                    st.warning("โš ๏ธ Please configure Alpaca connection first")591            592            if st.button("Stop Live Trading"):593                self.session_state.trading_active = False594                st.success("โœ… Live trading stopped")595    596    def portfolio_monitoring_panel(self):597        """Portfolio monitoring and analytics panel"""598        st.header("๐Ÿ“Š Portfolio Monitoring")599        600        if not self.alpaca_broker:601            st.warning("โš ๏ธ Connect to Alpaca to view portfolio")602            return603        604        try:605            # Portfolio overview606            account_info = self.alpaca_broker.get_account_info()607            if account_info:608                col1, col2, col3, col4 = st.columns(4)609                610                with col1:611                    st.metric(612                        label="Total Value",613                        value=f"${float(account_info['portfolio_value']):,.2f}"614                    )615                616                with col2:617                    st.metric(618                        label="Cash",619                        value=f"${float(account_info['cash']):,.2f}"620                    )621                622                with col3:623                    st.metric(624                        label="Buying Power",625                        value=f"${float(account_info['buying_power']):,.2f}"626                    )627                628                with col4:629                    equity = float(account_info['equity'])630                    portfolio_value = float(account_info['portfolio_value'])631                    pnl = equity - portfolio_value632                    st.metric(633                        label="P&L",634                        value=f"${pnl:,.2f}",635                        delta=f"{pnl:,.2f}"636                    )637            638            # Positions table639            positions = self.alpaca_broker.get_positions()640            if positions:641                st.subheader("Current Positions")642                643                positions_df = pd.DataFrame(positions)644                if not positions_df.empty:645                    # Calculate additional metrics646                    positions_df['market_value'] = positions_df['quantity'].astype(float) * positions_df['current_price'].astype(float)647                    positions_df['unrealized_pl'] = positions_df['unrealized_pl'].astype(float)648                    positions_df['unrealized_plpc'] = positions_df['unrealized_plpc'].astype(float)649                    650                    # Display positions651                    st.dataframe(652                        positions_df[['symbol', 'quantity', 'current_price', 'market_value', 'unrealized_pl', 'unrealized_plpc']],653                        use_container_width=True654                    )655                    656                    # Position chart657                    fig = px.pie(658                        positions_df, 659                        values='market_value', 660                        names='symbol',661                        title="Portfolio Allocation"662                    )663                    st.plotly_chart(fig, use_container_width=True)664                else:665                    st.info("No positions found")666            else:667                st.info("No current positions")668                669        except Exception as e:670            st.error(f"Error fetching portfolio data: {e}")671    672    def run(self):673        """Main UI application"""674        # Header675        st.markdown('<h1 class="main-header">๐Ÿค– Algorithmic Trading System</h1>', unsafe_allow_html=True)676        677        # Load configuration678        if self.load_configuration():679            self.config = load_config('config.yaml')680        681        # Sidebar navigation682        st.sidebar.title("Navigation")683        page = st.sidebar.selectbox(684            "Select Page",685            ["Dashboard", "Data Ingestion", "Alpaca Integration", "FinRL Training", "Trading Controls", "Portfolio Monitoring"]686        )687        688        # Display system status689        self.display_system_status()690        691        # Page routing692        if page == "Dashboard":693            st.header("๐Ÿ“Š Dashboard")694            695            if self.config:696                st.subheader("System Configuration")697                config_col1, config_col2 = st.columns(2)698                699                with config_col1:700                    st.write(f"**Symbol:** {self.config['trading']['symbol']}")701                    st.write(f"**Capital:** ${self.config['trading']['capital']:,}")702                    st.write(f"**Timeframe:** {self.config['trading']['timeframe']}")703                704                with config_col2:705                    st.write(f"**Broker:** {self.config['execution']['broker_api']}")706                    st.write(f"**FinRL Algorithm:** {self.config['finrl']['algorithm']}")707                    st.write(f"**Risk Max Drawdown:** {self.config['risk']['max_drawdown']:.1%}")708            709            # Quick actions710            st.subheader("Quick Actions")711            col1, col2, col3 = st.columns(3)712            713            with col1:714                if st.button("Load Data", type="primary"):715                    if self.config:716                        with st.spinner("Loading data..."):717                            self.data = load_data(self.config)718                            if self.data is not None:719                                st.success("โœ… Data loaded successfully")720            721            with col2:722                if st.button("Connect Alpaca"):723                    if self.config and self.config['execution']['broker_api'] in ['alpaca_paper', 'alpaca_live']:724                        with st.spinner("Connecting..."):725                            self.alpaca_broker = AlpacaBroker(self.config)726                            st.success("โœ… Connected to Alpaca")727            728            with col3:729                if st.button("Start Training"):730                    if self.data is not None:731                        st.info("Navigate to FinRL Training page to configure and start training")732        733        elif page == "Data Ingestion":734            self.data_ingestion_panel()735        736        elif page == "Alpaca Integration":737            self.alpaca_integration_panel()738        739        elif page == "FinRL Training":740            self.finrl_training_panel()741        742        elif page == "Trading Controls":743            self.trading_controls_panel()744        745        elif page == "Portfolio Monitoring":746            self.portfolio_monitoring_panel()747 748def main():749    """Main application entry point"""750    ui = TradingUI()751    ui.run()752 753def create_streamlit_app():754    """Create and return a Streamlit trading application"""755    return TradingUI()756 757if __name__ == "__main__":758    main()