diff --git a/ctp_blogr/models/__init__.py b/ctp_blogr/models/__init__.py index a193760..d82b4c0 100644 --- a/ctp_blogr/models/__init__.py +++ b/ctp_blogr/models/__init__.py @@ -7,7 +7,6 @@ import zope.sqlalchemy # Base.metadata prior to any initialization routines from .user import User from .blog_record import BlogRecord -from .portfolio import Actifs # run configure_mappers after defining all of the models to ensure # all relationships can be setup diff --git a/ctp_blogr/models/portfolio.py b/ctp_blogr/models/portfolio.py deleted file mode 100644 index fc1370c..0000000 --- a/ctp_blogr/models/portfolio.py +++ /dev/null @@ -1,63 +0,0 @@ -import datetime #<- will be used to set default dates on models -from ctp_blogr.models.meta import Base #<- we need to import our sqlalchemy metadata from which model classes will inherit -from sqlalchemy.orm import relationship -from sqlalchemy import ( - Column, - Integer, - Float, - Unicode, #<- will provide Unicode field - UnicodeText, #<- will provide Unicode text field - DateTime, #<- time abstraction field - Index, - ForeignKey, -) - - -class Actifs(Base): - __tablename__ = 'actifs' - no_id = Column(Integer, primary_key=True) - symbole = Column(Unicode(45), unique=True, nullable=False) - libelle = Column(Unicode(45), nullable=False) - classe = Column(Unicode(45), nullable=False) - nombre = Column(Integer) - cours = Column(Float) - pru = Column(Float) - valeur = Column(Float) - plus_value = Column(Float) - pc_plusvalue = Column(Float) - rendement = Column(Float) - pc_rdt = Column(Float) - pc_allocation = Column(Float) - ter = Column(Float) - ter_pondere = Column(Float) - devise = Column(Unicode(45), default='EUR') - parite = Column(Float) - website = Column(Unicode(100)) - modif_le = Column(DateTime, default=datetime.datetime.utcnow) - __table_args__ = (Index('symbole_index', 'symbole'),) - - -class Allocation(Base): - __tablename__ = 'allocation' - no_cat = Column(Integer, primary_key=True) - classe = Column(Unicode(45), ForeignKey('actifs.classe')) - pc_cible = Column(Integer) - pc_atteint = Column(Float) - pc_ecart = Column(Float) - valeur = Column(Float) - type = Column(Unicode(45), default='ACTION') - ordre = Column(Integer) - bg_color = Column(Unicode(45)) - __table_args__ = (Index('classe_index', 'classe'), Index('ordre_index', 'ordre'),) - - -class Histo(Base): - __tablename__ = 'histo' - no_id = Column(Integer, primary_key=True) - date = Column(DateTime, default=datetime.datetime.utcnow) - mvt_cash = Column(Float) - valeur_pf = Column(Float) - nb_part = Column(Float) - val_part = Column(Float) - cours_ref = Column(Float) - val_part_ref = Column(Float) diff --git a/ctp_blogr/services/portfolio.py b/ctp_blogr/services/portfolio.py deleted file mode 100644 index a932ccf..0000000 --- a/ctp_blogr/services/portfolio.py +++ /dev/null @@ -1,106 +0,0 @@ -import sqlalchemy as sa -from sqlalchemy import func -from ..models.portfolio import Actifs, Allocation, Histo - -class PFService(object): - - @classmethod - def get_actifs(cls, request, no_id): - if no_id == '0': - items = request.dbsession.query(Actifs, Allocation).join(Allocation).order_by(Allocation.ordre, Actifs.libelle).all() - else: - # lire une allocation par le no_id - items = request.dbsession.query(Actifs).filter(Actifs.no_id == no_id).first() - return items - - @classmethod - def get_allocation(cls, request, no_cat): - if no_cat == '0': - query = request.dbsession.query(Allocation) - query = query.order_by(sa.asc(Allocation.ordre)).all() - else: - # lire une allocation par le no_id - query = request.dbsession.query(Allocation).filter(Allocation.no_cat == no_cat).first() - return query - - @classmethod - def get_allocation_byType(cls, request, type): - # lire une allocation par le no_id - query = request.dbsession.query(Allocation).filter(Allocation.type == type).all() - return query - - @classmethod - def get_histo(cls, request, no_id): - if no_id == '0': - items = request.dbsession.query(Histo).order_by(sa.asc(Histo.date)).all() - elif no_id == '-1': - items = request.dbsession.query(Histo).order_by(sa.desc(Histo.date)).all() - else: - # lire le histo par le no_id - items = request.dbsession.query(Histo).filter(Histo.no_id == no_id).first() - return items - - @classmethod - def get_last_histo(cls, request): - # lire le dernier histo créé - items = request.dbsession.query(Histo).order_by(sa.desc(Histo.date)).first() - return items - - @classmethod - def delete_allocation(cls, request, no_cat): - request.dbsession.query(Allocation).filter(Allocation.no_cat == no_cat).delete(synchronize_session=False) - return - - @classmethod - def delete_histo(cls, request, no_id): - request.dbsession.query(Histo).filter(Histo.no_id == no_id).delete(synchronize_session=False) - return - - @classmethod - def update_actif_devise(cls, request, devise, taux): - request.dbsession.query(Actifs).filter(Actifs.devise == devise).update({'parite': taux}) - return - - def update_actif_valeur(request, symbole, cours, valeur, plus_value, pc_plusvalue): - request.dbsession.query(Actifs).filter(Actifs.symbole == symbole - ).update({'cours': cours, - 'valeur': valeur, - 'plus_value':plus_value, - 'pc_plusvalue': pc_plusvalue, - }) - return - - def update_portefeuille(request, today): - # cumuler la valeur totale des actifs - result = request.dbsession.query(Actifs, func.sum(Actifs.valeur).label("TotalValue")).first() - TotalValue = result.TotalValue - # maj du pourcentage d'allocation des lignes du portefeuille - items = PFService.get_actifs(request, '0') - for item in items: - pc_allocation = round(item.Actifs.valeur / TotalValue * 100, 3) - request.dbsession.query(Actifs).filter(Actifs.no_id == item.Actifs.no_id).update({'pc_allocation': pc_allocation, - 'modif_le': today}) - - # maj des allocations - items = PFService.get_allocation(request, '0') - for item in items: - # cumuler la valeur totale des actifs de cette classe - result = request.dbsession.query(Actifs, func.sum(Actifs.valeur).label("TotalClasse") - ).filter(Actifs.classe == item.classe).first() - TotalClasse = result.TotalClasse - pc_atteint = round(TotalClasse / TotalValue * 100, 3) - # maj du pourcentage d'allocation de cette classe - request.dbsession.query(Allocation).filter(Allocation.classe == item.classe - ).update({'valeur': TotalClasse, - 'pc_atteint': pc_atteint}) - - return - - def delete_actif(request, no_id): - request.dbsession.query(Actifs).filter(Actifs.no_id == no_id).delete(synchronize_session=False) - return - - - - - diff --git a/ctp_blogr/static/blog/Conso_2024_en_euro.png b/ctp_blogr/static/blog/Conso_2024_en_euro.png new file mode 100644 index 0000000..efb63ca Binary files /dev/null and b/ctp_blogr/static/blog/Conso_2024_en_euro.png differ diff --git a/ctp_blogr/static/blog/Conso_2024_en_kWh.png b/ctp_blogr/static/blog/Conso_2024_en_kWh.png new file mode 100644 index 0000000..c2a8bad Binary files /dev/null and b/ctp_blogr/static/blog/Conso_2024_en_kWh.png differ diff --git a/ctp_blogr/static/blog/Conso_2025_en_KWh.png b/ctp_blogr/static/blog/Conso_2025_en_KWh.png new file mode 100644 index 0000000..eb15dc3 Binary files /dev/null and b/ctp_blogr/static/blog/Conso_2025_en_KWh.png differ diff --git a/ctp_blogr/static/blog/Conso_2025_en_euro.png b/ctp_blogr/static/blog/Conso_2025_en_euro.png new file mode 100644 index 0000000..c5ef50f Binary files /dev/null and b/ctp_blogr/static/blog/Conso_2025_en_euro.png differ diff --git a/ctp_blogr/templates/portfolio/actif2_edit.jinja2 b/ctp_blogr/templates/portfolio/actif2_edit.jinja2 deleted file mode 100644 index d7d0d5d..0000000 --- a/ctp_blogr/templates/portfolio/actif2_edit.jinja2 +++ /dev/null @@ -1,88 +0,0 @@ -{% extends "ctp_blogr:templates/layout.jinja2" %} - -{% block content %} - -
- -
- - {{ form.classe(class_='form-control') }} -
- - {% for error in form.symbole.errors %} -
{{ error }}
- {% endfor %} -
- - {{form.symbole(class_='form-control')}} -
- - {% for error in form.libelle.errors %} -
{{ error }}
- {% endfor %} -
- - {{form.libelle(class_='form-control')}} -
- -
- -
-
{{ item.devise }}
- {{form.pru(class_='form-control')}} -
-
- -
- -
-
{{ item.devise }}
- {{form.cours(class_='form-control')}} -
-
- -
-

