SW application scenarios: Company Accounts

An experiment in W3C spec overlap: using SVG, MathML, XML, RDF to represent company accounts in the Web.

by Dan Brickley (W3C/ILRT), April 2002

Introduction

Company Accounts provide an interesting Semantic Web application scenario, since there are a number of issues associated with representing accounting information in the Web that require the use of multiple W3C specifications.

Status: This is a work in progress. Some sample data (company report summaries, RDFS schema) is available, along with some exerimental RDF-Logic rules. The MathML and SVG ideas are all vapourware at this stage. Help welcomed!

We can use MathML to represent numeric information (for presentation and for content interchange), we can use XML Schemas and DTDs to represent document formats for interchange; or RDF Schemas and Web Ontologies to represent the structure and constraints associated with the information modelling that underpins such documents. SVG provides an excellent format, again written in XML, for the exchange of diagramatic representation (eg. charts, figures) derrived from copmany account information. RDF can be used to merge information about companies from multiple sources, and RDF rule and inference systems (perhaps combined with MathML) may be useful for capturing the basic formulae that underpin company accounts. The challenge is to combine all these relevant components into a useful, understandable and maintainable whole.

This experiment begins with some sample data from the Biz/ed Web site.

The idea is to make some data available (see reports.xml and original text format), and then show how MathML, RDF, SVG etc representations overlap. For now, all we have is the RDF version, and some text (and Perl) representations of how the different company report properties are related.

Next Steps

It would be good to...

N3/Cwm implementation

Thanks to Sean and Aaron from #rdfig irc chat)

A writeup of this work isn't integrated here yet, but some test queries, sample output etc are available nearby in the Web. The example query uses the CWM RDF-Logic system, and in particular its math(s) support, to represent relationships between the notion of 'fc:sr' and 'fc:spe' and 'fc:noe'.

(expanded explanation would go nicely here)

Sample Definitions

The following definitions are used by the Biz/ed online company report profiler. They express relationships amongst the various measures used in company accounts.

Definitions (prose)

Calculated values:

RNA: Return on Net Assests = Operating Profit/Net Assets
PM: Profit Margin = Operating Profit/Sales Revenue
AT: Asset Turnover = Sales/Net Assets
SPE: Sales per Employee = Sales/Number of Employees
OPPE: Operating Profit per Employee = Operating Profit/Number of Employees
NUKSR: Non UK Sales = Non UK Sales/Total Sales
CR: Current Ratio = Current Assets/Current Liabilites$Calc{'ATR'}="&ATR()"; #

ATR: ???= (Current Assets - Stocks) /Current Liabilities
DD: Debtor Days = Debtors/Sales/365
SD: Stock Days = Stocks/Cost of Sales/365
G: Gearing = Long term Liabilities/Shareholders Funds
IC: Interest Cover = Operating Profit / Interest
DC: Dividend Cover = Profit Attributable / Dividends Paid
CA: Current Assets 

SOURCE: Company Name
YEAR: Year of report

Schema (draft)

The following is a draft (see rdf version) of a schema that captures the basic properties. TODO: check to see this is complete and consistent with the test data we have.

Properties and their labels

ca: Current Assets - Total 
cas: Current Assets - Stocks 
cad: Current Assets - Debtors 
cac: Current Assets - Cash etc. 
cl: Current Liabilities 
nwc: Net Working Capital 
ltl: Long Term Liabilities 
na: Net Assets 
sf: Shareholder's Funds 
eps: Earnings Per Share 
dps: Dividends Per Share 
rna: Return on Net Assets 
pm: Profit Margin 
at: Asset Turnover 
spe: Sales Per Employee 
oppe: Operating Profit per Employee 
nuksr: Non UK Sales percent 
cr: Current Ratio 
atr: Acid Test Ratio 
dd: Debtor Days 
sd: Stock Days 
g: Gearing 
ic: Interest Cover 
dc: Dividend Cover 

RDF/XML version

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#ltl" 
  rdfs:label="ltl" rdfs:comment="Long Term Liabilities"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#na" 
  rdfs:label="na" rdfs:comment="Net Assets"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#nuksr" 
  rdfs:label="nuksr" rdfs:comment="Non UK Sales percent"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#nwc" 
  rdfs:label="nwc" rdfs:comment="Net Working Capital"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#atr" 
  rdfs:label="atr" rdfs:comment="Acid Test Ratio"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#cas" 
  rdfs:label="cas" rdfs:comment="Current Assets - Stocks"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#spe" 
  rdfs:label="spe" rdfs:comment="Sales Per Employee"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#dps" 
  rdfs:label="dps" rdfs:comment="Dividends Per Share"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#g" 
  rdfs:label="g" rdfs:comment="Gearing"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#eps" 
  rdfs:label="eps" rdfs:comment="Earnings Per Share"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#ca" 
  rdfs:label="ca" rdfs:comment="Current Assets - Total"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#sd" 
  rdfs:label="sd" rdfs:comment="Stock Days"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#dc" 
  rdfs:label="dc" rdfs:comment="Dividend Cover"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#dd" 
  rdfs:label="dd" rdfs:comment="Debtor Days"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#sf" 
  rdfs:label="sf" rdfs:comment="Shareholder's Funds"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#pm" 
  rdfs:label="pm" rdfs:comment="Profit Margin"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#cac" 
  rdfs:label="cac" rdfs:comment="Current Assets - Cash etc."/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#cl" 
  rdfs:label="cl" rdfs:comment="Current Liabilities"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#cad" 
  rdfs:label="cad" rdfs:comment="Current Assets - Debtors"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#ic" 
  rdfs:label="ic" rdfs:comment="Interest Cover"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#at" 
  rdfs:label="at" rdfs:comment="Asset Turnover"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#rna" 
  rdfs:label="rna" rdfs:comment="Return on Net Assets"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#cr" 
  rdfs:label="cr" rdfs:comment="Current Ratio"/>

