Skip to content

Commit 6ed4cfd

Browse files
author
Andrew Brookins
committed
Now do bitcoin sentiment analysis
1 parent 739c843 commit 6ed4cfd

File tree

8 files changed

+117
-200
lines changed

8 files changed

+117
-200
lines changed

app/main.py

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1+
import functools
12
import json
23
import logging
3-
import socket
4+
from datetime import datetime
45

56
import aioredis
6-
from aiotestspeed.aio import Speedtest
7+
import requests
8+
from aioredis.exceptions import ResponseError
79
from fastapi import FastAPI
810
from pydantic import BaseSettings
911

1012

11-
SPEEDTEST_KEY = 'speedtest:{ip}'
13+
TIMESERIES_KEY = 'is-bitcoin-lit:sentiment:mean:{time}'
14+
SUMMARY_KEY = 'is-bitcoin-lit:summary:hourly:{time}'
15+
SENTIMENT_API_URL = 'https://api.senticrypt.com/v1/history/bitcoin-{time}.json'
16+
TIME_FORMAT_STRING = '%Y-%m-%d_%H'
1217

1318

1419
class Config(BaseSettings):
@@ -18,34 +23,45 @@ class Config(BaseSettings):
1823
logger = logging.getLogger(__name__)
1924
config = Config()
2025
app = FastAPI(title='FastAPI Redis Tutorial')
21-
redis = aioredis.from_url(config.redis_url)
26+
redis = aioredis.from_url(config.redis_url, decode_responses=True)
2227

2328

24-
def get_cache_key():
25-
hostname = socket.gethostname()
26-
ip = socket.gethostbyname(hostname)
27-
return SPEEDTEST_KEY.format(ip=ip)
29+
def make_summary(data):
30+
return {
31+
'time': datetime.now().timestamp(),
32+
'mean_sentiment': sum(d['mean'] for d in data) / len(data),
33+
}
2834

2935

30-
@app.get('/speedtest')
31-
async def speedtest():
32-
logger.debug('Running speedtest')
33-
key = get_cache_key()
36+
@app.get('/is-bitcoin-lit')
37+
async def bitcoin():
38+
sentiment_time = datetime.now().strftime(TIME_FORMAT_STRING)
39+
summary_key = SUMMARY_KEY.format(time=sentiment_time)
40+
ts_key = TIMESERIES_KEY.format(time=sentiment_time)
41+
url = SENTIMENT_API_URL.format(time=sentiment_time)
3442

35-
found = await redis.get(key)
36-
if found:
37-
data = json.loads(found)
38-
else:
39-
s: Speedtest = await Speedtest()
40-
await s.get_best_server()
41-
await s.download()
42-
await s.upload()
43+
summary = await redis.hgetall(summary_key)
4344

44-
data = {
45-
'ping_ms': s.results.ping,
46-
'download_mbps': s.results.download / 1000.0 / 1000.0 / 1,
47-
'upload_mbps': s.results.upload / 1000.0 / 1000.0 / 1,
48-
}
49-
await redis.set(key, json.dumps(data), ex=30)
45+
if not summary:
46+
# TODO: Only add timeseries data that we don't already have -- how?
47+
data = requests.get(url).json()
48+
summary = make_summary(data)
49+
await redis.hset(summary_key, mapping=summary)
50+
await redis.expire(summary_key, 60)
51+
partial = functools.partial(redis.execute_command, 'TS.MADD', ts_key)
52+
for datapoint in data:
53+
partial = functools.partial(
54+
partial, datapoint['timestamp'], datapoint['mean'],
55+
)
56+
await partial()
5057

51-
return data
58+
return summary
59+
60+
61+
@app.on_event('startup')
62+
async def startup_event():
63+
try:
64+
redis.execute_command('TS.CREATE', TIMESERIES_KEY)
65+
except ResponseError:
66+
# Time series already exists
67+
pass

docker-compose.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
version: '3.8'
22
services:
33
redis:
4-
image: redis
4+
image: redislabs/redismod
55
ports:
66
- "16379:6379"
77
volumes:
88
- $PWD/data:/data
9-
command: redis-server --appendonly yes --aof-use-rdb-preamble yes --dir /data
9+
command: --appendonly yes --aof-use-rdb-preamble yes --dir /data --loadmodule /usr/lib/redis/modules/redistimeseries.so
1010

1111
app:
1212
restart: always

poetry.lock

Lines changed: 20 additions & 41 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,22 @@
22
name = "fastapi-starter-template"
33
version = "0.1.0"
44
description = ""
5-
authors = ["Zidane Wright <zidanewright@outlook.com>"]
5+
authors = ["Andrew Brookins <andrew.brookins@redislabs.com>"]
66

77
[tool.poetry.dependencies]
88
python = "^3.8"
99
aioredis = "2.0.0a1"
1010
fastapi = "^0.61.0"
1111
uvicorn = "^0.11.8"
1212
requests = "^2.24.0"
13-
aiotestspeed = {git = "https://github.com/abrookins/aiotestspeed", rev = "master"}
14-
httpx = "^0.18.1"
1513

1614
[tool.poetry.dev-dependencies]
1715
pytest = "^5.2"
1816
pre-commit = "^2.6.0"
1917
tox = "^3.19.0"
2018
pytest-cov = "^2.10.1"
2119
pytest-asyncio = "^0.15.1"
20+
httpx = "^0.18.1"
2221

2322
[build-system]
2423
requires = ["poetry>=0.12"]

0 commit comments

Comments
 (0)