Dernière modif. : {{ item.modif_le }}

-
- -
-
- - Retour - - {% if form.no_id.data %} - - {% endif %} -
- - -
- - - - -{% endblock %} diff --git a/ctp_blogr/templates/portfolio/actif_edit.jinja2 b/ctp_blogr/templates/portfolio/actif_edit.jinja2 deleted file mode 100644 index e8afbeb..0000000 --- a/ctp_blogr/templates/portfolio/actif_edit.jinja2 +++ /dev/null @@ -1,111 +0,0 @@ -{% extends "ctp_blogr:templates/layout.jinja2" %} - -{% block content %} - -
- -
- - {{ form.classe(class_='form-control') }} -
- - {% for error in form.symbole.errors %} -
{{ error }}
- {% endfor %} -
- - {{form.symbole(class_='form-control')}} -
- - {% for error in form.libelle.errors %} -
{{ error }}
- {% endfor %} -
- - {{form.libelle(class_='form-control')}} -
- -
- - {{form.nombre(class_='form-control')}} -
- -
- -
-
{{ item.devise }}
- {{form.pru(class_='form-control')}} -
-
- -
- -
-
%
- {{form.ter(class_='form-control')}} -
-
- -
- -
-
%
- {{form.pc_rdt(class_='form-control')}} -
-
- -
- -
-
- -
- {{form.website(class_='form-control')}} -
-
- -
-

