from pydantic import BaseModel class PositionLong(BaseModel): units: str averagePrice: str pl: str resettablePL: str financing: str dividendAdjustment: str guaranteedExecutionFees: str tradeIDs: list[str] unrealizedPL: str class PositionShort(BaseModel): units: str pl: str resettablePL: str financing: str dividendAdjustment: str guaranteedExecutionFees: str unrealizedPL: str class Position(BaseModel): instrument: str long: PositionLong short: PositionShort pl: str resettablePL: str financing: str commission: str dividendAdjustment: str guaranteedExecutionFees: str unrealizedPL: str marginUsed: str class OpenPositions(BaseModel): positions: list[Position] lastTransactionID: str def parse_prices(x): if float(x["long"]["units"]) > 0: return x["long"]["averagePrice"] elif float(x["short"]["units"]) > 0: return x["short"]["averagePrice"] else: return 0 def parse_units(x): if float(x["long"]["units"]) > 0: return x["long"]["units"] elif float(x["short"]["units"]) > 0: return x["short"]["units"] else: return 0 def parse_value(x): if float(x["long"]["units"]) > 0: return float(x["long"]["units"]) * float(x["long"]["averagePrice"]) elif float(x["short"]["units"]) > 0: return float(x["short"]["units"]) * float(x["short"]["averagePrice"]) else: return 0 def parse_side(x): if float(x["long"]["units"]) > 0: return "long" elif float(x["short"]["units"]) > 0: return "short" else: return "unknown" OpenPositionsSchema = { "itemlist": ( "positions", [ { "symbol": "instrument", "unrealized_pl": "unrealizedPL", "price": parse_prices, "units": parse_units, "side": parse_side, "value": parse_value, } ], ) } class AccountDetailsNested(BaseModel): guaranteedStopLossOrderMode: str hedgingEnabled: bool id: str createdTime: str currency: str createdByUserID: int alias: str marginRate: str lastTransactionID: str balance: str openTradeCount: int openPositionCount: int pendingOrderCount: int pl: str resettablePL: str resettablePLTime: str financing: str commission: str dividendAdjustment: str guaranteedExecutionFees: str orders: list # Order positions: list # Position trades: list # Trade unrealizedPL: str NAV: str marginUsed: str marginAvailable: str positionValue: str marginCloseoutUnrealizedPL: str marginCloseoutNAV: str marginCloseoutMarginUsed: str marginCloseoutPositionValue: str marginCloseoutPercent: str withdrawalLimit: str marginCallMarginUsed: str marginCallPercent: str class AccountDetails(BaseModel): account: AccountDetailsNested lastTransactionID: str AccountDetailsSchema = { "guaranteedSLOM": "account.guaranteedStopLossOrderMode", "hedgingEnabled": "account.hedgingEnabled", "id": "account.id", "created_at": "account.createdTime", "currency": "account.currency", "createdByUserID": "account.createdByUserID", "alias": "account.alias", "marginRate": "account.marginRate", "lastTransactionID": "account.lastTransactionID", "balance": "account.balance", "openTradeCount": "account.openTradeCount", "openPositionCount": "account.openPositionCount", "pendingOrderCount": "account.pendingOrderCount", "pl": "account.pl", "resettablePL": "account.resettablePL", "resettablePLTime": "account.resettablePLTime", "financing": "account.financing", "commission": "account.commission", "dividendAdjustment": "account.dividendAdjustment", "guaranteedExecutionFees": "account.guaranteedExecutionFees", # "orders": "account.orders", # "positions": "account.positions", # "trades": "account.trades", "unrealizedPL": "account.unrealizedPL", "NAV": "account.NAV", "marginUsed": "account.marginUsed", "marginAvailable": "account.marginAvailable", "positionValue": "account.positionValue", "marginCloseoutUnrealizedPL": "account.marginCloseoutUnrealizedPL", "marginCloseoutNAV": "account.marginCloseoutNAV", "marginCloseoutMarginUsed": "account.marginCloseoutMarginUsed", "marginCloseoutPositionValue": "account.marginCloseoutPositionValue", "marginCloseoutPercent": "account.marginCloseoutPercent", "withdrawalLimit": "account.withdrawalLimit", "marginCallMarginUsed": "account.marginCallMarginUsed", "marginCallPercent": "account.marginCallPercent", } class PositionDetailsNested(BaseModel): instrument: str long: PositionLong short: PositionShort pl: str resettablePL: str financing: str commission: str dividendAdjustment: str guaranteedExecutionFees: str unrealizedPL: str marginUsed: str class PositionDetails(BaseModel): position: PositionDetailsNested lastTransactionID: str PositionDetailsSchema = { "symbol": "position.instrument", "long": "position.long", "short": "position.short", "pl": "position.pl", "resettablePL": "position.resettablePL", "financing": "position.financing", "commission": "position.commission", "dividendAdjustment": "position.dividendAdjustment", "guaranteedExecutionFees": "position.guaranteedExecutionFees", "unrealizedPL": "position.unrealizedPL", "marginUsed": "position.marginUsed", "price": lambda x: parse_prices(x["position"]), "units": lambda x: parse_units(x["position"]), "side": lambda x: parse_side(x["position"]), "value": lambda x: parse_value(x["position"]), } class InstrumentTag(BaseModel): type: str name: str class InstrumentFinancingDaysOfWeek(BaseModel): dayOfWeek: str daysCharged: int class InstrumentFinancing(BaseModel): longRate: str shortRate: str financingDaysOfWeek: list[InstrumentFinancingDaysOfWeek] class InstrumentGuaranteedRestriction(BaseModel): volume: str priceRange: str class Instrument(BaseModel): name: str type: str displayName: str pipLocation: int displayPrecision: int tradeUnitsPrecision: int minimumTradeSize: str maximumTrailingStopDistance: str minimumTrailingStopDistance: str maximumPositionSize: str maximumOrderUnits: str marginRate: str guaranteedStopLossOrderMode: str tags: list[InstrumentTag] financing: InstrumentFinancing guaranteedStopLossOrderLevelRestriction: InstrumentGuaranteedRestriction | None class AccountInstruments(BaseModel): instruments: list[Instrument] AccountInstrumentsSchema = { "itemlist": ( "instruments", [ { "name": "name", "type": "type", "displayName": "displayName", "pipLocation": "pipLocation", "displayPrecision": "displayPrecision", "tradeUnitsPrecision": "tradeUnitsPrecision", "minimumTradeSize": "minimumTradeSize", "maximumTrailingStopDistance": "maximumTrailingStopDistance", "minimumTrailingStopDistance": "minimumTrailingStopDistance", "maximumPositionSize": "maximumPositionSize", "maximumOrderUnits": "maximumOrderUnits", "marginRate": "marginRate", "guaranteedSLOM": "guaranteedStopLossOrderMode", "tags": "tags", "financing": "financing", "guaranteedSLOLR": "guaranteedStopLossOrderLevelRestriction", } ], ) }