# -*- coding: utf8 -*- from pyramid.response import Response from pyramid.renderers import render, get_renderer from pyramid.view import ( view_config, forbidden_view_config, ) from pyramid.httpexceptions import ( HTTPFound, HTTPNotFound, HTTPForbidden, ) from pyramid_mailer import get_mailer from pyramid_mailer.message import Message, Attachment from datetime import * import hashlib from sqlalchemy.exc import DBAPIError from ..security import groupfinder from ..models.default import * from ..models.actifs import * from ..models.members import ( get_member_by_email, ) from ..views.default import ( to_euro, to_usd, to_decimal, ) import json import time import yfinance as yf import html @view_config(route_name='portfolio', renderer='../templates/actifs/portfolio.pt', permission='view') def portfolio(request): logged_in = request.authenticated_userid member = get_member_by_email(request, logged_in) url = request.route_url('portfolio') message = '' # lire les categories items = get_allocation(request, '0') # construire la liste pour donut donut_cible=[] donut_cible.append(('Allocation cible', 'Pourcent')) donut_actuel=[] donut_actuel.append(('Allocation actuelle', 'Pourcent')) # calculer % total total = 0 for item in items: # construire la liste pour donut cible d = (item.classe, item.pc_cible) donut_cible.append(d) # construire la liste pour donut actuel d = (item.classe, int(item.pc_atteint * 10)) donut_actuel.append(d) # totaliser les pourcentages total += item.pc_cible if total != 100: message = 'Attention, le total de votre répartition cible est incorrect : %s.' % total # lire les actifs actifs = get_actifs(request, '0') # MAJ du prtefeuille if 'form.submitted' in request.params: # lire le cours de EURUSD ticker = yf.Ticker('EUR=X') # maj des parités des devises update_actif_devise(request, 'USD', ticker.info.get('regularMarketPrice')) for item in actifs: if item.type == 'ACTION': # lire le cours de l'action ticker = yf.Ticker(item.symbole) # caluler son rendement dividends = get_dividends(ticker) update_actif_valeur(request, item.symbole, ticker.info.get('regularMarketPrice'), dividends) time.sleep(1) # attendre 2 secondes # update du portefeuille update_portefeuille(request, logged_in) # relire les actifs actifs = get_actifs(request, '0') message = 'Le portefeuille est mis à jour avec succès.' total_valeur = 0 total_pv = 0 total_rdt = 0 for item in actifs: total_valeur += item.valeur total_pv += item.plus_value total_pc_value = total_pv / total_valeur * 100 total_rdt += item.rendement # lire l'historique histos = get_histo(request,'0') courbe_evoln=[] courbe_evoln.append(('Date', 'Valeur part PF', 'Valeur part CARINVT:FP')) for item in histos: # construire la liste pour donut cible d = (item.date.strftime('%d/%m/%Y'), int(item.val_part * 1000), int(item.val_part_ref * 1000)) courbe_evoln.append(d) return { 'page_title': "Portefeuille", 'message': message, 'url': url, 'items': items, 'member': member, 'donut_cible': json.dumps(donut_cible), 'donut_actuel': json.dumps(donut_actuel), 'courbe_evoln': json.dumps(courbe_evoln), 'actifs': actifs, 'total_valeur': total_valeur, 'total_pv': total_pv, 'total_pc_value': total_pc_value, 'total_rdt': total_rdt } @view_config(route_name='actif_edit', renderer='../templates/actifs/actif_edit.pt', permission='view') def actif_edit(request): no_id = request.matchdict['no_id'] url = request.route_url('actif_edit', no_id=no_id) message = '' allocation_list = get_allocation_bytype(request,'ACTION') if no_id == '0': # nouveau actif = {} actif['no_id'] = '0' actif['symbole'] = '' actif['libelle'] = '' actif['classe'] = '' actif['devise'] = 'EUR' actif['nombre'] = '0' actif['pru'] = '0' actif['ter'] = '0' actif['pc_rdt'] = '0' actif['website'] = '' actif['modif_le'] = None page_title= 'Nouvel actif ACTION' else: # lire la fiche du actif actif = get_actifs(request, no_id) if not actif: request.session.flash(u"Actif non trouvé : %s" % no_id, 'warning') return HTTPFound(location=request.route_url('portfolio')) page_title= "Actif ACTION : %s" % (actif.libelle) if 'form.submitted' in request.params: new_values = {} for param, db_value in actif.items(): if param in request.params and request.params[param] != db_value: new_values[param] = request.params[param] if new_values: if 'symbole' in request.params: symbole = request.params['symbole'] else: symbole = actif.symbole # récupérer le cours du symbole de Yahoo finance ticker = yf.Ticker(symbole) new_values['cours'] = ticker.info.get('regularMarketPrice') new_values['devise'] = ticker.info.get('currency') new_values['libelle'] = html.unescape(ticker.info.get('shortName')) update_actif(request, no_id, new_values) request.session.flash(u"La fiche a été mise à jour avec succès.", 'success') return HTTPFound(location=request.route_url('portfolio')) if 'form.deleted' in request.params: delete_actif(request, no_id) request.session.flash(u"La fiche a été supprimée avec succès.", 'success') return HTTPFound(location=request.route_url('portfolio')) return { 'page_title': page_title, 'url': url, 'actif': actif, 'allocation_list': allocation_list, 'message': message, } @view_config(route_name='actif2_edit', renderer='../templates/actifs/actif2_edit.pt', permission='view') def actif2_edit(request): no_id = request.matchdict['no_id'] url = request.route_url('actif2_edit', no_id=no_id) message = '' allocation_list = get_allocation_bytype(request,'AUTRE') if no_id == '0': # nouveau actif = {} actif['no_id'] = '0' actif['symbole'] = '' actif['classe'] = '' actif['libelle'] = '' actif['pru'] = '0' actif['cours'] = '0' actif['ter'] = '0' actif['pc_rdt'] = '0' actif['modif_le'] = None page_title= 'Nouvel actif' else: # lire la fiche du actif actif = get_actifs(request, no_id) if not actif: request.session.flash(u"Actif non trouvé : %s" % no_id, 'warning') return HTTPFound(location=request.route_url('portfolio')) page_title= "Actif : %s" % (actif.symbole) if 'form.submitted' in request.params: new_values = {} for param, db_value in actif.items(): if param in request.params and request.params[param] != db_value: new_values[param] = request.params[param] if new_values: new_values['nombre'] = 1000 new_values['devise'] = 'EUR' update_actif(request, no_id, new_values) request.session.flash(u"La fiche a été mise à jour avec succès.", 'success') return HTTPFound(location=request.route_url('portfolio')) if 'form.deleted' in request.params: delete_actif(request, no_id) request.session.flash(u"La fiche a été supprimée avec succès.", 'success') return HTTPFound(location=request.route_url('portfolio')) return { 'page_title': page_title, 'url': url, 'actif': actif, 'allocation_list': allocation_list, 'message': message, } @view_config(route_name='allocation_edit', renderer='../templates/actifs/allocation_edit.pt', permission='view') def allocation_edit(request): no_cat = request.matchdict['no_cat'] url = request.route_url('allocation_edit', no_cat=no_cat) message = '' # lire les classes classes_list = get_classes(request, '0') if no_cat == '0': # nouveau allocation = {} allocation['no_cat'] = '0' allocation['classe'] = '' allocation['type'] = 'ACTION' allocation['pc_cible'] = '0' page_title= 'Nouvelle classe' else: # lire la fiche de la categorie allocation = get_allocation(request, no_cat) if not allocation: request.session.flash(u"Classe non trouvé : %s" % no_cat, 'warning') return HTTPFound(location=request.route_url('portfolio')) page_title= "Classe : %s" % (allocation.classe) if 'form.submitted' in request.params: new_values = {} for param, db_value in allocation.items(): if param in request.params and request.params[param] != db_value: new_values[param] = request.params[param] if new_values: update_allocation(request, no_cat, new_values) request.session.flash(u"La fiche a été mise à jour avec succès.", 'success') return HTTPFound(location=request.route_url('portfolio')) if 'form.deleted' in request.params: delete_allocation(request, no_cat) request.session.flash(u"La fiche a été supprimée avec succès.", 'success') return HTTPFound(location=request.route_url('portfolio')) return { 'page_title': page_title, 'url': url, 'allocation': allocation, 'classes_list': classes_list, 'message': message, } @view_config(route_name='histo_list', renderer='../templates/actifs/histo_list.pt', permission='manage') def histo_list(request): # lire l historique items = get_histo(request, '0') liste=[] for item in items: # construire la liste pour datatable d = (item.date.strftime('%d/%m/%Y'), to_euro(item.mvt_cash), to_euro(item.valeur_pf), str(item.nb_part), to_euro(item.val_part), to_euro(item.cours_ref), to_euro(item.val_part_ref), str(item.no_id).zfill(4)) liste.append(d) return { 'page_title': 'Historique', 'dt_data': json.dumps(liste), } @view_config(route_name='histo_edit', renderer='../templates/actifs/histo_edit.pt', permission='view') def histo_edit(request): no_id = request.matchdict['no_id'] url = request.route_url('histo_edit', no_id=no_id) message = '' today = datetime.today() if no_id == '0': # nouveau item = {} item['no_id'] = 0 item['date'] = today item['mvt_cash'] = 0.0 item['nb_part'] = 0.0 page_title= 'Nouvelle valeur part' else: # lire la fiche de la categorie item = get_histo(request, no_id) if not item: request.session.flash(u"Histo non trouvé : %s" % no_id, 'warning') return HTTPFound(location=request.route_url('histo_list')) page_title= "Valeur part au %s" % (item.date.strftime('%d/%m/%Y')) if 'form.submitted' in request.params: new_values = {} for param, db_value in item.items(): if param in request.params and request.params[param] != db_value: new_values[param] = request.params[param] if new_values: # lire le cours de l'indice de réfence : Carmignac Investissement A EUR Acc ticker = yf.Ticker('0P00000FB2.F') new_values['cours_ref'] = ticker.info.get('regularMarketPrice') update_histo(request, no_id, new_values) request.session.flash(u"La fiche a été mise à jour avec succès.", 'success') return HTTPFound(location=request.route_url('histo_list')) if 'form.deleted' in request.params: delete_histo(request, no_id) request.session.flash(u"La fiche a été supprimée avec succès.", 'success') return HTTPFound(location=request.route_url('histo_list')) return { 'page_title': page_title, 'url': url, 'item': item, 'today': today, 'message': message, }