Add check_supported and trending endpoint from Sentiment Investor (#1262)

* Add supported and trending endpoint

* Allow valid hour to be 0

* Update Hugo server

* Update Hugo optional arguemnts

* Update documents for start data type

* Adding terminal images

* Update _index.md

* Fix header error

* Update tests for api token sentiment investor

* Add test for Sentiment Investor View & Model

* Mock the token

* Changed color for trend command

* Mock test view and add document for Test README

Co-authored-by: Minh Hoang <minh@Minhs-MBP.Home>
Co-authored-by: jmaslek <jmaslek11@gmail.com>
This commit is contained in:
minhhoang1023
2022-01-28 22:05:44 +00:00
committed by GitHub
parent ad85411542
commit d8b4fc0026
33 changed files with 774 additions and 234 deletions

View File

@@ -2,6 +2,7 @@
__docformat__ = "numpy"
from typing import Union, Dict
from datetime import datetime, timedelta
import requests
import pandas as pd
@@ -48,10 +49,96 @@ def get_historical(ticker: str, start: str, end: str, number: int) -> pd.DataFra
# check if result is not empty
if result:
df = pd.DataFrame(response.json()["results"])
df = pd.DataFrame(result)
df = df.set_index("timestamp_date")
df.index = pd.to_datetime(df.index)
return df
return pd.DataFrame()
def check_supported_ticker(ticker: str) -> bool:
"""Check if the ticker is supported
Source: [Sentiment Investor]
Parameters
----------
ticker: str
Ticker to view sentiment data
Returns
-------
result: Boolean
"""
payload: Dict[str, str] = {
"token": cfg.API_SENTIMENTINVESTOR_TOKEN,
"symbol": ticker,
}
response = requests.get(
"https://api.sentimentinvestor.com/v1/supported", params=payload
)
if response.status_code == 200:
try:
# if ticker is valid, payload has result key
return response.json()["result"]
# if ticker is not valid, payload doesn't have result key
except KeyError:
pass
return False
def get_trending(start: datetime, hour: int, number: int) -> pd.DataFrame:
"""Get sentiment data on the most talked about tickers
within the last hour
Source: [Sentiment Investor]
Parameters
----------
start: datetime
Datetime object (e.g. datetime(2021, 12, 21)
hour: int
Hour of the day in 24-hour notation (e.g. 14)
number : int
Number of results returned by API call
Maximum 250 per api call
Returns
-------
pd.DataFrame
Dataframe of trending data
"""
# type is datetime
start_timestamp = start + timedelta(hours=hour)
payload: Dict[str, Union[int, str]] = {
"token": cfg.API_SENTIMENTINVESTOR_TOKEN,
"start": str(start_timestamp),
"end": str(start_timestamp),
"limit": number,
}
response = requests.get(
"https://api.sentimentinvestor.com/v1/trending", params=payload
)
if response.status_code == 200:
result = response.json()["results"]
# check if result is not empty
if result:
df = pd.DataFrame(result)
return df
return pd.DataFrame()

View File

@@ -2,8 +2,10 @@
__docformat__ = "numpy"
import os
from datetime import datetime
import matplotlib.dates as mdates
from matplotlib import pyplot as plt
import pandas as pd
from gamestonk_terminal.common.behavioural_analysis import sentimentinvestor_model
from gamestonk_terminal.helper_funcs import export_data, print_rich_table
@@ -44,56 +46,136 @@ def display_historical(
-------
"""
df = sentimentinvestor_model.get_historical(ticker, start, end, number)
supported_ticker = sentimentinvestor_model.check_supported_ticker(ticker)
# Check to see if the ticker is supported
if not supported_ticker:
print(f"Ticker {ticker} not supported. Please try another one!\n")
else:
df = sentimentinvestor_model.get_historical(ticker, start, end, number)
if df.empty:
print("Error in Sentiment Investor request")
else:
_, ax1 = plt.subplots(figsize=(25, 7))
ax1.plot(df.index, df["RHI"], c="k")
ax2 = ax1.twinx()
ax1.grid()
ax2.plot(df.index, df["AHI"], c="orange")
ax1.set_ylabel("RHI")
ax1.set_xlabel("Time")
ax1.set_title("Hourly-level data of RHI and AHI")
ax1.set_xlim(df.index[0], df.index[-1])
ax2.set_ylabel("AHI")
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d %H:%M"))
plt.gcf().autofmt_xdate()
if gtff.USE_ION:
plt.ion()
plt.show()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"hist",
df,
)
RAW_COLS = ["twitter", "stocktwits", "yahoo", "likes", "RHI", "AHI"]
if raw:
df.index = df.index.strftime("%Y-%m-%d %H:%M")
df.index.name = "Time"
print_rich_table(
df[RAW_COLS].head(limit),
headers=[
"Twitter",
"Stocktwits",
"Yahoo",
"Likes",
"RHI",
"AHI",
],
show_index=True,
index_name="Time",
title="Historical Sentiment Data",
)
def display_trending(
start: datetime,
hour: int,
export: str,
number: int = 10,
limit: int = 10,
):
"""Display most talked about tickers within
the last hour together with their sentiment data.
Parameters
----------
start: datetime
Datetime object (e.g. datetime(2021, 12, 21)
hour: int
Hour of the day in 24-hour notation (e.g. 14)
number : int
Number of results returned by API call
Maximum 250 per api call
limit: int
Number of results display on the terminal
Default: 10
-------
Returns
None
"""
df = sentimentinvestor_model.get_trending(start, hour, number)
if df.empty:
print("Error in Sentiment Investor request")
else:
_, ax1 = plt.subplots(figsize=(25, 7))
ax1.plot(df.index, df["RHI"], c="k")
ax2 = ax1.twinx()
ax1.grid()
ax2.plot(df.index, df["AHI"], c="orange")
ax1.set_ylabel("RHI")
ax1.set_xlabel("Time")
ax1.set_title("Hourly-level data of RHI and AHI")
ax1.set_xlim(df.index[0], df.index[-1])
ax2.set_ylabel("AHI")
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d %H:%M"))
plt.gcf().autofmt_xdate()
if gtff.USE_ION:
plt.ion()
plt.show()
export_data(
export,
os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks"),
"hist",
"trend",
df,
)
RAW_COLS = ["twitter", "stocktwits", "yahoo", "likes", "RHI", "AHI"]
RAW_COLS = [
"total",
"twitter",
"stocktwits",
"yahoo",
"likes",
"RHI",
"AHI",
]
if raw:
df.index = df.index.strftime("%Y-%m-%d %H:%M")
df.index.name = "Time"
df.ticker = df.ticker.str.upper()
df = df.set_index("ticker")
print_rich_table(
df[RAW_COLS].head(limit),
headers=[
"Time",
"Twitter",
"Stocktwits",
"Yahoo",
"Likes",
"RHI",
"AHI",
],
show_index=True,
title="Historical Sentiment Data",
)
df.timestamp_date = pd.to_datetime(df.timestamp_date)
timestamp = df.timestamp_date[0].strftime("%Y-%m-%d %H:%M")
print_rich_table(
df[RAW_COLS].head(limit),
headers=[
"Total",
"Twitter",
"Stocktwits",
"Yahoo",
"Likes",
"RHI",
"AHI",
],
show_index=True,
index_name="Ticker",
title=f"Most trending stocks at {timestamp}",
)

View File

@@ -101,7 +101,6 @@ API_FINNHUB_KEY = os.getenv("GT_API_FINNHUB_KEY") or "REPLACE_ME"
API_IEX_TOKEN = os.getenv("GT_API_IEX_KEY") or "REPLACE_ME"
# https://www.sentimentinvestor.com
API_SENTIMENTINVESTOR_KEY = os.getenv("GT_API_SENTIMENTINVESTOR_KEY") or "REPLACE_ME"
API_SENTIMENTINVESTOR_TOKEN = (
os.getenv("GT_API_SENTIMENTINVESTOR_TOKEN") or "REPLACE_ME"
)

View File

@@ -1,7 +1,7 @@
"""CoinGecko model"""
__docformat__ = "numpy"
# pylint: disable=C0301
# pylint: disable=C0301, E1101
from typing import Any, List
import re

View File

@@ -264,6 +264,16 @@ def valid_date(s: str) -> datetime:
raise argparse.ArgumentTypeError(f"Not a valid date: {s}") from value_error
def valid_hour(hr: str) -> int:
"""Argparse type to check hour is valid with 24-hour notation"""
new_hr = int(hr)
if (new_hr < 0) or (new_hr > 24):
raise argparse.ArgumentTypeError(f"{hr} doesn't follow 24-hour notion.")
return new_hr
def plot_view_stock(df: pd.DataFrame, symbol: str, interval: str):
"""
Plot the loaded stock dataframe

View File

@@ -15,6 +15,7 @@ from gamestonk_terminal.helper_funcs import (
parse_known_args_and_warn,
check_int_range,
valid_date,
valid_hour,
check_positive,
)
from gamestonk_terminal.menu import session
@@ -56,6 +57,7 @@ class BehaviouralAnalysisController(StockController):
"popular",
"getdd",
"hist",
"trend",
]
historical_sort = ["date", "value"]
@@ -106,7 +108,8 @@ class BehaviouralAnalysisController(StockController):
regions regions that show highest interest in stock
queries top related queries with this stock
rise top rising related queries with stock{has_ticker_end}
[src][SentimentInvestor][/src]{has_ticker_start}
[src][SentimentInvestor][/src]
trend most talked about tickers within the last hour{has_ticker_start}
hist plot historical RHI and AHI data by hour{has_ticker_end}[/cmds]
"""
@@ -714,6 +717,52 @@ class BehaviouralAnalysisController(StockController):
raw=ns_parser.raw,
limit=ns_parser.limit,
)
else:
print("No ticker loaded. Please load using 'load <ticker>'\n")
console.print("No ticker loaded. Please load using 'load <ticker>'\n")
def call_trend(self, other_args: List[str]):
"""Process trend command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="trend",
description="Show most talked about tickers within the last one hour",
)
parser.add_argument(
"-s",
"--start",
type=valid_date,
default=datetime.utcnow().strftime("%Y-%m-%d"),
dest="start",
help="The starting date (format YYYY-MM-DD). Default: Today",
)
parser.add_argument(
"-hr",
"--hour",
type=valid_hour,
default=0,
dest="hour",
help="Hour of the day in the 24-hour notation. Example: 14",
)
parser.add_argument(
"-n",
"--number",
default=10,
type=check_positive,
dest="number",
help="Number of results returned from Sentiment Investor. Default: 10",
)
ns_parser = parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED, limit=10
)
if ns_parser:
sentimentinvestor_view.display_trending(
start=ns_parser.start,
hour=ns_parser.hour,
export=ns_parser.export,
number=ns_parser.number,
)

