Skip to content

Commit b373e36

Browse files
committed
chore: remove 3 unused QuantCore MCP tools
Removed fit_vol_surface, execute_paper_trade, and get_order_book_snapshot. None were wired into mcp_bridge or callable by any agent. execute_paper_trade is redundant (QuantPod has its own broker). The other two were dead stubs. 44 tools remain (down from 47).
1 parent add15e9 commit b373e36

File tree

2 files changed

+21
-270
lines changed

2 files changed

+21
-270
lines changed

packages/quantcore/mcp/server.py

Lines changed: 0 additions & 266 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,80 +1385,6 @@ async def compute_implied_vol(
13851385
return {"error": str(e)}
13861386

13871387

1388-
@mcp.tool()
1389-
async def fit_vol_surface(
1390-
symbol: str,
1391-
spot_price: float,
1392-
quotes: dict[str, Any],
1393-
risk_free_rate: float = 0.05,
1394-
beta: float = 1.0,
1395-
) -> dict[str, Any]:
1396-
"""
1397-
Fit SABR volatility surface to market IV quotes.
1398-
1399-
SABR model captures volatility smile/skew patterns for more realistic
1400-
option pricing and risk management.
1401-
1402-
Args:
1403-
symbol: Underlying symbol
1404-
spot_price: Current underlying price
1405-
quotes: Dictionary with 'strikes' and 'ivs' lists, plus 'dte'
1406-
Example: {"strikes": [95, 100, 105], "ivs": [0.25, 0.22, 0.24], "dte": 30}
1407-
risk_free_rate: Risk-free rate for forward calculation
1408-
beta: SABR beta parameter (0=normal, 1=lognormal, 0.5=CIR)
1409-
1410-
Returns:
1411-
Dictionary with SABR parameters, fit quality, and interpolated smile
1412-
"""
1413-
import pandas as pd
1414-
1415-
from quantcore.options.adapters.pysabr_adapter import (
1416-
fit_sabr_surface,
1417-
get_sabr_skew_metrics,
1418-
)
1419-
1420-
try:
1421-
# Validate inputs
1422-
strikes = quotes.get("strikes", [])
1423-
ivs = quotes.get("ivs", [])
1424-
dte = quotes.get("dte", 30)
1425-
1426-
if len(strikes) < 3 or len(strikes) != len(ivs):
1427-
return {"error": "Need at least 3 strike/IV pairs with matching lengths"}
1428-
1429-
# Create DataFrame
1430-
quotes_df = pd.DataFrame({"strike": strikes, "iv": ivs})
1431-
1432-
# Calculate forward price
1433-
time_to_expiry = dte / 365.0
1434-
forward = spot_price * np.exp(risk_free_rate * time_to_expiry)
1435-
1436-
# Fit SABR
1437-
result = fit_sabr_surface(
1438-
quotes=quotes_df,
1439-
forward=forward,
1440-
time_to_expiry=time_to_expiry,
1441-
beta=beta,
1442-
)
1443-
1444-
# Add skew metrics
1445-
skew_metrics = get_sabr_skew_metrics(
1446-
result["params"],
1447-
forward=forward,
1448-
time_to_expiry=time_to_expiry,
1449-
)
1450-
1451-
result["symbol"] = symbol
1452-
result["spot_price"] = spot_price
1453-
result["forward_price"] = forward
1454-
result["dte"] = dte
1455-
result["skew_metrics"] = skew_metrics
1456-
1457-
return result
1458-
1459-
except Exception as e:
1460-
return {"error": str(e)}
1461-
14621388

14631389
@mcp.tool()
14641390
async def analyze_option_structure(
@@ -4329,198 +4255,6 @@ async def get_event_calendar(
43294255
# =============================================================================
43304256

43314257

4332-
@mcp.tool()
4333-
async def execute_paper_trade(
4334-
symbol: str,
4335-
direction: str,
4336-
quantity: int,
4337-
structure_type: str = "single",
4338-
confidence: float = 0.5,
4339-
reason: str = "",
4340-
) -> dict[str, Any]:
4341-
"""
4342-
Execute a paper trade for testing strategies.
4343-
4344-
Simulates realistic order execution with:
4345-
- Slippage estimation
4346-
- Fill simulation
4347-
- Position tracking
4348-
4349-
Note: This is internal simulation. For broker paper trading,
4350-
use Alpaca MCP or eTrade sandbox.
4351-
4352-
Args:
4353-
symbol: Stock symbol
4354-
direction: "long" or "short"
4355-
quantity: Number of shares/contracts
4356-
structure_type: Trade type ("single", "vertical", "iron_condor")
4357-
confidence: Signal confidence (0-1)
4358-
reason: Trade rationale
4359-
4360-
Returns:
4361-
Order confirmation with simulated fill
4362-
"""
4363-
import uuid
4364-
from datetime import datetime
4365-
4366-
from quantcore.data.storage import DataStore
4367-
4368-
store = DataStore()
4369-
4370-
try:
4371-
# Get current price
4372-
df = store.load_ohlcv(symbol, Timeframe.D1)
4373-
4374-
if df.empty:
4375-
return {"error": f"No data for {symbol}"}
4376-
4377-
current_price = float(df["close"].iloc[-1])
4378-
4379-
# Simulate slippage (0.05% for liquid stocks)
4380-
slippage_pct = 0.0005
4381-
if direction.lower() == "long":
4382-
fill_price = current_price * (1 + slippage_pct)
4383-
else:
4384-
fill_price = current_price * (1 - slippage_pct)
4385-
4386-
# Generate order
4387-
order_id = str(uuid.uuid4())[:8]
4388-
timestamp = datetime.now()
4389-
4390-
order = {
4391-
"order_id": order_id,
4392-
"timestamp": timestamp.isoformat(),
4393-
"symbol": symbol,
4394-
"direction": direction,
4395-
"quantity": quantity,
4396-
"structure_type": structure_type,
4397-
"confidence": confidence,
4398-
"reason": reason,
4399-
"execution": {
4400-
"status": "FILLED",
4401-
"fill_price": round(fill_price, 2),
4402-
"fill_timestamp": timestamp.isoformat(),
4403-
"slippage_bps": round(slippage_pct * 10000, 1),
4404-
"notional_value": round(fill_price * quantity, 2),
4405-
},
4406-
"market_context": {
4407-
"current_price": current_price,
4408-
"bid_estimate": round(current_price * 0.9999, 2),
4409-
"ask_estimate": round(current_price * 1.0001, 2),
4410-
},
4411-
}
4412-
4413-
return {
4414-
"success": True,
4415-
"order": order,
4416-
"message": f"Paper trade executed: {direction} {quantity} {symbol} @ {fill_price:.2f}",
4417-
}
4418-
4419-
except Exception as e:
4420-
return {"error": str(e)}
4421-
finally:
4422-
store.close()
4423-
4424-
4425-
@mcp.tool()
4426-
async def get_order_book_snapshot(
4427-
symbol: str,
4428-
levels: int = 5,
4429-
) -> dict[str, Any]:
4430-
"""
4431-
Get simulated order book snapshot.
4432-
4433-
Returns bid/ask levels with depth for market microstructure analysis.
4434-
4435-
Note: This is a simulated order book based on historical data.
4436-
For live order book, use broker MCP.
4437-
4438-
Args:
4439-
symbol: Stock symbol
4440-
levels: Number of price levels to show
4441-
4442-
Returns:
4443-
Order book with bid/ask levels, spread, and depth
4444-
"""
4445-
from quantcore.data.storage import DataStore
4446-
4447-
store = DataStore()
4448-
4449-
try:
4450-
df = store.load_ohlcv(symbol, Timeframe.D1)
4451-
4452-
if df.empty:
4453-
return {"error": f"No data for {symbol}"}
4454-
4455-
# Get current price and volatility
4456-
current_price = float(df["close"].iloc[-1])
4457-
daily_range = float(df["high"].iloc[-1] - df["low"].iloc[-1])
4458-
avg_volume = float(df["volume"].tail(20).mean())
4459-
4460-
# Estimate spread from high-low
4461-
spread_estimate = daily_range / current_price * 0.1 # Simplified
4462-
half_spread = max(spread_estimate / 2, 0.0001)
4463-
4464-
# Generate synthetic order book
4465-
bids = []
4466-
asks = []
4467-
4468-
for i in range(levels):
4469-
# Bid side (below mid)
4470-
bid_price = current_price * (1 - half_spread - i * 0.0001)
4471-
bid_size = int(avg_volume / 100 * (levels - i) / levels)
4472-
bids.append(
4473-
{
4474-
"level": i + 1,
4475-
"price": round(bid_price, 2),
4476-
"size": bid_size,
4477-
"orders": max(1, bid_size // 100),
4478-
}
4479-
)
4480-
4481-
# Ask side (above mid)
4482-
ask_price = current_price * (1 + half_spread + i * 0.0001)
4483-
ask_size = int(avg_volume / 100 * (levels - i) / levels)
4484-
asks.append(
4485-
{
4486-
"level": i + 1,
4487-
"price": round(ask_price, 2),
4488-
"size": ask_size,
4489-
"orders": max(1, ask_size // 100),
4490-
}
4491-
)
4492-
4493-
best_bid = bids[0]["price"]
4494-
best_ask = asks[0]["price"]
4495-
spread = best_ask - best_bid
4496-
spread_bps = (spread / current_price) * 10000
4497-
4498-
return {
4499-
"symbol": symbol,
4500-
"timestamp": str(df.index[-1]),
4501-
"best_bid": best_bid,
4502-
"best_ask": best_ask,
4503-
"mid_price": round((best_bid + best_ask) / 2, 2),
4504-
"spread": round(spread, 4),
4505-
"spread_bps": round(spread_bps, 2),
4506-
"bids": bids,
4507-
"asks": asks,
4508-
"depth": {
4509-
"total_bid_size": sum(b["size"] for b in bids),
4510-
"total_ask_size": sum(a["size"] for a in asks),
4511-
"imbalance": round(
4512-
(sum(b["size"] for b in bids) - sum(a["size"] for a in asks))
4513-
/ (sum(b["size"] for b in bids) + sum(a["size"] for a in asks)),
4514-
3,
4515-
),
4516-
},
4517-
"note": "Simulated order book based on historical data. Use broker MCP for live data.",
4518-
}
4519-
4520-
except Exception as e:
4521-
return {"error": str(e)}
4522-
finally:
4523-
store.close()
45244258

45254259

45264260
# =============================================================================

uv.lock

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

0 commit comments

Comments
 (0)