def iter_investment(self): not_rounded_valuations = self.get_not_rounded_valuations() doc = self.browser.open('/brs/fisc/fisca10a.html').page.doc num_page = None try: num_page = int(CleanText('.')(doc.xpath(u'.//tr[contains(td[1], "Relevé des plus ou moins values latentes")]/td[2]')[0]).split('/')[1]) except IndexError: pass docs = [doc] if num_page: for n in range(2, num_page + 1): docs.append(self.browser.open('%s%s' % ('/brs/fisc/fisca10a.html?action=12&numPage=', str(n))).page.doc) for doc in docs: # There are two different tables possible depending on the market account type. is_detailed = bool(doc.xpath(u'//span[contains(text(), "Années d\'acquisition")]')) tr_xpath = '//tr[@height and td[@colspan="6"]]' if is_detailed else '//tr[count(td)>5]' for tr in doc.xpath(tr_xpath): cells = tr.findall('td') inv = Investment() title_split = cells[self.COL_LABEL].xpath('.//span')[0].attrib['title'].split(' - ') inv.label = unicode(title_split[0]) for code in title_split[1:]: if is_isin_valid(code): inv.code = unicode(code) inv.code_type = Investment.CODE_TYPE_ISIN break else: inv.code = NotAvailable inv.code_type = NotAvailable if is_detailed: inv.quantity = MyDecimal('.')(tr.xpath('./following-sibling::tr/td[2]')[0]) inv.unitprice = MyDecimal('.', replace_dots=True)(tr.xpath('./following-sibling::tr/td[3]')[1]) inv.unitvalue = MyDecimal('.', replace_dots=True)(tr.xpath('./following-sibling::tr/td[3]')[0]) try: # try to get not rounded value inv.valuation = not_rounded_valuations[inv.label] except KeyError: # ok.. take it from the page inv.valuation = MyDecimal('.')(tr.xpath('./following-sibling::tr/td[4]')[0]) inv.diff = MyDecimal('.')(tr.xpath('./following-sibling::tr/td[5]')[0]) or \ MyDecimal('.')(tr.xpath('./following-sibling::tr/td[6]')[0]) else: inv.quantity = MyDecimal('.')(cells[self.COL_QUANTITY]) inv.diff = MyDecimal('.')(cells[self.COL_DIFF]) inv.unitprice = MyDecimal('.')(cells[self.COL_UNITPRICE].xpath('.//tr[1]/td[2]')[0]) inv.unitvalue = MyDecimal('.')(cells[self.COL_VALUATION].xpath('.//tr[1]/td[2]')[0]) inv.valuation = MyDecimal('.')(cells[self.COL_VALUATION].xpath('.//tr[2]/td[2]')[0]) yield inv
def get_investments(self, account): if account is not None: # the balance is highly dynamic, fetch it along with the investments to grab a snapshot account.balance = CleanDecimal(None, replace_dots=True).filter(self.get_balance(account.type)) for line in self.doc.xpath('//table[@id="t_intraday"]/tbody/tr'): if line.find_class('categorie') or line.find_class('detail') or line.find_class('detail02'): continue cols = line.findall('td') inv = Investment() inv.label = CleanText(None).filter(cols[self.COL_LABEL]) link = cols[self.COL_LABEL].xpath('./a[contains(@href, "cdReferentiel")]')[0] inv.id = re.search('cdReferentiel=(.*)', link.attrib['href']).group(1) inv.code = re.match('^[A-Z]+[0-9]+(.*)$', inv.id).group(1) inv.quantity = self.parse_decimal(cols[self.COL_QUANTITY], True) inv.unitprice = self.parse_decimal(cols[self.COL_UNITPRICE], True) inv.unitvalue = self.parse_decimal(cols[self.COL_UNITVALUE], False) inv.valuation = self.parse_decimal(cols[self.COL_VALUATION], True) diff = cols[self.COL_PERF].text.strip() if diff == "-": inv.diff = NotAvailable else: inv.diff = CleanDecimal(None, replace_dots=True).filter(diff) if is_isin_valid(inv.code): inv.code_type = Investment.CODE_TYPE_ISIN yield inv if account.type != account.TYPE_MARKET: valuation = CleanDecimal(None, True).filter(self.doc.xpath('//*[@id="valorisation_compte"]/table/tr[3]/td[2]')) yield create_french_liquidity(valuation)
def get_investments(self, account): for line in self.doc.xpath('//table[@id="tableau_support"]/tbody/tr'): cols = line.findall('td') inv = Investment() inv.id = re.search( 'cdReferentiel=(.*)', cols[self.COL_LABEL].find('a').attrib['href']).group(1) inv.code = re.match('^[A-Z]+[0-9]+(.*)$', inv.id).group(1) inv.label = CleanText(None).filter(cols[self.COL_LABEL]) inv.quantity = self.parse_decimal(cols[self.COL_QUANTITY]) inv.unitprice = self.parse_decimal(cols[self.COL_UNITPRICE]) inv.unitvalue = self.parse_decimal(cols[self.COL_UNITVALUE]) inv.vdate = Date(CleanText(cols[self.COL_DATE], default=NotAvailable), dayfirst=True, default=NotAvailable)(self.doc) inv.valuation = self.parse_decimal(cols[self.COL_VALUATION]) inv.diff = self.parse_decimal(cols[self.COL_PERF]) diff_percent = self.parse_decimal(cols[self.COL_PERF_PERCENT]) inv.diff_percent = diff_percent / 100 if diff_percent else NotAvailable if is_isin_valid(inv.code): inv.code_type = Investment.CODE_TYPE_ISIN yield inv
def create_french_liquidity(valuation): """ Automatically fills a liquidity investment with label, code and code_type. """ liquidity = Investment() liquidity.label = "Liquidités" liquidity.code = "XX-liquidity" liquidity.code_type = NotAvailable liquidity.valuation = valuation return liquidity
def iter_investment(self): valuation = MyDecimal('//td[@class="donneeNumerique borderbottom "]/text()')(self.doc) if valuation is not None: inv = Investment() inv.code = 'XX-liquidity' inv.code_type = NotAvailable inv.label = 'Liquidités' inv.valuation = valuation yield inv for inv in self.get_investment(): yield inv
def iter_investment(self, account, invs=None): if account.id not in self.investments and invs is not None: self.investments[account.id] = [] for inv in invs: i = Investment() # If nothing is given to make the label, we use the ISIN instead # We let it crash if the ISIN is not available either. if all([inv['classification'], inv['description']]): i.label = "%s - %s" % (inv['classification'], inv['description']) else: i.label = Coalesce().filter(( inv['classification'], inv['description'], inv['isin'], )) i.code = inv['isin'] if not is_isin_valid(i.code): i.code = NotAvailable i.code_type = NotAvailable if u'Solde Espèces' in i.label: i.code = 'XX-liquidity' else: i.code_type = Investment.CODE_TYPE_ISIN i.quantity = CleanDecimal(default=NotAvailable).filter( inv['nombreParts']) i.unitprice = CleanDecimal(default=NotAvailable).filter( inv['prixMoyenAchat']) i.unitvalue = CleanDecimal(default=NotAvailable).filter( inv['valeurCotation']) i.valuation = CleanDecimal().filter(inv['montantEuro']) # For some invests the vdate returned is None # Consequently we set the default value at NotAvailable i.vdate = Date(default=NotAvailable).filter( inv['datePosition']) i.diff = CleanDecimal(default=NotAvailable).filter( inv['performanceEuro']) self.investments[account.id].append(i) return self.investments[account.id]
def obj_investments(self): inv = Investment() inv.quantity = CleanDecimal(TableCell('quantity'), replace_dots=True)(self) inv.code_type = Investment.CODE_TYPE_ISIN txt = CleanText(TableCell('name'))(self) match = re.match('(?:(.*) )?- ([^-]+)$', txt) inv.label = match.group(1) or NotAvailable inv.code = match.group(1) return [inv]
def iter_investment(self, account, invs=None): if account.id not in self.investments and invs is not None: self.investments[account.id] = [] for inv in invs: i = Investment() i.label = "%s - %s" % (inv['classification'], inv['description']) i.code = inv['isin'] i.code_type = Investment.CODE_TYPE_ISIN i.quantity = CleanDecimal().filter(inv['nombreParts']) i.unitprice = CleanDecimal().filter(inv['prixMoyenAchat']) i.unitvalue = CleanDecimal().filter(inv['valeurCotation']) i.valuation = CleanDecimal().filter(inv['montantEuro']) i.vdate = Date().filter(inv['datePosition']) i.diff = CleanDecimal().filter(inv['performanceEuro']) self.investments[account.id].append(i) return self.investments[account.id]
def obj_investments(self): inv = Investment() inv.quantity = CleanDecimal(TableCell('quantity'), replace_dots=True)(self) inv.code_type = Investment.CODE_TYPE_ISIN txt = CleanText(TableCell('name'))(self) match = re.match('(?:(.*) )?- ([^-]+)$', txt) inv.label = match.group(1) or NotAvailable inv.code = match.group(2) if inv.code in self.parent.labels: inv.label = inv.label or self.parent.labels[inv.code] elif inv.label: self.parent.labels[inv.code] = inv.label else: inv.label = inv.code return [inv]
def get_investments(self, account): for line in self.doc.xpath('//table[@id="tableau_support"]/tbody/tr'): cols = line.findall('td') inv = Investment() inv.id = re.search('cdReferentiel=(.*)', cols[self.COL_LABEL].find('a').attrib['href']).group(1) inv.code = re.match('^[A-Z]+[0-9]+(.*)$', inv.id).group(1) inv.label = CleanText(None).filter(cols[self.COL_LABEL]) inv.quantity = self.parse_decimal(cols[self.COL_QUANTITY]) inv.unitprice = self.parse_decimal(cols[self.COL_UNITPRICE]) inv.unitvalue = self.parse_decimal(cols[self.COL_UNITVALUE]) inv.vdate = Date(CleanText(cols[self.COL_DATE], default=NotAvailable), default=NotAvailable)(self.doc) inv.valuation = self.parse_decimal(cols[self.COL_VALUATION]) inv.diff = self.parse_decimal(cols[self.COL_PERF]) diff_percent = self.parse_decimal(cols[self.COL_PERF_PERCENT]) inv.diff_percent = diff_percent / 100 if diff_percent else NotAvailable if is_isin_valid(inv.code): inv.code_type = Investment.CODE_TYPE_ISIN yield inv