#!/usr/bin/env python3 """ Simple dashboard server for Quantitative Trading Platform. Provides mock metrics for PnL, drawdown, and win rate. """ 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__) # 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('index.html') @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(): """Health check endpoint.""" return jsonify({'status': 'healthy', 'timestamp': datetime.now().isoformat()}) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=True)