View File

@@ -261,13 +261,13 @@ def check_api_keys():
else:
key_dict["BITQUERY"] = "defined, test failed"
# SentimentInvestor keys
si_keys = [cfg.API_SENTIMENTINVESTOR_KEY, cfg.API_SENTIMENTINVESTOR_TOKEN]
si_keys = [cfg.API_SENTIMENTINVESTOR_TOKEN]
if "REPLACE_ME" in si_keys:
key_dict["SENTIMENT_INVESTOR"] = "Not defined"
else:
account = requests.get(
f"https://api.sentimentinvestor.com/v4/account"
f"?token={cfg.API_SENTIMENTINVESTOR_TOKEN}&key={cfg.API_SENTIMENTINVESTOR_KEY}"
f"https://api.sentimentinvestor.com/v1/trending"
f"?token={cfg.API_SENTIMENTINVESTOR_TOKEN}"
)
if account.ok and account.json().get("success", False):
key_dict["SENTIMENT_INVESTOR"] = "Defined, test passed"

19
tests/README.md vendored
View File

@@ -249,6 +249,23 @@ More information on markers location are available in pytest documentation :
## 3.8. Known `issue` / `solution`
**ION Usage**
If you are testing for a `_view.py` module that uses `ION`, you would need to mock it. With Windows, the charts / graphs are unable to close the graph applications. This would make the tests failed when running with Windows.
You can use the following example below. Once you have mocked the graphs / charts, simply call the display function, which is now a mocked object.
```
@pytest.mark.vcr
@pytest.mark.record_stdout
def test_display_defi_tvl(mocker):
# MOCK CHARTS
mocker.patch.object(target=llama_view.gtff, attribute="USE_ION", new=True)
mocker.patch(target="gamestonk_terminal.stocks.options.yfinance_view.plt.ion")
mocker.patch(target="gamestonk_terminal.stocks.options.yfinance_view.plt.show")
llama_view.display_defi_tvl(20)
```
**YFINANCE**
If a method is using the `yfinance` library but do not let you pick the `start/end` dates it will pick the current date each time.
@@ -324,7 +341,7 @@ def test_ark_orders_view(kwargs_dict, mocker, use_color):
The library `requests` doesn't support : `brotli` comnpression.
Unless `brotli` library is installed in the enviroment.
Unless `brotli` library is installed in the environment.
Plus `brotli` is not in `GamestonkTerminal` requirements.

