Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ broker order buy AAPL 100 --limit 185 \
- **Autonomous Execution** — Persistent auth keeps sessions alive 24/7. No manual logins, no token expiry interruptions.
- **Multi-Broker** — Unified commands across E\*Trade and Interactive Brokers. One skill file, one interface.
- **Full Options Support** — Option chains with greeks, expiry filtering, and strike ranges.
- **Risk Guardrails** — Exposure analysis, cancel-all for instant flattening, paper trading mode. Power with built-in safety valves.

## Supported Brokers

Expand Down Expand Up @@ -88,11 +87,6 @@ broker positions Current positions
broker pnl P&L summary
broker balance Account balances and margin
broker exposure --by symbol Exposure breakdown
broker risk check Pre-trade risk validation
broker risk limits Current risk limits
broker risk set PARAM VALUE Update a risk limit
broker risk halt Emergency halt
broker risk resume Resume after halt
broker audit orders Order audit trail
broker audit commands Command audit trail
```
Expand Down
1 change: 0 additions & 1 deletion cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ broker positions
broker order buy AAPL 5 --limit 180 --tif DAY --idempotency-key strat-42-aapl
broker order buy AAPL 5 --limit 180 --dry-run
broker chain AAPL --type call --strike-range 0.95:1.05 --limit 100 --fields strike,expiry,bid,ask
broker limits
broker audit commands --request-id <request_id>
broker schema quote.snapshot
```
Expand Down
1 change: 0 additions & 1 deletion cli/src/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,5 @@ def _default_suggestion(code: ErrorCode) -> str | None:
ErrorCode.IB_DISCONNECTED: "Verify IB Gateway/TWS is running and the gateway host/port are correct.",
ErrorCode.INVALID_ARGS: "Run `broker --help` or `<command> --help` for valid usage.",
ErrorCode.TIMEOUT: "Retry the command or increase `runtime.request_timeout_seconds` in config.",
ErrorCode.RISK_HALTED: "Review `broker limits`, then run `broker resume` when appropriate.",
}
return suggestions.get(code)
28 changes: 0 additions & 28 deletions cli/src/audit.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ class AuditSource(str, Enum):
class AuditTable(str, Enum):
ORDERS = "orders"
COMMANDS = "commands"
RISK = "risk"


