Generate and use test trade data

Here we use the RTS 2 Annex 3 model to generate test trade data which we then classify.

In these first examples we generate a couple of really simple cases. Read the comments in the code which explain what is happening at each step.

Do run the steps in order. The later steps build on work done by the earlier steps ... if you skip a step something may break. If that happens, just start again from the top.


In [1]:
# Import the RTS 2 Annex III taxonomy 
# ... and get hold of the object which represents the root of the taxonomy tree.
import rts2_annex3
root = rts2_annex3.class_root

# Now we print the root object to see what it is.
print(root)


<rts2_annex3_model.TaxonomyRoot object at 0x7fb2e4490780>

In [2]:
# Using the taxonomy to generate some test data:

# Starting with a Sub-asset class which has no criteria:
sub_asset_class = root.sub_asset_class_by_name("Exchange Traded Notes (ETNs)")

# Ask the Sub-asset class to generate a single sample trade
sample_trades = sub_asset_class.make_test_samples(number=1)
sample_trade = sample_trades[0]

# Get the RTS 2 Annex III taxonomy to classify the trade
classification = root.classification_for(subject=sample_trade)

print(classification.classification_dict())


OrderedDict([('RTS2 version', 'EU 2017/583 of 14 July 2016'), ('Asset class', 'Bonds (ETC and ETN bond types)'), ('Sub-asset class', 'Exchange Traded Notes (ETNs)')])

In [3]:
# Note that RTS 2 taxonomy is implemented in Python so the printed result above is 
# simply the literal form of a Python OrderedDict.

# We can make the classification easier to understand using JSON.
# ... but note that the content is just the same as above.

import json
print(classification.as_json(indent=4))


{
    "RTS2 version": "EU 2017/583 of 14 July 2016",
    "Asset class": "Bonds (ETC and ETN bond types)",
    "Sub-asset class": "Exchange Traded Notes (ETNs)"
}

In [4]:
# Now we generate a sample trade for an Asset class.

# We select an Asset class which has two child Sub-asset classes, including
# the Sub-asset class used as an example above.
asset_class = root.asset_class_by_name("Bonds (ETC and ETN bond types)")

# When we ask the asset class to make a sample it randomly chooses one of
# its two children.
sample = asset_class.make_test_samples(1)[0]

# This new sample trade is classified.
classification = root.classification_for(subject=sample)
print(classification.as_json(indent=4))

# Run the this cell many times and note that the Sub-asset class is selected randomly


{
    "RTS2 version": "EU 2017/583 of 14 July 2016",
    "Asset class": "Bonds (ETC and ETN bond types)",
    "Sub-asset class": "Exchange Traded Notes (ETNs)"
}

The above example uses Sub-asset classes which have no criteria. This makes for a simpler example but is not the most common case, most Sub-asset classes have criteria.

The next examples generate trades for Sub-asset classes which do have criteria. Some criteria are defined in the RTS to have a fixed nuber of options, for example segmentation criteria 1 for the "Energy commodity swaps" Sub-asset class is an energy type and must be one of 'ELEC', 'NGAS', 'OILP', 'COAL', 'INRG', 'RNNG', 'LGHT' and 'DIST' from RTS 23 table 2. Other criteria do not have value ranges defined in the RTS. In cases where the implementation can select a reasonable random option it does so e.g. 'NGAS', in cases where the values are not defined in RTS 2 generated trades contain values like 'settlement_type.value' which is not realistic, but is obvious.

For date buckets the code always generates the from_date as today and then chooses a random duration from a small set of options. This means the date buckets are alway valid and vary a bit to add some variety.

Note that it is possible to generate a sample trade and then modify the trade with more realistic values. We'll do that a bit later.


In [5]:
# We now make a sample trade which has many criteria.  First 
# get hold of the Sub-asset class
sub_asset_class = root.sub_asset_class_by_name("Energy commodity swaps")

# Then generate a sample trade
sample_trade = sub_asset_class.make_test_samples(1)[0]

# Notice that the sample trade has some values which change randomly, e.g. to_date
print(vars(sample_trade))

# ... so when the trade is classified the maturity bucket criteion varies
classification = root.classification_for(subject=sample_trade)
print(classification.as_json(indent=4))


