aboutsummaryrefslogtreecommitdiffstats
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/ops/__init__.py0
-rw-r--r--python/ops/__main__.py51
-rw-r--r--python/ops/file_gen.py272
-rw-r--r--python/ops/funds.py166
-rw-r--r--python/ops/headers.py935
-rw-r--r--python/ops/process_queue.py396
-rw-r--r--python/ops/product_loop.py33
-rw-r--r--python/ops/trade_dataclasses.py1812
8 files changed, 0 insertions, 3665 deletions
diff --git a/python/ops/__init__.py b/python/ops/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/python/ops/__init__.py
+++ /dev/null
diff --git a/python/ops/__main__.py b/python/ops/__main__.py
deleted file mode 100644
index 34445466..00000000
--- a/python/ops/__main__.py
+++ /dev/null
@@ -1,51 +0,0 @@
-import argparse
-import os
-
-from functools import partial
-from serenitas.analytics.bbg_helpers import init_bbg_session
-from serenitas.utils.pool import dawn_pool
-from serenitas.utils import get_redis_queue
-
-from .process_queue import process_indicative, process_upload, terminate_list
-
-os.environ["SERENITAS_APP_NAME"] = "process_queue"
-
-parser = argparse.ArgumentParser()
-parser.add_argument(
- "-n", "--no-upload", action="store_true", help="do not upload to Globeop"
-)
-args = parser.parse_args()
-r = get_redis_queue()
-with dawn_pool.connection() as conn, init_bbg_session() as session:
- for trade_type in [
- "cds",
- "swaption",
- "repo",
- "future",
- "wire",
- "spot",
- "fx_swap",
- "capfloor",
- ]:
- p_list = partial(
- process_indicative,
- trade_type=trade_type,
- upload=not args.no_upload,
- session=session,
- conn=conn,
- )
- r.transaction(p_list, trade_type)
- p_upload = partial(
- process_upload,
- trade_type=trade_type,
- upload=not args.no_upload,
- )
- r.transaction(p_upload, trade_type)
-
- for trade_type in ("cds", "swaption", "capfloor"):
- for fund in ("SERCGMAST", "BOWDST", "BRINKER"):
- key = f"{trade_type}_{fund}_termination"
- t_list = partial(
- terminate_list, key=key, upload=not args.no_upload, conn=conn
- )
- r.transaction(t_list, key)
diff --git a/python/ops/file_gen.py b/python/ops/file_gen.py
deleted file mode 100644
index 30fc509b..00000000
--- a/python/ops/file_gen.py
+++ /dev/null
@@ -1,272 +0,0 @@
-import datetime
-from serenitas.utils.misc import rename_keys
-
-from pyisda.date import previous_twentieth
-from quantlib.time.api import pydate_from_qldate, UnitedStates, Days, Date
-from serenitas.analytics.dates import bus_day
-
-
-def get_effective_date(d, swaption_type):
- if swaption_type == "CD_INDEX_OPTION":
- return previous_twentieth(d + datetime.timedelta(days=1))
- else:
- cal = UnitedStates()
- return pydate_from_qldate(cal.advance(Date.from_datetime(d), 2, Days))
-
-
-_client_name = {"SERCGMAST": "Serenitas", "BOWDST": "HEDGEMARK", "BRINKER": "LMCG"}
-
-
-def build_line(obj, trade_type="bond", fund="SERCGMAST"):
- obj["Client"] = _client_name[fund]
- # Bowdst Globeop has a special short name
- obj["fund"] = "BOS_PAT_BOWDOIN" if fund == "BOWDST" else fund
- obj["State"] = "Valid"
- rename_cols = {
- "fund": "Fund",
- "action": "Action",
- "dealid": "Deal Id",
- "folder": "Folder",
- "custodian": "Custodian",
- "cash_account": "Cash Account",
- "cp_code": "Counterparty",
- "identifier": "GlopeOp Security Identifier",
- "cusip": "CUSIP",
- "isin": "ISIN",
- "description": "Security Description",
- "accrued": "Accrued",
- "price": "Price",
- "faceamount": "FaceAmount",
- "trade_date": "Trade Date",
- "settle_date": "Settlement Date",
- "effective_date": "EffectiveDate",
- "maturity": "MaturityDate",
- "currency": "Currency",
- "fixed_rate": "FixedRate",
- "payment_rolldate": "PaymentRollDateConvention",
- "day_count": "DayCount",
- "protection": "Protection",
- "security_id": "UnderlyingSecurityId",
- "security_desc": "UnderlyingSecurityDescription",
- "upfront": "UpfrontFee",
- "upfront_settle_date": "UpfrontFeePayDate",
- "swap_type": "SwapType",
- "orig_attach": "AttachmentPoint",
- "orig_detach": "ExhaustionPoint",
- "clearing_facility": "Clearing Facility",
- "isda_definition": "ISDADefinition",
- "expiration_date": "ExpirationDate",
- "portfolio": "Portfolio",
- "settlement_type": "SettlementMode",
- "principal_payment": "PrincipalPayment",
- "accrued_payment": "AccruedPayment",
- "current_face": "CurrentFace",
- }
- rename_cols[
- "curr_notional" if fund in ("SERCGMAST", "BOWDST") else "notional"
- ] = "Notional"
- rename_keys(obj, rename_cols)
- if trade_type in ("bond", "swaption", "future"):
- obj["Transaction Indicator"] = "Buy" if obj["buysell"] else "Sell"
- if trade_type == "bond":
- obj["Deal Type"] = "MortgageDeal"
- obj["Portfolio"] = "MORTGAGES"
- obj["Delivery"] = "S"
- # zero coupon bond
- if obj["CUSIP"] != obj["GlopeOp Security Identifier"]:
- obj["CUSIP"] = None
- elif trade_type == "swaption":
- obj["Deal Type"] = "SwaptionDeal"
- obj["ExerciseType"] = "European"
- rename_keys(
- obj,
- {
- "Settlement Date": "PremiumSettlementDate",
- "notional": "Notional",
- "initial_margin_percentage": "InitialMarginPercentage",
- },
- )
- obj["PremiumSettlementAmount"] = (
- obj["Price"] * obj["Notional"] * obj.get("factor", 1.0) * 0.01
- )
- obj["PremiumSettlementCurrency"] = obj["Currency"]
- obj["RegenerateCashFlow"] = "N"
- for direction in ["Pay", "Receive"]:
- obj[direction + "MaturityDate"] = obj["MaturityDate"]
- obj[direction + "Currency"] = obj["Currency"]
- obj[direction + "Notional"] = obj["Notional"]
- obj[direction + "EffectiveDate"] = get_effective_date(
- obj["ExpirationDate"], obj["SwapType"]
- )
- if obj["SwapType"] == "CD_INDEX_OPTION":
- for direction in ["Pay", "Receive"]:
- obj[direction + "Daycount"] = "ACT/360"
- obj[direction + "Frequency"] = "Quarterly"
- obj[direction + "PaymentRollConvention"] = "Following"
-
- for leg_type in ["Receive", "Pay"]:
- obj[leg_type + "LegRateType"] = "Fixed"
- if obj["option_type"] == "PAYER":
- obj["ReceiveFixedRate"] = 0.0
- obj["PayFixedRate"] = obj["FixedRate"]
- elif obj["option_type"] == "RECEIVER":
- obj["PayFixedRate"] = 0.0
- obj["ReceiveFixedRate"] = obj["FixedRate"]
- elif obj["SwapType"] == "SWAPTION":
- for direction in ["Pay", "Receive"]:
- obj[direction + "PaymentRollConvention"] = "ModifiedFollowing"
- if obj["option_type"] == "RECEIVER":
- fixed, floating = "Receive", "Pay"
- else:
- fixed, floating = "Pay", "Receive"
- # fixed leg
- obj[fixed + "Frequency"] = "Yearly"
- obj[fixed + "Daycount"] = "ACT/360"
- obj[fixed + "FixedRate"] = obj["strike"]
- obj[fixed + "LegRateType"] = "Fixed"
- obj[fixed + "InterestCalcMethod"] = "Simple Interest"
- # floating leg
- obj[floating + "Frequency"] = "Yearly"
- obj[floating + "Daycount"] = "ACT/360"
- obj[floating + "LegRateType"] = "Float"
- obj[floating + "FloatRate"] = "SOFRINDX"
- obj[floating + "InterestCalcMethod"] = "Simple Interest"
-
- else:
- raise ValueError(
- "'SwapType' needs to be one of 'CD_INDEX_OPTION' or 'SWAPTION'"
- )
-
- obj["PremiumCurrency"] = obj["Currency"]
- if obj["InitialMarginPercentage"]:
- obj["InitialMarginCurrency"] = obj["Currency"]
- obj["UnderlyingInstrument"] = obj.pop("UnderlyingSecurityId")
- if obj["SwapType"] == "CD_INDEX_OPTION":
- obj["Strike"] = obj.pop("strike")
-
- elif trade_type == "cds":
- freq = {4: "Quarterly", 12: "Monthly"}
- obj["Deal Type"] = "CreditDefaultSwapDeal"
- obj["PaymentFrequency"] = freq[obj["frequency"]]
- obj["InitialMarginPercentage"] = obj.pop("initial_margin_percentage")
- if obj["InitialMarginPercentage"]:
- obj["InitialMarginCurrency"] = obj["Currency"]
- if obj["Clearing Facility"] is None:
- obj["Clearing Facility"] = "NOT CLEARED"
-
- elif trade_type == "future":
- obj["Deal Type"] = "FutureDeal"
- rename_keys(
- obj,
- {
- "commission": "Commission",
- "quantity": "Quantity",
- "swap_type": "Swap Type",
- "bbg_ticker": "Bloomberg Ticker",
- "Currency": "Trade Currency",
- "exchange": "Exchange",
- },
- )
- elif trade_type == "wire":
- obj["Deal Type"] = "CashFlowDeal"
- obj["Transaction Type"] = "Transfer"
- obj["Instrument Type"] = "Cashflow"
- obj["Settlement Date"] = obj["Trade Date"]
- strat_portfolio_map = {
- "IGOPTDEL": "OPTIONS",
- "COCSH": "OPTIONS",
- "IGINX": "TRANCHE",
- "BSPK": "TRANCHE",
- "TCSH": "TRANCHE",
- "SER_ITRXCURVE": "SERG__CURVE",
- "XCURVE": "SERG__CURVE",
- "M_CSH_CASH": "CASH",
- "CVECSH": "SERG__CURVE",
- "SER_ITRXCVCSH": "SERG__CURVE",
- }
- obj["Portfolio"] = strat_portfolio_map.get(obj["Folder"])
- rename_keys(obj, {"amount": "Amount"})
-
- elif trade_type == "spot":
- standard_settle = (obj["Trade Date"] + 2 * bus_day).date()
- if obj["Settlement Date"] > standard_settle:
- obj["Deal Type"] = "ForwardDeal"
- fx_rate = "Forward Rate"
- else:
- obj["Deal Type"] = "SpotDeal"
- fx_rate = "Spot Rate"
- rename_keys(
- obj,
- {
- "commission": "Commission",
- "commission_currency": "Commission Currency",
- "sell_currency": "Sell Currency",
- "sell_amount": "Sell Amount",
- "buy_currency": "Buy Currency",
- "buy_amount": "Buy Amount",
- "spot_rate": fx_rate,
- },
- )
- elif trade_type == "fx_swap":
- obj["Deal Type"] = "FxSwapDeal"
- obj["Action"] = "NEW"
- rename_keys(
- obj,
- {
- "near_rate": "Near Side Currency Rate",
- "near_settle_date": "Near Side Settlement Date",
- "near_buy_currency": "Near Side Buy Currency",
- "near_buy_amount": "Near Side Buy Amount",
- "near_sell_currency": "Near Side Sell Currency",
- "near_sell_amount": "Near Side Sell Amount",
- "far_rate": "Far Side Rate",
- "far_settle_date": "Far Side Settlement Date",
- "far_buy_currency": "Far Side Buy Currency",
- "far_buy_amount": "Far Side Buy Amount",
- "far_sell_currency": "Far Side Sell Currency",
- "far_sell_amount": "Far Side Sell Amount",
- },
- )
- elif trade_type == "repo":
- obj["Deal Type"] = "RepoDeal"
- obj["OpenRepo"] = "Y" if obj["open_repo"] else "N"
- rename_keys(
- obj,
- {
- "weighted_amount": "WeightedAmount",
- "repo_rate": "RepoRate",
- "transaction_indicator": "TransactionIndicator",
- },
- )
- elif trade_type == "capfloor":
- obj["Deal Type"] = "CapFloorDeal"
- obj["PaymentBDC"] = obj["bdc_convention"]
- obj["AccrualBDC"] = obj["bdc_convention"]
- obj["MaturityBDC"] = "NONE"
- obj["TransactionIndicator"] = "Buy" if obj["buysell"] else "Sell"
- # missing data : 'Adjusted', 'RollConvention', 'Calendar', 'Arrears', 'Collateralized', 'MaturityBDC'
- rename_keys(
- obj,
- {
- "comments": "Comments",
- "floating_rate_index_desc": "FloatingRateIndex",
- "cap_or_floor": "CapOrFloor",
- "amount": "Notional",
- "strike": "Strike",
- "value_date": "ValueDate",
- "expiration_date": "MaturityDate",
- "premium_percent": "PremiumPercent",
- "pricing_type": "PricingType",
- "payment_frequency": "PaymentFrequency",
- "fixing_frequency": "FixingFrequency",
- "day_count_convention": "Basis",
- "bdc_convention": "PaymentBDC",
- "payment_mode": "PaymentMode",
- "payment_at_beginning_or_end": "PaymentAtBeginningOrEnd",
- "initial_margin_percentage": "InitialMarginPercentage",
- "intial_margin_currency": "InitialMarginCurrency",
- "reset_lag": "ResetLag",
- "swap_type": "SwapType",
- },
- )
- return obj
diff --git a/python/ops/funds.py b/python/ops/funds.py
deleted file mode 100644
index 1b06ec35..00000000
--- a/python/ops/funds.py
+++ /dev/null
@@ -1,166 +0,0 @@
-import csv
-import datetime
-import pathlib
-from csv_headers.citco import GTL, GIL
-from serenitas.utils.remote import FtpClient, SftpClient
-from serenitas.utils.exchange import ExchangeMessage, FileAttachment
-from io import StringIO
-from pickle import dumps
-from typing import Tuple, Union
-from serenitas.utils.env import DAILY_DIR
-from .file_gen import build_line
-from .trade_dataclasses import DealKind
-from .headers import get_headers, MTM_HEADERS
-
-
-class Fund:
- staging_queue = []
- _registry = {}
- filepath_pattern = None
-
- def __class_getitem__(cls, fund_name: str):
- return cls._registry[fund_name]
-
- def __init_subclass__(cls, fund_name: str):
- cls.name = fund_name
- cls._registry[fund_name] = cls
-
- @classmethod
- def build_buffer(cls, trade_type):
- buf = StringIO()
- csvwriter = csv.writer(buf)
- cls.set_headers(trade_type)
- csvwriter.writerow(cls.headers)
- csvwriter.writerows(
- [[obj.get(h) for h in cls.headers] for obj in cls.staging_queue]
- )
- buf = buf.getvalue().encode()
- dest = cls.get_filepath(DAILY_DIR, trade_type)
- dest.parent.mkdir(exist_ok=True)
- dest.write_bytes(buf)
- return buf, dest
-
- @classmethod
- def set_headers(cls, trade_type):
- cls.headers = get_headers(trade_type, cls.name)
-
- @classmethod
- def stage(cls, trade, *, trade_type, **kwargs):
- cls.staging_queue.append(build_line(trade, trade_type, cls.name))
-
- @classmethod
- def get_filepath(
- cls,
- base_dir: pathlib.Path,
- trade_type: Union[str, Tuple[str, str]],
- ) -> pathlib.Path:
- d = {
- "bond": "Mortgages",
- "cds": "CreditDefaultSwapDeal",
- "swaption": "SwaptionDeal",
- "future": "Future",
- "wire": "CashFlowDeal",
- "spot": "SpotDeal",
- "fx_swap": "FxSwapDeal",
- "capfloor": "CapFloor",
- "repo": "RepoDeal",
- "iam": "IamDeal",
- "trs": "TRSDeal",
- "irs": "IRSDeal",
- }
- if cls is MTM:
- trade_tag = "TRN" if trade_type == "cds" else "CDISW"
- else:
- if isinstance(trade_type, tuple):
- trade_tag = d[trade_type[0]] + trade_type[1]
- else:
- trade_tag = d[trade_type]
-
- timestamp = datetime.datetime.now()
- return (
- base_dir
- / str(timestamp.date())
- / cls.filepath_pattern.format(timestamp=timestamp, trade_tag=trade_tag)
- )
-
-
-class Serenitas(Fund, fund_name="SERCGMAST"):
- filepath_pattern = "Serenitas.ALL.{timestamp:%Y%m%d.%H%M%S}.{trade_tag}.csv"
-
- @staticmethod
- def upload(buf, dest):
- ftp = FtpClient.from_creds("globeop", folder="incoming")
- ftp.put(buf, dest)
-
-
-class Brinker(Fund, fund_name="BRINKER"):
- filepath_pattern = "LMCG_BBH_SWAP_TRADES_P.{timestamp:%Y%m%d%H%M%S}.csv"
-
- @staticmethod
- def upload(buf, dest):
- sftp = SftpClient.from_creds("bbh")
- sftp.put(buf, dest)
-
-
-class Bowdst(Fund, fund_name="BOWDST"):
- filepath_pattern = "Bowdst.ALL.{timestamp:%Y%m%d.%H%M%S}.{trade_tag}.csv"
-
- @staticmethod
- def upload(buf, dest):
- sftp = SftpClient.from_creds("hm_globeop", folder="incoming")
- sftp.put(buf, dest)
- em = ExchangeMessage()
- recipients = ("hm-operations@bnymellon.com",)
- em.send_email(
- "Trade file",
- "",
- to_recipients=recipients,
- cc_recipients=("bowdoin-ops@lmcg.com",),
- attach=(FileAttachment(name=dest, content=buf),),
- )
-
-
-class Selene(Fund, fund_name="ISOSEL"):
- filepath_pattern = "innocap_serenitas_trades_{timestamp:%Y%m%d%H%M%S}.csv"
- headers = GTL
-
- @classmethod
- def set_headers(cls, trade_type):
- if trade_type == "product":
- cls.headers = GIL
- cls.filepath_pattern = "i.innocap_serenitas.{timestamp:%Y%m%d%H%M%S}.csv"
-
- @staticmethod
- def upload(buf, dest):
- sftp = SftpClient.from_creds("citco", folder="incoming")
- sftp.put(buf, dest)
-
- @classmethod
- def stage(cls, trade, *, trade_type, redis_pipeline, **kwargs):
- obj = DealKind[trade_type].from_dict(**trade)
- if (
- (trade_type not in ("cds", "irs", "swaption", "trs"))
- or (trade_type == "cds" and obj.attach is None)
- or obj.product.status == "Acknowledged"
- ):
- cls.staging_queue.append(obj.to_citco(trade["action"]))
- else:
- redis_pipeline.rpush("product_queue", dumps((trade_type, trade)))
-
-
-class MTM(Fund, fund_name="MTM"):
- filepath_pattern = "MTM.{timestamp:%Y%m%d.%H%M%S}.{trade_tag}.csv"
-
- @classmethod
- def set_headers(cls, trade_type):
- cls.headers = MTM_HEADERS[trade_type]
-
- @classmethod
- def stage(cls, trade, *, trade_type, **kwargs):
- obj = DealKind[trade_type].from_dict(**trade)
- cls.staging_queue.append(obj.to_markit())
-
- @staticmethod
- def upload(buf, dest):
- sftp = SftpClient.from_creds("mtm")
- sftp.put(buf, dest)
diff --git a/python/ops/headers.py b/python/ops/headers.py
deleted file mode 100644
index 5b1d54b6..00000000
--- a/python/ops/headers.py
+++ /dev/null
@@ -1,935 +0,0 @@
-from enum import Enum
-
-
-class DealType(Enum):
- Bond = "BOND"
- CDS = "CDX"
- Swaption = "SWAPTION"
- Termination = "TERM"
- Spot = "SPOT"
- FxSwap = "FXSWAP"
- Fx = "FX"
- TRS = "TRS"
- IRS = "IRS"
- TrancheProduct = "TRANCHEPRODUCT"
- SwaptionProduct = "SWAPTIONPRODUCT"
- IRSProduct = "IRSPRODUCT"
- TRSProduct = "TRSPRODUCT"
-
-
-HEADERS_PRE = [
- "Deal Type",
- "Deal Id",
- "Action",
- "Client",
- "Fund",
- "Portfolio",
- "Folder",
- "Custodian",
- "Cash Account",
- "Counterparty",
- "Comments",
- "State",
- "Trade Date",
-]
-
-HEADERS = {
- "bond": HEADERS_PRE
- + [
- "Settlement Date",
- "BrokerShortName",
- "GlopeOp Security Identifier",
- "CUSIP",
- "ISIN",
- "Sedol",
- "Reserved",
- "Reserved",
- "Security Description",
- "Transaction Indicator",
- "SubTransaction Indicator",
- "Quantity",
- "Price",
- "Commission",
- "Tax",
- "BlockId",
- "BlockAmount",
- "Reserved",
- "Reserved",
- "Accrued",
- "ClearingMode",
- "FaceAmount",
- "Reserved",
- "SettlementCurrency",
- "Reserved",
- "CrossCurrencyRate",
- "ClientReference",
- "Reserved",
- "SettlementAmount",
- "Yield",
- "TradeDateTimeStamp",
- "CpiRefRatio",
- "SettlementCurrencyHedge",
- "TradeDateFx",
- ],
- "cds": HEADERS_PRE
- + [
- "Reserved",
- "Reserved",
- "EffectiveDate",
- "MaturityDate",
- "Currency",
- "Notional",
- "FixedRate",
- "PaymentRollDateConvention",
- "DayCount",
- "PaymentFrequency",
- "FirstCouponRate",
- "FirstCouponDate",
- "ResetLag",
- "Liquidation",
- "LiquidationDate",
- "Protection",
- "UnderlyingSecurityId",
- "UnderlyingSecurityDescription",
- "CreditSpreadCurve",
- "CreditEvents",
- "RecoveryRate",
- "Settlement",
- "InitialMargin",
- "InitialMarginPercentage",
- "InitialMarginCurrency",
- "DiscountCurve",
- "ClientReference",
- "UpfrontFee",
- "UpfrontFeePayDate",
- "RegenerateCashFlow",
- "UpfrontFeeComment",
- "Executing Broker",
- "SwapType",
- "OnPrice",
- "OffPrice",
- "AttachmentPoint",
- "ExhaustionPoint",
- "Fees",
- "Fee Payment Dates",
- "Fee Comments",
- "Credit Event Occurred",
- "Calendar",
- "Clearing Facility",
- "Adjusted",
- "CcpTradeRef",
- "BlockId",
- "BlockAmount",
- "NettingId",
- "AnnouncementDate",
- "ExecTS",
- "DefaultProbability",
- "ClientMargin",
- "Factor",
- "ISDADefinition",
- ],
- "swaption": HEADERS_PRE
- + [
- "Reserved",
- "Reserved",
- "Reserved",
- "Notional",
- "PremiumSettlementDate",
- "ExpirationDate",
- "PremiumCurrency",
- "PercentageOfPremium",
- "ExerciseType",
- "Reserved",
- "SettlementMode",
- "SettlementRate",
- "Transaction Indicator",
- "InitialMargin",
- "InitialMarginPercentage",
- "InitialMarginCurrency",
- "ReceiveLegRateType",
- "ReceiveFloatRate",
- "ReceiveFirstCouponDate",
- "ReceiveFirstCouponRate",
- "ReceiveFixedRate",
- "ReceiveDaycount",
- "ReceiveFrequency",
- "ReceivePaymentRollConvention",
- "ReceiveEffectiveDate",
- "ReceiveMaturityDate",
- "ReceiveNotional",
- "ReceiveArrears",
- "ReceiveAdjusted",
- "ReceiveCompound",
- "ReceiveCurrency",
- "PayLegRateType",
- "PayFloatRate",
- "PayFirstCouponDate",
- "PayFirstCouponRate",
- "PayFixedRate",
- "PayDaycount",
- "PayFrequency",
- "PayPaymentRollConvention",
- "PayEffectiveDate",
- "PayMaturityDate",
- "PayNotional",
- "PayArrears",
- "PayAdjusted",
- "PayCompound",
- "PayCurrency",
- "RegenerateCashFlow",
- "GiveUpBroker",
- "ClientReference",
- "ReceiveDiscountCurve",
- "ReceiveForwardCurve",
- "PayDiscountCurve",
- "PayForwardCurve",
- "ReceiveFixingFrequency",
- "ReceiveInterestCalcMethod",
- "ReceiveCompoundAverageFrequency",
- "PayFixingFrequency",
- "PayInterestCalcMethod",
- "PayCompoundAverageFrequency",
- "SwapType",
- "AttachmentPoint",
- "ExhaustionPoint",
- "UnderlyingInstrument",
- "AssociatedDealType",
- "AssociatedDealId",
- "CounterpartyReference",
- "PremiumSettlementCurrency",
- "PremiumSettlementAmount",
- "ReceiveIMM Period",
- "PayIMMPeriod",
- "Reserved",
- "ClearingFacility",
- "Strike",
- "CcpTradeRef",
- "BreakClauseFrequency",
- "BlockId",
- "BlockAmount",
- "Cross Currency Premium Payment",
- "Premium Payment Amount",
- "Netting Id",
- "BreakClauseDate",
- ],
- "future": HEADERS_PRE
- + [
- "Settlement Date",
- "Reserved",
- "GlopeOp Security Identifier",
- "Reserved",
- "Reserved",
- "Reserved",
- "Bloomberg Ticker",
- "RIC",
- "Security Description",
- "Transaction Indicator",
- "SubTransaction Indicator",
- "Quantity",
- "Price",
- "Commission",
- "Tax",
- "VAT",
- "Trade Currency",
- "Reserved",
- "Reserved",
- "Broker Short Name",
- "MaturityDate",
- "Exchange",
- "Client Reference",
- "Swap Type",
- "Initial Margin",
- "Initial Margin Currency",
- "Future Event",
- "Commission Entries",
- "BlockId",
- "Block Amount",
- ],
- "wire": HEADERS_PRE
- + [
- "Settlement Date",
- "Reserved",
- "Reserved",
- "Currency",
- "Amount",
- "Associated Deal Type",
- "Associated Deal Id",
- "Transaction Type",
- "Instrument Type",
- "Yield",
- "Client Reference",
- "ClearingFacility",
- "Deal Function",
- "Reset Price",
- "Reset Date",
- "Ccp Trade Ref",
- "Margin Type",
- "Block Id",
- "Block Amount",
- ],
- "spot": HEADERS_PRE
- + [
- "Settlement Date",
- "Dealt Currency",
- "Spot Rate",
- "Forward Rate",
- "Buy Currency",
- "Buy Amount",
- "Sell Currency",
- "Sell Amount",
- "ClearingFees",
- "BlockId",
- "BlockAmount",
- "Commission Currency",
- "Commission",
- "Reserved",
- "AssociatedDealType",
- "AssociatedDealId",
- "BrokerShortName",
- "ClientReference",
- ],
- "fx_swap": HEADERS_PRE
- + [
- "Reserved",
- "Dealt Currency",
- "Currency Pair",
- "Near Side Currency Rate",
- "Near Side Settlement Date",
- "Near Side Buy Currency",
- "Near Side Buy Amount",
- "Near Side Sell Currency",
- "Near Side Sell Amount",
- "Reserved",
- "Far Side Rate",
- "Far Side Settlement Date",
- "Far Side Point",
- "Far Side Buy Currency",
- "Far Side Buy Amount",
- "Far Side Sell Currency",
- "Far Side Sell Amount",
- "Client Reference",
- "BrokerShortName",
- "CcpTradeRef",
- "BlockId",
- "BlockAmount",
- ],
- "repo": HEADERS_PRE
- + [
- "Settlement Date",
- "Broker",
- "GlopeOp Security Identifier",
- "CUSIP",
- "ISIN",
- "Sedol",
- "Reserved",
- "Reserved",
- "Security Description",
- "TransactionIndicator",
- "CurrentFactor",
- "Quantity",
- "Price",
- "Reserved",
- "Reserved",
- "Reserved",
- "Currency",
- "ExchangeRate",
- "Comments",
- "Reserved",
- "ExpirationDate",
- "Reserved",
- "WeightedAmount",
- "InterestCalcMethod",
- "DirtyPrice",
- "Haircut",
- "RepoRate",
- "OpenRepo",
- "CallNotice",
- "FaceAmount",
- "AccruedInterest",
- "Yield",
- "CouponTo",
- "DayCount",
- "ClearingMode",
- "SecurityType",
- "BrokerShortName",
- "ClientReference",
- "DateTimeStamp",
- ],
- "capfloor": HEADERS_PRE
- + [
- "Reserved",
- "Reserved",
- "FloatingRateIndex",
- "FloatingRateIndexDescription",
- "TransactionIndicator",
- "Reserved",
- "CapOrFloor",
- "Notional",
- "Strike",
- "ValueDate",
- "ExpirationDate",
- "PremiumPercent",
- "PremiumDate",
- "PricingType",
- "PaymentFrequency",
- "FixingFrequency",
- "DayCountConvention",
- "PaymentBDC",
- "Reserved",
- "PaymentAtBeginningOrEnd",
- "Commission",
- "FirstCouponDate",
- "InitialMargin",
- "InitialMarginPercent",
- "InitialMarginCurrency",
- "Reserved",
- "Reserved",
- "Reserved",
- "ResetLag",
- "Adjusted",
- "CashType",
- "BinaryFixedAmount",
- "BarrierPaymentAt",
- "KnockPeriod",
- "UpperBarrier",
- "LowerBarrier",
- "RebateUp",
- "RebateDown",
- "RebateSettlementLag",
- "ClientReference",
- "BrokerShortName",
- "CptyReference",
- "SwapType",
- "ClearingFacility",
- "CcpTradeRef",
- "BlockId",
- "BlockAmount",
- "Netting Id",
- "TradeDateTimeStamp",
- "AccrualBDC",
- "MaturityBDC",
- "RollConvention",
- "Calendar",
- "Arrears",
- "PaymentLag",
- "Reserved1",
- "InflationLag",
- "InflationReference",
- "SettlementCurrency",
- "Collateralized",
- "TradeDateFX",
- ],
- "termination": [
- "DealType",
- "DealId",
- "Action",
- "Client",
- "SubAction",
- "PartialTermination",
- "TerminationAmount",
- "TerminationDate",
- "FeesPaid",
- "FeesReceived",
- "DealFunction",
- "Reserved",
- "ClientReference",
- "TradeDate",
- "EffectiveDate",
- "FirstCouponDate",
- "FeePaymentDate",
- "SpecialInstructions",
- "AssignedCounterparty",
- "AssignmentFee",
- "AssignedFeeTradeDate",
- "AssignedFeeValueDate",
- "AssignedCustodian",
- "AssignedCashAccount",
- "Reserved",
- "FeeCurrency",
- "GoTradeId",
- "FeeComments",
- "ZeroOutInterestCashFlows",
- "Reserved",
- "Reserved",
- "Reserved",
- "Reserved",
- "Reserved",
- "Reserved",
- "Reserved",
- "InitialMargin",
- "InitialMarginCurrency",
- ],
- "trs": HEADERS_PRE
- + [
- "Reserved",
- "Reserved",
- "ReceiveLegRateType",
- "ReceiveUnderlyingType",
- "ReceiveUnderlyingSecurity",
- "ReceiveUnderlyingDescription",
- "ReceiveFloatRate",
- "ReceiveFirstCouponDate",
- "ReceiveFirstCouponRate",
- "ReceiveFixedRate",
- "ReceiveDaycount",
- "ReceiveFrequency",
- "ReceivePaymentBDC",
- "ReceiveEffectiveDate",
- "ReceiveMaturityDate",
- "ReceiveNotional",
- "ReceivePrice",
- "ReceiveArrears",
- "Reserved",
- "Reserved",
- "ReceiveCurrency",
- "Reserved",
- "ReceiveSpread",
- "PayLegRateType",
- "PayUnderlyingType",
- "PayUnderlyingSecurity",
- "PayUnderlyingDescription",
- "PayFloatRate",
- "PayFirstCouponDate",
- "PayFirstCouponRate",
- "PayFixedRate",
- "PayDaycount",
- "PayFrequency",
- "PayPaymentBDC",
- "PayEffectiveDate",
- "PayMaturityDate",
- "PayNotional",
- "PayPrice",
- "PayArrears",
- "Reserved",
- "Reserved",
- "PayCurrency",
- "Reserved",
- "PaySpread",
- "Reserved",
- "InitialMargin",
- "InitialMarginPercent",
- "InitialMarginCurrency",
- "ClientReference",
- "CcpTradeRef",
- "BlockId",
- "BlockAmount",
- "Netting Id",
- "ExchangeRate",
- "ReceiveQuantity",
- "PayQuantity",
- "ReceiveAccrued",
- "PayAccrued",
- "ReceiveNotionalExchange",
- "PayNotionalExchange",
- "ReceiveResetLag",
- "PayResetLag",
- "Reserved",
- "Reserved",
- "Reserved",
- "Reserved",
- "ReceiveCalendar",
- "PayCalendar",
- "ReceiveInterestCalcMethod",
- "PayInterestCalcMethod",
- "ReceiveCompoundAverageFrequency",
- "PayCompoundAverageFrequency",
- "ReceiveFixingFrequency",
- "PayFixingFrequency",
- "ReceiveStubLocation",
- "ReceiveBeginFloatRate1",
- "ReceiveBeginFloatRate2",
- "ReceiveEndFloatRate1",
- "ReceiveEndFloatRate2",
- "PayStubLocation",
- "PayBeginFloatRate1",
- "PayBeginFloatRate2",
- "PayEndFloatRate1",
- "PayEndFloatRate2",
- "Fees",
- "Fee Payment Dates",
- "Fee Comments",
- "ExecutionDateTimeStamp",
- "FeeTypes",
- "FeeCurrencies",
- "ReceivePaymentAt",
- "PayPaymentAt",
- "SwapType",
- "Reserved1",
- "ReceiveAccrualBDC",
- "PayAccrualBDC",
- "ReceiveMaturityBDC",
- "PayMaturityBDC",
- "ReceiveRollConvention",
- "PayRollConvention",
- "ReceivePaymentLag",
- "PayPaymentLag",
- "ReceiveSettlementCurrency",
- "PaySettlementCurrency",
- "Collateralized",
- "TradeDateFX",
- ],
- "irs": HEADERS_PRE
- + [
- "Reserved",
- "Reserved",
- "ReceiveLegRateType",
- "ReceiveFloatRate",
- "ReceiveFirstCouponDate",
- "ReceiveFirstCouponRate",
- "ReceiveFixedRate",
- "ReceiveDaycount",
- "ReceiveFrequency",
- "ReceivePaymentBDC",
- "ReceiveEffectiveDate",
- "ReceiveMaturityDate",
- "ReceiveNotional",
- "ReceiveResetArrears",
- "Reserved",
- "Reserved",
- "ReceiveCurrency",
- "Reserved",
- "PayLegRateType",
- "PayFloatRate",
- "PayFirstCouponDate",
- "PayFirstCouponRate",
- "PayFixedRate",
- "PayDaycount",
- "PayFrequency",
- "PayPaymentBDC",
- "PayEffectiveDate",
- "PayMaturityDate",
- "PayNotional",
- "PayResetArrears",
- "Reserved",
- "Reserved",
- "PayCurrency",
- "Reserved",
- "InitialMargin",
- "InitialMarginPercentage",
- "InitialMarginCurrency",
- "CalendarPay",
- "CalendarReceive",
- "Reserved",
- "ReceiveSpread",
- "ReceiveFixingFrequency",
- "ReceiveInterestCalcMethod",
- "Reserved",
- "PaySpread",
- "PayFixingFrequency",
- "PayInterestCalcMethod",
- "Reserved",
- "GiveUpCounterparty",
- "ReceiveStubLocation",
- "ReceiveBeginFloatRate1",
- "ReceiveBeginFloatRate2",
- "ReceiveEndFloatRate1",
- "ReceiveEndFloatRate2",
- "PayStubLocation",
- "PayBeginFloatRate1",
- "PayBeginFloatRate2",
- "PayEndFloatRate1",
- "PayEndFloatRate2",
- "Reserved",
- "Reserved",
- "SwapType",
- "Reserved",
- "ClientReference",
- "Reserved",
- "Reserved",
- "Reserved",
- "Reserved",
- "Reserved",
- "Reserved",
- "ReceiveResetLag",
- "PayResetLag",
- "ReceiveExchangeAmount",
- "PayExchangeAmount",
- "AssociatedDealType",
- "AssociatedDealId",
- "ClearingFacility",
- "CcpTradeRef",
- "BreakClauseFrequency",
- "BlockId",
- "BlockAmount",
- "UpfrontFee",
- "UpfrontFeePaydate",
- "UpFrontFeeComments",
- "UpfrontFeeCurrency ",
- "Netting Id",
- "BreakClauseDate",
- "CashFlowStubType",
- "IndexLevel",
- "ExecutionDateTimeStamp",
- "ReceivePaymentLag",
- "PayPaymentLag",
- "ReceiveRateMultiplier",
- "PayRateMultiplier",
- "ReceiveRateCap",
- "PayRateCap",
- "ReceiveRateFloor",
- "PayRateFloor",
- "ReceiveRollConvention",
- "PayRollConvention",
- "ReceiveAccrualBDC",
- "PayAccrualBDC",
- "ReceiveMaturityBDC",
- "PayMaturityBDC",
- "ReceivePaymentAt",
- "PayPaymentAt",
- "ReceiveClientMargin",
- "PayClientMargin",
- "Reserved1",
- "ReceiveRateCutOff",
- "PayRateCutOff",
- "InflationLag",
- "InflationReference",
- "ReceiveSettlementCurrency",
- "PaySettlementCurrency",
- "CounterpartyReference",
- "ReceiveInflationReference",
- "PayInflationReference",
- "Collateralized",
- "InitialFXRate",
- "TradeDateFX",
- ],
- "iam": HEADERS_PRE
- + [
- "SettlementDate",
- "Reserved",
- "InstrumentType",
- "ExpirationDate",
- "CallNoticeIndicator",
- "TransactionIndicator",
- "StartMoney",
- "Currency",
- "Rate",
- "Commission",
- "DealFunction",
- "FromAccount",
- "ClientReference",
- "Basis",
- "MarginType",
- "ClearingFacility" "CcpTradeRef",
- "BlockId",
- "BlockAmount",
- "ExecutionDateTimeStamp",
- "Collateralized",
- "TradeDateFX",
- ],
-}
-
-MTM_HEADERS = {
- "cds": [
- "Swap ID",
- "Allocation ID",
- "Description",
- "Broker Id",
- "DTCC CounterParty ID",
- "Trade ID",
- "Trade Date",
- "Effective Date",
- "Settle Date",
- "Maturity Date",
- "Account Abbreviation",
- "1st Leg Notional",
- "Currency Code",
- "1st Leg Rate",
- "Initial Payment",
- "Initial Payment Currency",
- "Original Issue Date",
- "Interest Payment Method Description",
- "First Payment Date",
- "Product Type",
- "Product Sub Type",
- "Transaction Type",
- "Protection",
- "Transaction Code",
- "Remaining Party",
- "DTCC Remaining CounterParty ID",
- "Independent Amount (%)",
- "Independent Amount ($)",
- "RED",
- "Issuer Name",
- "Settlement Amount",
- "Trader",
- "Executing Broker",
- "Dealer Trade ID",
- "Notes",
- "Parent Transaction Code",
- "Parent Trade Date",
- "Parent Notional",
- "Parent Currency Code",
- "Parent Net Amount",
- "Parent Effective Date",
- "Parent First Payment Date",
- "Parent Settle Date",
- "ComplianceHubAction",
- "DTCC Ineligible",
- "Master Document Date",
- "Master Document Version",
- "Include Contractual Supplement",
- "Contractual Supplement",
- "Supplement Date",
- "Entity Matrix",
- "Entity Matrix Date",
- "Modified Equity Delivery",
- "Calculation Agent Business Center",
- "Calculation Agent",
- "Attachment Point",
- "Exhaustion Point",
- "Strategy",
- "First Payment Period Accrual Start Date",
- "TieOut Ineligible",
- "Electronic Consent Ineligible",
- "External OMS ID",
- "Independent Amount Currency",
- "Independent Amount Payer",
- "Trade Revision",
- "Alternate Swap ID",
- "Alternate Trade ID",
- "Definitions Type",
- ],
- "swaption": [
- "Swap ID",
- "Broker Id",
- "Trade ID",
- "Trade Date",
- "Settle Date",
- "Supplement Date",
- "Supplement 2 Date",
- "Maturity Date",
- "Account Abbreviation",
- "1st Leg Notional",
- "Currency Code",
- "1st Leg Rate",
- "Initial Payment Currency",
- "Initial Payment",
- "Product Type",
- "Transaction Type",
- "Transaction Code",
- "Independent Amount (%)",
- "RED",
- "Issuer Name",
- "Entity Matrix",
- "Definitions Type",
- "Swaption Expiration Date",
- "Strike Price",
- "Swaption Settlement Type",
- "Master Document Date",
- "OptionBuySellIndicator",
- "Clearing House",
- "Protection",
- "Swaption Quotation Rate Type",
- "Effective Date",
- ],
- "termination": [
- "Swap ID",
- "Allocation ID",
- "Description",
- "Broker Id",
- "DTCC CounterParty ID",
- "Trade ID",
- "Trade Date",
- "Effective Date",
- "Settle Date",
- "Maturity Date",
- "Account Abbreviation",
- "1st Leg Notional",
- "Currency Code",
- "1st Leg Rate",
- "Initial Payment",
- "Initial Payment Currency",
- "Payment Frequency Description",
- "Original Issue Date",
- "Interest Payment Method Description",
- "First Payment Date",
- "Product Type",
- "Product Sub Type",
- "Transaction Type",
- "Protection",
- "Transaction Code",
- "Remaining Party",
- "DTCC Remaining CounterParty ID",
- ],
- "trs": [
- "Swap ID",
- "Allocation ID",
- "Description ",
- "Broker Id",
- "DTCC CounterParty ID",
- "Trade ID",
- "Trade Date",
- "Effective Date",
- "Settle Date",
- "Maturity Date",
- "Account Abbreviation",
- "1st Leg Notional",
- "Currency Code",
- "Initial Payment",
- "Initial Payment Currency",
- "Original Issue Date",
- "Interest Payment Method Description",
- "Product Type",
- "Product Sub Type",
- "Transaction Type",
- "Protection",
- "Transaction Code",
- "Remaining Party",
- "DTCC Remaining CounterParty ID",
- "Independent Amount (%)",
- "Independent Amount ($)",
- "RED",
- "Issuer Name",
- "Settlement Amount",
- "Trader",
- "Dealer Trade ID",
- "Notes",
- "Parent Transaction Code",
- "Parent Trade Date",
- "Parent Notional",
- "Parent Currency Code",
- "Parent Net Amount",
- "Parent Effective Date",
- "Parent First Payment Date",
- "Parent Settle Date",
- "ComplianceHubAction",
- "DTCC Ineligible",
- "Master Document Date",
- "Master Document Type",
- "Master Document Version",
- "",
- "",
- "Annex Date",
- "Supplement Date",
- "Documentation Type",
- "Calculation Agent Business Center",
- "",
- "Strategy",
- "Electronic Consent Ineligible",
- "External OMS ID",
- "Traded Rate/Price",
- "Independent Amount Currency",
- "Independent Amount Payer",
- "Trade Revision",
- "Alternate Swap ID",
- "Alternate Trade ID",
- "Definitions Type",
- "Initial Fixing Amount",
- "2nd Leg Index",
- "2nd Leg Spread",
- "2nd Leg Initial Floating Rate",
- ],
-}
-
-
-def get_headers(trade_type, fund):
- headers = HEADERS[trade_type]
- if fund == "BOWDST":
- if trade_type == "bond":
- return headers + ["PrincipalPayment", "AccruedPayment", "CurrentFace"]
- elif trade_type == "swaption":
- return headers + ["OptionType"]
- else:
- return headers
- else:
- return headers
diff --git a/python/ops/process_queue.py b/python/ops/process_queue.py
deleted file mode 100644
index 2b1f82c2..00000000
--- a/python/ops/process_queue.py
+++ /dev/null
@@ -1,396 +0,0 @@
-import blpapi
-import logging
-import psycopg
-import pathlib
-import re
-import redis
-import sys
-
-from serenitas.analytics.api import CreditIndex
-
-try:
- from serenitas.utils.env import DAILY_DIR
-except KeyError:
- sys.exit("Please set path of daily directory in 'SERENITAS_DAILY_DIR'")
-
-from collections import defaultdict
-from pickle import dumps, loads
-from serenitas.analytics.bbg_helpers import retrieve_data
-
-from tabulate import tabulate
-from .funds import Fund
-from .trade_dataclasses import DealKind
-
-
-def groupby(p: redis.client.Pipeline, key: str, trade_key: str):
- d = defaultdict(list)
- for buf in p.lrange(key, 0, -1):
- trade = loads(buf)
- d[trade[trade_key]].append(trade)
- return d
-
-
-def get_trades(p: redis.client.Pipeline, key: str):
- for tradeid, trades in groupby(p, key, "id").items():
- if len(trades) == 1:
- yield trades[0]
- else:
- if trades[-1]["action"] == "CANCEL":
- continue
- if trades[0]["action"] == "NEW":
- trades[-1]["action"] = "NEW"
- yield trades[-1]
- if trades[-1]["action"] == "UPDATE":
- yield trades[-1]
-
-
-def process_indicative(
- p: redis.client.Pipeline,
- trade_type: str,
- upload: bool,
- session: blpapi.session.Session,
- conn: psycopg.Connection,
-) -> None:
- process_fun = globals().get(
- f"{trade_type}_trade_process", lambda conn, session, trade: trade
- )
- mtm = Fund["MTM"]
- for trade in get_trades(p, trade_type):
- process_fun(conn, session, trade)
- fund = trade["fund"]
- if trade.get("upload", True) and (
- fund in ("SERCGMAST", "BOWDST") or trade_type in ("cds", "swaption")
- ):
- p.rpush(f"{trade_type}_upload", dumps(trade))
- if trade.get("swap_type", None) in (
- "CD_INDEX_OPTION",
- "CD_INDEX_TRANCHE",
- "BESPOKE",
- ):
- mtm.stage(trade, trade_type=trade_type)
- if mtm.staging_queue:
- buf, dest = mtm.build_buffer(trade_type)
- mtm.upload(buf, dest.name)
- mtm.staging_queue.clear()
- p.delete(trade_type)
-
-
-def process_upload(
- p: redis.client.Pipeline,
- trade_type: str,
- upload: bool,
-) -> None:
- key = f"{trade_type}_upload"
- for fund_name, l in groupby(p, key, "fund").items():
- fund = Fund[fund_name]()
- for trade in l:
- fund.stage(trade, trade_type=trade_type, redis_pipeline=p)
- buf, dest = fund.build_buffer(trade_type)
- if upload:
- fund.upload(buf, dest.name)
- fund.staging_queue.clear()
- p.delete(key)
-
-
-def terminate_list(
- p: redis.client.Pipeline,
- key: str,
- upload: bool,
- conn: psycopg.connection,
- base_dir: pathlib.Path = DAILY_DIR,
-):
- trade_type, fund, _ = key.split("_")
- mtm = Fund["MTM"]
- f = Fund[fund]()
- for term in p.lrange(key, 0, -1):
- obj = DealKind["termination"].from_dict(**loads(term))
- mtm.staging_queue.append(obj.to_markit())
- f.staging_queue.append(obj.to_globeop())
- if mtm.staging_queue:
- buf, dest = mtm.build_buffer(trade_type)
- mtm.upload(buf, dest.name)
- mtm.staging_queue.clear()
- if upload and f.staging_queue:
- buf, dest = f.build_buffer((trade_type, "A"))
- f.upload(buf, dest.name)
- p.delete(key)
-
-
-def get_bbg_data(
- conn,
- session,
- identifier,
- cusip=None,
- isin=None,
- settle_date=None,
- asset_class=None,
- **kwargs,
-):
- fields = ["MTG_FACTOR_SET_DT", "INT_ACC", "ISSUER"]
- fields_dict = {
- "Mtge": ["MTG_FACE_AMT", "START_ACC_DT"],
- "Corp": ["AMT_ISSUED", "PREV_CPN_DT"],
- }
- with conn.cursor() as c:
- c.execute(
- "SELECT identifier FROM securities WHERE identifier=%s", (identifier,)
- )
- if not c.fetchone():
- fields += [
- "MATURITY",
- "CRNCY",
- "NAME",
- "FLOATER",
- "FLT_SPREAD",
- "CPN",
- "CPN_TYP",
- "CPN_FREQ",
- "FIRST_CPN_DT",
- "MTG_PAY_DELAY",
- "DAY_CNT_DES",
- "NOMINAL_PAYMENT_DAY",
- "ISSUE_DT",
- "RESET_IDX",
- "ID_BB_GLOBAL",
- ]
-
- cusip_or_isin = cusip or isin
- for bbg_type in ["Mtge", "Corp"]:
- bbg_id = cusip_or_isin + " " + bbg_type
- data = retrieve_data(
- session,
- [bbg_id],
- fields + fields_dict[bbg_type],
- overrides={"SETTLE_DT": settle_date} if settle_date else None,
- )
- if data[bbg_id]:
- break
- else:
- logging.error(f"{cusip_or_isin} not in bloomberg")
- return
-
- bbg_data = data[bbg_id]
- if bbg_data.get("MTG_FACTOR_SET_DT", 0) == 0:
- bbg_data["MTG_FACTOR_SET_DT"] = 1
- bbg_data["INT_ACC"] = 0
- if len(fields) > 3: # we don't have the data in the securities table
- sql_fields = [
- "identifier",
- "cusip",
- "isin",
- "description",
- "face_amount",
- "maturity",
- "floater",
- "spread",
- "coupon",
- "frequency",
- "day_count",
- "first_coupon_date",
- "pay_delay",
- "currency",
- "bbg_type",
- "asset_class",
- "start_accrued_date",
- "issuer",
- "reset_index",
- "coupon_type",
- "payment_day",
- "issue_date",
- "figi",
- ]
- placeholders = ",".join(["%s"] * len(sql_fields))
- columns = ",".join(sql_fields)
-
- sqlstr = (
- f"INSERT INTO securities({columns}) VALUES({placeholders}) "
- "ON CONFLICT (identifier) DO NOTHING"
- )
- isfloater = bbg_data["FLOATER"] == "Y"
- pay_delay = bbg_data.get("MTG_PAY_DELAY", 0)
- day_count = bbg_data.get("DAY_CNT_DES")
- if m := re.match(r"[^(\s]+", day_count):
- day_count = m.group(0)
- if isinstance(pay_delay, str):
- pay_delay = int(pay_delay.split(" ")[0])
- with conn.cursor() as c:
- c.execute(
- sqlstr,
- (
- identifier,
- cusip,
- isin,
- bbg_data["NAME"],
- bbg_data.get("MTG_FACE_AMT") or bbg_data.get("AMT_ISSUED"),
- bbg_data.get("MATURITY"),
- isfloater,
- bbg_data.get("FLT_SPREAD") if isfloater else None,
- bbg_data.get("CPN") if not isfloater else None,
- bbg_data.get("CPN_FREQ"),
- day_count,
- bbg_data.get("FIRST_CPN_DT"),
- pay_delay,
- bbg_data.get("CRNCY"),
- bbg_type,
- asset_class,
- bbg_data.get("START_ACC_DT") or bbg_data.get("PREV_CPN_DT"),
- bbg_data["ISSUER"],
- bbg_data.get("RESET_IDX"),
- bbg_data["CPN_TYP"],
- bbg_data["NOMINAL_PAYMENT_DAY"],
- bbg_data["ISSUE_DT"],
- bbg_data["ID_BB_GLOBAL"],
- ),
- )
- conn.commit()
- return bbg_data
-
-
-def bond_trade_process(conn, session, trade):
- bbg_data = get_bbg_data(conn, session, **trade)
- currentface = trade["CurrentFace"] = (
- trade["faceamount"] * bbg_data["MTG_FACTOR_SET_DT"]
- )
- accrued_payment = trade["AccruedPayment"] = (
- bbg_data["INT_ACC"] * currentface / 100.0
- )
- principal_payment = trade["PrincipalPayment"] = currentface * trade["price"] / 100.0
- if trade["accrued"] is None:
- trade["accrued"] = bbg_data["INT_ACC"]
- else:
- if trade["accrued"] != bbg_data["INT_ACC"]:
- logging.error(
- f"{trade['accrued']} does not match bbg amount of {bbg_data['INT_ACC']}"
- )
-
- with conn.cursor() as c:
- c.execute(
- "UPDATE bonds SET principal_payment = %s, accrued_payment = %s, accrued=%s "
- "WHERE id = %s",
- (principal_payment, accrued_payment, trade["accrued"], int(trade["id"])),
- )
- # mark it at buy price
- if trade["buysell"]:
- sqlstr = "INSERT INTO marks VALUES(%s, %s, %s) ON CONFLICT DO NOTHING"
- with conn.cursor() as c:
- c.execute(
- sqlstr, (trade["trade_date"], trade["identifier"], trade["price"])
- )
- conn.commit()
- return trade
-
-
-def is_tranche_trade(trade):
- return trade["swap_type"] in ("CD_INDEX_TRANCHE", "BESPOKE")
-
-
-def swaption_trade_process(conn, session, trade):
- sqlstr = (
- "SELECT indexfactor/100 FROM index_version "
- "WHERE redindexcode=%(security_id)s"
- )
- try:
- with conn.cursor() as c:
- c.execute(sqlstr, trade)
- (factor,) = c.fetchone()
- except ValueError as e:
- logging.error(e)
- return trade
- except TypeError:
- # factor missing, probably IR swaption
- pass
- else:
- trade["factor"] = factor
- finally:
- if trade["option_type"] == "RECEIVER":
- trade["OptionType"] = "Call"
- elif trade["option_type"] == "PAYER":
- trade["OptionType"] = "Put"
- return trade
-
-
-def cds_trade_process(conn, session, trade):
- sqlstr = (
- "SELECT indexfactor/100 FROM index_version "
- "WHERE redindexcode=%(security_id)s"
- )
- try:
- with conn.cursor() as c:
- c.execute(sqlstr, trade)
- (factor,) = c.fetchone()
- except ValueError:
- bbg_data = get_bbg_data(
- conn,
- session,
- trade["security_id"],
- isin=trade["security_id"],
- asset_class="Subprime",
- )
-
- factor = bbg_data["MTG_FACTOR_SET_DT"]
- if is_tranche_trade(trade):
- tranche_factor = (trade["attach"] - trade["detach"]) / (
- trade["orig_attach"] - trade["orig_detach"]
- )
- trade["curr_notional"] = trade["notional"] * tranche_factor
- trade["Factor"] = tranche_factor
- else:
- trade["curr_notional"] = trade["notional"] * factor
- trade["Factor"] = factor
- if trade["upfront"]:
- return trade
- index = CreditIndex(
- redcode=trade["security_id"],
- maturity=trade["maturity"],
- notional=trade["notional"],
- value_date=trade["trade_date"],
- )
- index.direction = trade["protection"]
- with conn.cursor() as c:
- if trade["traded_level"]:
- if not is_tranche_trade(trade):
- index.ref = float(trade["traded_level"])
- trade["upfront"] = -index.pv
- else:
- accrued = index._accrued * trade["fixed_rate"]
- match index.index_type:
- case "HY":
- dirty_price = float(trade["traded_level"]) + accrued
- trade["upfront"] = (
- -(100 - dirty_price)
- * index.notional
- * trade["Factor"]
- * 0.01
- )
- case "EU" | "XO" if trade["orig_attach"] in (6, 12, 35):
- if trade["orig_attach"] == 6:
- index.recovery = 0.0
- index.spread = float(trade["traded_level"])
- trade["upfront"] = (
- -index._pv * trade["notional"] * trade["Factor"]
- )
- case _:
- dirty_protection = float(trade["traded_level"]) - accrued
- trade["upfront"] = (
- -dirty_protection * index.notional * trade["Factor"] * 0.01
- )
- c.execute(
- "UPDATE cds SET upfront=%s WHERE dealid=%s",
- (trade["upfront"], trade["dealid"]),
- )
-
- else:
- index.pv = -trade["upfront"]
- trade["traded_level"] = index.ref
- c.execute(
- "UPDATE cds SET traded_level=%s WHERE dealid=%s",
- (trade["traded_level"], trade["dealid"]),
- )
- conn.commit()
- return trade
-
-
-def print_trade(trade):
- d = trade.copy()
- d["buysell"] = "Buy" if d["buysell"] else "Sell"
- return tabulate((k, v) for k, v in d.items())
diff --git a/python/ops/product_loop.py b/python/ops/product_loop.py
deleted file mode 100644
index 58f7984c..00000000
--- a/python/ops/product_loop.py
+++ /dev/null
@@ -1,33 +0,0 @@
-from serenitas.utils import get_redis_queue
-from trade_dataclasses import DealKind
-from pickle import loads
-from .funds import Selene
-
-
-def upload_products():
- selene = Selene()
- cache = set()
- while True:
- pickle = q.lpop("product_queue")
- trade_type, trade = loads(pickle)
- if (h := hash(trade)) in cache: # we've gone full circle
- break
- else:
- obj = DealKind[trade_type].from_dict(**trade)
- product = obj.product
- if product.status == "Pending":
- q.rpush("product_queue", pickle)
- selene.staging_queue.append(product.to_citco())
- _cache |= h
- buf, dest = selene.build_buffer()
- selene.upload(buf, dest.name)
-
-
-async def gather_product():
- loop = asynctio.get_running_loop()
- end_time = loop.time() + 300
- while True:
- if loop.time() >= end_time:
- do_something()
- end_time = loop.time() + 300
- await asyncio.sleep(1)
diff --git a/python/ops/trade_dataclasses.py b/python/ops/trade_dataclasses.py
deleted file mode 100644
index 862c57b1..00000000
--- a/python/ops/trade_dataclasses.py
+++ /dev/null
@@ -1,1812 +0,0 @@
-from dataclasses import dataclass, field, fields, Field
-from enum import Enum
-from io import StringIO
-from .headers import DealType
-from typing import ClassVar, Tuple, Union
-from decimal import Decimal
-from typing import Literal
-import csv
-import datetime
-from psycopg.types.numeric import Int2BinaryDumper
-from psycopg import adapters
-from serenitas.analytics.dates import (
- next_business_day,
- previous_twentieth,
- adjust_next_business_day,
- prev_business_day,
-)
-from serenitas.utils.db2 import dbconn
-from serenitas.utils.env import DAILY_DIR
-from serenitas.utils.remote import FtpClient, SftpClient
-from lru import LRU
-
-from psycopg.errors import UniqueViolation
-import logging
-import warnings
-
-
-logger = logging.getLogger(__name__)
-Fund = Literal["SERCGMAST", "BRINKER", "BOWDST", "ISOSEL"]
-Portfolio = Literal[
- "OPTIONS", "IR", "MORTGAGES", "CURVE", "TRANCHE", "CLO", "HEDGE_MAC"
-] # deprecated IG, HY, STRUCTURED
-
-Status = Literal["Pending", "Submitted", "Acknowledged", "Failed"]
-_funds = {"BAML": "SERCGMAST", "GS": "BOWDST", "WF": "SERCGMAST"}
-_fcms = {
- "Bank of America, N.A.": "BAML",
- "Goldman Sachs": "GS",
- "BOA": "BAML",
- "GOLD": "GS",
- "Wells Fargo Secs": "WF",
-}
-
-_client_name = {"SERCGMAST": "Serenitas", "BOWDST": "HEDGEMARK", "BRINKER": "LMCG"}
-
-
-class BusDayConvention(str, Enum):
- modified_following = "Modified Following"
- following = "Following"
- modified_preceding = "Modified Preceding"
- second_day_after = "Second-Day-After"
- end_of_month = "End-of-Month"
-
-
-DayCount = Literal["ACT/360", "ACT/ACT", "30/360", "ACT/365"]
-
-IsdaDoc = Literal["ISDA2014", "ISDA2003Cred"]
-
-
-class Frequency(Enum):
- Quarterly = 4
- Monthly = 12
-
-
-Ccy = Literal["USD", "CAD", "EUR", "YEN"]
-
-
-SwapType = Literal[
- "CD_INDEX", "CD_INDEX_TRANCHE", "CD_BASKET_TRANCHE", "ABS_CDS", "BESPOKE"
-]
-
-OptionType = Literal["RECEIVER", "PAYER"]
-ClearingFacility = Literal["ICE-CREDIT", "NOT CLEARED"]
-CdsStrat = Literal[
- "HEDGE_CSO",
- "HEDGE_CLO",
- "HEDGE_MAC",
- "HEDGE_MBS",
- "SER_IGSNR",
- "SER_IGMEZ",
- "SER_IGEQY",
- "SER_IGINX",
- "SER_HYSNR",
- "SER_HYMEZ",
- "SER_HYEQY",
- "SER_HYINX",
- "SER_HYCURVE",
- "SER_IGCURVE",
- "SER_ITRXCURVE",
- "XCURVE",
- "MBSCDS",
- "IGOPTDEL",
- "HYOPTDEL",
- "HYEQY",
- "HYMEZ",
- "HYSNR",
- "HYINX",
- "IGEQY",
- "IGMEZ",
- "IGSNR",
- "IGINX",
- "XOEQY",
- "XOMEZ",
- "XOINX",
- "EUEQY",
- "EUMEZ",
- "EUSNR",
- "EUINX",
- "BSPK",
- "*",
-]
-BondStrat = Literal[
- "M_STR_MAV",
- "M_STR_MEZZ",
- "CSO_TRANCH",
- "M_CLO_BB20",
- "M_CLO_AAA",
- "M_CLO_BBB",
- "M_MTG_IO",
- "M_MTG_THRU",
- "M_MTG_GOOD",
- "M_MTG_B4PR",
- "M_MTG_RW",
- "M_MTG_FP",
- "M_MTG_LMG",
- "M_MTG_SD",
- "M_MTG_PR",
- "M_MTG_CRT_SD",
- "CRT_LD",
- "CRT_LD_JNR",
- "CRT_SD",
- "IGNORE",
- "MTG_REPO",
-]
-
-SwaptionStrat = Literal[
- "IGPAYER",
- "IGREC",
- "HYPAYER",
- "HYREC",
- "STEEP",
- "DV01",
- "HEDGE_MAC",
-]
-
-SpotStrat = Literal[
- "M_STR_MAV", "M_STR_MEZZ", "SER_IRTXCURVE", "M_CSH_CASH", "TCSH", "*"
-]
-AssetClass = Literal["CSO", "Subprime", "CLO", "CRT"]
-
-
-@dataclass
-class Counterparty:
- name: str
-
-
-class FrequencyDumper(Int2BinaryDumper):
- def dump(self, f):
- return super().dump(f.value)
-
-
-adapters.register_dumper(Frequency, FrequencyDumper)
-
-
-def desc_str(index_type, series, tenor):
- if index_type in ("IG", "HY", "HYBB"):
- return f"CDX {index_type} CDSI S{series} {tenor}Y"
- elif index_type == "XO":
- return f"ITRX XOVER CDSI S{series} {tenor}Y"
- elif index_type == "EU":
- return f"ITRX EUR CDSI S{series} {tenor}Y"
-
-
-def is_default_init_field(cls, attr):
- match getattr(cls, attr, None):
- case Field(init=False):
- return False
- case _:
- return True
-
-
-class DealKind:
- def __class_getitem__(cls, trade_type: str):
- match trade_type:
- case "cds":
- return CDSDeal
- case "swaption":
- return SwaptionDeal
- case "termination":
- return TerminationDeal
- case "irs":
- return IRSDeal
- case "trs":
- return TRSDeal
- case "spot":
- return SpotDeal
- case "fx_swap":
- return FxSwapDeal
- case _:
- return None
-
-
-def get_admin_headers(fund, trade_type):
- if fund in ("SERCGMAST", "BOWDST", "BRINKER"):
- try:
- return HEADERS[trade_type]
- except:
- from headers.globeop_upload import globeop_IRS, globeop_TRS
-
- return globeop_TRS
-
-
-def get_fname(
- trade_type: Union[str, Tuple[str, str]],
- fund: str = "SERCGMAST",
-):
- d = {
- "bond": "Mortgages",
- "cds": "CreditDefaultSwapDeal",
- "swaption": "SwaptionDeal",
- "future": "Future",
- "wire": "CashFlowDeal",
- "spot": "SpotDeal",
- "fx_swap": "FxSwapDeal",
- "capfloor": "CapFloor",
- "repo": "RepoDeal",
- "termination": "Termination",
- "trs": "TRS",
- "irs": "IRS",
- }
- trade_tag: str
- if isinstance(trade_type, tuple):
- trade_tag = d[trade_type[0]] + trade_type[1]
- else:
- trade_tag = d[trade_type]
-
- timestamp = datetime.datetime.now()
- if fund == "BRINKER":
- return f"LMCG_BBH_SWAP_TRADES_P.{timestamp:%Y%m%d%H%M%S}.csv"
- elif fund == "SERCGMAST":
- return f"Serenitas.ALL.{timestamp:%Y%m%d.%H%M%S}.{trade_tag}.csv"
- elif fund == "BOWDST":
- return f"Bowdst.ALL.{timestamp:%Y%m%d.%H%M%S}.{trade_tag}.csv"
-
-
-def upload_buf(buf, dest, fund):
- match fund:
- case "SERCGMAST":
- ftp = FtpClient.from_creds("globeop")
- ftp.client.cwd("incoming")
- ftp.put(buf, dest)
- case "BOWDST":
- sftp = SftpClient.from_creds("hm_globeop")
- sftp.put(buf, dest)
- case "BRINKER":
- sftp = SftpClient.from_creds("bbh")
- sftp.put(buf, dest)
-
-
-class Deal:
- _conn: ClassVar = dbconn("dawndb", application_name="autobooker")
- _registry = {}
- _table_name: None
- _sql_fields: ClassVar[list[str]]
- _sql_insert: ClassVar[str]
- _sql_select: ClassVar[str]
- _insert_queue: ClassVar[list] = []
- _admin_queue: ClassVar[list] = []
-
- def __class_getitem__(cls, deal_type: DealType):
- return cls._registry[deal_type]
-
- def __init_subclass__(
- cls, deal_type: DealType, table_name: str, insert_ignore=(), **kwargs
- ):
- super().__init_subclass__(**kwargs)
- cls._registry[deal_type] = cls
- cls._table_name = table_name
- insert_columns = [c for c in cls.__annotations__ if c not in insert_ignore]
- place_holders = ",".join(["%s"] * len(insert_columns))
- cls._sql_fields = {
- c: None for c in cls.__annotations__ if is_default_init_field(cls, c)
- }
-
- cls._sql_insert = f"INSERT INTO {table_name}({','.join(insert_columns)}) VALUES({place_holders})"
- cls._sql_select = (
- f"SELECT {','.join(cls._sql_fields)} FROM {table_name} WHERE id=%s"
- )
-
- def stage(self):
- self._insert_queue.append(
- [
- getattr(self, f.name)
- for f in fields(self)
- if f.metadata.get("insert", True)
- ]
- )
-
- @classmethod
- def admin_upload(cls, fund, trade_type, upload):
- if not cls._admin_queue: # early exit
- return
- buf = StringIO()
- csvwriter = csv.writer(buf)
- headers = get_admin_headers(fund, trade_type)
- csvwriter.writerow(headers)
- csvwriter.writerows(
- [row.get(h, None) for h in headers] for row in cls._admin_queue
- )
- buf = buf.getvalue().encode()
- fname = get_fname(trade_type, fund)
- dest = DAILY_DIR / str(datetime.date.today()) / fname
- dest.parent.mkdir(exist_ok=True)
- dest.write_bytes(buf)
- if upload:
- upload_buf(buf, fname, fund)
-
- def admin_stage(self):
- self._admin_queue.append(self.to_globeop())
-
- @classmethod
- def commit(cls):
- with cls._conn.cursor() as c:
- c.executemany(cls._sql_insert, cls._insert_queue)
- cls._conn.commit()
- cls._insert_queue.clear()
-
- @classmethod
- def from_tradeid(cls, trade_id: int):
- with cls._conn.cursor() as c:
- c.execute(cls._sql_select, (trade_id,))
- r = c.fetchone()
- return cls(*r)
-
- def serialize(self, tag: str):
- return {
- f.metadata.get(tag, f.name): getattr(self, f.name) for f in fields(self)
- }
-
- @classmethod
- def from_dict(cls, **kwargs):
- return cls(**{k: v for k, v in kwargs.items() if k in cls._sql_fields})
-
-
-class BbgDeal:
- _bbg_insert_queue: ClassVar[list] = []
- _cache: ClassVar[LRU] = LRU(128)
- _bbg_sql_insert: ClassVar[str]
-
- def __init_subclass__(cls, deal_type, **kwargs):
- super().__init_subclass__(deal_type, **kwargs)
- if deal_type == DealType.Bond:
- cls._bbg_sql_insert = (
- f"INSERT INTO bond_tickets VALUES({','.join(['%s'] * 20)})"
- )
- elif deal_type == DealType.CDS:
- cls._bbg_sql_insert = (
- f"INSERT INTO cds_tickets VALUES({','.join(['%s'] * 22)})"
- )
- elif deal_type in (DealType.Fx, DealType.Spot, DealType.FxSwap):
- cls._bbg_sql_insert = (
- f"INSERT INTO fx_tickets VALUES({','.join(['%s'] * 211)})"
- )
-
- @classmethod
- def commit(cls):
- with cls._conn.cursor() as c:
- try:
- c.executemany(cls._bbg_sql_insert, cls._bbg_insert_queue)
- except UniqueViolation as e:
- logger.warning(e)
- cls._conn.rollback()
- else:
- c.executemany(cls._sql_insert, cls._insert_queue)
- cls._conn.commit()
- finally:
- cls._bbg_insert_queue.clear()
- cls._insert_queue.clear()
-
- @classmethod
- def process(cls, file_handle, index):
- for row in csv.DictReader(file_handle):
- line = {"bbg_ticket_id": index, **row}
- trade = cls.from_bbg_line(line)
- trade.stage()
- type(trade).commit()
-
- @classmethod
- def get_cp_code(cls, bbg_code, code_type):
- with cls._conn.cursor() as c:
- c.execute(
- "SELECT cp_code from bbg_ticket_mapping where bbg_code=%s and code_type=%s",
- (bbg_code, code_type),
- )
- try:
- (cp_code,) = c.fetchone()
- except TypeError:
- raise ValueError(f"missing {bbg_code} in the db for {code_type}")
- return cp_code
-
-
-class Citco:
- pass
-
-
-class CitcoProduct(Citco):
- product_key = ()
-
- def __init_subclass__(cls, product_key, **kwargs):
- cls.product_key = product_key
-
- def get_productid(self):
- filter_clause = " AND ".join([f"{k}=%s" for k in self.product_key])
- sql_str = (
- f"SELECT id, dealid, status FROM {self._table_name} WHERE {filter_clause}"
- )
- with self._conn.cursor() as c:
- c.execute(
- sql_str,
- tuple([getattr(self, k) for k in self.product_key]),
- )
- if results := c.fetchone():
- (self.id, self.dealid, self.status) = results
-
- def to_citco(self):
- if not self.id:
- self.stage()
- self.commit()
- self.get_productid()
- obj = self.serialize("citco")
- for k in ["Birth_date", "Death_date"]:
- obj[k] = obj[k].strftime("%Y%m%d")
- return obj
-
-
-class CitcoTrade(Citco):
- def to_citco(self, action):
- obj = self.serialize("citco")
- obj["SettleCurrency"] = "USD"
- obj["OrdStatus"], obj["ExecTransType"] = self._action_to_citco(action)
- obj["FillID"] = obj["ClientOrderID"]
- obj["Trader"] = "DFLT"
- obj["StrategyCode"] = f"{obj['portfolio']}/{obj['folder']}"
- obj["TradeDate"] = (
- obj["TradeDate"].strftime("%Y%m%d") if obj.get("TradeDate") else None
- )
- obj["SettlementDate"] = (
- obj["SettlementDate"].strftime("%Y%m%d")
- if obj.get("SettlementDate")
- else None
- )
- obj["FillQty"] = obj.get("OrderQty")
- obj["FillPrice"] = obj.get("AvgPrice")
- obj["FXRate"] = 1
- return obj
-
- @staticmethod
- def _action_to_citco(action):
- match action:
- case "NEW":
- return ("N", 2)
- case "UPDATE":
- return ("R", 0)
- case "CANCEL":
- return ("D", 0)
-
-
-@dataclass
-class CDSDeal(
- CitcoTrade,
- BbgDeal,
- Deal,
- deal_type=DealType.CDS,
- table_name="cds",
- insert_ignore=("id", "dealid", "factor", "tenor", "redcode"),
-):
- fund: Fund = field(metadata={"mtm": "Account Abbreviation", "citco": "Fund"})
- account_code: str
- cp_code: str = field(metadata={"mtm": "Broker Id", "citco": "ExecutionBroker"})
- security_id: str = field(metadata={"mtm": "RED"})
- security_desc: str = field(metadata={"citco": "SecurityDescription"})
- maturity: datetime.date = field(metadata={"mtm": "Maturity Date"})
- currency: Ccy = field(
- metadata={"mtm": "Currency Code", "citco": "SecurityCurrency"}
- )
- protection: Literal["Buy", "Sell"]
- notional: float = field(metadata={"mtm": "1st Leg Notional", "citco": "OrderQty"})
- fixed_rate: float = field(metadata={"mtm": "1st Leg Rate"})
- upfront: float = field(metadata={"mtm": "Initial Payment"})
- traded_level: Decimal
- effective_date: datetime.date = field(
- default=None, metadata={"mtm": "Effective Date"}
- )
- portfolio: Portfolio = field(default=None)
- folder: CdsStrat = field(default=None)
- payment_rolldate: BusDayConvention = BusDayConvention.following
- day_count: DayCount = "ACT/360"
- frequency: Frequency = Frequency.Quarterly
- trade_date: datetime.date = field(
- default_factory=datetime.date.today(),
- metadata={"mtm": "Trade Date", "citco": "TradeDate"},
- )
- upfront_settle_date: datetime.date = field(
- default_factory=lambda: next_business_day(datetime.date.today()),
- metadata={"mtm": "First Payment Date", "citco": "SettlementDate"},
- )
- orig_attach: int = field(default=None, metadata={"mtm": "Attachment Point"})
- orig_detach: int = field(default=None, metadata={"mtm": "Exhaustion Point"})
- tenor: int = field(init=False, metadata={"insert": False})
- attach: int = field(default=None)
- detach: int = field(default=None)
- swap_type: SwapType = "CD_INDEX"
- clearing_facility: ClearingFacility = "ICE-CREDIT"
- isda_definition: IsdaDoc = "ISDA2014"
- id: int = field(default=None, metadata={"insert": False})
- dealid: str = field(
- default=None,
- metadata={"insert": False, "mtm": "Swap ID", "citco": "ClientOrderID"},
- )
- initial_margin_percentage: float = field(
- default=None, metadata={"mtm": "Independent Amount (%)"}
- )
- factor: float = field(default=1.0, init=False, metadata={"insert": False})
- redcode: str = field(init=False, metadata={"insert": False})
- bbg_ticket_id: str = None
-
- def __post_init__(self):
- start_protection = self.trade_date + datetime.timedelta(days=1)
- effective_date = previous_twentieth(prev_business_day(start_protection))
- self.effective_date = adjust_next_business_day(effective_date)
- if self.attach:
- self.factor = (self.detach - self.attach) / (
- self.orig_detach - self.orig_attach
- )
- else:
- with self._conn.cursor() as c:
- c.execute(
- "SELECT indexfactor / 100 FROM index_version WHERE redindexcode=%s",
- (self.security_id,),
- )
- (self.factor,) = c.fetchone()
- # do something better
- self.tenor = self.security_desc.rsplit(" ", 1)[1].removesuffix("Y")
- self.redcode = "_".join((self.security_id, self.tenor))
-
- def to_markit(self):
- obj = self.serialize("mtm")
- if obj["Initial Payment"] >= 0:
- obj["Transaction Code"] = "Receive"
- else:
- obj["Transaction Code"] = "Pay"
- obj["Initial Payment"] = round(abs(obj["Initial Payment"]), 2)
- obj["Trade ID"] = obj["Swap ID"]
- obj["Product Type"] = "TRN"
- obj["Transaction Type"] = "NEW"
- obj["Protection"] = "Buy" if obj["protection"] == "Buyer" else "Sell"
- obj["Entity Matrix"] = "Publisher"
- obj["Definitions Type"] = "ISDA2014Credit"
- # obj["Independent Amount (%)"] = obj["initial_margin_percentage"]
- if "ITRX" in obj["security_desc"]:
- obj["Include Contractual Supplement"] = "Y"
- obj["Contractual Supplement"] = "StandardiTraxxEuropeTranche"
- return obj
-
- def to_citco(self, action):
- obj = super().to_citco(action)
- obj["SecurityType"] = "CDS"
- obj["AvgPrice"] = (
- obj["OrderQty"] / obj["upfront"] / obj["factor"] / 100
- ) # Citco looks at factor as 1/100
- if obj["protection"] == "Buyer":
- obj["BuySellShortCover"] = "S"
- else:
- obj["BuySellShortCover"] = "B"
- obj["AvgPrice"] = -obj["AvgPrice"]
- obj["FillPrice"] = obj["AvgPrice"]
- if obj["orig_attach"] is not None:
- # tranche process
- obj["IDSource"] = "USERID"
- obj["ExecutionBroker"] = _citco_cp_isda[obj["ExecutionBroker"]]
- obj["ClearingAgent"] = obj["ExecutionBroker"]
- obj["SecurityID"] = self.product.dealid
- else:
- # cleared cds process
- obj["IDSource"] = "RED"
- obj["ExecutionBroker"] = (
- _citco_cp_cdea[obj["ExecutionBroker"]]
- if obj["ExecutionBroker"] != "BSEONY"
- else "BSEONY"
- )
- # We need to query DB via accounts table here
- warnings.warn("we will get rid of overwriting")
- obj["ClearingAgent"] = "BOA_FC"
- obj["SecurityID"] = self.redcode
-
- return obj
-
- @property
- def product(self):
- return TrancheProduct(
- underlying_security_id=self.redcode,
- attach=self.orig_attach,
- detach=self.orig_detach,
- death_date=self.maturity,
- security_desc=f"{self.security_desc} {self.orig_attach}-{self.orig_detach}",
- )
-
- @classmethod
- def from_bbg_line(cls, line: dict):
- if line["Client FCM"] == "":
- raise ValueError("Trade is unallocated")
- if line["Coupon"] == "":
- with cls._conn.cursor() as c:
- c.execute(
- "SELECT coupon, index, series, tenor FROM index_desc "
- "WHERE redindexcode=%s AND maturity =%s",
- (
- line["Red Code"],
- datetime.datetime.strptime(line["Mat Dt"], "%m/%d/%Y").date(),
- ),
- )
- coupon, index, series, tenor = c.fetchone()
- line["Security"] = desc_str(index, series, tenor.removesuffix("yr"))
- line["Coupon"] = coupon
- if "Price (Dec)" not in line: # Means this is a BSEF block file
- line["Price (Dec)"] = line["Price"]
- line["Quantity"] = float(line["Qty (M)"]) * 1000
- values = [line["bbg_ticket_id"]] + [None] * 21
- values[14] = _funds[_fcms[line["Client FCM"]]]
- values[15] = _fcms[line["Client FCM"]]
- else:
- values = list(line.values())
- cp_code = cls.get_cp_code(line["Brkr"], "CDS")
- cls._bbg_insert_queue.append(values)
- return cls(
- fund=_funds[_fcms[line["Client FCM"]]],
- folder="*",
- portfolio="UNALLOCATED",
- security_id=line["Red Code"],
- security_desc=line["Security"].removesuffix(" PRC"),
- traded_level=Decimal(line["Price (Dec)"]),
- notional=line["Quantity"],
- fixed_rate=float(line["Coupon"]) * 0.01,
- trade_date=datetime.datetime.strptime(line["Trade Dt"], "%m/%d/%Y").date(),
- maturity=datetime.datetime.strptime(line["Mat Dt"], "%m/%d/%Y").date(),
- currency=line["Curncy"],
- protection="Buyer" if line["Side"] == "B" else "Seller",
- upfront=line["Net"],
- cp_code=cp_code,
- account_code=_fcms[line["Client FCM"]],
- bbg_ticket_id=line["bbg_ticket_id"],
- )
-
-
-@dataclass
-class BondDeal(
- CitcoTrade,
- BbgDeal,
- Deal,
- deal_type=DealType.Bond,
- table_name="bonds",
- insert_ignore=("id", "dealid"),
-):
- buysell: bool
- description: str
- faceamount: float = field(metadata={"citco": "OrderQty"})
- price: float = field(metadata={"citco": "AvgPrice"})
- cp_code: str = field(metadata={"citco": "ExecutionBroker"})
- cusip: str = None
- isin: str = None
- identifier: str = field(default=None, metadata={"citco": "SecurityID"})
- trade_date: datetime.date = field(
- default_factory=datetime.date.today(), metadata={"citco": "TradeDate"}
- )
- settle_date: datetime.date = field(
- default_factory=lambda: next_business_day(datetime.date.today()),
- metadata={"citco": "SettlementDate"},
- )
- folder: BondStrat = field(default=None)
- portfolio: Portfolio = field(default=None)
- asset_class: AssetClass = field(default=None)
- bbg_ticket_id: str = None
- principal_payment: float = None
- accrued_payment: float = None
- current_face: float = None
- id: int = field(default=None, metadata={"insert": False})
- dealid: str = field(
- default=None,
- metadata={"insert": False, "mtm": "Swap ID", "citco": "ClientOrderID"},
- )
-
- @classmethod
- def from_bbg_line(cls, line: dict):
- with cls._conn.cursor() as c:
- c.execute(
- "SELECT asset_class from securities where figi=%s",
- (line["FIGI"],),
- )
- results = c.fetchone()
- asset_class = results[0] if results else None
- cp_code = cls.get_cp_code(line["Brkr"], "BOND")
- cls._bbg_insert_queue.append(list(line.values()))
- return cls(
- faceamount=Decimal(line["Quantity"]),
- price=Decimal(line["Price (Dec)"]),
- cp_code=cp_code,
- cusip=line["Cusip"],
- identifier=line["Cusip"],
- trade_date=datetime.datetime.strptime(line["Trade Dt"], "%m/%d/%Y"),
- settle_date=datetime.datetime.strptime(line["SetDt"], "%m/%d/%Y"),
- portfolio="UNALLOCATED",
- description=line["Security"].removesuffix(" Mtge"),
- buysell=line["Side"] == "B",
- bbg_ticket_id=line["bbg_ticket_id"],
- asset_class=asset_class,
- )
-
- @classmethod
- def from_allocationid(cls, allocation_id):
- with cls._conn.cursor() as c:
- c.execute(
- "SELECT tradeid, notional from bond_allocation where id=%s",
- (allocation_id,),
- )
- tradeid, notional = c.fetchone()
- cls = cls.from_tradeid(tradeid)
- ratio = notional / cls.faceamount
- for key in [
- "principal_payment",
- "accrued_payment",
- "current_face",
- "net_amount",
- ]:
- if key in cls.__dict__.keys():
- setattr(cls, key, getattr(cls, key) * ratio)
- setattr(cls, "faceamount", notional)
- return cls
-
- def to_citco(self, action):
- obj = super().to_citco(action)
- obj["SecurityType"] = "CMO"
- warnings.warn("Hardcoded")
- obj["ClearingAgent"] = "NT"
- obj["FXRate"] = 1
- obj["BuySellShortCover"] = "B" if obj["buysell"] else "S"
- obj["IDSource"] = "CUSIP"
- with self._conn.cursor() as c:
- c.execute(
- "SELECT coupon, day_count from securities where identifier=%s",
- (obj["SecurityID"],),
- )
- obj["Coupon%"], obj["DayCountFraction/RepoCalendar"] = c.fetchone()
- return obj
-
-
-@dataclass
-class SwaptionDeal(
- CitcoTrade,
- Deal,
- deal_type=DealType.Swaption,
- table_name="swaptions",
- insert_ignore=("id", "dealid", "factor"),
-):
- buysell: bool
- fund: Fund = field(metadata={"mtm": "Account Abbreviation", "citco": "Fund"})
- cp_code: str = field(metadata={"mtm": "Broker Id", "citco": "ExecutionBroker"})
- security_id: str = field(metadata={"mtm": "RED"})
- security_desc: str = field(metadata={"citco": "SecurityDescription"})
- maturity: datetime.date = field(metadata={"mtm": "Maturity Date"})
- currency: Ccy = field(
- metadata={"mtm": "Currency Code", "citco": "SecurityCurrency"}
- )
- notional: float = field(metadata={"mtm": "1st Leg Notional", "citco": "OrderQty"})
- fixed_rate: float = field(metadata={"mtm": "1st Leg Rate"})
- strike: float = field(metadata={"mtm": "Strike Price"})
- price: float = field(metadata={"citco": "AvgPrice"})
- option_type: OptionType
- expiration_date: datetime.date = field(metadata={"mtm": "Expiration"})
- portfolio: Portfolio = field(default=None)
- folder: SwaptionStrat = field(default=None)
- trade_date: datetime.date = field(
- default_factory=datetime.date.today(),
- metadata={"mtm": "Trade Date", "citco": "TradeDate"},
- )
- settle_date: datetime.date = field(
- default_factory=lambda: next_business_day(datetime.date.today()),
- metadata={"mtm": "Settle Date", "citco": "SettlementDate"},
- )
- expiration_date: datetime.date = field(
- metadata={"mtm": "Swaption Expiration Date"},
- )
- initial_margin_percentage: float = field(
- default=None, metadata={"mtm": "Independent Amount (%)"}
- )
- id: int = field(default=None, metadata={"insert": False})
- dealid: str = field(
- default=None,
- metadata={"insert": False, "mtm": "Swap ID", "citco": "ClientOrderID"},
- )
- factor: float = field(default=1.0, init=False, metadata={"insert": False})
- swap_type: str = field(default="CD_INDEX_OPTION")
-
- def __post_init__(self):
- # will need to filter a bit better, for now, just CDX index swaptions
- if self.security_desc:
- with self._conn.cursor() as c:
- c.execute(
- "SELECT indexfactor / 100 FROM index_version WHERE redindexcode=%s",
- (self.security_id,),
- )
- (self.factor,) = c.fetchone()
- self.tenor = self.security_desc.rsplit(" ", 1)[1].removesuffix("Y")
- self.redcode = "_".join((self.security_id, self.tenor))
-
- def to_markit(self):
- obj = self.serialize("mtm")
- obj["Initial Payment"] = (
- round(obj["price"] * obj["1st Leg Notional"] * 0.01, 2) * self.factor
- )
- obj["Trade ID"] = obj["Swap ID"]
- obj["Product Type"] = "CDISW"
- obj["Transaction Type"] = "NEW"
- if obj["buysell"]:
- obj["Transaction Code"] = "Pay"
- obj["Protection"] = "Buy" if obj["option_type"] == "PAYER" else "Sell"
- obj["OptionBuySellIndicator"] = "Buy"
- else:
- obj["Transaction Code"] = "Receive"
- obj["Protection"] = "Sell" if obj["option_type"] == "PAYER" else "Buy"
- obj["OptionBuySellIndicator"] = "Sell"
- obj["Entity Matrix"] = "Publisher"
- obj["Clearing House"] = "ICE_FCM_US"
- obj["Swaption Settlement Type"] = "Physical"
- obj["Supplement Date"] = datetime.date(2021, 12, 13)
- obj["Supplement 2 Date"] = datetime.date(2020, 1, 27)
- if "IG" in obj["security_desc"]:
- obj["Swaption Quotation Rate Type"] = "Spread"
- obj["Strike Price"] = obj["Strike Price"] * 0.01
- obj["Effective Date"] = obj["Trade Date"]
- return obj
-
- def to_citco(self, action):
- obj = super().to_citco(action)
- obj["ExecutionBroker"] = _citco_cp_isda[obj["ExecutionBroker"]]
- obj["ClearingAgent"] = obj["ExecutionBroker"]
- obj["SecurityType"] = "BNDOPT"
- obj["BuySellShortCover"] = "B" if obj["buysell"] == "Buy" else "S"
- obj["IDSource"] = "USERID"
- obj["ClearingAgent"] = obj["ExecutionBroker"]
- obj["SecurityID"] = self.product.dealid
- return obj
-
- @property
- def product(self):
- return SwaptionProduct(
- underlying_security_id=self.redcode
- if self.swap_type == "CD_INDEX_OPTION"
- else _to_index[self.security_id],
- instrument_type="BNDO" if self.swap_type == "CD_INDEX_OPTION" else "SWPO",
- callput=self.option_type == "RECEIVER",
- strike=self.strike,
- expiration=self.expiration_date,
- birth_date=None if self.swap_type == "CD_INDEX_OPTION" else self.trade_date,
- death_date=None if self.swap_type == "CD_INDEX_OPTION" else self.maturity,
- )
-
-
-@dataclass
-class TerminationDeal(
- Deal,
- deal_type=DealType.Termination,
- table_name="terminations",
- insert_ignore=("id", "dealid", "orig_cp", "currency", "fund", "product_type"),
-):
- partial_termination: bool
- termination_fee: float = field(metadata={"mtm": "Initial Payment"})
- fee_payment_date: datetime.date = field(
- metadata={"mtm": "Settle Date", "globeop": "FeePaymentDate"}
- )
- termination_cp: str = field(metadata={"mtm": "Broker Id"})
- termination_amount: float = field(
- metadata={"mtm": "1st Leg Notional", "globeop": "TerminationAmount"}
- )
- termination_date: datetime.date = field(
- default_factory=datetime.date.today(),
- metadata={"mtm": "Trade Date", "globeop": "TerminationDate"},
- )
- id: int = field(default=None, metadata={"insert": False})
- dealid: str = field(default=None, metadata={"insert": False, "mtm": "Swap ID"})
- factor: float = field(default=1, init=False, metadata={"insert": False})
- orig_cp: str = field(
- init=False,
- metadata={"mtm": "Remaining Party", "insert": False},
- )
- currency: str = field(
- init=False,
- metadata={"mtm": "Currency Code", "insert": False},
- )
- fund: str = field(
- init=False,
- metadata={"mtm": "Account Abbreviation", "insert": False},
- )
- product_type: str = field(
- init=False, metadata={"mtm": "Product Type", "insert": False}
- )
- deal_type: str = field(
- init=False, metadata={"insert": False, "globeop": "DealType"}
- )
- globeop_id: str = field(init=False, default=None, metadata={"globeop": "GoTradeId"})
-
- def __post_init__(self):
- if self.dealid.startswith("SWPTN"):
- self.product_type = "CDISW"
- self.deal_type = "SwaptionDeal"
- sql_str = (
- "SELECT cp_code, currency, fund, globeop_id FROM terminations "
- "LEFT JOIN swaptions USING (dealid) "
- "WHERE terminations.id = %s"
- )
- elif self.dealid.startswith("SCCDS"):
- self.product_type = "TRN"
- self.deal_type = "CreditDefaultSwapDeal"
- sql_str = (
- "SELECT cp_code, currency, fund, b.globeop_id, "
- "(detach - attach) / (orig_detach - orig_attach) "
- "FROM terminations "
- "LEFT JOIN cds USING (dealid) "
- "LEFT JOIN LATERAL ("
- " SELECT globeop_id FROM id_mapping WHERE serenitas_id=cds.id"
- " ORDER BY date DESC LIMIT 1"
- ") b ON true "
- "WHERE terminations.id = %s"
- )
- with self._conn.cursor() as c:
- c.execute(sql_str, (self.id,))
- if self.deal_type == "SwaptionDeal":
- self.orig_cp, self.currency, self.fund, self.globeop_id = c.fetchone()
- elif self.deal_type == "CreditDefaultSwapDeal":
- (
- self.orig_cp,
- self.currency,
- self.fund,
- self.globeop_id,
- self.factor,
- ) = c.fetchone()
-
- def to_markit(self):
- obj = self.serialize("mtm")
- if obj["Initial Payment"] >= 0:
- obj["Transaction Code"] = "Receive"
- else:
- obj["Transaction Code"] = "Pay"
- obj["Initial Payment"] = round(abs(obj["Initial Payment"]), 2)
- obj["Trade ID"] = obj["Swap ID"] + "-" + str(obj["id"])
- obj["Transaction Type"] = (
- "Termination"
- if obj["Remaining Party"] == obj["Broker Id"]
- else "Assignment"
- )
- obj["Effective Date"] = obj["Trade Date"] + datetime.timedelta(days=1)
- return obj
-
- def to_globeop(self):
- obj = self.serialize("globeop")
- obj["TerminationAmount"] *= self.factor
- obj["FeesPaid"] = (
- -obj["termination_fee"] if obj["termination_fee"] < 0 else None
- )
- obj["FeesReceived"] = (
- obj["termination_fee"] if obj["termination_fee"] > 0 else None
- )
- obj["Action"] = "UPDATE"
- obj["Client"] = _client_name[obj["fund"]]
- obj["SubAction"] = "Termination"
- if self.termination_cp != self.orig_cp:
- obj["AssignedCounterparty"] = self.termination_cp
- obj["PartialTermination"] = "Y" if self.partial_termination else "N"
- return obj
-
-
-@dataclass
-class SpotDeal(
- CitcoTrade,
- BbgDeal,
- Deal,
- deal_type=DealType.Spot,
- table_name="spots",
- insert_ignore=("id", "dealid"),
-):
- folder: SpotStrat
- portfolio: Portfolio
- spot_rate: float = field(metadata={"citco": "AvgPrice"})
- buy_currency: str
- buy_amount: float
- sell_currency: str
- sell_amount: float
- fund: Fund
- cp_code: str = field(metadata={"citco": "ExecutionBroker"})
- cash_account: str
- commission_currency: str = "USD"
- commission: float = None
- id: int = field(default=None, metadata={"insert": False})
- dealid: str = field(
- default=None, metadata={"insert": False, "citco": "ClientOrderID"}
- )
- trade_date: datetime.date = field(
- default_factory=datetime.date.today(), metadata={"citco": "TradeDate"}
- )
- settle_date: datetime.date = field(
- default_factory=datetime.date.today(), metadata={"citco": "SettlementDate"}
- )
- bbg_ticket_id: str = None
-
- @classmethod
- def from_bbg_line(cls, line: dict):
- cp_code = cls.get_cp_code(line["Counterparty Deal Code"], "FX")
- if line["Side"] == "B":
- key1, key2 = "buy", "sell"
- else:
- key1, key2 = "sell", "buy"
-
- d = {
- f"{key1}_currency": line["Currency 1"],
- f"{key1}_amount": line["Amount Dealt"],
- f"{key2}_currency": line["Currency 2"],
- f"{key2}_amount": line["Counter Amount"],
- }
- for key in ("Comp Quote 1",):
- if line[key] == "":
- line[key] = None
- cls._bbg_insert_queue.append(list(line.values()))
- return cls(
- folder="*",
- portfolio="UNALLOCATED",
- cp_code=cp_code,
- trade_date=datetime.datetime.strptime(line["Date Of Deal"], "%Y%m%d"),
- settle_date=datetime.datetime.strptime(
- line["Value Date Period 1 Currency 1"], "%Y%m%d"
- ),
- fund=_fx_funds[line["ALOC Account 1"]],
- spot_rate=line["Exchange Rate Period 1"],
- cash_account=_fx_accounts[line["ALOC Account 1"]],
- bbg_ticket_id=line["bbg_ticket_id"],
- **d,
- )
-
- def to_citco(self, action):
- obj = super().to_citco(action)
- if obj["buy_currency"] == "USD":
- key1, key2 = "sell", "buy"
- else:
- key1, key2 = "buy", "sell"
- obj["SecurityCurrency"] = obj[f"{key1}_currency"]
- obj["OrderQty"] = obj[f"{key1}_amount"]
- obj["FillQty"] = obj["OrderQty"]
- obj["SecurityType"] = "FX"
- obj["BuySellShortCover"] = "S" if obj["buy_currency"] == "USD" else "B"
- obj["IDSource"] = "BLOOMBERG"
- _citco_currency_mapping = {"EUR": "EURUSD CURNCY"}
- obj["SecurityID"] = _citco_currency_mapping[obj["SecurityCurrency"]]
- obj["ClearingAgent"] = "NT"
- obj["FillFXSettleAmount"] = obj[f"{key2}_amount"]
- obj["FXRate"] = 1
- return obj
-
-
-_fx_funds = {"serenitas": "SERCGMAST", "bowdst": "BOWDST", "baml_fcm": "SERCGMAST"}
-_fx_accounts = {"serenitas": "V0NSCLMAMB", "bowdst": "751254", "baml_fcm": "V0NSCLMSPT"}
-
-
-class FxDeal(BbgDeal, Deal, table_name=None, deal_type=DealType.Fx):
- @classmethod
- def from_bbg_line(cls, line: dict):
- if line["Deal Type"] in ("4", "2"):
- return SpotDeal.from_bbg_line(line)
- else:
- return FxSwapDeal.from_bbg_line(line)
-
-
-@dataclass
-class FxSwapDeal(
- CitcoTrade,
- BbgDeal,
- Deal,
- deal_type=DealType.FxSwap,
- table_name="fx_swaps",
- insert_ignore=("id", "dealid"),
-):
- folder: str
- portfolio: str
- trade_date: datetime.date = field(metadata={"citco": "TradeDate"})
- near_settle_date: datetime.date
- near_buy_currency: str
- near_buy_amount: float
- near_sell_currency: str
- near_sell_amount: float
- near_rate: float
- far_rate: float
- far_settle_date: datetime.date
- far_buy_currency: str
- far_buy_amount: float
- far_sell_currency: str
- far_sell_amount: str
- fund: Fund
- cp_code: str = field(metadata={"citco": "ExecutionBroker"})
- cash_account: str
- id: int = field(default=None, metadata={"insert": False})
- dealid: str = field(
- default=None, metadata={"insert": False, "citco": "ClientOrderID"}
- )
- bbg_ticket_id: str = None
-
- @classmethod
- def from_bbg_line(cls, line: dict):
- cp_code = cls.get_cp_code(line["Counterparty Deal Code"], "FX")
- if line["Side"] == "S":
- key1, key2 = "buy", "sell"
- else:
- key1, key2 = "sell", "buy"
-
- d = {
- f"near_{key1}_currency": line["Currency 1"],
- f"near_{key1}_amount": line["Amount Dealt"],
- f"far_{key1}_currency": line["Currency 2"],
- f"far_{key1}_amount": line["Far Counter Amount"],
- f"near_{key2}_currency": line["Currency 2"],
- f"near_{key2}_amount": line["Counter Amount"],
- f"far_{key2}_currency": line["Currency 1"],
- f"far_{key2}_amount": line["Far Amount Dealt"],
- }
- for key in ("Comp Quote 1",):
- if line[key] == "":
- line[key] = None
- cls._bbg_insert_queue.append(list(line.values()))
- return cls(
- folder="*",
- portfolio="UNALLOCATED",
- cp_code=cp_code,
- trade_date=datetime.datetime.strptime(line["Date Of Deal"], "%Y%m%d"),
- near_settle_date=datetime.datetime.strptime(
- line["Value Date Period 1 Currency 1"], "%Y%m%d"
- ),
- far_settle_date=datetime.datetime.strptime(
- line["Value Date Period 2 Currency 1"], "%Y%m%d"
- ),
- fund=_fx_funds[line["ALOC Account 1"]],
- near_rate=line["Exchange Rate Period 1"],
- far_rate=line["Exchange Rate Period 2"],
- cash_account=_fx_accounts[line["ALOC Account 1"]],
- bbg_ticket_id=line["bbg_ticket_id"],
- **d,
- )
-
- def to_citco(self, action):
- obj = super().to_citco(action)
- if obj["near_buy_currency"] == "USD": # This is for strict FX Swaps
- key1, key2 = "buy", "sell"
- else:
- key1, key2 = "sell", "buy"
- obj["SecurityCurrency"] = obj[f"far_{key1}_currency"]
- obj["OrderQty"] = obj[f"far_{key1}_amount"]
- obj["SecurityType"] = "FWDFX"
- obj["AvgPrice"] = obj["far_rate"]
- obj["BuySellShortCover"] = "B" if obj["near_buy_currency"] == "USD" else "S"
- obj["IDSource"] = "BLOOMBERG"
- _citco_currency_mapping = {"EUR": "EURUSD CURNCY"}
- obj["SecurityID"] = _citco_currency_mapping[obj["SecurityCurrency"]]
- obj["ClearingAgent"] = "NT"
- obj["SettlementDate"] = obj["far_settle_date"]
- obj["FillFXSettleAmount"] = obj[f"far_{key2}_amount"]
- near_trade = SpotDeal(
- folder=obj["folder"],
- portfolio=obj["portfolio"],
- spot_rate=obj["near_rate"],
- buy_currency=obj[f"near_{key1}_currency"],
- buy_amount=obj[f"near_{key1}_amount"],
- sell_currency=obj[f"near_{key2}_currency"],
- sell_amount=obj[f"near_{key2}_amount"],
- fund=obj["fund"],
- dealid=obj["ClientOrderID"] + "_N",
- trade_date=datetime.datetime.strptime(
- obj["TradeDate"], "%Y%m%d"
- ), # Will be cleaning up with a split function, this is just to run it
- settle_date=obj["near_settle_date"],
- cp_code=obj["ExecutionBroker"],
- cash_account=obj["cash_account"],
- )
- near_trade.citco_stage(action)
- obj["ClientOrderID"] = obj["ClientOrderID"] + "_F"
- obj["FXRate"] = 1
- warnings.warn("Repeated code, fix soon")
- obj["SettlementDate"] = (
- obj["SettlementDate"].strftime("%Y%m%d")
- if obj.get("SettlementDate")
- else None
- )
- obj["FillQty"] = obj.get("OrderQty")
- obj["FillPrice"] = obj.get("AvgPrice")
- return obj
-
-
-@dataclass
-class TRSDeal(
- CitcoTrade,
- Deal,
- deal_type=DealType.TRS,
- table_name="trs",
- insert_ignore=("id", "dealid", "orig_cp", "currency", "product_type"),
-):
- fund: str = field(
- metadata={"mtm": "Account Abbreviation", "globeop": "Fund"},
- )
- portfolio: str = field(metadata={"globeop": "Portfolio"})
- folder: str = field(metadata={"globeop": "Folder"})
- cash_account: str = field(metadata={"globeop": "Cash Account"})
- cp_code: str = field(
- metadata={
- "globeop": "Counterparty",
- "mtm": "Broker Id",
- "citco": "ExecutionBroker",
- }
- )
- trade_date: datetime.date = field(
- metadata={"globeop": "Trade Date", "mtm": "Trade Date", "citco": "TradeDate"}
- )
- effective_date: datetime.date = field(
- init=False, metadata={"mtm": "Effective Date", "citco": "SettlementDate"}
- )
- maturity_date: datetime.date = field(metadata={"mtm": "Maturity Date"})
- funding_index: str
- buysell: bool
- underlying_security: str
- price: float = field(metadata={"mtm": "Initial Fixing Amount", "citco": "AvgPrice"})
- accrued: float = field(metadata={"mtm": "Initial Payment", "citco": "Fee"})
- funding_freq: str
- funding_daycount: str
- funding_payment_roll_convention: str
- funding_arrears: bool
- asset_freq: str
- asset_daycount: str
- asset_payment_roll_convention: str
- initial_margin_percentage: float = field(
- metadata={"globeop": "InitialMarginPercent", "mtm": "Independent Amount (%)"}
- )
- notional: float = field(metadata={"mtm": "1st Leg Notional", "citco": "OrderQty"})
- currency: str = field(
- metadata={"mtm": "Currency Code", "citco": "SecurityCurrency"}
- )
- interest_calc_method: str
- compound_avg_frequency: str
- fixing_frequency: str
- cpty_id: str
- id: int = field(default=None, metadata={"insert": False})
- dealid: str = field(
- default=None,
- metadata={
- "insert": False,
- "mtm": "Swap ID",
- "globeop": "Deal Id",
- "citco": "ClientOrderID",
- },
- )
-
- def __post_init__(self):
- self.effective_date = self.trade_date + datetime.timedelta(days=1)
-
- def to_markit(self):
- _trs_red = {"IBOXHY": "4J623JAA8"}
- _mtm_index = {"SOFRRATE": "USD-SOFR-COMPOUND"}
- obj = self.serialize("mtm")
- obj["Trade ID"] = obj["Swap ID"]
- obj["Initial Payment Currency"] = obj["Currency Code"]
- if obj["Initial Payment"] >= 0:
- obj["Transaction Code"] = "Receive"
- else:
- obj["Transaction Code"] = "Pay"
- obj["Initial Payment"] = round(abs(obj["Initial Payment"]), 2)
- obj["Product Sub Type"] = "IBOXX" # Hardcoded for now
- obj["RED"] = _trs_red[obj["underlying_security"]]
- obj["Transaction Type"] = "New"
- obj["Protection"] = "Buy" if obj["buysell"] else "Sell"
- obj["Master Document Date"] = datetime.date(2020, 12, 18)
- obj["Supplement Date"] = datetime.date(2015, 2, 18)
- obj["Product Type"] = self.product_type
- obj["Independent Amount Payer"] = obj["Account Abbreviation"]
- obj["2nd Leg Index"] = _mtm_index[obj["funding_index"]]
- obj["2nd Leg Spread"] = 0
- obj["2nd Leg Initial Floating Rate"] = 0
- return obj
-
- def to_globeop(self):
- obj = self.serialize("globeop")
- if obj["buysell"]:
- key1, key2 = "Pay", "Receive"
- else:
- key1, key2 = "Receive", "Pay"
- d = {
- f"{key1}LegRateType": "Floating",
- f"{key1}UnderlyingType": "Interest",
- f"{key1}FloatRate": obj["funding_index"],
- f"{key1}FixedRate": 0,
- f"{key1}Daycount": obj["funding_daycount"],
- f"{key1}Frequency": obj["funding_freq"],
- f"{key1}EffectiveDate": obj["effective_date"],
- f"{key1}MaturityDate": obj["maturity_date"],
- f"{key1}Notional": obj["notional"],
- f"{key1}PaymentBDC": obj["funding_payment_roll_convention"],
- f"{key1}Arrears": "Y" if obj["funding_arrears"] else "N",
- f"{key1}InterestCalcMethod": obj["interest_calc_method"],
- f"{key1}CompoundAverageFrequency": obj["compound_avg_frequency"],
- f"{key1}Currency": obj["currency"],
- f"{key1}FixingFrequency": obj["fixing_frequency"],
- f"{key2}LegRateType": "Fixed",
- f"{key2}UnderlyingType": "Bond",
- f"{key2}UnderlyingSecurity": obj["underlying_security"],
- f"{key2}Daycount": obj["asset_daycount"],
- f"{key2}Frequency": obj["asset_freq"],
- f"{key2}EffectiveDate": obj["effective_date"],
- f"{key2}MaturityDate": obj["maturity_date"],
- f"{key2}Notional": obj["notional"],
- f"{key2}PaymentBDC": obj["asset_payment_roll_convention"],
- f"{key2}Price": obj["price"],
- f"{key2}Currency": obj["currency"],
- }
- obj["SwapType"] = "TOTAL_RETURN_SWAP"
- obj["Deal Type"] = "TotalReturnSwapDeal"
- obj["Action"] = "NEW" # Need to figure this out
- obj["Client"] = "Serenitas"
- obj["State"] = "Valid"
- obj["Custodian"] = "BAC"
- obj.update(d)
- return obj
-
- def to_citco(self, action):
- obj = super().to_citco(action)
- obj["ExecutionBroker"] = _citco_cp_isda[obj["ExecutionBroker"]]
- obj["ClearingAgent"] = obj["ExecutionBroker"]
- obj["SecurityType"] = "TRS"
- obj["BuySellShortCover"] = "B" if obj["buysell"] else "S"
- obj["IDSource"] = "USERID"
- obj["Fee"] = -obj["Fee"] if obj["buysell"] else obj["Fee"]
- obj["SecurityID"] = self.product.dealid
- return obj
-
- @property
- def product(self):
- return TRSProduct(
- birth_date=self.trade_date,
- death_date=self.maturity_date,
- underlying_security=self.underlying_security,
- funding_index=self.funding_index,
- )
-
-
-@dataclass
-class IRSDeal(
- CitcoTrade,
- Deal,
- deal_type=DealType.IRS,
- table_name="irs",
- insert_ignore=("id", "dealid", "orig_cp", "product_type"),
-):
- fund: str = field(
- metadata={"mtm": "Account Abbreviation", "globeop": "Fund"},
- )
- portfolio: str = field(metadata={"globeop": "Portfolio"})
- folder: str = field(metadata={"globeop": "Folder"})
- cash_account: str = field(metadata={"globeop": "Cash Account"})
- cp_code: str = field(
- metadata={"globeop": "GiveUpCounterparty", "citco": "ExecutionBroker"}
- )
- trade_date: datetime.date = field(
- metadata={"globeop": "Trade Date", "citco": "TradeDate"}
- )
- effective_date: datetime.date = field(metadata={"citco": "SettlementDate"})
- maturity_date: datetime.date
- payreceive: bool
- fixed_rate: float = field(metadata={"citco": "AvgPrice"})
- fixed_daycount: str
- fixed_payment_freq: str
- fixed_bdc: str
- notional: float = field(metadata={"citco": "OrderQty"})
- float_index: str
- float_daycount: str
- float_payment_freq: str
- float_bdc: str
- float_arrears: bool
- float_fixing_freq: str
- pay_interest_calc_method: str
- clearing_facility: str = field(metadata={"globeop": "ClearingFacility"})
- swap_type: str = field(metadata={"globeop": "SwapType"})
- cleared_trade_id: str
- currency: str = field(metadata={"citco": "SecurityCurrency"})
- custodian: int = field(
- default=None, metadata={"insert": False, "globeop": "Custodian"}, init=False
- )
- id: int = field(default=None, metadata={"insert": False})
- dealid: str = field(
- default=None,
- metadata={
- "insert": False,
- "mtm": "Swap ID",
- "globeop": "Deal Id",
- "citco": "ClientOrderID",
- },
- )
-
- def __post_init__(self):
- with self._conn.cursor() as c:
- c.execute(
- "SELECT cp_code from accounts2 where cash_account=%s",
- (self.cash_account,),
- )
- (self.custodian,) = c.fetchone()
-
- def to_globeop(self):
- obj = self.serialize("globeop")
- if obj["payreceive"]:
- key1, key2 = "Receive", "Pay"
- else:
- key1, key2 = "Pay", "Receive"
- d = {
- f"{key1}LegRateType": "Float",
- f"{key1}FloatRate": obj["float_index"],
- f"{key1}Daycount": obj["float_daycount"],
- f"{key1}Frequency": obj["float_payment_freq"],
- f"{key1}PaymentBDC": obj["float_bdc"],
- f"{key1}EffectiveDate": obj["effective_date"],
- f"{key1}MaturityDate": obj["maturity_date"],
- f"{key1}Notional": obj["notional"],
- f"{key1}ResetArrears": "Y" if obj["float_arrears"] else "N",
- f"{key1}Currency": obj["currency"],
- f"{key1}FixingFrequency": obj["float_fixing_freq"],
- f"{key1}InterestCalcMethod": obj["pay_interest_calc_method"],
- f"{key2}LegRateType": "Fixed",
- f"{key2}FixedRate": obj["fixed_rate"],
- f"{key2}Daycount": obj["fixed_daycount"],
- f"{key2}Frequency": obj["fixed_payment_freq"],
- f"{key2}PaymentBDC": obj["fixed_bdc"],
- f"{key2}EffectiveDate": obj["effective_date"],
- f"{key2}MaturityDate": obj["maturity_date"],
- f"{key2}Notional": obj["notional"],
- f"{key2}Currency": obj["currency"],
- }
- obj["Deal Type"] = "InterestRateSwapDeal"
- obj["Action"] = "NEW" # Need to figure this out
- obj["Client"] = "Serenitas"
- obj["State"] = "Valid"
- obj.update(d)
- return obj
-
- def to_citco(self, action):
- obj = super().to_citco(action)
- obj["ExecutionBroker"] = _citco_cp_cdea[obj["ExecutionBroker"]]
- obj["SecurityType"] = "IRS"
- obj["StrategyCode"] = f"{obj['portfolio']}/{obj['folder']}"
- obj["FillPrice"] = obj["AvgPrice"]
- obj["BuySellShortCover"] = "B" if obj["payreceive"] else "S"
- obj["IDSource"] = "USERID"
- obj["SecurityID"] = self.product.dealid
- warnings.warn("Query DB")
- obj["ClearingAgent"] = "BOA_FC"
- return obj
-
- @property
- def product(self):
- return IRSProduct(
- birth_date=self.trade_date,
- death_date=self.maturity_date,
- fixed_rate=self.fixed_rate,
- float_index=self.float_index,
- )
-
-
-from enum import IntEnum
-
-
-class TrancheType(IntEnum):
- DayCount = 3
-
-
-@dataclass
-class TrancheProduct(
- Deal,
- CitcoProduct,
- deal_type=DealType.TrancheProduct,
- table_name="citco_tranche",
- product_key=("underlying_security_id", "attach", "detach"),
- insert_ignore=(
- "id",
- "dealid",
- "birth_date",
- "death_date",
- "security_desc",
- "coupon",
- "currency",
- ),
-):
- underlying_security_id: str = field(metadata={"citco": "UnderlyingSecurityId"})
- attach: float = field(metadata={"citco": "Attachment_Points"})
- detach: float = field(metadata={"citco": "Detachment_Points"})
- birth_date: datetime.date = field(
- default=None, metadata={"insert": False, "citco": "Birth_date"}
- )
- death_date: datetime.date = field(
- default=None, metadata={"insert": False, "citco": "Death_date"}
- )
- coupon: float = field(
- default=None, metadata={"insert": False, "citco": "CouponRate"}
- )
- security_desc: str = field(
- default=None, metadata={"insert": False, "citco": "Sec_Desc"}
- )
- currency: str = field(default=None, metadata={"citco": "LocalCcy", "insert": False})
- instrument_type: str = field(default="CDS", metadata={"citco": "InstrumentType"})
- underlying_id_source: str = field(
- default="RED", metadata={"citco": "UnderlyingIDSource"}
- )
- status: Status = field(default="Pending")
- id: int = field(default=None, metadata={"insert": False})
- dealid: str = field(
- default=None, metadata={"insert": False, "citco": "UniqueIdentifier"}
- )
-
- def __post_init__(self):
- if not all(
- [
- self.birth_date,
- self.death_date,
- self.coupon,
- self.security_desc,
- self.currency,
- ]
- ):
- redcode, tenor = self.underlying_security_id.split("_")
- tenor_yr = tenor + "yr"
- sql_str = (
- "SELECT issue_date, maturity, coupon, index, series "
- "FROM index_desc WHERE tenor=%s AND redindexcode=%s"
- )
- with self._conn.cursor() as c:
- c.execute(sql_str, (tenor_yr, redcode))
- (
- self.birth_date,
- self.death_date,
- self.coupon,
- index,
- series,
- ) = c.fetchone()
- self.security_desc = (
- f"{desc_str(index, series, tenor)} {self.attach}-{self.detach}"
- )
- self.currency = "EUR" if index in ("XO", "EU") else "USD"
- self.get_productid()
-
- def to_citco(self):
- obj = super().to_citco()
- obj["Command"] = "N"
- obj["Active"] = "Y"
- obj["CouponRate"] = obj["CouponRate"] / 100
- obj["SettleDays"] = 3
- obj["AccruStartDate"] = obj["Birth_date"]
- return obj
-
-
-@dataclass
-class SwaptionProduct(
- Deal,
- CitcoProduct,
- deal_type=DealType.SwaptionProduct,
- table_name="citco_swaption",
- product_key=(
- "underlying_security_id",
- "strike",
- "expiration",
- "callput",
- "birth_date",
- "death_date",
- ),
- insert_ignore=(
- "id",
- "dealid",
- "security_desc",
- "currency",
- ),
-):
- underlying_security_id: str = field(metadata={"citco": "UnderlyingSecurityId"})
- security_desc: str = field(
- init=False, metadata={"insert": False, "citco": "Sec_Desc"}
- )
- currency: str = field(
- init=False, default=None, metadata={"citco": "LocalCcy", "insert": False}
- )
- instrument_type: str = field(metadata={"citco": "InstrumentType"})
- callput: bool
- strike: float = field(metadata={"citco": "StrikePrice"})
- expiration: datetime.date = field(metadata={"citco": "ExpirationDate"})
- underlying_id_source: str = field(
- default="RED", metadata={"citco": "UnderlyingIDSource"}
- )
- birth_date: datetime.date = field(default=None, metadata={"citco": "Birth_date"})
- death_date: datetime.date = field(default=None, metadata={"citco": "Death_date"})
-
- committed: bool = field(default=False)
- id: int = field(default=None, metadata={"insert": False})
- dealid: str = field(
- default=None, metadata={"insert": False, "citco": "UniqueIdentifier"}
- )
-
- def __post_init__(self):
- if self.instrument_type == "BNDO":
- sql_str = "SELECT issue_date, maturity, coupon, index, series FROM index_desc WHERE tenor='5yr' AND redindexcode=%s"
- with self._conn.cursor() as c:
- c.execute(sql_str, (self.underlying_security_id.removesuffix("_5"),))
- (
- self.birth_date,
- self.death_date,
- self.coupon,
- index,
- series,
- ) = c.fetchone()
- self.security_desc = f"{desc_str(index, series, '5')} {self.expiration}-{self.strike}-{'C' if self.callput else 'P'}-{self.birth_date}-{self.death_date}"
- self.currency = "EUR" if index in ("XO", "EU") else "USD"
- elif self.instrument_type == "SWPO":
- self.security_desc = ""
- self.underlying_id_source = "USERID"
- self.get_productid()
-
- def to_citco(self):
- if not self.id:
- self.stage()
- self.commit()
- self.get_productid()
- obj = super().to_citco()
- if self.instrument_type == "SWPO": # Implies this is a Interest Rate Swaption
- irs = IRSProduct(
- birth_date=self.birth_date,
- death_date=self.death_date,
- fixed_rate=self.strike,
- float_index=self.underlying_security_id,
- )
- warnings.warn("We're just tacking on the IRS here, it's not very elegant")
- irs.citco_stage()
- obj["UnderlyingSecurityId"] = irs.dealid
- obj["Command"] = "N"
- obj["Active"] = "Y"
- obj["ExpirationDate"] = obj["ExpirationDate"].strftime("%Y%m%d")
- obj["Put/CallFlag"] = "C" if obj["callput"] else "P"
- obj["OptionType"] = "Vanilla European"
- return obj
-
-
-_citco_frequency = {"Yearly": 1, "Daily": 9, "Quarterly": 3}
-_citco_bdc = {"Modified Following": 4}
-_citco_daycount = {"ACT/360": 2}
-_citco_ratesource = {"SOFRRATE": 17819}
-_to_index = {"SOFRINDX": "SOFRRATE"}
-_citco_cp_isda = {
- "MSCSNY": "MS_IS",
- "GOLDNY": "GS_IS",
- "BAMSNY": "BOA_IS",
- "BNPBNY": "BNP_IS",
- "JPCBNY": "JPM_IS",
-}
-_citco_cp_cdea = {
- "MSCSNY": "MS_CD",
- "GOLDNY": "GS_CD",
- "BAMSNY": "BOA_CD",
- "BNPBNY": "BNP_CD",
- "JPCBNY": "JPM_CD",
- "CSFBBO": "CS_CD",
- "CITINY": "CIT_CD",
- "BARCNY": "BAR_CD",
-}
-
-
-@dataclass
-class IRSProduct(
- Deal,
- CitcoProduct,
- deal_type=DealType.IRSProduct,
- table_name="citco_irs",
- product_key=("birth_date", "death_date", "float_index", "fixed_rate"),
- insert_ignore=("id", "dealid", "security_desc"),
-):
- birth_date: datetime.date = field(metadata={"citco": "Birth_date"})
- death_date: datetime.date = field(metadata={"citco": "Death_date"})
- fixed_rate: float
- instrument_type: str = field(default="IRS", metadata={"citco": "InstrumentType"})
- active: str = field(default=True, metadata={"citco": "Active"})
- fixed_daycount: str = field(default="ACT/360")
- fixed_payment_freq: str = field(default="Yearly")
- fixed_bdc: str = field(default="Modified Following")
- float_index: str = field(default="SOFRRATE")
- float_daycount: str = field(default="ACT/360")
- float_payment_freq: str = field(default="Yearly")
- float_bdc: str = field(default="Modified Following")
- currency: str = field(default="USD", metadata={"citco": "LocalCcy"})
- float_fixing_freq: str = field(default="Daily")
- pay_interest_calc_method: str = field(default="Compound")
- committed: bool = field(default=False)
- security_desc: str = field(
- init=False, metadata={"insert": False, "citco": "Sec_Desc"}, default=None
- )
- id: int = field(default=None, metadata={"insert": False})
- dealid: str = field(
- default=None, metadata={"insert": False, "citco": "UniqueIdentifier"}
- )
-
- def __post_init__(self):
- self.get_productid()
- self.security_desc = f"SWAP IRS {self.float_index}-{self.fixed_rate}-{self.birth_date}-{self.death_date}"
-
- def to_citco(self):
- obj = super().to_citco()
- d = {
- "S_P_CurrencyCode": self.currency,
- "S_P_PaymentFreqID": _citco_frequency[self.fixed_payment_freq],
- "S_P_RateIndexID": 0,
- "S_P_AccrualMethodID": _citco_daycount[self.fixed_daycount],
- "S_P_InterestRate": self.fixed_rate,
- "S_P_DayConventionID": _citco_bdc[self.fixed_bdc],
- "S_P_ResetFreqID": 0,
- "S_R_CurrencyCode": self.currency,
- "S_R_PaymentFreqID": _citco_frequency[self.float_payment_freq],
- "S_R_RateIndexID": 28,
- "S_R_AccrualMethodID": _citco_daycount[self.float_daycount],
- "S_R_InterestRate": 0,
- "S_R_DayConventionID": _citco_bdc[self.float_bdc],
- "S_R_ResetFreqID": _citco_frequency[self.float_fixing_freq],
- "S_R_RateSource": _citco_ratesource[self.float_index],
- }
- obj.update(d)
- obj["Command"] = "N"
- obj["Active"] = "Y" if obj["Active"] else "N"
- obj["PrincipalExchTypeID"] = 1
- return obj
-
-
-@dataclass
-class TRSProduct(
- Deal,
- CitcoProduct,
- deal_type=DealType.TRSProduct,
- table_name="citco_trs",
- product_key=("birth_date", "death_date", "funding_index", "underlying_security"),
- insert_ignore=("id", "dealid", "security_desc"),
-):
- birth_date: datetime.date = field(metadata={"citco": "Birth_date"})
- death_date: datetime.date = field(metadata={"citco": "Death_date"})
- underlying_security: str = field(metadata={"citco": "UnderlyingSecurityId"})
- active: str = field(default=True, metadata={"citco": "Active"})
- funding_daycount: str = field(default="ACT/360")
- funding_freq: str = field(default="Quarterly")
- funding_payment_roll_convention: str = field(default="Modified Following")
- asset_daycount: str = field(default="ACT/360")
- asset_freq: str = field(default="Quarterly")
- asset_payment_roll_convention: str = field(default="Modified Following")
- currency: str = field(default="USD", metadata={"citco": "LocalCcy"})
- interest_calc_method: str = field(default="Compound")
- compound_avg_frequency: str = field(default="Daily")
- fixing_frequency: str = field(default="Daily")
- committed: bool = field(default=False)
- instrument_type: str = field(default="TRS", metadata={"citco": "InstrumentType"})
- funding_index: str = field(default="SOFRRATE", metadata={})
- security_desc: str = field(
- init=False, metadata={"insert": False, "citco": "Sec_Desc"}, default=None
- )
- id: int = field(default=None, metadata={"insert": False})
- dealid: str = field(
- default=None, metadata={"insert": False, "citco": "UniqueIdentifier"}
- )
-
- def __post_init__(self):
- self.get_productid()
- _citco_trs = {"4J623JAA8": "IBOXHY_TRS"}
- self.security_desc = f"{_citco_trs[self.underlying_security]}-{self.funding_index}-{self.birth_date}-{self.death_date}"
-
- def to_citco(self, action):
- if not self.id:
-
- self.stage()
- self.commit()
- self.get_productid()
- obj = super().to_citco(action)
- d = {
- "S_P_CurrencyCode": self.currency,
- "S_P_PaymentFreqID": _citco_frequency[self.funding_freq],
- "S_P_RateIndexID": 28,
- "S_P_AccrualMethodID": _citco_daycount[self.funding_daycount],
- "S_P_InterestRate": 0,
- "S_P_PaymentCalandarID": 3,
- "S_P_DayConventionID": _citco_bdc[self.funding_payment_roll_convention],
- "S_P_ResetFreqID": _citco_frequency[self.funding_freq],
- "S_P_RateSourceID": _citco_ratesource[self.funding_index],
- "S_R_CurrencyCode": self.currency,
- "S_R_PaymentFreqID": _citco_frequency[self.asset_freq],
- "S_R_RateIndexID": 0,
- "S_R_AccrualMethodID": _citco_daycount[self.asset_daycount],
- "S_R_InterestRate": 0,
- "S_R_PaymentCalandarID": 3,
- "S_R_DayConventionID": _citco_bdc[self.asset_payment_roll_convention],
- "S_R_ResetFreqID": _citco_frequency[self.asset_freq],
- "S_R_RateSourceID": 0,
- }
- obj.update(d)
- obj["Command"] = "N"
- obj["Active"] = "Y" if obj["Active"] else "N"
- obj["GeneralDirection"] = "F"
- obj["PrincipalExchTypeID"] = 3
- obj["UnderlyingIDSource"] = "RED"
- return obj