Skip to main content

Traded options

An exchange settles thousands of options a day, but a trading desk usually needs only the ones it holds. A positions view gives you exactly those: for an ondate it returns only the maturities, strikes and sides (call or put) you hold, with all the market values for that ondate plus your position volume and traded price.

It answers questions such as:

  • What did each option we hold settle at today, and what was its volatility and delta?
  • How many lots do we hold of each option, and at what average price?
  • Which of our options have no market price today?

The examples follow the fictional Northgate Energy, which holds ICE Endex EUA futures options.


How it works​

PartWhat it is
Position eventsYour own event list, for example NGE.EUA:POSITIONS, with one event per option held (or per trade). The event time is the position date
Position setAll the position events dated on one day. A set holds until a later set is uploaded
Positions viewAn EventOptions on the market options events, with positions set to your event list

When you read the view for an ondate:

  1. The latest position set dated on or before the ondate is found.
  2. The positions in it are netted per option (tenor, strike, call or put).
  3. The market options for the ondate are read for just those tenors and strikes.
  4. Each option you hold gets its market values plus POSITION_VOLUME and TRADED_PRICE.

1. Upload your positions​

Each position event holds the tenor, the strike, call or put, the volume and the traded price:

PropertyExampleNotes
tenor2026M09The absolute code (2026M09) or the relative code (M01)
strike85A number, or a number as text
callputCC or P, or Call or Put
volume10The volume held; negative for a short position
price0.80The traded price (optional)

A small function makes the events. Give each event its own id: createId() builds the id from the event time alone, so every position dated on the same day would get the same id and replace the others.

function makeOptionPosition(posdate, ref, tenor, strike, callput, volume, price)
e = Event(posdate)
e.id = "ID_" + format(posdate, "yyyyMMdd") + "_" + ref
e.tenor = tenor
e.strike = strike
e.callput = callput
e.volume = volume
e.price = price
makeOptionPosition = e
end

Upload the positions held on the 15th September 2026:

d = Date("2026-09-15")
o = Object()
o.id = "NGE.EUA"
o.POSITIONS = []
o.POSITIONS.add(makeOptionPosition(d, "T1001", "2026M09", 85, "C", 10, 0.80))
o.POSITIONS.add(makeOptionPosition(d, "T1002", "2026M09", 85, "C", 5, 0.95))
o.POSITIONS.add(makeOptionPosition(d, "T1003", "2026M10", 87.5, "P", -20, 2.50))
o.POSITIONS.add(makeOptionPosition(d, "T1004", "2026M12", 100, "C", 3, 1.00))
save o

This set holds two trades in the September 85 call, a short October 87.5 put and a December 100 call.

Uploading a new set​

A new set replaces the previous one from its position date on, so it must hold every option you still hold. An option that is not in the new set is no longer held. Sets for earlier dates are kept, so reading an earlier ondate still gives the positions of that time.

d = Date("2026-09-17")
o = Object()
o.id = "NGE.EUA"
o.POSITIONS = []
o.POSITIONS.add(makeOptionPosition(d, "T1001", "2026M09", 85, "C", 15, 0.85))
o.POSITIONS.add(makeOptionPosition(d, "T1005", "2026M09", 80, "C", 1, 5.30))
save o
caution

An empty set cannot be uploaded. To close every position, upload the options you held with a volume of 0; otherwise the previous set carries on.


2. Define the positions view​

Define the view once, on the market options events, with positions set to your event list:

p = EventOptions("ICE.NDEX.EFO:OPTIONS")
p.name = "EUA option positions"
p.source = "common"
p.positions = "NGE.EUA:POSITIONS"

o = Object()
o.id = "NGE.EUA"
o.POSITIONS_VIEW = p
save o

The position settings:

SettingDefaultWhat it does
positionsThe event list with your position events
positionSourceprivateWhere the position events are: private, common or public
positionFilterOptional filter (JSON) on the position events, for example one book: '{"book": "B1"}'
positionTenortenorThe position event property with the tenor
positionStrikestrikeThe position event property with the strike
positionCallPutcallputThe position event property with call or put
positionVolumevolumeThe position event property with the volume
positionPricepriceThe position event property with the traded price

If your positions come from another system with other names, set them: for example p.positionVolume = "quantity". All the options settings, such as columns, apply to the market values.


3. Read the options you hold​

Read the view for an ondate as you would any options:

held = ${data:"NGE.EUA:POSITIONS_VIEW:2026-09-16"}
print "Positions as of " + held.properties.positionDate
c = held["2026M09"][85].call
print c.POSITION_VOLUME
print c.TRADED_PRICE
print c.SETTLEMENT_PRICE

There is no set on the 16th, so the set of the 15th is used. The result:

TenorStrikeSideSettleVolDeltaOpen interestVolumePositionTraded price
2026M0985Call0.9122.07910.46623695200150.85
2026M1087.5Put2.3123.3-0.5580025-202.50
2026M12100Call31.00
  • The two September 85 call trades are netted: 10 + 5 = 15 lots at an average traded price of 0.85.
  • Only the side you hold is shown: there is no 85 put, although the exchange settled one.
  • The December 100 call had no market event on the 16th, so it has only its position values; it is listed last and counted in properties.unpriced.

The JSON is the options JSON with POSITION_VOLUME and TRADED_PRICE added to the held side and to columns, and these properties:

PropertyWhat it is
positionsThe position event list
positionDateThe date of the position set used
unpricedThe number of held options with no market values on the ondate (only when there are any)

Through the REST API:

GET https://api.opendatadsl.com/api/data/v1/private/NGE.EUA:POSITIONS_VIEW:2026-09-16
Authorization: Bearer {{token}}

Rules​

RuleDetail
Which setThe latest set dated on or before the ondate. Before the first set there are no options (not found)
NettingVolumes are summed per tenor, strike and call or put. The traded price is the average of the prices weighted by volume, over the events that have a price
Closed optionsAn option whose volumes net to zero is left out
Incomplete eventsA position event with no tenor, strike, call or put, or volume is skipped
Held side onlyA strike shows only the side you hold, with all its market columns
No market valueA held option with no market event on the ondate is kept with only its position values
OndatesThe market ondates from the first position date on. A date with no market events is not found, as for the market options
Single optionsNGE.EUA:POSITIONS_VIEW:2026M09:85:C is the market timeseries of that option, without positions

Good to know​

  • Positions are your own private events, read with your security policies. The market events are read with your access to the exchange data too: without it the request is refused.
  • The view reads only the market events for the tenors and strikes you hold, so it stays quick however large the exchange data is.
  • A position given with a relative tenor (M01) is matched to the market tenor that is M01 on the ondate.