Compare commits
10 Commits
c749c42bc4
...
823b8b4297
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
823b8b4297 | ||
|
|
16ee24d45f | ||
|
|
c9a1775bb5 | ||
|
|
b072878ca5 | ||
|
|
69d7c1f572 | ||
|
|
f3c3ab5e2d | ||
|
|
25839d0b19 | ||
|
|
1ac1e245d6 | ||
|
|
d231fcce67 | ||
|
|
8faf5ecca6 |
174
README.md
Normal file
174
README.md
Normal file
@@ -0,0 +1,174 @@
|
||||
# Gridbot MCP Server
|
||||
|
||||
Exposes eToroGridbot trading bot operations via Model Context Protocol. Provides monitoring, trading, and analysis tools for the automated trading system.
|
||||
|
||||
## Requirements
|
||||
|
||||
- VPN connection to services network: `vpn-connect`
|
||||
- Gridbot conductor running on services VM (http://services:8000)
|
||||
- Python 3.10+ with uv for development
|
||||
|
||||
## Configuration
|
||||
|
||||
Add to `~/.claude/settings.json` under `mcpServers`:
|
||||
|
||||
```json
|
||||
{
|
||||
"gridbot": {
|
||||
"command": "/path/to/gridbot-mcp/.venv/bin/python",
|
||||
"args": ["-m", "src.server"],
|
||||
"cwd": "/path/to/gridbot-mcp",
|
||||
"env": {
|
||||
"GRIDBOT_API_URL": "http://services:8000"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Tools
|
||||
|
||||
### Monitoring
|
||||
- `health` - Check conductor health, queue size, capacity
|
||||
- `emergency_status` - Emergency stop status, circuit breaker, drawdown limits
|
||||
- `market_hours` - Market hours for all exchanges (NYSE, NASDAQ, CRYPTO, FOREX)
|
||||
- `positions` - All portfolio positions with real-time P/L
|
||||
- `pending_orders` - Pending limit orders with amounts, rates, TP/SL
|
||||
- `risk_score` - Portfolio risk score and components
|
||||
- `dashboard` - Full dashboard (positions, orders, analytics)
|
||||
- `session_start` - Comprehensive session summary (replaces 5-6 individual calls)
|
||||
|
||||
### Market Data
|
||||
- `vix` - VIX volatility index and interpretation
|
||||
- `crypto_fear_greed` - Crypto Fear & Greed index with trading guidance
|
||||
|
||||
### Trading Operations
|
||||
- `validate_trade` - Validate trade before execution (checks risk limits)
|
||||
- `create_order` - Create BUY/SELL order with full validation
|
||||
- `close_position` - Close existing position (full or partial)
|
||||
- `close_positions_by_filter` - Close multiple positions (e.g., all crypto, all losers)
|
||||
- `cancel_order` - Cancel single pending order
|
||||
- `cancel_orders_bulk` - Cancel multiple orders at once
|
||||
- `find_duplicate_orders` - Find duplicate pending orders
|
||||
- `emergency_stop` - HALT all trading (emergency use only)
|
||||
- `emergency_reset` - Resume trading after emergency stop
|
||||
- `cleanup_stale_orders` - Cleanup stale/expired orders
|
||||
|
||||
### Signal Intents (Limit Orders)
|
||||
- `intents` - List signal intents (pending orders awaiting trigger)
|
||||
- `intents_pending` - List pending intents only
|
||||
- `intents_executed` - List executed intents
|
||||
- `intents_stats` - Intent statistics (pending/executed/expired)
|
||||
- `create_intent` - Create signal intent (limit order)
|
||||
- `create_intents_bulk` - Create multiple intents at once
|
||||
- `cancel_intent` - Cancel pending intent
|
||||
|
||||
### Scale-Out (Profit Taking)
|
||||
- `scale_out_status` - Scale-out monitor status
|
||||
- `scale_out_pending` - Positions pending scale-out
|
||||
- `scale_out_stats` - Scale-out statistics (P/L locked)
|
||||
- `scale_out_trigger` - Manually trigger scale-out for position
|
||||
- `scale_out_adjust_threshold` - Override threshold for symbol
|
||||
- `scale_out_get_overrides` - Get all threshold overrides
|
||||
- `scale_out_delete_override` - Delete threshold override
|
||||
- `scale_out_set_dry_run` - Enable/disable dry-run mode
|
||||
|
||||
### Analysis
|
||||
- `trades` - Recent trades with P/L details
|
||||
- `analytics` - Trading analytics (win rate, Sharpe ratio)
|
||||
- `expectancy` - Trading expectancy metrics by symbol
|
||||
- `profitable_symbols` - Profitable symbols ranked by expectancy
|
||||
- `correlations` - Top correlated asset pairs
|
||||
- `signal_quality` - Signal acceptance rate, rejection reasons
|
||||
- `trend_alerts` - Active trend change alerts
|
||||
- `statistics` - Trading statistics summary
|
||||
- `support_resistance` - Support/resistance levels for symbol
|
||||
|
||||
### System
|
||||
- `queue_status` - Signal processing queue status
|
||||
- `bot_health` - Trading bot health (Freqtrade, Hummingbot)
|
||||
- `stale_bots` - Bots with no recent signals
|
||||
- `monitoring_stats` - System monitoring stats
|
||||
- `env_health` - Environment health (API keys, credentials)
|
||||
- `candle_freshness` - Candle data staleness check
|
||||
- `rate_limiter` - Rate limiter statistics
|
||||
- `portfolio_allocation` - Portfolio allocation breakdown
|
||||
- `market_closure_context` - Market closure context
|
||||
- `container_logs` - Get container logs with grep filter
|
||||
- `container_restart` - Restart a container
|
||||
- `pi_consensus_query` - Get PI consensus data for symbol
|
||||
- `pi_consensus_top` - Get top PI consensus opportunities
|
||||
- `pi_scan_trigger` - Trigger manual PI portfolio scan
|
||||
|
||||
## CLI Wrapper
|
||||
|
||||
A command-line wrapper is available at `~/Development/Infrastructure/AgilitonScripts/bin/gridbot`:
|
||||
|
||||
```bash
|
||||
# Session start (recommended)
|
||||
gridbot session-start # Comprehensive session summary
|
||||
|
||||
# Monitoring
|
||||
gridbot health # Check system health
|
||||
gridbot positions # List all positions
|
||||
gridbot pending # Show pending orders
|
||||
gridbot risk # Portfolio risk score
|
||||
gridbot dashboard # Full dashboard
|
||||
|
||||
# Market data
|
||||
gridbot market-hours # Market hours
|
||||
gridbot vix # Volatility index
|
||||
gridbot crypto-fear-greed # Fear & Greed index
|
||||
|
||||
# Trading validation
|
||||
gridbot validate BTC BUY 100 # Validate $100 BTC buy
|
||||
|
||||
# Analysis
|
||||
gridbot trades # Recent trades
|
||||
gridbot analytics # Trading performance
|
||||
gridbot expectancy # Expectancy by symbol
|
||||
gridbot profitable # Best performing symbols
|
||||
gridbot correlations # Correlated pairs
|
||||
gridbot statistics # Trading statistics
|
||||
|
||||
# System
|
||||
gridbot queue # Queue status
|
||||
gridbot bot-health # Bot health
|
||||
gridbot monitoring # System stats
|
||||
gridbot env-health # Environment check
|
||||
gridbot candle-freshness # Data freshness
|
||||
|
||||
# Emergency
|
||||
gridbot emergency-stop "reason" # HALT trading
|
||||
gridbot emergency-reset # Resume trading
|
||||
gridbot cleanup-orders # Cleanup stale orders
|
||||
```
|
||||
|
||||
The CLI wrapper provides terminal access to all MCP tools without requiring Claude Code.
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
# Setup
|
||||
uv venv
|
||||
source .venv/bin/activate
|
||||
uv pip install -r requirements.txt
|
||||
|
||||
# Run
|
||||
python -m src.server
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
- **Conductor API**: Trading bot coordinator (services:8000)
|
||||
- **Position Management**: Real-time P/L tracking with BotPriceProvider
|
||||
- **Risk Management**: Portfolio risk scoring, circuit breakers
|
||||
- **Signal Intents**: Limit orders with trigger price
|
||||
- **Scale-Out**: Automated profit-taking at thresholds
|
||||
- **PI Consensus**: Portfolio Intelligence integration
|
||||
- **Market Hours**: Dynamic allocation based on market status
|
||||
|
||||
## Related
|
||||
|
||||
- Conductor: `/Users/christian.gick/Development/Apps/eToroGridbot`
|
||||
- Dashboard: http://services:5555
|
||||
- Documentation: ClaudeFramework/docs/gridbot/
|
||||
BIN
src/__pycache__/__init__.cpython-314.pyc
Normal file
BIN
src/__pycache__/__init__.cpython-314.pyc
Normal file
Binary file not shown.
BIN
src/__pycache__/server.cpython-314.pyc
Normal file
BIN
src/__pycache__/server.cpython-314.pyc
Normal file
Binary file not shown.
252
src/server.py
252
src/server.py
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Gridbot MCP Server - Wraps eToroGridbot REST API as MCP tools.
|
||||
|
||||
Requires SSH tunnel: ssh -L 8000:localhost:8000 services
|
||||
Requires VPN connection and GRIDBOT_API_URL env var (default: http://services.agiliton.internal:8000)
|
||||
"""
|
||||
|
||||
import os
|
||||
@@ -13,7 +13,7 @@ from mcp.server import Server
|
||||
from mcp.server.stdio import stdio_server
|
||||
from mcp.types import Tool, TextContent
|
||||
|
||||
BASE_URL = os.getenv("GRIDBOT_API_URL", "http://localhost:8000")
|
||||
BASE_URL = os.getenv("GRIDBOT_API_URL", "http://services.agiliton.internal:8000")
|
||||
TIMEOUT = 30.0
|
||||
|
||||
server = Server("gridbot-mcp")
|
||||
@@ -27,7 +27,7 @@ async def api_get(endpoint: str) -> dict[str, Any]:
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
except httpx.ConnectError:
|
||||
return {"error": "Connection failed - is SSH tunnel running?"}
|
||||
return {"error": "Connection failed - check VPN (vpn-connect) and GRIDBOT_API_URL"}
|
||||
except httpx.HTTPStatusError as e:
|
||||
return {"error": f"HTTP {e.response.status_code}: {e.response.text}"}
|
||||
except Exception as e:
|
||||
@@ -42,7 +42,7 @@ async def api_post(endpoint: str, data: dict[str, Any] | None = None) -> dict[st
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
except httpx.ConnectError:
|
||||
return {"error": "Connection failed - is SSH tunnel running?"}
|
||||
return {"error": "Connection failed - check VPN (vpn-connect) and GRIDBOT_API_URL"}
|
||||
except httpx.HTTPStatusError as e:
|
||||
return {"error": f"HTTP {e.response.status_code}: {e.response.text}"}
|
||||
except Exception as e:
|
||||
@@ -57,7 +57,7 @@ async def api_delete(endpoint: str) -> dict[str, Any]:
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
except httpx.ConnectError:
|
||||
return {"error": "Connection failed - is SSH tunnel running?"}
|
||||
return {"error": "Connection failed - check VPN (vpn-connect) and GRIDBOT_API_URL"}
|
||||
except httpx.HTTPStatusError as e:
|
||||
return {"error": f"HTTP {e.response.status_code}: {e.response.text}"}
|
||||
except Exception as e:
|
||||
@@ -113,6 +113,11 @@ async def list_tools() -> list[Tool]:
|
||||
description="Get full dashboard summary including positions, orders, and analytics",
|
||||
inputSchema={"type": "object", "properties": {}, "required": []},
|
||||
),
|
||||
Tool(
|
||||
name="session_start",
|
||||
description="Get comprehensive session start summary (replaces 5-6 calls: health, VIX, portfolio, pending, risk, scale-out). Single call for instant situational awareness.",
|
||||
inputSchema={"type": "object", "properties": {}, "required": []},
|
||||
),
|
||||
Tool(
|
||||
name="analytics",
|
||||
description="Get trading analytics summary (win rate, Sharpe ratio, P/L)",
|
||||
@@ -191,6 +196,18 @@ async def list_tools() -> list[Tool]:
|
||||
description="Get recent trades with P/L details",
|
||||
inputSchema={"type": "object", "properties": {}, "required": []},
|
||||
),
|
||||
Tool(
|
||||
name="monthly_performance",
|
||||
description="Get monthly trade performance analytics (win rate, P/L, exit reasons, TP/SL used)",
|
||||
inputSchema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"year": {"type": "integer", "description": "Year (e.g., 2026)"},
|
||||
"month": {"type": "integer", "description": "Month (1-12)"},
|
||||
},
|
||||
"required": ["year", "month"],
|
||||
},
|
||||
),
|
||||
Tool(
|
||||
name="expectancy",
|
||||
description="Get trading expectancy metrics for all symbols",
|
||||
@@ -266,6 +283,7 @@ async def list_tools() -> list[Tool]:
|
||||
"take_profit_pct": {"type": "number", "description": "Take profit percentage (e.g., 10 for 10%)"},
|
||||
"stop_loss_pct": {"type": "number", "description": "Stop loss percentage (e.g., 5 for 5%)"},
|
||||
"dry_run": {"type": "boolean", "default": False, "description": "Validate only, do not execute"},
|
||||
"is_tsl_enabled": {"type": "boolean", "default": True, "description": "Enable trailing stop loss (eToro native feature)"},
|
||||
},
|
||||
"required": ["symbol", "action", "amount"],
|
||||
},
|
||||
@@ -282,6 +300,21 @@ async def list_tools() -> list[Tool]:
|
||||
"required": ["position_id"],
|
||||
},
|
||||
),
|
||||
Tool(
|
||||
name="close_positions_by_filter",
|
||||
description="Close multiple positions matching filters (fast rebalancing). Examples: close all metals, close all losers < -3%, close crypto. 10x faster than manual.",
|
||||
inputSchema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"asset_class": {"type": "string", "enum": ["crypto", "stocks", "metals", "etf"], "description": "Filter by asset class"},
|
||||
"min_pnl_pct": {"type": "number", "description": "Minimum P/L % (e.g., -10)"},
|
||||
"max_pnl_pct": {"type": "number", "description": "Maximum P/L % (e.g., -3)"},
|
||||
"symbols": {"type": "array", "items": {"type": "string"}, "description": "Specific symbols to close"},
|
||||
"close_percentage": {"type": "number", "default": 100, "description": "Percentage to close (1-100)"},
|
||||
"dry_run": {"type": "boolean", "default": True, "description": "Preview matches without executing (safety first)"},
|
||||
},
|
||||
},
|
||||
),
|
||||
# === SIGNAL INTENTS ===
|
||||
Tool(
|
||||
name="intents",
|
||||
@@ -340,6 +373,32 @@ async def list_tools() -> list[Tool]:
|
||||
"required": ["symbol", "amount", "trigger_price"],
|
||||
},
|
||||
),
|
||||
Tool(
|
||||
name="create_intents_bulk",
|
||||
description="Create multiple signal intents at once. Ideal for PI consensus scans with 3-5 opportunities. 5-10x faster than individual creates.",
|
||||
inputSchema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"intents": {
|
||||
"type": "array",
|
||||
"description": "List of intents to create",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"symbol": {"type": "string", "description": "Trading symbol (e.g., BTC, NVDA)"},
|
||||
"trigger_price": {"type": "number", "description": "Price at which to trigger"},
|
||||
"amount": {"type": "number", "description": "Position size in USD"},
|
||||
"is_buy": {"type": "boolean", "default": True},
|
||||
"take_profit_pct": {"type": "number"},
|
||||
"stop_loss_pct": {"type": "number"},
|
||||
},
|
||||
"required": ["symbol", "trigger_price", "amount"],
|
||||
},
|
||||
},
|
||||
},
|
||||
"required": ["intents"],
|
||||
},
|
||||
),
|
||||
Tool(
|
||||
name="cancel_intent",
|
||||
description="Cancel a pending signal intent by ID",
|
||||
@@ -384,6 +443,75 @@ async def list_tools() -> list[Tool]:
|
||||
description="Find duplicate pending orders (same instrument + rate + direction). Returns order IDs to cancel.",
|
||||
inputSchema={"type": "object", "properties": {}, "required": []},
|
||||
),
|
||||
# === SCALE-OUT (Session 241: Position Exit Management) ===
|
||||
Tool(
|
||||
name="scale_out_status",
|
||||
description="Get scale-out monitor service status (running, dry-run mode, statistics)",
|
||||
inputSchema={"type": "object", "properties": {}, "required": []},
|
||||
),
|
||||
Tool(
|
||||
name="scale_out_pending",
|
||||
description="Get positions pending scale-out (haven't had 50% partial close executed yet)",
|
||||
inputSchema={"type": "object", "properties": {}, "required": []},
|
||||
),
|
||||
Tool(
|
||||
name="scale_out_stats",
|
||||
description="Get scale-out statistics (total, executed, pending, P/L locked)",
|
||||
inputSchema={"type": "object", "properties": {}, "required": []},
|
||||
),
|
||||
Tool(
|
||||
name="scale_out_set_dry_run",
|
||||
description="Enable or disable scale-out dry-run mode. In dry-run, scale-outs are logged but not executed.",
|
||||
inputSchema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dry_run": {"type": "boolean", "description": "True to enable dry-run (log only), False to enable live execution"},
|
||||
},
|
||||
"required": ["dry_run"],
|
||||
},
|
||||
),
|
||||
Tool(
|
||||
name="scale_out_trigger",
|
||||
description="Manually trigger scale-out (partial close) for a position. Locks profit without waiting for auto threshold. Prevents givebacks.",
|
||||
inputSchema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"position_id": {"type": "integer", "description": "Position ID to scale out"},
|
||||
"percentage": {"type": "number", "default": 50, "description": "Percentage to close (1-100)"},
|
||||
"reason": {"type": "string", "default": "manual_trigger", "description": "Reason for manual trigger"},
|
||||
},
|
||||
"required": ["position_id"],
|
||||
},
|
||||
),
|
||||
Tool(
|
||||
name="scale_out_adjust_threshold",
|
||||
description="Override scale-out threshold for a symbol. Dynamic elite symbol tuning. E.g., set GOOGL to 12% instead of 8%, or 0% to disable.",
|
||||
inputSchema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"symbol": {"type": "string", "description": "Symbol to override (e.g., GOOGL, AMD)"},
|
||||
"threshold_pct": {"type": "number", "description": "New threshold % (e.g., 12 for 12%). Set to 0 to disable."},
|
||||
"reason": {"type": "string", "description": "Optional reason for override"},
|
||||
},
|
||||
"required": ["symbol", "threshold_pct"],
|
||||
},
|
||||
),
|
||||
Tool(
|
||||
name="scale_out_get_overrides",
|
||||
description="Get all scale-out threshold overrides (per-symbol custom thresholds).",
|
||||
inputSchema={"type": "object", "properties": {}, "required": []},
|
||||
),
|
||||
Tool(
|
||||
name="scale_out_delete_override",
|
||||
description="Delete threshold override for a symbol (revert to default).",
|
||||
inputSchema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"symbol": {"type": "string", "description": "Symbol to revert to default"},
|
||||
},
|
||||
"required": ["symbol"],
|
||||
},
|
||||
),
|
||||
# === CONTAINER OPERATIONS ===
|
||||
Tool(
|
||||
name="container_logs",
|
||||
@@ -411,6 +539,45 @@ async def list_tools() -> list[Tool]:
|
||||
"required": ["container", "confirm"],
|
||||
},
|
||||
),
|
||||
# === SESSION 452: 24/5 TRADING & CRYPTO FOCUS ===
|
||||
Tool(
|
||||
name="market_closure_context",
|
||||
description="Get current market closure context and crypto allocation adjustments",
|
||||
inputSchema={"type": "object", "properties": {}, "required": []},
|
||||
),
|
||||
Tool(
|
||||
name="pi_consensus_query",
|
||||
description="Get PI consensus data for a symbol (3+ PIs holding)",
|
||||
inputSchema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"symbol": {"type": "string", "description": "Ticker symbol (e.g., BTC, NVDA, AAPL)"},
|
||||
},
|
||||
"required": ["symbol"],
|
||||
},
|
||||
),
|
||||
Tool(
|
||||
name="pi_consensus_top",
|
||||
description="Get top PI consensus opportunities",
|
||||
inputSchema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"limit": {"type": "number", "default": 10, "description": "Max results (1-100)"},
|
||||
},
|
||||
"required": [],
|
||||
},
|
||||
),
|
||||
Tool(
|
||||
name="pi_scan_trigger",
|
||||
description="Trigger manual PI portfolio scan",
|
||||
inputSchema={
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"usernames": {"type": "string", "description": "Comma-separated PI usernames (optional)"},
|
||||
},
|
||||
"required": [],
|
||||
},
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@@ -438,6 +605,8 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent]:
|
||||
result = await api_get("/api/market-intel/crypto-fear-greed")
|
||||
case "dashboard":
|
||||
result = await api_get("/api/dashboard/summary")
|
||||
case "session_start":
|
||||
result = await api_get("/api/dashboard/session-start")
|
||||
case "analytics":
|
||||
result = await api_get("/api/analytics/summary")
|
||||
case "queue_status":
|
||||
@@ -475,6 +644,10 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent]:
|
||||
result = await api_get("/api/correlations/top")
|
||||
case "trades":
|
||||
result = await api_get("/api/dashboard/trades")
|
||||
case "monthly_performance":
|
||||
year = arguments.get("year")
|
||||
month = arguments.get("month")
|
||||
result = await api_get(f"/api/trades/monthly/{year}/{month}")
|
||||
case "expectancy":
|
||||
result = await api_get("/api/expectancy/")
|
||||
case "profitable_symbols":
|
||||
@@ -497,7 +670,12 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent]:
|
||||
case "rate_limiter":
|
||||
result = await api_get("/api/monitoring/rate_limiter/stats")
|
||||
case "portfolio_allocation":
|
||||
result = await api_get("/api/portfolio/status")
|
||||
# Get positions and extract allocation breakdown
|
||||
positions_data = await api_get("/api/trade/positions")
|
||||
if positions_data and "summary" in positions_data and "by_asset_class" in positions_data["summary"]:
|
||||
result = positions_data["summary"]["by_asset_class"]
|
||||
else:
|
||||
result = {"error": "Asset allocation data not available"}
|
||||
case "create_order":
|
||||
payload = {
|
||||
"symbol": arguments["symbol"],
|
||||
@@ -507,6 +685,7 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent]:
|
||||
"take_profit_pct": arguments.get("take_profit_pct", 10),
|
||||
"stop_loss_pct": arguments.get("stop_loss_pct", 5),
|
||||
"dry_run": arguments.get("dry_run", False),
|
||||
"is_tsl_enabled": arguments.get("is_tsl_enabled", True),
|
||||
}
|
||||
if arguments.get("limit_price"):
|
||||
payload["limit_price"] = arguments["limit_price"]
|
||||
@@ -516,6 +695,20 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent]:
|
||||
if arguments.get("close_percentage"):
|
||||
payload["close_percentage"] = arguments["close_percentage"]
|
||||
result = await api_post("/api/trade/close", payload)
|
||||
case "close_positions_by_filter":
|
||||
payload = {}
|
||||
if arguments.get("asset_class"):
|
||||
payload["asset_class"] = arguments["asset_class"]
|
||||
if arguments.get("min_pnl_pct") is not None:
|
||||
payload["min_pnl_pct"] = arguments["min_pnl_pct"]
|
||||
if arguments.get("max_pnl_pct") is not None:
|
||||
payload["max_pnl_pct"] = arguments["max_pnl_pct"]
|
||||
if arguments.get("symbols"):
|
||||
payload["symbols"] = arguments["symbols"]
|
||||
if arguments.get("close_percentage"):
|
||||
payload["close_percentage"] = arguments["close_percentage"]
|
||||
payload["dry_run"] = arguments.get("dry_run", True)
|
||||
result = await api_post("/portfolio/close-by-filter", payload)
|
||||
# === SIGNAL INTENTS ===
|
||||
case "intents":
|
||||
params = []
|
||||
@@ -561,6 +754,8 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent]:
|
||||
if arguments.get("source_type"):
|
||||
payload["source_type"] = arguments["source_type"]
|
||||
result = await api_post("/intents", payload)
|
||||
case "create_intents_bulk":
|
||||
result = await api_post("/intents/bulk", arguments["intents"])
|
||||
case "cancel_intent":
|
||||
intent_id = arguments["intent_id"]
|
||||
result = await api_delete(f"/intents/{intent_id}")
|
||||
@@ -576,6 +771,35 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent]:
|
||||
result = await api_post("/api/trade/orders/cancel-bulk", {"order_ids": order_ids})
|
||||
case "find_duplicate_orders":
|
||||
result = await api_get("/api/trade/orders/duplicates")
|
||||
# === SCALE-OUT (Session 241) ===
|
||||
case "scale_out_status":
|
||||
result = await api_get("/api/trade/scale-out/status")
|
||||
case "scale_out_pending":
|
||||
result = await api_get("/api/trade/scale-out/pending")
|
||||
case "scale_out_stats":
|
||||
result = await api_get("/api/trade/scale-out/stats")
|
||||
case "scale_out_set_dry_run":
|
||||
result = await api_post("/api/trade/scale-out/dry-run", {"dry_run": arguments["dry_run"]})
|
||||
case "scale_out_trigger":
|
||||
payload = {
|
||||
"position_id": arguments["position_id"],
|
||||
"percentage": arguments.get("percentage", 50.0),
|
||||
"reason": arguments.get("reason", "manual_trigger"),
|
||||
}
|
||||
result = await api_post("/api/trade/scale-out/trigger", payload)
|
||||
case "scale_out_adjust_threshold":
|
||||
payload = {
|
||||
"symbol": arguments["symbol"],
|
||||
"threshold_pct": arguments["threshold_pct"],
|
||||
}
|
||||
if arguments.get("reason"):
|
||||
payload["reason"] = arguments["reason"]
|
||||
result = await api_post("/api/scale-out/adjust-threshold", payload)
|
||||
case "scale_out_get_overrides":
|
||||
result = await api_get("/api/scale-out/overrides")
|
||||
case "scale_out_delete_override":
|
||||
symbol = arguments["symbol"]
|
||||
result = await api_delete(f"/api/scale-out/threshold/{symbol}")
|
||||
# === CONTAINER OPERATIONS ===
|
||||
case "container_logs":
|
||||
params = [f"container={arguments['container']}"]
|
||||
@@ -590,6 +814,22 @@ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent]:
|
||||
result = await api_post(
|
||||
f"/containers/restart?container={arguments['container']}&confirm={str(arguments.get('confirm', False)).lower()}"
|
||||
)
|
||||
# === SESSION 452: 24/5 TRADING & CRYPTO FOCUS ===
|
||||
case "market_closure_context":
|
||||
# Get market closure context from dashboard
|
||||
result = await api_get("/api/dashboard/market-closure-context")
|
||||
case "pi_consensus_query":
|
||||
symbol = arguments["symbol"].upper()
|
||||
result = await api_get(f"/api/pi-intelligence/consensus/{symbol}")
|
||||
case "pi_consensus_top":
|
||||
limit = arguments.get("limit", 10)
|
||||
result = await api_get(f"/api/pi-intelligence/consensus/top?limit={limit}")
|
||||
case "pi_scan_trigger":
|
||||
usernames = arguments.get("usernames")
|
||||
endpoint = "/api/pi-intelligence/scan/trigger"
|
||||
if usernames:
|
||||
endpoint += f"?usernames={usernames}"
|
||||
result = await api_post(endpoint)
|
||||
case _:
|
||||
result = {"error": f"Unknown tool: {name}"}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user