diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/Dawn/models.py | 68 | ||||
| -rw-r--r-- | python/Dawn/templates/base.html | 2 | ||||
| -rw-r--r-- | python/Dawn/templates/capfloor_blotter.html | 40 | ||||
| -rw-r--r-- | python/Dawn/views.py | 23 |
4 files changed, 125 insertions, 8 deletions
diff --git a/python/Dawn/models.py b/python/Dawn/models.py index d11a6394..ef686dd3 100644 --- a/python/Dawn/models.py +++ b/python/Dawn/models.py @@ -84,11 +84,18 @@ SWAP_TYPE = ENUM('CD_INDEX', 'CD_INDEX_TRANCHE', 'CD_BASKET_TRANCHE', 'ABS_CDS', 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) @@ -112,9 +119,9 @@ class BondDeal(db.Model): 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}) + buysell = db.Column(db.Boolean, nullable=False, info={'choices': [(0, 'sell'), (1, 'buy')], + 'coerce': lambda x: bool(int(x)) \ + if x is not None else x}) faceamount = db.Column(db.Float, nullable=False) price = db.Column(db.Float, nullable=False) accrued = db.Column(db.Float, nullable = False) @@ -292,6 +299,59 @@ class CashFlowDeal(db.Model): trade_date = db.Column(db.Date, nullable=False) account = db.relationship(Accounts) +class CapFloorDeal(db.Model): + __tablename__ = 'capfloors' + 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(SWAPTION_STRAT, nullable=False) + custodian = db.Column(db.String(12), default='NONE', nullable=False) + cashaccount = db.Column(db.String(10), default='SGNSCLMASW', 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) + 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}) + termination_date = db.Column(db.Date) + termination_amount = db.Column(db.Float) + termination_cp = db.Column(db.String(12), db.ForeignKey('counterparties.code'), + info={'choices': [(None, '')], + 'label': 'termination counterparty'}) + counterparty = db.relationship(Counterparties, foreign_keys=[cp_code]) + termination_counterparty = db.relationship(Counterparties, + foreign_keys=[termination_cp]) + BaseModelForm = model_form_factory(FlaskForm) class ModelForm(BaseModelForm): @classmethod diff --git a/python/Dawn/templates/base.html b/python/Dawn/templates/base.html index 3e261e42..97ba4e3d 100644 --- a/python/Dawn/templates/base.html +++ b/python/Dawn/templates/base.html @@ -29,6 +29,7 @@ <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='wire')}}">Wires</a></li> + <li><a href="{{url_for('list_trades', kind='capfloor')}}">Caps and Floors</a></li> </ul> </li> <li class="dropdown"> @@ -44,6 +45,7 @@ <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('wire_manage')}}">Wires</a></li> + <li><a href="{{url_for('trade_manage', kind='capfloor')}}">Caps and Floors</a></li> </ul> </li> <li class="dropdown"> diff --git a/python/Dawn/templates/capfloor_blotter.html b/python/Dawn/templates/capfloor_blotter.html new file mode 100644 index 00000000..e8cf14cf --- /dev/null +++ b/python/Dawn/templates/capfloor_blotter.html @@ -0,0 +1,40 @@ +{% 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>Notional</td> + <td>Type</td> + <td>Expiry</td> + <td>Strike</td> + <td>Price</td> + <td>Description</td> + <td>Red Code</td> + <td>Counterparty</td> + <td>Strategy</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.settle_date}}</td> + <td>{% if trade.buysell %}Buy{% else %}Sell{% endif %}</td> + <td>{{"{0:,.2f}".format(trade.amount)}}</td> + <td>{{trade.option_type}}</td> + <td>{{trade.expiration_date}}</td> + <td>{{trade.strike}}</td> + <td>{{trade.premium_percent}}</td> + <td>{{trade.floating_rate_index}}</td> + <td>{{trade.floating_rate_index_desc}}</td> + <td><a href="{{url_for('edit_counterparty', + cpcode=trade.counterparty.code)}}">{{trade.counterparty.name}}</a></td> + <td>{{trade.folder}}</td> + </tr> + {% endfor %} +</table> +{% endblock %} diff --git a/python/Dawn/views.py b/python/Dawn/views.py index 3aa374ac..c427e97c 100644 --- a/python/Dawn/views.py +++ b/python/Dawn/views.py @@ -10,7 +10,7 @@ from flask import (abort, request, render_template, redirect, from .models import (ModelForm, CASH_STRAT, CCY, BondDeal, CDSDeal, SwaptionDeal, FutureDeal, CashFlowDeal, - Counterparties, Accounts) + CapFloorDeal, Counterparties, Accounts) from sqlalchemy.exc import IntegrityError from wtforms.fields import BooleanField @@ -36,7 +36,7 @@ def cp_choices(kind='bond'): with_entities(Counterparties.code, Counterparties.name)) elif kind == 'future': return [] - elif kind == 'cds' or kind == 'swaption': + elif kind in ['cds', 'swaption', 'capfloor']: return (Counterparties.query. order_by('name'). filter(Counterparties.name.ilike('%CDS%')). @@ -117,6 +117,14 @@ class FutureForm(ModelForm): 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', 'termination_amount', + 'termination_cp', 'termination_date'] def get_deal(kind): if kind == 'cds': @@ -129,6 +137,8 @@ def get_deal(kind): return FutureDeal elif kind == 'wire': return CashFlowDeal + elif kind == 'capfloor': + return CapFloorDeal else: raise RuntimeError(f'Unknown Deal type: {kind}') @@ -142,6 +152,8 @@ def _get_form(kind): return SwaptionForm elif kind == 'future': return FutureForm + elif kind == 'capfloor': + return CapFloorForm else: raise RuntimeError('Unknown Deal type') @@ -389,11 +401,14 @@ def get_bbg_id(): tenor = tenor[:-1] + 'yr' series = int(series[1:]) sqlstr1 = "SELECT * FROM index_redcode(%s::index_type, %s::smallint, %s)" - sqlstr2 = "SELECT maturity, coupon FROM index_maturity WHERE index=%s and series=%s and tenor=%s" + sqlstr2 = ("SELECT maturity, coupon FROM index_maturity WHERE index=%s " + "and series=%s and tenor=%s") db = get_db() with db.cursor() as c: c.execute(sqlstr1, (indextype, series, pd.datetime.today().date())) (redcode,) = c.fetchone() c.execute(sqlstr2, (indextype, series, tenor)) maturity, coupon = c.fetchone() - return jsonify({'maturity': maturity.strftime('%Y-%m-%d'), 'redcode': redcode, 'coupon': coupon}) + return jsonify({'maturity': maturity.strftime('%Y-%m-%d'), + 'redcode': redcode, + 'coupon': coupon}) |
