Sentiment forecast
/forecasts/sentiment
Where an asset's sentiment is likely to go over the next 72 hours, as a range of outcomes with their chances. series gives, every 4 hours, the bullish, bearish, neutral, and total posts expected in that step and the sentiment_signal at its end, on the /sentiment scale. chance_higher_24h and chance_higher_72h give the chance the signal ends above current_sentiment_signal; their _confident flags mark when that chance leans clearly one way.
Forecasts update within a minute of new posts about the asset, and at least every 15 minutes. refresh=true recomputes on the latest data in about 5 seconds; if that takes over 20, you get the latest forecast with refreshed: false, charged at 5. Assets without a forecast return status: not_forecastable with a reason; /forecasts/assets lists the assets that have one.
Costs 5 credits, or 10 with refresh=true. not_forecastable answers are free, up to 30 an hour per account; past that this endpoint returns 429 until the hour clears.
Parameters
Asset ID from /assets or /search, such as NVDA, GLD, SPX, or bitcoin. Send it with the asset_class returned alongside it.
Example:NVDA
Class of the asset named by asset_id: equity (stocks and ETFs), commodity, index, or crypto. Send the asset_class that /assets or /search returned alongside the asset_id.
equitycommodityindexcrypto
Example:equity
true recomputes the forecast on the latest data: 10 credits, about 5 seconds. Defaults to false.
Example:false
cURL Example
curl --get \
--url 'https://nebula-api.hiddensystems.ai/api/v1/public/forecasts/sentiment' \
--data-urlencode 'asset_id=NVDA' \
--data-urlencode 'asset_class=equity' \
--header 'X-API-Key: YOUR_API_KEY'
Responses
Media type application/json
as_of
UTC start of the forecast: the end of the last complete 15 minutes it was computed from. Null when the asset has never been scored.
chance_higher_24h
The chance the sentiment signal is higher than current_sentiment_signal in 24 hours, from 0 to 1.
chance_higher_24h_confident
True when chance_higher_24h is under 0.3 or over 0.7: the forecast leans clearly one way. Nearer 0.5, read it as no clear direction.
chance_higher_72h
The chance the sentiment signal is higher than current_sentiment_signal in 72 hours, from 0 to 1.
chance_higher_72h_confident
True when chance_higher_72h is under 0.3 or over 0.7: the forecast leans clearly one way. Nearer 0.5, read it as no clear direction.
current_sentiment_signal
The sentiment signal at as_of, on the /sentiment scale: bullish minus bearish posts over the trailing 24 hours, recent posts weighted more. Every path starts here, and the chances are measured against it. It can differ slightly from the latest /sentiment point, which is hourly.
horizon_hours
How far ahead the forecast runs, in hours: always 72.
reason
Why the asset cannot be forecast: too_little_history, stale_data, or missing_price. Null when status is ok.
too_little_historystale_datamissing_pricenull
refreshed
True when this request re-ran the forecast (refresh=true and the re-run finished in time); false when it is the latest scheduled forecast.
sample_paths
24 possible paths for the sentiment signal, each aligned with series. Draw them to show the spread of outcomes.
series
array<object>
The forecast every 4 hours from as_of: 18 steps, oldest first.
series
The forecast every 4 hours from as_of: 18 steps, oldest first.
series[].bearish_posts
object
The bearish posts expected in this 4-hour step alone, bots excluded: like /sentiment's interval posts, not its trailing 24-hour counts.
series[].bearish_posts
The bearish posts expected in this 4-hour step alone, bots excluded: like /sentiment's interval posts, not its trailing 24-hour counts.
series[].bearish_posts.mean
The expected number of bearish posts in the step.
series[].bearish_posts.p10
The 10th percentile of the bearish posts in the step.
series[].bearish_posts.p25
The 25th percentile of the bearish posts in the step.
series[].bearish_posts.p50
The 50th percentile of the bearish posts in the step.
series[].bearish_posts.p75
The 75th percentile of the bearish posts in the step.
series[].bearish_posts.p90
The 90th percentile of the bearish posts in the step.
series[].bullish_posts
object
The bullish posts expected in this 4-hour step alone, bots excluded: like /sentiment's interval posts, not its trailing 24-hour counts.
series[].bullish_posts
The bullish posts expected in this 4-hour step alone, bots excluded: like /sentiment's interval posts, not its trailing 24-hour counts.
series[].bullish_posts.mean
The expected number of bullish posts in the step.
series[].bullish_posts.p10
The 10th percentile of the bullish posts in the step.
series[].bullish_posts.p25
The 25th percentile of the bullish posts in the step.
series[].bullish_posts.p50
The 50th percentile of the bullish posts in the step.
series[].bullish_posts.p75
The 75th percentile of the bullish posts in the step.
series[].bullish_posts.p90
The 90th percentile of the bullish posts in the step.
series[].neutral_posts
object
The neutral posts expected in this 4-hour step alone, bots excluded: like /sentiment's interval posts, not its trailing 24-hour counts.
series[].neutral_posts
The neutral posts expected in this 4-hour step alone, bots excluded: like /sentiment's interval posts, not its trailing 24-hour counts.
series[].neutral_posts.mean
The expected number of neutral posts in the step.
series[].neutral_posts.p10
The 10th percentile of the neutral posts in the step.
series[].neutral_posts.p25
The 25th percentile of the neutral posts in the step.
series[].neutral_posts.p50
The 50th percentile of the neutral posts in the step.
series[].neutral_posts.p75
The 75th percentile of the neutral posts in the step.
series[].neutral_posts.p90
The 90th percentile of the neutral posts in the step.
series[].sentiment_signal
object
The sentiment signal at the end of the step, on the /sentiment scale: where the line is likely to be.
series[].sentiment_signal
The sentiment signal at the end of the step, on the /sentiment scale: where the line is likely to be.
series[].sentiment_signal.mean
The expected sentiment signal at the end of the step.
series[].sentiment_signal.p10
The 10th percentile of the sentiment signal at the end of the step.
series[].sentiment_signal.p50
The 50th percentile of the sentiment signal at the end of the step.
series[].sentiment_signal.p90
The 90th percentile of the sentiment signal at the end of the step.
series[].sentiment_signal.quantiles
21 quantiles of the sentiment signal at the end of the step: the 0th, 5th, 10th, ... 100th percentiles, lowest first. Interpolate between them for the chance of landing in any range.
series[].timestamp
UTC time the step ends: as_of plus 4, 8, ... 72 hours.
series[].total_posts
object
The posts (bullish, bearish, and neutral together) expected in this 4-hour step alone, bots excluded: like /sentiment's interval posts, not its trailing 24-hour counts. Its percentiles are of the total itself, so they are not the sums of the three kinds' percentiles.
series[].total_posts
The posts (bullish, bearish, and neutral together) expected in this 4-hour step alone, bots excluded: like /sentiment's interval posts, not its trailing 24-hour counts. Its percentiles are of the total itself, so they are not the sums of the three kinds' percentiles.
series[].total_posts.mean
The expected number of posts (bullish, bearish, and neutral together) in the step.
series[].total_posts.p10
The 10th percentile of the posts (bullish, bearish, and neutral together) in the step.
series[].total_posts.p25
The 25th percentile of the posts (bullish, bearish, and neutral together) in the step.
series[].total_posts.p50
The 50th percentile of the posts (bullish, bearish, and neutral together) in the step.
series[].total_posts.p75
The 75th percentile of the posts (bullish, bearish, and neutral together) in the step.
series[].total_posts.p90
The 90th percentile of the posts (bullish, bearish, and neutral together) in the step.
status
ok, or not_forecastable when the asset cannot be forecast (the summary fields are then null and the series empty; reason says why).
oknot_forecastable
turning
1 while sentiment is turning bullish (the last few hours lean clearly more bullish than the last day), -1 while it is turning bearish, 0 otherwise.
-101null
{
"as_of": "2026-09-14T09:15:00Z",
"chance_higher_24h": 0.74,
"chance_higher_24h_confident": true,
"chance_higher_72h": 0.61,
"chance_higher_72h_confident": false,
"current_sentiment_signal": 128.6,
"horizon_hours": 72,
"reason": null,
"refreshed": false,
"sample_paths": [
[
133.2,
141.7
],
[
126.4,
118.9
]
],
"series": [
{
"bearish_posts": {
"mean": 18,
"p10": 9.9,
"p25": 13.5,
"p50": 17.1,
"p75": 21.6,
"p90": 27.9
},
"bullish_posts": {
"mean": 46,
"p10": 25.3,
"p25": 34.5,
"p50": 43.7,
"p75": 55.2,
"p90": 71.3
},
"neutral_posts": {
"mean": 29,
"p10": 16,
"p25": 21.8,
"p50": 27.6,
"p75": 34.8,
"p90": 45
},
"sentiment_signal": {
"mean": 131.4,
"p10": 92.9,
"p50": 129.6,
"p90": 175.5,
"quantiles": [
21.6,
70.2,
92.9,
104.8,
113.1,
119.4,
124.2,
127.6,
130.5,
132.7,
134.5,
136.4,
138.7,
141.3,
144.9,
149.2,
155.1,
163.8,
179.4,
202.6,
287.3
]
},
"timestamp": "2026-09-14T13:15:00Z",
"total_posts": {
"mean": 93,
"p10": 51.2,
"p25": 69.8,
"p50": 88.4,
"p75": 111.6,
"p90": 144.2
}
},
{
"bearish_posts": {
"mean": 19,
"p10": 10.5,
"p25": 14.3,
"p50": 18.1,
"p75": 22.8,
"p90": 29.5
},
"bullish_posts": {
"mean": 50,
"p10": 27.5,
"p25": 37.5,
"p50": 47.5,
"p75": 60,
"p90": 77.5
},
"neutral_posts": {
"mean": 31,
"p10": 17.1,
"p25": 23.3,
"p50": 29.5,
"p75": 37.2,
"p90": 48.1
},
"sentiment_signal": {
"mean": 137.6,
"p10": 99.1,
"p50": 135.79999999999998,
"p90": 181.7,
"quantiles": [
21.6,
70.2,
92.9,
104.8,
113.1,
119.4,
124.2,
127.6,
130.5,
132.7,
134.5,
136.4,
138.7,
141.3,
144.9,
149.2,
155.1,
163.8,
179.4,
202.6,
287.3
]
},
"timestamp": "2026-09-14T17:15:00Z",
"total_posts": {
"mean": 100,
"p10": 55,
"p25": 75,
"p50": 95,
"p75": 120,
"p90": 155
}
}
],
"status": "ok",
"turning": 0
}