Dernière modif. : {{ item.modif_le }}

-
- -
-
- - Retour - - {% if form.no_id.data %} - - {% endif %} -
- - -
- - - - -{% endblock %} diff --git a/ctp_blogr/templates/portfolio/allocation_edit.jinja2 b/ctp_blogr/templates/portfolio/allocation_edit.jinja2 deleted file mode 100644 index 370b24c..0000000 --- a/ctp_blogr/templates/portfolio/allocation_edit.jinja2 +++ /dev/null @@ -1,69 +0,0 @@ -{% extends "ctp_blogr:templates/layout.jinja2" %} - -{% block content %} - -
- -
- - {{ form.classe(class_='form-control') }} -
- - {% for error in form.pc_cible.errors %} -
{{ error }}
- {% endfor %} -
- - {{form.pc_cible(class_='form-control')}} -
- -
- - {{form.type(class_='form-control')}} -
-
- - {{form.bg_color(class_='form-control')}} -
- -
-
- - Retour - - {% if form.no_cat.data %} - - {% endif %} -
- - -
- - - - -{% endblock %} diff --git a/ctp_blogr/templates/portfolio/histo_edit.jinja2 b/ctp_blogr/templates/portfolio/histo_edit.jinja2 deleted file mode 100644 index 296fef4..0000000 --- a/ctp_blogr/templates/portfolio/histo_edit.jinja2 +++ /dev/null @@ -1,64 +0,0 @@ -{% extends "ctp_blogr:templates/layout.jinja2" %} - -{% block content %} - -
- -
-

Date : {{ item.date.strftime('%d-%m-%Y') }}

-
- - {% for error in form.mvt_cash.errors %} -
{{ error }}
- {% endfor %} -
- -
-
- {{form.mvt_cash(class_='form-control')}} -
-

(si le montant est négatif, le montant est retiré du portefeuille)

-
- -
-
- - Retour - {% if form.no_id.data %} - - {% else %} - - {% endif %} -
- - -
- - - - -{% endblock %} diff --git a/ctp_blogr/templates/portfolio/histo_list.jinja2 b/ctp_blogr/templates/portfolio/histo_list.jinja2 deleted file mode 100644 index 105eddc..0000000 --- a/ctp_blogr/templates/portfolio/histo_list.jinja2 +++ /dev/null @@ -1,49 +0,0 @@ -{% extends "ctp_blogr:templates/layout.jinja2" %} - -{% block content %} - -

