diff options
Diffstat (limited to 'python/process_queue.py')
| -rw-r--r-- | python/process_queue.py | 939 |
1 files changed, 623 insertions, 316 deletions
diff --git a/python/process_queue.py b/python/process_queue.py index 8a56a751..ca50d3ce 100644 --- a/python/process_queue.py +++ b/python/process_queue.py @@ -22,83 +22,270 @@ from gmail_helpers import GmailMessage from tabulate import tabulate 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', 'Reserved', 'GlopeOp Security Identifier', - 'CUSIP', 'ISIN', 'Reserved', 'Reserved', - 'Reserved', 'Security Description', 'Transaction Indicator', - 'SubTransaction Indicator', 'Accrued', 'Price', 'BlockId', 'BlockAmount', - 'Reserved', 'Resesrved', 'Reserved', 'Reserved', 'ClientReference', 'ClearingMode', - 'FaceAmount', 'Pool Factor', 'FactorAsOfDate', 'Delivery'], - '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", "Reserved", "Buy Currency", "Buy Amount", - "Sell Currency", "Sell Amount", "ClearingFees", "BlockId", - "BlockAmount", "Commission Currency", "Commission", "Reserved", - "AssociatedDealType", "AssociatedDealId", "BrokerShortName", - "ClientReference"] + "Deal Type", + "Deal Id", + "Action", + "Client", + "Fund", + "Portfolio", + "Folder", + "Custodian", + "Cash Account", + "Counterparty", + "Comments", + "State", + "Trade Date", +] +HEADERS = { + "bond": HEADERS_PRE + + [ + "Settlement Date", + "Reserved", + "GlopeOp Security Identifier", + "CUSIP", + "ISIN", + "Reserved", + "Reserved", + "Reserved", + "Security Description", + "Transaction Indicator", + "SubTransaction Indicator", + "Accrued", + "Price", + "BlockId", + "BlockAmount", + "Reserved", + "Resesrved", + "Reserved", + "Reserved", + "ClientReference", + "ClearingMode", + "FaceAmount", + "Pool Factor", + "FactorAsOfDate", + "Delivery", + ], + "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", + "Reserved", + "Buy Currency", + "Buy Amount", + "Sell Currency", + "Sell Amount", + "ClearingFees", + "BlockId", + "BlockAmount", + "Commission Currency", + "Commission", + "Reserved", + "AssociatedDealType", + "AssociatedDealId", + "BrokerShortName", + "ClientReference", + ], } + def get_effective_date(d, swaption_type): if swaption_type == "CD_INDEX_OPTION": return previous_twentieth(d + datetime.timedelta(days=1)) @@ -107,22 +294,22 @@ def get_effective_date(d, swaption_type): return pydate_from_qldate(cal.advance(Date.from_datetime(d), 2, Days)) -def get_trades(q, trade_type='bond', fund="SERCGMAST"): +def get_trades(q, trade_type="bond", fund="SERCGMAST"): queue_name = f"{trade_type}_{fund}" r = q.lrange(queue_name, 0, -1) df = [loads(e) for e in r] list_trades = [] if df: - for tradeid, v in groupby(df, lambda x: x['id']): + for tradeid, v in groupby(df, lambda x: x["id"]): trades = list(v) - trades = sorted(trades, key=lambda x: x['lastupdate']) + trades = sorted(trades, key=lambda x: x["lastupdate"]) if len(trades) == 1: list_trades.append(trades[0]) else: - if trades[-1]['action'] == 'CANCEL': + if trades[-1]["action"] == "CANCEL": continue - if trades[0]['action'] == 'NEW': - trades[-1]['action'] = 'NEW' + if trades[0]["action"] == "NEW": + trades[-1]["action"] = "NEW" list_trades.append(trades[-1]) return list_trades @@ -135,279 +322,384 @@ def rename_keys(d, mapping): def build_termination(obj): - headers = ['DealType', 'DealId', 'Action', 'Client', 'SubAction', 'PartialTermination', - 'TerminationAmount', 'TerminationDate', 'FeesPaid', 'FeesReceived', - 'DealFunction', 'Reserved', 'ClientReference'] + ['Reserved'] * 4 + \ - ['SpecialInstructions', 'AssignedCounterparty'] + ['Reserved'] * 7 + \ - ['GoTradeId'] + ['Reserved'] * 8 + ['InMoney', 'FeeCurrency'] - return ['SwaptionDeal', obj['dealid'], 'Update', 'Serenitas', 'Termination'] + headers = ( + [ + "DealType", + "DealId", + "Action", + "Client", + "SubAction", + "PartialTermination", + "TerminationAmount", + "TerminationDate", + "FeesPaid", + "FeesReceived", + "DealFunction", + "Reserved", + "ClientReference", + ] + + ["Reserved"] * 4 + + ["SpecialInstructions", "AssignedCounterparty"] + + ["Reserved"] * 7 + + ["GoTradeId"] + + ["Reserved"] * 8 + + ["InMoney", "FeeCurrency"] + ) + return ["SwaptionDeal", obj["dealid"], "Update", "Serenitas", "Termination"] def build_line(obj, trade_type="bond"): - obj['Client'] = 'Serenitas' - obj['State'] = 'Valid' - rename_cols = {'fund': 'Fund', - 'action': 'Action', - 'dealid': 'Deal Id', - 'folder': 'Folder', - 'custodian': 'Custodian', - 'cashaccount': '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', - 'curr_notional': 'Notional', - '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'} + obj["Client"] = "Serenitas" + obj["State"] = "Valid" + rename_cols = { + "fund": "Fund", + "action": "Action", + "dealid": "Deal Id", + "folder": "Folder", + "custodian": "Custodian", + "cashaccount": "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", + "curr_notional": "Notional", + "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", + } 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' + 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', - 'Price': 'PercentageOfPremium', - 'notional': 'Notional', - 'initial_margin_percentage': 'InitialMarginPercentage'}) + 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", + "Price": "PercentageOfPremium", + "notional": "Notional", + "initial_margin_percentage": "InitialMarginPercentage", + }, + ) - 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['Trade Date'], - 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' + 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["Trade Date"], 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" - if obj['option_type'] == 'PAYER': - obj['ReceiveLegRateType'] = 'Float' - obj['ReceiveFloatRate'] = 'US0003M' - obj['PayLegRateType'] = 'Fixed' - obj['PayFixedRate'] = obj['FixedRate'] - elif obj['option_type'] == 'RECEIVER': - obj['PayLegRateType'] = 'Float' - obj['PayFloatRate'] = 'US0003M' - obj['ReceiveLegRateType'] = 'Fixed' - obj['ReceiveFixedRate'] = obj['FixedRate'] - elif obj['SwapType'] == 'SWAPTION': - for direction in ['Pay', 'Receive']: - obj[direction + 'PaymentRollConvention'] = 'ModifiedFollowing' - if (obj['buysell'] and obj['option_type'] == 'RECEIVER') or\ - (not obj['buysell'] and obj['option_type'] == 'PAYER'): - obj['ReceiveFrequency'] = 'Half-Yearly' - obj['ReceiveDaycount'] = '30/360' - obj['PayFrequency'] = 'Quarterly' - obj['PayDaycount'] = 'ACT/360' - obj['ReceiveFixedRate'] = obj['strike'] - obj['ReceiveLegRateType'] = 'Fixed' - obj['PayLegRateType'] = 'Float' - obj['PayFloatRate'] = 'US0003M' + if obj["option_type"] == "PAYER": + obj["ReceiveLegRateType"] = "Float" + obj["ReceiveFloatRate"] = "US0003M" + obj["PayLegRateType"] = "Fixed" + obj["PayFixedRate"] = obj["FixedRate"] + elif obj["option_type"] == "RECEIVER": + obj["PayLegRateType"] = "Float" + obj["PayFloatRate"] = "US0003M" + obj["ReceiveLegRateType"] = "Fixed" + obj["ReceiveFixedRate"] = obj["FixedRate"] + elif obj["SwapType"] == "SWAPTION": + for direction in ["Pay", "Receive"]: + obj[direction + "PaymentRollConvention"] = "ModifiedFollowing" + if (obj["buysell"] and obj["option_type"] == "RECEIVER") or ( + not obj["buysell"] and obj["option_type"] == "PAYER" + ): + obj["ReceiveFrequency"] = "Half-Yearly" + obj["ReceiveDaycount"] = "30/360" + obj["PayFrequency"] = "Quarterly" + obj["PayDaycount"] = "ACT/360" + obj["ReceiveFixedRate"] = obj["strike"] + obj["ReceiveLegRateType"] = "Fixed" + obj["PayLegRateType"] = "Float" + obj["PayFloatRate"] = "US0003M" else: - obj['ReceiveFrequency'] = 'Quarterly' - obj['ReceiveDaycount'] = 'ACT/360' - obj['PayFrequency'] = 'Half-Yearly' - obj['PayDaycount'] = '30/360' - obj['ReceiveFloatRate'] = 'US0003M' - obj['ReceiveLegRateType'] = 'Float' - obj['PayLegRateType'] = 'Fixed' - obj['PayFixedRate'] = obj['strike'] + obj["ReceiveFrequency"] = "Quarterly" + obj["ReceiveDaycount"] = "ACT/360" + obj["PayFrequency"] = "Half-Yearly" + obj["PayDaycount"] = "30/360" + obj["ReceiveFloatRate"] = "US0003M" + obj["ReceiveLegRateType"] = "Float" + obj["PayLegRateType"] = "Fixed" + obj["PayFixedRate"] = obj["strike"] else: - raise ValueError("'SwapType' needs to be one of 'CD_INDEX_OPTION' or 'SWAPTION'") + 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') + 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.get('AttachmentPoint') is None: - obj['Executing Broker'] = obj['Counterparty'] - if obj['account_code'] == 'BAML': - obj['Counterparty'] = 'BAMSNY' - obj['Custodian'] = 'BOMLCM' - elif obj['account_code'] == 'WF': - obj['Counterparty'] = 'WELFEI' - obj['Custodian'] = 'WELLSFCM' - if obj['Clearing Facility'] is None: - obj['Clearing Facility'] = 'NOT CLEARED' + 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.get("AttachmentPoint") is None: + obj["Executing Broker"] = obj["Counterparty"] + if obj["account_code"] == "BAML": + obj["Counterparty"] = "BAMSNY" + obj["Custodian"] = "BOMLCM" + elif obj["account_code"] == "WF": + obj["Counterparty"] = "WELFEI" + obj["Custodian"] = "WELLSFCM" + if obj["Clearing Facility"] is None: + obj["Clearing Facility"] = "NOT CLEARED" - elif trade_type == 'future': - obj['Deal Type'] = 'FutureDeal' - rename_keys(obj, {'currency': 'Trade Currency', - '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'] - rename_keys(obj, {'amount': 'Amount'}) - elif trade_type == 'spot': - obj['Deal Type'] = 'SpotDeal' - 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': 'Spot Rate'}) + elif trade_type == "future": + obj["Deal Type"] = "FutureDeal" + rename_keys( + obj, + { + "currency": "Trade Currency", + "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"] + rename_keys(obj, {"amount": "Amount"}) + elif trade_type == "spot": + obj["Deal Type"] = "SpotDeal" + 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": "Spot Rate", + }, + ) return [obj.get(h, None) for h in HEADERS[trade_type]] -def get_bbg_data(conn, session, identifier, cusip=None, isin=None, - settle_date=None, asset_class=None, **kwargs): +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"] - fields_dict = {'Mtge': ["MTG_FACE_AMT", "START_ACC_DT"], - 'Corp': ["AMT_ISSUED", "PREV_CPN_DT"]} + 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,)) + c.execute( + "SELECT identifier FROM securities WHERE identifier=%s", (identifier,) + ) if not c.fetchone(): - fields += ["MATURITY", "CRNCY", "NAME", "FLOATER", "FLT_SPREAD", "CPN", - "CPN_FREQ", "FIRST_CPN_DT", "MTG_PAY_DELAY", "DAY_CNT_DES"] + fields += [ + "MATURITY", + "CRNCY", + "NAME", + "FLOATER", + "FLT_SPREAD", + "CPN", + "CPN_FREQ", + "FIRST_CPN_DT", + "MTG_PAY_DELAY", + "DAY_CNT_DES", + ] 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) + 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') + 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) > 2: # 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'] + 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) > 2: # 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", + ] placeholders = ",".join(["%s"] * len(sql_fields)) columns = ",".join(sql_fields) sqlstr = f"INSERT INTO securities({columns}) VALUES({placeholders})" - isfloater = bbg_data['FLOATER'] == 'Y' - pay_delay = bbg_data.get('MTG_PAY_DELAY', 0) - day_count = bbg_data.get('DAY_CNT_DES') + isfloater = bbg_data["FLOATER"] == "Y" + pay_delay = bbg_data.get("MTG_PAY_DELAY", 0) + day_count = bbg_data.get("DAY_CNT_DES") m = re.match("[^(\s]+", day_count) if m: day_count = m.group(0) if isinstance(pay_delay, str): - pay_delay = int(pay_delay.split(' ')[0]) + 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'))) + 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"), + ), + ) conn.commit() return bbg_data + def bond_trade_process(conn, session, trade): bbg_data = get_bbg_data(conn, session, **trade) - currentface = trade['faceamount'] * bbg_data['MTG_FACTOR_SET_DT'] - accrued_payment = bbg_data['INT_ACC'] * currentface /100. - principal_payment = currentface * trade['price'] / 100. + currentface = trade["faceamount"] * bbg_data["MTG_FACTOR_SET_DT"] + accrued_payment = bbg_data["INT_ACC"] * currentface / 100.0 + principal_payment = currentface * trade["price"] / 100.0 with conn: with conn.cursor() as c: - c.execute("UPDATE bonds SET principal_payment = %s, accrued_payment = %s " - "WHERE id = %s", (principal_payment, accrued_payment, int(trade['id']))) + c.execute( + "UPDATE bonds SET principal_payment = %s, accrued_payment = %s " + "WHERE id = %s", + (principal_payment, accrued_payment, int(trade["id"])), + ) # mark it at buy price - if trade['buysell']: + if trade["buysell"]: sqlstr = "INSERT INTO marks VALUES(%s, %s, %s) ON CONFLICT DO NOTHING" with conn: with conn.cursor() as c: - c.execute(sqlstr, (trade['trade_date'], trade['identifier'], trade['price'])) + c.execute( + sqlstr, (trade["trade_date"], trade["identifier"], trade["price"]) + ) def send_email(trade): # send out email with trade content email = GmailMessage() email.set_content(print_trade(trade)) - email['To'] = 'nyops@lmcg.com' - email['Subject'] = email_subject(trade) + email["To"] = "nyops@lmcg.com" + email["Subject"] = email_subject(trade) email.send() def is_tranche_trade(trade): - return trade['swap_type'] in ('CD_INDEX_TRANCHE', 'BESPOKE') + return trade["swap_type"] in ("CD_INDEX_TRANCHE", "BESPOKE") def cds_trade_process(conn, session, trade): - sqlstr = ("SELECT indexfactor/100 FROM index_version " - "WHERE redindexcode=%(security_id)s") + 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') + bbg_data = get_bbg_data( + conn, + session, + trade["security_id"], + isin=trade["security_id"], + asset_class="Subprime", + ) - factor = bbg_data['MTG_FACTOR_SET_DT'] + 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 + tranche_factor = (trade["attach"] - trade["detach"]) / ( + trade["orig_attach"] - trade["orig_detach"] + ) + trade["curr_notional"] = trade["notional"] * tranche_factor else: - trade['curr_notional'] = trade['notional'] * factor + trade["curr_notional"] = trade["notional"] * factor return trade @@ -425,59 +717,73 @@ def generate_csv(l, trade_type="bond", fund="SERCGMAST"): return output.getvalue().encode() -def get_filepath(base_dir: pathlib.Path, trade_type: str, - fund: str) -> pathlib.Path: - d = {'bond': 'Mortgages', - 'cds': 'CreditDefaultSwapDeal', - 'swaption': 'SwaptionDeal', - 'future': 'Future', - 'wire': 'CashFlowDeal', - 'spot': 'SpotDeal', - 'capfloor': 'TODO'} +def get_filepath(base_dir: pathlib.Path, trade_type: str, fund: str) -> pathlib.Path: + d = { + "bond": "Mortgages", + "cds": "CreditDefaultSwapDeal", + "swaption": "SwaptionDeal", + "future": "Future", + "wire": "CashFlowDeal", + "spot": "SpotDeal", + "capfloor": "TODO", + } timestamp = datetime.datetime.now() if fund == "BRINKER": - return (base_dir / str(timestamp.date()) / - f"LMCG_BBH_SWAP_TRADES_P.{timestamp:%Y%m%d%H%M%S}.csv") + return ( + base_dir + / str(timestamp.date()) + / f"LMCG_BBH_SWAP_TRADES_P.{timestamp:%Y%m%d%H%M%S}.csv" + ) else: - return (base_dir / str(timestamp.date()) / - f'Serenitas.ALL.{timestamp:%Y%m%d.%H%M%S}.{d[trade_type]}.csv') + return ( + base_dir + / str(timestamp.date()) + / f"Serenitas.ALL.{timestamp:%Y%m%d.%H%M%S}.{d[trade_type]}.csv" + ) def upload_file(file_path: pathlib.Path) -> None: if "BBH" in file_path.name: return - ftp = FTP('ftp.globeop.com') - ftp.login('srntsftp', config.ftp_password) - ftp.cwd('incoming') + ftp = FTP("ftp.globeop.com") + ftp.login("srntsftp", config.ftp_password) + ftp.cwd("incoming") cmd = f"STOR {file_path.name}" with file_path.open("rb") as fh: - ftp.storbinary(cmd, fh) + ftp.storbinary(cmd, fh) -def write_buffer(buf: bytes, base_dir: pathlib.Path, - trade_type: str = "bond", - fund: str = "SERCGMAST"): +def write_buffer( + buf: bytes, + base_dir: pathlib.Path, + trade_type: str = "bond", + fund: str = "SERCGMAST", +): file_path = get_filepath(base_dir, trade_type, fund) file_path.write_bytes(buf) return file_path def email_subject(trade): - return "[{0}] {1} {2} {3}".format(trade['asset_class'], trade['action'], - "Buy" if trade['buysell'] else "Sell", - trade['description']) + return "[{0}] {1} {2} {3}".format( + trade["asset_class"], + trade["action"], + "Buy" if trade["buysell"] else "Sell", + trade["description"], + ) def print_trade(trade): d = trade.copy() - d['buysell'] = "Buy" if d["buysell"] else "Sell" + d["buysell"] = "Buy" if d["buysell"] else "Sell" return tabulate((k, v) for k, v in d.items()) if __name__ == "__main__": parser = argparse.ArgumentParser() - parser.add_argument("-n", "--no-upload", action="store_true", - help="do not upload to Globeop") + parser.add_argument( + "-n", "--no-upload", action="store_true", help="do not upload to Globeop" + ) parser.add_argument("fund", nargs="?", default="SERCGMAST") args = parser.parse_args() q = get_redis_queue() @@ -486,11 +792,11 @@ if __name__ == "__main__": except KeyError: sys.exit("Please set path of daily directory in 'DAILY_DIR'") - dawndb = dbconn('dawndb') - for trade_type in ['bond', 'cds', 'swaption', 'future', 'wire', 'spot', 'capfloor']: + dawndb = dbconn("dawndb") + for trade_type in ["bond", "cds", "swaption", "future", "wire", "spot", "capfloor"]: list_trades = get_trades(q, trade_type, args.fund) if list_trades: - if trade_type in ['bond', 'cds']: + if trade_type in ["bond", "cds"]: process_fun = globals()[f"{trade_type}_trade_process"] with init_bbg_session(BBG_IP) as session: for trade in list_trades: @@ -503,9 +809,10 @@ if __name__ == "__main__": try: buf = generate_csv( filter(lambda t: t.get("upload", True), list_trades), - trade_type, args.fund) - file_path = write_buffer(buf, DAILY_DIR, - trade_type, args.fund) + trade_type, + args.fund, + ) + file_path = write_buffer(buf, DAILY_DIR, trade_type, args.fund) if not args.no_upload: upload_file(file_path) except IOError: |
