Python Forum
How to change from printFacts ( ) to return a list & Loop over list when writing CSV
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to change from printFacts ( ) to return a list & Loop over list when writing CSV
#3
The code I posted is modified to extract, print and write to CSV additional data points that the orginal code did not cover (like for example: Entity Common Stock Shares Outstanding"). I have enclosed the original code below.

# Copyright 2014 Altova GmbH
# 
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# 
#	  http:
# 
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os, re, sys
from altova import xml, xsd, xbrl

sec_ns =  '/dei/'		# was: 'http:
fasb_ns = '/us-gaap/'	# was: 'http:

# We need to implement a simple locking class that allows us to avoid having 
# on_xbrl_valid called from multiple threads in RaptorXML at the same time.

if sys.platform == 'win32':
	import msvcrt

	# fcntl is not available under Windows, so we'll use a 
	# file locking function from the msvcrt library instead...

	class Lock:

		def __init__(self, filename):
			self.filename = filename
			# This will create it if it does not exist already
			self.handle = open(filename, 'w')

		# Bitwise OR fcntl.LOCK_NB if you need a non-blocking lock
		def acquire(self):
			msvcrt.locking(self.handle.fileno(), msvcrt.LK_LOCK, 1)

		def release(self):
			msvcrt.locking(self.handle.fileno(), msvcrt.LK_UNLCK, 1)

		def __del__(self):
			self.handle.close()

else:
	import fcntl

	# Under Linux and MacOS we can use the fcntl library to implement
	# the simple file locking mechanism...

	class Lock:

		def __init__(self, filename):
			self.filename = filename
			# This will create it if it does not exist already
			self.handle = open(filename, 'w')

		# Bitwise OR fcntl.LOCK_NB if you need a non-blocking lock
		def acquire(self):
			fcntl.flock(self.handle, fcntl.LOCK_EX)

		def release(self):
			fcntl.flock(self.handle, fcntl.LOCK_UN)

		def __del__(self):
			self.handle.close()

def camelToSpaces( label ):
	# Utility for pretty-printing the labels
	s1 = re.sub('(.)([A-Z][a-z]+)', r'\1 \2', label)
	return re.sub('([a-z0-9])([A-Z])', r'\1 \2', s1)

def factFinder( instance, namespace, label ):
	# Locate facts in the instance document by namespace and label, ignoring facts that have a context with a segment_element
	l = []
	for f in instance.items:
		if f.qname.namespace_name.find( namespace ) and f.qname.local_name == label:
			segment = None
			try:
				entElement = f.context.entity.element
				for childElement in entElement.children:
					if childElement.local_name=="segment":
						segment = childElement
			except:
				pass
			if segment==None:
				l.append( f )
	return l

def printFacts( facts, indent=1, targetDate=None ):
	# Find the fact for the relevant target date and print it
	factValue = 0
	for fact in facts:
		if targetDate==None or fact.context.period.instant == targetDate:
			if fact.concept.item_type==fact.concept.MONETARY_ITEM_TYPE:
				factValue = fact.effective_numeric_value
				print( indent * "\t", camelToSpaces( fact.qname.local_name ).ljust(100-indent*8), "$", '{0:>16,}'.format( factValue ) )
			else:
				factValue = fact.normalized_value
				print( indent * "\t", camelToSpaces( fact.qname.local_name ).ljust(100-indent*8), factValue )
	return factValue

def on_xbrl_valid( job, instance ):

	try:
		# a portable solution to get the tmp dir
		import tempfile
		tmp = tempfile.gettempdir()
		tmplk = os.path.join( tmp, "extract_ratios_lock.tmp" )
		lock = Lock(tmplk)
		lock.acquire()

		# Create output CSV file if it doesn't exist yet
		if not os.path.isfile( "ratios.csv" ):
			with open("ratios.csv", "a") as ratiofile:
				ratiofile.write( "DocumentType,EntityName,CIK,PeriodEndDate,CurrentRatio,QuickRatio,CashRatio\n" )
				ratiofile.close()

		# Extract some basic facts from the filing, such as the effective end-date for balance sheet etc.
		docEndDate = "2013-12-31"
		documentType = factFinder( instance, sec_ns, "DocumentType" )
		documentFiscalYearFocus = factFinder( instance, sec_ns, "DocumentFiscalYearFocus" )
		documentFiscalPeriodFocus = factFinder( instance, sec_ns, "DocumentFiscalPeriodFocus" )
		documentPeriodEndDate = factFinder( instance, sec_ns, "DocumentPeriodEndDate" )
		if len(documentPeriodEndDate) > 0:
			docEndDate = documentPeriodEndDate[0].normalized_value

		# Extract Filer Name and other key data
		entityRegistrantName = factFinder( instance, sec_ns, "EntityRegistrantName" )
		entityCentralIndexKey = factFinder( instance, sec_ns, "EntityCentralIndexKey" )
		entityCommonStockSharesOutstanding = factFinder( instance, sec_ns, "EntityCommonStockSharesOutstanding" )

		# Print information about filing and entity
		print( "Document and Entity Information:" )
		docType = printFacts( documentType )
		entityName = printFacts( entityRegistrantName )
		entityCIK = printFacts( entityCentralIndexKey )
		printFacts( documentPeriodEndDate )
		printFacts( documentFiscalPeriodFocus )
		printFacts( documentFiscalYearFocus )

		if docType=="10-K" or docType=="10-Q":
			# Now let's calculate some useful ratios from the balance sheet
			print( "Analytical Ratios:" )
			print( "\tBalance Sheet:" )

			# Current Ratio
			currentRatio = 0
			print( "\t\tCurrent Ratio = Current Assets / Current Liabilities:" )
			currentAssetsFacts = factFinder( instance, fasb_ns, "AssetsCurrent" )
			currentLiabilitiesFacts = factFinder( instance, fasb_ns, "LiabilitiesCurrent" )
			currentAssets = printFacts( currentAssetsFacts, 3, docEndDate )
			currentLiabilities = printFacts( currentLiabilitiesFacts, 3, docEndDate )
			if not currentLiabilities==0:
				currentRatio = currentAssets / currentLiabilities
			print( 3 * "\t", "Current Ratio = ".ljust(100-3*8), '{0:.2f}'.format( currentRatio ) )

			# Quick Ratio
			quickRatio = 0
			print( "\t\tQuick Ratio = ( Cash + Short-Term Marketable Securities + Accounts Receivable ) / Current Liabilities:" )
			cashFacts = factFinder( instance, fasb_ns, "Cash" )
			if len(cashFacts)==0:
				cashFacts = factFinder( instance, fasb_ns, "CashAndCashEquivalentsAtCarryingValue" )
			if len(cashFacts)==0:
				cashFacts = factFinder( instance, fasb_ns, "CashCashEquivalentsAndShortTermInvestments" )
			marketableSecuritiesFacts = factFinder( instance, fasb_ns, "MarketableSecuritiesCurrent" )
			if len(marketableSecuritiesFacts)==0:
				marketableSecuritiesFacts = factFinder( instance, fasb_ns, "AvailableForSaleSecuritiesCurrent" )
			if len(marketableSecuritiesFacts)==0:
				marketableSecuritiesFacts = factFinder( instance, fasb_ns, "ShortTermInvestments" )
			if len(marketableSecuritiesFacts)==0:
				marketableSecuritiesFacts = factFinder( instance, fasb_ns, "OtherShortTermInvestments" )
			accountsReceivableFacts = factFinder( instance, fasb_ns, "AccountsReceivableNetCurrent" )
			currentLiabilitiesFacts = factFinder( instance, fasb_ns, "LiabilitiesCurrent" )
			cash = printFacts( cashFacts, 3, docEndDate )
			marketableSecurities = printFacts( marketableSecuritiesFacts, 3, docEndDate )
			accountsReceivable = printFacts( accountsReceivableFacts, 3, docEndDate )
			currentLiabilities = printFacts( currentLiabilitiesFacts, 3, docEndDate )
			if not currentLiabilities==0:
				quickRatio = ( cash + marketableSecurities + accountsReceivable ) / currentLiabilities
			print( 3 * "\t", "Quick Ratio = ".ljust(100-3*8), '{0:.2f}'.format( quickRatio ) )

			# Cash Ratio
			cashRatio = 0
			print( "\t\tCash Ratio = ( Cash + Short-Term Marketable Securities ) / Current Liabilities:" )
			cash = printFacts( cashFacts, 3, docEndDate )
			marketableSecurities = printFacts( marketableSecuritiesFacts, 3, docEndDate )
			currentLiabilities = printFacts( currentLiabilitiesFacts, 3, docEndDate )
			if not currentLiabilities==0:
				cashRatio = ( cash + marketableSecurities ) / currentLiabilities
			print( 3 * "\t", "Cash Ratio = ".ljust(100-3*8), '{0:.2f}'.format( cashRatio ) )


			# Append ratios to a CSV file for further analysis
			with open("ratios.csv", "a") as ratiofile:
				ratiofile.write( docType + ',"' + entityName + '",' + entityCIK + "," + docEndDate + "," + '{0:.2f}'.format( currentRatio ) + "," + '{0:.2f}'.format( quickRatio ) + "," + '{0:.2f}'.format( cashRatio ) + "\n" )
				ratiofile.close()

	finally:
		lock.release()

Note, I should add that for the above security (Ford) there are two values for Entity Common Stock Shares Outstanding as one is for Common Stock and other is for Class B stock but as per SEC's website the XBRL for Ford's 10 Q shows the above values on two different lines but both have same name: EntityCommomStockSharesOutstanding

The modified code returns the values for both common stock and class B stock (both shown separately on my mac terminal screen under heading Entity Common Stock Shares Outstanding but the written CSV file only picks up one of the two values for Entity Common Stock Shares Oustanding
Reply


Messages In This Thread
RE: How to change from printFacts ( ) to return a list & Loop over list when writing CSV - by Ivan1 - Aug-27-2017, 12:18 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Help with writing monitored data to mysql upon change of one particular variable donottrackmymetadata 3 305 Apr-18-2024, 09:55 PM
Last Post: deanhystad
  How do I calculate a ratio from 2 numbers and return an equivalent list of about 1000 Pleiades 8 15,720 Jan-05-2024, 08:30 PM
Last Post: sgrey
  No matter what I do I get back "List indices must be integers or slices, not list" Radical 4 1,185 Sep-24-2023, 05:03 AM
Last Post: deanhystad
  Change font in a list or tuple apffal 4 2,700 Jun-16-2023, 02:55 AM
Last Post: schriftartenio
  Delete strings from a list to create a new only number list Dvdscot 8 1,555 May-01-2023, 09:06 PM
Last Post: deanhystad
  List all possibilities of a nested-list by flattened lists sparkt 1 926 Feb-23-2023, 02:21 PM
Last Post: sparkt
  Сheck if an element from a list is in another list that contains a namedtuple elnk 8 1,856 Oct-26-2022, 04:03 PM
Last Post: deanhystad
  convert this List Comprehensions to loop jacklee26 8 1,533 Oct-21-2022, 04:25 PM
Last Post: deanhystad
  How to change the datatype of list elements? mHosseinDS86 9 2,011 Aug-24-2022, 05:26 PM
Last Post: deanhystad
Question Keyword to build list from list of objects? pfdjhfuys 3 1,579 Aug-06-2022, 11:39 PM
Last Post: Pedroski55

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020