2022-11-22 07:20:37 +00:00
|
|
|
from decimal import Decimal as D
|
|
|
|
|
2022-10-30 19:11:07 +00:00
|
|
|
from pydantic import BaseModel
|
2022-10-31 08:58:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
class PositionLong(BaseModel):
|
|
|
|
units: str
|
2022-11-29 07:20:39 +00:00
|
|
|
averagePrice: str | None
|
2022-10-31 08:58:08 +00:00
|
|
|
pl: str
|
|
|
|
resettablePL: str
|
|
|
|
financing: str
|
|
|
|
dividendAdjustment: str
|
|
|
|
guaranteedExecutionFees: str
|
2022-11-29 07:20:39 +00:00
|
|
|
tradeIDs: list[str] | None
|
2022-10-31 08:58:08 +00:00
|
|
|
unrealizedPL: str
|
|
|
|
|
|
|
|
|
|
|
|
class PositionShort(BaseModel):
|
|
|
|
units: str
|
2022-11-29 07:20:39 +00:00
|
|
|
averagePrice: str | None
|
2022-10-31 08:58:08 +00:00
|
|
|
pl: str
|
|
|
|
resettablePL: str
|
|
|
|
financing: str
|
|
|
|
dividendAdjustment: str
|
|
|
|
guaranteedExecutionFees: str
|
2022-11-29 07:20:39 +00:00
|
|
|
tradeIDs: list[str] | None
|
2022-10-31 08:58:08 +00:00
|
|
|
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
|
2022-11-02 18:25:34 +00:00
|
|
|
|
|
|
|
|
2022-11-02 19:04:05 +00:00
|
|
|
def parse_prices(x):
|
2022-11-02 19:09:50 +00:00
|
|
|
if float(x["long"]["units"]) > 0:
|
2022-11-02 19:04:05 +00:00
|
|
|
return x["long"]["averagePrice"]
|
2022-11-29 07:20:39 +00:00
|
|
|
elif float(x["short"]["units"]) < 0:
|
2022-11-02 19:04:05 +00:00
|
|
|
return x["short"]["averagePrice"]
|
|
|
|
else:
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
2022-11-02 19:09:50 +00:00
|
|
|
def parse_units(x):
|
|
|
|
if float(x["long"]["units"]) > 0:
|
|
|
|
return x["long"]["units"]
|
2022-11-29 07:20:39 +00:00
|
|
|
elif float(x["short"]["units"]) < 0:
|
2022-11-02 19:09:50 +00:00
|
|
|
return x["short"]["units"]
|
|
|
|
else:
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
|
def parse_value(x):
|
|
|
|
if float(x["long"]["units"]) > 0:
|
2022-11-22 07:20:37 +00:00
|
|
|
return D(x["long"]["units"]) * D(x["long"]["averagePrice"])
|
2022-11-29 07:20:39 +00:00
|
|
|
elif float(x["short"]["units"]) < 0:
|
2022-11-22 07:20:37 +00:00
|
|
|
return D(x["short"]["units"]) * D(x["short"]["averagePrice"])
|
2022-11-02 19:09:50 +00:00
|
|
|
else:
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
|
def parse_side(x):
|
|
|
|
if float(x["long"]["units"]) > 0:
|
|
|
|
return "long"
|
2022-11-29 07:20:39 +00:00
|
|
|
elif float(x["short"]["units"]) < 0:
|
2022-11-02 19:09:50 +00:00
|
|
|
return "short"
|
|
|
|
else:
|
|
|
|
return "unknown"
|
|
|
|
|
|
|
|
|
2022-11-29 07:20:39 +00:00
|
|
|
def parse_trade_ids(x, sum=0):
|
2022-11-29 07:20:39 +00:00
|
|
|
if float(x["long"]["units"]) > 0:
|
|
|
|
return [str(int(y) + sum) for y in x["long"]["tradeIDs"]]
|
|
|
|
elif float(x["short"]["units"]) < 0:
|
|
|
|
return [str(int(y) + sum) for y in x["short"]["tradeIDs"]]
|
|
|
|
else:
|
|
|
|
return "unknown"
|
|
|
|
|
|
|
|
|
2022-11-04 07:20:55 +00:00
|
|
|
OpenPositionsSchema = {
|
2022-11-02 18:25:34 +00:00
|
|
|
"itemlist": (
|
|
|
|
"positions",
|
2022-11-02 19:04:05 +00:00
|
|
|
[
|
|
|
|
{
|
|
|
|
"symbol": "instrument",
|
|
|
|
"unrealized_pl": "unrealizedPL",
|
2022-11-29 07:20:39 +00:00
|
|
|
"trade_ids": parse_trade_ids, # actual value is lower by 1
|
2022-11-02 19:04:05 +00:00
|
|
|
"price": parse_prices,
|
2022-11-02 19:09:50 +00:00
|
|
|
"units": parse_units,
|
|
|
|
"side": parse_side,
|
|
|
|
"value": parse_value,
|
2022-11-02 19:04:05 +00:00
|
|
|
}
|
|
|
|
],
|
2022-11-02 18:25:34 +00:00
|
|
|
)
|
|
|
|
}
|
2022-11-04 07:20:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
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",
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-11-10 07:20:14 +00:00
|
|
|
class AccountSummaryNested(BaseModel):
|
|
|
|
marginCloseoutNAV: str
|
|
|
|
marginUsed: str
|
|
|
|
currency: str
|
|
|
|
resettablePL: str
|
|
|
|
NAV: str
|
|
|
|
marginCloseoutMarginUsed: str
|
|
|
|
marginCloseoutPositionValue: str
|
|
|
|
openTradeCount: int
|
|
|
|
id: str
|
|
|
|
hedgingEnabled: bool
|
|
|
|
marginCloseoutPercent: str
|
|
|
|
marginCallMarginUsed: str
|
|
|
|
openPositionCount: int
|
|
|
|
positionValue: str
|
|
|
|
pl: str
|
|
|
|
lastTransactionID: str
|
|
|
|
marginAvailable: str
|
|
|
|
marginRate: str
|
|
|
|
marginCallPercent: str
|
|
|
|
pendingOrderCount: int
|
|
|
|
withdrawalLimit: str
|
|
|
|
unrealizedPL: str
|
|
|
|
alias: str
|
|
|
|
createdByUserID: int
|
|
|
|
marginCloseoutUnrealizedPL: str
|
|
|
|
createdTime: str
|
|
|
|
balance: str
|
|
|
|
|
|
|
|
|
|
|
|
class AccountSummary(BaseModel):
|
|
|
|
account: AccountSummaryNested
|
|
|
|
lastTransactionID: str
|
|
|
|
|
|
|
|
|
|
|
|
AccountSummarySchema = {
|
|
|
|
"marginCloseoutNAV": "account.marginCloseoutNAV",
|
|
|
|
"marginUsed": "account.marginUsed",
|
|
|
|
"currency": "account.currency",
|
|
|
|
"resettablePL": "account.resettablePL",
|
|
|
|
"NAV": "account.NAV",
|
|
|
|
"marginCloseoutMarginUsed": "account.marginCloseoutMarginUsed",
|
|
|
|
"marginCloseoutPositionValue": "account.marginCloseoutPositionValue",
|
|
|
|
"openTradeCount": "account.openTradeCount",
|
|
|
|
"id": "account.id",
|
|
|
|
"hedgingEnabled": "account.hedgingEnabled",
|
|
|
|
"marginCloseoutPercent": "account.marginCloseoutPercent",
|
|
|
|
"marginCallMarginUsed": "account.marginCallMarginUsed",
|
|
|
|
"openPositionCount": "account.openPositionCount",
|
|
|
|
"positionValue": "account.positionValue",
|
|
|
|
"pl": "account.pl",
|
|
|
|
"lastTransactionID": "account.lastTransactionID",
|
|
|
|
"marginAvailable": "account.marginAvailable",
|
|
|
|
"marginRate": "account.marginRate",
|
|
|
|
"marginCallPercent": "account.marginCallPercent",
|
|
|
|
"pendingOrderCount": "account.pendingOrderCount",
|
|
|
|
"withdrawalLimit": "account.withdrawalLimit",
|
|
|
|
"unrealizedPL": "account.unrealizedPL",
|
|
|
|
"alias": "account.alias",
|
|
|
|
"createdByUserID": "account.createdByUserID",
|
|
|
|
"marginCloseoutUnrealizedPL": "account.marginCloseoutUnrealizedPL",
|
|
|
|
"createdTime": "account.createdTime",
|
|
|
|
"balance": "account.balance",
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-11-04 07:20:14 +00:00
|
|
|
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"]),
|
2022-11-29 07:20:39 +00:00
|
|
|
"trade_ids": lambda x: parse_trade_ids(
|
|
|
|
x["position"], sum=0
|
|
|
|
), # this value is correct
|
2022-11-04 07:20:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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",
|
|
|
|
}
|
|
|
|
],
|
|
|
|
)
|
|
|
|
}
|
2022-11-10 19:27:46 +00:00
|
|
|
|
2022-11-10 07:20:20 +00:00
|
|
|
|
2022-11-10 19:27:46 +00:00
|
|
|
class OrderTransaction(BaseModel):
|
|
|
|
id: str
|
|
|
|
accountID: str
|
|
|
|
userID: int
|
|
|
|
batchID: str
|
|
|
|
requestID: str
|
|
|
|
time: str
|
|
|
|
type: str
|
|
|
|
instrument: str
|
|
|
|
units: str
|
|
|
|
timeInForce: str
|
|
|
|
positionFill: str
|
|
|
|
reason: str
|
|
|
|
|
2022-11-10 07:20:20 +00:00
|
|
|
|
2022-11-10 19:27:46 +00:00
|
|
|
class OrderCreate(BaseModel):
|
|
|
|
orderCreateTransaction: OrderTransaction
|
|
|
|
|
2022-11-10 07:20:20 +00:00
|
|
|
|
2022-11-10 19:27:46 +00:00
|
|
|
OrderCreateSchema = {
|
|
|
|
"id": "orderCreateTransaction.id",
|
|
|
|
"accountID": "orderCreateTransaction.accountID",
|
|
|
|
"userID": "orderCreateTransaction.userID",
|
|
|
|
"batchID": "orderCreateTransaction.batchID",
|
|
|
|
"requestID": "orderCreateTransaction.requestID",
|
|
|
|
"time": "orderCreateTransaction.time",
|
|
|
|
"type": "orderCreateTransaction.type",
|
|
|
|
"symbol": "orderCreateTransaction.instrument",
|
|
|
|
"units": "orderCreateTransaction.units",
|
|
|
|
"timeInForce": "orderCreateTransaction.timeInForce",
|
|
|
|
"positionFill": "orderCreateTransaction.positionFill",
|
|
|
|
"reason": "orderCreateTransaction.reason",
|
|
|
|
}
|
|
|
|
|
2022-11-10 07:20:20 +00:00
|
|
|
|
2022-11-10 19:27:46 +00:00
|
|
|
class PriceBid(BaseModel):
|
|
|
|
price: str
|
|
|
|
liquidity: int
|
|
|
|
|
2022-11-10 07:20:20 +00:00
|
|
|
|
2022-11-10 19:27:46 +00:00
|
|
|
class PriceAsk(BaseModel):
|
|
|
|
price: str
|
|
|
|
liquidity: int
|
|
|
|
|
2022-11-10 07:20:20 +00:00
|
|
|
|
2022-11-10 19:27:46 +00:00
|
|
|
class PriceQuoteHomeConversionFactors(BaseModel):
|
|
|
|
positiveUnits: str
|
|
|
|
negativeUnits: str
|
|
|
|
|
2022-11-10 07:20:20 +00:00
|
|
|
|
2022-11-10 19:27:46 +00:00
|
|
|
class Price(BaseModel):
|
|
|
|
type: str
|
|
|
|
time: str
|
|
|
|
bids: list[PriceBid]
|
|
|
|
asks: list[PriceAsk]
|
|
|
|
closeoutBid: str
|
|
|
|
closeoutAsk: str
|
|
|
|
status: str
|
|
|
|
tradeable: bool
|
|
|
|
quoteHomeConversionFactors: PriceQuoteHomeConversionFactors
|
|
|
|
instrument: str
|
|
|
|
|
2022-11-10 07:20:20 +00:00
|
|
|
|
2022-11-10 19:27:46 +00:00
|
|
|
class PricingInfo(BaseModel):
|
|
|
|
time: str
|
|
|
|
prices: list[Price]
|
|
|
|
|
2022-11-10 07:20:20 +00:00
|
|
|
|
2022-11-10 19:27:46 +00:00
|
|
|
PricingInfoSchema = {
|
|
|
|
"time": "time",
|
|
|
|
"prices": (
|
|
|
|
"prices",
|
|
|
|
[
|
|
|
|
{
|
|
|
|
"type": "type",
|
|
|
|
"time": "time",
|
|
|
|
"bids": "bids",
|
|
|
|
"asks": "asks",
|
|
|
|
"closeoutBid": "closeoutBid",
|
|
|
|
"closeoutAsk": "closeoutAsk",
|
|
|
|
"status": "status",
|
|
|
|
"tradeable": "tradeable",
|
|
|
|
"quoteHomeConversionFactors": "quoteHomeConversionFactors",
|
|
|
|
"symbol": "instrument",
|
|
|
|
}
|
|
|
|
],
|
|
|
|
),
|
|
|
|
}
|