<rdf:Property rdf:about="http://xmlns.com/foaf/corp#oppe" 
  rdfs:label="oppe" rdfs:comment="Operating Profit per Employee"/>

Yet More Info...

The following extracted from the Perl code and the headings from the data file.

SOURCE: Company Name
YEAR: Year of report
CAS:
CAD
CAC
CL
NWC
LTL
NA
SF
SR
COS
OP
INT
PAT
DP
RP
NE
NUKS
SFO
RNA
PM
AT
SPE
OPPE
NUKST
SPSF
CR
ATR
DD
SD
G
IC
EPS
DPS
DC

As Perl5 functions

sub RNA
{             
    return("RNA") if($inHeader);
    return("*") if ($elements[$Index{'NA'}]==0); # NULL trap
    return(sprintf("%.2f",$elements[$Index{'OPOA'}]/$elements[$Index{'NA'}]*100));
}

sub PM
{ 
    return("PM") if($inHeader);
    return("*") if ($elements[$Index{'SR'}]==0); # NULL trap
    return(sprintf("%.2f",$elements[$Index{'OPOA'}]/$elements[$Index{'SR'}]*100));
}

sub AT
{ 
    return("AT") if($inHeader);
    return("*") if ($elements[$Index{'NA'}]==0); # NULL trap
    return(sprintf("%.2f",$elements[$Index{'SR'}]/$elements[$Index{'NA'}]));
}

sub SPE
{ 
    return("SPE") if($inHeader);
    return("*") if ($elements[$Index{'NOE'}]==0); # NULL trap
    return(sprintf("%.2f",$elements[$Index{'SR'}]/$elements[$Index{'NOE'}]*1000000));
}

sub OPPE
{ 
    return("OPPE") if($inHeader);
    return("*") if ($elements[$Index{'NOE'}]==0); # NULL trap
    return(sprintf("%.2f",$elements[$Index{'OPOA'}]/$elements[$Index{'NOE'}]*1000000));
}

sub NUKSR
{ 
    return("NUKSR") if($inHeader);
    return("*") if ($elements[$Index{'SR'}]==0); # NULL trap
    return(sprintf("%.2f",$elements[$Index{'NUKSV'}]/$elements[$Index{'SR'}]*100));
}

sub CR
{ 
    return("CR") if($inHeader);
    return("*") if ($elements[$Index{'CL'}]==0); # NULL trap
    return(sprintf("%.2f",&CA()/$elements[$Index{'CL'}]));
}

sub ATR
{ 
    return("ATR") if($inHeader);
    return("*") if ($elements[$Index{'SR'}]==0); # NULL trap
    return(sprintf("%.2f",($elements[$Index{'CAD'}]+$elements[$Index{'CAC'}])/$elements[$Index{'CL'}]));
}

sub CA
{ 
    return("CA") if($inHeader);
    return(sprintf("%.2f",$elements[$Index{'CAS'}]+$elements[$Index{'CAD'}]+$elements[$Index{'CAC'}]));
}

sub DD 
{
    return("DD") if($inHeader);
    return("*") if ($elements[$Index{'SR'}]==0); # NULL trap
    return(sprintf("%.2f",($elements[$Index{'CAD'}]*100000/$elements[$Index{'SR'}])/365));
}

sub SD 
{
    return("SD") if($inHeader);
    return("*") if ($elements[$Index{'SR'}]==0); # NULL trap
    return(sprintf("%.2f",($elements[$Index{'CAS'}]*100000/$elements[$Index{'COS'}])/365));
}

sub G
{
    return("G") if ($inHeader);
    return("*") if ($elements[$Index{'SF'}]==0); # NULL trap
    return(sprintf("%.2f",$elements[$Index{'LTL'}]/$elements[$Index{'SF'}]*100));
}


sub IC
{
    return("IC") if ($inHeader);
    return("*") if ($elements[$Index{'I'}]==0); # NULL trap
    return(sprintf("%.2f",$elements[$Index{'OPOA'}]/$elements[$Index{'I'}]));
}

sub DC
{
    return("DC") if ($inHeader);
    return("*") if ($elements[$Index{'DP'}]==0); # NULL trap
    return(sprintf("%.2f",$elements[$Index{'PATC'}]/$elements[$Index{'DP'}]));
    
}