diff options
Diffstat (limited to 'python/Dawn')
| -rw-r--r-- | python/Dawn/models.py | 656 | ||||
| -rw-r--r-- | python/Dawn/utils.py | 12 | ||||
| -rw-r--r-- | python/Dawn/views.py | 430 |
3 files changed, 719 insertions, 379 deletions
diff --git a/python/Dawn/models.py b/python/Dawn/models.py index 39bac9cf..c094f531 100644 --- a/python/Dawn/models.py +++ b/python/Dawn/models.py @@ -7,8 +7,9 @@ from sqlalchemy_utils import EmailType, PhoneNumberType from . import db + class Counterparties(db.Model): - __tablename__ = 'counterparties' + __tablename__ = "counterparties" code = db.Column(db.String(12), primary_key=True) name = db.Column(db.String) city = db.Column(db.String) @@ -26,140 +27,294 @@ class Counterparties(db.Model): valuation_contact4 = db.Column(db.String) valuation_email4 = db.Column(EmailType) notes = db.Column(db.String) - instructions = db.Column(db.String, info={'form_field_class': FileField}) + instructions = db.Column(db.String, info={"form_field_class": FileField}) + class Accounts(db.Model): - __tablename__ = 'accounts' + __tablename__ = "accounts" code = db.Column(db.String(5), primary_key=True) name = db.Column(db.String) custodian = db.Column(db.String) cash_account = db.Column(db.String) - counterparty = db.Column(db.String(12), db.ForeignKey('counterparties.code')) + counterparty = db.Column(db.String(12), db.ForeignKey("counterparties.code")) + + +FUND = ENUM("SERCGMAST", "BRINKER", name="fund") -FUND = ENUM('SERCGMAST', 'BRINKER', name='fund') +PORTFOLIO = ENUM( + "OPTIONS", + "IR", + "MORTGAGES", + "IG", + "HY", + "CURVE", + "TRANCHE", + "CLO", + "HEDGE_MAC", + "STRUCTURED", + name="portfolio", +) -PORTFOLIO = ENUM('OPTIONS', 'IR', 'MORTGAGES', 'IG', 'HY', 'CURVE', 'TRANCHE', - 'CLO', 'HEDGE_MAC', 'STRUCTURED', name='portfolio') +BOND_STRAT = ENUM( + "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", + "CRT_SD", + "CRT_LD", + "CRT_LD_JNR", + name="bond_strat", +) -BOND_STRAT = ENUM('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', 'CRT_SD', 'CRT_LD', 'CRT_LD_JNR', - name='bond_strat') +CDS_STRAT = ENUM( + "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_IGCURVE", + "MBSCDS", + "IGOPTDEL", + "HYOPTDEL", + "SER_ITRXCURVE", + "HYEQY", + "HYMEZ", + "HYSNR", + "HYINX", + "IGEQY", + "IGMEZ", + "IGSNR", + "IGINX", + "BSPK", + name="cds_strat", +) -CDS_STRAT = ENUM('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_IGCURVE', 'MBSCDS', - 'IGOPTDEL', 'HYOPTDEL', 'SER_ITRXCURVE', - 'HYEQY', 'HYMEZ', 'HYSNR', 'HYINX', 'IGEQY', 'IGMEZ', - 'IGSNR', 'IGINX', 'BSPK', name='cds_strat') +SWAPTION_STRAT = ENUM( + "IGPAYER", "IGREC", "HYPAYER", "HYREC", "STEEP", name="swaption_strat" +) -SWAPTION_STRAT = ENUM('IGPAYER', 'IGREC', 'HYPAYER', 'HYREC', 'STEEP', - name='swaption_strat') +FUTURE_STRAT = ENUM( + "M_STR_MAV", + "M_MTG_IO", + "M_STR_MEZZ", + "M_MTG_RW", + "SER_ITRXCURVE", + "M_CSH_CASH", + "DELTAONE", + name="future_strat", +) -FUTURE_STRAT = ENUM('M_STR_MAV', 'M_MTG_IO', 'M_STR_MEZZ', 'M_MTG_RW', 'SER_ITRXCURVE', - 'M_CSH_CASH', 'DELTAONE', name='future_strat') +CASH_STRAT = ENUM( + "M_CSH_CASH", + "MBSCDSCSH", + "SER_IGCVECSH", + "SER_ITRXCVCSH", + "CSOCDSCSH", + "IGCDSCSH", + "HYCDSCSH", + "CLOCDSCSH", + "IGTCDSCSH", + "MACCDSCSH", + "M_STR_MEZZ", + "IRDEVCSH", + "TCSH", + "COCSH", + name="cash_strat", +) -CASH_STRAT = ENUM('M_CSH_CASH', 'MBSCDSCSH', 'SER_IGCVECSH', 'SER_ITRXCVCSH', 'CSOCDSCSH', - 'IGCDSCSH', 'HYCDSCSH', 'CLOCDSCSH', 'IGTCDSCSH', 'MACCDSCSH', 'M_STR_MEZZ', - 'IRDEVCSH', 'TCSH', 'COCSH', - name='cash_strat') +SPOT_STRAT = ENUM( + "M_STR_MAV", "M_STR_MEZZ", "SER_ITRXCURVE", "M_CSH_CASH", name="spot_strat" +) -SPOT_STRAT = ENUM('M_STR_MAV', 'M_STR_MEZZ', 'SER_ITRXCURVE', 'M_CSH_CASH', - name='spot_strat') +OPTION_TYPE = ENUM("PAYER", "RECEIVER", name="option_type") -OPTION_TYPE = ENUM('PAYER', 'RECEIVER', - name='option_type') +SWAPTION_TYPE = ENUM("CD_INDEX_OPTION", "SWAPTION", name="swaption_type") +SETTLEMENT_TYPE = ENUM("Delivery", "Cash", name="settlement_type") -SWAPTION_TYPE = ENUM('CD_INDEX_OPTION', 'SWAPTION', name='swaption_type') -SETTLEMENT_TYPE = ENUM('Delivery', 'Cash', name='settlement_type') +REPO_TYPE = ENUM("REPO", "REVERSE REPO", name="repo_type") +FUTURE_TYPE = ENUM( + "FUTURE", "CFD", "SYNTHETIC-FUTURE", "LME-FORWARD", name="future_type" +) -REPO_TYPE = ENUM('REPO', 'REVERSE REPO', name='repo_type') -FUTURE_TYPE = ENUM('FUTURE', 'CFD', 'SYNTHETIC-FUTURE', 'LME-FORWARD', name='future_type') +CALL_NOTICE = ENUM( + "24H", + "48H", + "3D", + "4D", + "5D", + "6D", + "1W", + "8D", + "9D", + "10D", + "2W", + "1M", + "2M", + name="call_notice", +) -CALL_NOTICE = ENUM('24H', '48H', '3D', '4D', '5D', '6D', - '1W', '8D', '9D', '10D', '2W', '1M', '2M', name='call_notice') +ASSET_CLASS = ENUM( + "CSO", + "Subprime", + "CLO", + "Tranches", + "Futures", + "Cash", + "FX", + "Cleared", + name="asset_class", +) +ACTION = ENUM("NEW", "UPDATE", "CANCEL", name="action") -ASSET_CLASS = ENUM('CSO', 'Subprime', 'CLO', 'Tranches', 'Futures', 'Cash', 'FX', 'Cleared', - name='asset_class') -ACTION = ENUM('NEW', 'UPDATE', 'CANCEL', name='action') +CCY = ENUM("USD", "CAD", "EUR", "YEN", name="currency") -CCY = ENUM('USD', 'CAD', 'EUR', 'YEN', name='currency') +BBG_TYPE = ENUM("Mtge", "Corp", name="bbg_type") -BBG_TYPE = ENUM('Mtge', 'Corp', name='bbg_type') +SWAP_TYPE = ENUM( + "CD_INDEX", + "CD_INDEX_TRANCHE", + "CD_BASKET_TRANCHE", + "ABS_CDS", + "BESPOKE", + name="swap_type", +) -SWAP_TYPE = ENUM('CD_INDEX', 'CD_INDEX_TRANCHE', 'CD_BASKET_TRANCHE', - 'ABS_CDS', 'BESPOKE', name='swap_type') +ISDA = ENUM("ISDA2014", "ISDA2003Cred", name="isda") -ISDA = ENUM('ISDA2014', 'ISDA2003Cred', name='isda') +DAY_COUNT = ENUM("ACT/360", "ACT/ACT", "30/360", "ACT/365", name="day_count") +FREQ = ENUM( + "Yearly", + "Half-Yearly", + "Quarterly", + "Bi-Monthly", + "Monthly", + "Weekly", + "Daily", + "Straight", + name="frequency", +) +BUS_DAY_CONVENTION = ENUM( + "Modified Following", + "Following", + "Modified Preceding", + "Preceding", + "Second-Day-After", + "End-of-Month", + name="bus_day_convention", +) +PROTECTION = ENUM("Buyer", "Seller", name="protection") -DAY_COUNT = ENUM('ACT/360', 'ACT/ACT', '30/360', 'ACT/365', name='day_count') -FREQ = ENUM('Yearly', 'Half-Yearly', 'Quarterly', 'Bi-Monthly', 'Monthly', - 'Weekly', 'Daily', 'Straight', name='frequency') -BUS_DAY_CONVENTION = ENUM('Modified Following', 'Following', 'Modified Preceding', 'Preceding', - 'Second-Day-After', 'End-of-Month', name='bus_day_convention') -PROTECTION = ENUM('Buyer', 'Seller', name='protection') +CAPFLOOR_TYPE = ENUM( + "CAPFLOOR", "CMS_OPTION", "STRUCTURED", "FORWARD_PREMIUM", name="capfloor_type" +) +CAPFLOOR = ENUM("C", "F", name="cap_or_floor") +PAYMENT_MODE = ENUM("F", "S", name="payment_mode") +PRICING_TYPE = ENUM("PlainVanilla", "EquityIndex", name="pricing_type") +BEGIN_OR_END = ENUM("B", "E", name="begin_or_end") -CAPFLOOR_TYPE = ENUM('CAPFLOOR', 'CMS_OPTION', 'STRUCTURED', 'FORWARD_PREMIUM', name='capfloor_type') -CAPFLOOR = ENUM('C', 'F', name='cap_or_floor') -PAYMENT_MODE = ENUM('F', 'S', name='payment_mode') -PRICING_TYPE = ENUM('PlainVanilla', 'EquityIndex', name='pricing_type') -BEGIN_OR_END = ENUM('B', 'E', name='begin_or_end') class BondDeal(db.Model): - __tablename__ = 'bonds' - id = db.Column('id', db.Integer, primary_key=True) - fund = db.Column(FUND, nullable=False, default='SERCGMAST') + __tablename__ = "bonds" + id = db.Column("id", db.Integer, primary_key=True) + fund = db.Column(FUND, nullable=False, default="SERCGMAST") dealid = db.Column(db.String(28)) - lastupdate = db.Column(db.DateTime, server_default=db.func.now(), onupdate=db.func.now()) + lastupdate = db.Column( + db.DateTime, server_default=db.func.now(), onupdate=db.func.now() + ) action = db.Column(ACTION, nullable=False) folder = db.Column(BOND_STRAT, nullable=False) - custodian = db.Column(db.String(12), default='BAC', nullable=False) - cashaccount = db.Column(db.String(10), default='V0NSCLMAMB', nullable=False) - cp_code = db.Column(db.String(12), db.ForeignKey('counterparties.code'), - info={'choices': [(None, '')], - 'label': 'counterparty'}, nullable=False) - trade_date = db.Column(db.Date, nullable = False) - settle_date = db.Column(db.Date, nullable = False) - cusip = db.Column(db.String(9), info={'validators': Length(9, 9), - 'filters': [lambda x: x or None,], - 'trim': True}) - isin = db.Column(db.String(12), info={'validators': Length(12, 12), - 'filters': [lambda x: x or None,], - 'trim': True}) - identifier = db.Column(db.String(12), info={'filters': [lambda x: x or None,], - 'trim': True}) - description = db.Column(db.String(32), nullable = False, info={'trim': True}) - buysell = db.Column(db.Boolean, nullable=False, info={'choices': [(0, 'sell'), (1, 'buy')], - 'coerce': lambda x: bool(int(x)) \ - if x is not None else x}) + custodian = db.Column(db.String(12), default="BAC", nullable=False) + cashaccount = db.Column(db.String(10), default="V0NSCLMAMB", nullable=False) + cp_code = db.Column( + db.String(12), + db.ForeignKey("counterparties.code"), + info={"choices": [(None, "")], "label": "counterparty"}, + nullable=False, + ) + trade_date = db.Column(db.Date, nullable=False) + settle_date = db.Column(db.Date, nullable=False) + cusip = db.Column( + db.String(9), + info={ + "validators": Length(9, 9), + "filters": [lambda x: x or None], + "trim": True, + }, + ) + isin = db.Column( + db.String(12), + info={ + "validators": Length(12, 12), + "filters": [lambda x: x or None], + "trim": True, + }, + ) + identifier = db.Column( + db.String(12), info={"filters": [lambda x: x or None], "trim": True} + ) + description = db.Column(db.String(32), nullable=False, info={"trim": True}) + buysell = db.Column( + db.Boolean, + nullable=False, + info={ + "choices": [(0, "sell"), (1, "buy")], + "coerce": lambda x: bool(int(x)) if x is not None else x, + }, + ) faceamount = db.Column(db.Float, nullable=False) price = db.Column(db.Float, nullable=False) - accrued = db.Column(db.Float, nullable = False) + accrued = db.Column(db.Float, nullable=False) asset_class = db.Column(ASSET_CLASS) - ticket = db.Column(db.String, info={'form_field_class': FileField}) + ticket = db.Column(db.String, info={"form_field_class": FileField}) principal_payment = db.Column(db.Float) accrued_payment = db.Column(db.Float) counterparty = db.relationship(Counterparties) - __table_args__= (db.CheckConstraint('cusip is not Null or isin is not Null'),) + __table_args__ = (db.CheckConstraint("cusip is not Null or isin is not Null"),) + class CDSDeal(db.Model): - __tablename__ = 'cds' - id = db.Column('id', db.Integer, primary_key=True) - fund = db.Column(FUND, nullable=False, default='SERCGMAST') + __tablename__ = "cds" + id = db.Column("id", db.Integer, primary_key=True) + fund = db.Column(FUND, nullable=False, default="SERCGMAST") dealid = db.Column(db.String(28)) - lastupdate = db.Column(db.DateTime, server_default=db.func.now(), onupdate=db.func.now()) + lastupdate = db.Column( + db.DateTime, server_default=db.func.now(), onupdate=db.func.now() + ) action = db.Column(ACTION, nullable=False) portfolio = db.Column(PORTFOLIO, nullable=False) folder = db.Column(CDS_STRAT, nullable=False) - account_code = db.Column(db.String(5), db.ForeignKey('accounts.code'), - info={'choices': [(None,'')], - 'label': 'fcm_account'}, nullable=False) - custodian = db.Column(db.String(12), default='NONE', nullable=False) - cashaccount = db.Column(db.String(10), default='V0NSCLMFCM', nullable=False) - cp_code = db.Column(db.String(12), db.ForeignKey('counterparties.code'), - info={'choices': [(None, '')], - 'label': 'counterparty'}, nullable=False) + account_code = db.Column( + db.String(5), + db.ForeignKey("accounts.code"), + info={"choices": [(None, "")], "label": "fcm_account"}, + nullable=False, + ) + custodian = db.Column(db.String(12), default="NONE", nullable=False) + cashaccount = db.Column(db.String(10), default="V0NSCLMFCM", nullable=False) + cp_code = db.Column( + db.String(12), + db.ForeignKey("counterparties.code"), + info={"choices": [(None, "")], "label": "counterparty"}, + nullable=False, + ) trade_date = db.Column(db.Date, nullable=False) effective_date = db.Column(db.Date, nullable=False) maturity = db.Column(db.Date, nullable=False) @@ -176,55 +331,80 @@ class CDSDeal(db.Model): upfront_settle_date = db.Column(db.Date, nullable=False) initial_margin_percentage = db.Column(db.Float) swap_type = db.Column(SWAP_TYPE, nullable=False) - orig_attach = db.Column(db.SmallInteger, info={'min': 0, 'max': 100}) - orig_detach = db.Column(db.SmallInteger, info={'min': 0, 'max': 100}) - attach = db.Column(db.Float, info={'min': 0., 'max': 100.}) - detach = db.Column(db.Float, info={'min': 0., 'max': 100.}) - corr_attach = db.Column(db.Float, info={'min': 0., 'max': 1.}) - corr_detach = db.Column(db.Float, info={'min': 0., 'max':1.}) + orig_attach = db.Column(db.SmallInteger, info={"min": 0, "max": 100}) + orig_detach = db.Column(db.SmallInteger, info={"min": 0, "max": 100}) + attach = db.Column(db.Float, info={"min": 0.0, "max": 100.0}) + detach = db.Column(db.Float, info={"min": 0.0, "max": 100.0}) + corr_attach = db.Column(db.Float, info={"min": 0.0, "max": 1.0}) + corr_detach = db.Column(db.Float, info={"min": 0.0, "max": 1.0}) index_ref = db.Column(db.Float) - clearing_facility = db.Column(db.String(12), default=None, - info={'filters': [lambda x: x or None,]}) + clearing_facility = db.Column( + db.String(12), default=None, info={"filters": [lambda x: x or None]} + ) isda_definition = db.Column(ISDA) termination_date = db.Column(db.Date) termination_amount = db.Column(db.Float) - termination_cp = db.Column(db.String(12), db.ForeignKey('counterparties.code'), - info={'choices': [(None, '')], - 'label': 'termination_counterparty'}) + termination_cp = db.Column( + db.String(12), + db.ForeignKey("counterparties.code"), + info={"choices": [(None, "")], "label": "termination_counterparty"}, + ) counterparty = db.relationship(Counterparties, foreign_keys=[cp_code]) - termination_counterparty = db.relationship(Counterparties, foreign_keys=[termination_cp]) + termination_counterparty = db.relationship( + Counterparties, foreign_keys=[termination_cp] + ) fcm_account = db.relationship(Accounts, foreign_keys=[account_code]) - __table_args__ = (db.CheckConstraint( - "(swap_type IN ('CD_INDEX_TRANCHE', 'BESPOKE') AND " - "(orig_attach IS NOT NULL AND orig_detach IS NOT NULL AND clearing_facility IS NULL))" - "OR (swap_type='CD_INDEX' AND " - "orig_attach IS NULL AND orig_detach IS NULL AND clearing_facility='ICE-CREDIT')" - "OR (swap_type='ABS_CDS' AND " - "orig_attach IS NULL AND orig_detach IS NULL AND clearing_faciliy IS NULL)"),) + __table_args__ = ( + db.CheckConstraint( + "(swap_type IN ('CD_INDEX_TRANCHE', 'BESPOKE') AND " + "(orig_attach IS NOT NULL AND orig_detach IS NOT NULL AND clearing_facility IS NULL))" + "OR (swap_type='CD_INDEX' AND " + "orig_attach IS NULL AND orig_detach IS NULL AND clearing_facility='ICE-CREDIT')" + "OR (swap_type='ABS_CDS' AND " + "orig_attach IS NULL AND orig_detach IS NULL AND clearing_faciliy IS NULL)" + ), + ) + class RepoDeal(db.Model): - __tablename__ = 'repo' - id = db.Column('id', db.Integer, primary_key=True) - fund = db.Column(FUND, nullable=False, default='SERCGMAST') - lastupdate = db.Column(db.DateTime, server_default=db.func.now(), onupdate=db.func.now()) + __tablename__ = "repo" + id = db.Column("id", db.Integer, primary_key=True) + fund = db.Column(FUND, nullable=False, default="SERCGMAST") + lastupdate = db.Column( + db.DateTime, server_default=db.func.now(), onupdate=db.func.now() + ) action = db.Column(ACTION, nullable=False) folder = db.Column(CDS_STRAT, nullable=False) - custodian = db.Column(db.String(12), default='SGFCM', nullable=False) - cashaccount = db.Column(db.String(10), default='V0NSCLMAMB', nullable=False) - cp_code = db.Column(db.String(12), db.ForeignKey('counterparties.code'), - info={'choices': [(None, '')], - 'label': 'counterparty'}, nullable=False) + custodian = db.Column(db.String(12), default="SGFCM", nullable=False) + cashaccount = db.Column(db.String(10), default="V0NSCLMAMB", nullable=False) + cp_code = db.Column( + db.String(12), + db.ForeignKey("counterparties.code"), + info={"choices": [(None, "")], "label": "counterparty"}, + nullable=False, + ) trade_date = db.Column(db.Date, nullable=False) settle_date = db.Column(db.Date, nullable=False) - cusip = db.Column(db.String(9), info={'validators': Length(9,9), - 'filters': [lambda x: x or None,], - 'trim': True}) - isin = db.Column(db.String(12), info={'validators': Length(12, 12), - 'filters': [lambda x: x or None,], - 'trim': True}) - identifier = db.Column(db.String(12), info={'filters': [lambda x: x or None,], - 'trim': True}) - description = db.Column(db.String(32), nullable=False, info={'trim': True}) + cusip = db.Column( + db.String(9), + info={ + "validators": Length(9, 9), + "filters": [lambda x: x or None], + "trim": True, + }, + ) + isin = db.Column( + db.String(12), + info={ + "validators": Length(12, 12), + "filters": [lambda x: x or None], + "trim": True, + }, + ) + identifier = db.Column( + db.String(12), info={"filters": [lambda x: x or None], "trim": True} + ) + description = db.Column(db.String(32), nullable=False, info={"trim": True}) transation_indicator = db.Column(REPO_TYPE) faceamount = db.Column(db.Float, nullable=False) price = db.Column(db.Float, nullable=False) @@ -235,32 +415,46 @@ class RepoDeal(db.Model): repo_rate = db.Column(db.Float, nullable=False) call_notice = db.Column(CALL_NOTICE) daycount = db.Column(DAY_COUNT) - ticket = db.Column(db.String, info={'form_field_class': FileField}) - __table__args = (db.CheckConstraint("haircut is not NULL and weighted_amount is NULL) or " \ - "haircut is NULL and weighted_amount is NOT NULL)"), - db.CheckConstraint("cusip is NOT NULL or isin is NOT NULL")) + ticket = db.Column(db.String, info={"form_field_class": FileField}) + __table__args = ( + db.CheckConstraint( + "haircut is not NULL and weighted_amount is NULL) or " + "haircut is NULL and weighted_amount is NOT NULL)" + ), + db.CheckConstraint("cusip is NOT NULL or isin is NOT NULL"), + ) class SwaptionDeal(db.Model): - __tablename__ = 'swaptions' - id = db.Column('id', db.Integer, primary_key=True) - fund = db.Column(FUND, nullable=False, default='SERCGMAST') + __tablename__ = "swaptions" + id = db.Column("id", db.Integer, primary_key=True) + fund = db.Column(FUND, nullable=False, default="SERCGMAST") dealid = db.Column(db.String(28), nullable=False) - lastupdate = db.Column(db.DateTime, server_default=db.func.now(), onupdate=db.func.now()) + lastupdate = db.Column( + db.DateTime, server_default=db.func.now(), onupdate=db.func.now() + ) action = db.Column(ACTION, nullable=False) portfolio = db.Column(PORTFOLIO, nullable=False) folder = db.Column(SWAPTION_STRAT, nullable=False) - custodian = db.Column(db.String(12), default='NONE', nullable=False) - cashaccount = db.Column(db.String(10), default='V0NSCLMAMB', nullable=False) - cp_code = db.Column(db.String(12), db.ForeignKey('counterparties.code'), - info={'choices': [(None, '')], - 'label': 'counterparty'}, nullable=False) + custodian = db.Column(db.String(12), default="NONE", nullable=False) + cashaccount = db.Column(db.String(10), default="V0NSCLMAMB", nullable=False) + cp_code = db.Column( + db.String(12), + db.ForeignKey("counterparties.code"), + info={"choices": [(None, "")], "label": "counterparty"}, + nullable=False, + ) swap_type = db.Column(SWAPTION_TYPE, nullable=False) trade_date = db.Column(db.Date, nullable=False) settle_date = db.Column(db.Date, nullable=False) - buysell = db.Column(db.Boolean, nullable=False, info={'choices': [(0, 'sell'), (1, 'buy')], - 'coerce': lambda x: bool(int(x)) - if x is not None else x}) + buysell = db.Column( + db.Boolean, + nullable=False, + info={ + "choices": [(0, "sell"), (1, "buy")], + "coerce": lambda x: bool(int(x)) if x is not None else x, + }, + ) notional = db.Column(db.Float, nullable=False) option_type = db.Column(OPTION_TYPE, nullable=False) strike = db.Column(db.Float, nullable=False) @@ -276,31 +470,45 @@ class SwaptionDeal(db.Model): settlement_type = db.Column(SETTLEMENT_TYPE, nullable=False) termination_date = db.Column(db.Date) termination_amount = db.Column(db.Float) - termination_cp = db.Column(db.String(12), db.ForeignKey('counterparties.code'), - info={'choices': [(None, '')], - 'label': 'termination_counterparty'}) + termination_cp = db.Column( + db.String(12), + db.ForeignKey("counterparties.code"), + info={"choices": [(None, "")], "label": "termination_counterparty"}, + ) counterparty = db.relationship(Counterparties, foreign_keys=[cp_code]) - termination_counterparty = db.relationship(Counterparties, foreign_keys=[termination_cp]) + termination_counterparty = db.relationship( + Counterparties, foreign_keys=[termination_cp] + ) class FutureDeal(db.Model): - __tablename__ = 'futures' - id = db.Column('id', db.Integer, primary_key=True) + __tablename__ = "futures" + id = db.Column("id", db.Integer, primary_key=True) fund = db.Column(FUND, nullable=False) dealid = db.Column(db.String(28), nullable=False) - lastupdate = db.Column(db.DateTime, server_default=db.func.now(), onupdate=db.func.now()) + lastupdate = db.Column( + db.DateTime, server_default=db.func.now(), onupdate=db.func.now() + ) action = db.Column(ACTION, nullable=False) folder = db.Column(FUTURE_STRAT, nullable=False) - custodian = db.Column(db.String(12), default='INTBR', nullable=False) - cashaccount = db.Column(db.String(10), default='IANSCLMAFU', nullable=False) - cp_code = db.Column(db.String(12), db.ForeignKey('counterparties.code'), - info={'choices': [('IBKRNY', 'Interactive Brokers')], - 'label': 'counterparty'}, nullable=False) + custodian = db.Column(db.String(12), default="INTBR", nullable=False) + cashaccount = db.Column(db.String(10), default="IANSCLMAFU", nullable=False) + cp_code = db.Column( + db.String(12), + db.ForeignKey("counterparties.code"), + info={"choices": [("IBKRNY", "Interactive Brokers")], "label": "counterparty"}, + nullable=False, + ) trade_date = db.Column(db.Date, nullable=False) settle_date = db.Column(db.Date, nullable=False) - buysell = db.Column(db.Boolean, nullable=False, info={'choices':[(0, 'sell'), (1, 'buy')], - 'coerce': lambda x: bool(int(x)) \ - if x is not None else x}) + buysell = db.Column( + db.Boolean, + nullable=False, + info={ + "choices": [(0, "sell"), (1, "buy")], + "coerce": lambda x: bool(int(x)) if x is not None else x, + }, + ) bbg_ticker = db.Column(db.String(32), nullable=False) quantity = db.Column(db.Float, nullable=False) price = db.Column(db.Float, nullable=False) @@ -309,17 +517,20 @@ class FutureDeal(db.Model): security_desc = db.Column(db.String(32), nullable=False) maturity = db.Column(db.Date, nullable=False) currency = db.Column(CCY, nullable=False) - exchange = db.Column(db.String(3), default='CME', nullable=False) + exchange = db.Column(db.String(3), default="CME", nullable=False) counterparty = db.relationship(Counterparties) + class CashFlowDeal(db.Model): - __tablename__ = 'wires' - id = db.Column('id', db.Integer, primary_key=True) + __tablename__ = "wires" + id = db.Column("id", db.Integer, primary_key=True) dealid = db.Column(db.String(28)) - lastupdate = db.Column(db.DateTime, server_default=db.func.now(), onupdate=db.func.now()) + lastupdate = db.Column( + db.DateTime, server_default=db.func.now(), onupdate=db.func.now() + ) action = db.Column(ACTION) folder = db.Column(CASH_STRAT, nullable=False) - code = db.Column(db.String(5), db.ForeignKey('accounts.code'), nullable=False) + code = db.Column(db.String(5), db.ForeignKey("accounts.code"), nullable=False) amount = db.Column(db.Float, nullable=False) currency = db.Column(CCY, nullable=False) trade_date = db.Column(db.Date, nullable=False) @@ -328,17 +539,22 @@ class CashFlowDeal(db.Model): class SpotDeal(db.Model): __tablename__ = "spots" - id = db.Column('id', db.Integer, primary_key=True) - fund = db.Column(FUND, nullable=False, default='SERCGMAST') + id = db.Column("id", db.Integer, primary_key=True) + fund = db.Column(FUND, nullable=False, default="SERCGMAST") dealid = db.Column(db.String(28), nullable=False) - lastupdate = db.Column(db.DateTime, server_default=db.func.now(), onupdate=db.func.now()) + lastupdate = db.Column( + db.DateTime, server_default=db.func.now(), onupdate=db.func.now() + ) action = db.Column(ACTION, nullable=False) folder = db.Column(SPOT_STRAT, nullable=False) - custodian = db.Column(db.String(12), default='INTBR', nullable=False) - cashaccount = db.Column(db.String(10), default='IANSCLMAFU', nullable=False) - cp_code = db.Column(db.String(12), db.ForeignKey('counterparties.code'), - info={'choices': [('IBKRNY', 'Interactive Brokers')], - 'label': 'counterparty'}, nullable=False) + custodian = db.Column(db.String(12), default="INTBR", nullable=False) + cashaccount = db.Column(db.String(10), default="IANSCLMAFU", nullable=False) + cp_code = db.Column( + db.String(12), + db.ForeignKey("counterparties.code"), + info={"choices": [("IBKRNY", "Interactive Brokers")], "label": "counterparty"}, + nullable=False, + ) trade_date = db.Column(db.Date, nullable=False) settle_date = db.Column(db.Date, nullable=False) spot_rate = db.Column(db.Float, nullable=False) @@ -350,62 +566,86 @@ class SpotDeal(db.Model): commission = db.Column(db.Float) counterparty = db.relationship(Counterparties) + class CapFloorDeal(db.Model): - __tablename__ = 'capfloors' - id = db.Column('id', db.Integer, primary_key=True) - fund = db.Column(FUND, nullable=False, default='SERCGMAST') + __tablename__ = "capfloors" + id = db.Column("id", db.Integer, primary_key=True) + fund = db.Column(FUND, nullable=False, default="SERCGMAST") dealid = db.Column(db.String(28), nullable=False) - lastupdate = db.Column(db.DateTime, server_default=db.func.now(), onupdate=db.func.now()) + lastupdate = db.Column( + db.DateTime, server_default=db.func.now(), onupdate=db.func.now() + ) action = db.Column(ACTION, nullable=False) folder = db.Column(SWAPTION_STRAT, nullable=False) - custodian = db.Column(db.String(12), default='NONE', nullable=False) - cashaccount = db.Column(db.String(10), default='V0NSCLMAMB', nullable=False) - cp_code = db.Column(db.String(12), db.ForeignKey('counterparties.code'), - info={'choices': [(None, '')], - 'label': 'counterparty'}, nullable=False) + custodian = db.Column(db.String(12), default="NONE", nullable=False) + cashaccount = db.Column(db.String(10), default="V0NSCLMAMB", nullable=False) + cp_code = db.Column( + db.String(12), + db.ForeignKey("counterparties.code"), + info={"choices": [(None, "")], "label": "counterparty"}, + nullable=False, + ) comments = db.Column(db.String(100)) - floating_rate_index = db.Column(db.String(12), nullable=False, - info={'label': 'Floating Rate Index'}) + floating_rate_index = db.Column( + db.String(12), nullable=False, info={"label": "Floating Rate Index"} + ) floating_rate_index_desc = db.Column(db.String(32)) - buysell = db.Column(db.Boolean, nullable=False, info={'choices':[(0, 'sell'), (1, 'buy')], - 'coerce': lambda x: bool(int(x)) \ - if x is not None else x}) - cap_or_floor = db.Column(CAPFLOOR, nullable=False, - info={'choices': [('C', 'Cap'), ('F', 'Floor')], - 'label': 'Cap or Floor?'}) + buysell = db.Column( + db.Boolean, + nullable=False, + info={ + "choices": [(0, "sell"), (1, "buy")], + "coerce": lambda x: bool(int(x)) if x is not None else x, + }, + ) + cap_or_floor = db.Column( + CAPFLOOR, + nullable=False, + info={"choices": [("C", "Cap"), ("F", "Floor")], "label": "Cap or Floor?"}, + ) strike = db.Column(db.Float, nullable=False) value_date = db.Column(db.Date, nullable=False) expiration_date = db.Column(db.Date, nullable=False) premium_percent = db.Column(db.Float, nullable=False) pricing_type = db.Column(PRICING_TYPE, nullable=False) - payment_frequency = db.Column(FREQ, nullable=False, default='Straight') - fixing_frequency = db.Column(FREQ, nullable=False, default='Straight') - day_count_counvention = db.Column(DAY_COUNT, default='Act/Act') - bdc_convention = db.Column(BUS_DAY_CONVENTION, default='Modified') - payment_mode = db.Column(PAYMENT_MODE, nullable=False, - info={'choices': [('F', 'Flat'), ('S', 'Schedule')]}) - payment_at_beginning_or_end = db.Column(BEGIN_OR_END, nullable=False, - info={'label': 'In arrears?', - 'choices': [('E', True), - ('B', False)]}) + payment_frequency = db.Column(FREQ, nullable=False, default="Straight") + fixing_frequency = db.Column(FREQ, nullable=False, default="Straight") + day_count_counvention = db.Column(DAY_COUNT, default="Act/Act") + bdc_convention = db.Column(BUS_DAY_CONVENTION, default="Modified") + payment_mode = db.Column( + PAYMENT_MODE, + nullable=False, + info={"choices": [("F", "Flat"), ("S", "Schedule")]}, + ) + payment_at_beginning_or_end = db.Column( + BEGIN_OR_END, + nullable=False, + info={"label": "In arrears?", "choices": [("E", True), ("B", False)]}, + ) initial_margin_percentage = db.Column(db.Float) initial_margin_currency = db.Column(CCY) - amount = db.Column(db.Float, nullable=False, info={'label': 'notional'}) + amount = db.Column(db.Float, nullable=False, info={"label": "notional"}) trade_date = db.Column(db.Date, nullable=False) swap_type = db.Column(CAPFLOOR_TYPE, nullable=False) reset_lag = db.Column(db.Integer, default=2) - trade_confirm = db.Column(db.String, info={'form_field_class': FileField}) + trade_confirm = db.Column(db.String, info={"form_field_class": FileField}) termination_date = db.Column(db.Date) termination_amount = db.Column(db.Float) - termination_cp = db.Column(db.String(12), db.ForeignKey('counterparties.code'), - info={'choices': [(None, '')], - 'label': 'termination counterparty'}) + termination_cp = db.Column( + db.String(12), + db.ForeignKey("counterparties.code"), + info={"choices": [(None, "")], "label": "termination counterparty"}, + ) cpty_id = db.Column(db.Text) counterparty = db.relationship(Counterparties, foreign_keys=[cp_code]) - termination_counterparty = db.relationship(Counterparties, - foreign_keys=[termination_cp]) + termination_counterparty = db.relationship( + Counterparties, foreign_keys=[termination_cp] + ) + BaseModelForm = model_form_factory(FlaskForm) + + class ModelForm(BaseModelForm): @classmethod def get_session(self): diff --git a/python/Dawn/utils.py b/python/Dawn/utils.py index 731d6dbb..3dd0d1c5 100644 --- a/python/Dawn/utils.py +++ b/python/Dawn/utils.py @@ -12,9 +12,13 @@ def bump_rev(filename): def simple_serialize(obj, **kwargs): d = {c.name: getattr(obj, c.name) for c in obj.__table__.columns} # add data from foreign relationship - if obj.__table__.name == 'wires': - d.update({'Counterparty': obj.account.counterparty, - 'cashaccount': obj.account.cash_account, - 'custodian': obj.account.custodian}) + if obj.__table__.name == "wires": + d.update( + { + "Counterparty": obj.account.counterparty, + "cashaccount": obj.account.cash_account, + "custodian": obj.account.custodian, + } + ) d.update(kwargs) return dumps(d) diff --git a/python/Dawn/views.py b/python/Dawn/views.py index 2960d78c..4dfb3c47 100644 --- a/python/Dawn/views.py +++ b/python/Dawn/views.py @@ -5,19 +5,38 @@ import psycopg2 import redis import socket -from flask import (abort, request, render_template, redirect, - url_for, send_from_directory, send_file, g, jsonify) +from flask import ( + abort, + request, + render_template, + redirect, + url_for, + send_from_directory, + send_file, + g, + jsonify, +) -from .models import (ModelForm, CASH_STRAT, CCY, - BondDeal, CDSDeal, SwaptionDeal, FutureDeal, CashFlowDeal, - CapFloorDeal, SpotDeal, Counterparties, Accounts) +from .models import ( + ModelForm, + CASH_STRAT, + CCY, + BondDeal, + CDSDeal, + SwaptionDeal, + FutureDeal, + CashFlowDeal, + CapFloorDeal, + SpotDeal, + Counterparties, + Accounts, +) from sqlalchemy.exc import IntegrityError from wtforms.fields import BooleanField from pandas.tseries.offsets import CustomBusinessDay -from pandas.tseries.holiday import (get_calendar, HolidayCalendarFactory, - GoodFriday) +from pandas.tseries.holiday import get_calendar, HolidayCalendarFactory, GoodFriday from pyisda.date import previous_twentieth from .utils import bump_rev, simple_serialize @@ -26,56 +45,61 @@ from io import BytesIO from . import app from . import db -fed_cal = get_calendar('USFederalHolidayCalendar') -bond_cal = HolidayCalendarFactory('BondCalendar', fed_cal, GoodFriday) +fed_cal = get_calendar("USFederalHolidayCalendar") +bond_cal = HolidayCalendarFactory("BondCalendar", fed_cal, GoodFriday) bus_day = CustomBusinessDay(calendar=bond_cal()) -def cp_choices(kind='bond'): - if kind == 'bond': - return (Counterparties.query.order_by('name'). - with_entities(Counterparties.code, Counterparties.name)) - elif kind in ['future', 'spot']: +def cp_choices(kind="bond"): + if kind == "bond": + return Counterparties.query.order_by("name").with_entities( + Counterparties.code, Counterparties.name + ) + elif kind in ["future", "spot"]: return [] - elif kind in ['cds', 'swaption', 'capfloor']: - return (Counterparties.query. - order_by('name'). - filter(Counterparties.name.ilike('%CDS%')). - with_entities(Counterparties.code, Counterparties.name)) + elif kind in ["cds", "swaption", "capfloor"]: + return ( + Counterparties.query.order_by("name") + .filter(Counterparties.name.ilike("%CDS%")) + .with_entities(Counterparties.code, Counterparties.name) + ) def account_codes(): - return Accounts.query.order_by('code').with_entities(Accounts.code, Accounts.name) + return Accounts.query.order_by("code").with_entities(Accounts.code, Accounts.name) + def fcm_accounts(): - return (Accounts.query. - order_by('code'). - filter(Accounts.name.ilike('%FCM%')). - with_entities(Accounts.code, Accounts.name)) + return ( + Accounts.query.order_by("code") + .filter(Accounts.name.ilike("%FCM%")) + .with_entities(Accounts.code, Accounts.name) + ) + def get_queue(): - q = getattr(g, 'queue', None) + q = getattr(g, "queue", None) if q is None: hostname = socket.gethostname() - if hostname == 'ziggy': - q = g.queue = redis.Redis(unix_socket_path='/run/redis/redis.sock') + if hostname == "ziggy": + q = g.queue = redis.Redis(unix_socket_path="/run/redis/redis.sock") else: - q = g.queue = redis.Redis(host='ziggy') + q = g.queue = redis.Redis(host="ziggy") return q def get_db(): - db = getattr(g, '_database', None) + db = getattr(g, "_database", None) if db is None: - db = g._database = psycopg2.connect(database="serenitasdb", - user="serenitas_user", - host="debian") + db = g._database = psycopg2.connect( + database="serenitasdb", user="serenitas_user", host="debian" + ) return db @app.teardown_appcontext def close_connection(exception): - db = getattr(g, '_database', None) + db = getattr(g, "_database", None) if db is not None: db.close() @@ -92,8 +116,12 @@ class BondForm(ModelForm): class Meta: model = BondDeal include_foreign_keys = True - exclude = ['dealid', 'lastupdate', # we generate it with a trigger at the server level - 'principal_payment', 'accrued_payment'] + exclude = [ + "dealid", + "lastupdate", # we generate it with a trigger at the server level + "principal_payment", + "accrued_payment", + ] class CDSForm(ModelForm): @@ -102,9 +130,17 @@ class CDSForm(ModelForm): class Meta: model = CDSDeal include_foreign_keys = True - exclude = ['dealid', 'lastupdate', 'termination_amount', - 'termination_cp', 'termination_date', 'custodian', - 'cashaccount', 'attach', 'detach'] + exclude = [ + "dealid", + "lastupdate", + "termination_amount", + "termination_cp", + "termination_date", + "custodian", + "cashaccount", + "attach", + "detach", + ] class SwaptionForm(ModelForm): @@ -113,8 +149,13 @@ class SwaptionForm(ModelForm): class Meta: model = SwaptionDeal include_foreign_keys = True - exclude = ['dealid', 'lastupdate', 'termination_amount', - 'termination_cp', 'termination_date'] + exclude = [ + "dealid", + "lastupdate", + "termination_amount", + "termination_cp", + "termination_date", + ] class FutureForm(ModelForm): @@ -123,7 +164,8 @@ class FutureForm(ModelForm): class Meta: model = FutureDeal include_foreign_keys = True - exclude = ['dealid', 'lastupdate'] + exclude = ["dealid", "lastupdate"] + class SpotForm(ModelForm): upload_globeop = BooleanField(label="Upload to globeop?") @@ -131,7 +173,7 @@ class SpotForm(ModelForm): class Meta: model = SpotDeal include_foreign_keys = True - exclude = ['dealid', 'lastupdate'] + exclude = ["dealid", "lastupdate"] class CapFloorForm(ModelForm): @@ -140,44 +182,49 @@ class CapFloorForm(ModelForm): class Meta: model = CapFloorDeal include_foreign_keys = True - exclude = ['dealid', 'lastupdate', 'termination_amount', - 'termination_cp', 'termination_date'] + exclude = [ + "dealid", + "lastupdate", + "termination_amount", + "termination_cp", + "termination_date", + ] def get_deal(kind): - if kind == 'cds': + if kind == "cds": return CDSDeal - elif kind == 'bond': + elif kind == "bond": return BondDeal - elif kind == 'swaption': + elif kind == "swaption": return SwaptionDeal - elif kind == 'future': + elif kind == "future": return FutureDeal - elif kind == 'wire': + elif kind == "wire": return CashFlowDeal - elif kind == 'capfloor': + elif kind == "capfloor": return CapFloorDeal - elif kind == 'spot': + elif kind == "spot": return SpotDeal else: - raise RuntimeError(f'Unknown Deal type: {kind}') + raise RuntimeError(f"Unknown Deal type: {kind}") def _get_form(kind): - if kind == 'cds': + if kind == "cds": return CDSForm - elif kind == 'bond': + elif kind == "bond": return BondForm - elif kind == 'swaption': + elif kind == "swaption": return SwaptionForm - elif kind == 'future': + elif kind == "future": return FutureForm - elif kind == 'capfloor': + elif kind == "capfloor": return CapFloorForm - elif kind == 'spot': + elif kind == "spot": return SpotForm else: - raise RuntimeError('Unknown Deal type') + raise RuntimeError("Unknown Deal type") def get_form(trade, kind): @@ -187,28 +234,35 @@ def get_form(trade, kind): else: today = pd.datetime.today() tomorrow = today + pd.DateOffset(1) - if kind == 'cds': - form = Form(trade_date=today.date(), - effective_date=previous_twentieth(today.date()), - upfront_settle_date=today.date() + 1 * bus_day) + if kind == "cds": + form = Form( + trade_date=today.date(), + effective_date=previous_twentieth(today.date()), + upfront_settle_date=today.date() + 1 * bus_day, + ) form.account_code.choices = fcm_accounts() - form.portfolio.choices = [c for c in form.portfolio.choices - if c[0] not in ('IR', 'IG', 'HY')] - form.folder.choices = [c for c in form.folder.choices - if (not c[0].startswith("SER_") or c[0].endswith("CURVE"))] + form.portfolio.choices = [ + c for c in form.portfolio.choices if c[0] not in ("IR", "IG", "HY") + ] + form.folder.choices = [ + c + for c in form.folder.choices + if (not c[0].startswith("SER_") or c[0].endswith("CURVE")) + ] elif kind == "swaption": - form = Form(trade_date=today.date(), - effective_date=tomorrow.date(), - upfront_settle_date=today.date() + 3 * bus_day) - form.portfolio.choices = [('OPTIONS', 'OPTIONS'), ('IR', 'IR')] + form = Form( + trade_date=today.date(), + effective_date=tomorrow.date(), + upfront_settle_date=today.date() + 3 * bus_day, + ) + form.portfolio.choices = [("OPTIONS", "OPTIONS"), ("IR", "IR")] else: - form = Form(trade_date=today.date(), - settle_date=today.date() + 2 * bus_day) + form = Form(trade_date=today.date(), settle_date=today.date() + 2 * bus_day) # add extra empty fields - empty_choice = (None, '') - for attr in ['folder', 'buysell', 'asset_class', 'swaption_type']: + empty_choice = (None, "") + for attr in ["folder", "buysell", "asset_class", "swaption_type"]: try: dropdown = getattr(form, attr) if dropdown.choices[0] != empty_choice: @@ -229,20 +283,17 @@ def save_ticket(trade, old_ticket_name): new_name = bump_rev(old_ticket_name) else: new_name = f"{trade.trade_date} {trade.id} {trade.description}.pdf" - trade.ticket.save(os.path.join(app.config['TICKETS_FOLDER'], - new_name)) + trade.ticket.save(os.path.join(app.config["TICKETS_FOLDER"], new_name)) trade.ticket = new_name else: trade.ticket = old_ticket_name def save_confirm(trade, old_confirm): - d = {'C': 'Cap', - 'F': 'Floor'} + d = {"C": "Cap", "F": "Floor"} if trade.trade_confirm: file_name = f"{trade.trade_date} {d[trade.cap_or_floor]}.pdf" - trade.trade_confirm.save(os.path.join(app.config['CONFIRMS_FOLDER'], - file_name)) + trade.trade_confirm.save(os.path.join(app.config["CONFIRMS_FOLDER"], file_name)) trade.trade_confirm = file_name else: trade.trade_confirm = old_confirm @@ -250,21 +301,39 @@ def save_confirm(trade, old_confirm): def split_direction(g, direction): if direction == "outgoing": - return [{"folder": cf.folder, "amount": -cf.amount, "code": cf.code, - "currency": cf.currency, "action": cf.action} - for cf in g if cf.amount < 0] + return [ + { + "folder": cf.folder, + "amount": -cf.amount, + "code": cf.code, + "currency": cf.currency, + "action": cf.action, + } + for cf in g + if cf.amount < 0 + ] elif direction == "incoming": - return [{"folder": cf.folder, "amount": cf.amount, "code": cf.code, - "currency": cf.currency, "action": cf.action} - for cf in g if cf.amount > 0] + return [ + { + "folder": cf.folder, + "amount": cf.amount, + "code": cf.code, + "currency": cf.currency, + "action": cf.action, + } + for cf in g + if cf.amount > 0 + ] else: raise ValueError("direction can be one of 'outgoing' or 'incoming'") def gen_cashflow_deals(form, session, wire_id=None): to_date = lambda s: datetime.datetime.strptime(s, "%Y-%m-%d") - d = {'action': form.get("action"), - 'trade_date': form.get("trade_date", None, to_date)} + d = { + "action": form.get("action"), + "trade_date": form.get("trade_date", None, to_date), + } for direction in ["incoming", "outgoing"]: count = 1 @@ -272,13 +341,17 @@ def gen_cashflow_deals(form, session, wire_id=None): if f"{direction}-code-{count}" not in form: break else: - d .update({field: form.get(f"{direction}-{field}-{count}") for field - in ["folder", "code", "amount", "currency"]}) + d.update( + { + field: form.get(f"{direction}-{field}-{count}") + for field in ["folder", "code", "amount", "currency"] + } + ) count += 1 if direction == "outgoing": - d['amount'] = - float(d['amount']) + d["amount"] = -float(d["amount"]) elif direction == "incoming": - d['amount'] = float(d['amount']) + d["amount"] = float(d["amount"]) else: raise ValueError("direction needs to be 'outgoing' or 'incoming'") if wire_id: @@ -292,10 +365,10 @@ def gen_cashflow_deals(form, session, wire_id=None): yield cf -@app.route('/wires/<int:wire_id>', methods=['GET', 'POST']) -@app.route('/wires/', defaults={'wire_id': None}, methods=['GET', 'POST']) +@app.route("/wires/<int:wire_id>", methods=["GET", "POST"]) +@app.route("/wires/", defaults={"wire_id": None}, methods=["GET", "POST"]) def wire_manage(wire_id): - if request.method == 'POST': + if request.method == "POST": wires = list(gen_cashflow_deals(request.form, db.session, wire_id)) try: @@ -303,90 +376,99 @@ def wire_manage(wire_id): except IntegrityError as e: app.logger.error(e) db.session.rollback() - return render_template('wire_entry.html', - strategies=CASH_STRAT.enums, - currencies=CCY.enums, - accounts=account_codes(), - outgoing_wires=split_direction(wires, "outgoing"), - incoming_wires=split_direction(wires, "incoming"), - action=request.form.get('action'), - trade_date=request.form.get('trade_date')) + return render_template( + "wire_entry.html", + strategies=CASH_STRAT.enums, + currencies=CCY.enums, + accounts=account_codes(), + outgoing_wires=split_direction(wires, "outgoing"), + incoming_wires=split_direction(wires, "incoming"), + action=request.form.get("action"), + trade_date=request.form.get("trade_date"), + ) else: - if request.form.get('upload_globeop') == 'y': + if request.form.get("upload_globeop") == "y": q = get_queue() for wire in wires: - q.rpush('wire_SERCGMAST', simple_serialize(wire)) - return redirect(url_for('list_trades', kind='wire')) + q.rpush("wire_SERCGMAST", simple_serialize(wire)) + return redirect(url_for("list_trades", kind="wire")) wire = CashFlowDeal() if wire_id is None else CashFlowDeal.query.get(wire_id) - return render_template('wire_entry.html', - strategies=CASH_STRAT.enums, - currencies=CCY.enums, - accounts=account_codes(), - outgoing_wires=split_direction([wire], "outgoing") if wire_id else [], - incoming_wires=split_direction([wire], "incoming") if wire_id else [], - trade_date=wire.trade_date if wire_id else datetime.date.today(), - action_url=url_for('wire_manage', wire_id=wire_id), - action=wire.action if wire_id else None) + return render_template( + "wire_entry.html", + strategies=CASH_STRAT.enums, + currencies=CCY.enums, + accounts=account_codes(), + outgoing_wires=split_direction([wire], "outgoing") if wire_id else [], + incoming_wires=split_direction([wire], "incoming") if wire_id else [], + trade_date=wire.trade_date if wire_id else datetime.date.today(), + action_url=url_for("wire_manage", wire_id=wire_id), + action=wire.action if wire_id else None, + ) -@app.route('/trades/<kind>/<int:tradeid>', methods=['GET', 'POST']) -@app.route('/trades/<kind>/', defaults={'tradeid': None}, - methods=['GET', 'POST']) -@app.route('/trades/', defaults={'tradeid': None, 'kind': 'bond'}, - methods=['GET', 'POST']) +@app.route("/trades/<kind>/<int:tradeid>", methods=["GET", "POST"]) +@app.route("/trades/<kind>/", defaults={"tradeid": None}, methods=["GET", "POST"]) +@app.route( + "/trades/", defaults={"tradeid": None, "kind": "bond"}, methods=["GET", "POST"] +) def trade_manage(tradeid, kind): trade = get_trade(tradeid, kind) form = _get_form(kind)() form.cp_code.choices = form.cp_code.choices + list(cp_choices(kind)) - if kind == 'bond': + if kind == "bond": old_ticket_name = trade.ticket - if kind == 'capfloor': + if kind == "capfloor": old_confirm = trade.trade_confirm - if kind == 'cds': + if kind == "cds": form.account_code.choices = fcm_accounts() if form.validate_on_submit(): form.populate_obj(trade) session = form.get_session() if not tradeid: session.add(trade) - if kind == 'bond': + if kind == "bond": save_ticket(trade, old_ticket_name) - if kind == 'capfloor': + if kind == "capfloor": save_confirm(trade, old_confirm) try: session.commit() except IntegrityError as e: app.logger.error(e) session.rollback() - return render_template('trade_entry.html', form=form, - action_url= - url_for('trade_manage', tradeid=tradeid, kind=kind)) + return render_template( + "trade_entry.html", + form=form, + action_url=url_for("trade_manage", tradeid=tradeid, kind=kind), + ) else: - if kind == 'cds': - if trade.swap_type != 'CD_INDEX': - trade.account_code = 'BAC' + if kind == "cds": + if trade.swap_type != "CD_INDEX": + trade.account_code = "BAC" trade.cashaccount = trade.fcm_account.cash_account session.commit() buf = simple_serialize(trade, upload=form.upload_globeop.data) q = get_queue() q.rpush(f"{kind}_{form.fund.data}", buf) - return redirect(url_for('list_trades', kind=kind)) + return redirect(url_for("list_trades", kind=kind)) else: if form.errors: app.logger.error(form.errors) form = get_form(trade, kind) form.cp_code.choices = form.cp_code.choices + list(cp_choices(kind)) - if kind == 'cds': + if kind == "cds": form.account_code.choices = list(fcm_accounts()) - return render_template('trade_entry.html', form=form, - action_url=url_for('trade_manage', tradeid=tradeid, kind=kind)) + return render_template( + "trade_entry.html", + form=form, + action_url=url_for("trade_manage", tradeid=tradeid, kind=kind), + ) -@app.route('/', defaults={'kind': 'bond'}) -@app.route('/<kind>') +@app.route("/", defaults={"kind": "bond"}) +@app.route("/<kind>") def list_trades(kind): try: Deal = get_deal(kind) @@ -395,42 +477,47 @@ def list_trades(kind): abort(404) else: trade_list = Deal.query.order_by(Deal.trade_date.desc(), Deal.id.desc()) - return render_template(f'{kind}_blotter.html', trades=trade_list.all()) + return render_template(f"{kind}_blotter.html", trades=trade_list.all()) -@app.route('/tickets/<int:tradeid>') +@app.route("/tickets/<int:tradeid>") def download_ticket(tradeid): trade = BondDeal.query.get(tradeid) pdf = PdfFileMerger() - pdf.append(os.path.join(app.config['TICKETS_FOLDER'], trade.ticket)) - pdf.append(os.path.join(app.config['CP_FOLDER'], trade.counterparty.instructions)) + pdf.append(os.path.join(app.config["TICKETS_FOLDER"], trade.ticket)) + pdf.append(os.path.join(app.config["CP_FOLDER"], trade.counterparty.instructions)) fh = BytesIO() pdf.write(fh) pdf.close() fh.seek(0) - return send_file(fh, mimetype='application/pdf') + return send_file(fh, mimetype="application/pdf") + -@app.route('/confirms/<int:tradeid>') +@app.route("/confirms/<int:tradeid>") def download_confirm(tradeid): trade = CapFloorDeal.query.get(tradeid) - return send_file(os.path.join(app.config['CONFIRMS_FOLDER'], trade.trade_confirm), - mimetype='application/pdf') + return send_file( + os.path.join(app.config["CONFIRMS_FOLDER"], trade.trade_confirm), + mimetype="application/pdf", + ) -@app.route('/counterparties/<path:instr>', methods=['GET']) -@app.route('/counterparties/', defaults={'instr': None}, methods=['GET']) +@app.route("/counterparties/<path:instr>", methods=["GET"]) +@app.route("/counterparties/", defaults={"instr": None}, methods=["GET"]) def list_counterparties(instr): if instr: - return send_from_directory(filename=instr, - directory=app.config['CP_FOLDER'], - mimetype='application/pdf') + return send_from_directory( + filename=instr, + directory=app.config["CP_FOLDER"], + mimetype="application/pdf", + ) else: cp_list = Counterparties.query.order_by(Counterparties.name) - return render_template('counterparties.html', counterparties=cp_list.all()) + return render_template("counterparties.html", counterparties=cp_list.all()) -@app.route('/edit_cp/<cpcode>', methods=['GET', 'POST']) -@app.route('/edit_cp/', defaults={'cpcode': None}, methods=['GET', 'POST']) +@app.route("/edit_cp/<cpcode>", methods=["GET", "POST"]) +@app.route("/edit_cp/", defaults={"cpcode": None}, methods=["GET", "POST"]) def edit_counterparty(cpcode): if cpcode: cp = Counterparties.query.get(cpcode) @@ -448,34 +535,43 @@ def edit_counterparty(cpcode): if not instructions.data: cp.instructions = old_instructions else: - cp.instructions = cp.name + '.pdf' - instructions.data.save(os.path.join(app.config['CP_FOLDER'], - cp.instructions)) + cp.instructions = cp.name + ".pdf" + instructions.data.save( + os.path.join(app.config["CP_FOLDER"], cp.instructions) + ) session.commit() - return redirect(url_for('list_counterparties')) + return redirect(url_for("list_counterparties")) else: - return render_template('edit_cp.html', form=CounterpartyForm(obj=cp), code=cpcode) + return render_template( + "edit_cp.html", form=CounterpartyForm(obj=cp), code=cpcode + ) -@app.route('/_ajax', methods=['GET']) +@app.route("/_ajax", methods=["GET"]) def get_bbg_id(): - bbg_id = request.args.get('bbg_id') + bbg_id = request.args.get("bbg_id") try: _, indextype, _, series, tenor = bbg_id.split() except ValueError: return "not a valid bloomberg description", 400 indextype = indextype[:2] - tenor = tenor[:-1] + 'yr' + tenor = tenor[:-1] + "yr" series = int(series[1:]) sqlstr1 = "SELECT * FROM index_redcode(%s::index_type, %s::smallint, %s)" - sqlstr2 = ("SELECT maturity, coupon FROM index_maturity WHERE index=%s " - "and series=%s and tenor=%s") + sqlstr2 = ( + "SELECT maturity, coupon FROM index_maturity WHERE index=%s " + "and series=%s and tenor=%s" + ) db = get_db() with db.cursor() as c: c.execute(sqlstr1, (indextype, series, pd.datetime.today().date())) (redcode,) = c.fetchone() c.execute(sqlstr2, (indextype, series, tenor)) maturity, coupon = c.fetchone() - return jsonify({'maturity': maturity.strftime('%Y-%m-%d'), - 'redcode': redcode, - 'coupon': coupon}) + return jsonify( + { + "maturity": maturity.strftime("%Y-%m-%d"), + "redcode": redcode, + "coupon": coupon, + } + ) |
