DEV Community

Stock Expert AI
Stock Expert AI

Posted on

Sentiment Scoring for Finance News: A Practical Intro

So you want to play around with sentiment analysis of finance news? Awesome. It's an interesting field, and frankly, it's not as scary as it sounds. I'll walk you through a basic but working example to get you started. This isn't an academic exercise; we're getting our hands dirty.

Why bother? News articles can move markets. Quantify the tone of news—is it positive, negative, or neutral about a company or asset?—and you might find predictive power. Note that "might." There are zero guarantees in this game.

Let's begin with the basics: text. Let's say we have this headline:

headline = "Company X announces record profits, stock price surges"

The simplest method is a pre-trained sentiment lexicon. Think of it as a dictionary with pre-assigned sentiment scores for words. A common one is VADER (Valence Aware Dictionary and sEntiment Reasoner). I can't tell you where to find it, but they exist.

Imagine the lexicon looks like this (totally fabricated, BTW):

lexicon = {
 "record": 0.7,
 "profits": 0.8,
 "surges": 0.9,
 "announces": 0.2, # Could be positive or neutral
 # ... lots more words ...
}
Enter fullscreen mode Exit fullscreen mode

Scores show how positive or negative the word is, perhaps on a scale from -1 to +1.

Here's some code:

def score_headline(headline, lexicon):
 words = headline.lower().split() # Lowercase and split into words
 total_score = 0
 for word in words:
 if word in lexicon:
 total_score += lexicon[word]
 return total_score

headline = "Company X announces record profits, stock price surges"
sentiment_score = score_headline(headline, lexicon)
print(f"Sentiment score: {sentiment_score}")
Enter fullscreen mode Exit fullscreen mode

This is dead simple. It sums the scores of headline words found in the lexicon. This yields a number. A positive number means positive sentiment, and the reverse is also true.

Why is this too simple?

Tons of reasons. It doesn't handle negation. "Not good" should be negative, but this code treats "good" as positive and ignores the "not." It also ignores context. "Bankrupt" is bad, but "avoided bankruptcy" is different. It certainly doesn't handle sarcasm; good luck with that one. And finally, it treats all words equally, which is not ideal.

Simple improvements:

  • Negation Handling: Look for "not," "never," or "no" before a sentiment word. If you find one, flip the sentiment score's sign.
def score_headline_with_negation(headline, lexicon):
 words = headline.lower().split()
 total_score = 0
 negate = False # Track negation
 for word in words:
 if word in ["not", "never", "no"]:
 negate = True
 elif word in lexicon:
 score = lexicon[word]
 if negate:
 score *= -1
 negate = False # Reset negation
 total_score += score
 return total_score
Enter fullscreen mode Exit fullscreen mode
  • N-grams: Consider pairs or triplets of words (bigrams, trigrams). The phrase "not good" is a bigram. You'd need to grow your lexicon to include these phrases. This gets complicated fast, I promise.
  • Weighting: Give different words different weights. Maybe "record" and "surges" matter more than "announces." Adjust the lexicon scores or use multipliers in your code to do this.

Real-World Stuff

Lexicons are almost never perfect, and you'll probably need to customize yours. This means manually checking headlines and changing scores, or adding terms. Tedious, but needed.

The subject area matters. Finance news sentiment differs from movie review sentiment. A general lexicon won't cut it.

Don't just use headlines. Article bodies have more info, but processing them costs a lot more.

Sentiment analysis is just one piece. Don't expect to get rich scoring headlines. It's a weak signal.

Beyond Lexicons

Lexicon methods are simple, but limited. Advanced methods use machine learning models trained on big text datasets. These models learn more complex patterns. But they need lots of data and compute power.

Sentiment scoring is fun and hard. Start simple, iterate, and don't expect miracles.

Top comments (0)