autoscholar-cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +212 -0
- package/dist/agents/euler.js +261 -0
- package/dist/agents/fisher.js +348 -0
- package/dist/agents/gauss.js +177 -0
- package/dist/agents/governor.js +201 -0
- package/dist/agents/newton.js +207 -0
- package/dist/agents/turing.js +307 -0
- package/dist/cli/banner.js +136 -0
- package/dist/cli/configCommand.js +125 -0
- package/dist/cli/interactive.js +115 -0
- package/dist/cli/outputsCommand.js +191 -0
- package/dist/cli/resumeCommand.js +78 -0
- package/dist/cli/runCommand.js +91 -0
- package/dist/config/loader.js +154 -0
- package/dist/config/setup.js +179 -0
- package/dist/connectors/academic.js +307 -0
- package/dist/connectors/eodhd.js +90 -0
- package/dist/connectors/firecrawl.js +94 -0
- package/dist/connectors/fmp.js +115 -0
- package/dist/connectors/fred.js +82 -0
- package/dist/connectors/index.js +24 -0
- package/dist/connectors/websearch.js +117 -0
- package/dist/index.js +72 -0
- package/dist/latex/generator.js +413 -0
- package/dist/python/runner.js +141 -0
- package/dist/utils/llm.js +73 -0
- package/dist/utils/logger.js +83 -0
- package/dist/utils/project.js +100 -0
- package/package.json +63 -0
- package/python/analysis/garch_template.py +131 -0
- package/python/clients/eodhd_client.py +78 -0
- package/python/clients/fmp_client.py +64 -0
- package/python/clients/fred_client.py +57 -0
- package/python/clients/macro_clients.py +81 -0
- package/python/requirements.txt +23 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FMP (Financial Modeling Prep) Python Client
|
|
3
|
+
Pre-loaded in AutoScholar Python execution environment
|
|
4
|
+
"""
|
|
5
|
+
import os
|
|
6
|
+
import requests
|
|
7
|
+
import pandas as pd
|
|
8
|
+
|
|
9
|
+
class FMPClient:
|
|
10
|
+
BASE_URL = "https://financialmodelingprep.com/stable"
|
|
11
|
+
|
|
12
|
+
def __init__(self, api_key=None):
|
|
13
|
+
self.api_key = api_key or os.environ.get("FMP_API_KEY", "")
|
|
14
|
+
|
|
15
|
+
def _request(self, endpoint, params=None):
|
|
16
|
+
params = params or {}
|
|
17
|
+
params["apikey"] = self.api_key
|
|
18
|
+
resp = requests.get(f"{self.BASE_URL}/{endpoint}", params=params, timeout=60)
|
|
19
|
+
resp.raise_for_status()
|
|
20
|
+
return resp.json()
|
|
21
|
+
|
|
22
|
+
def get_quote(self, symbol):
|
|
23
|
+
return self._request("quote", {"symbol": symbol})
|
|
24
|
+
|
|
25
|
+
def get_historical_prices(self, symbol, from_date=None, to_date=None):
|
|
26
|
+
params = {"symbol": symbol}
|
|
27
|
+
if from_date: params["from"] = from_date
|
|
28
|
+
if to_date: params["to"] = to_date
|
|
29
|
+
data = self._request("historical-price-eod/full", params)
|
|
30
|
+
historical = data if isinstance(data, list) else data.get("historical", [])
|
|
31
|
+
return pd.DataFrame(historical)
|
|
32
|
+
|
|
33
|
+
def get_income_statement(self, symbol, period="annual", limit=10):
|
|
34
|
+
data = self._request("income-statement", {"symbol": symbol, "period": period, "limit": limit})
|
|
35
|
+
return pd.DataFrame(data if isinstance(data, list) else [])
|
|
36
|
+
|
|
37
|
+
def get_balance_sheet(self, symbol, period="annual", limit=10):
|
|
38
|
+
data = self._request("balance-sheet-statement", {"symbol": symbol, "period": period, "limit": limit})
|
|
39
|
+
return pd.DataFrame(data if isinstance(data, list) else [])
|
|
40
|
+
|
|
41
|
+
def get_cash_flow(self, symbol, period="annual", limit=10):
|
|
42
|
+
data = self._request("cash-flow-statement", {"symbol": symbol, "period": period, "limit": limit})
|
|
43
|
+
return pd.DataFrame(data if isinstance(data, list) else [])
|
|
44
|
+
|
|
45
|
+
def get_key_metrics(self, symbol, period="annual", limit=10):
|
|
46
|
+
data = self._request("key-metrics", {"symbol": symbol, "period": period, "limit": limit})
|
|
47
|
+
return pd.DataFrame(data if isinstance(data, list) else [])
|
|
48
|
+
|
|
49
|
+
def get_financial_ratios(self, symbol, period="annual", limit=10):
|
|
50
|
+
data = self._request("ratios", {"symbol": symbol, "period": period, "limit": limit})
|
|
51
|
+
return pd.DataFrame(data if isinstance(data, list) else [])
|
|
52
|
+
|
|
53
|
+
def get_company_profile(self, symbol):
|
|
54
|
+
return self._request("profile", {"symbol": symbol})
|
|
55
|
+
|
|
56
|
+
def get_stock_news(self, symbol, limit=50):
|
|
57
|
+
return self._request("stock-news", {"tickers": symbol, "limit": limit})
|
|
58
|
+
|
|
59
|
+
def search(self, query, limit=10):
|
|
60
|
+
return self._request("search", {"query": query, "limit": limit})
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# Pre-instantiate
|
|
64
|
+
fmp = FMPClient()
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""
|
|
2
|
+
FRED (Federal Reserve Economic Data) Python Client
|
|
3
|
+
Pre-loaded in AutoScholar Python execution environment
|
|
4
|
+
"""
|
|
5
|
+
import os
|
|
6
|
+
import requests
|
|
7
|
+
import pandas as pd
|
|
8
|
+
|
|
9
|
+
class FREDClient:
|
|
10
|
+
BASE_URL = "https://api.stlouisfed.org/fred"
|
|
11
|
+
|
|
12
|
+
def __init__(self, api_key=None):
|
|
13
|
+
self.api_key = api_key or os.environ.get("FRED_API_KEY", "")
|
|
14
|
+
|
|
15
|
+
def _request(self, endpoint, params=None):
|
|
16
|
+
params = params or {}
|
|
17
|
+
params["api_key"] = self.api_key
|
|
18
|
+
params["file_type"] = "json"
|
|
19
|
+
resp = requests.get(f"{self.BASE_URL}/{endpoint}", params=params, timeout=30)
|
|
20
|
+
resp.raise_for_status()
|
|
21
|
+
return resp.json()
|
|
22
|
+
|
|
23
|
+
def get_series_df(self, series_id, observation_start=None, observation_end=None,
|
|
24
|
+
units=None, frequency=None):
|
|
25
|
+
"""Get FRED series as a pandas DataFrame"""
|
|
26
|
+
params = {"series_id": series_id}
|
|
27
|
+
if observation_start: params["observation_start"] = observation_start
|
|
28
|
+
if observation_end: params["observation_end"] = observation_end
|
|
29
|
+
if units: params["units"] = units
|
|
30
|
+
if frequency: params["frequency"] = frequency
|
|
31
|
+
|
|
32
|
+
data = self._request("series/observations", params)
|
|
33
|
+
obs = data.get("observations", [])
|
|
34
|
+
df = pd.DataFrame(obs)
|
|
35
|
+
if len(df) > 0:
|
|
36
|
+
df["date"] = pd.to_datetime(df["date"])
|
|
37
|
+
df["value"] = pd.to_numeric(df["value"], errors="coerce")
|
|
38
|
+
df = df[["date", "value"]].dropna()
|
|
39
|
+
df.columns = ["date", series_id]
|
|
40
|
+
return df
|
|
41
|
+
|
|
42
|
+
def get_series(self, series_id):
|
|
43
|
+
"""Get series metadata"""
|
|
44
|
+
data = self._request("series", {"series_id": series_id})
|
|
45
|
+
return data.get("seriess", [{}])[0]
|
|
46
|
+
|
|
47
|
+
def search_series(self, search_text, limit=20):
|
|
48
|
+
"""Search for FRED series"""
|
|
49
|
+
data = self._request("series/search", {"search_text": search_text, "limit": limit})
|
|
50
|
+
return data.get("seriess", [])
|
|
51
|
+
|
|
52
|
+
def get_category(self, category_id):
|
|
53
|
+
return self._request("category", {"category_id": category_id})
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# Pre-instantiate
|
|
57
|
+
fred = FREDClient()
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""
|
|
2
|
+
World Bank, IMF, OECD Python Clients
|
|
3
|
+
Free APIs — no API key required
|
|
4
|
+
Pre-loaded in AutoScholar Python execution environment
|
|
5
|
+
"""
|
|
6
|
+
import requests
|
|
7
|
+
import pandas as pd
|
|
8
|
+
|
|
9
|
+
class WorldBankClient:
|
|
10
|
+
BASE_URL = "https://api.worldbank.org/v2"
|
|
11
|
+
|
|
12
|
+
def get_indicator(self, indicator, country="all", date_range="2000:2025", per_page=500):
|
|
13
|
+
"""Get World Bank indicator data as DataFrame"""
|
|
14
|
+
resp = requests.get(
|
|
15
|
+
f"{self.BASE_URL}/country/{country}/indicator/{indicator}",
|
|
16
|
+
params={"format": "json", "date": date_range, "per_page": per_page},
|
|
17
|
+
timeout=20
|
|
18
|
+
)
|
|
19
|
+
resp.raise_for_status()
|
|
20
|
+
data = resp.json()
|
|
21
|
+
if isinstance(data, list) and len(data) > 1:
|
|
22
|
+
records = data[1] or []
|
|
23
|
+
rows = [{
|
|
24
|
+
"country": r.get("country", {}).get("value", ""),
|
|
25
|
+
"country_code": r.get("countryiso3code", ""),
|
|
26
|
+
"date": r.get("date", ""),
|
|
27
|
+
"value": r.get("value"),
|
|
28
|
+
"indicator": r.get("indicator", {}).get("id", indicator)
|
|
29
|
+
} for r in records if r.get("value") is not None]
|
|
30
|
+
return pd.DataFrame(rows)
|
|
31
|
+
return pd.DataFrame()
|
|
32
|
+
|
|
33
|
+
def search_indicators(self, query, per_page=50):
|
|
34
|
+
resp = requests.get(
|
|
35
|
+
f"{self.BASE_URL}/indicator",
|
|
36
|
+
params={"format": "json", "per_page": per_page},
|
|
37
|
+
timeout=15
|
|
38
|
+
)
|
|
39
|
+
resp.raise_for_status()
|
|
40
|
+
data = resp.json()
|
|
41
|
+
if isinstance(data, list) and len(data) > 1:
|
|
42
|
+
return [i for i in data[1] if query.lower() in i.get("name", "").lower()]
|
|
43
|
+
return []
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class IMFClient:
|
|
47
|
+
BASE_URL = "http://dataservices.imf.org/REST/SDMX_JSON.svc"
|
|
48
|
+
|
|
49
|
+
def get_data(self, dataset, frequency, country, indicator, start=None, end=None):
|
|
50
|
+
"""Get IMF dataset"""
|
|
51
|
+
url = f"{self.BASE_URL}/CompactData/{dataset}/{frequency}.{country}.{indicator}"
|
|
52
|
+
params = {}
|
|
53
|
+
if start: params["startPeriod"] = start
|
|
54
|
+
if end: params["endPeriod"] = end
|
|
55
|
+
resp = requests.get(url, params=params, timeout=20)
|
|
56
|
+
resp.raise_for_status()
|
|
57
|
+
return resp.json()
|
|
58
|
+
|
|
59
|
+
def get_weo(self, country="US", subject="NGDP_RPCH"):
|
|
60
|
+
"""Get World Economic Outlook data"""
|
|
61
|
+
return self.get_data("WEO", "A", country, subject)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class OECDClient:
|
|
65
|
+
BASE_URL = "https://sdmx.oecd.org/public/rest"
|
|
66
|
+
|
|
67
|
+
def get_data(self, dataflow, key="all", start=None, end=None):
|
|
68
|
+
"""Get OECD dataflow"""
|
|
69
|
+
url = f"{self.BASE_URL}/data/{dataflow}/{key}"
|
|
70
|
+
params = {"format": "jsondata"}
|
|
71
|
+
if start: params["startPeriod"] = start
|
|
72
|
+
if end: params["endPeriod"] = end
|
|
73
|
+
resp = requests.get(url, params=params, timeout=20)
|
|
74
|
+
resp.raise_for_status()
|
|
75
|
+
return resp.json()
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# Pre-instantiate
|
|
79
|
+
wb = WorldBankClient()
|
|
80
|
+
imf = IMFClient()
|
|
81
|
+
oecd = OECDClient()
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Core (required)
|
|
2
|
+
pandas>=2.0
|
|
3
|
+
numpy>=1.24
|
|
4
|
+
scipy>=1.10
|
|
5
|
+
matplotlib>=3.7
|
|
6
|
+
seaborn>=0.12
|
|
7
|
+
scikit-learn>=1.3
|
|
8
|
+
statsmodels>=0.14
|
|
9
|
+
requests>=2.31
|
|
10
|
+
|
|
11
|
+
# Econometrics (recommended)
|
|
12
|
+
arch>=6.0
|
|
13
|
+
linearmodels>=5.0
|
|
14
|
+
|
|
15
|
+
# ML (optional)
|
|
16
|
+
xgboost>=2.0
|
|
17
|
+
lightgbm>=4.0
|
|
18
|
+
|
|
19
|
+
# Optimization (optional)
|
|
20
|
+
cvxpy>=1.4
|
|
21
|
+
|
|
22
|
+
# Other (optional)
|
|
23
|
+
fredapi>=0.5
|