View File

@@ -1772,4 +1772,36 @@ interactions:
status:
code: 200
message: OK
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- python-requests/2.26.0
method: GET
uri: https://api.sentimentinvestor.com/v1/trending?token=MJYQW23-5TMMDD8-KEMTCN9-GEHX08G
response:
body:
string: '{"success":true,"results":[{"id":"hist_27_11_tsla","sentiment_count":38,"timestamp_date":"2022-01-27T11:00:00.000Z","total":94,"twitter":0,"stocktwits":73,"reddit_comment":0,"reddit_post":0,"yahoo":21,"ticker":"tsla","likes":39,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":1.4586,"AHI":1.4576,"SGP":0,"total_tweet_volume":203},{"id":"hist_27_11_msft","sentiment_count":8,"timestamp_date":"2022-01-27T11:00:00.000Z","total":16,"twitter":0,"stocktwits":10,"reddit_comment":0,"reddit_post":0,"yahoo":6,"ticker":"msft","likes":6,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.6668,"AHI":0.9962,"SGP":0,"total_tweet_volume":21},{"id":"hist_27_11_aapl","sentiment_count":22,"timestamp_date":"2022-01-27T11:00:00.000Z","total":39,"twitter":0,"stocktwits":32,"reddit_comment":0,"reddit_post":0,"yahoo":7,"ticker":"aapl","likes":11,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":1.3089,"AHI":1.4339,"SGP":0,"total_tweet_volume":15},{"id":"hist_27_12_amzn","sentiment_count":3,"timestamp_date":"2022-01-27T12:00:00.000Z","total":6,"twitter":0,"stocktwits":6,"reddit_comment":0,"reddit_post":0,"yahoo":0,"ticker":"amzn","likes":2,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.6556,"AHI":0.7887,"SGP":0,"total_tweet_volume":6},{"id":"hist_27_11_t","sentiment_count":7,"timestamp_date":"2022-01-27T11:00:00.000Z","total":18,"twitter":0,"stocktwits":8,"reddit_comment":0,"reddit_post":0,"yahoo":10,"ticker":"t","likes":1,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":1.2419,"AHI":1.5161,"SGP":0,"total_tweet_volume":3},{"id":"hist_27_11_amd","sentiment_count":68,"timestamp_date":"2022-01-27T11:00:00.000Z","total":131,"twitter":0,"stocktwits":75,"reddit_comment":0,"reddit_post":0,"yahoo":56,"ticker":"amd","likes":60,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":1.1039,"AHI":1.1116,"SGP":0,"total_tweet_volume":2}],"start":"2022-01-27T11:00:00.000Z","end":"2022-01-27T12:59:59.999Z","limit":10}'
headers:
Access-Control-Allow-Origin:
- '*'
Content-Length:
- '1964'
Content-Type:
- application/json; charset=utf-8
Date:
- Thu, 27 Jan 2022 12:44:37 GMT
Etag:
- W/"7ac-qd5HBUoH8qXqlwMmTJslqPErT/Q"
X-Powered-By:
- Express
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,34 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- python-requests/2.26.0
method: GET
uri: https://api.sentimentinvestor.com/v1/supported?symbol=BTC-USD&token=MOCK_TOKEN
response:
body:
string: '{"error":"symbol \"btc-usd\" is not currently active."}'
headers:
Access-Control-Allow-Origin:
- '*'
Content-Length:
- '55'
Content-Type:
- application/json; charset=utf-8
Date:
- Thu, 27 Jan 2022 16:22:36 GMT
Etag:
- W/"37-H7l44r2kph8E+3x5mpaNoV/50F8"
X-Powered-By:
- Express
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,34 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- python-requests/2.26.0
method: GET
uri: https://api.sentimentinvestor.com/v1/supported?symbol=BTC&token=MOCK_TOKEN
response:
body:
string: '{"success":true,"result":true}'
headers:
Access-Control-Allow-Origin:
- '*'
Content-Length:
- '30'
Content-Type:
- application/json; charset=utf-8
Date:
- Thu, 27 Jan 2022 16:22:36 GMT
Etag:
- W/"1e-67lGrrcaMC/51/8ZvvIFlxBZfJs"
X-Powered-By:
- Express
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,34 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- python-requests/2.26.0
method: GET
uri: https://api.sentimentinvestor.com/v1/historical?end=2020-12-7&limit=100&start=2020-12-1&symbol=AAPL&token=MOCK_TOKEN
response:
body:
string: '{"success":true,"start":"2020-12-01T00:00:00.000Z","end":"2020-12-07T00:00:00.000Z","limit":"100","symbol":"AAPL","results":[],"total":0}'
headers:
Access-Control-Allow-Origin:
- '*'
Content-Length:
- '137'
Content-Type:
- application/json; charset=utf-8
Date:
- Thu, 27 Jan 2022 16:22:37 GMT
Etag:
- W/"89-ae4LkH5VoQJkOubQIH9O3cOMy+U"
X-Powered-By:
- Express
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,34 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- python-requests/2.26.0
method: GET
uri: https://api.sentimentinvestor.com/v1/trending?end=2021-12-21+09%3A00%3A00&limit=10&start=2021-12-21+09%3A00%3A00&token=MOCK_TOKEN
response:
body:
string: '{"success":true,"results":[{"id":"hist_21_9_btc.x","sentiment_count":22,"timestamp_date":"2021-12-21T09:00:00.000Z","total":40,"twitter":0,"stocktwits":40,"reddit_comment":0,"reddit_post":0,"yahoo":0,"ticker":"btc.x","likes":25,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":3.4728,"AHI":3.3006,"SGP":0},{"id":"hist_21_9_amc","sentiment_count":33,"timestamp_date":"2021-12-21T09:00:00.000Z","total":40,"twitter":0,"stocktwits":40,"reddit_comment":0,"reddit_post":0,"yahoo":0,"ticker":"amc","likes":57,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.4931,"AHI":0.5699,"SGP":0},{"id":"hist_21_9_tsla","sentiment_count":19,"timestamp_date":"2021-12-21T09:00:00.000Z","total":33,"twitter":0,"stocktwits":31,"reddit_comment":0,"reddit_post":0,"yahoo":2,"ticker":"tsla","likes":30,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.4169,"AHI":0.5384,"SGP":1,"sentiment":7.8684},{"id":"hist_21_9_mrna","sentiment_count":11,"timestamp_date":"2021-12-21T09:00:00.000Z","total":15,"twitter":0,"stocktwits":8,"reddit_comment":0,"reddit_post":0,"yahoo":7,"ticker":"mrna","likes":4,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.7673,"AHI":0.6587,"SGP":0},{"id":"hist_21_9_btc","sentiment_count":9,"timestamp_date":"2021-12-21T09:00:00.000Z","total":12,"twitter":0,"stocktwits":0,"reddit_comment":0,"reddit_post":0,"yahoo":12,"ticker":"btc","likes":0,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.4879,"AHI":0.4465,"SGP":1,"sentiment":16.9798},{"id":"hist_21_9_aapl","sentiment_count":9,"timestamp_date":"2021-12-21T09:00:00.000Z","total":10,"twitter":0,"stocktwits":8,"reddit_comment":0,"reddit_post":0,"yahoo":2,"ticker":"aapl","likes":10,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.3676,"AHI":0.4111,"SGP":0},{"id":"hist_21_9_lcid","sentiment_count":8,"timestamp_date":"2021-12-21T09:00:00.000Z","total":10,"twitter":0,"stocktwits":9,"reddit_comment":0,"reddit_post":0,"yahoo":1,"ticker":"lcid","likes":23,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.4674,"AHI":0.5561,"SGP":0},{"id":"hist_21_9_amd","sentiment_count":6,"timestamp_date":"2021-12-21T09:00:00.000Z","total":9,"twitter":0,"stocktwits":3,"reddit_comment":0,"reddit_post":0,"yahoo":6,"ticker":"amd","likes":3,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.4516,"AHI":0.5424,"SGP":0},{"id":"hist_21_9_nke","sentiment_count":4,"timestamp_date":"2021-12-21T09:00:00.000Z","total":6,"twitter":0,"stocktwits":4,"reddit_comment":0,"reddit_post":0,"yahoo":2,"ticker":"nke","likes":1,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":1.3136,"AHI":2.0879,"SGP":0},{"id":"hist_21_9_t","sentiment_count":4,"timestamp_date":"2021-12-21T09:00:00.000Z","total":6,"twitter":0,"stocktwits":3,"reddit_comment":0,"reddit_post":0,"yahoo":3,"ticker":"t","likes":0,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.4844,"AHI":0.6866,"SGP":0}],"start":"2021-12-21T09:00:00.000Z","end":"2021-12-21T09:00:00.000Z","limit":"10"}'
headers:
Access-Control-Allow-Origin:
- '*'
Content-Length:
- '2986'
Content-Type:
- application/json; charset=utf-8
Date:
- Thu, 27 Jan 2022 16:22:37 GMT
Etag:
- W/"baa-MWXy163w4MAIoe1ZkpGOeHUUI0M"
X-Powered-By:
- Express
status:
code: 200
message: OK
version: 1

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,34 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- python-requests/2.26.0
method: GET
uri: https://api.sentimentinvestor.com/v1/trending?end=2021-12-21+09%3A00%3A00&limit=10&start=2021-12-21+09%3A00%3A00&token=MOCK_TOKEN
response:
body:
string: '{"success":true,"results":[{"id":"hist_21_9_btc.x","sentiment_count":22,"timestamp_date":"2021-12-21T09:00:00.000Z","total":40,"twitter":0,"stocktwits":40,"reddit_comment":0,"reddit_post":0,"yahoo":0,"ticker":"btc.x","likes":25,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":3.4728,"AHI":3.3006,"SGP":0},{"id":"hist_21_9_amc","sentiment_count":33,"timestamp_date":"2021-12-21T09:00:00.000Z","total":40,"twitter":0,"stocktwits":40,"reddit_comment":0,"reddit_post":0,"yahoo":0,"ticker":"amc","likes":57,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.4931,"AHI":0.5699,"SGP":0},{"id":"hist_21_9_tsla","sentiment_count":19,"timestamp_date":"2021-12-21T09:00:00.000Z","total":33,"twitter":0,"stocktwits":31,"reddit_comment":0,"reddit_post":0,"yahoo":2,"ticker":"tsla","likes":30,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.4169,"AHI":0.5384,"SGP":1,"sentiment":7.8684},{"id":"hist_21_9_mrna","sentiment_count":11,"timestamp_date":"2021-12-21T09:00:00.000Z","total":15,"twitter":0,"stocktwits":8,"reddit_comment":0,"reddit_post":0,"yahoo":7,"ticker":"mrna","likes":4,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.7673,"AHI":0.6587,"SGP":0},{"id":"hist_21_9_btc","sentiment_count":9,"timestamp_date":"2021-12-21T09:00:00.000Z","total":12,"twitter":0,"stocktwits":0,"reddit_comment":0,"reddit_post":0,"yahoo":12,"ticker":"btc","likes":0,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.4879,"AHI":0.4465,"SGP":1,"sentiment":16.9798},{"id":"hist_21_9_aapl","sentiment_count":9,"timestamp_date":"2021-12-21T09:00:00.000Z","total":10,"twitter":0,"stocktwits":8,"reddit_comment":0,"reddit_post":0,"yahoo":2,"ticker":"aapl","likes":10,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.3676,"AHI":0.4111,"SGP":0},{"id":"hist_21_9_lcid","sentiment_count":8,"timestamp_date":"2021-12-21T09:00:00.000Z","total":10,"twitter":0,"stocktwits":9,"reddit_comment":0,"reddit_post":0,"yahoo":1,"ticker":"lcid","likes":23,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.4674,"AHI":0.5561,"SGP":0},{"id":"hist_21_9_amd","sentiment_count":6,"timestamp_date":"2021-12-21T09:00:00.000Z","total":9,"twitter":0,"stocktwits":3,"reddit_comment":0,"reddit_post":0,"yahoo":6,"ticker":"amd","likes":3,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.4516,"AHI":0.5424,"SGP":0},{"id":"hist_21_9_nke","sentiment_count":4,"timestamp_date":"2021-12-21T09:00:00.000Z","total":6,"twitter":0,"stocktwits":4,"reddit_comment":0,"reddit_post":0,"yahoo":2,"ticker":"nke","likes":1,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":1.3136,"AHI":2.0879,"SGP":0},{"id":"hist_21_9_t","sentiment_count":4,"timestamp_date":"2021-12-21T09:00:00.000Z","total":6,"twitter":0,"stocktwits":3,"reddit_comment":0,"reddit_post":0,"yahoo":3,"ticker":"t","likes":0,"retweets":0,"user_followers":0,"user_tweet_count":0,"RHI":0.4844,"AHI":0.6866,"SGP":0}],"start":"2021-12-21T09:00:00.000Z","end":"2021-12-21T09:00:00.000Z","limit":"10"}'
headers:
Access-Control-Allow-Origin:
- '*'
Content-Length:
- '2986'
Content-Type:
- application/json; charset=utf-8
Date:
- Thu, 27 Jan 2022 17:41:19 GMT
Etag:
- W/"baa-MWXy163w4MAIoe1ZkpGOeHUUI0M"
X-Powered-By:
- Express
status:
code: 200
message: OK
version: 1

