DIONYSUS position sizing, stops, and targets

How the optimizer turns dollars into whole shares, stop levels, and risk/reward metadata—so you can read an allocation row with confidence.

Why this page exists

Optimization responses look like a table of trades, but every number is the output of deterministic rules applied to analysis documents. Understanding those rules helps you interpret percent_of_account, stop_loss, and target_price without mistaking them for broker guarantees or personalized advice.

From dollars to whole shares

  1. Each strategy assigns capital to a symbol (or a Kelly fraction × capital) up to max_positions and per-position caps.
  2. _calculate_position_size (conceptual name in the DIONYSUS service) converts that capital allocation into:
    • A price from the analysis document (must be present and positive).
    • A stop loss — preferably from risk_parameters.stop_loss when present; otherwise a fallback (e.g. estimated below the entry) so risk per share is never zero.
    • Risk per share = distance from entry to stop (with a floor relative to price so degenerate cases do not produce infinite share counts).
  3. max_risk_per_trade applies to total portfolio capital (not only the slice allocated to that line). So “4% risk per trade” means “about 4% of account equity at risk for this position’s stop distance,” before other positions—consistent with how retail users think about account-level risk budgets.
  4. Whole shares — the service rounds down to integer shares. Very small allocations can collapse to zero shares, and that line is skipped.
  5. Minimum dollar sanity — if allocated capital is tiny relative to price, you may not afford one share; the line fails and logs a warning pattern.

Nothing here replaces your broker’s lot size, fractional settings, or commissions—those are outside DIONYSUS.

Stop loss and target price (response fields)

  • Stop is primarily a risk-modeling anchor for share count and risk_amount, not an order sent to the market.
  • Target price in the default path is derived from a fixed reward multiple of risk per share (implementation uses a multiplier such as risk for a long). Your live trading plan may use different targets; treat the API field as illustrative.
  • Volatility stop levels — when ATHENA provides volatility_stop_loss_levels (e.g. aggressive / moderate / conservative), they are passed through on the allocation record for ATLAS/UI—DIONYSUS still uses its primary stop for sizing unless product logic changes.

percent_of_account: read it carefully

In the position builder, percent_of_account is computed relative to the capital allocation line used for that symbol in the sizing step—not always identical to “% of total portfolio” after greedy trimming and rounding. Use position_value / total_capital for portfolio-level percentage when reconciling to your spreadsheet.

Greedy pass: when total exceeds capital

After initial lines are built, sum of position_value can exceed total_capital due to rounding and independent per-line sizing. A greedy constraint then:

  1. Sorts candidate lines by a composite priority (confidence, risk/reward, stage ordering—Stage 2 favored over Stage 1, etc.).
  2. Adds lines in order until the running total fits total_capital.
  3. Drops the tail. So your “top” names by that internal score survive; others disappear entirely—not partial trims per line.

If you see fewer positions than max_positions, this pass is one reason (others: filters, sector caps, turnover blend).

High-priced stocks

If a name’s price exceeds the dollar allocation for that line, you cannot buy one share—the line fails. That often shows up when max_positions is large but capital is modest, or when Kelly or equal slices are thin. Raising capital, reducing position count, or tightening the universe (screeners) usually helps more than cranking max_risk_per_trade without thought.

Progress is saved in this browser. Cloud sync requires PUBLIC_IRIS_API_BASE, IRIS CORS allowlist, and window.__trinityIdToken.