Strategy Builder

Constraints & Objectives

The optimizer solves a mathematical problem: given your universe, what weights maximise your objective subject to your constraints? This page explains every option, when to use it, and the exact JSON format for bulk upload.

How Constraints and Objectives Work Together

Objective— what you're optimising for (e.g. maximise Sharpe ratio). The optimizer finds weights that score highest on this metric.

Constraints— boundaries the optimizer must stay within (e.g. no single stock > 10%). Think of them as the rules of the game. The optimizer can do anything as long as it doesn't break these rules.

Without constraints, a Sharpe-maximising optimizer will often put everything in one or two stocks. Good constraints make the portfolio realistic and tradeable.

Constraints

Position Size Bound

Sets a floor and ceiling on how much of the portfolio any single stock can hold. Prevents over-concentration and ensures minimum diversification.

position_size_bound

When to use: Without this, the optimizer may put 80%+ in one stock if it has the best risk-adjusted return. Typical range: 2%–10% per position.

Parameters

FieldExample ValueDescription
min_weight"0.02"Minimum allocation per stock (2%)
max_weight"0.10"Maximum allocation per stock (10%)

JSON

{
  "name": "Position Size Bound",
  "type": "Position Size Bound",
  "params": {
    "min_weight": "0.02",
    "max_weight": "0.10"
  },
  "status": "active"
}

Maximum Number of Positions

Caps the total number of stocks held at any one time. Forces the optimizer to concentrate in the highest-conviction names.

max_positions

When to use: Portfolios with 100+ positions often resemble the index. 15–30 positions gives meaningful active exposure while keeping transaction costs manageable.

Parameters

FieldExample ValueDescription
max_positions"20"Maximum number of distinct holdings

JSON

{
  "name": "Maximum Number of Positions",
  "type": "Maximum Number of Positions",
  "params": {
    "max_positions": "20"
  },
  "status": "active"
}

Maximum Capital

Limits the total allocated weight across all positions. Setting this below 1.0 keeps some cash in reserve.

max_total_weight

When to use: Useful if you want to hold 10% cash at all times (set max_capital: 0.9) or to simulate strategies that don't fully deploy capital.

Parameters

FieldExample ValueDescription
max_capital"0.95"Fraction of portfolio to deploy (0–1)

JSON

{
  "name": "Maximum Capital",
  "type": "Maximum Capital",
  "params": {
    "max_capital": "0.95"
  },
  "status": "active"
}

Beta Exposure Constraint

Keeps the portfolio's overall market sensitivity (beta) within a target band. Beta 1.0 = moves with market; <1.0 = defensive; >1.0 = aggressive.

beta_exposure

When to use: If you want a market-neutral strategy, target beta near 0. If you want a low-vol defensive portfolio, set max_beta: 0.8.

Parameters

FieldExample ValueDescription
min_beta"0.7"Lower bound on portfolio beta
max_beta"1.2"Upper bound on portfolio beta

JSON

{
  "name": "Beta Exposure Constraint",
  "type": "Beta Exposure Constraint",
  "params": {
    "min_beta": "0.7",
    "max_beta": "1.2"
  },
  "status": "active"
}

Portfolio Turnover Constraint

Limits how much of the portfolio is traded at each rebalance. High turnover = high transaction costs that eat into returns.

turnover

When to use: At 30bps per trade (our default), turning over 100% monthly costs ~3.6% per year just in costs. Limiting turnover to 30–50% per rebalance can significantly improve net returns.

Parameters

FieldExample ValueDescription
max_turnover"0.30"Maximum portfolio traded per rebalance (30%)

JSON

{
  "name": "Portfolio Turnover Constraint",
  "type": "Portfolio Turnover Constraint",
  "params": {
    "max_turnover": "0.30"
  },
  "status": "active"
}

Minimum Position Size Constraint

Ensures every included stock has a minimum meaningful allocation. Prevents the optimizer from holding a stock at 0.1% — too small to matter.

min_position_size

When to use: If a stock is worth holding, it should be held at a size that actually impacts returns. 1–3% minimum ensures every position counts.

Parameters

FieldExample ValueDescription
min_position_size"0.01"Minimum weight if a stock is included (1%)

JSON

{
  "name": "Minimum Position Size Constraint",
  "type": "Minimum Position Size Constraint",
  "params": {
    "min_position_size": "0.01"
  },
  "status": "active"
}

Portfolio Risk Budget Constraint

Sets a target for the portfolio's total annualised volatility. Forces the optimizer to stay within a risk envelope.

risk_budget

When to use: If your mandate is 'low-risk income', cap volatility at 10%. If you're running an aggressive growth fund, you might allow up to 25%.

Parameters

FieldExample ValueDescription
risk_budget"0.15"Target annualised volatility (15%)

JSON

{
  "name": "Portfolio Risk Budget Constraint",
  "type": "Portfolio Risk Budget Constraint",
  "params": {
    "risk_budget": "0.15"
  },
  "status": "active"
}

Objectives