- - Retour - - Entrée / Sortie cash -

- - - - - - - - - - - - - - - {% for item in items %} - - - - - - - - - - - {% endfor %} -
DateE/S CashValeur PfNb PartValeur PartCours refNb Part refNo Id
{{ item.date.strftime('%d/%m/%Y') }}{{ '{0:0.2f} €'.format(item.mvt_cash) }}{{ '{0:0.2f} €'.format(item.valeur_pf) }}{{ '{0:0.2f}'.format(item.nb_part) }}{{ '{0:0.2f} €'.format(item.val_part) }}{{ '{0:0.2f} €'.format(item.cours_ref) }}{{ '{0:0.2f}'.format(item.val_part_ref) }} - {{ item.no_id }} -
-
-
- - -{% endblock %} - - - - - diff --git a/ctp_blogr/templates/portfolio/portfolio.jinja2 b/ctp_blogr/templates/portfolio/portfolio.jinja2 deleted file mode 100644 index 539bc33..0000000 --- a/ctp_blogr/templates/portfolio/portfolio.jinja2 +++ /dev/null @@ -1,245 +0,0 @@ -{% extends "ctp_blogr:templates/layout.jinja2" %} - -{% block content %} - -

- [ Nouvelle classe ] -

-
-
- - - - - - - - - - - - {% for item in items %} - - - - - {% if (item.pc_atteint - item.pc_cible) >= 0 %} - - {% else %} - - {% endif %} - - - {% endfor %} - -
Classe% cible% actuelEcartValeur
{{ item.classe }}{{ item.pc_cible }} %{{ '{0:0.1f}'.format(item.pc_atteint) }} %{{ '{0:0.1f}'.format(item.pc_ecart) }}{{ '{0:0.1f}'.format(item.pc_ecart) }}{{ '{0:0,.0f} €'.format(item.valeur).replace(',',' ') }}
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - -
PortefeuilleMontant%
Valorisation{{ '{0:0.2f} €'.format(total_valeur).replace(',',' ') }}
Plus value{{ '{0:0,.0f} €'.format(total_pv).replace(',',' ') }}{{ '{0:0.1f} %'.format(total_pc_value) }}
Safe Withdrawal Rate{{ '{0:0,.0f} €'.format(swr_amount) }}{{ '{0:0.1f} %'.format(swr_rate) }}
-

- Allocation globale : 70% actions + 30% obligations
- [Inspirée du - Fond souverain Norvégien]
- Allocation actions : 80% Monde (56%) + 20% Croissance (14%)
-

-
- -
- -
-
- -
-
-
- -
-
-
- -
-

Mes actifs

-

"Diversification is not determined by the number of securities held." - Larry Swedroe

