aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--python/Dawn/__init__.py25
-rw-r--r--python/Dawn/models.py709
-rw-r--r--python/Dawn/static/LMCG.pngbin50746 -> 0 bytes
-rw-r--r--python/Dawn/static/dawn.css5
-rw-r--r--python/Dawn/static/dawn.js194
-rwxr-xr-xpython/Dawn/static/favicon.icobin5430 -> 0 bytes
-rw-r--r--python/Dawn/static/utils.js26
-rw-r--r--python/Dawn/static/wire.js46
-rw-r--r--python/Dawn/templates/base.html72
-rw-r--r--python/Dawn/templates/bond_blotter.html43
-rw-r--r--python/Dawn/templates/capfloor_blotter.html41
-rw-r--r--python/Dawn/templates/cds_blotter.html43
-rw-r--r--python/Dawn/templates/counterparties.html43
-rw-r--r--python/Dawn/templates/edit_cp.html30
-rw-r--r--python/Dawn/templates/future_blotter.html42
-rw-r--r--python/Dawn/templates/spot_blotter.html35
-rw-r--r--python/Dawn/templates/swaption_blotter.html46
-rw-r--r--python/Dawn/templates/termination.html50
-rw-r--r--python/Dawn/templates/trade_entry.html51
-rw-r--r--python/Dawn/templates/wire_blotter.html25
-rw-r--r--python/Dawn/templates/wire_entry.html150
-rw-r--r--python/Dawn/utils.py24
-rw-r--r--python/Dawn/views.py625
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
deleted file mode 100644
index ec1c5292..00000000
--- a/python/Dawn/static/LMCG.png
+++ /dev/null
Binary files differ
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
deleted file mode 100755
index bee8bf36..00000000
--- a/python/Dawn/static/favicon.ico
+++ /dev/null
Binary files differ
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,
- }
- )