Skip to main content
Glama
knishioka

IB Analytics MCP Server

by knishioka
position.py3.21 kB
"""Position data model""" from datetime import date from decimal import Decimal from pydantic import BaseModel, Field, field_validator from ib_sec_mcp.models.trade import AssetClass class Position(BaseModel): """Current position""" account_id: str = Field(..., description="Account ID") symbol: str = Field(..., description="Trading symbol") description: str | None = Field(None, description="Security description") asset_class: AssetClass = Field(..., description="Asset class") cusip: str | None = Field(None, description="CUSIP") isin: str | None = Field(None, description="ISIN") quantity: Decimal = Field(..., description="Position quantity") multiplier: Decimal = Field(Decimal("1"), description="Contract multiplier") mark_price: Decimal = Field(..., description="Current market price") position_value: Decimal = Field(..., description="Current position value") average_cost: Decimal = Field(..., description="Average cost basis") cost_basis: Decimal = Field(..., description="Total cost basis") unrealized_pnl: Decimal = Field(Decimal("0"), description="Unrealized P&L") realized_pnl: Decimal = Field(Decimal("0"), description="Realized P&L to date") currency: str = Field("USD", description="Currency") fx_rate_to_base: Decimal = Field(Decimal("1.0"), description="FX rate to base currency") position_date: date = Field(..., description="Position as of date") # Bond-specific fields coupon_rate: Decimal | None = Field(None, description="Coupon rate (for bonds)") maturity_date: date | None = Field(None, description="Maturity date (for bonds)") ytm: Decimal | None = Field(None, description="Yield to maturity (for bonds)") duration: Decimal | None = Field(None, description="Duration (for bonds)") @field_validator("quantity", "mark_price", "position_value", mode="before") @classmethod def convert_to_decimal(cls, v: int | float | str | Decimal) -> Decimal: """Convert numeric fields to Decimal""" if isinstance(v, (int, float, str)): return Decimal(str(v)) return v @property def market_value(self) -> Decimal: """Current market value (alias for position_value)""" return self.position_value @property def total_pnl(self) -> Decimal: """Total P&L (realized + unrealized)""" return self.realized_pnl + self.unrealized_pnl @property def pnl_percentage(self) -> Decimal: """P&L as percentage of cost basis""" if self.cost_basis == 0: return Decimal("0") return (self.unrealized_pnl / self.cost_basis) * 100 @property def is_long(self) -> bool: """Check if position is long""" return self.quantity > 0 @property def is_short(self) -> bool: """Check if position is short""" return self.quantity < 0 @property def is_bond(self) -> bool: """Check if position is a bond""" return self.asset_class == AssetClass.BOND class Config: """Pydantic config""" json_encoders = { date: lambda v: v.isoformat(), Decimal: lambda v: str(v), }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/knishioka/ib-sec-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server