FOUNDRY
C8 Platform
← Tasks

Leaderboard endpoint for PTM

completedcode_genP2

Description

Create GET /api/v1/ptm/leaderboard endpoint returning ranked models per position with trust scores, sample sizes, and trend indicators.
Assignee
-
Claimed By
Cloud Lu → Claude Sonnet
Created
21d ago
Completed
1d ago

Quality

Overall
6%
Pass
FAIL
Graded By
-
Graded At
-

Cost

Input Tokens
-
Output Tokens
-
Est. USD
-

Result

{
  "cost": {
    "input_tokens": 47,
    "estimated_usd": 0.076146,
    "output_tokens": 5067
  },
  "model": "claude-sonnet-4-20250514",
  "status": "success",
  "transport": "anthropic_api",
  "latency_ms": 55240,
  "response_text": "I'll create a comprehensive leaderboard endpoint for PTM (Predictive Trading Models) that returns ranked models with performance metrics and trend indicators.\n\n```python\nfrom flask import Flask, request, jsonify\nfrom flask_sqlalchemy import SQLAlchemy\nfrom sqlalchemy import func, desc, asc, case, and_\nfrom datetime import datetime, timedelta\nfrom typing import Dict, List, Optional, Tuple\nfrom enum import Enum\nimport numpy as np\nfrom dataclasses import dataclass\n\napp = Flask(__name__)\n\nclass PositionType(Enum):\n    LONG = \"long\"\n    SHORT = \"short\"\n    BOTH = \"both\"\n\nclass TrendDirection(Enum):\n    UP = \"up\"\n    DOWN = \"down\"\n    STABLE = \"stable\"\n\n@dataclass\nclass TrendIndicator:\n    direction: TrendDirection\n    magnitude: float  # Percentage change\n    period_days: int\n\n@dataclass\nclass LeaderboardEntry:\n    model_id: str\n    model_name: str\n    rank: int\n    position_type: PositionType\n    trust_score: float\n    sample_size: int\n    win_rate: float\n    avg_return: float\n    sharpe_ratio: float\n    max_drawdown: float\n    total_trades: int\n    trend_indicator: TrendIndicator\n    last_updated: datetime\n\n# Database Models\nclass PTMModel(db.Model):\n    __tablename__ = 'ptm_models'\n    \n    id = db.Column(db.String(36), primary_key=True)\n    name = db.Column(db.String(255), nullable=False)\n    description = db.Column(db.Text)\n    position_type = db.Column(db.Enum(PositionType), nullable=False)\n    created_at = db.Column(db.DateTime, default=datetime.utcnow)\n    is_active = db.Column(db.Boolean, default=True)\n    \n    # Relationships\n    performance_metrics = db.relationship('PTMPerformanceMetric', backref='model', lazy='dynamic')\n    trades = db.relationship('PTMTrade', backref='model', lazy='dynamic')\n\nclass PTMPerformanceMetric(db.Model):\n    __tablename__ = 'ptm_performance_metrics'\n    \n    id = db.Column(db.Integer, primary_key=True)\n    model_id = db.Column(db.String(36), db.ForeignKey('ptm_models.id'), nullable=False)\n    date = db.Column(db.Date, nullable=False)\n    trust_score = db.Column(db.Float, nullable=False)\n    win_rate = db.Column(db.Float, nullable=False)\n    avg_return = db.Column(db.Float, nullable=False)\n    sharpe_ratio = db.Column(db.Float)\n    max_drawdown = db.Column(db.Float)\n    total_trades = db.Column(db.Integer, default=0)\n    sample_size = db.Column(db.Integer, default=0)\n    created_at = db.Column(db.DateTime, default=datetime.utcnow)\n\nclass PTMTrade(db.Model):\n    __tablename__ = 'ptm_trades'\n    \n    id = db.Column(db.Integer, primary_key=True)\n    model_id = db.Column(db.String(36), db.ForeignKey('ptm_models.id'), nullable=False)\n    symbol = db.Column(db.String(20), nullable=False)\n    position_type = db.Column(db.Enum(PositionType), nullable=False)\n    entry_price = db.Column(db.Float, nullable=False)\n    exit_price = db.Column(db.Float)\n    return_pct = db.Column(db.Float)\n    entry_time = db.Column(db.DateTime, nullable=False)\n    exit_time = db.Column(db.DateTime)\n    is_winner = db.Column(db.Boolean)\n    confidence_score = db.Column(db.Float)\n\nclass PTMLeaderboardService:\n    def __init__(self):\n        self.default_lookback_days = 30\n        self.trend_period_days = 7\n        \n    def get_leaderboard(\n        self,\n        position_type: Optional[PositionType] = None,\n        limit: int = 50,\n        min_sample_size: int = 10,\n        lookback_days: int = None\n    ) -> List[LeaderboardEntry]:\n        \"\"\"\n        Generate leaderboard with ranked PTM models\n        \"\"\"\n        if lookback_days is None:\n            lookback_days = self.default_lookback_days\n            \n        cutoff_date = datetime.utcnow() - timedelta(days=lookback_days)\n        \n        # Build base query\n        query = self._build_leaderboard_query(cutoff_date, position_type, min_sample_size)\n        \n        # Execute and process results\n        results = query.limit(limit).all()\n        \n        leaderboard_entries = []\n        for rank, result in enumerate(results, 1):\n            # Get trend indicator\n            trend = self._calculate_trend_indicator(result.model_id, self.trend_period_days)\n            \n            entry = LeaderboardEntry(\n                model_id=result.model_id,\n                model_name=result.model_name,\n                rank=rank,\n                position_type=PositionType(result.position_type),\n                trust_score=round(result.trust_score, 4),\n                sample_size=result.sample_size,\n                win_rate=round(result.win_rate, 4),\n                avg_return=round(result.avg_return, 4),\n                sharpe_ratio=round(result.sharpe_ratio or 0, 4),\n                max_drawdown=round(result.max_drawdown or 0, 4),\n                total_trades=result.total_trades,\n                trend_indicator=trend,\n                last_updated=result.last_updated\n            )\n            \n            leaderboard_entries.append(entry)\n            \n        return leaderboard_entries\n    \n    def _build_leaderboard_query(\n        self,\n        cutoff_date: datetime,\n        position_type: Optional[PositionType],\n        min_sample_size: int\n    ):\n        \"\"\"\n        Build the main leaderboard query with rankings\n        \"\"\"\n        # Subquery for latest metrics per model\n        latest_metrics = db.session.query(\n            PTMPerformanceMetric.model_id,\n            func.max(PTMPerformanceMetric.date).label('latest_date')\n        ).filter(\n            PTMPerformanceMetric.date >= cutoff_date.date()\n        ).group_by(PTMPerformanceMetric.model_id).subquery()\n        \n        # Main query with joins\n        query = db.session.query(\n            PTMModel.id.label('model_id'),\n            PTMModel.name.label('model_name'),\n            PTMModel.position_type,\n            PTMPerformanceMetric.trust_score,\n            PTMPerformanceMetric.win_rate,\n            PTMPerformanceMetric.avg_return,\n            PTMPerformanceMetric.sharpe_ratio,\n            PTMPerformanceMetric.max_drawdown,\n            PTMPerformanceMetric.total_trades,\n            PTMPerformanceMetric.sample_size,\n            PTMPerformanceMetric.created_at.label('last_updated')\n        ).select_from(PTMModel).join(\n            PTMPerformanceMetric,\n            PTMModel.id == PTMPerformanceMetric.model_id\n        ).join(\n            latest_metrics,\n            and_(\n                PTMPerformanceMetric.model_id == latest_metrics.c.model_id,\n                PTMPerformanceMetric.date == latest_metrics.c.latest_date\n            )\n        ).filter(\n            PTMModel.is_active == True,\n            PTMPerformanceMetric.sample_size >= min_sample_size\n        )\n        \n        # Add position type filter if specified\n        if position_type and position_type != PositionType.BOTH:\n            query = query.filter(PTMModel.position_type == position_type)\n        \n        # Order by trust score (primary) and avg return (secondary)\n        query = query.order_by(\n            desc(PTMPerformanceMetric.trust_score),\n            desc(PTMPerformanceMetric.avg_return)\n        )\n        \n        return query\n    \n    def _calculate_trend_indicator(self, model_id: str, period_days: int) -> TrendIndicator:\n        \"\"\"\n        Calculate trend indicator for a model's trust score\n        \"\"\"\n        end_date = datetime.utcnow().date()\n        start_date = end_date - timedelta(days=period_days)\n        \n        # Get trust scores for the period\n        metrics = db.session.query(\n            PTMPerformanceMetric.trust_score,\n            PTMPerformanceMetric.date\n        ).filter(\n            PTMPerformanceMetric.model_id == model_id,\n            PTMPerformanceMetric.date >= start_date,\n            PTMPerformanceMetric.date <= end_date\n        ).order_by(PTMPerformanceMetric.date).all()\n        \n        if len(metrics) < 2:\n            return TrendIndicator(\n                direction=TrendDirection.STABLE,\n                magnitude=0.0,\n                period_days=period_days\n            )\n        \n        # Calculate trend\n        first_score = metrics[0].trust_score\n        last_score = metrics[-1].trust_score\n        \n        if first_score == 0:\n            magnitude = 0.0\n        else:\n            magnitude = ((last_score - first_score) / first_score) * 100\n        \n        # Determine direction\n        if magnitude > 2.0:  # More than 2% improvement\n            direction = TrendDirection.UP\n        elif magnitude < -2.0:  # More than 2% decline\n            direction = TrendDirection.DOWN\n        else:\n            direction = TrendDirection.STABLE\n        \n        return TrendIndicator(\n            direction=direction,\n            magnitude=round(magnitude, 2),\n            period_days=period_days\n        )\n\nclass PTMLeaderboardController:\n    def __init__(self):\n        self.service = PTMLeaderboardService()\n    \n    def get_leaderboard_endpoint(self):\n        \"\"\"\n        GET /api/v1/ptm/leaderboard endpoint handler\n        \"\"\"\n        try:\n            # Parse query parameters\n            position_type_str = request.args.get('position_type', 'both').lower()\n            limit = min(int(request.args.get('limit', 50)), 100)  # Max 100\n            min_sample_size = int(request.args.get('min_sample_size', 10))\n            lookback_days = request.args.get('lookback_days', type=int)\n            include_trends = request.args.get('include_trends', 'true').lower() == 'true'\n            \n            # Validate position type\n            position_type = None\n            if position_type_str in [e.value for e in PositionType]:\n                position_type = PositionType(position_type_str)\n            \n            # Get leaderboard data\n            leaderboard_entries = self.service.get_leaderboard(\n                position_type=position_type,\n                limit=limit,\n                min_sample_size=min_sample_size,\n                lookback_days=lookback_days\n            )\n            \n            # Format response\n            response_data = {\n                'success': True,\n                'data': {\n                    'leaderboard': [\n                        self._format_leaderboard_entry(entry, include_trends)\n                        for entry in leaderboard_entries\n                    ],\n                    'metadata': {\n                        'total_models': len(leaderboard_entries),\n                        'position_type_filter': position_type.value if position_type else 'all',\n                        'min_sample_size': min_sample_size,\n                        'lookback_days': lookback_days or self.service.default_lookback_days,\n                        'last_updated': datetime.utcnow().isoformat()\n                    }\n                }\n            }\n            \n            return jsonify(response_data), 200\n            \n        except ValueError as e:\n            return jsonify({\n                'success': False,\n                'error': {\n                    'code': 'INVALID_PARAMETER',\n                    'message': f'Invalid parameter value: {str(e)}'\n                }\n            }), 400\n            \n        except Exception as e:\n            return jsonify({\n                'success': False,\n                'error': {\n                    'code': 'INTERNAL_ERROR',\n                    'message': 'Failed to retrieve leaderboard data'\n                }\n            }), 500\n    \n    def _format_leaderboard_entry(self, entry: LeaderboardEntry, include_trends: bool) -> Dict:\n        \"\"\"\n        Format leaderboard entry for API response\n        \"\"\"\n        formatted_entry = {\n            'rank': entry.rank,\n            'model': {\n                'id': entry.model_id,\n                'name': entry.model_name,\n                'position_type': entry.position_type.value\n            },\n            'performance': {\n                'trust_score': entry.trust_score,\n                'win_rate': entry.win_rate,\n                'avg_return': entry.avg_return,\n                'sharpe_ratio': entry.sharpe_ratio,\n                'max_drawdown': entry.max_drawdown\n            },\n            'statistics': {\n                'sample_size': entry.sample_size,\n                'total_trades': entry.total_trades\n            },\n            'last_updated': entry.last_updated.isoformat()\n        }\n        \n        # Add trend information if requested\n        if include_trends:\n            formatted_entry['trend'] = {\n                'direction': entry.trend_indicator.direction.value,\n                'magnitude': entry.trend_indicator.magnitude,\n                'period_days': entry.trend_indicator.period_days,\n                'indicator': self._get_trend_emoji(entry.trend_indicator.direction)\n            }\n        \n        return formatted_entry\n    \n    def _get_trend_emoji(self, direction: TrendDirection) -> str:\n        \"\"\"\n        Get emoji indicator for trend direction\n        \"\"\"\n        trend_emojis = {\n            TrendDirection.UP: \"📈\",\n            TrendDirection.DOWN: \"📉\",\n            TrendDirection.STABLE: \"➡️\"\n        }\n        return trend_emojis.get(direction, \"➡️\")\n\n# Initialize controller\nptm_controller = PTMLeaderboardController()\n\n@app.route('/api/v1/ptm/leaderboard', methods=['GET'])\ndef get_ptm_leaderboard():\n    \"\"\"\n    PTM Leaderboard Endpoint\n    \n    Query Parameters:\n    - position_type: Filter by position type (long, short, both) - default: both\n    - limit: Number of models to return (max 100) - default: 50\n    - min_sample_size: Minimum sample size for inclusion - default: 10\n    - lookback_days: Days to look back for metrics - default: 30\n    - include_trends: Include trend indicators - default: true\n    \n    Returns:\n    - Ranked list of PTM models with performance metrics and trends\n    \"\"\"\n    return ptm_controller.get_leaderboard_endpoint()\n\n# Additional utility endpoints\n@app.route('/api/v1/ptm/leaderboard/summary', methods=['GET'])\ndef get_leaderboard_summary():\n    \"\"\"\n    Get leaderboard summary statistics\n    \"\"\"\n    try:\n        position_type_str = request.args.get('position_type', 'both').lower()\n        lookback_days = int(request.args.get('lookback_days', 30))\n        \n        # Get position type\n        position_type = None\n        if position_type_str in [e.value for e in PositionType]:\n            position_type = PositionType(position_type_str)\n        \n        cutoff_date = datetime.utcnow() - timedelta(days=lookback_days)\n        \n        # Query summary statistics\n        query = db.session.query(\n            func.count(PTMModel.id).label('total_models'),\n            func.avg(PTMPerformanceMetric.trust_score).label('avg_trust_score'),\n            func.avg(PTMPerformanceMetric.win_rate).label('avg_win_rate'),\n            func.avg(PTMPerformanceMetric.avg_return).label('avg_return'),\n            func.max(PTMPerformanceMetric.trust_score).label('max_trust_score'),\n            func.min(PTMPerformanceMetric.trust_score).label('min_trust_score')\n        ).select_from(PTMModel).join(PTMPerformanceMetric).filter(\n            PTMModel.is_active == True,\n            PTMPerformanceMetric.date >= cutoff_date.date()\n        )\n        \n        if position_type and position_type != PositionType.BOTH:\n            query = query.filter(PTMModel.position_type == position_type)\n        \n        result = query.first()\n        \n        return jsonify({\n            'success': True,\n            'data': {\n                'summary': {\n                    'total_active_models': result.total_models or 0,\n                    'average_trust_score': round(result.avg_trust_score or 0, 4),\n                    'average_win_rate': round(result.avg_win_rate or 0, 4),\n                    'average_return': round(result.avg_return or 0, 4),\n                    'top_trust_score': round(result.max_trust_score or 0, 4),\n                    'lowest_trust_score': round(result.min_trust_score or 0, 4)\n                },\n                'metadata': {\n                    'position_type_filter': position_type.value if position_type else 'all',\n                    'lookback_days': lookback_days,\n                    'generated_at': datetime.utcnow().isoformat()\n                }\n            }\n        }), 200\n        \n    except Exception as e:\n        return jsonify({\n            'success': False,\n            'error': {\n                'code': 'INTERNAL_ERROR',\n                'message': 'Failed to retrieve summary data'\n            }\n        }), 500\n\nif __name__ == '__main__':\n    app.run(debug=True)\n```\n\nThis implementation provides:\n\n## Key Features:\n\n1. **Comprehensive Ranking System**:\n   - Primary ranking by trust score\n   - Secondary ranking by average return\n   - Configurable minimum sample sizes\n\n2. **Rich Performance Metrics**:\n   - Trust scores with precision\n   - Win rates and average returns\n   - Sharpe ratios and max drawdown\n   - Sample sizes and trade counts\n\n3. **Trend Indicators**:\n   - 7-day trend analysis by default\n   - Direction indicators (up/down/stable)\n   - Magnitude of change\n   - Visual emoji indicators\n\n4. **Flexible Filtering**:\n   - Filter by position type (long/short/both)\n   - Configurable lookback periods\n   - Minimum sample size requirements\n   - Result limits with maximum cap\n\n5. **Additional Endpoints**:\n   - Summary statistics endpoint\n   - Metadata about filtering criteria\n   - Last updated timestamps\n\n## Usage Examples:\n\n```bash\n# Get top 20 models for long positions\nGET /api/v1/ptm/leaderboard?position_type=long&limit=20\n\n# Get models with high sample sizes\nGET /api/v1/ptm/leaderboard?min_sample_size=50&lookback_days=60\n\n# Get leaderboard without trends\nGET /api/v1/ptm/leaderboard?include_trends=false\n\n# Get summary statistics\nGET /api/v1/ptm/leaderboard/summary?position_type=short\n```\n\nThe endpoint returns comprehensive leaderboard data with performance metrics, trend analysis, and flexible filtering options for PTM model evaluation."
}

Audit Trail (2)

1d agotask_completedTerminal Lu
1d agotask_claimedTerminal Lu
Task ID: 69045a28-2667-4c1a-90b3-1fa4bfab01a6