class ExportFormat(str, Enum):
Expand Down Expand Up @@ -92,30 +91,6 @@ def commands(
handle_error(exc, json_output=state.json_output, command=command, strict=state.strict)


@app.command("risk", help="Query risk event audit records.")
def risk(
ctx: typer.Context,
event_type: str | None = typer.Option(None, "--type"),
) -> None:
state = get_state(ctx)
command = "audit.risk"
params: dict[str, object] = {}
if event_type:
params["type"] = event_type

try:
result = run_async(daemon_request(state, command, params))
print_output(
result.data.get("risk_events", []),
json_output=state.json_output,
command=command,
request_id=result.request_id,
strict=state.strict,
)
except BrokerError as exc:
handle_error(exc, json_output=state.json_output, command=command, strict=state.strict)


@app.command("export", help="Export audit rows to CSV.")
def export(
ctx: typer.Context,
Expand All @@ -126,7 +101,6 @@ def export(
status: OrderStatusFilter | None = typer.Option(None, "--status", case_sensitive=False, help="Order status filter."),
source: AuditSource | None = typer.Option(None, "--source", case_sensitive=False),
request_id: str | None = typer.Option(None, "--request-id", help="Command-audit filter by request_id."),
event_type: str | None = typer.Option(None, "--type", help="Risk event type filter."),
) -> None:
state = get_state(ctx)
command = "audit.export"
Expand All @@ -139,8 +113,6 @@ def export(
params["source"] = source.value
if request_id:
params["request_id"] = request_id
if event_type:
params["type"] = event_type

try:
result = run_async(daemon_request(state, command, params))
Expand Down
2 changes: 1 addition & 1 deletion cli/src/daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def stop(ctx: typer.Context) -> None:
handle_error(exc, json_output=state.json_output, command=command, strict=state.strict)


@app.command("status", help="Show daemon uptime, IB connection state, and risk halt status.")
@app.command("status", help="Show daemon uptime and connection state.")
def status(ctx: typer.Context) -> None:
state = get_state(ctx)
command = "daemon.status"
Expand Down
6 changes: 2 additions & 4 deletions cli/src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,24 @@
import market
import orders
import portfolio
import risk
import schema_cmd
import update
from _common import CLIState, build_typer, load_config

app = build_typer(
"""Broker command-line interface for trading, portfolio, risk, and audit workflows.
"""Broker command-line interface for trading, portfolio, and audit workflows.

Examples:
broker quote AAPL MSFT
broker order buy AAPL 10 --limit 180
broker check --side buy --symbol AAPL --qty 50
broker positions
"""
)

app.add_typer(daemon.app, name="daemon")
app.add_typer(market.app)
app.add_typer(orders.order_app, name="order")
app.add_typer(portfolio.app)
app.add_typer(risk.app)
app.add_typer(audit.app, name="audit")

# Flat commands required by spec.
Expand Down
2 changes: 1 addition & 1 deletion cli/src/portfolio.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def exposure(
handle_error(exc, json_output=state.json_output, command=command, strict=state.strict)


@app.command("snapshot", help="Fetch quote/portfolio/risk state in one request.")
@app.command("snapshot", help="Fetch quote and portfolio state in one request.")
def snapshot(
ctx: typer.Context,
symbols: str | None = typer.Option(
Expand Down
154 changes: 0 additions & 154 deletions cli/src/risk.py

This file was deleted.

25 changes: 2 additions & 23 deletions cli/tests/test_cli/test_command_contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import market
import orders
import portfolio
import risk
import schema_cmd
from main import app

Expand Down Expand Up @@ -81,21 +80,14 @@ async def fake_daemon_request(_: Any, command: str, params: dict[str, Any] | Non
"order.cancel": {"ok": True},
"orders.cancel_all": {"cancelled": 0},
"fills.list": {"fills": []},
"risk.check": {"ok": True},
"risk.limits": {"limits": {"max_order_value": 50000}},
"risk.set": {"limits": {"max_order_value": 1000}},
"risk.halt": {"halted": True},
"risk.resume": {"halted": False},
"risk.override": {"override": {"param": "max_order_value", "value": 1000}},
"audit.commands": {"commands": []},
"audit.orders": {"orders": []},
"audit.risk": {"risk_events": []},
"audit.export": {"output": "/tmp/audit.csv", "rows": 0},
"schema.get": {"schema_version": "v1", "commands": {}},
}
return FakeRPCResult(command, responses.get(command, {"ok": True}))

for mod in (audit, daemon, market, orders, portfolio, risk, schema_cmd):
for mod in (audit, daemon, market, orders, portfolio, schema_cmd):
monkeypatch.setattr(mod, "daemon_request", fake_daemon_request)

return calls
Expand All @@ -122,12 +114,6 @@ def test_root_command_surface_contract(runner: CliRunner) -> None:
"pnl",
"balance",
"exposure",
"check",
"limits",
"set",
"halt",
"resume",
"override",
"snapshot",
"audit",
"schema",
Expand All @@ -139,7 +125,7 @@ def test_root_command_surface_contract(runner: CliRunner) -> None:
[
(["daemon", "--help"], {"start", "stop", "status", "restart"}),
(["order", "--help"], {"buy", "sell", "bracket", "status"}),
(["audit", "--help"], {"orders", "commands", "risk", "export"}),
(["audit", "--help"], {"orders", "commands", "export"}),
],
)
def test_subcommand_surface_contract(
Expand Down Expand Up @@ -220,15 +206,8 @@ def test_subcommand_surface_contract(
(["balance"], "portfolio.balance"),
(["exposure"], "portfolio.exposure"),
(["snapshot"], "portfolio.snapshot"),
(["check", "--side", "buy", "--symbol", "AAPL", "--qty", "1"], "risk.check"),
(["limits"], "risk.limits"),
(["set", "max_order_value", "1000"], "risk.set"),
(["halt"], "risk.halt"),
(["resume"], "risk.resume"),
(["override", "--param", "max_order_value", "--value", "1000", "--duration", "1h", "--reason", "test"], "risk.override"),
(["audit", "orders"], "audit.orders"),
(["audit", "commands"], "audit.commands"),
(["audit", "risk"], "audit.risk"),
(["audit", "export", "--output", "/tmp/audit.csv"], "audit.export"),
(["schema"], "schema.get"),
(["daemon", "status"], "daemon.status"),
Expand Down
3 changes: 1 addition & 2 deletions daemon/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
# Broker Daemon

`broker-daemon` is the long-running backend for broker execution and risk enforcement.
`broker-daemon` is the long-running backend for broker execution.

## Responsibilities

- maintain session state to IB Gateway/TWS
- route requests from CLI/SDK clients
- enforce risk controls before execution
- persist audit events for traceability

## Interfaces
Expand Down
Loading