- -
-
- - [ Nouvel actif ] - [ Historique ] - [ Mouvements ] -
-
- - - - - - - - - - - - - - - - - {% for ligne in actifs %} - - - {% if ligne.Allocation.type=='ACTION' %} - - {% else %} - - {% endif %} - {% if ligne.Actifs.devise=='EUR' %} - - {% else %} - - {% endif %} - - - {% if ligne.Actifs.plus_value >= 0 %} - - - {% else %} - - - {% endif %} - - - - {% endfor %} - - - - - {% if total_pv >= 0 %} - - - {% else %} - - - {% endif %} - - - - -
ClasseLibelléCoursNbValeur+/- Valeur% de +/-% TER% PF
{{ ligne.Allocation.classe }}{{ ligne.Actifs.libelle }}{{ ligne.Actifs.libelle }}{{ '{0:0.2f} €'.format(ligne.Actifs.cours) }}{{ '{0:0.2f} $'.format(ligne.Actifs.cours) }}{{ ligne.Actifs.nombre }}{{ '{0:0,.2f} €'.format(ligne.Actifs.valeur).replace(',',' ') }}{{ '{0:0,.2f} €'.format(ligne.Actifs.plus_value).replace(',',' ') }}{{ '{0:0.1f}'.format(ligne.Actifs.pc_plusvalue) }}{{ '{0:0,.2f} €'.format(ligne.Actifs.plus_value).replace(',',' ') }}{{ '{0:0.1f}'.format(ligne.Actifs.pc_plusvalue) }}{{ '{0:0.1f}'.format(ligne.Actifs.ter) }}{{ '{0:0.1f}'.format(ligne.Actifs.pc_allocation) }}
Total au {{ maj_pf_le.strftime('%d/%m/%Y') }}{{ '{0:0,.2f} €'.format(total_valeur).replace(',',' ') }}{{ '{0:0,.2f} €'.format(total_pv).replace(',',' ') }}{{ '{0:0.1f}'.format(total_pc_value) }}{{ '{0:0,.2f} €'.format(total_pv).replace(',',' ') }}{{ '{0:0.1f}'.format(total_pc_value) }}100.0
-
-
-
- -
-
-
- - - - - - - - - - - - -{% endblock %} diff --git a/ctp_blogr/views/portfolio.py b/ctp_blogr/views/portfolio.py deleted file mode 100644 index 6b3cd19..0000000 --- a/ctp_blogr/views/portfolio.py +++ /dev/null @@ -1,373 +0,0 @@ -from pyramid.view import ( - view_config, -) -from pyramid.httpexceptions import HTTPFound -from ..services.portfolio import PFService -from ..forms import ActifForm, Actif2Form, AllocationForm, HistoForm -from ..models.portfolio import Actifs, Histo, Allocation - -import datetime #<- will be used to set default dates on models -import yfinance as yf -import json -import html - -@view_config(route_name='portfolio', renderer='../templates/portfolio/portfolio.jinja2', permission='view') -def portfolio(request): - logged_in = request.authenticated_userid - url = request.route_url('portfolio') - - # lire les categories - items = PFService.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 - - swr_rate = 3.5 - if total != 100: - request.session.flash('Attention, le total de votre répartition cible dépasse 100% : ' + str(total), 'warning') - - # lire les actifs - actifs = PFService.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 - taux = ticker.fast_info.get('lastPrice') - PFService.update_actif_devise(request, 'USD', taux) - - for item in actifs: - if item.Allocation.type == 'ACTION': - symbole = item.Actifs.symbole - # lire le cours de l'action - ticker = yf.Ticker(symbole) - # ticker delisted ? - if symbole == 'SHLDQ': - cours = 0.1 - else: - cours = round(ticker.fast_info.get('lastPrice'), 3) - - valeur = round(cours * item.Actifs.parite * item.Actifs.nombre, 3) - plus_value = round(valeur - (item.Actifs.pru * item.Actifs.nombre),2) - pc_plusvalue = round(valeur * 100 / (item.Actifs.pru * item.Actifs.nombre) - 100, 3) - PFService.update_actif_valeur(request, symbole, cours, valeur, plus_value, pc_plusvalue) - # time.sleep(1) # attendre 2 secondes - - # update du portefeuille - today = datetime.datetime.now() - PFService.update_portefeuille(request, today) - # relire les actifs - actifs = PFService.get_actifs(request, '0') - request.session.flash('Le portefeuille est mis à jour avec succès.', 'success') - - total_valeur = 0 - total_pv = 0 - total_rdt = 0 - maj_pf_le = None - for item in actifs: - maj_pf_le = item.Actifs.modif_le - total_valeur += item.Actifs.valeur - total_pv += item.Actifs.plus_value - if total_valeur == 0: - total_pc_value = 0 - else: - total_pc_value = total_pv / total_valeur * 100 - total_rdt += item.Actifs.rendement - - # lire l'historique - histos = PFService.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", - 'url': url, - 'items': items, - '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, - 'maj_pf_le' : maj_pf_le, - 'swr_rate' : swr_rate, - 'swr_amount': float(total_valeur) * swr_rate / 100, - } - - -@view_config(route_name='histo_list', renderer='../templates/portfolio/histo_list.jinja2', permission='view') -def histo_list(request): - # lire l historique - items = PFService.get_histo(request, '-1') - - return { - 'page_title': 'Historique des parts', - 'items': items, - } - - -@view_config(route_name='allocation_edit', renderer='../templates/portfolio/allocation_edit.jinja2', permission='view') -def allocation_edit(request): - no_cat = request.matchdict['no_cat'] - url = request.route_url('allocation_edit', no_cat=no_cat) - - if no_cat == '0': - # create a new allocation - entry = Allocation() - form = AllocationForm(request.POST, entry) - page_title = "Nouvelle allocation" - - else: - # modify post - entry = PFService.get_allocation(request, no_cat) - if not entry: - request.session.flash(u"Allocation non trouvée : %s" % no_cat, 'warning') - return HTTPFound(location=request.route_url('portfolio')) - form = AllocationForm(request.POST, entry) - page_title = "Modifier Allocation : " + str(entry.no_cat) - - if 'form.submitted' in request.params : - if no_cat == '0': - form.populate_obj(entry) - entry.pc_atteint = 0 - entry.pc_ecart = 0 - entry.valeur = 0 - request.dbsession.add(entry) - return HTTPFound(location=request.route_url('portfolio')) - else: - del form.no_cat # SECURITY: prevent overwriting of primary key - form.populate_obj(entry) - - return HTTPFound(location=request.route_url('portfolio')) - - if 'form.deleted' in request.params: - PFService.delete_allocation(request, entry.no_cat) - request.session.flash("La fiche a été supprimée avec succès.", 'success') - return HTTPFound(location=request.route_url('portfolio')) - - return { - 'page_title': page_title, - 'url': url, - 'form': form, - 'item': entry, - } - - -@view_config(route_name='histo_edit', renderer='../templates/portfolio/histo_edit.jinja2', permission='view') -def histo_edit(request): - no_id = request.matchdict['no_id'] - url = request.route_url('histo_edit', no_id=no_id) - - if no_id == '0': - # create a new tag - entry = Histo() - entry.mvt_cash = 0 - entry.date = datetime.datetime.now() - form = HistoForm(request.POST, entry) - page_title = "Nouveau Histo" - - else: - # modify post - entry = PFService.get_histo(request, no_id) - if not entry: - request.session.flash(u"Histo non trouvé : %s" % no_id, 'warning') - return HTTPFound(location=request.route_url('histo_list')) - form = HistoForm(request.POST, entry) - page_title = "Modifier histo no " + str(entry.no_id) - - if 'form.submitted' in request.params and form.validate(): - form.populate_obj(entry) - - # lire le cours de l'indice de réfence : Carmignac Investissement A EUR Acc - ticker = yf.Ticker('0P00000FB2.F') - entry.cours_ref = round(ticker.fast_info.last_price, 3) - - # lire le dernier histo - last = PFService.get_last_histo(request) - - # lire les actifs et cumuler leurs valeurs - actifs = PFService.get_actifs(request, '0') - valeur_pf = 0 - for item in actifs: - valeur_pf += item.Actifs.valeur - - entry.valeur_pf = valeur_pf - # nlle valeur part = ancienne + nouvelle ratio - entry.nb_part = round(last.nb_part + (float(entry.mvt_cash) / (valeur_pf - float(entry.mvt_cash))/last.nb_part), 3) - entry.val_part = round(entry.valeur_pf / entry.nb_part, 3) - entry.val_part_ref = round(float(entry.cours_ref) * last.val_part_ref / last.cours_ref, 3) - - request.dbsession.add(entry) - - return HTTPFound(location=request.route_url('histo_list')) - - if 'form.deleted' in request.params: - PFService.delete_histo(request, entry.no_id) - request.session.flash("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, - 'form': form, - 'item': entry, - } - -@view_config(route_name='actif_edit', renderer='../templates/portfolio/actif_edit.jinja2', permission='view') -def actif_edit(request): - no_id = request.matchdict['no_id'] - url = request.route_url('actif_edit', no_id=no_id) - - # get the list of classes - classes = PFService.get_allocation_byType(request, 'ACTION') - - if no_id == '0': - # create a new allocation - entry = Actifs() - entry.pru = 0 - entry.cours = 0 - entry.pc_rdt = 0 - entry.ter = 0 - form = ActifForm(request.POST, entry) - form.classe.choices = [(row.classe, row.classe) for row in classes] - page_title = "Nouvel actif" - - else: - # modify post - entry = PFService.get_actifs(request, no_id) - if not entry: - request.session.flash(u"Actif non trouvé : %s" % no_id, 'warning') - return HTTPFound(location=request.route_url('portfolio')) - form = ActifForm(request.POST, entry) - form.classe.choices = [(row.classe, row.classe) for row in classes] - page_title = "Modifier Actif : " + entry.symbole - - if 'form.submitted' in request.params : - if no_id == '0': - form.populate_obj(entry) - # récupérer le cours du symbole de Yahoo finance - ticker = yf.Ticker(entry.symbole) - entry.cours = ticker.fast_info.get('lastPrice') - entry.devise = ticker.fast_info.get('currency') - # raccourcir le libelle - entry.pc_allocation = 1.0 - entry.valeur = round(float(entry.cours) * entry.parite * entry.nombre, 3) - entry.plus_value = round(entry.valeur - float(entry.pru * entry.nombre), 3) - entry.pc_plusvalue = round(entry.plus_value / entry.valeur * 100, 3) - entry.rendement = 0 # round(entry.valeur * float(entry.pc_rdt) / 100, 3) - request.dbsession.add(entry) - return HTTPFound(location=request.route_url('portfolio')) - else: - if entry.symbole != 'SHLDQ': - del form.no_id # SECURITY: prevent overwriting of primary key - form.populate_obj(entry) - # récupérer le cours du symbole de Yahoo finance - ticker = yf.Ticker(entry.symbole) - entry.cours = ticker.fast_info.get('lastPrice') - entry.devise = ticker.fast_info.get('currency') - # raccourcir le libelle - entry.valeur = round(float(entry.cours) * entry.parite * entry.nombre, 3) - entry.plus_value = round(entry.valeur - float(entry.pru * entry.nombre), 3) - entry.pc_plusvalue = round(entry.plus_value / entry.valeur * 100, 3) - entry.rendement = 0 # round(entry.valeur * float(entry.pc_rdt) / 100, 3) - - return HTTPFound(location=request.route_url('portfolio')) - - if 'form.deleted' in request.params: - PFService.delete_actif(request, entry.no_id) - request.session.flash("La fiche a été supprimée avec succès.", 'success') - return HTTPFound(location=request.route_url('portfolio')) - - return { - 'page_title': page_title, - 'url': url, - 'form': form, - 'item': entry, - } - -@view_config(route_name='actif2_edit', renderer='../templates/portfolio/actif2_edit.jinja2', permission='view') -def actif2_edit(request): - no_id = request.matchdict['no_id'] - url = request.route_url('actif2_edit', no_id=no_id) - - # get the list of classes - classes = PFService.get_allocation_byType(request, 'AUTRE') - - if no_id == '0': - # create a new allocation - entry = Actifs() - entry.pru = 0 - entry.cours = 0 - entry.pc_rdt = 0 - entry.ter = 0 - entry.devise = 'EUR' - form = Actif2Form(request.POST, entry) - form.classe.choices = [(row.classe, row.classe) for row in classes] - page_title = "Nouvel actif" - - else: - # modify post - entry = PFService.get_actifs(request, no_id) - if not entry: - request.session.flash(u"Actif non trouvé : %s" % no_id, 'warning') - return HTTPFound(location=request.route_url('portfolio')) - form = Actif2Form(request.POST, entry) - form.classe.choices = [(row.classe, row.classe) for row in classes] - page_title = "Modifier Actif : " + entry.symbole - - if 'form.submitted' in request.params : - if no_id == '0': - form.populate_obj(entry) - entry.nombre = 1000 - entry.devise = 'EUR' - entry.parite = 1.0 - entry.pc_allocation = 1.0 - entry.valeur = float(entry.cours) * entry.parite * entry.nombre; - entry.plus_value = entry.valeur - float(entry.pru * entry.nombre); - entry.pc_plusvalue = entry.plus_value / entry.valeur * 100; - entry.rendement = entry.valeur * float(entry.pc_rdt) / 100; - request.dbsession.add(entry) - return HTTPFound(location=request.route_url('portfolio')) - else: - del form.no_id # SECURITY: prevent overwriting of primary key - form.populate_obj(entry) - entry.valeur = float(entry.cours) * entry.parite * entry.nombre; - entry.plus_value = entry.valeur - float(entry.pru * entry.nombre); - entry.pc_plusvalue = entry.plus_value / entry.valeur * 100; - entry.rendement = entry.valeur * float(entry.pc_rdt) / 100; - - return HTTPFound(location=request.route_url('portfolio')) - - if 'form.deleted' in request.params: - PFService.delete_actif(request, entry.no_id) - request.session.flash("La fiche a été supprimée avec succès.", 'success') - return HTTPFound(location=request.route_url('portfolio')) - - return { - 'page_title': page_title, - 'url': url, - 'form': form, - 'item': entry, - }