diff --git a/app.py b/app.py index 8e01999..34e0ca7 100644 --- a/app.py +++ b/app.py @@ -4,62 +4,92 @@ Simple dashboard server for Quantitative Trading Platform. Provides mock metrics for PnL, drawdown, and win rate. """ -from flask import Flask, render_template, jsonify +from flask import Flask, render_template, jsonify, request import random from datetime import datetime, timedelta +from data.connectors import create_moomoo_client, Interval app = Flask(__name__) -def generate_mock_metrics(): - """Generate realistic mock trading metrics.""" - # Simulate daily PnL over last 30 days - end_date = datetime.now() - start_date = end_date - timedelta(days=30) - - daily_pnl = [] - current_pnl = 0 - for i in range(30): - day_pnl = random.uniform(-500, 1500) - current_pnl += day_pnl - daily_pnl.append({ - 'date': (start_date + timedelta(days=i)).strftime('%Y-%m-%d'), - 'pnl': round(day_pnl, 2), - 'cumulative': round(current_pnl, 2) - }) - - # Calculate derived metrics - total_pnl = current_pnl - peak = max([d['cumulative'] for d in daily_pnl]) - trough = min([d['cumulative'] for d in daily_pnl]) - max_drawdown = round(abs(trough - peak), 2) if peak > 0 else 0 - - # Win rate (percentage of profitable days) - profitable_days = sum(1 for d in daily_pnl if d['pnl'] > 0) - win_rate = round(profitable_days / len(daily_pnl) * 100, 1) - - # Current portfolio value (simulated) - portfolio_value = 100000 + total_pnl - - return { - 'total_pnl': round(total_pnl, 2), - 'daily_pnl': daily_pnl, - 'max_drawdown': max_drawdown, - 'win_rate': win_rate, - 'portfolio_value': round(portfolio_value, 2), - 'peak': round(peak, 2), - 'trough': round(trough, 2), - 'last_updated': end_date.isoformat() - } +# Initialize MoomooClient in mock mode (using our LLM scenario generator) +client = create_moomoo_client(mock_mode=True) @app.route('/') def dashboard(): """Serve the dashboard HTML page.""" - return render_template('dashboard.html') + return render_template('index.html') -@app.route('/api/metrics') -def metrics(): - """API endpoint returning current metrics.""" - return jsonify(generate_mock_metrics()) +@app.route('/api/market-data/') +def market_data(symbol): + """ + API endpoint returning market data for a symbol. + Fetches 30 days of daily data by default for the dashboard. + """ + try: + # Fetch OHLCV data from our connector (which uses the simulator) + end_date = datetime.now() + start_date = end_date - timedelta(days=30) + + # Determine interval from query param, default to 1d + interval_str = request.args.get('interval', '1d') + interval = Interval(interval_str) + + ohlcv_data = client.get_ohlcv( + symbol=symbol.upper(), + interval=interval, + start_date=start_date, + end_date=end_date, + limit=100 + ) + + # Transform for frontend + daily_pnl = [] + cumulative = 0 + + # Simple simulation of PnL based on close price changes + # In a real app, this would come from the Strategy/Portfolio engine + initial_balance = 10000.0 + position_size = 10 # shares + + prev_close = ohlcv_data[0].close if ohlcv_data else 0 + + for point in ohlcv_data: + change = point.close - prev_close + pnl = change * position_size + cumulative += pnl + + daily_pnl.append({ + 'date': point.timestamp.strftime('%Y-%m-%d'), + 'pnl': round(pnl, 2), + 'cumulative': round(cumulative, 2), + 'close': point.close + }) + prev_close = point.close + + # Calculate summary metrics + total_pnl = cumulative + peak = max([d['cumulative'] for d in daily_pnl]) if daily_pnl else 0 + trough = min([d['cumulative'] for d in daily_pnl]) if daily_pnl else 0 + max_drawdown = min(0, trough - peak) + + profitable_days = sum(1 for d in daily_pnl if d['pnl'] > 0) + win_rate = (profitable_days / len(daily_pnl) * 100) if daily_pnl else 0 + + return jsonify({ + 'symbol': symbol.upper(), + 'metrics': { + 'total_pnl': round(total_pnl, 2), + 'max_drawdown': round(max_drawdown, 2), + 'win_rate': round(win_rate, 1), + 'portfolio_value': round(initial_balance + total_pnl, 2), + 'peak': round(peak, 2), + 'trough': round(trough, 2) + }, + 'daily_pnl': daily_pnl + }) + + except Exception as e: + return jsonify({'error': str(e)}), 500 @app.route('/health') def health(): diff --git a/data/connectors/moomoo_client.py b/data/connectors/moomoo_client.py index b3f21fe..b1f5fcf 100644 --- a/data/connectors/moomoo_client.py +++ b/data/connectors/moomoo_client.py @@ -265,7 +265,27 @@ class MoomooClient(DataConnector): interval = params.get("interval", "1d") if params else "1d" limit = params.get("limit", 100) if params else 100 - # Generate mock OHLCV data + # Try to load LLM-generated scenario first + scenario_file = f"data/mock_scenarios/{symbol}_rally.json" + try: + import os + if os.path.exists(scenario_file): + with open(scenario_file, 'r') as f: + data = json.load(f) + # Filter/slice data if needed + return { + "code": 0, + "msg": "success", + "data": { + "symbol": symbol, + "interval": interval, + "list": data[:limit] + } + } + except Exception as e: + logger.warning(f"Failed to load mock scenario: {e}") + + # Fallback to algorithmic generation data = [] base_price = random.uniform(100, 200) for i in range(limit): diff --git a/data/mock_scenarios/AAPL_rally.json b/data/mock_scenarios/AAPL_rally.json new file mode 100644 index 0000000..f1b14fc --- /dev/null +++ b/data/mock_scenarios/AAPL_rally.json @@ -0,0 +1,3512 @@ +[ + { + "code": "AAPL", + "time": "2026-02-06 09:30:00", + "open": 150.01, + "high": 150.03, + "low": 149.96, + "close": 149.96, + "volume": 117653 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:31:00", + "open": 150.19, + "high": 150.29, + "low": 150.12, + "close": 150.18, + "volume": 134769 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:32:00", + "open": 150.35, + "high": 150.48, + "low": 150.29, + "close": 150.33, + "volume": 101483 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:33:00", + "open": 150.25, + "high": 150.39, + "low": 150.13, + "close": 150.16, + "volume": 101830 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:34:00", + "open": 150.0, + "high": 150.02, + "low": 149.89, + "close": 149.95, + "volume": 91075 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:35:00", + "open": 150.64, + "high": 150.71, + "low": 150.57, + "close": 150.65, + "volume": 89718 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:36:00", + "open": 150.54, + "high": 150.64, + "low": 150.52, + "close": 150.59, + "volume": 42719 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:37:00", + "open": 150.72, + "high": 150.76, + "low": 150.67, + "close": 150.76, + "volume": 147321 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:38:00", + "open": 150.57, + "high": 150.69, + "low": 150.56, + "close": 150.61, + "volume": 126502 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:39:00", + "open": 150.8, + "high": 150.85, + "low": 150.7, + "close": 150.76, + "volume": 71729 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:40:00", + "open": 150.94, + "high": 150.98, + "low": 150.91, + "close": 150.94, + "volume": 152294 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:41:00", + "open": 150.9, + "high": 151.04, + "low": 150.84, + "close": 150.98, + "volume": 89332 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:42:00", + "open": 151.09, + "high": 151.12, + "low": 151.0, + "close": 151.12, + "volume": 150338 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:43:00", + "open": 151.21, + "high": 151.24, + "low": 151.19, + "close": 151.24, + "volume": 88494 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:44:00", + "open": 150.83, + "high": 150.88, + "low": 150.83, + "close": 150.86, + "volume": 138055 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:45:00", + "open": 151.32, + "high": 151.38, + "low": 151.29, + "close": 151.29, + "volume": 153029 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:46:00", + "open": 151.26, + "high": 151.31, + "low": 151.16, + "close": 151.26, + "volume": 113010 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:47:00", + "open": 151.39, + "high": 151.45, + "low": 151.32, + "close": 151.39, + "volume": 57882 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:48:00", + "open": 151.49, + "high": 151.6, + "low": 151.42, + "close": 151.51, + "volume": 78498 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:49:00", + "open": 151.9, + "high": 151.93, + "low": 151.85, + "close": 151.88, + "volume": 88656 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:50:00", + "open": 151.37, + "high": 151.42, + "low": 151.34, + "close": 151.42, + "volume": 114804 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:51:00", + "open": 151.79, + "high": 151.86, + "low": 151.69, + "close": 151.76, + "volume": 38559 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:52:00", + "open": 151.95, + "high": 151.97, + "low": 151.89, + "close": 151.89, + "volume": 130343 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:53:00", + "open": 151.95, + "high": 152.04, + "low": 151.81, + "close": 151.89, + "volume": 141159 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:54:00", + "open": 152.05, + "high": 152.18, + "low": 151.99, + "close": 152.12, + "volume": 137978 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:55:00", + "open": 152.09, + "high": 152.12, + "low": 152.08, + "close": 152.12, + "volume": 178645 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:56:00", + "open": 152.06, + "high": 152.08, + "low": 152.0, + "close": 152.08, + "volume": 156735 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:57:00", + "open": 152.03, + "high": 152.06, + "low": 151.88, + "close": 152.02, + "volume": 111257 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:58:00", + "open": 152.26, + "high": 152.28, + "low": 152.22, + "close": 152.23, + "volume": 129629 + }, + { + "code": "AAPL", + "time": "2026-02-06 09:59:00", + "open": 152.34, + "high": 152.37, + "low": 152.27, + "close": 152.37, + "volume": 10414 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:00:00", + "open": 152.44, + "high": 152.47, + "low": 152.36, + "close": 152.42, + "volume": 46555 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:01:00", + "open": 152.39, + "high": 152.44, + "low": 152.34, + "close": 152.38, + "volume": 24945 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:02:00", + "open": 152.51, + "high": 152.52, + "low": 152.43, + "close": 152.5, + "volume": 54565 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:03:00", + "open": 152.45, + "high": 152.5, + "low": 152.35, + "close": 152.48, + "volume": 28180 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:04:00", + "open": 152.56, + "high": 152.6, + "low": 152.53, + "close": 152.56, + "volume": 44510 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:05:00", + "open": 152.47, + "high": 152.6, + "low": 152.41, + "close": 152.48, + "volume": 48715 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:06:00", + "open": 152.37, + "high": 152.49, + "low": 152.34, + "close": 152.34, + "volume": 37389 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:07:00", + "open": 152.35, + "high": 152.35, + "low": 152.31, + "close": 152.34, + "volume": 36620 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:08:00", + "open": 152.35, + "high": 152.41, + "low": 152.32, + "close": 152.35, + "volume": 31249 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:09:00", + "open": 152.34, + "high": 152.36, + "low": 152.29, + "close": 152.34, + "volume": 36921 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:10:00", + "open": 152.31, + "high": 152.37, + "low": 152.2, + "close": 152.27, + "volume": 29572 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:11:00", + "open": 152.44, + "high": 152.49, + "low": 152.41, + "close": 152.41, + "volume": 49226 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:12:00", + "open": 152.5, + "high": 152.62, + "low": 152.39, + "close": 152.47, + "volume": 58348 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:13:00", + "open": 152.38, + "high": 152.46, + "low": 152.36, + "close": 152.42, + "volume": 69177 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:14:00", + "open": 152.25, + "high": 152.27, + "low": 152.2, + "close": 152.25, + "volume": 45346 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:15:00", + "open": 152.28, + "high": 152.3, + "low": 152.25, + "close": 152.25, + "volume": 33679 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:16:00", + "open": 152.38, + "high": 152.41, + "low": 152.34, + "close": 152.34, + "volume": 35781 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:17:00", + "open": 152.19, + "high": 152.19, + "low": 152.18, + "close": 152.18, + "volume": 32428 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:18:00", + "open": 152.35, + "high": 152.39, + "low": 152.32, + "close": 152.35, + "volume": 26308 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:19:00", + "open": 152.32, + "high": 152.33, + "low": 152.31, + "close": 152.31, + "volume": 51745 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:20:00", + "open": 152.25, + "high": 152.26, + "low": 152.21, + "close": 152.22, + "volume": 53749 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:21:00", + "open": 152.21, + "high": 152.22, + "low": 152.13, + "close": 152.15, + "volume": 44922 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:22:00", + "open": 152.1, + "high": 152.13, + "low": 152.08, + "close": 152.11, + "volume": 68576 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:23:00", + "open": 152.22, + "high": 152.25, + "low": 152.09, + "close": 152.16, + "volume": 41645 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:24:00", + "open": 151.97, + "high": 151.99, + "low": 151.92, + "close": 151.92, + "volume": 28776 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:25:00", + "open": 152.23, + "high": 152.24, + "low": 152.19, + "close": 152.19, + "volume": 31842 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:26:00", + "open": 152.06, + "high": 152.12, + "low": 152.02, + "close": 152.12, + "volume": 15169 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:27:00", + "open": 152.2, + "high": 152.2, + "low": 152.18, + "close": 152.2, + "volume": 36510 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:28:00", + "open": 151.97, + "high": 152.03, + "low": 151.96, + "close": 151.99, + "volume": 53262 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:29:00", + "open": 152.2, + "high": 152.25, + "low": 152.13, + "close": 152.21, + "volume": 34254 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:30:00", + "open": 152.27, + "high": 152.27, + "low": 152.26, + "close": 152.26, + "volume": 30793 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:31:00", + "open": 152.23, + "high": 152.29, + "low": 152.2, + "close": 152.23, + "volume": 38183 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:32:00", + "open": 152.14, + "high": 152.2, + "low": 152.13, + "close": 152.15, + "volume": 37809 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:33:00", + "open": 151.98, + "high": 152.01, + "low": 151.84, + "close": 151.9, + "volume": 40284 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:34:00", + "open": 152.02, + "high": 152.11, + "low": 151.94, + "close": 152.0, + "volume": 54762 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:35:00", + "open": 152.18, + "high": 152.21, + "low": 152.12, + "close": 152.17, + "volume": 39920 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:36:00", + "open": 152.05, + "high": 152.08, + "low": 152.04, + "close": 152.07, + "volume": 40272 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:37:00", + "open": 152.21, + "high": 152.22, + "low": 152.19, + "close": 152.19, + "volume": 17594 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:38:00", + "open": 152.03, + "high": 152.14, + "low": 151.93, + "close": 152.06, + "volume": 54523 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:39:00", + "open": 152.03, + "high": 152.04, + "low": 152.01, + "close": 152.01, + "volume": 55643 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:40:00", + "open": 152.14, + "high": 152.14, + "low": 152.05, + "close": 152.13, + "volume": 42305 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:41:00", + "open": 151.84, + "high": 151.92, + "low": 151.83, + "close": 151.86, + "volume": 35562 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:42:00", + "open": 151.93, + "high": 151.93, + "low": 151.89, + "close": 151.93, + "volume": 49984 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:43:00", + "open": 152.11, + "high": 152.14, + "low": 152.09, + "close": 152.1, + "volume": 28937 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:44:00", + "open": 152.09, + "high": 152.13, + "low": 152.06, + "close": 152.07, + "volume": 36507 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:45:00", + "open": 151.77, + "high": 151.78, + "low": 151.76, + "close": 151.76, + "volume": 46956 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:46:00", + "open": 151.93, + "high": 152.03, + "low": 151.84, + "close": 151.95, + "volume": 48768 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:47:00", + "open": 151.79, + "high": 151.8, + "low": 151.75, + "close": 151.8, + "volume": 22185 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:48:00", + "open": 151.99, + "high": 152.02, + "low": 151.92, + "close": 151.99, + "volume": 36857 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:49:00", + "open": 152.0, + "high": 152.08, + "low": 151.95, + "close": 151.98, + "volume": 43855 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:50:00", + "open": 151.92, + "high": 151.99, + "low": 151.87, + "close": 151.95, + "volume": 52191 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:51:00", + "open": 151.99, + "high": 152.0, + "low": 151.95, + "close": 151.96, + "volume": 34403 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:52:00", + "open": 151.8, + "high": 151.82, + "low": 151.77, + "close": 151.77, + "volume": 39872 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:53:00", + "open": 151.7, + "high": 151.77, + "low": 151.67, + "close": 151.71, + "volume": 27663 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:54:00", + "open": 151.72, + "high": 151.81, + "low": 151.65, + "close": 151.71, + "volume": 33664 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:55:00", + "open": 151.78, + "high": 151.83, + "low": 151.72, + "close": 151.79, + "volume": 49398 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:56:00", + "open": 151.89, + "high": 151.95, + "low": 151.83, + "close": 151.88, + "volume": 24473 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:57:00", + "open": 151.94, + "high": 151.98, + "low": 151.91, + "close": 151.94, + "volume": 30629 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:58:00", + "open": 151.82, + "high": 151.85, + "low": 151.79, + "close": 151.8, + "volume": 44168 + }, + { + "code": "AAPL", + "time": "2026-02-06 10:59:00", + "open": 151.88, + "high": 151.94, + "low": 151.85, + "close": 151.94, + "volume": 33790 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:00:00", + "open": 151.82, + "high": 151.83, + "low": 151.74, + "close": 151.77, + "volume": 34241 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:01:00", + "open": 151.89, + "high": 151.92, + "low": 151.84, + "close": 151.89, + "volume": 22155 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:02:00", + "open": 151.83, + "high": 151.85, + "low": 151.81, + "close": 151.83, + "volume": 47849 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:03:00", + "open": 151.81, + "high": 151.82, + "low": 151.77, + "close": 151.8, + "volume": 39661 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:04:00", + "open": 151.79, + "high": 151.84, + "low": 151.74, + "close": 151.77, + "volume": 19618 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:05:00", + "open": 151.81, + "high": 151.85, + "low": 151.79, + "close": 151.85, + "volume": 21599 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:06:00", + "open": 151.83, + "high": 151.86, + "low": 151.81, + "close": 151.81, + "volume": 26281 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:07:00", + "open": 151.88, + "high": 151.96, + "low": 151.84, + "close": 151.89, + "volume": 18354 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:08:00", + "open": 151.85, + "high": 151.87, + "low": 151.82, + "close": 151.86, + "volume": 28074 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:09:00", + "open": 151.85, + "high": 151.91, + "low": 151.81, + "close": 151.87, + "volume": 34495 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:10:00", + "open": 151.92, + "high": 151.96, + "low": 151.85, + "close": 151.91, + "volume": 17858 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:11:00", + "open": 151.94, + "high": 151.97, + "low": 151.93, + "close": 151.97, + "volume": 27146 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:12:00", + "open": 151.84, + "high": 151.84, + "low": 151.78, + "close": 151.81, + "volume": 22624 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:13:00", + "open": 151.85, + "high": 151.87, + "low": 151.8, + "close": 151.87, + "volume": 28100 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:14:00", + "open": 151.82, + "high": 151.82, + "low": 151.78, + "close": 151.78, + "volume": 18332 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:15:00", + "open": 151.81, + "high": 151.93, + "low": 151.81, + "close": 151.84, + "volume": 29752 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:16:00", + "open": 151.92, + "high": 151.94, + "low": 151.91, + "close": 151.91, + "volume": 9249 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:17:00", + "open": 152.08, + "high": 152.15, + "low": 152.05, + "close": 152.07, + "volume": 31248 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:18:00", + "open": 151.86, + "high": 151.86, + "low": 151.79, + "close": 151.84, + "volume": 9883 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:19:00", + "open": 151.84, + "high": 151.85, + "low": 151.78, + "close": 151.8, + "volume": 24917 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:20:00", + "open": 151.9, + "high": 151.9, + "low": 151.88, + "close": 151.9, + "volume": 30152 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:21:00", + "open": 151.85, + "high": 151.89, + "low": 151.84, + "close": 151.84, + "volume": 35515 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:22:00", + "open": 151.94, + "high": 151.97, + "low": 151.91, + "close": 151.91, + "volume": 21558 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:23:00", + "open": 151.92, + "high": 151.93, + "low": 151.9, + "close": 151.91, + "volume": 24241 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:24:00", + "open": 151.92, + "high": 151.94, + "low": 151.91, + "close": 151.94, + "volume": 33565 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:25:00", + "open": 151.92, + "high": 151.95, + "low": 151.89, + "close": 151.91, + "volume": 27686 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:26:00", + "open": 151.84, + "high": 151.86, + "low": 151.81, + "close": 151.81, + "volume": 23263 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:27:00", + "open": 151.81, + "high": 151.87, + "low": 151.75, + "close": 151.81, + "volume": 21094 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:28:00", + "open": 152.02, + "high": 152.05, + "low": 152.0, + "close": 152.05, + "volume": 20473 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:29:00", + "open": 152.0, + "high": 152.05, + "low": 151.92, + "close": 152.02, + "volume": 22919 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:30:00", + "open": 151.79, + "high": 151.82, + "low": 151.79, + "close": 151.81, + "volume": 17197 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:31:00", + "open": 151.81, + "high": 151.86, + "low": 151.79, + "close": 151.83, + "volume": 29113 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:32:00", + "open": 151.91, + "high": 151.97, + "low": 151.88, + "close": 151.9, + "volume": 29612 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:33:00", + "open": 151.98, + "high": 152.0, + "low": 151.91, + "close": 151.97, + "volume": 28664 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:34:00", + "open": 151.85, + "high": 151.87, + "low": 151.76, + "close": 151.86, + "volume": 24329 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:35:00", + "open": 151.78, + "high": 151.83, + "low": 151.77, + "close": 151.77, + "volume": 36795 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:36:00", + "open": 151.87, + "high": 151.9, + "low": 151.74, + "close": 151.81, + "volume": 23104 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:37:00", + "open": 151.84, + "high": 151.85, + "low": 151.81, + "close": 151.83, + "volume": 16206 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:38:00", + "open": 152.0, + "high": 152.02, + "low": 151.96, + "close": 152.0, + "volume": 29156 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:39:00", + "open": 151.9, + "high": 151.93, + "low": 151.85, + "close": 151.93, + "volume": 32656 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:40:00", + "open": 152.0, + "high": 152.02, + "low": 151.99, + "close": 152.0, + "volume": 18937 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:41:00", + "open": 151.99, + "high": 152.0, + "low": 151.95, + "close": 151.96, + "volume": 26729 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:42:00", + "open": 151.89, + "high": 151.89, + "low": 151.83, + "close": 151.87, + "volume": 31145 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:43:00", + "open": 151.9, + "high": 151.91, + "low": 151.86, + "close": 151.9, + "volume": 18965 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:44:00", + "open": 151.9, + "high": 151.91, + "low": 151.87, + "close": 151.88, + "volume": 24509 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:45:00", + "open": 152.01, + "high": 152.07, + "low": 152.0, + "close": 152.01, + "volume": 24710 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:46:00", + "open": 152.23, + "high": 152.26, + "low": 152.2, + "close": 152.2, + "volume": 13515 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:47:00", + "open": 151.99, + "high": 152.01, + "low": 151.95, + "close": 151.97, + "volume": 27147 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:48:00", + "open": 152.03, + "high": 152.09, + "low": 151.97, + "close": 152.03, + "volume": 29462 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:49:00", + "open": 152.12, + "high": 152.14, + "low": 152.09, + "close": 152.1, + "volume": 26768 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:50:00", + "open": 151.93, + "high": 151.95, + "low": 151.93, + "close": 151.93, + "volume": 14566 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:51:00", + "open": 152.12, + "high": 152.17, + "low": 152.11, + "close": 152.15, + "volume": 16873 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:52:00", + "open": 151.91, + "high": 151.93, + "low": 151.82, + "close": 151.89, + "volume": 19499 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:53:00", + "open": 151.8, + "high": 151.82, + "low": 151.71, + "close": 151.8, + "volume": 26350 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:54:00", + "open": 151.99, + "high": 152.02, + "low": 151.94, + "close": 152.01, + "volume": 19057 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:55:00", + "open": 151.92, + "high": 151.94, + "low": 151.82, + "close": 151.89, + "volume": 21402 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:56:00", + "open": 152.03, + "high": 152.04, + "low": 152.02, + "close": 152.02, + "volume": 18461 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:57:00", + "open": 151.93, + "high": 151.97, + "low": 151.89, + "close": 151.92, + "volume": 21081 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:58:00", + "open": 152.02, + "high": 152.05, + "low": 152.01, + "close": 152.01, + "volume": 31721 + }, + { + "code": "AAPL", + "time": "2026-02-06 11:59:00", + "open": 151.93, + "high": 151.93, + "low": 151.84, + "close": 151.88, + "volume": 22497 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:00:00", + "open": 151.85, + "high": 151.92, + "low": 151.82, + "close": 151.88, + "volume": 29379 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:01:00", + "open": 151.95, + "high": 152.02, + "low": 151.95, + "close": 151.96, + "volume": 21624 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:02:00", + "open": 151.98, + "high": 152.01, + "low": 151.91, + "close": 151.95, + "volume": 26570 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:03:00", + "open": 151.97, + "high": 152.01, + "low": 151.95, + "close": 151.97, + "volume": 42937 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:04:00", + "open": 151.93, + "high": 151.96, + "low": 151.86, + "close": 151.96, + "volume": 21990 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:05:00", + "open": 151.99, + "high": 152.08, + "low": 151.97, + "close": 152.03, + "volume": 19215 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:06:00", + "open": 152.07, + "high": 152.09, + "low": 152.04, + "close": 152.06, + "volume": 41572 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:07:00", + "open": 152.08, + "high": 152.14, + "low": 152.07, + "close": 152.14, + "volume": 20107 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:08:00", + "open": 152.04, + "high": 152.06, + "low": 152.0, + "close": 152.03, + "volume": 21686 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:09:00", + "open": 152.14, + "high": 152.18, + "low": 152.11, + "close": 152.17, + "volume": 29122 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:10:00", + "open": 151.89, + "high": 151.92, + "low": 151.86, + "close": 151.87, + "volume": 23378 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:11:00", + "open": 152.01, + "high": 152.06, + "low": 152.0, + "close": 152.0, + "volume": 26731 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:12:00", + "open": 151.97, + "high": 152.01, + "low": 151.95, + "close": 151.99, + "volume": 24287 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:13:00", + "open": 152.04, + "high": 152.08, + "low": 151.93, + "close": 152.02, + "volume": 23320 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:14:00", + "open": 151.84, + "high": 151.89, + "low": 151.8, + "close": 151.85, + "volume": 14499 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:15:00", + "open": 152.05, + "high": 152.11, + "low": 152.05, + "close": 152.06, + "volume": 19801 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:16:00", + "open": 152.07, + "high": 152.07, + "low": 152.03, + "close": 152.06, + "volume": 21210 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:17:00", + "open": 152.21, + "high": 152.27, + "low": 152.18, + "close": 152.23, + "volume": 34212 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:18:00", + "open": 152.17, + "high": 152.17, + "low": 152.11, + "close": 152.16, + "volume": 27982 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:19:00", + "open": 152.23, + "high": 152.33, + "low": 152.23, + "close": 152.24, + "volume": 25068 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:20:00", + "open": 152.08, + "high": 152.18, + "low": 152.07, + "close": 152.07, + "volume": 29464 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:21:00", + "open": 152.09, + "high": 152.14, + "low": 152.09, + "close": 152.13, + "volume": 24578 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:22:00", + "open": 152.19, + "high": 152.2, + "low": 152.11, + "close": 152.18, + "volume": 22840 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:23:00", + "open": 152.12, + "high": 152.19, + "low": 152.11, + "close": 152.14, + "volume": 35044 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:24:00", + "open": 152.02, + "high": 152.05, + "low": 151.99, + "close": 152.03, + "volume": 20304 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:25:00", + "open": 152.08, + "high": 152.17, + "low": 152.06, + "close": 152.09, + "volume": 27675 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:26:00", + "open": 152.03, + "high": 152.06, + "low": 152.03, + "close": 152.03, + "volume": 47630 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:27:00", + "open": 152.13, + "high": 152.19, + "low": 152.08, + "close": 152.11, + "volume": 41736 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:28:00", + "open": 152.15, + "high": 152.17, + "low": 152.12, + "close": 152.17, + "volume": 20753 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:29:00", + "open": 152.14, + "high": 152.17, + "low": 152.11, + "close": 152.14, + "volume": 29359 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:30:00", + "open": 152.12, + "high": 152.14, + "low": 152.1, + "close": 152.11, + "volume": 24444 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:31:00", + "open": 152.09, + "high": 152.12, + "low": 152.06, + "close": 152.1, + "volume": 27694 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:32:00", + "open": 152.13, + "high": 152.2, + "low": 152.12, + "close": 152.14, + "volume": 25585 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:33:00", + "open": 152.0, + "high": 152.05, + "low": 151.95, + "close": 152.03, + "volume": 19038 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:34:00", + "open": 152.17, + "high": 152.19, + "low": 152.14, + "close": 152.16, + "volume": 35639 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:35:00", + "open": 152.05, + "high": 152.06, + "low": 152.03, + "close": 152.05, + "volume": 30886 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:36:00", + "open": 152.01, + "high": 152.06, + "low": 151.94, + "close": 152.03, + "volume": 14147 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:37:00", + "open": 152.04, + "high": 152.05, + "low": 152.03, + "close": 152.03, + "volume": 31172 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:38:00", + "open": 152.23, + "high": 152.27, + "low": 152.21, + "close": 152.25, + "volume": 32207 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:39:00", + "open": 151.95, + "high": 151.97, + "low": 151.88, + "close": 151.94, + "volume": 31772 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:40:00", + "open": 152.07, + "high": 152.09, + "low": 152.06, + "close": 152.06, + "volume": 31746 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:41:00", + "open": 152.05, + "high": 152.07, + "low": 152.01, + "close": 152.03, + "volume": 15923 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:42:00", + "open": 152.15, + "high": 152.18, + "low": 152.12, + "close": 152.14, + "volume": 21205 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:43:00", + "open": 152.19, + "high": 152.28, + "low": 152.15, + "close": 152.19, + "volume": 7540 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:44:00", + "open": 152.14, + "high": 152.2, + "low": 152.09, + "close": 152.13, + "volume": 22697 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:45:00", + "open": 152.04, + "high": 152.12, + "low": 151.99, + "close": 152.03, + "volume": 31114 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:46:00", + "open": 152.29, + "high": 152.37, + "low": 152.26, + "close": 152.32, + "volume": 31131 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:47:00", + "open": 152.07, + "high": 152.08, + "low": 152.0, + "close": 152.07, + "volume": 19946 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:48:00", + "open": 152.1, + "high": 152.14, + "low": 152.1, + "close": 152.14, + "volume": 11692 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:49:00", + "open": 152.21, + "high": 152.24, + "low": 152.19, + "close": 152.19, + "volume": 20677 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:50:00", + "open": 152.21, + "high": 152.22, + "low": 152.16, + "close": 152.19, + "volume": 24727 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:51:00", + "open": 152.12, + "high": 152.13, + "low": 152.12, + "close": 152.12, + "volume": 27371 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:52:00", + "open": 152.14, + "high": 152.16, + "low": 152.11, + "close": 152.12, + "volume": 27971 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:53:00", + "open": 152.25, + "high": 152.27, + "low": 152.21, + "close": 152.27, + "volume": 11471 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:54:00", + "open": 152.2, + "high": 152.22, + "low": 152.18, + "close": 152.19, + "volume": 16542 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:55:00", + "open": 152.11, + "high": 152.15, + "low": 152.08, + "close": 152.11, + "volume": 37466 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:56:00", + "open": 152.21, + "high": 152.24, + "low": 152.14, + "close": 152.2, + "volume": 39887 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:57:00", + "open": 152.15, + "high": 152.24, + "low": 152.12, + "close": 152.21, + "volume": 17046 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:58:00", + "open": 152.22, + "high": 152.23, + "low": 152.2, + "close": 152.23, + "volume": 22581 + }, + { + "code": "AAPL", + "time": "2026-02-06 12:59:00", + "open": 152.15, + "high": 152.15, + "low": 152.11, + "close": 152.15, + "volume": 19462 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:00:00", + "open": 152.44, + "high": 152.47, + "low": 152.38, + "close": 152.43, + "volume": 72131 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:01:00", + "open": 152.31, + "high": 152.33, + "low": 152.22, + "close": 152.26, + "volume": 36256 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:02:00", + "open": 152.51, + "high": 152.55, + "low": 152.48, + "close": 152.52, + "volume": 53436 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:03:00", + "open": 152.21, + "high": 152.28, + "low": 152.19, + "close": 152.19, + "volume": 31863 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:04:00", + "open": 152.2, + "high": 152.25, + "low": 152.18, + "close": 152.2, + "volume": 32698 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:05:00", + "open": 151.98, + "high": 152.04, + "low": 151.95, + "close": 152.04, + "volume": 80328 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:06:00", + "open": 152.24, + "high": 152.24, + "low": 152.22, + "close": 152.23, + "volume": 65729 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:07:00", + "open": 152.01, + "high": 152.03, + "low": 151.99, + "close": 152.0, + "volume": 56023 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:08:00", + "open": 152.37, + "high": 152.58, + "low": 152.33, + "close": 152.45, + "volume": 82238 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:09:00", + "open": 152.26, + "high": 152.31, + "low": 152.14, + "close": 152.3, + "volume": 49490 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:10:00", + "open": 152.32, + "high": 152.37, + "low": 152.31, + "close": 152.36, + "volume": 72813 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:11:00", + "open": 152.46, + "high": 152.5, + "low": 152.43, + "close": 152.5, + "volume": 73432 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:12:00", + "open": 152.36, + "high": 152.4, + "low": 152.32, + "close": 152.39, + "volume": 67717 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:13:00", + "open": 152.21, + "high": 152.25, + "low": 152.17, + "close": 152.25, + "volume": 72179 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:14:00", + "open": 152.17, + "high": 152.21, + "low": 152.14, + "close": 152.2, + "volume": 90641 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:15:00", + "open": 152.29, + "high": 152.35, + "low": 152.26, + "close": 152.29, + "volume": 78833 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:16:00", + "open": 152.33, + "high": 152.35, + "low": 152.26, + "close": 152.31, + "volume": 67907 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:17:00", + "open": 152.52, + "high": 152.53, + "low": 152.51, + "close": 152.53, + "volume": 42707 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:18:00", + "open": 152.31, + "high": 152.33, + "low": 152.3, + "close": 152.31, + "volume": 66167 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:19:00", + "open": 152.15, + "high": 152.18, + "low": 152.12, + "close": 152.14, + "volume": 51629 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:20:00", + "open": 152.51, + "high": 152.57, + "low": 152.44, + "close": 152.5, + "volume": 53788 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:21:00", + "open": 152.39, + "high": 152.44, + "low": 152.24, + "close": 152.39, + "volume": 72991 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:22:00", + "open": 152.49, + "high": 152.53, + "low": 152.48, + "close": 152.53, + "volume": 38611 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:23:00", + "open": 152.6, + "high": 152.68, + "low": 152.55, + "close": 152.61, + "volume": 91265 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:24:00", + "open": 152.4, + "high": 152.51, + "low": 152.37, + "close": 152.42, + "volume": 48303 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:25:00", + "open": 152.29, + "high": 152.36, + "low": 152.25, + "close": 152.29, + "volume": 81730 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:26:00", + "open": 152.37, + "high": 152.43, + "low": 152.29, + "close": 152.39, + "volume": 19341 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:27:00", + "open": 152.57, + "high": 152.61, + "low": 152.55, + "close": 152.56, + "volume": 75687 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:28:00", + "open": 152.45, + "high": 152.49, + "low": 152.4, + "close": 152.41, + "volume": 52002 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:29:00", + "open": 152.43, + "high": 152.51, + "low": 152.37, + "close": 152.43, + "volume": 67259 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:30:00", + "open": 152.49, + "high": 152.57, + "low": 152.48, + "close": 152.48, + "volume": 40487 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:31:00", + "open": 152.51, + "high": 152.52, + "low": 152.49, + "close": 152.5, + "volume": 41508 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:32:00", + "open": 152.64, + "high": 152.64, + "low": 152.54, + "close": 152.54, + "volume": 74711 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:33:00", + "open": 152.25, + "high": 152.28, + "low": 152.19, + "close": 152.2, + "volume": 48301 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:34:00", + "open": 152.5, + "high": 152.54, + "low": 152.47, + "close": 152.54, + "volume": 70736 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:35:00", + "open": 152.54, + "high": 152.57, + "low": 152.47, + "close": 152.57, + "volume": 71509 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:36:00", + "open": 152.56, + "high": 152.81, + "low": 152.49, + "close": 152.65, + "volume": 73784 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:37:00", + "open": 152.52, + "high": 152.56, + "low": 152.47, + "close": 152.48, + "volume": 58450 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:38:00", + "open": 152.52, + "high": 152.62, + "low": 152.48, + "close": 152.49, + "volume": 40502 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:39:00", + "open": 152.43, + "high": 152.5, + "low": 152.39, + "close": 152.39, + "volume": 54809 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:40:00", + "open": 152.43, + "high": 152.49, + "low": 152.38, + "close": 152.49, + "volume": 98353 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:41:00", + "open": 152.62, + "high": 152.65, + "low": 152.55, + "close": 152.65, + "volume": 51413 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:42:00", + "open": 152.6, + "high": 152.62, + "low": 152.54, + "close": 152.62, + "volume": 83471 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:43:00", + "open": 152.6, + "high": 152.61, + "low": 152.49, + "close": 152.57, + "volume": 45295 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:44:00", + "open": 152.52, + "high": 152.57, + "low": 152.51, + "close": 152.51, + "volume": 101097 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:45:00", + "open": 152.41, + "high": 152.46, + "low": 152.31, + "close": 152.43, + "volume": 76563 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:46:00", + "open": 152.45, + "high": 152.5, + "low": 152.41, + "close": 152.41, + "volume": 65210 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:47:00", + "open": 152.67, + "high": 152.69, + "low": 152.61, + "close": 152.67, + "volume": 31983 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:48:00", + "open": 152.64, + "high": 152.65, + "low": 152.6, + "close": 152.62, + "volume": 41240 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:49:00", + "open": 152.37, + "high": 152.44, + "low": 152.28, + "close": 152.34, + "volume": 97684 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:50:00", + "open": 152.49, + "high": 152.61, + "low": 152.48, + "close": 152.57, + "volume": 77113 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:51:00", + "open": 152.37, + "high": 152.48, + "low": 152.3, + "close": 152.37, + "volume": 66897 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:52:00", + "open": 152.51, + "high": 152.58, + "low": 152.45, + "close": 152.5, + "volume": 61295 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:53:00", + "open": 152.56, + "high": 152.62, + "low": 152.46, + "close": 152.53, + "volume": 47304 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:54:00", + "open": 152.94, + "high": 152.98, + "low": 152.86, + "close": 152.94, + "volume": 79302 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:55:00", + "open": 152.67, + "high": 152.75, + "low": 152.63, + "close": 152.69, + "volume": 55877 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:56:00", + "open": 152.9, + "high": 152.93, + "low": 152.84, + "close": 152.84, + "volume": 42836 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:57:00", + "open": 152.46, + "high": 152.54, + "low": 152.45, + "close": 152.45, + "volume": 75158 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:58:00", + "open": 152.74, + "high": 152.84, + "low": 152.67, + "close": 152.74, + "volume": 81843 + }, + { + "code": "AAPL", + "time": "2026-02-06 13:59:00", + "open": 152.73, + "high": 152.8, + "low": 152.72, + "close": 152.77, + "volume": 47826 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:00:00", + "open": 152.63, + "high": 152.67, + "low": 152.56, + "close": 152.56, + "volume": 67388 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:01:00", + "open": 152.46, + "high": 152.56, + "low": 152.42, + "close": 152.42, + "volume": 60640 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:02:00", + "open": 152.49, + "high": 152.6, + "low": 152.43, + "close": 152.5, + "volume": 81858 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:03:00", + "open": 152.68, + "high": 152.74, + "low": 152.56, + "close": 152.65, + "volume": 39640 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:04:00", + "open": 152.51, + "high": 152.51, + "low": 152.45, + "close": 152.49, + "volume": 62271 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:05:00", + "open": 152.53, + "high": 152.62, + "low": 152.53, + "close": 152.57, + "volume": 41145 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:06:00", + "open": 152.6, + "high": 152.66, + "low": 152.58, + "close": 152.6, + "volume": 93244 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:07:00", + "open": 152.77, + "high": 152.78, + "low": 152.69, + "close": 152.73, + "volume": 64955 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:08:00", + "open": 152.58, + "high": 152.66, + "low": 152.56, + "close": 152.58, + "volume": 78185 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:09:00", + "open": 152.72, + "high": 152.78, + "low": 152.66, + "close": 152.72, + "volume": 31411 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:10:00", + "open": 152.78, + "high": 152.83, + "low": 152.78, + "close": 152.82, + "volume": 60452 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:11:00", + "open": 152.8, + "high": 152.87, + "low": 152.78, + "close": 152.83, + "volume": 59356 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:12:00", + "open": 152.76, + "high": 152.77, + "low": 152.69, + "close": 152.76, + "volume": 63029 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:13:00", + "open": 152.82, + "high": 152.91, + "low": 152.71, + "close": 152.77, + "volume": 48524 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:14:00", + "open": 152.78, + "high": 152.8, + "low": 152.76, + "close": 152.77, + "volume": 68784 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:15:00", + "open": 152.63, + "high": 152.64, + "low": 152.6, + "close": 152.63, + "volume": 38197 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:16:00", + "open": 152.59, + "high": 152.64, + "low": 152.57, + "close": 152.62, + "volume": 89842 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:17:00", + "open": 152.54, + "high": 152.57, + "low": 152.49, + "close": 152.52, + "volume": 32337 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:18:00", + "open": 152.68, + "high": 152.72, + "low": 152.64, + "close": 152.64, + "volume": 85638 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:19:00", + "open": 152.72, + "high": 152.76, + "low": 152.68, + "close": 152.68, + "volume": 35393 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:20:00", + "open": 152.68, + "high": 152.68, + "low": 152.65, + "close": 152.66, + "volume": 55823 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:21:00", + "open": 152.9, + "high": 152.92, + "low": 152.83, + "close": 152.9, + "volume": 33548 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:22:00", + "open": 152.8, + "high": 152.88, + "low": 152.78, + "close": 152.86, + "volume": 58652 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:23:00", + "open": 152.63, + "high": 152.71, + "low": 152.57, + "close": 152.6, + "volume": 60085 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:24:00", + "open": 152.85, + "high": 152.91, + "low": 152.74, + "close": 152.81, + "volume": 31410 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:25:00", + "open": 152.76, + "high": 152.79, + "low": 152.69, + "close": 152.77, + "volume": 64574 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:26:00", + "open": 152.97, + "high": 153.03, + "low": 152.91, + "close": 153.01, + "volume": 39667 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:27:00", + "open": 152.87, + "high": 152.88, + "low": 152.8, + "close": 152.82, + "volume": 65136 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:28:00", + "open": 152.89, + "high": 152.93, + "low": 152.89, + "close": 152.93, + "volume": 48122 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:29:00", + "open": 152.82, + "high": 152.87, + "low": 152.81, + "close": 152.86, + "volume": 60207 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:30:00", + "open": 152.9, + "high": 153.02, + "low": 152.83, + "close": 152.9, + "volume": 44379 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:31:00", + "open": 152.62, + "high": 152.71, + "low": 152.57, + "close": 152.64, + "volume": 66589 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:32:00", + "open": 152.88, + "high": 152.91, + "low": 152.88, + "close": 152.91, + "volume": 43050 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:33:00", + "open": 152.99, + "high": 153.07, + "low": 152.95, + "close": 152.97, + "volume": 49705 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:34:00", + "open": 152.88, + "high": 152.96, + "low": 152.84, + "close": 152.92, + "volume": 78703 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:35:00", + "open": 152.89, + "high": 152.91, + "low": 152.86, + "close": 152.86, + "volume": 85542 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:36:00", + "open": 152.83, + "high": 152.86, + "low": 152.83, + "close": 152.86, + "volume": 54553 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:37:00", + "open": 153.0, + "high": 153.03, + "low": 152.99, + "close": 153.03, + "volume": 71242 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:38:00", + "open": 152.88, + "high": 152.95, + "low": 152.87, + "close": 152.92, + "volume": 70859 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:39:00", + "open": 153.06, + "high": 153.07, + "low": 153.05, + "close": 153.06, + "volume": 49819 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:40:00", + "open": 152.86, + "high": 152.89, + "low": 152.79, + "close": 152.85, + "volume": 39944 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:41:00", + "open": 152.83, + "high": 152.88, + "low": 152.75, + "close": 152.86, + "volume": 47215 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:42:00", + "open": 152.99, + "high": 153.04, + "low": 152.98, + "close": 152.98, + "volume": 65186 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:43:00", + "open": 153.02, + "high": 153.03, + "low": 152.98, + "close": 152.98, + "volume": 58336 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:44:00", + "open": 152.85, + "high": 152.93, + "low": 152.84, + "close": 152.84, + "volume": 45389 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:45:00", + "open": 152.88, + "high": 152.97, + "low": 152.84, + "close": 152.91, + "volume": 39724 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:46:00", + "open": 153.14, + "high": 153.19, + "low": 153.13, + "close": 153.16, + "volume": 27350 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:47:00", + "open": 152.91, + "high": 152.95, + "low": 152.89, + "close": 152.95, + "volume": 53505 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:48:00", + "open": 153.06, + "high": 153.09, + "low": 153.02, + "close": 153.09, + "volume": 66323 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:49:00", + "open": 152.96, + "high": 153.0, + "low": 152.9, + "close": 152.94, + "volume": 57013 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:50:00", + "open": 153.17, + "high": 153.21, + "low": 153.16, + "close": 153.19, + "volume": 58981 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:51:00", + "open": 153.14, + "high": 153.21, + "low": 153.11, + "close": 153.15, + "volume": 43164 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:52:00", + "open": 153.01, + "high": 153.02, + "low": 152.95, + "close": 152.97, + "volume": 75563 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:53:00", + "open": 153.21, + "high": 153.24, + "low": 153.15, + "close": 153.19, + "volume": 43232 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:54:00", + "open": 152.98, + "high": 153.06, + "low": 152.96, + "close": 153.03, + "volume": 32335 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:55:00", + "open": 153.11, + "high": 153.12, + "low": 153.04, + "close": 153.07, + "volume": 64424 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:56:00", + "open": 153.0, + "high": 153.02, + "low": 152.94, + "close": 153.02, + "volume": 32183 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:57:00", + "open": 152.97, + "high": 153.08, + "low": 152.93, + "close": 153.04, + "volume": 63548 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:58:00", + "open": 153.03, + "high": 153.11, + "low": 152.99, + "close": 152.99, + "volume": 47893 + }, + { + "code": "AAPL", + "time": "2026-02-06 14:59:00", + "open": 153.21, + "high": 153.26, + "low": 153.15, + "close": 153.2, + "volume": 48775 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:00:00", + "open": 152.87, + "high": 152.89, + "low": 152.83, + "close": 152.89, + "volume": 59168 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:01:00", + "open": 153.05, + "high": 153.07, + "low": 152.95, + "close": 153.01, + "volume": 78160 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:02:00", + "open": 152.91, + "high": 152.94, + "low": 152.91, + "close": 152.92, + "volume": 78950 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:03:00", + "open": 153.01, + "high": 153.11, + "low": 152.96, + "close": 153.0, + "volume": 158973 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:04:00", + "open": 152.95, + "high": 152.96, + "low": 152.84, + "close": 152.93, + "volume": 166104 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:05:00", + "open": 153.02, + "high": 153.04, + "low": 152.98, + "close": 152.99, + "volume": 82904 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:06:00", + "open": 152.85, + "high": 152.89, + "low": 152.78, + "close": 152.82, + "volume": 29043 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:07:00", + "open": 153.11, + "high": 153.2, + "low": 153.0, + "close": 153.13, + "volume": 114394 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:08:00", + "open": 153.02, + "high": 153.07, + "low": 152.98, + "close": 153.02, + "volume": 105726 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:09:00", + "open": 153.26, + "high": 153.27, + "low": 153.21, + "close": 153.26, + "volume": 73950 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:10:00", + "open": 153.32, + "high": 153.35, + "low": 153.31, + "close": 153.34, + "volume": 106606 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:11:00", + "open": 153.15, + "high": 153.17, + "low": 153.02, + "close": 153.16, + "volume": 142477 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:12:00", + "open": 153.26, + "high": 153.27, + "low": 153.19, + "close": 153.24, + "volume": 89444 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:13:00", + "open": 153.26, + "high": 153.33, + "low": 153.21, + "close": 153.27, + "volume": 81578 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:14:00", + "open": 153.1, + "high": 153.22, + "low": 153.04, + "close": 153.18, + "volume": 123472 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:15:00", + "open": 153.11, + "high": 153.17, + "low": 153.06, + "close": 153.11, + "volume": 163043 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:16:00", + "open": 153.12, + "high": 153.17, + "low": 153.08, + "close": 153.08, + "volume": 74319 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:17:00", + "open": 153.44, + "high": 153.49, + "low": 153.34, + "close": 153.41, + "volume": 106483 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:18:00", + "open": 153.25, + "high": 153.27, + "low": 153.21, + "close": 153.24, + "volume": 89451 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:19:00", + "open": 153.1, + "high": 153.11, + "low": 153.04, + "close": 153.04, + "volume": 145107 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:20:00", + "open": 153.24, + "high": 153.27, + "low": 153.21, + "close": 153.25, + "volume": 68329 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:21:00", + "open": 153.45, + "high": 153.51, + "low": 153.45, + "close": 153.45, + "volume": 80210 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:22:00", + "open": 153.22, + "high": 153.25, + "low": 153.2, + "close": 153.24, + "volume": 87300 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:23:00", + "open": 153.13, + "high": 153.18, + "low": 153.07, + "close": 153.18, + "volume": 67062 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:24:00", + "open": 152.9, + "high": 152.98, + "low": 152.9, + "close": 152.98, + "volume": 105594 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:25:00", + "open": 153.44, + "high": 153.44, + "low": 153.31, + "close": 153.37, + "volume": 70506 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:26:00", + "open": 153.13, + "high": 153.2, + "low": 153.08, + "close": 153.09, + "volume": 45141 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:27:00", + "open": 153.32, + "high": 153.45, + "low": 153.32, + "close": 153.35, + "volume": 88965 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:28:00", + "open": 152.96, + "high": 153.09, + "low": 152.88, + "close": 152.97, + "volume": 131404 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:29:00", + "open": 153.16, + "high": 153.2, + "low": 153.15, + "close": 153.18, + "volume": 62153 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:30:00", + "open": 153.14, + "high": 153.23, + "low": 153.06, + "close": 153.13, + "volume": 28454 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:31:00", + "open": 153.17, + "high": 153.27, + "low": 153.1, + "close": 153.2, + "volume": 121176 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:32:00", + "open": 153.1, + "high": 153.13, + "low": 152.99, + "close": 153.06, + "volume": 110236 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:33:00", + "open": 153.29, + "high": 153.34, + "low": 153.28, + "close": 153.31, + "volume": 72773 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:34:00", + "open": 153.37, + "high": 153.42, + "low": 153.3, + "close": 153.36, + "volume": 76395 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:35:00", + "open": 153.41, + "high": 153.43, + "low": 153.35, + "close": 153.38, + "volume": 56311 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:36:00", + "open": 153.5, + "high": 153.67, + "low": 153.47, + "close": 153.54, + "volume": 66999 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:37:00", + "open": 153.47, + "high": 153.52, + "low": 153.46, + "close": 153.52, + "volume": 132785 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:38:00", + "open": 153.42, + "high": 153.46, + "low": 153.32, + "close": 153.4, + "volume": 69971 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:39:00", + "open": 153.47, + "high": 153.58, + "low": 153.43, + "close": 153.54, + "volume": 109258 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:40:00", + "open": 153.25, + "high": 153.31, + "low": 153.24, + "close": 153.29, + "volume": 80171 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:41:00", + "open": 153.22, + "high": 153.29, + "low": 153.21, + "close": 153.26, + "volume": 128166 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:42:00", + "open": 153.16, + "high": 153.26, + "low": 153.15, + "close": 153.19, + "volume": 70176 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:43:00", + "open": 153.31, + "high": 153.44, + "low": 153.23, + "close": 153.33, + "volume": 102429 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:44:00", + "open": 153.36, + "high": 153.47, + "low": 153.31, + "close": 153.31, + "volume": 73289 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:45:00", + "open": 153.25, + "high": 153.28, + "low": 153.17, + "close": 153.21, + "volume": 81538 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:46:00", + "open": 153.65, + "high": 153.66, + "low": 153.63, + "close": 153.63, + "volume": 83346 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:47:00", + "open": 153.36, + "high": 153.38, + "low": 153.28, + "close": 153.28, + "volume": 60788 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:48:00", + "open": 153.45, + "high": 153.58, + "low": 153.42, + "close": 153.5, + "volume": 143961 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:49:00", + "open": 153.59, + "high": 153.62, + "low": 153.42, + "close": 153.6, + "volume": 58420 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:50:00", + "open": 153.33, + "high": 153.38, + "low": 153.3, + "close": 153.32, + "volume": 93976 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:51:00", + "open": 153.46, + "high": 153.48, + "low": 153.39, + "close": 153.39, + "volume": 74916 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:52:00", + "open": 153.55, + "high": 153.63, + "low": 153.54, + "close": 153.56, + "volume": 58255 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:53:00", + "open": 153.36, + "high": 153.48, + "low": 153.32, + "close": 153.4, + "volume": 62945 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:54:00", + "open": 153.39, + "high": 153.43, + "low": 153.35, + "close": 153.41, + "volume": 154466 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:55:00", + "open": 153.23, + "high": 153.24, + "low": 153.22, + "close": 153.24, + "volume": 94050 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:56:00", + "open": 153.62, + "high": 153.64, + "low": 153.58, + "close": 153.64, + "volume": 83058 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:57:00", + "open": 153.4, + "high": 153.43, + "low": 153.36, + "close": 153.36, + "volume": 69012 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:58:00", + "open": 153.56, + "high": 153.59, + "low": 153.5, + "close": 153.51, + "volume": 95017 + }, + { + "code": "AAPL", + "time": "2026-02-06 15:59:00", + "open": 153.31, + "high": 153.34, + "low": 153.23, + "close": 153.34, + "volume": 78479 + } +] \ No newline at end of file diff --git a/data/utils/market_simulator.py b/data/utils/market_simulator.py new file mode 100644 index 0000000..107cb04 --- /dev/null +++ b/data/utils/market_simulator.py @@ -0,0 +1,87 @@ +import json +import random +import math +from datetime import datetime, timedelta + +def generate_ohlcv_from_pattern(symbol, date_str, pattern_segments): + """ + Generates minute-by-minute OHLCV data based on a list of trend segments. + + Args: + symbol: Ticker symbol + date_str: Date (YYYY-MM-DD) + pattern_segments: List of dicts with: + - duration_mins: int + - start_price: float + - end_price: float + - volatility: float (standard deviation) + - volume_mult: float (multiplier of average volume) + """ + base_date = datetime.strptime(date_str, "%Y-%m-%d") + current_time = base_date.replace(hour=9, minute=30) + + data = [] + + for segment in pattern_segments: + duration = segment['duration_mins'] + start_p = segment['start_price'] + end_p = segment['end_price'] + volatility = segment['volatility'] + vol_mult = segment.get('volume_mult', 1.0) + + price_step = (end_p - start_p) / duration + + for i in range(duration): + trend_price = start_p + (price_step * i) + + # Random walk component + noise = random.gauss(0, volatility) + + # OHLC generation + open_p = trend_price + noise + high_p = open_p + abs(random.gauss(0, volatility/2)) + low_p = open_p - abs(random.gauss(0, volatility/2)) + close_p = (open_p + high_p + low_p) / 3 + random.gauss(0, volatility/4) + + # Ensure logical constraints + high_p = max(open_p, close_p, high_p) + low_p = min(open_p, close_p, low_p) + + # Volume profile (U-shaped usually, but modulated by segment) + time_factor = 1.0 + if current_time.hour < 10 or current_time.hour >= 15: + time_factor = 1.5 + + base_vol = 50000 * time_factor * vol_mult + volume = int(max(100, random.gauss(base_vol, base_vol * 0.3))) + + data.append({ + "code": symbol, + "time": current_time.strftime("%Y-%m-%d %H:%M:%S"), + "open": round(open_p, 2), + "high": round(high_p, 2), + "low": round(low_p, 2), + "close": round(close_p, 2), + "volume": volume + }) + + current_time += timedelta(minutes=1) + + return data + +if __name__ == "__main__": + # Example: AAPL "Morning Rally then Chop" + # Starting at 150.00 + segments = [ + {"duration_mins": 30, "start_price": 150.0, "end_price": 152.5, "volatility": 0.15, "volume_mult": 1.5}, # Rally + {"duration_mins": 60, "start_price": 152.5, "end_price": 151.8, "volatility": 0.10, "volume_mult": 0.8}, # Pullback + {"duration_mins": 120, "start_price": 151.8, "end_price": 152.2, "volatility": 0.08, "volume_mult": 0.5}, # Chop + {"duration_mins": 180, "start_price": 152.2, "end_price": 153.5, "volatility": 0.12, "volume_mult": 1.2}, # Afternoon push + ] + + data = generate_ohlcv_from_pattern("AAPL", "2026-02-06", segments) + + with open("data/mock_scenarios/AAPL_rally.json", "w") as f: + json.dump(data, f, indent=2) + + print(f"Generated {len(data)} points for AAPL") diff --git a/static/css/style.css b/static/css/style.css new file mode 100644 index 0000000..f287907 --- /dev/null +++ b/static/css/style.css @@ -0,0 +1,485 @@ +/* + * Quantitative Trading Platform - Interactive Mockup + * CSS Styles for the complete platform mockup + */ + +:root { + /* Color Palette */ + --primary-dark: #0a1929; + --secondary-dark: #1e2a38; + --tertiary-dark: #2a3a4d; + + /* Accent Colors */ + --accent-blue: #1976d2; + --accent-green: #4caf50; + --accent-red: #f44336; + --accent-purple: #9c27b0; + --accent-orange: #ff9800; + --accent-cyan: #00bcd4; + --accent-yellow: #ffc107; + + /* Text Colors */ + --text-primary: #ffffff; + --text-secondary: #b0bec5; + --text-muted: #78909c; + + /* Border Colors */ + --border-dark: #37474f; + --border-light: #546e7a; + + /* Status Colors */ + --status-success: #4caf50; + --status-warning: #ff9800; + --status-danger: #f44336; + --status-info: #2196f3; + + /* Chart Colors */ + --chart-line: #4caf50; + --chart-area: rgba(76, 175, 80, 0.1); + --chart-grid: #37474f; +} + +/* Base Styles */ +body { + font-family: 'Segoe UI', system-ui, -apple-system, BlinkMacSystemFont, 'Roboto', sans-serif; + background-color: var(--primary-dark); + color: var(--text-primary); + overflow-x: hidden; + font-size: 0.9rem; + line-height: 1.5; +} + +/* Typography */ +h1, h2, h3, h4, h5, h6 { + font-weight: 600; + color: var(--text-primary); +} + +.text-muted { + color: var(--text-muted) !important; +} + +/* Cards */ +.card { + background-color: var(--primary-dark); + border: 1px solid var(--border-dark); + border-radius: 8px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); + transition: all 0.2s ease; +} + +.card:hover { + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4); + transform: translateY(-2px); +} + +.card-header { + background-color: rgba(255, 255, 255, 0.03); + border-bottom: 1px solid var(--border-dark); + padding: 0.75rem 1rem; +} + +.card-body { + padding: 1rem; +} + +/* Border accent colors */ +.border-accent-blue { + border-color: var(--accent-blue) !important; +} + +.border-accent-green { + border-color: var(--accent-green) !important; +} + +.border-accent-red { + border-color: var(--accent-red) !important; +} + +.border-accent-purple { + border-color: var(--accent-purple) !important; +} + +.border-accent-orange { + border-color: var(--accent-orange) !important; +} + +.border-secondary-dark { + border-color: var(--secondary-dark) !important; +} + +/* Sidebar Navigation */ +.sidebar { + min-height: calc(100vh - 56px); + padding-top: 1rem; +} + +.nav-link { + color: var(--text-secondary); + padding: 0.75rem 1rem; + margin: 0.125rem 0.5rem; + border-radius: 6px; + transition: all 0.2s ease; +} + +.nav-link:hover { + color: var(--text-primary); + background-color: rgba(255, 255, 255, 0.05); +} + +.nav-link.active { + color: var(--text-primary); + background-color: rgba(25, 118, 210, 0.15); + border-left: 3px solid var(--accent-blue); +} + +.nav-link i { + width: 20px; + text-align: center; +} + +/* Progress Bars */ +.progress { + background-color: var(--tertiary-dark); + border-radius: 4px; +} + +.progress-bar { + border-radius: 4px; +} + +/* Tables */ +.table-dark { + --bs-table-bg: transparent; + --bs-table-striped-bg: rgba(255, 255, 255, 0.03); + --bs-table-hover-bg: rgba(255, 255, 255, 0.05); + color: var(--text-primary); + border-color: var(--border-dark); +} + +.table-dark th { + font-weight: 600; + color: var(--text-secondary); + border-color: var(--border-dark); +} + +.table-dark td { + border-color: var(--border-dark); +} + +/* Forms */ +.form-control, .form-select { + background-color: var(--secondary-dark); + border: 1px solid var(--border-dark); + color: var(--text-primary); +} + +.form-control:focus, .form-select:focus { + background-color: var(--secondary-dark); + border-color: var(--accent-blue); + color: var(--text-primary); + box-shadow: 0 0 0 0.25rem rgba(25, 118, 210, 0.25); +} + +.form-control::placeholder { + color: var(--text-muted); +} + +.input-group-text { + background-color: var(--tertiary-dark); + border: 1px solid var(--border-dark); + color: var(--text-secondary); +} + +/* Buttons */ +.btn { + border-radius: 6px; + font-weight: 500; + transition: all 0.2s ease; +} + +.btn-outline-light { + color: var(--text-secondary); + border-color: var(--border-dark); +} + +.btn-outline-light:hover { + background-color: rgba(255, 255, 255, 0.1); + border-color: var(--border-light); + color: var(--text-primary); +} + +.btn-primary { + background-color: var(--accent-blue); + border-color: var(--accent-blue); +} + +.btn-primary:hover { + background-color: #1565c0; + border-color: #1565c0; +} + +.btn-success { + background-color: var(--accent-green); + border-color: var(--accent-green); +} + +.btn-danger { + background-color: var(--accent-red); + border-color: var(--accent-red); +} + +.btn-warning { + background-color: var(--accent-orange); + border-color: var(--accent-orange); + color: #000; +} + +.btn-info { + background-color: var(--accent-cyan); + border-color: var(--accent-cyan); +} + +/* Badges */ +.badge { + font-weight: 500; + padding: 0.35em 0.65em; + border-radius: 4px; +} + +.bg-purple { + background-color: var(--accent-purple) !important; +} + +/* Alerts */ +.alert { + border-radius: 6px; + border: 1px solid transparent; +} + +.alert-warning { + background-color: rgba(255, 152, 0, 0.1); + border-color: rgba(255, 152, 0, 0.3); + color: var(--accent-orange); +} + +.alert-success { + background-color: rgba(76, 175, 80, 0.1); + border-color: rgba(76, 175, 80, 0.3); + color: var(--accent-green); +} + +.alert-info { + background-color: rgba(33, 150, 243, 0.1); + border-color: rgba(33, 150, 243, 0.3); + color: var(--accent-blue); +} + +/* Charts Container */ +canvas { + max-width: 100%; +} + +/* Section Transitions */ +.section-content { + animation: fadeIn 0.3s ease; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* Responsive Adjustments */ +@media (max-width: 768px) { + .sidebar { + min-height: auto; + border-right: none; + border-bottom: 1px solid var(--border-dark); + } + + .nav-link { + margin: 0.125rem 0; + } + + .display-4 { + font-size: 2.5rem; + } +} + +/* Utility Classes */ +.text-success { + color: var(--accent-green) !important; +} + +.text-danger { + color: var(--accent-red) !important; +} + +.text-warning { + color: var(--accent-orange) !important; +} + +.text-info { + color: var(--accent-cyan) !important; +} + +.bg-primary-dark { + background-color: var(--primary-dark) !important; +} + +.bg-secondary-dark { + background-color: var(--secondary-dark) !important; +} + +.border-secondary-dark { + border-color: var(--secondary-dark) !important; +} + +/* Scrollbar Styling */ +::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +::-webkit-scrollbar-track { + background: var(--secondary-dark); +} + +::-webkit-scrollbar-thumb { + background: var(--tertiary-dark); + border-radius: 5px; +} + +::-webkit-scrollbar-thumb:hover { + background: var(--border-light); +} + +/* List Groups */ +.list-group-item { + background-color: transparent; + color: var(--text-primary); + border-color: var(--border-dark); +} + +.list-group-item:hover { + background-color: rgba(255, 255, 255, 0.03); +} + +/* Hover Effects */ +.hover-lift { + transition: transform 0.2s ease; +} + +.hover-lift:hover { + transform: translateY(-2px); +} + +/* Highlight animation for updated values */ +@keyframes highlight { + 0% { color: var(--text-primary); } + 50% { color: var(--accent-yellow); } + 100% { color: var(--text-primary); } +} + +.text-highlight { + animation: highlight 1s ease; +} + +/* Status Indicators */ +.status-indicator { + display: inline-block; + width: 8px; + height: 8px; + border-radius: 50%; + margin-right: 6px; +} + +.status-indicator.online { + background-color: var(--accent-green); + box-shadow: 0 0 8px var(--accent-green); +} + +.status-indicator.warning { + background-color: var(--accent-orange); + box-shadow: 0 0 8px var(--accent-orange); +} + +.status-indicator.offline { + background-color: var(--accent-red); + box-shadow: 0 0 8px var(--accent-red); +} + +/* Metric Cards */ +.metric-card { + position: relative; + overflow: hidden; +} + +.metric-card::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 3px; + background: linear-gradient(90deg, var(--accent-blue), var(--accent-cyan)); +} + +.metric-card.green::before { + background: linear-gradient(90deg, var(--accent-green), #81c784); +} + +.metric-card.red::before { + background: linear-gradient(90deg, var(--accent-red), #e57373); +} + +.metric-card.orange::before { + background: linear-gradient(90deg, var(--accent-orange), #ffb74d); +} + +/* Loading States */ +.loading-skeleton { + background: linear-gradient(90deg, var(--secondary-dark) 25%, var(--tertiary-dark) 50%, var(--secondary-dark) 75%); + background-size: 200% 100%; + animation: loading 1.5s infinite; +} + +@keyframes loading { + 0% { + background-position: 200% 0; + } + 100% { + background-position: -200% 0; + } +} + +/* Tooltips */ +.tooltip-inner { + background-color: var(--tertiary-dark); + color: var(--text-primary); + border-radius: 4px; + padding: 0.5rem 0.75rem; +} + +.tooltip.bs-tooltip-top .tooltip-arrow::before { + border-top-color: var(--tertiary-dark); +} + +.tooltip.bs-tooltip-bottom .tooltip-arrow::before { + border-bottom-color: var(--tertiary-dark); +} + +.tooltip.bs-tooltip-start .tooltip-arrow::before { + border-left-color: var(--tertiary-dark); +} + +.tooltip.bs-tooltip-end .tooltip-arrow::before { + border-right-color: var(--tertiary-dark); +} \ No newline at end of file diff --git a/static/js/app.js b/static/js/app.js new file mode 100644 index 0000000..5fe3302 --- /dev/null +++ b/static/js/app.js @@ -0,0 +1,381 @@ +/* + * Quantitative Trading Platform - Interactive Mockup + * Main JavaScript for navigation and interactivity + */ + +// Global state +const AppState = { + currentSection: 'dashboard', + charts: {}, + mockData: {} +}; + +// Initialize the application +function initApp() { + console.log('Quantitative Trading Platform Mockup Initialized'); + + // Set up navigation + setupNavigation(); + + // Load mock data + loadMockData(); + + // Initialize charts + initCharts(); + + // Show default section + showSection('dashboard'); + + // Set up event listeners for interactive elements + setupEventListeners(); +} + +// Set up sidebar navigation +function setupNavigation() { + const navLinks = document.querySelectorAll('.nav-link[data-section]'); + + navLinks.forEach(link => { + link.addEventListener('click', function(e) { + e.preventDefault(); + const section = this.getAttribute('data-section'); + showSection(section); + + // Update active state + navLinks.forEach(l => l.classList.remove('active')); + this.classList.add('active'); + }); + }); +} + +// Show a specific section +function showSection(sectionId) { + // Hide all sections + const sections = document.querySelectorAll('.section-content'); + sections.forEach(section => { + section.classList.add('d-none'); + }); + + // Show the selected section + const targetSection = document.getElementById(`${sectionId}-section`); + if (targetSection) { + targetSection.classList.remove('d-none'); + AppState.currentSection = sectionId; + + // Update page title + const sectionTitle = targetSection.querySelector('h1, h2')?.textContent || 'Quantitative Trading Platform'; + document.title = `${sectionTitle} - Mockup`; + + // Refresh charts for the section if needed + refreshSectionCharts(sectionId); + } +} + +// Refresh charts for a specific section +function refreshSectionCharts(sectionId) { + switch(sectionId) { + case 'dashboard': + if (AppState.charts.portfolioChart) { + updatePortfolioChart(); + } + break; + case 'data-management': + if (AppState.charts.dataQualityChart) { + updateDataQualityChart(); + } + break; + case 'strategy-engine': + if (AppState.charts.backtestChart) { + updateBacktestChart(); + } + break; + case 'risk-management': + if (AppState.charts.riskChart) { + updateRiskChart(); + } + break; + } +} + +// Set up event listeners for buttons and interactive elements +function setupEventListeners() { + // Refresh buttons + const refreshButtons = document.querySelectorAll('button:contains("Refresh"), .btn-refresh, .btn-outline-light'); + refreshButtons.forEach(btn => { + // Look for the refresh button specifically + if (btn.querySelector('.bi-arrow-clockwise') || btn.textContent.includes('Refresh')) { + btn.addEventListener('click', function() { + // Fetch real market data from backend + const symbol = 'AAPL'; // Default for now + fetch(`/api/market-data/${symbol}`) + .then(response => response.json()) + .then(data => { + // Update UI with real data + updateDashboardWithRealData(data); + showToast(`Data refreshed for ${symbol}`, 'success'); + }) + .catch(error => { + console.error('Error fetching data:', error); + showToast('Failed to refresh data', 'danger'); + }); + }); + } + }); + + // Form submissions + const forms = document.querySelectorAll('form'); + forms.forEach(form => { + form.addEventListener('submit', function(e) { + e.preventDefault(); + showToast('Settings saved successfully', 'success'); + }); + }); + + // Toggle buttons + const toggleButtons = document.querySelectorAll('.btn[data-toggle]'); + toggleButtons.forEach(btn => { + btn.addEventListener('click', function() { + const target = this.getAttribute('data-toggle'); + const state = this.getAttribute('data-state'); + + if (target && state) { + // Toggle state + const newState = state === 'on' ? 'off' : 'on'; + this.setAttribute('data-state', newState); + + // Update button appearance + if (newState === 'on') { + this.classList.remove('btn-outline-secondary'); + this.classList.add('btn-success'); + this.innerHTML = ' ON'; + } else { + this.classList.remove('btn-success'); + this.classList.add('btn-outline-secondary'); + this.innerHTML = ' OFF'; + } + + showToast(`Feature ${newState === 'on' ? 'enabled' : 'disabled'}`, 'info'); + } + }); + }); + + // Tab clicks + const tabs = document.querySelectorAll('[data-bs-toggle="tab"]'); + tabs.forEach(tab => { + tab.addEventListener('shown.bs.tab', function() { + const tabId = this.getAttribute('data-bs-target'); + console.log(`Tab activated: ${tabId}`); + }); + }); + + // Simulate live data updates + setInterval(updateLiveData, 5000); +} + +// Update live data (simulated) +function updateLiveData() { + if (AppState.currentSection === 'dashboard') { + // Update metrics with small random changes + updateDashboardMetrics(); + } +} + +// Update dashboard metrics with random changes +function updateDashboardMetrics() { + const metrics = { + 'total-pnl': { base: 42580, range: 500 }, + 'max-drawdown': { base: 8420, range: 200 }, + 'win-rate': { base: 64.8, range: 1.5 } + }; + + for (const [id, config] of Object.entries(metrics)) { + const element = document.getElementById(id); + if (element) { + const current = parseFloat(element.textContent.replace(/[^\d.-]/g, '')); + const change = (Math.random() - 0.5) * 2 * config.range; + const newValue = config.base + change; + + // Format based on metric type + if (id === 'total-pnl' || id === 'max-drawdown') { + element.textContent = `$${Math.round(newValue).toLocaleString()}`; + } else if (id === 'win-rate') { + element.textContent = `${newValue.toFixed(1)}%`; + } + + // Add subtle animation + element.classList.add('text-highlight'); + setTimeout(() => { + element.classList.remove('text-highlight'); + }, 1000); + } + } +} + +function updateDashboardWithRealData(data) { + // Update key metrics cards + const metrics = data.metrics; + + // Total P&L + const pnlEl = document.querySelector('.card-title.text-success'); + if (pnlEl) pnlEl.textContent = `$${metrics.total_pnl.toLocaleString()}`; + + // Max Drawdown + const ddEl = document.querySelector('.card-title.text-danger'); + if (ddEl) ddEl.textContent = `$${metrics.max_drawdown.toLocaleString()}`; + + // Win Rate + const winEl = document.querySelector('.card-title.text-info'); + if (winEl) winEl.textContent = `${metrics.win_rate}%`; + + // Update chart + if (AppState.charts.portfolioChart) { + AppState.charts.portfolioChart.data.labels = data.daily_pnl.map(d => d.date); + AppState.charts.portfolioChart.data.datasets[0].data = data.daily_pnl.map(d => d.cumulative); + AppState.charts.portfolioChart.update(); + } +} + +// Show toast notification +function showToast(message, type = 'info') { + // Create toast container if it doesn't exist + let toastContainer = document.getElementById('toast-container'); + if (!toastContainer) { + toastContainer = document.createElement('div'); + toastContainer.id = 'toast-container'; + toastContainer.className = 'toast-container position-fixed bottom-0 end-0 p-3'; + document.body.appendChild(toastContainer); + } + + // Create toast + const toastId = 'toast-' + Date.now(); + const toast = document.createElement('div'); + toast.id = toastId; + toast.className = `toast align-items-center text-bg-${type} border-0`; + toast.setAttribute('role', 'alert'); + toast.setAttribute('aria-live', 'assertive'); + toast.setAttribute('aria-atomic', 'true'); + + toast.innerHTML = ` +
+
+ ${message} +
+ +
+ `; + + toastContainer.appendChild(toast); + + // Initialize and show toast + const bsToast = new bootstrap.Toast(toast, { delay: 3000 }); + bsToast.show(); + + // Remove toast after it's hidden + toast.addEventListener('hidden.bs.toast', function() { + toast.remove(); + }); +} + +// Load mock data +function loadMockData() { + // Generate mock data for charts + AppState.mockData = { + portfolioData: generatePortfolioData(), + dataQualityData: generateDataQualityData(), + backtestData: generateBacktestData(), + riskData: generateRiskData() + }; +} + +// Generate mock portfolio data +function generatePortfolioData() { + const data = []; + let value = 100000; + + for (let i = 0; i < 30; i++) { + const date = new Date(); + date.setDate(date.getDate() - (30 - i)); + + // Random walk with drift + const change = (Math.random() - 0.4) * 0.02 * value; + value += change; + + data.push({ + date: date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }), + value: Math.max(90000, value) + }); + } + + return data; +} + +// Generate mock data quality data +function generateDataQualityData() { + const data = []; + + for (let i = 0; i < 7; i++) { + const date = new Date(); + date.setDate(date.getDate() - (7 - i)); + + data.push({ + date: date.toLocaleDateString('en-US', { weekday: 'short' }), + completeness: 90 + Math.random() * 8, + latency: 5 + Math.random() * 15, + errors: Math.floor(Math.random() * 5) + }); + } + + return data; +} + +// Generate mock backtest data +function generateBacktestData() { + const strategies = ['Dual Momentum', 'Mean Reversion', 'Pairs Trading']; + const data = []; + + strategies.forEach(strategy => { + let returns = 100; + const returnsData = []; + + for (let i = 0; i < 12; i++) { + const monthlyReturn = (Math.random() - 0.2) * 0.1; + returns *= (1 + monthlyReturn); + returnsData.push(returns); + } + + data.push({ + strategy, + returns: returnsData, + sharpe: 0.8 + Math.random() * 1.5, + winRate: 50 + Math.random() * 30 + }); + }); + + return data; +} + +// Generate mock risk data +function generateRiskData() { + const metrics = ['VaR', 'CVaR', 'Max Drawdown', 'Volatility']; + const data = []; + + metrics.forEach(metric => { + const values = []; + for (let i = 0; i < 10; i++) { + values.push(Math.random() * 10); + } + data.push({ metric, values }); + }); + + return data; +} + +// Initialize when DOM is loaded +document.addEventListener('DOMContentLoaded', initApp); + +// Export for use in other scripts +window.App = { + showSection, + showToast, + refreshSectionCharts, + state: AppState +}; \ No newline at end of file diff --git a/static/js/mock-data.js b/static/js/mock-data.js new file mode 100644 index 0000000..04af5d6 --- /dev/null +++ b/static/js/mock-data.js @@ -0,0 +1,414 @@ +/* + * Quantitative Trading Platform - Interactive Mockup + * Mock data generation for charts and displays + */ + +// Chart initialization +function initCharts() { + // Initialize Portfolio Chart + initPortfolioChart(); + + // Initialize Data Quality Chart + initDataQualityChart(); + + // Initialize Backtest Chart + initBacktestChart(); + + // Initialize Risk Chart + initRiskChart(); +} + +// Portfolio Performance Chart +function initPortfolioChart() { + const ctx = document.getElementById('portfolioChart'); + if (!ctx) return; + + const data = generatePortfolioData(); + + AppState.charts.portfolioChart = new Chart(ctx, { + type: 'line', + data: { + labels: data.map(d => d.date), + datasets: [{ + label: 'Portfolio Value', + data: data.map(d => d.value), + borderColor: '#4caf50', + backgroundColor: 'rgba(76, 175, 80, 0.1)', + fill: true, + tension: 0.4, + pointRadius: 2, + pointHoverRadius: 5 + }] + }, + options: { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { + display: false + }, + tooltip: { + mode: 'index', + intersect: false, + callbacks: { + label: function(context) { + return `$${context.parsed.y.toLocaleString()}`; + } + } + } + }, + scales: { + x: { + grid: { + color: 'rgba(255, 255, 255, 0.05)' + }, + ticks: { + color: '#b0bec5' + } + }, + y: { + grid: { + color: 'rgba(255, 255, 255, 0.05)' + }, + ticks: { + color: '#b0bec5', + callback: function(value) { + return '$' + (value / 1000).toFixed(0) + 'k'; + } + } + } + } + } + }); +} + +// Data Quality Chart +function initDataQualityChart() { + const ctx = document.getElementById('dataQualityChart'); + if (!ctx) return; + + const data = generateDataQualityData(); + + AppState.charts.dataQualityChart = new Chart(ctx, { + type: 'line', + data: { + labels: data.map(d => d.date), + datasets: [ + { + label: 'Completeness (%)', + data: data.map(d => d.completeness), + borderColor: '#4caf50', + backgroundColor: 'rgba(76, 175, 80, 0.1)', + fill: true, + tension: 0.4, + yAxisID: 'y' + }, + { + label: 'Latency (ms)', + data: data.map(d => d.latency), + borderColor: '#2196f3', + backgroundColor: 'rgba(33, 150, 243, 0.1)', + fill: true, + tension: 0.4, + yAxisID: 'y1' + } + ] + }, + options: { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { + position: 'top', + labels: { + color: '#b0bec5' + } + } + }, + scales: { + x: { + grid: { + color: 'rgba(255, 255, 255, 0.05)' + }, + ticks: { + color: '#b0bec5' + } + }, + y: { + type: 'linear', + display: true, + position: 'left', + min: 80, + max: 100, + grid: { + color: 'rgba(255, 255, 255, 0.05)' + }, + ticks: { + color: '#b0bec5', + callback: function(value) { + return value + '%'; + } + } + }, + y1: { + type: 'linear', + display: true, + position: 'right', + min: 0, + max: 30, + grid: { + drawOnChartArea: false + }, + ticks: { + color: '#b0bec5', + callback: function(value) { + return value + 'ms'; + } + } + } + } + } + }); +} + +// Backtest Results Chart +function initBacktestChart() { + const ctx = document.getElementById('backtestChart'); + if (!ctx) return; + + const data = generateBacktestData(); + + AppState.charts.backtestChart = new Chart(ctx, { + type: 'line', + data: { + labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + datasets: data.map((strategy, index) => { + const colors = ['#4caf50', '#2196f3', '#9c27b0']; + return { + label: strategy.strategy, + data: strategy.returns, + borderColor: colors[index], + backgroundColor: colors[index] + '20', + fill: false, + tension: 0.4 + }; + }) + }, + options: { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { + position: 'top', + labels: { + color: '#b0bec5' + } + } + }, + scales: { + x: { + grid: { + color: 'rgba(255, 255, 255, 0.05)' + }, + ticks: { + color: '#b0bec5' + } + }, + y: { + grid: { + color: 'rgba(255, 255, 255, 0.05)' + }, + ticks: { + color: '#b0bec5', + callback: function(value) { + return '$' + value.toLocaleString(); + } + } + } + } + } + }); +} + +// Risk Management Chart +function initRiskChart() { + const ctx = document.getElementById('riskChart'); + if (!ctx) return; + + const data = generateRiskData(); + + AppState.charts.riskChart = new Chart(ctx, { + type: 'radar', + data: { + labels: data.map(d => d.metric), + datasets: [{ + label: 'Risk Metrics', + data: data.map(d => d.values[0]), + backgroundColor: 'rgba(255, 152, 0, 0.2)', + borderColor: 'rgba(255, 152, 0, 1)', + pointBackgroundColor: 'rgba(255, 152, 0, 1)', + pointBorderColor: '#fff', + pointHoverBackgroundColor: '#fff', + pointHoverBorderColor: 'rgba(255, 152, 0, 1)' + }] + }, + options: { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { + display: false + } + }, + scales: { + r: { + angleLines: { + color: 'rgba(255, 255, 255, 0.1)' + }, + grid: { + color: 'rgba(255, 255, 255, 0.1)' + }, + pointLabels: { + color: '#b0bec5' + }, + ticks: { + color: '#b0bec5', + backdropColor: 'transparent' + }, + min: 0, + max: 10 + } + } + } + }); +} + +// Update functions for live data +function updatePortfolioChart() { + if (!AppState.charts.portfolioChart) return; + + const newData = generatePortfolioData(); + AppState.charts.portfolioChart.data.labels = newData.map(d => d.date); + AppState.charts.portfolioChart.data.datasets[0].data = newData.map(d => d.value); + AppState.charts.portfolioChart.update('none'); +} + +function updateDataQualityChart() { + if (!AppState.charts.dataQualityChart) return; + + const newData = generateDataQualityData(); + AppState.charts.dataQualityChart.data.labels = newData.map(d => d.date); + AppState.charts.dataQualityChart.data.datasets[0].data = newData.map(d => d.completeness); + AppState.charts.dataQualityChart.data.datasets[1].data = newData.map(d => d.latency); + AppState.charts.dataQualityChart.update('none'); +} + +function updateBacktestChart() { + if (!AppState.charts.backtestChart) return; + + const newData = generateBacktestData(); + newData.forEach((strategy, index) => { + AppState.charts.backtestChart.data.datasets[index].data = strategy.returns; + }); + AppState.charts.backtestChart.update('none'); +} + +function updateRiskChart() { + if (!AppState.charts.riskChart) return; + + const newData = generateRiskData(); + AppState.charts.riskChart.data.datasets[0].data = newData.map(d => d.values[0]); + AppState.charts.riskChart.update('none'); +} + +// Data generation functions (same as in app.js but exported for use) +function generatePortfolioData() { + const data = []; + let value = 100000; + + for (let i = 0; i < 30; i++) { + const date = new Date(); + date.setDate(date.getDate() - (30 - i)); + + const change = (Math.random() - 0.4) * 0.02 * value; + value += change; + + data.push({ + date: date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }), + value: Math.max(90000, value) + }); + } + + return data; +} + +function generateDataQualityData() { + const data = []; + + for (let i = 0; i < 7; i++) { + const date = new Date(); + date.setDate(date.getDate() - (7 - i)); + + data.push({ + date: date.toLocaleDateString('en-US', { weekday: 'short' }), + completeness: 90 + Math.random() * 8, + latency: 5 + Math.random() * 15, + errors: Math.floor(Math.random() * 5) + }); + } + + return data; +} + +function generateBacktestData() { + const strategies = ['Dual Momentum', 'Mean Reversion', 'Pairs Trading']; + const data = []; + + strategies.forEach(strategy => { + let returns = 100; + const returnsData = []; + + for (let i = 0; i < 12; i++) { + const monthlyReturn = (Math.random() - 0.2) * 0.1; + returns *= (1 + monthlyReturn); + returnsData.push(returns); + } + + data.push({ + strategy, + returns: returnsData, + sharpe: 0.8 + Math.random() * 1.5, + winRate: 50 + Math.random() * 30 + }); + }); + + return data; +} + +function generateRiskData() { + const metrics = ['VaR', 'CVaR', 'Max Drawdown', 'Volatility']; + const data = []; + + metrics.forEach(metric => { + const values = []; + for (let i = 0; i < 10; i++) { + values.push(Math.random() * 10); + } + data.push({ metric, values }); + }); + + return data; +} + +// Export for use in other scripts +window.MockData = { + initCharts, + updatePortfolioChart, + updateDataQualityChart, + updateBacktestChart, + updateRiskChart, + generatePortfolioData, + generateDataQualityData, + generateBacktestData, + generateRiskData +}; \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..bb374e2 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,820 @@ + + + + + + Quantitative Trading Platform - Interactive Mockup + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+
+

+ + Dashboard +

+
+
+ + +
+
+
+ + +
+
+
+
+
+
+
Total P&L
+

$42,580

+
+ +
+

+ +12.4% MTD +

+
+
+
+
+
+
+
+
+
Max Drawdown
+

-$8,420

+
+ +
+

+ -4.2% from peak +

+
+
+
+
+
+
+
+
+
Win Rate
+

64.8%

+
+ +
+

+ 182 winning trades +

+
+
+
+
+
+
+
+
+
Active Strategies
+

4

+
+ +
+

+ 2 in paper trading +

+
+
+
+
+ + +
+
+
+
+
Portfolio Performance
+
+
+ +
+
+
+
+
+
+
Top Holdings
+
+
+
+
+ AAPL + +12.4% +
+
+ MSFT + +8.7% +
+
+ GOOGL + -2.3% +
+
+ TSLA + +15.2% +
+
+ NVDA + +24.1% +
+
+
+
+
+
+ + +
+
+
+
+
Recent Trades
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TimeSymbolActionQuantityPriceP&LStatus
10:45 AMAAPLBUY50$182.34+$420Filled
10:30 AMTSLASELL25$245.67+$1,250Filled
09:15 AMMSFTBUY100$412.89PendingPending
YesterdayGOOGLSELL75$145.23-$320Filled
+
+
+
+
+
+
+ + +
+
+

+ + Data Management +

+
+
+ + +
+
+
+ + +
+
+
+
+
+
Moomoo API
+ Connected +
+

Real-time market data, historical OHLCV, order execution

+
+ Rate Limit +
+
+
+ 42/60 requests per minute +
+
+ + +
+
+
+
+
+
+
+
+
Alternative Data
+ Partial +
+

Economic calendar, news feeds, sentiment analysis

+
+ Data Quality +
+
+
+ 78% completeness +
+
+ + +
+
+
+
+
+ + +
+
+
+
+
Data Quality Dashboard
+
+
+
+
+
99.2%
+ Uptime +
+
+
12ms
+ Avg Latency +
+
+
0.8%
+ Missing Data +
+
+
3
+ Anomalies Today +
+
+ +
+
+
+
+
+ + +
+
+

+ + Strategy Engine +

+
+
+ + +
+
+
+ + +
+
+
+
+
Active Strategies
+
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StrategyTypeStatusP&LWin RateSharpeActions
+ Dual Momentum +
Large-cap US stocks +
Trend FollowingLive+$18,42068.2%1.85 + + +
+ Mean Reversion +
S&P 500 components +
Mean ReversionPaper Trading+$5,23059.7%1.12 + + +
+ Pairs Trading +
Tech sector pairs +
Statistical ArbitragePaused-$2,15052.4%0.45 + + +
+
+
+
+
+
+ + +
+
+
+
+
Backtest Results
+
+
+ +
+
+
+
+
+
+
Create New Strategy
+
+
+
+
+ + +
+
+ + +
+
+ +
+ $ + +
+
+
+ +
+
+
+
+
+
+
+ + +
+
+

+ + Risk Management +

+
+
+ + +
+
+
+ + +
+
+
+
+
4.2%
+ Max Drawdown +
+
+
+
+
+
+
1.85
+ Sharpe Ratio +
+
+
+
+
+
+
12.4%
+ Volatility (Annual) +
+
+
+
+
+
+
95%
+ VaR (1-day, 95%) +
+
+
+
+ + +
+
+
+
+
Circuit Breakers
+
+
+
+ +
+ + USD +
+
Trading pauses if daily loss exceeds this amount
+
+
+ +
+ + % +
+
Maximum allocation to any single position
+
+
+ +
+ + % +
+
Maximum allocation to any single sector
+
+
+ +
+
+
+
+
+
+
+
Risk Dashboard
+
+
+ +
+
+ + Warning: Tech sector concentration at 38% (limit: 40%) +
+
+ + All Systems Normal: All risk limits within bounds +
+
+
+
+
+
+
+ + + + + +
+
+

+ + Trade Execution +

+
+
+ + Trade Execution interface would show real-time order management, execution quality metrics, and manual trading controls. +
+
+ + +
+
+

+ + Reports & Analytics +

+
+
+ + Reports section would include performance attribution, trade journals, compliance reports, and export functionality. +
+
+ + +
+
+

+ + Alerting System +

+
+
+ + Alerting system would configure Telegram/email notifications for critical events, risk breaches, and performance milestones. +
+
+ + +
+
+

+ + Configuration +

+
+
+ + Configuration interface would manage API keys, system settings, user preferences, and integration settings. +
+
+
+
+
+ + + + + + + + + + + \ No newline at end of file