View File

@@ -0,0 +1,11 @@
,id,sentiment_count,timestamp_date,total,twitter,stocktwits,reddit_comment,reddit_post,yahoo,ticker,likes,retweets,user_followers,user_tweet_count,RHI,AHI,SGP,sentiment
0,hist_21_9_btc.x,22,2021-12-21T09:00:00.000Z,40,0,40,0,0,0,btc.x,25,0,0,0,3.4728,3.3006,0,
1,hist_21_9_amc,33,2021-12-21T09:00:00.000Z,40,0,40,0,0,0,amc,57,0,0,0,0.4931,0.5699,0,
2,hist_21_9_tsla,19,2021-12-21T09:00:00.000Z,33,0,31,0,0,2,tsla,30,0,0,0,0.4169,0.5384,1,7.8684
3,hist_21_9_mrna,11,2021-12-21T09:00:00.000Z,15,0,8,0,0,7,mrna,4,0,0,0,0.7673,0.6587,0,
4,hist_21_9_btc,9,2021-12-21T09:00:00.000Z,12,0,0,0,0,12,btc,0,0,0,0,0.4879,0.4465,1,16.9798
5,hist_21_9_aapl,9,2021-12-21T09:00:00.000Z,10,0,8,0,0,2,aapl,10,0,0,0,0.3676,0.4111,0,
6,hist_21_9_lcid,8,2021-12-21T09:00:00.000Z,10,0,9,0,0,1,lcid,23,0,0,0,0.4674,0.5561,0,
7,hist_21_9_amd,6,2021-12-21T09:00:00.000Z,9,0,3,0,0,6,amd,3,0,0,0,0.4516,0.5424,0,
8,hist_21_9_nke,4,2021-12-21T09:00:00.000Z,6,0,4,0,0,2,nke,1,0,0,0,1.3136,2.0879,0,
9,hist_21_9_t,4,2021-12-21T09:00:00.000Z,6,0,3,0,0,3,t,0,0,0,0,0.4844,0.6866,0,
1 id sentiment_count timestamp_date total twitter stocktwits reddit_comment reddit_post yahoo ticker likes retweets user_followers user_tweet_count RHI AHI SGP sentiment
2 0 hist_21_9_btc.x 22 2021-12-21T09:00:00.000Z 40 0 40 0 0 0 btc.x 25 0 0 0 3.4728 3.3006 0
3 1 hist_21_9_amc 33 2021-12-21T09:00:00.000Z 40 0 40 0 0 0 amc 57 0 0 0 0.4931 0.5699 0
4 2 hist_21_9_tsla 19 2021-12-21T09:00:00.000Z 33 0 31 0 0 2 tsla 30 0 0 0 0.4169 0.5384 1 7.8684
5 3 hist_21_9_mrna 11 2021-12-21T09:00:00.000Z 15 0 8 0 0 7 mrna 4 0 0 0 0.7673 0.6587 0
6 4 hist_21_9_btc 9 2021-12-21T09:00:00.000Z 12 0 0 0 0 12 btc 0 0 0 0 0.4879 0.4465 1 16.9798
7 5 hist_21_9_aapl 9 2021-12-21T09:00:00.000Z 10 0 8 0 0 2 aapl 10 0 0 0 0.3676 0.4111 0
8 6 hist_21_9_lcid 8 2021-12-21T09:00:00.000Z 10 0 9 0 0 1 lcid 23 0 0 0 0.4674 0.5561 0
9 7 hist_21_9_amd 6 2021-12-21T09:00:00.000Z 9 0 3 0 0 6 amd 3 0 0 0 0.4516 0.5424 0
10 8 hist_21_9_nke 4 2021-12-21T09:00:00.000Z 6 0 4 0 0 2 nke 1 0 0 0 1.3136 2.0879 0
11 9 hist_21_9_t 4 2021-12-21T09:00:00.000Z 6 0 3 0 0 3 t 0 0 0 0 0.4844 0.6866 0

