Skip to content

Instantly share code, notes, and snippets.

@gjlr2000
Last active January 28, 2021 06:56
Show Gist options
  • Save gjlr2000/da7142d7fff9ddebadcd3d31a15af18b to your computer and use it in GitHub Desktop.
Save gjlr2000/da7142d7fff9ddebadcd3d31a15af18b to your computer and use it in GitHub Desktop.
SentimentAnalysisFinance.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "SentimentAnalysisFinance.ipynb",
"version": "0.3.2",
"provenance": [],
"collapsed_sections": []
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"[View in Colaboratory](https://colab.research.google.com/gist/gjlr2000/da7142d7fff9ddebadcd3d31a15af18b/sentimentanalysisfinance.ipynb)"
]
},
{
"metadata": {
"id": "QroVmDntMELx",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"# Sentiment Analysis in Finance\n",
"\n",
"A very hyped use of AI in Finance comes from the application of Sentiment Analysis as a factor to predict the future price of a security.\n",
"\n",
"Below I will explain some of the basics and caveats of using it in a financial context.\n",
"\n",
"Sentiment analysis can be defined as:\n",
"\n",
"\n",
"> \"*Sentiment analysis, or opinion mining, is an active area of\n",
"study in the field of natural language processing that analyzes\n",
"people's opinions, sentiments, evaluations, attitudes,\n",
"and emotions via the** computational treatment** of subjectivity\n",
"in text. *\"\n",
"\n",
"A simple introduction to it can be found in [\"How Quant Traders Use Sentiment To Get An Edge On The Market\"](https://www.forbes.com/sites/kumesharoomoogan/2015/08/06/how-quant-traders-use-sentiment-to-get-an-edge-on-the-market/#5a38018d4b5d), and typical academic papers explaining in full detail the process are [\"Twitter mood predicts the stock market.\"](https://arxiv.org/pdf/1010.3003.pdf) and [\"Stock Prediction Using Twitter Sentiment Analysis\"](http://cs229.stanford.edu/proj2011/GoelMittal-StockMarketPredictionUsingTwitterSentimentAnalysis.pdf).\n",
"\n",
"The basic idea is the following:\n",
"* convert a pipeline text sources (news, twitters, posts) into one or many **quantitative** (numerical) values,\n",
"* feed the above values into a complex model (classical econometrics or newly developed neural networks) as input to predict the price of a security.\n",
"\n",
"If you did open one of the academic papers, you would have been drowned in jargon, but by now \n",
"big companies like Bloomberg and new companies like RavenPack have jumped on the bandwagon and now provide Sentiment Analysis indices as utilities: [\"How you can get an edge by trading on news sentiment data\"](https://www.bloomberg.com/professional/blog/can-get-edge-trading-news-sentiment-data/) and [\"Abnormal Media Attention Impacts Stock Returns\"](https://www.ravenpack.com/research/abnormal-media-attention-impacts-stock-returns/).\n",
"\n",
"As in the previous posts, on one hand I prefer to produce [reproducible research](https://en.wikipedia.org/wiki/Reproducibility#Reproducible_research) in the form of jupyter notebooks that actually run (instead of pdf papers like the links above), but in this case the complexity is such that I only will illustrate basic concepts.\n",
"\n",
"Let starts by downloading a python off-the-shelf sentiment analyzer ([\"VADER: A Parsimonious Rule-based Model for\n",
"Sentiment Analysis of Social Media Text\"](https://pdfs.semanticscholar.org/a6e4/a2532510369b8f55c68f049ff11a892fefeb.pdf)).\n",
"\n",
"\n"
]
},
{
"metadata": {
"id": "l8s1wFcMEv27",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 88
},
"outputId": "b30d039c-5e74-4471-a07a-a3241004314b"
},
"cell_type": "code",
"source": [
"\n",
"import nltk\n",
"nltk.download('vader_lexicon')\n",
"from nltk.sentiment.vader import SentimentIntensityAnalyzer\n",
"from nltk import tokenize\n"
],
"execution_count": 2,
"outputs": [
{
"output_type": "stream",
"text": [
"[nltk_data] Downloading package vader_lexicon to /content/nltk_data...\n"
],
"name": "stdout"
},
{
"output_type": "stream",
"text": [
"/usr/local/lib/python3.6/dist-packages/nltk/twitter/__init__.py:20: UserWarning: The twython library has not been installed. Some functionality from the twitter package will not be available.\n",
" warnings.warn(\"The twython library has not been installed. \"\n"
],
"name": "stderr"
}
]
},
{
"metadata": {
"id": "LQIxsbZrFB18",
"colab_type": "code",
"colab": {}
},
"cell_type": "code",
"source": [
"sid = SentimentIntensityAnalyzer()"
],
"execution_count": 0,
"outputs": []
},
{
"metadata": {
"id": "Lb_lLZtJV96E",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"That's it. The magic of open source collaboration allows you to get the underlying tools free of charge, although if you are partial to corporate solution (and like Jeopardy) you can use IBM's [Watson Natural Understanding kit](https://www.ibm.com/watson/services/natural-language-understanding/).\n",
"\n",
"If you have this notebook open in Google colaboratory you can change the sentences below."
]
},
{
"metadata": {
"id": "LUOI27_nWz8J",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"outputId": "6c2f7c90-46b9-43eb-bc75-302bd0e501e1"
},
"cell_type": "code",
"source": [
"#@title Example of a negative sentence:\n",
"sentence = \"North Korea threatens to cancel Trump summit\" #@param {type:\"string\"}\n",
"ss = sid.polarity_scores(sentence)\n",
"print (ss)"
],
"execution_count": 4,
"outputs": [
{
"output_type": "stream",
"text": [
"{'neg': 0.479, 'neu': 0.521, 'pos': 0.0, 'compound': -0.5574}\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "HZ7fZdDdqdqQ",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"outputId": "1e3ad743-f9ad-4003-c1dc-5604166508d2"
},
"cell_type": "code",
"source": [
"#@title Example of a positive sentence:\n",
"sentence = \"Colombia's ex-fighters taught skills for peace\" #@param {type:\"string\"}\n",
"ss = sid.polarity_scores(sentence)\n",
"print (ss)"
],
"execution_count": 5,
"outputs": [
{
"output_type": "stream",
"text": [
"{'neg': 0.0, 'neu': 0.588, 'pos': 0.412, 'compound': 0.5423}\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "vVv6Ucb8Xj7I",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"You can see how the tool converted the text into various numerical values.\n",
"\n",
"The last value ('compound') can be used as a measure (from -1 to 1) of how 'positive' or 'negative' the sentence is, which in turn can now be manipulated numerically:\n",
"\n",
"\n",
"* aggregate them to create an index of positive and negative total sentiment,\n",
"* use metadata to identify clusters of activity geographically\n",
"* separate text by likely subject (company) and use sentiment by company\n",
"\n",
"However, how does this off-the-shelf tool work in a financial context ? After all, it was developed as \"*a simple rule-based model for **general** sentiment analysis*\". \n",
"\n",
"Let's try it in another two examples:\n"
]
},
{
"metadata": {
"id": "hZ1Vz0s4qGo9",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"outputId": "4dc67608-b2de-4ae1-ff7a-1a80389a54b2"
},
"cell_type": "code",
"source": [
"#@title Example of a positive business sentence:\n",
"sentence = \"Paddy Power Betfair confirms it is in talks to buy FanDuel\" #@param {type:\"string\"}\n",
"ss = sid.polarity_scores(sentence)\n",
"print (ss)"
],
"execution_count": 6,
"outputs": [
{
"output_type": "stream",
"text": [
"{'neg': 0.0, 'neu': 1.0, 'pos': 0.0, 'compound': 0.0}\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "WLkHvmZLGYQk",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"outputId": "fb09387a-bdda-4376-eb11-1dd35a4ff9b2"
},
"cell_type": "code",
"source": [
"#@title Example of a negative business sentence:\n",
"sentence = \"Court order threatens deal with Jio and sends shares down by a fifth\" #@param {type:\"string\"}\n",
"ss = sid.polarity_scores(sentence)\n",
"print (ss)"
],
"execution_count": 7,
"outputs": [
{
"output_type": "stream",
"text": [
"{'neg': 0.176, 'neu': 0.676, 'pos': 0.149, 'compound': -0.1027}\n"
],
"name": "stdout"
}
]
},
{
"metadata": {
"id": "vodIyE9TsqJj",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"It does not do well in this very specific domain; a business analyst would have expected FanDuel shares to shot up while Jio's were already down 20% (a number which does not correlate well with only a compound score of -0.1027 instead of close to -1).\n",
"\n",
"## Some issues with Sentiment analysis in Finance\n",
"\n",
"It turns out that this off-the-shelf tool is not great for financial results (and that is only after checking 2 simple cases). Some additional problems:\n",
"\n",
"\n",
"* Sentiment analysis is very 'domain specific' (academic talk to say that a set of tools only works in a pre-defined context - so you need to find the correct one for your applications)\n",
"* Regime changes can happen - if you keep using 'old' models for current data you will miss opportunities: think what happens if you use use pre-2013 models (before [HODL](https://litecoinalliance.org/hodl-on-for-dear-life-the-history-and-meaning-of-hodl/) for cryptocurrencies entered the cybersphere) - in fact, if you look at Vaders [lexicon data](https://www.kaggle.com/nltkdata/vader-lexicon/data) you will not find 'hodl'.\n",
"* as the 'Jio' example shows, a piece of news can be very negative *but* the price impact can be muted (that particular piece of news is very negative but is also a laggard indicator as the price already tanked).\n",
"\n",
"Instead, we can:\n",
"\n",
"###Create our own sentiment tool. \n",
"\n",
"The Vader guys:\n",
"> \" collected\n",
"intensity ratings on each of our candidate lexical\n",
"features from ten independent human raters (for a total of\n",
"90,000+ ratings).\"\n",
"\n",
"Instead of using their \"lexical features\", we would have to design and implement a system to collect the ratings of something close to 90k (the more the merrier) in a business context (create a user interface). I could not find a publicly available corpus of annotated financial news (financial news with a score).\n",
"\n",
"Also, if we are training in our own we could change the numerical measure to reflect directly the impact on the stock.\n",
"\n",
"**Connecting to relevant (and timely) news pipeline:** assuming the sentiment tool is ok, we would need to connect it to a set of reliable news and relevant comments (no fake news, or add a fake news analyser).\n",
"\n",
"### Use Professional sentiment indicators \n",
"I mentioned above some sentiment analysis providers. The good thing is that the platforms handle the whole data connection. Unfortunately, their systems are proprietary (blackest black box of all):\n",
"* so we cannot test whether their sentiment tool is finely tuned to our specific financial topics (or generic business topics), \n",
"* we cannot control how often they update them,\n",
"* are available to competitors, hence the alpha they can provide will diminish in time.\n",
"\n",
"\n"
]
},
{
"metadata": {
"id": "bMaodn4csn0K",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"# Entity Recognition\n",
"\n",
"In financial news we would also like to to separate text documents that correspond to different companies. We can do so by using additional modules that perform [Entity Recognition](https://en.wikipedia.org/wiki/Named-entity_recognition): \"*a subtask of information extraction that seeks to locate and classify named entities in text into pre-defined categories such as the names of persons, organizations, locations, expressions of times, quantities, monetary values, percentages, etc*\"\n",
"\n",
"Applying the general purpose ER module on:\n",
"\n",
"\n",
"> \"Court order threatens deal with Jio and sends shares down by a fifth\"\n",
"\n",
"We get two entities, \"Court\" and \"Jio\": if we were monitoring \"Jio\" we could now separate this message into the 'bad' news bucket and see how its sentiment would affect the price.\n",
"\n",
"\n",
"\n",
"\n"
]
},
{
"metadata": {
"id": "6iR1EL06nVRH",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 1319
},
"outputId": "a038c61a-7ab7-4372-e04a-6ccb7c52dc64"
},
"cell_type": "code",
"source": [
"\n",
"nltk.download('maxent_ne_chunker')\n",
"nltk.download('words')\n",
"\n",
"from nltk import ne_chunk, pos_tag, word_tokenize\n",
"from nltk.tree import Tree\n",
" \n",
"def get_continuous_chunks(text):\n",
" chunked = ne_chunk(pos_tag(word_tokenize(text)))\n",
" prev = None\n",
" continuous_chunk = []\n",
" current_chunk = []\n",
" for i in chunked:\n",
"# print(i)\n",
"# print (type(i))\n",
"\n",
" if type(i) == Tree:\n",
" print(i)\n",
" current_chunk.append(\" \".join([token for token, pos in i.leaves()]))\n",
" elif current_chunk:\n",
" named_entity = \" \".join(current_chunk)\n",
" if named_entity not in continuous_chunk:\n",
" continuous_chunk.append(named_entity)\n",
" current_chunk = []\n",
" else:\n",
" continue\n",
" return continuous_chunk\n",
"\n",
"sentence = \"Court order threatens deal with Jio and sends shares down by a fifth\"\n",
"get_continuous_chunks(sentence)\n",
"\n",
"\n",
"\n"
],
"execution_count": 8,
"outputs": [
{
"output_type": "stream",
"text": [
"[nltk_data] Downloading package maxent_ne_chunker to\n",
"[nltk_data] /content/nltk_data...\n",
"[nltk_data] Unzipping chunkers/maxent_ne_chunker.zip.\n",
"[nltk_data] Downloading package words to /content/nltk_data...\n",
"[nltk_data] Unzipping corpora/words.zip.\n"
],
"name": "stdout"
},
{
"output_type": "error",
"ename": "LookupError",
"evalue": "ignored",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mLookupError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-8-6104947d0db7>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 28\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 29\u001b[0m \u001b[0msentence\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"Court order threatens deal with Jio and sends shares down by a fifth\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 30\u001b[0;31m \u001b[0mget_continuous_chunks\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msentence\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 31\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 32\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m<ipython-input-8-6104947d0db7>\u001b[0m in \u001b[0;36mget_continuous_chunks\u001b[0;34m(text)\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mget_continuous_chunks\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtext\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 9\u001b[0;31m \u001b[0mchunked\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mne_chunk\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpos_tag\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mword_tokenize\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtext\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 10\u001b[0m \u001b[0mprev\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0mcontinuous_chunk\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/usr/local/lib/python3.6/dist-packages/nltk/tokenize/__init__.py\u001b[0m in \u001b[0;36mword_tokenize\u001b[0;34m(text, language, preserve_line)\u001b[0m\n\u001b[1;32m 126\u001b[0m \u001b[0;34m:\u001b[0m\u001b[0mtype\u001b[0m \u001b[0mpreserver_line\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mbool\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 127\u001b[0m \"\"\"\n\u001b[0;32m--> 128\u001b[0;31m \u001b[0msentences\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mtext\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mpreserve_line\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0msent_tokenize\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtext\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlanguage\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 129\u001b[0m return [token for sent in sentences\n\u001b[1;32m 130\u001b[0m for token in _treebank_word_tokenizer.tokenize(sent)]\n",
"\u001b[0;32m/usr/local/lib/python3.6/dist-packages/nltk/tokenize/__init__.py\u001b[0m in \u001b[0;36msent_tokenize\u001b[0;34m(text, language)\u001b[0m\n\u001b[1;32m 92\u001b[0m \u001b[0;34m:\u001b[0m\u001b[0mparam\u001b[0m \u001b[0mlanguage\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mthe\u001b[0m \u001b[0mmodel\u001b[0m \u001b[0mname\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mthe\u001b[0m \u001b[0mPunkt\u001b[0m \u001b[0mcorpus\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 93\u001b[0m \"\"\"\n\u001b[0;32m---> 94\u001b[0;31m \u001b[0mtokenizer\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mload\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'tokenizers/punkt/{0}.pickle'\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlanguage\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 95\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mtokenizer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtokenize\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtext\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 96\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/usr/local/lib/python3.6/dist-packages/nltk/data.py\u001b[0m in \u001b[0;36mload\u001b[0;34m(resource_url, format, cache, verbose, logic_parser, fstruct_reader, encoding)\u001b[0m\n\u001b[1;32m 832\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 833\u001b[0m \u001b[0;31m# Load the resource.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 834\u001b[0;31m \u001b[0mopened_resource\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_open\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresource_url\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 835\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 836\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mformat\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'raw'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/usr/local/lib/python3.6/dist-packages/nltk/data.py\u001b[0m in \u001b[0;36m_open\u001b[0;34m(resource_url)\u001b[0m\n\u001b[1;32m 950\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 951\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mprotocol\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mprotocol\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlower\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'nltk'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 952\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfind\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpath_\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpath\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m''\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mopen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 953\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mprotocol\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlower\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'file'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 954\u001b[0m \u001b[0;31m# urllib might not use mode='rb', so handle this one ourselves:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m/usr/local/lib/python3.6/dist-packages/nltk/data.py\u001b[0m in \u001b[0;36mfind\u001b[0;34m(resource_name, paths)\u001b[0m\n\u001b[1;32m 671\u001b[0m \u001b[0msep\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'*'\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0;36m70\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 672\u001b[0m \u001b[0mresource_not_found\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'\\n%s\\n%s\\n%s\\n'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0msep\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msep\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 673\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mLookupError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresource_not_found\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 674\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 675\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mLookupError\u001b[0m: \n**********************************************************************\n Resource \u001b[93mpunkt\u001b[0m not found.\n Please use the NLTK Downloader to obtain the resource:\n\n \u001b[31m>>> import nltk\n >>> nltk.download('punkt')\n \u001b[0m\n Searched in:\n - '/content/nltk_data'\n - '/usr/share/nltk_data'\n - '/usr/local/share/nltk_data'\n - '/usr/lib/nltk_data'\n - '/usr/local/lib/nltk_data'\n - '/usr/nltk_data'\n - '/usr/lib/nltk_data'\n - ''\n**********************************************************************\n"
]
}
]
},
{
"metadata": {
"id": "nIikAOf5GpeE",
"colab_type": "text"
},
"cell_type": "markdown",
"source": [
"As with Sentiment analysis, Entity recognition can be fine tuned to handle a specific financial domain (companies,equity, bonds, sovereigns, etc) - but needs lots of data and a training system, but also can be used independently:\n",
"* as a measure of media impact (aggregation of news mentioning a company, regardless of whether bad or good)\n",
"* to extract information and act on it -- for example in the news \"Paddy Power Betfair confirms it is in talks to buy FanDuel\" ER can be used to identify which company (Paddy Power Betfair) buys another (FanDuel) and act on it (e.g. [Risk arbitrage](https://en.wikipedia.org/wiki/Risk_arbitrage) - \"*a hedge fund investment strategy that speculates on the successful completion of mergers and acquisitions.*\")\n"
]
},
{
"metadata": {
"id": "KG1qVEL2GcMW",
"colab_type": "code",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 85
},
"outputId": "7772a0c5-2779-4b5e-c2b5-2f2970d42ed5"
},
"cell_type": "code",
"source": [
"sentence = \"Paddy Power Betfair confirms it is in talks to buy FanDuel\" \n",
"get_continuous_chunks(sentence)"
],
"execution_count": 0,
"outputs": [
{
"output_type": "stream",
"text": [
"(PERSON Paddy/NNP)\n",
"(PERSON Power/NNP Betfair/NNP)\n",
"(ORGANIZATION FanDuel/NNP)\n"
],
"name": "stdout"
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
"['Paddy Power Betfair']"
]
},
"metadata": {
"tags": []
},
"execution_count": 34
}
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment