- Add advanced metrics dashboard with trade analytics - Add new trading components (EntryTypeAnalysis, MultiDayPositionTracker, NewsEventTracker, etc.) - Add strategy mode selector and trend confirmation - Add risk automation panel and slippage correlation analysis - Add daily trading plan enhancements with modal components - Add custom hooks (useApi, useLocalStorage, useAdvancedTradeMetrics) - Add broker service integration and trading API - Add test setup and vitest configuration - Include parquet data files for live market data - Add comprehensive documentation in docs/ folder
80 lines
2.3 KiB
Python
80 lines
2.3 KiB
Python
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter, HTTPException
|
|
from pydantic import BaseModel, Field, validator
|
|
|
|
from app.services.broker_bridge import BrokerError, broker_bridge_service
|
|
|
|
router = APIRouter(prefix="/brokers", tags=["Brokers"])
|
|
|
|
|
|
class ConnectRequest(BaseModel):
|
|
provider_id: str = Field(..., description="Broker provider identifier")
|
|
api_key: str = Field(..., description="API key or session token")
|
|
account_id: str = Field(..., description="Broker account identifier/login")
|
|
demo: bool = Field(True, description="If true, stays in practice/demo mode when supported")
|
|
|
|
@validator("provider_id")
|
|
def _trim(cls, value: str) -> str:
|
|
value = value.strip()
|
|
if not value:
|
|
raise ValueError("provider_id is required")
|
|
return value
|
|
|
|
|
|
class OrderRequest(BaseModel):
|
|
action: str
|
|
symbol: str
|
|
quantity: float
|
|
price: float
|
|
type: str | None = None
|
|
stopLoss: float | None = None
|
|
takeProfit: float | None = None
|
|
|
|
|
|
@router.get("/providers")
|
|
async def list_providers():
|
|
return broker_bridge_service.list_providers()
|
|
|
|
|
|
@router.get("/session")
|
|
async def get_session():
|
|
return broker_bridge_service.get_session()
|
|
|
|
|
|
@router.post("/connect")
|
|
async def connect(request: ConnectRequest):
|
|
try:
|
|
return await broker_bridge_service.connect(
|
|
request.provider_id,
|
|
{
|
|
"api_key": request.api_key,
|
|
"account_id": request.account_id,
|
|
"demo": request.demo,
|
|
},
|
|
)
|
|
except BrokerError as exc: # pragma: no cover - depends on environment
|
|
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
|
|
|
|
@router.post("/disconnect")
|
|
async def disconnect():
|
|
await broker_bridge_service.disconnect()
|
|
return {"status": "disconnected"}
|
|
|
|
|
|
@router.post("/orders")
|
|
async def place_order(request: OrderRequest):
|
|
try:
|
|
return await broker_bridge_service.place_order(request.dict())
|
|
except BrokerError as exc: # pragma: no cover
|
|
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
|
|
|
|
@router.post("/sync")
|
|
async def sync_positions():
|
|
try:
|
|
return await broker_bridge_service.sync_positions()
|
|
except BrokerError as exc: # pragma: no cover
|
|
raise HTTPException(status_code=400, detail=str(exc)) from exc
|