![](https://www.benzinga.com/apis/wp-content/uploads/2025/02/yorgos-ntrahas-mcAUHlGirVs-unsplash-2-1024x683.jpg)
Introduction
Context is as critical as data. Relying solely on price movements is like evaluating a novel by its cover—you risk overlooking the deeper narrative behind market shifts. Benzinga’s Newsfeed & Bars APIs bridge this gap by combining market-moving headlines with detailed historical price data, which gives a better view of market behavior.
In this guide, we will walk you through integrating these robust data sources into your trading strategy. You’ll learn how to extract full-length articles using Benzinga’s Why Is It Moving v2 endpoint and obtain precise price bars from the Bars endpoint. By merging these insights into a sentiment-based model, you can uncover actionable intelligence that enhances your market predictions. This straightforward yet powerful approach showcases how real-time news sentiment can elevate your decision-making in a dynamic market environment.
1. The APIs at a Glance
Newsfeed (Why Is It Moving v2)
- Endpoint: GET /news
- Purpose: Pulls news items by ticker, date, and other filters.
- Notable Parameters:
- token (your API key)
- tickers (comma-separated list of symbols)
- displayOutput (e.g., full to see the entire article body)
- dateFrom, dateTo or page and pageSize to organize how many articles you get.
- Why Use It?
Up-to-date headlines and deeper stories are essential for gauging sentiment and discovering why a stock is in the spotlight.
Bars Endpoint
- Endpoint: GET /bars
- Purpose: Returns historical candlestick (bar) data to measure how a stock’s price changes over time.
- Key Parameters:
- symbols (one or more comma-separated tickers)
- from, to (date range)
- interval (1D, 5M, 1W, etc.)
- Why Use It?
Comparing sentiment against price movements can help uncover patterns in how news influences stock returns.
2. Let’s Build a Sentiment-Fueled Predictor
Below, we’ll walk through the code in manageable parts to show how we fetch data, analyze it, and make a simple prediction about tomorrow’s price movement.
2.1 Import Libraries & Set Up Endpoints
First, we need our usual suspects for making requests, handling data, performing sentiment analysis, and running a model.
import requests
import pandas as pd
from textblob import TextBlob
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
import datetime, sys
API_KEY = "YOUR_API_KEY"
NEWS_ENDPOINT = "https://api.benzinga.com/api/v2/news"
BARS_ENDPOINT = "https://api.benzinga.com/api/v2/bars"
- requests helps us call the Benzinga APIs.
- pandas structures our data in easy-to-use data frames.
- TextBlob quickly calculates text sentiment.
- sklearn libraries let us build and evaluate a simple Logistic Regression model.
2.2 Fetching News Data
Next, we define a helper function to retrieve articles from the Newsfeed endpoint. We pass parameters like tickers, dateFrom, dateTo, and—most importantly—our API key.
def fetch_news_data(ticker="AAPL", date_from="2023-01-01", date_to="2023-12-01"):
params = {
"token": API_KEY,
"tickers": ticker,
"displayOutput": "full",
"dateFrom": date_from,
"dateTo": date_to,
"pageSize": 20
}
headers = {"accept": "application/json"}
resp = requests.get(NEWS_ENDPOINT, params=params, headers=headers)
if resp.status_code != 200:
print("Error:", resp.text)
- displayOutput=full ensures we get the article’s full text.
- pageSize=20 controls how many articles come back in a single query.
2.3 Fetching Price Bars
Similarly, our fetch_bar_data function grabs daily candlestick data. We can adjust the interval to 1D, 5M, or other increments.
def fetch_bar_data(ticker="AAPL", from_date="2023-01-01", to_date="2023-12-01"):
params = {
"token": API_KEY,
"symbols": ticker,
"interval": "1D",
"from": from_date,
"to": to_date
}
headers = {"accept": "application/json"}
resp = requests.get(BARS_ENDPOINT, params=params, headers=headers)
if resp.status_code != 200:
print("Error:", resp.text)
sys.exit(1)
return resp.json()
- symbols can be multiple tickers, comma-separated.
- interval=1D suits our plan to look at daily moves.
2.4 Combining News & Bars
Now it’s time to call our functions, parse the returned data, and build a pandas DataFrame. Notice how we handle the date in articles, then merge everything by date.
# 1. Fetch news
news_data = fetch_news_data("AAPL", "2023-01-01", "2023-12-01")
news_records = []
for article in news_data:
raw_date = article.get("created", "")
try:
date_parsed = datetime.datetime.strptime(raw_date[:25], "%a, %d %b %Y %H:%M:%S")
except:
date_parsed = None
combined_text = (article.get("title", "") + " " + article.get("body", "")).strip()
if date_parsed:
news_records.append({"date": date_parsed.date(), "text": combined_text})
df_news = pd.DataFrame(news_records)
Key Points
- We parse out the “created” field, trimming the string to avoid time-zone quirks.
- We combine the title and body to get the entire text for sentiment analysis.
2.5 Calculating Sentiment
Here’s where TextBlob comes in. We average the polarity (sentiment) of all articles that appear on the same day. Values range from -1 (very negative) to 1 (very positive).
df_news["sentiment"] = df_news["text"].apply(lambda x: TextBlob(x).sentiment.polarity)
df_daily_sent = df_news.groupby("date")["sentiment"].mean().reset_index()
df_daily_sent.columns = ["date", "avg_sentiment"]
2.6 Merging with Bar Data
Let’s grab the bar data, convert it to a DataFrame, and then merge the sentiment we just computed. We fill missing sentiment data with 0.
bars_data = fetch_bar_data("AAPL", "2023-01-01", "2023-12-01")
if isinstance(bars_data, list) and len(bars_data) > 0 and "candles" in bars_data[0]:
candle_list = bars_data[0]["candles"]
df_bars = pd.DataFrame(candle_list)
df_bars["time"] = pd.to_numeric(df_bars["time"], errors="coerce")
df_bars["date"] = pd.to_datetime(df_bars["time"], unit='ms').dt.date
df_bars = df_bars[["date", "open", "high", "low", "close"]]
else:
df_bars = pd.DataFrame(columns=["date", "open", "high", "low", "close"])
df_merged = pd.merge(df_bars, df_daily_sent, on="date", how="left").fillna(0)
2.7 Creating a Label and Training the Model
Finally, we shift the closing price by one day to see if tomorrow’s close is higher than today’s.
df_merged["next_close"] = df_merged["close"].shift(-1)
df_merged.dropna(inplace=True)
df_merged["label"] = (df_merged["next_close"] > df_merged["close"]).astype(int)
X = df_merged[["close", "avg_sentiment"]]
y = df_merged["label"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)
model = LogisticRegression()
model.fit(X_train, y_train)
- label is 1 if the stock price goes up, 0 otherwise.
- We’re using an 80/20 split for training and testing.
2.8 Evaluating & Making a Prediction
We check accuracy on the test set, then predict tomorrow’s movement.
y_pred = model.predict(X_test)
acc = accuracy_score(y_test, y_pred)
print(f"Validation Accuracy: {acc:.2f}")
latest_row = df_merged.iloc[-1][["close", "avg_sentiment"]]
prediction = model.predict([latest_row])
signal = "UP" if prediction[0] == 1 else "DOWN"
print(f"Tomorrow's predicted movement: {signal}")
3. The Output
Below is a sample output you might see when running the script:
nikhil05@Nikhil:~/Algo-AI/client/python $ python3 bezinga.py
News endpoint status: 200
News articles retrieved: 20
Bars endpoint status: 200
Bars retrieved: 231
Validation Accuracy: 0.59
Tomorrow's predicted movement: DOWN
- Validation Accuracy: This numeric score (e.g., 0.59) tells you how often the model guesses the next day’s movement correctly during back-testing.
- Tomorrow’s Predicted Movement: Printed as either “UP” or “DOWN.” This uses the last known data point’s sentiment and closing price to guess where the market might head tomorrow.
4. Why This Matters
Market headlines can trigger sudden spikes or drops, so ignoring news is like driving with one eye closed. By pairing Benzinga’s robust news feed (including article titles, teasers, and full bodies) with bar data, you can catch subtle shifts in investor sentiment. Even a simple logistic regression reveals how bullish or bearish signals in the news might align with a stock’s next-day performance.
Final Thoughts
That’s all it takes to build a basic sentiment-based stock predictor—and you can level it up in countless ways. Try analyzing multiple tickers at once, applying advanced natural language processing, or adding technical indicators on top of price bars.
With Benzinga’s APIs, you have the raw ingredients for your own unique “recipe” in market analysis. The beauty is in experimenting, refining, and seeing how each new insight helps you navigate the market more confidently.