← Back to Learn
III AdvancedWeek 31 • Lesson 85Duration: 40 min

PORT Portfolio Construction

The final piece — from signals to a real, diversified portfolio

Learning Objectives

  • Master end-to-end portfolio construction for live trading
  • Understand capital allocation across strategies and instruments
  • Build a complete portfolio management system

Explain Like I'm 5

Portfolio construction is where everything comes together. You have signals, risk management, and all the infrastructure. Now: how do you allocate capital across instruments? How many simultaneous positions? How do you rebalance? This is the final piece that turns a collection of individual trades into a coherent portfolio.

Think of It This Way

Portfolio construction is like being a chef creating a tasting menu. Each dish (trade) is great individually, but the menu (portfolio) needs to flow: not too much of one flavor (cluster concentration), proper pacing (position timing), and a balanced experience (diversification).

1V7 Portfolio Construction

The complete V7 portfolio construction process: 1. Universe definition: Which instruments to trade? - V7 trades ~20 instruments across 6 clusters - FOREX, METALS, INDEX, CRYPTO, COMMODITY, EQUITY - Each instrument has cluster-specific L1 thresholds 2. Signal generation: L1 scores for each instrument - 38 features -> XGBoost -> probability score - Cluster-specific thresholds (FOREX: 0.52, METALS: 0.52, INDEX: 0.50, etc.) 3. Signal filtering: L2 SKIP/ENTER gate - Timing quality check - Reduces ~40% of signals (prevents over-trading) 4. Portfolio optimization: Which signals to act on? - Rank by L1 confidence - Apply cluster limits (max 3-4 per cluster) - Apply total position limit (max 10-15) - Apply daily risk budget (max 4.5R) 5. Position sizing: How much per trade? - Base: 0.30% risk (0.003 x equity) - Adjustments: confidence multiplier, regime multiplier, DD zone multiplier - Final size = base x confidence x regime x DD_mult 6. Execution: Enter trades via MT5 - Set SL/TP at entry (server-side) - L3 manages exit timing 7. Monitoring: Track portfolio performance - Real-time PnL, DD, exposure - Daily review cycle

2Capital Allocation Strategy

With a $100K FTMO account: Per-trade risk: 0.30% = $300 per trade - If SL is 20 pips -> position size = $300 / (20 x pip_value) - For EURUSD with $10/pip: 1.5 mini lots (0.15 standard lots) Max daily risk: 4.5R = $1,350 - Can take up to ~4-5 trades before hitting daily limit - S40 reduces this in higher DD zones Diversification targets: - Max 3 positions in same cluster - No more than 50% of risk budget in one cluster - Aim for cross-cluster diversification Capital efficiency: - Leverage 1:100 (FTMO standard for FOREX) - Margin usage typically 5-15% of account - Never use more than 30% margin The V7 engine achieves ~4.35% monthly return with this allocation: - ~600 trades/year (2-3 per day) - 59.2% win rate - Average win 1.5R, average loss 1.0R - Max DD 1.49% (Monte Carlo validated) This is the end result of the entire 3-layer ML pipeline, 43 S-series components, and rigorous validation. Every lesson in this course contributed to making this work.

Key Formulas

Position Size

The fundamental position sizing formula. Risk a fixed percentage of your account, with size inversely proportional to stop distance. This is how V7 sizes every trade.

V7 Adjusted Position Size

Base size adjusted by confidence multiplier (L1 score), regime multiplier (Hurst-based), and DD zone multiplier (S40). Each adjustment can reduce size but never increases beyond base.

Hands-On Code

Complete Portfolio Construction

python
import numpy as np

class V7PortfolioConstructor:
    """End-to-end portfolio construction for V7."""
    
    def __init__(self, account_balance, base_risk_pct=0.30,
                 max_daily_r=4.5, max_positions=12, max_per_cluster=3):
        self.balance = account_balance
        self.base_risk = base_risk_pct / 100
        self.max_daily_r = max_daily_r
        self.max_positions = max_positions
        self.max_per_cluster = max_per_cluster
    
    def construct(self, signals, dd_zone='NORMAL', current_positions=None):
        """Build portfolio from signals."""
        current_positions = current_positions or []
        
        # DD zone risk multiplier
        dd_mult = {'NORMAL': 1.0, 'CAUTION': 0.83, 'DANGER': 0.67, 'CRITICAL': 0.50}
        risk_mult = dd_mult.get(dd_zone, 1.0)
        
        # Sort by confidence
        ranked = sorted(signals, key=lambda s: s['confidence'], reverse=True)
        
        portfolio = list(current_positions)
        cluster_counts = {}
        for p in current_positions:
            cluster_counts[p['cluster']] = cluster_counts.get(p['cluster'], 0) + 1
        
        daily_r_used = sum(p.get('risk_r', 0.3) for p in current_positions)
        
        new_trades = []
        for signal in ranked:
            # Check limits
            if len(portfolio) >= self.max_positions:
                break
            if cluster_counts.get(signal['cluster'], 0) >= self.max_per_cluster:
                continue
            
            # Compute position size
            risk_amount = self.balance * self.base_risk * risk_mult
            risk_r = risk_amount / self.balance * 100 / 0.30  # normalize to R
            
            if daily_r_used + risk_r > self.max_daily_r:
                continue
            
            trade = {
                'symbol': signal['symbol'],
                'cluster': signal['cluster'],
                'direction': signal['direction'],
                'confidence': signal['confidence'],
                'risk_amount': risk_amount,
                'risk_r': risk_r,
            }
            
            new_trades.append(trade)
            portfolio.append(trade)
            cluster_counts[signal['cluster']] = cluster_counts.get(signal['cluster'], 0) + 1
            daily_r_used += risk_r
        
        print(f"=== V7 PORTFOLIO ({dd_zone} zone) ===")
        print(f"Existing positions: {len(current_positions)}")
        print(f"New trades: {len(new_trades)}")
        print(f"Total positions: {len(portfolio)}")
        print(f"Daily R used: {daily_r_used:.1f} / {self.max_daily_r}")
        print(f"Risk per trade: {self.balance * self.base_risk * risk_mult:.0f}")
        
        return new_trades

# constructor = V7PortfolioConstructor(account_balance=100000)
# trades = constructor.construct(signals, dd_zone='NORMAL')

Portfolio construction integrates everything: signal ranking, cluster limits, daily risk budget, DD-based scaling. This is the final output of the V7 pipeline — specific, sized trades ready for execution.

Knowledge Check

Q1.You have $100K account, 0.30% risk, and are in the CAUTION DD zone (0.25% effective). How much do you risk per trade?

Assignment

Build a complete portfolio construction system that takes L1 signals and outputs specific trades. Include: signal ranking, cluster limits, position sizing with DD adjustment, and daily risk budget. Test on historical signals and verify all constraints are respected.