Only one objective is active at a time. The optimizer solves for this single goal while respecting all active constraints.

Risk-Adjusted Return Objective

Maximises the Sharpe ratio — return per unit of risk. The most common objective for long-only equity portfolios.

maximize_sharpe

Why: A portfolio returning 20% with 30% volatility (Sharpe 0.67) is worse than one returning 15% with 12% volatility (Sharpe 1.25). Sharpe maximisation finds the best risk-return trade-off.

When to use: Use for general-purpose portfolios where you want the best risk-adjusted outcome.

Parameters

FieldExample ValueDescription
weight"1"Relative importance when combining multiple objectives

JSON

{
  "name": "Risk-Adjusted Return Objective",
  "type": "Risk-Adjusted Return Objective",
  "params": {
    "weight": "1"
  },
  "status": "active"
}

Risk Minimization Objective

Finds the minimum variance portfolio — the allocation with the lowest possible volatility, regardless of return.

minimize_risk

Why: Useful for capital preservation mandates, retiree portfolios, or when the universe is volatile and you want stability first.

When to use: Use when drawdown protection matters more than maximising return. Often combined with a Position Size Bound constraint.

Parameters

FieldExample ValueDescription
risk_type"variance"variance or std_dev
weight"1"Relative importance

JSON

{
  "name": "Risk Minimization Objective",
  "type": "Risk Minimization Objective",
  "params": {
    "risk_type": "variance",
    "weight": "1"
  },
  "status": "active"
}

Return Maximization Objective

Maximises expected portfolio return without regard for risk. Produces concentrated, aggressive portfolios.

maximize_return

Why: In practice, pure return maximisation puts everything in the single highest-expected-return asset. Always combine with Position Size Bound and Beta constraints.

When to use: Use for high-conviction, high-risk-tolerance strategies. Requires strong constraints to stay diversified.

Parameters

FieldExample ValueDescription
weight"1"Relative importance

JSON

{
  "name": "Return Maximization Objective",
  "type": "Return Maximization Objective",
  "params": {
    "weight": "1"
  },
  "status": "active"
}

Tracking Error Minimization

Minimises deviation from a benchmark index. Produces a portfolio that closely tracks the benchmark while maintaining some active positions.

minimize_tracking_error

Why: For fund managers measured against an index (NIFTY 50, NIFTY 500), large tracking error means large active bets. Minimising TE reduces career risk.

When to use: Use for enhanced index funds, benchmark-aware strategies, or when mandate requires staying close to an index.

Parameters

FieldExample ValueDescription
benchmark"NIFTY 50"The index to track
weight"1"Relative importance

JSON

{
  "name": "Tracking Error Minimization",
  "type": "Tracking Error Minimization",
  "params": {
    "benchmark": "NIFTY 50",
    "weight": "1"
  },
  "status": "active"
}

Bulk Upload Format

Use the ↑ upload button on the Constraints or Objectives card in the Strategy Builder to load a JSON file directly. All existing entries are replaced. Download your current setup with the ↓ download button to use as a starting template.

constraints.json

constraints.json
[
  {
    "name": "Position Size Bound",
    "type": "Position Size Bound",
    "params": {
      "min_weight": "0.02",
      "max_weight": "0.10"
    },
    "status": "active"
  },
  {
    "name": "Maximum Number of Positions",
    "type": "Maximum Number of Positions",
    "params": {
      "max_positions": "20"
    },
    "status": "active"
  },
  {
    "name": "Beta Exposure Constraint",
    "type": "Beta Exposure Constraint",
    "params": {
      "min_beta": "0.7",
      "max_beta": "1.2"
    },
    "status": "active"
  },
  {
    "name": "Portfolio Turnover Constraint",
    "type": "Portfolio Turnover Constraint",
    "params": {
      "max_turnover": "0.30"
    },
    "status": "active"
  }
]

objectives.json

objectives.json
[
  {
    "name": "Risk-Adjusted Return Objective",
    "type": "Risk-Adjusted Return Objective",
    "params": {
      "weight": "1"
    },
    "status": "active"
  }
]

JSON Schema Rules

  • Top-level must be a JSON array [ ... ]
  • Each entry requires: name, type, params, status
  • status must be "active" or "inactive"
  • All params values must be strings even if numeric — e.g. "0.10" not 0.10
  • Duplicate types are automatically removed on upload (first occurrence kept)
  • id is optional — ignored on upload, auto-assigned

Recommended Setups

Balanced Growth

Objective

Risk-Adjusted Return (Sharpe)

Constraints

  • Position Size Bound 2–10%
  • Max 25 positions
  • Beta 0.8–1.2
  • Max turnover 40%

Low Volatility

Objective

Risk Minimization

Constraints

  • Position Size Bound 3–8%
  • Max 30 positions
  • Beta 0.5–0.9
  • Risk Budget 12%

Index Hugger

Objective

Tracking Error Minimization

Constraints

  • Position Size Bound 1–6%
  • Max 50 positions
  • Beta 0.9–1.1
  • Max turnover 20%