Example #1
0
	def borrowing_capacity(self,as_of_date=None):
		'''
		Reflects borrowing capacity for the month-end `as_of_date`. 
		History is available going back back 12 months.

		Loan collateral reflects intraday processing of Mortgage Collateral Updates.
		Market value and all other data is as of prior business day close.

		:returns: TBD
		:rtype: dict of nested dicts
		'''
		today = datetime.now().strftime('%Y-%m-%d')
		if as_of_date is None:
			as_of_date = today
		else:
			self._validate_date(as_of_date)
			if as_of_date != today:
				self.is_monthend(as_of_date)

		borrowing_capacity_endpoint = 'borrowing-capacity'
		params = urlencode({'as_of_date':as_of_date})

		borrowing_capacity_url = urljoin(
			self.reports_url,
			borrowing_capacity_endpoint
		)
		
		self.driver.get(borrowing_capacity_url + '?' + params)
		
		tables = WebDriverWait(self.driver, 15).until(
			EC.presence_of_all_elements_located(
				(By.XPATH,"//table[contains(@class,'report-table report-sub-table')" 
				 + " or contains(@class,'report-table report-parent-table')]")
			)
		)
		
		tree = lambda: defaultdict(tree)
		res  = tree()
		
		for i,table in enumerate(tables):
			doc = html.fromstring(table.get_attribute('innerHTML'))
			headers = doc.xpath('.//th//text()')
			data   = doc.xpath('.//td//text()')
			if i == 0: # hack - first table missing 2nd to last value in footer
				data = data[:-1] + [None] + data[-1:]
			record_size = len(headers) or 2
			recs = partition(record_size,mapt(self.format_text,data))
			section = 'capacity' if i in [1,2,3,5] else 'collateral'
			credit_program = 'standard' if i in range(4) else 'securities_backed'
			for rec in recs:
				collateral_type, *info = rec
				if headers:
					entry = dict(zip(headers[1:],info))
				else:
					entry = info[0]
				res[credit_program][section][collateral_type] = entry
		return res
Example #2
0
	def sta_account(self,start_date,end_date):
		'''
		Shows the Settlement/Transaction Account for a range of dates, with
		history going back 6 months.

		:param  start_date: starting date of the report in "YYYY-mm-dd" format
		:param  end_date: ending date of the report in "YYYY-mm-dd" format
		
		:type  as_of_date: str
		:type  end_date: str

		:returns: {'date1':[{'Reference Number':ref#, 'Description':desc...}
		                    {'Reference Number':ref#, 'Description':desc...}]
				   'date2':[...]}
		:rtype: defaultdict
		'''
	
		sta_endpoint = 'settlement-transaction-account'
		
		bdate = self._validate_date(start_date)
		edate = self._validate_date(end_date)

		sta_url = urljoin(self.reports_url,sta_endpoint)
		
		self.driver.get(urljoin(
			sta_url,
			'?start_date={}&end_date={}'.format(bdate,edate)))
		
		table = self._webdriver_get_xpath(15,"//table[@class='report-table']")
		
		doc = html.fromstring(table.get_attribute('innerHTML'))
		td = doc.xpath('//tr//td')
		headers  = doc.xpath('//th//text()')
		headers  = [x.strip() for x in headers]
		sta_data = [x.getchildren()[0].text if x.getchildren() else x.text for x in td]
		sta_data = mapt(Client.format_text,sta_data)
		sta_data = itertools.groupby(
			partition(7,sta_data),
			lambda record: record[0]
		)

		res = defaultdict(list)
		for date, records_per_date in sta_data:
			for record in records_per_date:
				res[date].append(dict(zip(headers[1:],record[1:])))
		return res
Example #3
0
	def letters_of_credit(self):
		'''
		Reflects current status of letters of credit.

		:returns: [{'LC Number':2081-10, 'Beneficiary': 'inst name', ...}
				   {'LC Number':2081-10, 'Beneficiary': 'inst name', ...}...]
		:rtype: list of dicts
		'''
		
		loc_url = urljoin(self.base_url,'letters-of-credit/manage')
		self.driver.get(loc_url)
		table = self._webdriver_get_xpath(15,'//table')
		doc = html.fromstring(table.get_attribute('innerHTML'))
		data =  [self.format_text(d.strip()) 
				 for d in doc.xpath('//td//text()') if d != '\n']
		headers = doc.xpath('//th//text()')
		return [dict(zip(headers,rec)) for rec in partition(len(headers),data)]
