from flask import (request, render_template, redirect, url_for, send_from_directory, send_file, g, jsonify) from .models import ModelForm, BondDeal, CDSDeal, Counterparties from sqlalchemy.exc import IntegrityError from wtforms.fields import BooleanField import pandas as pd from pandas.tseries.offsets import BDay import os import datetime import redis from .utils import load_counterparties, bump_rev, simple_serialize from PyPDF2 import PdfFileMerger from io import BytesIO from Dawn import app import socket import psycopg2 def cp_choices(): return Counterparties.query.order_by('name').\ with_entities(Counterparties.code, Counterparties.name) def get_queue(): q = getattr(g, 'queue', None) if q is None: hostname = socket.gethostname() if hostname == 'debian': q = g.queue = redis.Redis(unix_socket_path='/var/run/redis/redis.sock') elif hostname =='gomez': q = g.queue = redis.Redis(host='debian') 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 class CounterpartyForm(ModelForm): class Meta: model = Counterparties 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'] @app.route('/trades/', methods=['GET', 'POST']) @app.route('/trades/', defaults={'tradeid': None}, methods=['GET', 'POST']) def trade_manage(tradeid): trade = BondDeal.query.get(tradeid) if tradeid else BondDeal() if tradeid: bond_form = BondForm(obj = trade) old_ticket_name = trade.ticket else: bond_form = BondForm(trade_date = pd.datetime.today().date(), settle_date = pd.datetime.today().date() + 3 * BDay()) #add extra empty fields bond_form.folder.choices = [(None, '')] + bond_form.folder.choices bond_form.buysell.choices = [(None, '')] + bond_form.buysell.choices bond_form.asset_class.choices = [(None, '')] + bond_form.asset_class.choices bond_form.cp_code.choices = bond_form.cp_code.choices + list(cp_choices()) if bond_form.is_submitted(): if bond_form.validate(): bond_form.populate_obj(trade) session = bond_form.get_session() ticket_file = trade.ticket trade.ticket = None if not tradeid: session.add(trade) if ticket_file.filename == '': if tradeid: trade.ticket = old_ticket_name else: if tradeid and old_ticket_name: trade.ticket = bump_rev(old_ticket_name) else: trade.ticket = "{0} {1}.pdf".format(str(trade.trade_date), trade.description) ticket_file.save(os.path.join(app.config['TICKETS_FOLDER'], trade.ticket)) try: session.commit() except IntegrityError as e: app.logger.error(e) finally: if bond_form.upload_globeop.data: q = get_queue() q.rpush('bond_trades', simple_serialize(trade)) return redirect(url_for('list_trades')) else: return str(bond_form.errors) return render_template('trade_entry.html', form=bond_form, trade_id=tradeid) @app.route('/cdstrades/', methods=['GET', 'POST']) @app.route('/cdstrades/', defaults={'tradeid': None}, methods=['GET', 'POST']) def cds_trade_manage(tradeid): trade = CDSDeal.query.get(tradeid) if tradeid else CDSDeal() if tradeid: cds_form = CDSForm(obj = trade) else: today = pd.datetime.today() tomorrow = today + pd.DateOffset(1) cds_form = CDSForm(trade_date = today.date(), effective_date= tomorrow.date(), upfront_settle_date = today.date() + 3 * BDay()) cds_form.cp_code.choices = cds_form.cp_code.choices + list(cp_choices()) if cds_form.is_submitted(): if cds_form.validate(): cds_form.populate_obj(trade) session = cds_form.get_session() if not tradeid: session.add(trade) try: session.commit() except IntegrityError as e: app.logger.error(e) finally: if cds_form.upload_globeop.data: q = get_queue() q.rpush('cds_trades', simple_serialize(trade)) return redirect(url_for('list_cds_trades')) return render_template('cds_trade_entry.html', form=cds_form, trade_id=tradeid) @app.route('/blotter/') def list_trades(): trade_list = BondDeal.query.order_by(BondDeal.trade_date.desc(), BondDeal.id.desc()) return render_template('blotter.html', trades=trade_list.all()) @app.route('/cdsblotter') def list_cds_trades(): trade_list = CDSDeal.query.order_by(CDSDeal.trade_date.desc(), CDSDeal.id.desc()) return render_template('cds_blotter.html', trades=trade_list.all()) @app.route('/tickets/') 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('/counterparties/', 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/', methods=['GET', 'POST']) def edit_counterparty(cpcode): cp = Counterparties.query.get(cpcode) cp_form = CounterpartyForm(obj = cp) old_instructions = cp.instructions if cp_form.is_submitted(): if cp_form.validate(): cp_form.populate_obj(cp) session = cp_form.get_session() instructions = cp.instructions if instructions.filename == '': cp.instructions = old_instructions else: cp.instructions = cp.name + '.pdf' instructions.save(os.path.join(app.config['CP_FOLDER'], cp.instructions)) session.commit() return redirect(url_for('list_counterparties')) return render_template('edit_cp.html', form=cp_form, code=cpcode) @app.route('/_ajax', methods=['GET']) def get_bbg_id(): bbg_id = request.args.get('bbg_id') _, indextype, _, series, tenor = bbg_id.split() indextype = indextype[:2] 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" db = get_db() with db.cursor() as c: print(indextype, series) c.execute(sqlstr1, (indextype, series, datetime.datetime(2015,10, 25).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})