You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

118 lines
3.1 KiB

""" Web service app
"""
import json
from datetime import datetime, timedelta
import pytz
from clickhouse_driver import Client
from flask import Flask
app = Flask(__name__)
with open("config.json", "r") as fp:
config = json.load(fp)
client = Client(**config["clickhouse"])
@app.route("/instruments")
def get_instruments():
""" Get list of instruments with the latest quote
"""
data = client.execute("""
SELECT
isin,
description,
last_value
FROM (
SELECT
isin,
argMax(description, added_on) AS description,
argMax(status, added_on) AS status
FROM symbols FINAL
GROUP BY isin
) ndsymbols
LEFT JOIN (
SELECT
isin,
toString(argMax(last_value, minute_start)) AS last_value
FROM (
SELECT
isin, minute_start,
maxMerge(last_record_timestamp) AS last_record_timestamp,
argMinMerge(first_value)/1000000.0 AS first_value,
argMaxMerge(last_value)/1000000.0 AS last_value,
minMerge(min_value)/1000000.0 AS min_value,
maxMerge(max_value)/1000000.0 AS max_value
FROM traderepublic.quotes
GROUP BY (isin, minute_start)
) aquotes
GROUP BY isin
) vals
ON vals.isin=ndsymbols.isin
WHERE ndsymbols.status=1
ORDER BY isin
""")
response_rows = []
for row in data:
response_rows.append({
"isin":
row[0],
"description":
row[1],
"last_value":
float(row[2]) if row[2] != "" else None
})
return {"data": response_rows}
@app.route("/last30m/<string:isin>")
def get_last30m(isin: str):
""" Get last 30 minutes of candlestick data with 1 minute resolution
"""
time30m = datetime.utcnow() - timedelta(minutes=30)
time30m = time30m.replace(second=0, microsecond=0)
data = client.execute(
"""
SELECT
minute_start,
first_value,
last_value,
min_value,
max_value
FROM (
SELECT
isin, minute_start,
argMinMerge(first_value)/1000000.0 AS first_value,
argMaxMerge(last_value)/1000000.0 AS last_value,
minMerge(min_value)/1000000.0 AS min_value,
maxMerge(max_value)/1000000.0 AS max_value
FROM traderepublic.quotes
WHERE isin=%(isin)s AND minute_start > %(time30m)s
GROUP BY (isin, minute_start)
ORDER BY minute_start
) aquotes
""", {
"isin": isin,
"time30m": time30m,
})
if not data:
return {}
result = {"isin": isin, "candlesticks": []}
candlesticks = result["candlesticks"]
timezone = pytz.timezone("UTC")
for row in data:
time_start = row[0].replace(tzinfo=timezone)
candlesticks.append({
"time_start":
time_start.strftime("%Y-%m-%d %H:%M:%S%z"),
"open":
row[1],
"close":
row[2],
"min":
row[3],
"max":
row[4]
})
return result