View File

@@ -0,0 +1,47 @@
from datetime import datetime
import pytest
from gamestonk_terminal.common.behavioural_analysis import sentimentinvestor_model
@pytest.fixture(scope="module")
def vcr_config():
return {
"filter_query_parameters": [
("token", "MOCK_TOKEN"),
],
}
@pytest.mark.vcr
@pytest.mark.parametrize(
"ticker",
[
("BTC"),
("BTC-USD"),
],
)
def test_check_supported_ticker(ticker, recorder):
df = sentimentinvestor_model.check_supported_ticker(ticker)
recorder.capture(df)
@pytest.mark.vcr
@pytest.mark.parametrize(
"ticker, start, end, number",
[("AAPL", "2020-12-1", "2020-12-7", 100)],
)
def test_get_historical(ticker, start, end, number, recorder):
df = sentimentinvestor_model.get_historical(ticker, start, end, number)
recorder.capture(df)
@pytest.mark.vcr
@pytest.mark.parametrize(
"start, hour, number",
[(datetime(2021, 12, 21), 9, 10)],
)
def test_get_trending(start, hour, number, recorder):
df = sentimentinvestor_model.get_trending(start, hour, number)
recorder.capture(df)

View File

@@ -0,0 +1,42 @@
from datetime import datetime
import pytest
from gamestonk_terminal.common.behavioural_analysis import sentimentinvestor_view
@pytest.fixture(scope="module")
def vcr_config():
return {
"filter_query_parameters": [
("token", "MOCK_TOKEN"),
],
}
@pytest.mark.vcr
@pytest.mark.record_stdout
def test_display_historical(mocker):
mocker.patch.object(
target=sentimentinvestor_view.gtff, attribute="USE_ION", new=True
)
mocker.patch(
target="gamestonk_terminal.common.behavioural_analysis.sentimentinvestor_view.plt.ion"
)
mocker.patch(
target="gamestonk_terminal.common.behavioural_analysis.sentimentinvestor_view.plt.show"
)
sentimentinvestor_view.display_historical(
ticker="AAPL", start="2021-12-12", end="2021-12-15", export="", raw=True
)
@pytest.mark.vcr
@pytest.mark.record_stdout
def test_display_trending():
sentimentinvestor_view.display_trending(
start=datetime(2021, 12, 21),
hour=9,
number=10,
limit=10,
export="",
)

