- The interpretation presented below is a work in progress.
- It is presented solely as an exploration of automated rights management and is intended to provoke debate.
Code
uses the turtle syntax defined here: https://www.w3.org/TR/turtle/. Hopefully though you can usefully read the document without reading the code.
The semantics of the ODRL terms are defined here: https://www.w3.org/TR/odrl-model/ and here: https://www.w3.org/TR/odrl-vocab/
The CME Category A License: Automated Trading Usage Category.
We need five documents from the CME to understand this license:
The key actions the consumer can take are specified in Schedule 4. We’re after Category A: Automated Trading Usage.
Three usage rights are defined: trading as a principle on a CME Group exchange; trading for clients on a CME Group exchange; or doing either of these on another exchange. If we were being literal, we would define four actions here:
But we can then model these as just two actions: trading as a principle and trading for a client which we could then constrain by venue: on or off a CME Group exchange.
But the venue doesn’t actually seem to matter; we’re allowed to trade anywhere. So, we can drop the constraint.
Equally we could roll up (aka superclass) trading as a principle and trading for a client under the umbrella term of automated trading. (We can also imagine automated trading rolling up to the broader term non-display use, which in turn rolls up to use)
So let’s create a permission with the identifier :P1 that allows this:
:P1 rdf:type odrl:Permission . :P1 odrl:action md:AutomatedTrading .
What does this mean? Just that :P1 is a permission that allows actions that are of the type automated trading.
The base license (aka the Information License Agreement) allows an additional usage right: to create limited derivative works solely for internal business purposes. This is clearly a derive action where the use of the output of the derivation is contrained to recipients who are internal to the licencee .
Let’s create another permission that allows us to make derivations
:P2 rdf:type odrl:Permission . :P2 odrl:action odrl:Derive .
But what can we do with the output of the derivation? We can use it, but only if the recipient of the output is internal to the licencee. So let’s create another permission that expresses this:
:P3 rdf:type odrl:Permission . :P3 odrl:action [ rdf:type odrl:Use ; odrl:recipient md:Internal ] .
What does this mean? It’s a permission to use the output of the derivation so long as the recipient of the data is internal.
The Information License Agreement is clear that the licensee cannot distribute or grant use of CME’s data. In addition, Schedule 4 makes it clear that this license offers only non-display use, which precludes displaying the data.
We can model this with a prohibition. Let’s give it the identifier :PR1.
:PR1 rdf:type odrl:Prohibition . :PR1 odrl:action odrl:Display , odrl:Distribute , odrl:GrantUse .
So actions of type display, distribute, or grant use are prohibited.
The burden of prohibitions on the derived data are a little lighter. You can’t distribute it. So let’s create a new prohibition :PR2
:PR2 rdf:type odrl:Prohibition . :PR2 odrl:action odrl:Distribute .
So far we haven’t explicity specified the data that these permissions and prohibitions control. Let’s do it now. For this example, I’m going to chose one of CME’s products: the Eurodollar Futures Contract.
The Eurodollar Futures Contract is our underlying resource. There are a few things we can say about it. It has a provider - the CME. I’m also going to say it’s a service, which has a code and a trading venue (I may be using the wrong terms here). There’s also something we can say about its nature: it’s dynamic, endlessly changing.
Let’s call the resource :R1
:R1 rdf:type md:Resource . :R1 rdfs:label "Eurodollar Futures Contract" . :R1 md:provider <https://permid.org/1-4295899615> . # Identifier for CME :R1 md:service [ rdf:type md:Service ; md:venue [ rdf:type md:Venue ; rdfs:label "Globex" ; md:operatingMic "XCME" ; md:mic "GLBX" ] ; md:code "GE" ] . :R1 md:contentNature md:Dynamic .
NOTE: this would look a lot nicer, and be a lot safer, if we had globally unique identifiers for services and venues like we do for providers. To support interoperability, we can also say that this resource is a dcat:DataSet and a prov:Collection so:
:R1 rdf:type dcat:DataSet , prov:Collection .
There’s another version of this resource that differs in its content nature (and, potentially, on pricing). It’s the end-of-day summary, so it’s static. It doesn’t change.
Let’s call the resource :R2
:R2 rdf:type md:Resource , dcat:DataSet , prov:Collection . :R2 rdfs:label "Eurodollar Futures Contract" . :R2 md:provider <https://permid.org/1-4295899615> . # Identifier for CME :R2 md:service [ rdf:type md:Service . md:venue [ rdf:type md:Venue ; rdfs:label "Globex" ; md:operatingMic "XCME" ; md:mic "GLBX" ] ; md:code "GE" ] . :R2 md:contentNature md:StaticEOD .
It’s a little difficult to identify the output of the derivation. It doesn’t exist yet! So I’m going to see if I can get by without explicitly naming or describing it.
The permissions that control the use of market data are highly sensitive to the speed at which that data is delivered. Data delivered in milliseconds is far more valueable than data delivered in minutes, hours, or months.
In the language of ODRL, the assets that our permissions control are refinements of the underlying resource. For maket data, that will usually include specifying the timeliness of delivery.
The Information License Agreement enumerates how the CME sees it. Realtime data is data recieved within ten minutes of time of issue (by the market). Delayed data is recieved between ten minutes and eight hours of time of issue. End-of-day data is embargoed, and make available at market close.
So we have three assets here:
Unfortunately, it’s surprising difficult to get computers to handle time and time periods. Anyone remember the millenium bug? So bear with me on this one.
Let’s call our three assets :A1, :A2, and :A3. First, realtime:
:A1 rdf:type odrl:Asset . :A1 md:resource :R1 . :AI md:timelinessOfDelivery [ rdf:type time:ProperInterval , md:Realtime ; time:intervalEquals [ rdf:type time:ProperInterval ; md:timeReference time:Instant , md:TimeOfIssue ; time:hasXSDDuration "PT10M"^^xsd:duration ] ] .
Then delayed:
:A2 rdf:type odrl:Asset . :A2 md:resource :R1 . :A2 md:timelinessOfDelivery [ rdf:type time:ProperInterval , md:Delayed ; time:intervalAfter [ rdf:type time:ProperInterval ; md:timeReference time:Instant , md:TimeOfIssue ; time:hasXSDDuration "PT10M"^^xsd:duration ] ; time:intervalBefore [ rdf:type time:ProperInterval ; md:timeReference time:Instant , md:TimeOfIssue ; time:hasXSDDuration "PT8H"^^xsd:duration ] ] .
Finally, end-of-day:
:A3 a odrl:Asset . :A3 md:resource :R2 . :A3 md:timelinessOfDelivery [ rdf:type time:ProperInterval , md:Embargoed ; time:after [ rdf:type time:Instant, md:MarketClose ; time:inDateTime [ rdf:type time::DateTimeDescription ; # Monday to Friday? time:hour "16"^^xsd:int ; time::timeZone <https://www.timeanddate.com/time/zones/ct> ] ] ] .
Now we know the assets that our license controls, we can take a quick look at how the CME sells them to get a sharper idea of the policies and permissions we need.
By looking at the fee schedule we see that only realtime data is charged for in the context of automated trading. That kind-of makes sense. Trading only with delayed data might be problematic! But let’s support it for now.
So we have one charged-for offer that allows automated trading over realtime, delayed, and end-of-day data; and one free offer that allows for automated trading over delayed and end-of-day data.
Each offer provides the two permissions we discussed above - the one that allows for actions of the type automated trading, and the other for actions of the type derive. But the permissions in the two offers target a slightly different set of assets. Only the first offer allows use of realtime data. So we actually have four different permissions.
The permissions in the first offer cover realtime, delayed, and end-of-day data. So, for automated trading:
:P1 rdf:type odrl:Permission . :P1 odrl:action md:AutomatedTrading . :P1 odrl:target :A1 , :A2 , :A3 .
… and for the derivations …
:P2 rdf:type odrl:Permission . :P2 odrl:action odrl:Derive . :P2 odrl:target :A1 , :A2 , :A3 .
The permissions in the second offer cover only delayed and end-of-day data. So they need new identifiers, :P3 and :P4:
:P3 rdf:type odrl:Permission . :P3 odrl:action md:AutomatedTrading . :P3 odrl:target :A2 , :A3 .
… and …
:P4 rdf:type odrl:Permission . :P4 odrl:action odrl:Derive . :P4 odrl:target :A2 , :A3 .
We can do the same trick with the prohibitions, and then specify the two offers. In both cases, the entity making the rights assignment (the assigner) is the CME.
Let’s call them :T1 and :T2
:T1 rdf:type odrl:Offer . :T1 odrl:assigner <https://permid.org/1-4295899615> . # CME :T1 odrl:permission :P1 , :P2 . :T1 odrl:prohibition :PR1 .
… and …
:T2 rdf:type odrl:Offer . :T2 odrl:assigner <https://permid.org/1-4295899615> . # CME :T2 odrl:permission :P3 , :P4 . :T2 odrl:prohibition :PR2 .
We’re not done yet. CME’s license also controls the use of the output of the derive action. It’s use is constrained to internal use. The data cannot be distributed to third-parties under this license. (That requires a derived data license.) So we have another policy, :U1, that contains one permission, :P5, and one prohibition, :Pr3.
We have a new type of policy here because we don’t yet know who the rights holder in the derived data will be. We’ll know that when the offers above are accepted and the assignee specified.
:U1 rdf:type odrl:Set . :U1 odrl:permission :P5 . :U1 odrl:prohibition :Pr3 .
The permission :P5 allows the use action, but limits it to internal recipients:
:P5 rdf:type odrl:Permission . :P5 odrl:action [ rdf:type md:use ; odrl:recipient md:Internal ] .
The prohibition :Pr3 explicilty forbids distribution of the derivation:
:Pr3 rdf:type odrl:Prohibition . :Pr3 odrl:action ordrl:Distribute .
Later we’ll show how this policy controlling the use of the derived data is linked to the permission allowing derivation from the CME’s data.
Of course, none of this comes for free. To exercise these permissions we have some duties to fulfill.
Some obligations relate to any data provided by CME: keep a record of access controls; accept an audit if the CME requests one.
Other duties are more closely tied to the specific permissions agreed: report on usage; attribute ownership; and, of course, pay.
But they all share a similar structure. They require an action to be taken. The actor can be called the debtor; the beneficiary, the creditor.
Duties become active at different times. As we’re working in a subscription model, many of the duties we’re talking about become active based on a periodicity - usually monthly - which we can augment with a count: the number of times within the time interval that the action must be taken. Sometimes, duties provide a grace period in which the action can be taken (like a credit policy does for payment). We can call that the deadline delta.
Some duties require other duties to be fulfilled before becoming active.
If we don’t specify these things, then the duty becomes active immediately on accepting the offer and creating an agreement.
Let’s start with audits.
The Information License Agreement provides for two mechanisms by which the CME can launch an audit of a consumer. The first is on the basis of thirty-days notice. The second can be launched immediately, but requires reasonable suspicion. Each need only be accepted once per year.
Let’s call the first of these :O1 - Once a year, accept an audit thirty days after the CME provides notice. So the action is to accept (an audit); the creditor is the CME; the time interval is a year; the deadline delta is thirty days; and the count one; and the CME has a duty to provide notice (which we’ll call :D1).
:O1 rdf:type odrl:Duty . :O1 nl:creditor <https://permid.org/1-4295899615> . # CME :O1 nl:hasDeadlineDelta [ rdf:type time:ProperInterval ; md:timeReference time:Instant , md:TimeOfNotification ; time:hasXSDDuration "P30D"^^xsd:duration ] . :O1 odrl:timeInterval [ rdf:type time:ProperInterval ; time:hasXSDDuration "P1Y"^^xsd:duration ] . :O1 odrl:action [ rdf:type md:Accept ; md:scope md:Audit ; odrl:count "1"^^xsd:int ] . :O1 odrl:duty :D1 .
Then specifying the duty on the CME to provide notice:
:D1 rdf:type odrl:Duty . :D1 nl:debtor <https://permid.org/1-4295899615> . # CME :D1 odrl:action [ rdf:type md:Notify ; md:scope md:Audit ; odrl:count "1"^^xsd:int ] .
The second mechanism is similar, but there is no notice period, and the CME has a duty to report reasonable suspicion. Let’s call the duties :O2 and :D2 respectively.
:O2 rdf:type odrl:Duty . :O2 nl:creditor <https://permid.org/1-4295899615> . # CME :O2 odrl:timeInterval [ rdf:type time:ProperInterval ; time:hasXSDDuration "P1Y"^^xsd:duration ] . :O2 odrl:action [ rdf:type md:Accept ; md:scope md:Audit ; odrl:count "1"^^xsd:int ] . :O2 odrl:duty :D2 .
Then specifying the duty on the CME to report reasonable suspicion:
:D2 rdf:type odrl:Duty . :D2 nl:debtor <https://permid.org/1-4295899615> . # CME :D2 odrl:action [ rdf:type md:Report ; md:scope md:ReasonableSuspicion ; odrl:count "1"^^xsd:int ] .
CME expects its licensee’s to maintain auditable evidence of the operation of the the access and security controls used to protect CME’s data from unauthorized use. Failure to do so invalidates all CME permissions.
We can capture this so:
:O3 rdf:type odrl:Duty . :O3 nl:creditor <https://permid.org/1-4295899615> . # CME :O3 odrl:action [ rdf:type md:Evidence ; md:scope md:Controls ; ] .
Notice that we don’t use a count property. The licensee must keep continuous evidence of the controls used to protect CME’s data.
We can now add these obligations to the two policies :T1 and :T2:
:T1 odrl:obligation :O1 , :O2 , :O3 . :T2 odrl:obligation :O1 , :O2 , :O3 .
We’re not done yet - licensees still have further duties to fulfill. These duties are tied to specific permissions. We have to attribute ownership of the data to the CME; we have to report usage of the data; and we have to pay for it (at least, for the permissions that cover realtime data).
Here the action is to attribute (ownership) using the attribution provided:
:D3 rdf:type odrl:Duty . :D3 nl:creditor <https://permid.org/1-4295899615> . # CME :D3 odrl:action [ rdf:type odrl:Attribute ; md:scope md:Ownership ; md:attribution "The market data is the property of Chicago Mercantile Exchange Inc. or it’s licensors as applicable. All rights reserved, or otherwise licensed by Chicago Mercantile Exchange Inc." ] .
The reporting duty is a tiny bit more complicated. We need to provide a count of the applications using the data once per month, 30 days in arrears.
:D4 rdf:type odrl:Duty . :D4 nl:creditor <https://permid.org/1-4295899615> . # CME :D4 nl:hasDeadlineDelta [ rdf:type time:ProperInterval ; time:hasXSDDuration "P1M"^^xsd:duration ] . :D4 odrl:timeInterval [ rdf:type time:ProperInterval ; time:hasXSDDuration "P1M"^^xsd:duration ] . :D4 odrl:action [ rdf:type md:Report ; md:scope md:Usage ; odrl:unitOfCount md:Application ; odrl:count "1"^^xsd:int ] .
The payment duty has a similar structure, though now the deadline delta is defined as a month following invoicing, with the CME having a duty to invoice. Let’s specify that first:
:D5 rdf:type odrl:Duty ; :D5 nl:debtor <https://permid.org/1-4295899615> ; # CME :D5 odrl:action [ rdf:type md:Invoice ; odrl:count "1"^^xsd:int ] .
Now we can write the full payment duty:
:D6 rdf:type odrl:Duty ; :D6 nl:creditor <https://permid.org/1-4295899615> ; # CME :D6 nl:hasDeadlineDelta [ rdf:type time:ProperInterval ; md:timeReference time:Instant , md:TimeOfInvoicing ; time:hasXSDDuration "P1M"^^xsd:duration ] ; :D6 odrl:timeInterval [ rdf:type time:ProperInterval ; time:hasXSDDuration "P1M"^^xsd:duration ] ; :D6 odrl:action [ rdf:type odrl:Compensate ; odrl:unitOfCount md:Application ; odrl:payAmount "1150.00"^^xsd:float ; odrl:unit <https://www.wikidata.org/wiki/Q4917> ; # US dollar odrl:count "1"^^xsd:int ] ; :D6 odrl:duty :D5 .
As a penultimate step we can update the permissions that control access to the CME data with these duties, noting two things:
So:
:P1 odrl:duty :D3, :D4, :D6 . :P2 odrl:duty :D3, :D4, :D6 . :P3 odrl:duty :D7, :D8 . :P4 odrl:duty :D7, :D8 .
Finally, we can link the policy controlling the use of the derived data (:U1 above) to the permissions allowing derivation from the CME’s data. We use a “next policy” duty to do so.
:D9 rdf:type odrl:Duty ; :D9 nl:creditor <https://permid.org/1-4295899615> ; # CME :D9 odrl:action odrl:nextPolicy ; :D9 odrl:target :U1 .
Now we add this duty to the two derive permissions defined earlier:
:P2 odrl:duty :D3, :D4, :D6, :D9 . :P4 odrl:duty :D7, :D8, :D9 .
This effectively says that any output from the derive permissions must be controlled by the policy :U1. Using this technique, we can control the flow of rights and obligations down the supply chain using only peer-to-peer communication.
The full translation can be found here