132 lines
4.0 KiB
Python
Executable File
132 lines
4.0 KiB
Python
Executable File
import pandas as pd
|
|
from datetime import datetime
|
|
import numpy as np
|
|
import ujson
|
|
import asyncio
|
|
import sqlite3
|
|
import os
|
|
from tqdm import tqdm
|
|
|
|
async def save_json(symbol, data):
|
|
os.makedirs("json/var", exist_ok=True) # Ensure directory exists
|
|
with open(f"json/var/{symbol}.json", 'w') as file:
|
|
ujson.dump(data, file)
|
|
|
|
# Define risk rating scale
|
|
def assign_risk_rating(var):
|
|
if var >= 25:
|
|
return 1
|
|
elif var >= 20:
|
|
return 2
|
|
elif var >= 15:
|
|
return 3
|
|
elif var >= 10:
|
|
return 4
|
|
elif var >= 8:
|
|
return 5
|
|
elif var >= 6:
|
|
return 6
|
|
elif var >= 4:
|
|
return 7
|
|
elif var >= 2:
|
|
return 8
|
|
elif var >= 1:
|
|
return 9
|
|
else:
|
|
return 10
|
|
|
|
def compute_var(df):
|
|
# Calculate daily returns
|
|
df['Returns'] = df['close'].pct_change()
|
|
df = df.dropna()
|
|
# Calculate VaR at 95% confidence level
|
|
confidence_level = 0.95
|
|
var = np.percentile(df['Returns'], 100 * (1 - confidence_level))
|
|
var_N_days = round(var * np.sqrt(len(df)) * 100, 2) # N days: the length of df represents the N days
|
|
|
|
if var_N_days <= -100:
|
|
var_N_days = -99
|
|
|
|
return var_N_days # Positive value represents a loss
|
|
|
|
async def run():
|
|
start_date = "2015-01-01"
|
|
end_date = datetime.today().strftime("%Y-%m-%d")
|
|
|
|
con = sqlite3.connect('stocks.db')
|
|
etf_con = sqlite3.connect('etf.db')
|
|
crypto_con = sqlite3.connect('crypto.db')
|
|
|
|
cursor = con.cursor()
|
|
cursor.execute("PRAGMA journal_mode = wal")
|
|
cursor.execute("SELECT DISTINCT symbol FROM stocks")
|
|
stocks_symbols = [row[0] for row in cursor.fetchall()]
|
|
|
|
etf_cursor = etf_con.cursor()
|
|
etf_cursor.execute("PRAGMA journal_mode = wal")
|
|
etf_cursor.execute("SELECT DISTINCT symbol FROM etfs")
|
|
etf_symbols = [row[0] for row in etf_cursor.fetchall()]
|
|
|
|
crypto_cursor = crypto_con.cursor()
|
|
crypto_cursor.execute("PRAGMA journal_mode = wal")
|
|
crypto_cursor.execute("SELECT DISTINCT symbol FROM cryptos")
|
|
crypto_symbols = [row[0] for row in crypto_cursor.fetchall()]
|
|
|
|
total_symbols = stocks_symbols + etf_symbols + crypto_symbols
|
|
|
|
for symbol in tqdm(total_symbols):
|
|
try:
|
|
if symbol in etf_symbols:
|
|
query_con = etf_con
|
|
elif symbol in crypto_symbols:
|
|
query_con = crypto_con
|
|
elif symbol in stocks_symbols:
|
|
query_con = con
|
|
else:
|
|
continue
|
|
|
|
query_template = """
|
|
SELECT
|
|
date, open, high, low, close, volume
|
|
FROM
|
|
"{symbol}"
|
|
WHERE
|
|
date BETWEEN ? AND ?
|
|
"""
|
|
query = query_template.format(symbol=symbol)
|
|
df = pd.read_sql_query(query, query_con, params=(start_date, end_date))
|
|
|
|
# Convert date to datetime
|
|
df['date'] = pd.to_datetime(df['date'])
|
|
|
|
# Group by year and month
|
|
monthly_groups = df.groupby(df['date'].dt.to_period('M'))
|
|
history = []
|
|
|
|
for period, group in monthly_groups:
|
|
if len(group) >=19: # Check if the month has at least 19 data points
|
|
var_data = compute_var(group)
|
|
history.append({'date': str(period), 'var': var_data})
|
|
|
|
risk_rating = assign_risk_rating(abs(history[-1]['var']))
|
|
outlook = 'Neutral'
|
|
if risk_rating < 5:
|
|
outlook = 'Risky'
|
|
elif risk_rating > 5:
|
|
outlook = 'Minimum Risk'
|
|
res = {'rating': risk_rating, 'history': history, 'outlook': outlook}
|
|
|
|
await save_json(symbol, res)
|
|
|
|
except Exception as e:
|
|
print(f"Error processing {symbol}: {e}")
|
|
|
|
con.close()
|
|
etf_con.close()
|
|
crypto_con.close()
|
|
|
|
try:
|
|
asyncio.run(run())
|
|
except Exception as e:
|
|
print(e)
|