diff options
Diffstat (limited to 'python')
23 files changed, 0 insertions, 2325 deletions
diff --git a/python/Dawn/__init__.py b/python/Dawn/__init__.py deleted file mode 100644 index 0d447845..00000000 --- a/python/Dawn/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -import logging - -from flask import Flask -from flask_sqlalchemy import SQLAlchemy -from sqlalchemy import MetaData -from flask_wtf.csrf import CSRFProtect - -app = Flask(__name__) -app.config.from_envvar("CONF") -csrf = CSRFProtect(app) -db = SQLAlchemy(app, metadata=MetaData(schema=app.config["SCHEMA"])) - -if not app.debug: - fh = logging.FileHandler(filename=app.config["LOGFILE"]) - fh.setLevel(logging.INFO) - formatter = logging.Formatter( - "%(asctime)s - %(name)s - %(levelname)s - %(message)s" - ) - fh.setFormatter(formatter) - app.logger.addHandler(fh) - -import Dawn.views - -app.jinja_env.globals.update(bus_day=Dawn.models.bus_day) -app.jinja_env.filters["thousands"] = "{0:,.2f}".format diff --git a/python/Dawn/models.py b/python/Dawn/models.py deleted file mode 100644 index 34464fec..00000000 --- a/python/Dawn/models.py +++ /dev/null @@ -1,709 +0,0 @@ -from flask_wtf import FlaskForm -from flask_wtf.file import FileField - -from pandas.tseries.offsets import CustomBusinessDay, BDay -from pandas.tseries.holiday import get_calendar, HolidayCalendarFactory, GoodFriday -from pyisda.date import previous_twentieth - -from sqlalchemy.dialects.postgresql import ENUM -from wtforms.validators import Length -from wtforms_alchemy import model_form_factory -from sqlalchemy_utils import EmailType, PhoneNumberType - -from . import db - -import datetime - -fed_cal = get_calendar("USFederalHolidayCalendar") -bond_cal = HolidayCalendarFactory("BondCalendar", fed_cal, GoodFriday) -bus_day = CustomBusinessDay(calendar=bond_cal()) - - -class Counterparties(db.Model): - __tablename__ = "counterparties" - code = db.Column(db.String(12), primary_key=True) - name = db.Column(db.String) - city = db.Column(db.String) - state = db.Column(db.String(2)) - dtc_number = db.Column(db.Integer) - sales_contact = db.Column(db.String) - sales_email = db.Column(EmailType) - sales_phone = db.Column(PhoneNumberType()) - valuation_contact1 = db.Column(db.String) - valuation_email1 = db.Column(EmailType) - valuation_contact2 = db.Column(db.String) - valuation_email2 = db.Column(EmailType) - valuation_contact3 = db.Column(db.String) - valuation_email3 = db.Column(EmailType) - 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}) - - -class Accounts(db.Model): - __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")) - - -FUND = ENUM("SERCGMAST", "BRINKER", "BOWDST", name="fund") - -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", -) - -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_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", - name="cds_strat", -) - -SWAPTION_STRAT = ENUM( - "IGPAYER", "IGREC", "HYPAYER", "HYREC", "STEEP", "DV01", name="swaption_strat" -) - -FUTURE_STRAT = ENUM( - "M_STR_MAV", - "M_MTG_IO", - "M_STR_MEZZ", - "M_MTG_RW", - "SER_ITRXCURVE", - "M_CSH_CASH", - "DELTAONE", - "TCSH", - name="future_strat", -) - -CASH_STRAT = ENUM( - "M_CSH_CASH", - "MBSCDSCSH", - "SER_IGCVECSH", - "SER_ITRXCVCSH", - "CVECSH", - "CSOCDSCSH", - "IGCDSCSH", - "HYCDSCSH", - "CLOCDSCSH", - "IGTCDSCSH", - "MACCDSCSH", - "M_STR_MEZZ", - "IRDEVCSH", - "TCSH", - "COCSH", - "XCURVE", - "SER_ITRXCURVE", - "BSPK", - "SER_HYINX", - "IGOPTDEL", - "IGINX", - "HEDGE_CLO", - name="cash_strat", -) - -SPOT_STRAT = ENUM( - "M_STR_MAV", - "M_STR_MEZZ", - "M_CSH_CASH", - "TCSH", - "CVECSH", - "SER_ITRXCURVE", - name="spot_strat", -) - -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") - -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", -) - -ASSET_CLASS = ENUM( - "CSO", - "Subprime", - "CLO", - "Tranches", - "Futures", - "Cash", - "FX", - "Cleared", - "CRT", - name="asset_class", -) -ACTION = ENUM("NEW", "UPDATE", "CANCEL", name="action") - -CCY = ENUM("USD", "CAD", "EUR", "YEN", name="currency") - -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", -) - -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") - -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") - dealid = db.Column(db.String(28)) - 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(12), 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, default=datetime.date.today) - settle_date = db.Column( - db.Date, nullable=False, default=lambda: datetime.date.today() + 2 * bus_day - ) - 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) - asset_class = db.Column(ASSET_CLASS) - 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"),) - - -class CDSDeal(db.Model): - __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() - ) - 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(12), 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, default=datetime.date.today) - effective_date = db.Column( - db.Date, - nullable=False, - default=lambda: previous_twentieth(datetime.date.today() + BDay()), - ) - maturity = db.Column(db.Date, nullable=False) - currency = db.Column(CCY, nullable=False) - payment_rolldate = db.Column(BUS_DAY_CONVENTION, nullable=False) - notional = db.Column(db.Float, nullable=False) - fixed_rate = db.Column(db.Float, nullable=False) - day_count = db.Column(DAY_COUNT, nullable=False) - frequency = db.Column(db.SmallInteger, default=4, nullable=False) - protection = db.Column(PROTECTION, nullable=False) - security_id = db.Column(db.String(12), nullable=False) - security_desc = db.Column(db.String(32), nullable=False) - upfront = db.Column(db.Float) - upfront_settle_date = db.Column( - db.Date, nullable=False, default=lambda: datetime.date.today() + BDay() - ) - 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.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]} - ) - isda_definition = db.Column(ISDA) - counterparty = db.relationship(Counterparties, foreign_keys=[cp_code]) - fcm_account = db.relationship( - Accounts, foreign_keys=[account_code], load_on_pending=True - ) - ref = db.Column(db.Float) - __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() - ) - 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(12), 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}) - transation_indicator = db.Column(REPO_TYPE) - faceamount = db.Column(db.Float, nullable=False) - price = db.Column(db.Float, nullable=False) - currency = db.Column(CCY, nullable=False) - expiration_date = db.Column(db.Date) - weighted_amount = db.Column(db.Float) - haircut = db.Column(db.Float) - 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"), - ) - - -class SwaptionDeal(db.Model): - __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() - ) - 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(12), 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, default=datetime.date.today) - settle_date = db.Column( - db.Date, nullable=False, default=lambda: datetime.date.today() + 3 * bus_day - ) - 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) - price = db.Column(db.Float, nullable=False) - expiration_date = db.Column(db.Date, nullable=False) - initial_margin_percentage = db.Column(db.Float) - index_ref = db.Column(db.Float) - security_id = db.Column(db.String(12), nullable=False) - security_desc = db.Column(db.String(32)) - fixed_rate = db.Column(db.Float) - maturity = db.Column(db.Date, nullable=False) - currency = db.Column(CCY, nullable=False) - settlement_type = db.Column(SETTLEMENT_TYPE, nullable=False) - counterparty = db.relationship(Counterparties, foreign_keys=[cp_code]) - - -class FutureDeal(db.Model): - __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() - ) - 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"), ("GOLDNY", "Goldman Sachs")], - "label": "counterparty", - }, - nullable=False, - ) - trade_date = db.Column(db.Date, nullable=False, default=datetime.date.today) - settle_date = db.Column( - db.Date, nullable=False, default=lambda: datetime.date.today() + 2 * bus_day - ) - 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) - commission = db.Column(db.Float) - swap_type = db.Column(FUTURE_TYPE, nullable=False) - 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) - counterparty = db.relationship(Counterparties) - - -class CashFlowDeal(db.Model): - __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() - ) - action = db.Column(ACTION) - folder = db.Column(CASH_STRAT, 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, default=datetime.date.today) - account = db.relationship(Accounts) - - -class SpotDeal(db.Model): - __tablename__ = "spots" - 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() - ) - 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(12), default="IANSCLMAFU", nullable=False) - cp_code = db.Column( - db.String(12), - db.ForeignKey("counterparties.code"), - info={ - "choices": [ - ("IBKRNY", "Interactive Brokers"), - ("BAMSNY", "BofA"), - ("WELFEI", "Wells Fargo"), - ("BONY", "Bank of New York"), - ], - "label": "counterparty", - }, - nullable=False, - ) - trade_date = db.Column(db.Date, nullable=False, default=datetime.date.today) - settle_date = db.Column( - db.Date, nullable=False, default=lambda: datetime.date.today() + 2 * bus_day - ) - spot_rate = db.Column(db.Float, nullable=False) - buy_currency = db.Column(CCY, nullable=False) - buy_amount = db.Column(db.Float, nullable=False) - sell_currency = db.Column(CCY, nullable=False) - sell_amount = db.Column(db.Float, nullable=False) - commission_currency = db.Column(CCY) - 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") - dealid = db.Column(db.String(28), nullable=False) - 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(12), 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_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?"}, - ) - 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)]}, - ) - initial_margin_percentage = db.Column(db.Float) - initial_margin_currency = db.Column(CCY) - amount = db.Column(db.Float, nullable=False, info={"label": "notional"}) - trade_date = db.Column(db.Date, nullable=False, default=datetime.date.today) - 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}) - cpty_id = db.Column(db.Text) - counterparty = db.relationship(Counterparties, foreign_keys=[cp_code]) - - -class Termination(db.Model): - __tablename__ = "terminations" - id = db.Column("id", db.Integer, primary_key=True) - dealid = db.Column(db.String(28), nullable=False) - termination_date = db.Column(db.Date, nullable=False, default=datetime.date.today) - termination_cp = db.Column( - db.String(12), - db.ForeignKey("counterparties.code"), - info={ - "choices": [(None, "")], - "label": "termination counterparty", - "coerce": lambda s: None if s == "None" else s, - }, - ) - counterparty = db.relationship(Counterparties, foreign_keys=[termination_cp]) - termination_amount = db.Column(db.Float) - termination_fee = db.Column(db.Float, nullable=False) - fee_payment_date = db.Column( - db.Date, nullable=False, default=lambda: datetime.date.today() + 3 * bus_day - ) - partial_termination = db.Column(db.Boolean, nullable=False, default=False) - - -BaseModelForm = model_form_factory(FlaskForm) - - -class ModelForm(BaseModelForm): - @classmethod - def get_session(self): - return db.session diff --git a/python/Dawn/static/LMCG.png b/python/Dawn/static/LMCG.png Binary files differdeleted file mode 100644 index ec1c5292..00000000 --- a/python/Dawn/static/LMCG.png +++ /dev/null diff --git a/python/Dawn/static/dawn.css b/python/Dawn/static/dawn.css deleted file mode 100644 index cac2a4e2..00000000 --- a/python/Dawn/static/dawn.css +++ /dev/null @@ -1,5 +0,0 @@ -body { - max-width:1500px; - margin: 0 auto; - padding-top: 70px; -}
\ No newline at end of file diff --git a/python/Dawn/static/dawn.js b/python/Dawn/static/dawn.js deleted file mode 100644 index ac972e24..00000000 --- a/python/Dawn/static/dawn.js +++ /dev/null @@ -1,194 +0,0 @@ -var index_list = []; -var bbg_map = {'CDX': ["IG", "HY"], 'ITRX': ["EUR", "XOVER"]}; -var series_map = {'CDX': ["24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35"], - 'ITRX': ["24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34"]}; -var index_tenor = ["3Y", "5Y", "7Y", "10Y"]; -for(var begin_index in bbg_map){ - for(var index_type of bbg_map[begin_index]){ - for(var series of series_map[begin_index]){ - for(var tenor of index_tenor){ - index_list.push(`${begin_index} ${index_type} CDSI S${series} ${tenor}`); - } - } - } -}; - -$(function() { - $('#security_desc').attr('list', 'index_list'); - var security_desc = document.getElementById('security_desc'); - if (security_desc) { - security_desc.addEventListener('change', (event) => { - fetch(`../../_ajax?bbg_id=${encodeURIComponent(event.target.value)}&` + - `trade_date=${$('#trade_date').val()}`) - .then(data => data.json()) - .then(data => { - $('#fixed_rate').val(data['coupon']/100); - $('#security_id').val(data['redcode']); - $('#maturity').val(data['maturity']); - }); - if (event.target.value.startsWith("ITRX")) { - $('#currency').val("EUR"); - } else{ - $('#currency').val("USD"); - } - }); - } - $('#folder').change(function() { - if ($('#swap_type').val() == 'CD_INDEX') { - switch ($(this).val()) { - case 'IGOPTDEL': - case 'HYOPTDEL': - $('#portfolio').val('OPTIONS'); - break; - case 'SER_HYCURVE': - case 'SER_ITRXCURVE': - case 'SER_IGCURVE': - case 'XCURVE': - $('#portfolio').val('CURVE'); - break; - case 'HYEQY': - case 'HYMEZ': - case 'HYSNR': - case 'IGEQY': - case 'IGMEZ': - case 'IGSNR': - case 'XOEQY': - case 'XOMEZ': - case 'BSPK': - $('#portfolio').val('TRANCHE'); - $('#swap_type').val('CD_INDEX_TRANCHE'); - $('#swap_type').change(); - break; - case 'HYINX': - case 'IGINX': - case 'XOINX': - case 'EUINX': - $('#portfolio').val('TRANCHE'); - break; - case 'HEDGE_CLO': - $('#portfolio').val('CLO'); - break; - case 'HEDGE_MAC': - $('#portfolio').val('HEDGE_MAC'); - break; - case 'HEDGE_CSO': - $('#portfolio').val('STRUCTURED'); - break; - case 'HEDGE_MBS': - case 'MBSCDS': - $('#portfolio').val('MORTGAGES'); - break; - } - } - var strat = $(this).val(); - if (strat.startsWith('CRT')) { - $('#asset_class').val('CRT'); - } else if (strat.includes('MTG')) { - $('#asset_class').val('Subprime'); - } else if (strat.includes('CLO')) { - $('#asset_class').val('CLO'); - } else { - $('#asset_class').val('CSO'); - } - }); - $('#swap_type').change(function() { - var to_hide, to_show; - const hide = (arr) => arr.forEach(id => { - document.getElementById(id) - .parentElement - .parentElement - .style.display = 'none'; - }); - const show = (arr) => arr.forEach(id => { - document.getElementById(id) - .parentElement - .parentElement - .style.display = 'block'; - }); - switch ($(this).val()) { - case 'CD_BASKET_TRANCHE': - case 'CD_INDEX_TRANCHE': - case 'BESPOKE': - show(['orig_attach', 'orig_detach', 'initial_margin_percentage', - 'index_ref', 'corr_attach', 'corr_detach']); - hide(['clearing_facility', 'account_code']); - $('#clearing_facility').val(''); - $('#portfolio').val('TRANCHE'); - break; - case 'CD_INDEX': - hide(['orig_attach', 'orig_detach', 'initial_margin_percentage', - 'index_ref', 'corr_attach', 'corr_detach']); - show(['clearing_facility', 'account_code']); - $('#clearing_facility').val('ICE-CREDIT'); - $('#folder').change(); - break; - case 'ABS_CDS': - hike(['orig_attach', 'orig_detach', - 'index_ref', 'corr_attach', 'corr_detach', - 'clearing_facility']); - show(['initial_margin_percentage']); - $('#clearing_facility').val(''); - $('#portfolio').val('MORTGAGES'); - break; - case 'SWAPTION': - hide(['fixed_rate', 'index_ref', 'security_desc']); - $('#portfolio').val('IR'); - $('#settlement_type').val('Cash'); - break; - case 'CD_INDEX_OPTION': - show(['fixed_rate', 'index_ref', 'security_desc']); - $('#portfolio').val('OPTIONS'); - $('#settlement_type').val('Delivery'); - break; - } - }); - $('#partial_termination').change( - function() { - if( $(this).prop('checked') ) { - $('#termination_amount').parent().parent().css('display', 'block'); - } else { - $('#termination_amount').val(''); - $('#termination_amount').parent().parent().css('display', 'none'); - } - } - ); - $('#partial_termination').change(); - $('#swap_type').change(); - var datalist = $('#index_list'); - index_list.forEach(item => { - var option = document.createElement('option'); - option.value = item; - datalist.append(option); - }); - $('#fund').change( - function() { - if (window.location.pathname.includes('future') || - window.location.pathname.includes('spot')) { - return; - } - switch ($(this).val()) { - case 'SERCGMAST': - $('#custodian').val('BAC'); - $('#cashaccount').val('V0NSCLMAMB'); - break; - case 'BOWDST': - $('#custodian').val('BONY'); - $('#cashaccount').val('BPMG10240000'); - $('#account_code').val('GS'); - break; - case 'BRINKER': - $('#custodian').val('BBH'); - $('#cashaccount').val('4023461'); - break; - } - }); - $('#fund').change(); - //change default value to Following - $('#payment_rolldate').val('Following'); - $('#upfront').attr('data-toggle', 'tooltip'); - $('#upfront').attr('title', 'This is Cash Amount on the bloomberg ticket, i.e. the net amount we receive.'); - $('#upfront').tooltip(); - $('#spot_rate').attr('data-toggle', 'tooltip'); - $('#spot_rate').attr('title', 'Spot rate must be entered with pairs ordered by dominance. EUR > GBP > USD > CAD > CHF > YEN'); - $('#spot_rate').tooltip(); -}); diff --git a/python/Dawn/static/favicon.ico b/python/Dawn/static/favicon.ico Binary files differdeleted file mode 100755 index bee8bf36..00000000 --- a/python/Dawn/static/favicon.ico +++ /dev/null diff --git a/python/Dawn/static/utils.js b/python/Dawn/static/utils.js deleted file mode 100644 index befcc442..00000000 --- a/python/Dawn/static/utils.js +++ /dev/null @@ -1,26 +0,0 @@ -function $(s) { - return( document.getElementById(s) ); -} - -function encode_dict(d){ - var r = []; - for(var k in d){ - r.push(encodeURIComponent(k) + '=' + encodeURIComponent(d[k])); - } - return r.join('&'); -} - -function query(url, params, callback){ - var xhr = new XMLHttpRequest(); - xhr.open('GET', url + '?' + encode_dict(params)); - xhr.onreadystatechange = function() { - if( xhr.readyState === 4 ) { - if( xhr.status === 200 ) { - callback(xhr.responseText); - } else if ( xhr.status === 400 ) { - console.log(xhr.responseText); - } - } - }; - xhr.send(); -} diff --git a/python/Dawn/static/wire.js b/python/Dawn/static/wire.js deleted file mode 100644 index b2d761c6..00000000 --- a/python/Dawn/static/wire.js +++ /dev/null @@ -1,46 +0,0 @@ -var outgoing_count = 0; -var incoming_count = 0; - -function addWire(direction, wire_data) { - return function() { - if( this != window.window) { - this.remove(); - } - var template = document.getElementById("fragment"); - var clone = document.importNode(template.content, true); - count = direction == "outgoing" ? ++outgoing_count : ++incoming_count; - - clone.querySelectorAll("label").forEach( - label => label.setAttribute("for", - direction + "-" + label.getAttribute("for") + "-" + count)); - clone.querySelectorAll(".form-control").forEach( - elem => {elem.id = direction + "-" + elem.id + "-" + count; - elem.setAttribute("name", - direction + "-" + elem.getAttribute("name") + "-" + count); - }); - clone.getElementById("btn").id = direction + "-btn"; - document.getElementById(direction).appendChild(clone); - for(var key in wire_data) { - if( key == "action" ){ - document.getElementById("action").value = wire_data[key]; - } else { - document.getElementById(direction + "-" + key + "-" + count).value = wire_data[key]; - } - } - document.getElementById(direction + "-btn").addEventListener("click", addWire(direction)); - }; -} - -$(function() { - for (let w of outgoing_wires) { - addWire("outgoing", w)(); - } - for (let w of incoming_wires) { - console.log(w); - addWire("incoming", w)(); - } - if (outgoing_wires.length == 0 && incoming_wires.length == 0) { - addWire("outgoing")(); - addWire("incoming")(); - } -}) diff --git a/python/Dawn/templates/base.html b/python/Dawn/templates/base.html deleted file mode 100644 index 0af075eb..00000000 --- a/python/Dawn/templates/base.html +++ /dev/null @@ -1,72 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"> - <link rel="stylesheet" href="{{url_for('static', filename='dawn.css')}}"> - <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> - <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js" integrity="sha512-K1qjQ+NcF2TYO/eI3M6v8EiNYZfA95pQumfvcVrTHtwQVDG+aHRqLi/ETn2uB+1JqwYqVG3LIvdm9lj6imS/pQ==" crossorigin="anonymous"></script> - </head> - <body> - <nav class="navbar navbar-default navbar-fixed-top"> - <div class="container"> - <div class="navbar-header"> - <a class="navbar-brand" style="padding-top: 7.5px" href="#"> - <img style="height:35px" alt="LMCG Investments" src="{{url_for('static', filename='LMCG.png')}}"> - </a> - </div> - <ul class="nav navbar-nav"> - <li class="dropdown"> - <a href="#" class="dropdown-toggle" - data-toggle="dropdown" - role="button" - aria-haspopup="true" - aria-expanded="false">Blotter<span class="caret"></span> - </a> - <ul class="dropdown-menu"> - <li><a href="{{url_for('list_trades', kind='bond')}}">Bonds</a></li> - <li><a href="{{url_for('list_trades', kind='cds')}}">CDS</a></li> - <li><a href="{{url_for('list_trades', kind='swaption')}}">Swaptions</a></li> - <li><a href="{{url_for('list_trades', kind='future')}}">Futures</a></li> - <li><a href="{{url_for('list_trades', kind='spot')}}">Spot</a></li> - <li><a href="{{url_for('list_trades', kind='wire')}}">Wires</a></li> - <li><a href="{{url_for('list_trades', kind='capfloor')}}">Caps and Floors</a></li> - </ul> - </li> - <li class="dropdown"> - <a href="#" class="dropdown-toggle" - data-toggle="dropdown" - role="button" - aria-haspopup="true" - aria-expanded="false">Book<span class="caret"></span> - </a> - <ul class="dropdown-menu"> - <li><a href="{{url_for('trade_manage', kind='bond')}}">Bonds</a></li> - <li><a href="{{url_for('trade_manage', kind='cds')}}">CDS</a></li> - <li><a href="{{url_for('trade_manage', kind='swaption')}}">Swaptions</a></li> - <li><a href="{{url_for('trade_manage', kind='future')}}">Futures</a></li> - <li><a href="{{url_for('trade_manage', kind='spot')}}">Spot</a></li> - <li><a href="{{url_for('wire_manage')}}">Wires</a></li> - <li><a href="{{url_for('trade_manage', kind='capfloor')}}">Caps and Floors</a></li> - </ul> - </li> - <li class="dropdown"> - <a href="#" class="dropdown-toggle" - data-toggle="dropdown" - role="button" - aria-haspopup="true" - aria-expanded="false">Counterparties<span class="caret"></span> - </a> - <ul class="dropdown-menu"> - <li><a href="../counterparties">List</a></li> - <li><a href="{{url_for('edit_counterparty', cpcode=None)}}">New</a></li> - </ul> - </li> - </ul> - </div> - </nav> - <main> - {% block content %}{% endblock %} - </main> - </body> -</html> diff --git a/python/Dawn/templates/bond_blotter.html b/python/Dawn/templates/bond_blotter.html deleted file mode 100644 index b9648730..00000000 --- a/python/Dawn/templates/bond_blotter.html +++ /dev/null @@ -1,43 +0,0 @@ -{% extends "base.html" %} -{% block content %} -<table class="table table-striped"> - <thead> - <tr> - <td>Deal ID</td> - <td>Trade Date</td> - <td>Settle Date</td> - <td>Buy/Sell</td> - <td>Identifier</td> - <td>Description</td> - <td>Notional</td> - <td>Price</td> - <td>Counterparty</td> - <td>Fund</td> - <td>Strategy</td> - <td>Asset Class</td> - <td>Acc Int</td> - <td>Ticket</td> - </tr> - </thead> - {% for trade in trades %} - <tr> - <td><a href="{{url_for('trade_manage', tradeid=trade.id, kind='bond')}}">{{trade.dealid}}</a></td> - <td>{{trade.trade_date}}</td> - <td>{{trade.settle_date}}</td> - <td>{% if trade.buysell %}Buy{% else %}Sell{% endif %}</td> - <td>{{trade.identifier}}</td> - <td>{{trade.description}}</td> - <td>{{"{0:,.0f}".format(trade.faceamount)}}</td> - <td>{{trade.price|round(3)}}</td> - <td><a href="{{url_for('edit_counterparty', - cpcode=trade.counterparty.code)}}">{{trade.counterparty.name}}</a></td> - <td>{{trade.fund}}</td> - <td>{{trade.folder}}</td> - <td>{{trade.asset_class}}</td> - <td>{% if trade.accrued is not none %}{{trade.accrued|round(3)}}{% else %}-{% endif %}</td> - <td>{%if trade.ticket %}<a href="{{url_for('download_ticket', tradeid = trade.id)}}"> - <span class="glyphicon glyphicon-file"></span></a>{% endif %}</td> - </tr> - {% endfor %} -</table> -{% endblock %} diff --git a/python/Dawn/templates/capfloor_blotter.html b/python/Dawn/templates/capfloor_blotter.html deleted file mode 100644 index 66f9a2b4..00000000 --- a/python/Dawn/templates/capfloor_blotter.html +++ /dev/null @@ -1,41 +0,0 @@ -{% extends "base.html" %} -{% block content %} -<table class="table table-striped"> - <thead> - <tr> - <td>Deal ID</td> - <td>Trade Date</td> - <td>Buy/Sell</td> - <td>Notional</td> - <td>Type</td> - <td>Expiry</td> - <td>Strike</td> - <td>Price</td> - <td>FixedRate Index</td> - <td>Comments</td> - <td>Counterparty</td> - <td>Strategy</td> - <td>Confirm</td> - </tr> - </thead> - {% for trade in trades %} - <tr> - <td><a href="{{url_for('trade_manage', tradeid=trade.id, kind='capfloor')}}">{{trade.dealid}}</a></td> - <td>{{trade.trade_date}}</td> - <td>{% if trade.buysell %}Buy{% else %}Sell{% endif %}</td> - <td>{{"{0:,.2f}".format(trade.amount)}}</td> - <td>{{trade.swap_type}}</td> - <td>{{trade.expiration_date}}</td> - <td>{{trade.strike}}</td> - <td>{{trade.premium_percent}}</td> - <td>{{trade.floating_rate_index}}</td> - <td>{{trade.comments}}</td> - <td><a href="{{url_for('edit_counterparty', - cpcode=trade.counterparty.code)}}">{{trade.counterparty.name}}</a></td> - <td>{{trade.folder}}</td> - <td>{%if trade.trade_confirm %}<a href="{{url_for('download_confirm', tradeid=trade.id)}}"> - <span class="glyphicon glyphicon-file"></span></a>{% endif %}</td> - </tr> - {% endfor %} -</table> -{% endblock %} diff --git a/python/Dawn/templates/cds_blotter.html b/python/Dawn/templates/cds_blotter.html deleted file mode 100644 index 7802ba3a..00000000 --- a/python/Dawn/templates/cds_blotter.html +++ /dev/null @@ -1,43 +0,0 @@ -{% extends "base.html" %} -{% block content %} -<table class="table table-striped"> - <thead> - <tr> - <td>Deal ID</td> - <td>Trade Date</td> - <td>Protection</td> - <td>Description</td> - <td>Red Code</td> - <td>Notional</td> - <td style="text-align:center">Upfront</td> - <td style="text-align:center">Ref</td> - <td>Attach</td> - <td>Detach</td> - <td>Counterparty</td> - <td>Trade Type</td> - <td>Fund</td> - <td>Strategy</td> - </tr> - </thead> - {% for trade in trades %} - <tr> - <td><a href="{{url_for('trade_manage', tradeid=trade.id, kind='cds')}}">{{trade.dealid}}</a></td> - <td>{{trade.trade_date}}</td> - <td>{{trade.protection}}</td> - <td>{{trade.security_desc}}</td> - <td>{{trade.security_id}}</td> - <td>{{trade.notional|thousands}}</td> - <td style="text-align:right">{{"{0:,.2f}".format(trade.upfront) if trade.upfront else "-"}}</td> - <td style="text-align:right">{{"{0:,.4f}".format(trade.ref) if trade.ref else "-"}}</td> - <td>{{trade.orig_attach if trade.orig_attach is not none}}</td> - <td>{{trade.orig_detach if trade.orig_detach is not none}}</td> - <td><a href="{{url_for('edit_counterparty', - cpcode=trade.cp_code)}}">{{trade.name}}</a></td> - <td>{{trade.trade_type}}</td> - <td>{{trade.fund}}</td> - <td>{{trade.folder}}</td> - <td>{% if trade.trade_type == "New" %}<a href="{{url_for('terminate', dealid=trade.dealid, kind='cds')}}">x</a>{% endif %}</td> - </tr> - {% endfor %} -</table> -{% endblock %} diff --git a/python/Dawn/templates/counterparties.html b/python/Dawn/templates/counterparties.html deleted file mode 100644 index 16f3680f..00000000 --- a/python/Dawn/templates/counterparties.html +++ /dev/null @@ -1,43 +0,0 @@ -{% extends "base.html" %} -{% block content %} -<table class="table table-striped"> - <thead> - <tr> - <td>CODE</td> - <td>Firm</td> - <td>Location</td> - <td>DTC Number</td> - <td>Sales Contact</td> - <td>Sales Phone</td> - <td>Valuation Contact1</td> - <td>Valuation Contact2</td> - <td>Valuation Contact3</td> - <td>Valuation Contact4</td> - <td>Valuation Note</td> - <td>Instructions</td> - </tr> - </thead> - {% for cp in counterparties %} - <tr> - <td><a href="{{url_for('edit_counterparty',cpcode=cp.code)}}">{{cp.code}}</td> - <td>{{cp.name}}</td> - <td>{{cp.city}}, {{cp.state}}</td> - <td>{{cp.dtc_number if cp.dtc_number}}</td> - <td><a href="mailto:{{cp.sales_email}}">{{cp.sales_contact if cp.sales_contact}}</a></td> - <td>{{cp.sales_phone if cp.sales_phone}}</td> - <td>{% if cp.valuation_contact1 %} - <a href="mailto:{{cp.valuation_email1}}"> - {{cp.valuation_contact1}}</a>{% endif %}</td> - <td>{% if cp.valuation_contact2 %} - <a href="mailto:{{cp.valuation_email2}}">{{cp.valuation_contact2}}</a>{% endif %}</td> - <td>{% if cp.valuation_contact3 %} - <a href="mailto:{{cp.valuation_email3}}">{{cp.valuation_contact3}}</a>{% endif %}</td> - <td>{% if cp.valuation_contact4 %} - <a href="mailto:{{cp.valuation_email4}}">{{cp.valuation_contact4}}</a>{% endif %}</td> - <td style="width:50px">{{cp.notes if cp.notes}}</td> - <td>{%if cp.instructions %}<a href="{{url_for('list_counterparties', instr = cp.instructions)}}"> - <span class="glyphicon glyphicon-file"></span></a>{% endif %}</td> - </tr> - {% endfor %} -</table> -{% endblock %} diff --git a/python/Dawn/templates/edit_cp.html b/python/Dawn/templates/edit_cp.html deleted file mode 100644 index ff581c9f..00000000 --- a/python/Dawn/templates/edit_cp.html +++ /dev/null @@ -1,30 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"> - </head> - <body style="max-width:1024px; margin:0 auto"> - <form method="POST" class="form-horizontal" - action="{{url_for('edit_counterparty', cpcode=code)}}" - enctype="multipart/form-data"> - {% for field in form %} - <div class="form-group"> - {% if field.type != 'CSRFTokenField' %} - <label class="control-label col-md-2" for="{{ field.id }}"> - {{ field.label.text }} - </label> - {% endif %} - <div class="col-md-3"> - {{ field(class_="form-control") }} - </div> - </div> - {% endfor %} - <div class="form-group"> - <div class="col-md-offset-2 col-md-3"> - <button type="submit" class="btn btn-default">Submit</button> - </div> - </div> - </form> - </body> -</html> diff --git a/python/Dawn/templates/future_blotter.html b/python/Dawn/templates/future_blotter.html deleted file mode 100644 index 54244b2a..00000000 --- a/python/Dawn/templates/future_blotter.html +++ /dev/null @@ -1,42 +0,0 @@ -{% extends "base.html" %} -{% block content %} -<table class="table table-striped"> - <thead> - <tr> - <td>Deal ID</td> - <td>Trade Date</td> - <td>Settle Date</td> - <td>Buy/Sell</td> - <td>Quantity</td> - <td>Type</td> - <td>Maturity</td> - <td>Price</td> - <td>Commission</td> - <td>Description</td> - <td>Ticker</td> - <td>Counterparty</td> - <td>Fund</td> - <td>Strategy</td> - </tr> - </thead> - {% for trade in trades %} - <tr> - <td><a href="{{url_for('trade_manage', tradeid=trade.id, kind='future')}}">{{trade.dealid}}</a></td> - <td>{{trade.trade_date}}</td> - <td>{{trade.settle_date}}</td> - <td>{% if trade.buysell %}Buy{% else %}Sell{% endif %}</td> - <td>{{trade.quantity}}</td> - <td>{{trade.swap_type}}</td> - <td>{{trade.maturity}}</td> - <td>{{trade.price}}</td> - <td>{{trade.commission}}</td> - <td>{{trade.security_desc}}</td> - <td>{{trade.bbg_ticker}}</td> - <td><a href="{{url_for('edit_counterparty', - cpcode=trade.counterparty.code)}}">{{trade.counterparty.name}}</a></td> - <td>{{trade.fund}}</td> - <td>{{trade.folder}}</td> - </tr> - {% endfor %} -</table> -{% endblock %} diff --git a/python/Dawn/templates/spot_blotter.html b/python/Dawn/templates/spot_blotter.html deleted file mode 100644 index a4e8bb8d..00000000 --- a/python/Dawn/templates/spot_blotter.html +++ /dev/null @@ -1,35 +0,0 @@ -{% extends "base.html" %} -{% block content %} -<table class="table table-striped"> - <thead> - <tr> - <td>Deal ID</td> - <td>Trade Date</td> - <td>Settle Date</td> - <td>Strategy</td> - <td>Spot Rate</td> - <td>Buy CCY</td> - <td>Buy Amount</td> - <td>Sell CCY</td> - <td>Sell Amount</td> - <td>Commission CCY</td> - <td>Commission Amount</td> - </tr> - </thead> - {% for trade in trades %} - <tr> - <td><a href="{{url_for('trade_manage', tradeid=trade.id, kind='spot')}}">{{trade.dealid}}</a></td> - <td>{{trade.trade_date}}</td> - <td>{{trade.settle_date}}</td> - <td>{{trade.folder}}</td> - <td>{{"{:,.5f}".format(trade.spot_rate)}}</td> - <td>{{trade.buy_currency}}</td> - <td>{{"{:,.2f}".format(trade.buy_amount)}}</td> - <td>{{trade.sell_currency}}</td> - <td>{{"{:,.2f}".format(trade.sell_amount)}}</td> - <td>{{trade.commission_currency}}</td> - <td>{{trade.commission or "-"}}</td> - </tr> - {% endfor %} -</table> -{% endblock %} diff --git a/python/Dawn/templates/swaption_blotter.html b/python/Dawn/templates/swaption_blotter.html deleted file mode 100644 index 5f62b556..00000000 --- a/python/Dawn/templates/swaption_blotter.html +++ /dev/null @@ -1,46 +0,0 @@ -{% extends "base.html" %} -{% block content %} -<table class="table table-striped"> - <thead> - <tr> - <td>Deal ID</td> - <td>Trade Date</td> - <td>Settle Date</td> - <td>Buy/Sell</td> - <td style="text-align:center">Notional</td> - <td>Type</td> - <td>Expiry</td> - <td>Strike</td> - <td style="text-align:center">Fee</td> - <td style="text-align:center">Description</td> - <td>Red Code</td> - <td>Counterparty</td> - <td>Trade Type</td> - <td>Strategy</td> - <td>Fund</td> - <td>Termination</td> - </tr> - </thead> - {% for trade in trades %} - <tr> - <td><a href="{{url_for('trade_manage', tradeid=trade.id, kind='swaption')}}">{{trade.dealid}}</a></td> - <td>{{trade.trade_date}}</td> - <td>{{(trade.trade_date + 3 * bus_day).date()}}</td> - <td>{% if trade.buysell %}Buy{% else %}Sell{% endif %}</td> - <td>{{"{0:,}".format(trade.notional)}}</td> - <td>{{trade.option_type}}</td> - <td>{{trade.expiration_date}}</td> - <td>{{trade.strike}}</td> - <td style="text-align:right">{{trade.fee|thousands}}</td> - <td>{{trade.security_desc}}</td> - <td>{{trade.security_id}}</td> - <td><a href="{{url_for('edit_counterparty', - cpcode=trade.cp_code)}}">{{trade.name}}</a></td> - <td>{{trade.trade_type}}</td> - <td>{{trade.folder}}</td> - <td>{{trade.fund}}</td> - <td>{% if trade.trade_type == "New" %}<a href="{{url_for('terminate', dealid=trade.dealid, kind='swaption')}}">x</a>{% endif %}</td> - </tr> - {% endfor %} -</table> -{% endblock %} diff --git a/python/Dawn/templates/termination.html b/python/Dawn/templates/termination.html deleted file mode 100644 index d12b3304..00000000 --- a/python/Dawn/templates/termination.html +++ /dev/null @@ -1,50 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"> - </head> - <body style="max-width:1024px; margin:3em auto"> - <form method="POST" class="form-horizontal" - action="{{action_url}}" enctype="multipart/form-data"> - {% for field in form if field.name != "upload_globeop" %} - <div class="form-group {% if field.id in form.errors %}has-error{% endif %}"> - {% if field.type != 'CSRFTokenField' %} - <label class="control-label col-md-2" for="{{ field.id }}"> - {{ field.label.text }} - </label> - {% endif %} - <div class="col-md-3"> - {{ field(class_="form-control") }} - </div> - {% if field.id in form.errors %} - <div class="col-md-3"> - {{form.errors[field.id][0]}} - </div>{% endif %} - </div> - {% endfor %} - <div class="form-group"> - <div class="col-md-offset-2 col-md-3"> - <div class="checkbox"> - <label> - <input id="upload_globeop" name="upload_globeop" type="checkbox" value="y">Upload to globeop? - </label> - </div> - </div> - </div> - <div class="form-group"> - <div class="col-md-offset-2 col-md-3"> - <button type="submit" class="btn btn-default">Submit</button> - </div> - </div> - </form> - {% if 'cds' or 'swaption' or 'terminate' in action_url %} - <script type="text/javascript" src="https://code.jquery.com/jquery-2.2.0.min.js"></script> - <script type="text/javascript" - src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" - integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" - crossorigin="anonymous"></script> - <script type="text/javascript" src="{{ url_for('static', filename='dawn.js') }}"></script> - {% endif %} - </body> -</html> diff --git a/python/Dawn/templates/trade_entry.html b/python/Dawn/templates/trade_entry.html deleted file mode 100644 index a7b19ab6..00000000 --- a/python/Dawn/templates/trade_entry.html +++ /dev/null @@ -1,51 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"> - </head> - <body style="max-width:1024px; margin:0 auto"> - <datalist id="index_list"></datalist> - <form method="POST" class="form-horizontal" - action="{{action_url}}" enctype="multipart/form-data"> - {% for field in form if field.type != 'BooleanField' %} - <div class="form-group {% if field.id in form.errors %}has-error{% endif %}"> - {% if field.type != 'CSRFTokenField' %} - <label class="control-label col-md-2" for="{{ field.id }}"> - {{ field.label.text }} - </label> - {% endif %} - <div class="col-md-3"> - {{ field(class_="form-control") }} - </div> - {% if field.id in form.errors %} - <div class="col-md-3"> - {{form.errors[field.id][0]}} - </div>{% endif %} - </div> - {% endfor %} - <div class="form-group"> - <div class="col-md-offset-2 col-md-3"> - <div class="checkbox"> - <label> - <input id="upload_globeop" name="upload_globeop" type="checkbox" value="y">Upload to globeop? - </label> - </div> - </div> - </div> - <div class="form-group"> - <div class="col-md-offset-2 col-md-3"> - <button type="submit" class="btn btn-default">Submit</button> - </div> - </div> - </form> - {% if 'cds' or 'swaption' in action_url %} - <script type="text/javascript" src="https://code.jquery.com/jquery-2.2.0.min.js"></script> - <script type="text/javascript" - src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" - integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" - crossorigin="anonymous"></script> - <script type="text/javascript" src="{{ url_for('static', filename='dawn.js') }}"></script> - {% endif %} - </body> -</html> diff --git a/python/Dawn/templates/wire_blotter.html b/python/Dawn/templates/wire_blotter.html deleted file mode 100644 index e4e3e2b8..00000000 --- a/python/Dawn/templates/wire_blotter.html +++ /dev/null @@ -1,25 +0,0 @@ -{% extends "base.html" %} -{% block content %} -<table class="table table-striped"> - <thead> - <tr> - <td>Deal ID</td> - <td>Trade Date</td> - <td>Strategy</td> - <td>Account</td> - <td>Amount</td> - <td>Currency</td> - </tr> - </thead> - {% for trade in trades %} - <tr> - <td><a href="{{url_for('wire_manage', wire_id=trade.id)}}">{{trade.dealid}}</a></td> - <td>{{trade.trade_date}}</td> - <td>{{trade.folder}}</td> - <td>{{trade.account.name}}</td> - <td>{{trade.amount}}</td> - <td>{{trade.currency}}</td> - </tr> - {% endfor %} -</table> -{% endblock %} diff --git a/python/Dawn/templates/wire_entry.html b/python/Dawn/templates/wire_entry.html deleted file mode 100644 index d22d0ee9..00000000 --- a/python/Dawn/templates/wire_entry.html +++ /dev/null @@ -1,150 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"> - </head> - <body style="max-width:512px; margin:20px auto"> - <form method="POST" class="form-horizontal" - action="{{action_url}}" enctype="multipart/form-data"> - <div class="form-group "> - <label class="control-label col-md-4" for="action"> - action - </label> - <div class="col-md-6"> - <select class="form-control" id="action" name="action"> - <option value="NEW" - {% if action and action == 'NEW' %} - selected="selected" - {% endif %}>NEW</option> - <option value="UPDATE" - {% if action and action == 'UPDATE' %} - selected="selected" - {% endif %}>UPDATE</option> - <option value="CANCEL" - {% if action and action == 'CANCEL' %} - selected="selected" - {% endif %}>CANCEL</option> - </select> - </div> - </div> - <fieldset id="outgoing"> - <legend>Outgoing amounts</legend> - </fieldset> - <fieldset id="incoming"> - <legend>Incoming amounts</legend> - </fieldset> - <hr> - <div class="form-group"> - </div> - - <div class="form-group"> - <label class="control-label col-md-4" for="trade_date"> - trade_date - </label> - - <div class="col-md-6"> - <input class="form-control" id="trade_date" name="trade_date" value="{{trade_date}}" type="date"> - </div> - </div> - - <div class="form-group "> - - <div class="col-md-3"> - <input class="form-control" id="csrf_token" name="csrf_token" value="{{csrf_token()}}" type="hidden"> - </div> - - </div> - - <div class="form-group"> - <div class="col-md-offset-4 col-md-6"> - <div class="checkbox"> - <label> - <input id="upload_globeop" name="upload_globeop" value="y" type="checkbox">Upload to globeop? - </label> - </div> - </div> - </div> - <div class="form-group"> - <div class="col-md-offset-4 col-md-6"> - <button type="submit" class="btn btn-default">Submit</button> - </div> - </div> - </form> - <template id="fragment"> - <div class="form-group"> - <label class="control-label col-md-4" for="folder"> - folder - </label> - <div class="col-md-6"> - <select class="form-control" id="folder" name="folder"> - <option value="None"></option> - {% for strat in strategies %} - <option value="{{strat}}">{{strat}}</option> - {% endfor %} - </select> - </div> - - </div> - <div class="form-group "> - - <label class="control-label col-md-4" for="code"> - account - </label> - - <div class="col-md-6"> - <select class="form-control" id="code" name="code"> - <option value="None"></option> - {% for account in accounts %} - <option value="{{account[0]}}">{{account[1]}}</option> - {% endfor %} - </select> - </div> - - </div> - - <div class="form-group "> - <label class="control-label col-md-4" for="amount">amount</label> - - <div class="col-md-6"> - <input class="form-control" id="amount" name="amount" value="" type="text"> - </div> - </div> - <div class="form-group "> - <label class="control-label col-md-4" for="currency">currency</label> - <div class="col-md-6"> - <select class="form-control" id="currency" name="currency"> - {% for curr in currencies %} - <option value="{{curr}}">{{curr}}</option> - {% endfor %} - </select> - </div> - <div class="col-md-2"> - <input id="btn" type="button" class="btn" value="+"> - </div> - </div> - </template> - <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" - integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" - crossorigin="anonymous"></script> - <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.3/umd/popper.min.js" - integrity="sha384-vFJXuSJphROIrBnz7yo7oB41mKfc8JzQZiCq4NCceLEaO4IHwicKwpJf9c9IpFgh" - crossorigin="anonymous"></script> - <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/js/bootstrap.min.js" - integrity="sha384-alpBpkh1PFOepccYVYDB4do5UnbKysX5WZXm3XxPqe5iKTfUKjNkCk9SaVuEZflJ" - crossorigin="anonymous"></script> - <script type="text/javascript" src="{{ url_for('static', filename='wire.js') }}"></script> - <script type="text/javascript"> - {% if outgoing_wires is defined %} - var outgoing_wires = {{outgoing_wires|tojson|safe}} - {% else %} - var outgoing_wires = []; - {% endif %} - {% if incoming_wires is defined %} - var incoming_wires = {{incoming_wires|tojson|safe}} - {% else %} - var incoming_wires = []; - {% endif %} - </script> - </body> -</html> diff --git a/python/Dawn/utils.py b/python/Dawn/utils.py deleted file mode 100644 index 3dd0d1c5..00000000 --- a/python/Dawn/utils.py +++ /dev/null @@ -1,24 +0,0 @@ -import re -from pickle import dumps - - -def bump_rev(filename): - pattern = r"([^r]*)(\srev(\d)|).pdf" - begin, _, rev_number = re.match(pattern, filename).groups() - rev_number = int(rev_number) + 1 if rev_number else 1 - return f"{begin} rev{rev_number}.pdf" - - -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, - } - ) - d.update(kwargs) - return dumps(d) diff --git a/python/Dawn/views.py b/python/Dawn/views.py deleted file mode 100644 index 56bf0497..00000000 --- a/python/Dawn/views.py +++ /dev/null @@ -1,625 +0,0 @@ -import datetime -import os -import psycopg2 -import redis -import socket - -from flask import ( - abort, - request, - render_template, - redirect, - url_for, - send_from_directory, - send_file, - g, - jsonify, - session, -) - -from .models import ( - ModelForm, - CASH_STRAT, - CCY, - BondDeal, - CDSDeal, - FUND, - SwaptionDeal, - FutureDeal, - CashFlowDeal, - CapFloorDeal, - SpotDeal, - Counterparties, - Accounts, - Termination, -) - -from sqlalchemy.exc import IntegrityError -from sqlalchemy.sql import text -from sqlalchemy.sql.expression import func -from wtforms.fields import BooleanField - -from .utils import bump_rev, simple_serialize -from PyPDF2 import PdfFileMerger -from io import BytesIO -from . import app -from . import db - - -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) - ) - - -def account_codes(): - 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) - ) - - -def get_queue(): - 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") - else: - q = g.queue = redis.Redis(host="ziggy") - return q - - -def get_db(): - db = getattr(g, "_database", None) - if db is None: - 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) - if db is not None: - db.close() - - -class CounterpartyForm(ModelForm): - class Meta: - model = Counterparties - include_primary_keys = True - - -class BondForm(ModelForm): - upload_globeop = BooleanField(label="Upload to globeop?") - - 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", - ] - - -class CDSForm(ModelForm): - upload_globeop = BooleanField(label="Upload to globeop?") - - class Meta: - model = CDSDeal - include_foreign_keys = True - exclude = [ - "dealid", - "lastupdate", - "custodian", - "cashaccount", - "attach", - "detach", - ] - - -class SwaptionForm(ModelForm): - upload_globeop = BooleanField(label="Upload to globeop?") - - class Meta: - model = SwaptionDeal - include_foreign_keys = True - exclude = ["dealid", "lastupdate"] - - -class TerminationForm(ModelForm): - upload_globeop = BooleanField(label="Upload to globeop?") - - class Meta: - model = Termination - include_foreign_keys = True - - -class FutureForm(ModelForm): - upload_globeop = BooleanField(label="Upload to globeop?") - - class Meta: - model = FutureDeal - include_foreign_keys = True - exclude = ["dealid", "lastupdate"] - - -class SpotForm(ModelForm): - upload_globeop = BooleanField(label="Upload to globeop?") - - class Meta: - model = SpotDeal - include_foreign_keys = True - exclude = ["dealid", "lastupdate"] - - -class CapFloorForm(ModelForm): - upload_globeop = BooleanField(label="Upload to globeop?") - - class Meta: - model = CapFloorDeal - include_foreign_keys = True - exclude = ["dealid", "lastupdate"] - - -def get_deal(kind): - if kind == "cds": - return CDSDeal - elif kind == "bond": - return BondDeal - elif kind == "swaption": - return SwaptionDeal - elif kind == "future": - return FutureDeal - elif kind == "wire": - return CashFlowDeal - elif kind == "capfloor": - return CapFloorDeal - elif kind == "spot": - return SpotDeal - else: - raise RuntimeError(f"Unknown Deal type: {kind}") - - -def _get_form(kind): - if kind == "cds": - return CDSForm - elif kind == "bond": - return BondForm - elif kind == "swaption": - return SwaptionForm - elif kind == "future": - return FutureForm - elif kind == "capfloor": - return CapFloorForm - elif kind == "spot": - return SpotForm - else: - raise RuntimeError("Unknown Deal type") - - -def get_form(trade, kind): - Form = _get_form(kind) - if trade.id: - form = Form(obj=trade) - else: - form = Form() - # add extra empty fields - empty_choice = (None, "") - for attr in ["folder", "buysell", "asset_class", "swaption_type"]: - try: - dropdown = getattr(form, attr) - if dropdown.choices[0] != empty_choice: - dropdown.choices.insert(0, empty_choice) - except AttributeError: - continue - - if kind == "cds": - 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 (c[0] is None or (not c[0].startswith("SER_") or c[0].endswith("CURVE"))) - ] - elif kind == "swaption": - form.portfolio.choices = [("OPTIONS", "OPTIONS"), ("IR", "IR")] - form.cp_code.choices = form.cp_code.choices + list(cp_choices(kind)) - return form - - -def get_trade(tradeid, kind): - Deal = get_deal(kind) - return Deal.query.get(tradeid) if tradeid else Deal() - - -def save_ticket(trade, old_ticket_name): - if trade.ticket: - if 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 = new_name - else: - trade.ticket = old_ticket_name - - -def save_confirm(trade, old_confirm): - 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 = file_name - else: - trade.trade_confirm = 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 - ] - 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 - ] - else: - raise ValueError("direction can be one of 'outgoing' or 'incoming'") - - -def gen_cashflow_deals(form, sql_session, wire_id=None): - to_date = datetime.date.fromisoformat - d = { - "action": form.get("action"), - "trade_date": form.get("trade_date", None, to_date), - } - - for direction in ["incoming", "outgoing"]: - count = 1 - while True: - 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"] - } - ) - count += 1 - if direction == "outgoing": - d["amount"] = -float(d["amount"]) - elif direction == "incoming": - d["amount"] = float(d["amount"]) - else: - raise ValueError("direction needs to be 'outgoing' or 'incoming'") - if wire_id: - cf = CashFlowDeal.query.get(wire_id) - for k, v in d.items(): - setattr(cf, k, v) - yield cf - else: - cf = CashFlowDeal(**d) - sql_session.add(cf) - yield cf - - -@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": - wires = list(gen_cashflow_deals(request.form, db.session, wire_id)) - - try: - db.session.commit() - 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"), - ) - else: - 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")) - - 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, - ) - - -@app.route("/trades/<kind>/<dealid>/terminate", methods=["GET", "POST"]) -def terminate(dealid, kind): - termination = Termination() - form = TerminationForm(dealid=dealid) - form.termination_cp.choices = form.termination_cp.choices + list(cp_choices(kind)) - table = kind if kind.endswith("s") else kind + "s" - if form.validate_on_submit(): - form.populate_obj(termination) - sql_session = form.get_session() - rec = db.session.execute( - "SELECT notional, coalesce(terminated_amount, 0.), currency, b.globeop_id, " - "cp_code, fund " - f"FROM {table} " - "LEFT JOIN " - "(SELECT dealid, sum(termination_amount) AS terminated_amount " - " FROM terminations group by dealid) term USING (dealid) " - "LEFT JOIN LATERAL ( " - " SELECT globeop_id FROM id_mapping " - " WHERE serenitas_id=id AND date <= :date " - " ORDER BY date DESC LIMIT 1" - ") b ON true " - "WHERE dealid = :dealid", - {"dealid": dealid, "date": termination.termination_date}, - ) - notional, terminated_amount, currency, globeop_id, cp_code, fund = next(rec) - is_assignment = True - if not termination.partial_termination: - termination.termination_amount = notional - terminated_amount - if termination.termination_cp is None: - termination.termination_cp = cp_code - is_assignment = False - sql_session.add(termination) - try: - sql_session.commit() - except IntegrityError as e: - app.logger.error(e) - sql_session.rollback() - else: - buf = simple_serialize( - termination, - ccy=currency, - globeopid=globeop_id, - is_assignment=is_assignment, - ) - q = get_queue() - q.rpush(f"{kind}_{fund}_termination", buf) - return redirect(url_for("list_trades", kind=kind)) - else: - return render_template( - "termination.html", - form=form, - action_url=url_for("terminate", dealid=dealid, kind=kind), - ) - - -@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)() - - if kind == "bond": - old_ticket_name = trade.ticket - if kind == "capfloor": - old_confirm = trade.trade_confirm - if kind == "cds": - form.account_code.choices = fcm_accounts() - form.cp_code.choices = form.cp_code.choices + list(cp_choices(kind)) - if form.validate_on_submit(): - form.populate_obj(trade) - sql_session = form.get_session() - if not tradeid: - sql_session.add(trade) - if kind == "bond": - save_ticket(trade, old_ticket_name) - if kind == "capfloor": - save_confirm(trade, old_confirm) - if kind == "cds": - if trade.swap_type != "CD_INDEX": - if trade.fund == "SERCGMAST": - trade.account_code = "BAC" - elif trade.fund == "BRINKER": - trade.account_code = "BBH" - elif trade.fund == "BOWDST": - trade.account_code = "BONY" - else: - raise ValueError("Unknown fund") - trade.cashaccount = trade.fcm_account.cash_account - trade.custodian = trade.fcm_account.custodian - try: - sql_session.commit() - except IntegrityError as e: - app.logger.error(e) - sql_session.rollback() - return render_template( - "trade_entry.html", - form=form, - action_url=url_for("trade_manage", tradeid=tradeid, kind=kind), - ) - else: - 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)) - else: - if form.errors: - app.logger.error(form.errors) - form = get_form(trade, kind) - return render_template( - "trade_entry.html", - form=form, - action_url=url_for("trade_manage", tradeid=tradeid, kind=kind), - ) - - -@app.route("/", defaults={"kind": "bond", "fund": None}) -@app.route("/<kind>/<fund>") -@app.route("/<kind>", defaults={"fund": None}) -def list_trades(kind, fund): - try: - Deal = get_deal(kind) - except RuntimeError as e: - app.logger.error(e) - abort(404) - else: - if kind not in ("cds", "swaption"): - trade_list = Deal.query.order_by(Deal.trade_date.desc(), Deal.id.desc()) - if fund is not None: - trade_list = trade_list.filter( - Deal.fund == func.cast(func.upper(fund), FUND) - ) - else: - if fund is not None: - sql_str = text( - f"SELECT * FROM {kind}_trades WHERE fund=UPPER(:fund)::fund" - ) - trade_list = db.session.execute(sql_str, {"fund": fund}) - else: - trade_list = db.session.execute(f"SELECT * FROM {kind}_trades") - return render_template(f"{kind}_blotter.html", trades=trade_list) - - -@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)) - fh = BytesIO() - pdf.write(fh) - pdf.close() - fh.seek(0) - return send_file(fh, mimetype="application/pdf") - - -@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", - ) - - -@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", - ) - else: - cp_list = Counterparties.query.order_by(Counterparties.name) - 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"]) -def edit_counterparty(cpcode): - if cpcode: - cp = Counterparties.query.get(cpcode) - else: - cp = Counterparties() - cp_form = CounterpartyForm() - - old_instructions = cp.instructions or None - if cp_form.validate_on_submit(): - cp_form.populate_obj(cp) - sql_session = cp_form.get_session() - if not cpcode: - sql_session.add(cp) - instructions = cp_form.instructions - 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) - ) - sql_session.commit() - return redirect(url_for("list_counterparties")) - else: - return render_template( - "edit_cp.html", form=CounterpartyForm(obj=cp), code=cpcode - ) - - -@app.route("/_ajax", methods=["GET"]) -def get_bbg_id(): - bbg_id = request.args.get("bbg_id") - trade_date = request.args.get("trade_date", datetime.date.today()) - try: - _, indextype, _, series, tenor = bbg_id.split() - except ValueError: - return "not a valid bloomberg description", 400 - indextype = indextype[:2] - tenor = tenor[:-1] + "yr" - series = int(series[1:]) - sql_str = ( - "SELECT redindexcode, maturity, coupon " - "FROM index_desc " - "WHERE index=%s and series=%s and tenor=%s " - " and lastdate >=%s ORDER BY version" - ) - db = get_db() - with db.cursor() as c: - c.execute(sql_str, (indextype, series, tenor, trade_date)) - redcode, maturity, coupon = c.fetchone() - return jsonify( - { - "maturity": str(maturity), - "redcode": redcode, - "coupon": coupon, - } - ) |