View File

@@ -0,0 +1,12 @@
twitter stocktwits yahoo likes RHI AHI
Time
2021-12-12 00:00 65 27 8 114 2.8149 3.0529
2021-12-12 01:00 50 8 2 4569 2.4082 2.6144
2021-12-12 02:00 47 20 2 115 2.2945 2.4960
2021-12-12 03:00 57 15 4 180 2.1122 2.3058
2021-12-12 04:00 47 10 3 46 2.0821 2.2691
2021-12-12 05:00 24 15 2 474 1.9097 2.0761
2021-12-12 06:00 16 8 2 31 1.7674 1.9161
2021-12-12 07:00 24 4 1 7 1.6779 1.8184
2021-12-12 08:00 34 2 1 22 1.5859 1.7262
2021-12-12 09:00 28 4 1 10 1.4951 1.6218

View File

@@ -0,0 +1,12 @@
total twitter stocktwits yahoo likes RHI AHI
ticker
BTC.X 40 0 40 0 25 3.4728 3.3006
AMC 40 0 40 0 57 0.4931 0.5699
TSLA 33 0 31 2 30 0.4169 0.5384
MRNA 15 0 8 7 4 0.7673 0.6587
BTC 12 0 0 12 0 0.4879 0.4465
AAPL 10 0 8 2 10 0.3676 0.4111
LCID 10 0 9 1 23 0.4674 0.5561
AMD 9 0 3 6 3 0.4516 0.5424
NKE 6 0 4 2 1 1.3136 2.0879
T 6 0 3 3 0 0.4844 0.6866