{'settlement_type': 'settlement_type.value', 'delivery': 'delivery.value', 'notional_currency': 'notional_currency.value', 'asset_class_name': 'Commodity Derivatives', 'load_type': 'load_type.value', 'to_date': datetime.date(2019, 6, 17), 'sub_asset_class_name': 'Energy commodity swaps', 'from_date': datetime.date(2018, 6, 17), 'underlying_energy': 'underlying_energy.value', 'energy_type': 'RNNG'}
{
    "RTS2 version": "EU 2017/583 of 14 July 2016",
    "Asset class": "Commodity Derivatives",
    "Sub-asset class": "Energy commodity swaps",
    "Segmentation criterion 1 description": "energy type: oil, oil distillates, coal, oil light ends, natural gas, electricity, inter-energy",
    "Segmentation criterion 1": "RNNG",
    "Segmentation criterion 2 description": "underlying energy",
    "Segmentation criterion 2": "underlying_energy.value",
    "Segmentation criterion 3 description": "notional currency defined as the currency in which the notional amount of the swap is denominated",
    "Segmentation criterion 3": "notional_currency.value",
    "Segmentation criterion 4 description": "settlement type defined as cash, physical or other",
    "Segmentation criterion 4": "settlement_type.value",
    "Segmentation criterion 5 description": "load type defined as baseload, peakload, off-peak or others, applicable to energy type: electricity",
    "Segmentation criterion 5": "load_type.value",
    "Segmentation criterion 6 description": "delivery/ cash settlement location applicable to energy types: oil, oil distillates, oil light ends, electricity, inter-energy",
    "Segmentation criterion 6": "delivery.value",
    "Segmentation criterion 7 description": "Natural Gas/'Electricity/Inter-energy",
    "Segmentation criterion 7": "Maturity bucket 2: 1 month to 1 year"
}

In [6]:
# Now to generate and clasify lots of sample trades

# Generate a sample trade for each Sub-asset class in the taxonomy
samples = []
for sub_asset_class in root.all_sub_asset_classes():
    samples.extend(sub_asset_class.make_test_samples(1))

# Classify each sample
classifications = [root.classification_for(subject=sample) for sample in samples]

# Show a couple of random examples of the classifications
import random
for n in range(2):
    a_classification = random.choice(classifications)
    print("\nSample trade {n} looks like this:".format(n=n))
    print(vars(a_classification.subject))
    print("\nThe classification of sample trade {n} looks like this:".format(n=n))
    print(a_classification.as_json(indent=4))


Sample trade 0 looks like this:
{'sub_asset_class_name': 'Stock index futures/ forwards', 'asset_class_name': 'Equity Derivatives', 'underlying_stock_index': 'underlying_stock_index.value'}

The classification of sample trade 0 looks like this:
{
    "RTS2 version": "EU 2017/583 of 14 July 2016",
    "Asset class": "Equity Derivatives",
    "Sub-asset class": "Stock index futures/ forwards",
    "Segmentation criterion 1 description": "underlying stock index",
    "Segmentation criterion 1": "underlying_stock_index.value"
}

Sample trade 1 looks like this:
{'notional_currency_pair': 'notional_currency_pair.value', 'sub_asset_class_name': "Overnight Index Swap (OIS) 'multi-currency swaps' or 'cross-currency swaps' and futures/forwards on Overnight Index Swap (OIS) 'multi-currency swaps' or 'cross-currency swaps'", 'to_date': datetime.date(2018, 7, 17), 'asset_class_name': 'Interest Rate Derivatives', 'from_date': datetime.date(2018, 6, 17)}

The classification of sample trade 1 looks like this:
{
    "RTS2 version": "EU 2017/583 of 14 July 2016",
    "Asset class": "Interest Rate Derivatives",
    "Sub-asset class": "Overnight Index Swap (OIS) 'multi-currency swaps' or 'cross-currency swaps' and futures/forwards on Overnight Index Swap (OIS) 'multi-currency swaps' or 'cross-currency swaps'",
    "Segmentation criterion 1 description": "notional currency pair defined as combination of the two currencies in which the two legs of the swap are denominated",
    "Segmentation criterion 1": "notional_currency_pair.value",
    "Segmentation criterion 2 description": "time to maturity bucket of the swap defined as follows:",
    "Segmentation criterion 2": "Maturity bucket 1: Zero to 1 month"
}