The optimizer builds stock portfolios based on your risk preference. Instead of guessing weights, it uses diversification, historical behavior, and realistic constraints to keep portfolios balanced and valid.
The optimizer uses multi-year historical behavior to understand how stocks tend to move relative to each other. It analyzes patterns in volatility, returns, and correlations over extended periods.
By relying on historical data rather than forecasts or daily news, the optimizer builds portfolios that are grounded in observable patterns that tend to persist over time, avoiding short-term noise and speculation.
Risk affects multiple dimensions of your portfolio: volatility, concentration, and how much exposure you take to correlated stocks. It's not just about being aggressive or conservative.
Higher risk allows more concentration in fewer stocks and greater exposure to growth-oriented assets. Lower risk enforces more stability and diversification across a broader set of holdings.
The risk slider (1-10) controls how the optimizer balances these tradeoffs, giving you control over the fundamental structure of your portfolio.
Diversification means not putting all your risk in stocks that move together. If you hold five tech stocks and they all drop 20% on the same day, you haven't really diversified.
Correlation is simply "how similarly two stocks behave." High correlation means when one goes up, the other tends to go up too. Low correlation means they move more independently.
High correlation reduces the benefit of holding both stocks. The optimizer tries to combine assets that don't all move the same way, spreading risk across different market behaviors. Some correlation is natural and even beneficial—the goal is to avoid over-concentration in highly correlated groups.
What this means for you: Owning stocks that don't all move together can reduce swings without needing to 'predict' the market.
No single stock or sector should dominate your portfolio unless you explicitly override the constraints. Caps prevent accidental "all-in" portfolios that put too much risk in one place.
These limits vary by risk level. Higher risk portfolios may allow more concentration in individual stocks, while lower risk portfolios enforce stricter diversification rules. The optimizer respects these limits while still finding the best balance of weights across your selected stocks.
What this means for you: You avoid accidental 'all-in' bets on one stock or one sector.
The optimizer actively manages sector exposure to prevent over-concentration in any single industry. Each stock is classified into a sector (like Technology, Healthcare, Financial Services, Energy, etc.), and the optimizer enforces limits on how much of your portfolio can be in each sector.
The optimizer sets a maximum percentage that any single sector can occupy, which varies by your risk level:
Some sectors have additional specific limits beyond the general cap:
The stricter limit applies—so if the general cap is 38% but Tech has a 50% limit, Tech can go up to 38% at that risk level. If Tech has a 50% limit but risk level allows 60% per sector, Tech is still capped at 50%.
For lower risk portfolios, the optimizer ensures you have exposure to multiple sectors:
If your portfolio doesn't meet the minimum, the optimizer automatically adds high-quality stocks from missing sectors to ensure proper diversification.
When a sector exceeds its limit, the optimizer:
What this means for you: You get automatic protection against sector concentration while still allowing higher-risk portfolios to take focused positions when appropriate.
This isn't equal-weighting. The optimizer assigns weights based on your risk preference, stock characteristics, and diversification goals. Some stocks get more weight, others get less.
The optimizer balances multiple goals at once: managing risk, maintaining diversification, maximizing return potential, and considering quality signals. These goals sometimes conflict, and the optimizer finds the best compromise, creating a portfolio where each stock's weight reflects its role in achieving your overall risk-return profile.
The optimizer uses an iterative algorithm to build your portfolio step by step, starting from an empty portfolio and adding stocks one at a time based on their scores and how they fit with your risk preference.
If the optimizer can't build a valid portfolio with strict constraints (for example, if you've selected only tech stocks but set a low risk level), it automatically tries progressively relaxed constraints:
This ensures you always get a valid portfolio, even with challenging stock selections or risk preferences.
Once the optimizer finishes, it finalizes the portfolio by:
What this means for you: The optimizer handles all the complex math and constraint checking automatically, so you can focus on your risk preference and stock selection.
Weights always sum to 100%. This isn't just a display rule—it's a fundamental constraint that the optimizer enforces at every step.
When you edit one weight, the optimizer automatically rebalances the rest to maintain the 100% total. This happens instantly, keeping your portfolio valid even as you make adjustments. The optimizer prevents invalid states, so you can't accidentally create a portfolio that doesn't add up or violates the risk and concentration limits you've set.
What this means for you: You can experiment freely without breaking the portfolio math.
A long-term estimate based on historical behavior. It represents the average return you might expect over time, not a guarantee for any specific period.
How much the portfolio tends to fluctuate. Higher volatility means larger swings up and down. Lower volatility means more stable, predictable movement.
A stability and consistency signal based on the underlying stocks. Higher quality scores indicate more reliable, established companies with consistent performance patterns.
Risk-adjusted efficiency. It measures how much return you get per unit of risk. Higher Sharpe ratios indicate better risk-adjusted performance.
⚠️ These are estimates, not guarantees. Past performance does not predict future results.
The optimizer helps you build portfolios that balance risk, diversification, and return potential based on historical patterns. It's a systematic approach to portfolio construction, not a crystal ball for market timing or stock picking.
For developers and advanced users: detailed technical architecture, data processing pipeline, and scoring methodology.
StockRisker is a portfolio risk assessment and optimization tool that evaluates individual securities (stocks and ETFs) and constructs optimal portfolios based on quantitative metrics. The system processes raw financial data from multiple sources, normalizes it, computes risk-adjusted scores, and uses these scores for portfolio construction.
The data collection pipeline follows this workflow:
Data is fetched from financial data APIs, parsed and validated, normalized to consistent units, and stored with metadata.
Risk metrics are computed:
The scoring engine classifies instruments (ETF vs stock), routes to the appropriate scoring function, computes component scores, combines them with weights, and handles missing data gracefully.
Financial Data APIs
↓
Data Fetching
- Fetch data
- Normalize
- Store JSON
↓
Risk Calculation
- Compute risk
- Calculate metrics
↓
Scoring Engine
- Classify (ETF/Stock)
- Score
- Combine
↓
Portfolio Optimizer
- Rank
- Optimize
- GenerateEquity scores are composed of four main dimensions:
Based on volatility, beta, tracking error, Sharpe ratio, and danger metrics. Higher = less risk / better.
Combines growth potential, sustainability, income, analyst sentiment, and value.
Measures business quality through profitability, value, growth, and debt.
Portfolio-level metric (0 for individual stock scoring).
Final Equity Score Formula:
Final Score = 0.40 × Risk-Adjusted Score + 0.30 × Expected Return Score + 0.20 × Quality Score + 0.10 × Diversification BonusETF scores use a different methodology optimized for fund characteristics:
Final ETF Score Formula:
Final ETF Score = 0.55 × Risk-Adjusted Score + 0.20 × Return Score + 0.15 × Income Score + 0.05 × Cost Score + 0.05 × Liquidity ScoreFor complete formula details, see the Scoring Formulas Reference.
The system automatically detects instrument type using metadata from data sources:
quoteType === "ETF": Routes to ETF scoring pathquoteType === "EQUITY" (or missing): Routes to equity scoring pathKey Differences:
Sectors are resolved directly from stock metadata:
stocks.json) - Primary source, all stocks have sector dataSector names from stock data (e.g., "Technology") are normalized to internal classifications (e.g., "Tech") to match sector limits. All sector data is stored in the stock metadata files, ensuring consistency and eliminating the need for hardcoded mappings.
The general maximum sector weight is calculated by risk level:
getMaxSectorWeight(risk): Risk 1: 22% Risk 2: 28% Risk 3: 32% Risk 4: 38% Risk 5-10: Linear interpolation from 38% to 70%
This is enforced via enforceMaxSectorWeight() before sector-specific limits.
Defined in SECTOR_LIMITS constant:
SECTOR_LIMITS = {
Tech: 0.50, // 50% (60% if risk >= 9)
Financials: 0.35,
Energy: 0.20,
ConsumerDefensive: 0.70,
Healthcare: 0.40,
Meme: 0.05,
Junk: 0.00,
Crypto: 0.10
}Enforced via enforceSectorLimits(). The stricter limit applies (general cap vs sector-specific).
For low risk levels (1-4), minimum sector counts are enforced:
enforceSectorDiversity(): Risk 1: minSectors = 6 Risk 2: minSectors = 5 Risk 3: minSectors = 4 Risk 4: minSectors = 3 Risk 5-10: No enforcement
If minimum not met, optimizer adds high-quality stocks from missing sectors.
The computeSectorExposure() function calculates total weight per sector:
for each stock:
sector = classifyStockSector(stock)
weight = weights[stock.ticker]
exposure[sector] += weight
Returns: { sector: totalWeight, ... }When a sector exceeds its limit in enforceSectorLimits():
Financial data APIs may return data in inconsistent units (percent vs decimal). The system normalizes all values to decimal format before storage.
| Field Type | Source Format | Normalization Rule | Stored As |
|---|---|---|---|
| Yield / Fee Fields | Percent (e.g., 12.58 = 12.58%) | If abs(value) > threshold → divide by 100 | Decimal (e.g., 0.1258) |
| Return Fields | Mixed (percent or decimal) | If abs(value) > 1.0 → divide by 100 | Decimal |
| Change-Percent Fields | Mixed (percent or decimal) | If abs(value) >= 1.0 → divide by 100 | Decimal |
| Risk Metrics | Already decimal | No conversion needed | Decimal |
All risk metrics are computed from historical price data, never taken directly from data sources.
Annualized standard deviation of daily returns
stdDev(dailyReturns) × √252Sensitivity to market movements
Covariance(stock, market) / Variance(market)Risk-adjusted return
(Return - RiskFreeRate) / VolatilityExcess return after accounting for market risk
Return - (RiskFreeRate + Beta × MarketReturn)0.40 × Risk-Adjusted Score +
0.30 × Expected Return Score +
0.20 × Quality Score +
0.10 × Diversification BonusScores range from 0.0 to 1.0. Higher = better investment opportunity (risk-adjusted).
0.55 × Risk-Adjusted Score +
0.20 × Return Score +
0.15 × Income Score +
0.05 × Cost Score +
0.05 × Liquidity ScoreHeavier weight on risk (55%) reflects importance of risk management for ETFs.
Build your portfolio based on your risk preference.
Build my portfolioEducational purposes only. Not financial advice.