Skip to content

Commit 44da7c8

Browse files
committed
Test ai
1 parent 24048e2 commit 44da7c8

7 files changed

Lines changed: 519 additions & 31 deletions

File tree

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Documentation = "https://quantmind.github.io/quantflow/"
2222

2323
[project.optional-dependencies]
2424
ai = [
25+
"asciichartpy>=1.5.25",
26+
"ccy[holidays]>=1.7.1",
2527
"google-genai>=1.61.0",
2628
"mcp>=1.26.0",
2729
"openai>=2.16.0",

quantflow/ai/tools/base.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
from dataclasses import dataclass, field
2-
from io import StringIO
32
from pathlib import Path
43

5-
import pandas as pd
6-
from ccy.cli.console import df_to_rich
74
from mcp.server.fastmcp.exceptions import ToolError
8-
from rich.console import Console
95

106
from quantflow.data.fmp import FMP
117
from quantflow.data.fred import Fred
@@ -35,10 +31,3 @@ def fred(self) -> Fred:
3531
" Please add it using the vault_add tool."
3632
)
3733
return Fred(key=key)
38-
39-
def rich(self, df: pd.DataFrame) -> str:
40-
table = df_to_rich(df)
41-
buf = StringIO()
42-
console = Console(file=buf, no_color=True)
43-
console.print(table)
44-
return buf.getvalue()

quantflow/ai/tools/crypto.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ async def crypto_historical_volatility(currency: str) -> str:
3737
df = await client.get_volatility(currency)
3838
if df.empty:
3939
return f"No volatility data for {currency}"
40-
return f"Historical volatility for {currency}:\n{df.to_string(index=False)}"
40+
return df.to_csv(index=False)
4141

4242
@mcp.tool()
4343
async def crypto_term_structure(currency: str) -> str:
@@ -52,7 +52,7 @@ async def crypto_term_structure(currency: str) -> str:
5252
loader = await client.volatility_surface_loader(currency)
5353
vs: VolSurface = loader.surface()
5454
ts = vs.term_structure().round({"ttm": 4})
55-
return f"Term structure for {currency}:\n{ts.to_string(index=False)}"
55+
return ts.to_csv(index=False)
5656

5757
@mcp.tool()
5858
async def crypto_implied_volatility(currency: str, maturity_index: int = -1) -> str:
@@ -71,7 +71,7 @@ async def crypto_implied_volatility(currency: str, maturity_index: int = -1) ->
7171
vs.bs(index=index)
7272
df = vs.options_df(index=index)
7373
df["implied_vol"] = df["implied_vol"].map("{:.2%}".format)
74-
return f"Implied volatility for {currency}:\n{df.to_string(index=False)}"
74+
return df.to_csv(index=False)
7575

7676
@mcp.tool()
7777
async def crypto_prices(symbol: str, frequency: str = "") -> str:
@@ -87,4 +87,4 @@ async def crypto_prices(symbol: str, frequency: str = "") -> str:
8787
if df.empty:
8888
return f"No price data for {symbol}"
8989
df = df[["date", "open", "high", "low", "close", "volume"]].sort_values("date")
90-
return f"Prices for {symbol}:\n{df.tail(50).to_string(index=False)}"
90+
return df.tail(50).to_csv(index=False)

quantflow/ai/tools/fred.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ async def fred_subcategories(category_id: str | None = None) -> str:
2626
import pandas as pd
2727

2828
df = pd.DataFrame(cats, columns=["id", "name"])
29-
return f"FRED categories:\n{df.to_string(index=False)}"
29+
return df.to_csv(index=False)
3030

3131
@mcp.tool()
3232
async def fred_series(category_id: str) -> str:
@@ -55,7 +55,7 @@ async def fred_series(category_id: str) -> str:
5555
"observation_end",
5656
],
5757
).sort_values("popularity", ascending=False)
58-
return f"FRED series for category {category_id}:\n{df.to_string(index=False)}"
58+
return df.to_csv(index=False)
5959

6060
@mcp.tool()
6161
async def fred_data(
@@ -79,4 +79,4 @@ async def fred_data(
7979
sort_order="desc",
8080
)
8181
)
82-
return f"FRED data for {series_id}:\n{df.to_string(index=False)}"
82+
return df.to_csv(index=False)

quantflow/ai/tools/stocks.py

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
"""Stocks tools for the quantflow MCP server."""
22

33
from datetime import timedelta
4+
from typing import cast
45

56
import pandas as pd
7+
from ccy import period as to_period
8+
from ccy.tradingcentres import prevbizday
9+
from fluid.utils.data import compact_dict
610
from mcp.server.fastmcp import FastMCP
711

812
from quantflow.utils.dates import utcnow
@@ -17,7 +21,7 @@ async def stock_indices() -> str:
1721
"""List available stock market indices."""
1822
async with tool.fmp() as client:
1923
data = await client.indices()
20-
return tool.rich(pd.DataFrame(data))
24+
return pd.DataFrame(data).to_csv(index=False)
2125

2226
@mcp.tool()
2327
async def stock_search(query: str) -> str:
@@ -30,7 +34,7 @@ async def stock_search(query: str) -> str:
3034
data = await client.search(query)
3135

3236
df = pd.DataFrame(data, columns=["symbol", "name", "currency", "stockExchange"])
33-
return f"Search results for '{query}':\n{df.to_string(index=False)}"
37+
return df.to_csv(index=False)
3438

3539
@mcp.tool()
3640
async def stock_profile(symbol: str) -> str:
@@ -62,7 +66,7 @@ async def stock_prices(symbol: str, frequency: str = "") -> str:
6266
if df.empty:
6367
return f"No price data for {symbol}"
6468
df = df[["date", "open", "high", "low", "close", "volume"]].sort_values("date")
65-
return f"Prices for {symbol}:\n{df.tail(50).to_string(index=False)}"
69+
return df.to_csv(index=False)
6670

6771
@mcp.tool()
6872
async def sector_performance(period: str = "1d") -> str:
@@ -71,10 +75,6 @@ async def sector_performance(period: str = "1d") -> str:
7175
Args:
7276
period: Time period - 1d, 1w, 1m, 3m, 6m, 1y (default: 1d)
7377
"""
74-
from ccy import period as to_period
75-
from ccy.tradingcentres import prevbizday
76-
from fluid.utils.data import compact_dict
77-
7878
async with tool.fmp() as client:
7979
to_date = utcnow().date()
8080
if period != "1d":
@@ -89,16 +89,11 @@ async def sector_performance(period: str = "1d") -> str:
8989
pe = await client.sector_pe(
9090
params=compact_dict(date=prevbizday(to_date, 0).isoformat())
9191
)
92-
93-
from typing import cast
94-
95-
import pandas as pd
96-
9792
spd = cast(dict, sp)
9893
pes = {k["sector"]: round(float(k["pe"]), 3) for k in pe if k["sector"] in spd}
9994
rows = [
10095
{"sector": k, "performance": float(v), "pe": pes.get(k, float("nan"))}
10196
for k, v in spd.items()
10297
]
10398
df = pd.DataFrame(rows).sort_values("performance", ascending=False)
104-
return f"Sector performance ({period}):\n{df.to_string(index=False)}"
99+
return df.to_csv(index=False)

0 commit comments

Comments
 (0)