View File

@@ -421,6 +421,23 @@ def test_call_func_expect_queue(expected_queue, queue, func):
limit=10,
),
),
(
"call_trend",
[
"--start=2020-12-01",
"--hour=9",
"--export=csv",
"--number=20",
],
"sentimentinvestor_view.display_trending",
[],
dict(
start=datetime(2020, 12, 1),
hour=9,
export="csv",
number=20,
),
),
(
"call_popular",
["--num=1", "--limit=2", "--sub=MOCK_SUB"],
@@ -500,6 +517,7 @@ def test_call_func(
"call_headlines",
"call_stats",
"call_hist",
"call_trend",
"call_popular",
"call_getdd",
],

View File

@@ -28,4 +28,5 @@ Ticker: TSLA
queries top related queries with this stock
rise top rising related queries with stock
[SentimentInvestor]
trend most talked about tickers within the last hour
hist plot historical RHI and AHI data by hour

View File

@@ -1,40 +0,0 @@
```
usage: emerging [-l LIMIT] [-h]
```
The emerging command prints the stocks with highest Relative Hype Index right now.
RHI (Relative Hype Index)
---
RHI is a measure of whether people are talking about a stock more or less than
usual, calculated by dividing the mean AHI for the past day by the mean AHI for
for the past week for that stock.
===
Sentiment Investor analyzes data from four major social media platforms to
generate hourly metrics on over 2,000 stocks. Sentiment provides volume and
sentiment metrics powered by proprietary NLP models.
```
optional arguments:
-l LIMIT, --limit LIMIT
the maximum number of stocks to retrieve
-h, --help show this help message
```
```
(✨) (stocks)>(ba)> emerging
Rank Ticker RHI
------ -------- -----
1 FINV 6.432
2 GOVX 6.282
3 JZXN 5.368
4 GOGO 5.311
5 GWW 4.993
6 SHW 4.937
7 EYES 4.772
8 FSD 4.387
9 NUAN 4.019
10 JNUG 3.970
```

View File

@@ -0,0 +1,38 @@
```
usage: hist [-s START] [-e END] [-n NUMBER] [-h] [--export {csv,json,xlsx,png,jpg,pdf,svg}] [--raw] [-l LIMIT]
```
Plot historical sentiment data of RHI and AHI by hour. Source: [Sentiment Investor]
AHI (Absolute Hype Index)
---
AHI is a measure of how much people are talking about a stock on social media.
It is calculated by dividing the total number of mentions for the chosen stock on a social network by the mean number of mentions any stock receives on that social medium.
RHI (Relative Hype Index)
---
RHI is a measure of whether people are talking about a stock more or less than usual, calculated by dividing the mean AHI for the past day by the mean AHI for for the past week for that stock.
```
optional arguments:
-s START, --start START
The starting date (format YYYY-MM-DD) of the stock. Default: 7 days ago (default: 2022-01-19)
-e END, --end END The ending date (format YYYY-MM-DD) of the stock. Default: today (default: 2022-01-26)
-n NUMBER, --number NUMBER
Number of results returned from Sentiment Investor. Default: 100 (default: 100)
-h, --help show this help message (default: False)
--export {csv,json,xlsx,png,jpg,pdf,svg}
Export raw data into csv, json, xlsx and figure into png, jpg, pdf, svg (default: )
--raw Flag to display raw data (default: False)
-l LIMIT, --limit LIMIT
Number of entries to show in data. (default: 10)
```
**Plot**
![image](https://user-images.githubusercontent.com/40023817/151354884-e62ddfa9-3eed-44a2-91cb-4219b2fca245.png)
**Raw Data**
![image](https://user-images.githubusercontent.com/40023817/151355175-0a11f78d-5e62-451b-9dc6-37e04f084a6f.png)

View File

@@ -1,42 +0,0 @@
```
usage: historical [-s [{date,value}]] [-d [{asc,desc}]] [-h] [{sentiment,AHI,RHI,SGP}]
```
Sentiment Investor analyzes data from four major social media platforms to generate hourly metrics on over 2,000 stocks. Sentiment provides volume and sentiment metrics powered by proprietary NLP models.
The historical command plots the past week of data for a selected metric, one of:
AHI (Absolute Hype Index)
---
AHI is a measure of how much people are talking about a stock on social media.
It is calculated by dividing the total number of mentions for the chosen stock on a social network by the mean number of mentions any stock receives on that social medium.
RHI (Relative Hype Index)
---
RHI is a measure of whether people are talking about a stock more or less than usual, calculated by dividing the mean AHI for the past day by the mean AHI for for the past week for that stock.
Sentiment Score
---
Sentiment score is the percentage of people talking positively about the stock.
For each social network the number of positive posts/comments is divided by the total number of both positive and negative posts/comments.
SGP (Standard General Perception)
---
SGP is a measure of whether people are more or less positive about a stock than usual. It is calculated by averaging the past day of sentiment values and then dividing it by the average of the past week of sentiment values.
```
positional arguments:
{sentiment,AHI,RHI,SGP}
the metric to plot
optional arguments:
-s [{date,value}], --sort [{date,value}]
the parameter to sort output table by
-d [{asc,desc}], --direction [{asc,desc}]
the direction to sort the output table
-h, --help show this help message
```
<img width="1183" alt="Captura de ecrã 2021-08-06, às 22 00 22" src="https://user-images.githubusercontent.com/25267873/128570628-162d036e-37f8-48cc-bd8d-b5e79141db5d.png">
![sentiment_score](https://user-images.githubusercontent.com/25267873/128570642-b40df4d1-e95e-4e7e-846c-9f38d34c75cd.png)

View File

@@ -1,41 +0,0 @@
```
usage: metrics [-h]
```
Sentiment Investor analyzes data from four major social media platforms to
generate hourly metrics on over 2,000 stocks. Sentiment provides volume and
sentiment metrics powered by proprietary NLP models.
The metrics command prints the following realtime metrics:
AHI (Absolute Hype Index)
---
AHI is a measure of how much people are talking about a stock on social media.
It is calculated by dividing the total number of mentions for the chosen stock
on a social network by the mean number of mentions any stock receives on that
social medium.
RHI (Relative Hype Index)
---
RHI is a measure of whether people are talking about a stock more or less than
usual, calculated by dividing the mean AHI for the past day by the mean AHI for
for the past week for that stock.
Sentiment Score
---
Sentiment score is the percentage of people talking positively about the stock.
For each social network the number of positive posts/comments is divided by the
total number of both positive and negative posts/comments.
SGP (Standard General Perception)
---
SGP is a measure of whether people are more or less positive about a stock than
usual. It is calculated by averaging the past day of sentiment values and then
dividing it by the average of the past week of sentiment values.
```
optional arguments:
-h, --help show this help message
```
<img width="1183" alt="Captura de ecrã 2021-08-06, às 22 00 05" src="https://user-images.githubusercontent.com/25267873/128570641-29bab43b-b4bb-4c40-8467-ea366c903b7e.png">

View File

@@ -1,35 +0,0 @@
```
usage: popularsi [-l LIMIT] [-h]
```
The stocks with highest Average Hype Index right now.
AHI (Absolute Hype Index)
---
AHI is a measure of how much people are talking about a stock on social media.
It is calculated by dividing the total number of mentions for the chosen stock on a social network by the mean number of mentions any stock receives on that social medium.
Sentiment Investor analyzes data from four major social media platforms to generate hourly metrics on over 2,000 stocks. Sentiment provides volume and
sentiment metrics powered by proprietary NLP models.
```
optional arguments:
-l LIMIT, --limit LIMIT
the maximum number of stocks to retrieve
-h, --help show this help message
```
Sample output:
```
(✨) (stocks)>(ba)> popularsi
Rank Ticker AHI
------ -------- -----
1 AMC 4.514
2 TSLA 4.184
3 BTC 4.045
4 SPY 3.890
5 WISH 3.175
6 NAKD 2.220
7 SOFI 2.153
8 SAND 1.813
9 AMD 1.628
10 MMAT 1.617

View File

@@ -1,14 +0,0 @@
```
usage: social [-h]
```
Sentiment Investor analyzes data from four major social media platforms to generate hourly metrics on over 2,000 stocks. Sentiment provides volume and sentiment metrics powered by proprietary NLP models.
The social command prints the raw data for a given stock, including the number of mentions it has received on social media in the last hour and the sentiment score of those comments.
```
optional arguments:
-h, --help show this help message
```
<img width="1186" alt="Captura de ecrã 2021-08-06, às 22 00 15" src="https://user-images.githubusercontent.com/25267873/128570633-14bf8855-59ad-4ba2-a116-777b299c083c.png">

View File

@@ -0,0 +1,22 @@
```
usage: trend [-s START] [-hr HOUR] [-n NUMBER] [-h] [--export {csv,json,xlsx}] [-l LIMIT]
```
Show most talked about tickers within the last one hour. Source: [Sentiment Investor]
```
optional arguments:
-s START, --start START
The starting date (format YYYY-MM-DD). Default: Today (default: 2022-01-26)
-hr HOUR, --hour HOUR
Hour of the day in the 24-hour notation. Example: 14 (default: 0)
-n NUMBER, --number NUMBER
Number of results returned from Sentiment Investor. (default: 10)
-h, --help show this help message (default: False)
--export {csv,json,xlsx}
Export raw data into csv, json, xlsx (default: )
-l LIMIT, --limit LIMIT
Number of entries to show in data. (default: 10)
```
![image](https://user-images.githubusercontent.com/40023817/151354698-dc5eb7ab-46c4-4c98-882b-2c9607659b7d.png)

View File

@@ -544,16 +544,10 @@ main:
ref: "/common/behavioural_analysis/queries"
- name: rise
ref: "/common/behavioural_analysis/rise"
- name: popularsi
ref: "/common/behavioural_analysis/popularsi"
- name: emerging
ref: "/common/behavioural_analysis/emerging"
- name: metrics
ref: "/common/behavioural_analysis/metrics"
- name: social
ref: "/common/behavioural_analysis/social"
- name: historical
ref: "/common/behavioural_analysis/historical"
- name: hist
ref: "/common/behavioural_analysis/hist"
- name: trend
ref: "/common/behavioural_analysis/trend"
- name: quantitative analysis
ref: "/common/quantitative_analysis"
sub:
@@ -1255,4 +1249,4 @@ main:
- name: "shortdata"
ref: "jupyter/dashboards/shortdata"
- name: "reports"
ref: "/jupyter/reports"
ref: "/jupyter/reports"