Example #4
0
	def historical_rates(self,
						 start_date,
						 end_date,
						 collateral_type=None,
						 credit_type=None):
		'''
		Historical price indications as of 6:00 am PST on the date(s) referenced

		:param  start_date: starting date of the report in "YYYY-mm-dd" format
		:param  end_date: ending date of the report in "YYYY-mm-dd" format
		:param  collateral_type: one of: Standard Credit Program, 
			Securities-Backed Credit Program, or Settlemant/Transaction Acct. Rate
		:param  credit_type: one of: Fixed Rate Credit, Variable Rate Credit, or
			Adjustable Rate Credit, where Adjustable Rate Credit may be either
			1 Month Libor, 3 Month LIBOR, 6 Month LIBOR, or Daily Prime.  Note
			that Daily Prime is only applicable for the Standard Credit Program
			collateral_type.
		
		:type  as_of_date: str
		:type  end_date: str
		:type  collateral_type: str
		:type  credit_type: str

		:returns: {'date1': {'maturity1':rate1,'maturity2':rate2}
		           'date2': {...}
				  }
		:rtype: dict
		'''
		self._validate_date(start_date)
		self._validate_date(end_date)

		collateral_type = collateral_type.lower() if collateral_type else None
		credit_type     = credit_type.lower() if credit_type else None
		
		credit_types = ['frc','vrc','1m_libor','3m_libor',
						'6m_libor','daily_prime']
		
		valid_pairings = set(itertools.chain(
				itertools.product(['standard'],credit_types),
				itertools.product(['sbc'],credit_types[0:-1]),
				[('sta',None)]
			))

		if (collateral_type,credit_type) not in valid_pairings:
				raise AttributeError(
					"No matching entry for combination credit_type: {}".format(
						credit_type) + 
					" and collateral_type: {}".format(collateral_type)
				)

		historical_rates_endpoint = 'historical-price-indications'
		historical_rates_url      = urljoin(
			self.reports_url,
			historical_rates_endpoint
		)
		params = {
			'start_date'                       :start_date,
			'end_date'       				   :end_date,
			'historical_price_collateral_type' :collateral_type,
			'historical_price_credit_type'     :credit_type
		}
		params = urlencode(params)
		request_url = historical_rates_url + '?' + params
		self.driver.get(request_url)
		 # wait for data to load - sloppy but couldn't find a common xpath
		 # that all sub url's share.  Maybe try to find one again later
		 # but moving on for now
		time.sleep(10)
		# hopefully after 10 seconds the table referenced by the xpath 
		# below is populated
		table = self._webdriver_get_xpath(0,"//table[contains(@class,'report-table')]")
		table_html = html.fromstring(table.get_attribute('innerHTML'))
		data = table_html[0].xpath('//td//text()')
		headers = table_html[0].xpath('//th//text()')
		headers = [x.strip() for x in headers]
		records = [x.strip() for x in data if x.strip()]
		record_count = len(headers)
	
		if credit_type in ['frc','vrc'] or collateral_type == 'sta':
			return {p[0]:dict(zip(headers[1:],p[1:]))
				    for p in partition(record_count,
									   mapt(self.format_text,records))}
		elif 'libor' in credit_type:
			return {p[0]:dict(zip(headers[2:],p[1:]))
				    for p in partition(record_count-1,
							 	       mapt(self.format_text,records))}
		elif credit_type == 'daily_prime':
			mats, headers = headers[0:4], headers[4:]
			data = [mapt(self.format_text,p) for p in partition(9,records)]
			
			res = {}
			for d in data:
				date, *others = d
				bench_and_spread = partition(2,others)
				per_maturity = zip(mats,bench_and_spread)
				
				daily_obs = {}
				for mat,bns in per_maturity:
					daily_obs[mat] = {'benchmark':bns[0],'spread':bns[1]}
				res[date] = daily_obs
			return res
Example #5
0
	def current_rates(self):
		'''
		Reflects price indications as of 6:00 am PT on the current business day and STA
		rate as of the end of the prior business day.

		:returns: {'standard credit vrc':[{'Advance Maturity':'Overnight/Open',
		                                  {'Advance Rate (%)':2.57}}]
				   'standard credit frc': [{...}]}
		:rtype: dict
		'''
		
		current_rates_endpoint = 'current-price-indications'
		# dependent on table order in the website - if that changes, so should this
		tables = ['standard credit vrc',
				  'standard credit frc',
				  'standard adjustable rate credit',
				  'securities-backed credit vrc',
				  'securities-backed credit frc',
				  'securities-backed adjustable rate credit']
		
		self.driver.get(urljoin(self.reports_url,current_rates_endpoint))
		# wait for one of the tables to populate (they all do at the same time)
		self._webdriver_get_xpath(15,"//table[@id='DataTables_Table_1']/tbody")
		# then get outer div that wraps them (prior to waiting, all are empty)
		main_div = self._webdriver_get_xpath(15,
			"//div[@class='report report-price-indications " +
			"report-current-price-indications row']")
		
		div_html = html.fromstring(main_div.get_attribute('innerHTML'))
		
		rate_tables = {}
		for i, credit_type in enumerate(tables):
			table = div_html.xpath("//table[@id='DataTables_Table_{}']/tbody".format(i))
			text = table[0].xpath('.//td//text()') 
			records = [x.strip() for x in text if x.strip()]
			# dependent on table order in the website - if that changes, so should this
			if i in [0,1,3,4]:
				headers = ['Advance Maturity','Advance Rate (%)']
			elif i == 2:
				headers = [
					'Advance Maturity',
					'1 Month LIBOR',
					'3 Month LIBOR',
					'6 Month LIBOR',
					'Daily Prime'
				]
			else:
				headers = [
					'Advance Maturity',
					'1 Month LIBOR',
					'3 Month LIBOR',
					'6 Month LIBOR'
				]
			
			records = [dict(zip(headers,p)) 
				for p in partition(len(headers),mapt(self.format_text,records))]
			
			rate_tables[credit_type] = records
		
		sta_rates = div_html.xpath(".//table[@class='report-table sta-rate-table " +
			"report-table-vertical-headers']//td//text()")
		
		rate_tables['Settlement/Transaction Account (STA)'] = {sta_rates[0]:sta_rates[1]}
		
		return rate_tables