Stops & Icebergs Tracker
What is it
This add-on tracks the executions of Stop orders and the evolution of Iceberg orders. Its main features are:
- 100% accurate detection of:
- Execution and tracking of Iceberg orders
- Executions of Stop orders
- The true size of the aggressor order (e.g. "trade reconstruction"). This includes the entire size of partially executed limit orders. The limit price of such orders also becomes known.
- Ability to apply order size filter on any of the above
- Instant computation and display of each update. Not once per minute or second, but whenever it happens
- Computes and displays the results from the moment of instrument subscription, not from the moment of enabling the addon
- Processes millions of market data events per second on a regular laptop. This allows to re-compute the indicator instantly whenever user changes the settings
- (An upcoming feature currently in development) Ability to create custom indicator lines with a couple of lines written in JavaScript. This short script has access to all the data including Stops and Icebergs info. The built-in lines (Stops and Icebergs) are also implemented as short JavaScript code and can be used as examples
Installation
Technical details: download the addon's jar file either from the download section in your marketplace dashboard or using the direct link. In Bookmap click Settings -> Addons -> Add, and add the jar file.
Background
Exchanges process orders in atomic manner which means strictly according to the order of their arrival to the exchange (unless it applies artificial speed bumps). Orders that can't be immediately executed (e.g., due to their limit price) become resting (or working) orders and form the order book. A new order can be matched against one or more or none of the resting orders. Because only the newly arrived (or newly replaced) order may initiate a trade, we call it the aggressor order, and its counterparties -- passive orders.
The trade object
A trade can be represented by a single aggressor order with a list of affected by it passive orders. Here are examples of such objects in JSON form:
{
"timestamp": 1553517589009337101,
"orderId": "645557118818",
"isBuy": true,
"isStop": false,
"orderSize": 7,
"passiveOrdersList": [
{
"orderId": "645557118724",
"price": 11234,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6222141269
},
{
"orderId": "645557118725",
"price": 11234,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6222061501
},
{
"orderId": "645557118733",
"price": 11234,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 5291476329
},
{
"orderId": "645557118734",
"price": 11234,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 5291466590
},
{
"orderId": "645557118735",
"price": 11234,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 5291403982
},
{
"orderId": "645557118740",
"price": 11234,
"tradeSize": 2,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 2,
"remainedSize": 4,
"lifeTime": 5283330257
}
]
},
{
"timestamp": 1553517571175695053,
"orderId": "645557115281",
"isBuy": true,
"isStop": true,
"orderSize": 4,
"passiveOrdersList": [
{
"orderId": "645557113818",
"price": 11234,
"tradeSize": 2,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 2,
"remainedSize": 0,
"lifeTime": 260762777483
},
{
"orderId": "645557113822",
"price": 11234,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 260762748266
},
{
"orderId": "645557113831",
"price": 11234,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 260758484854
}
]
},
{
"timestamp": 1553516837968759321,
"orderId": "645557101905",
"isBuy": true,
"isStop": false,
"orderSize": 64,
"passiveOrdersList": [
{
"orderId": "645557101746",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6684971251
},
{
"orderId": "645557101747",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6684972179
},
{
"orderId": "645557101751",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6683991775
},
{
"orderId": "645557101753",
"price": 11227,
"tradeSize": 4,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 4,
"remainedSize": 0,
"lifeTime": 6683947717
},
{
"orderId": "645557101754",
"price": 11227,
"tradeSize": 3,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 3,
"remainedSize": 0,
"lifeTime": 6683426442
},
{
"orderId": "645557101765",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6681909924
},
{
"orderId": "645557101775",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6680682795
},
{
"orderId": "645557090167",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": true,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 58938807765
},
{
"orderId": "645557101788",
"price": 11227,
"tradeSize": 2,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 2,
"remainedSize": 0,
"lifeTime": 6677298222
},
{
"orderId": "645557101789",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6663871233
},
{
"orderId": "645557101790",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6663831348
},
{
"orderId": "645557101791",
"price": 11227,
"tradeSize": 2,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 2,
"remainedSize": 0,
"lifeTime": 6664338246
},
{
"orderId": "645557101792",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6664322014
},
{
"orderId": "645557101793",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6664290941
},
{
"orderId": "645557101794",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6663946826
},
{
"orderId": "645557101795",
"price": 11227,
"tradeSize": 2,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 2,
"remainedSize": 0,
"lifeTime": 6663919928
},
{
"orderId": "645557101797",
"price": 11227,
"tradeSize": 4,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 4,
"remainedSize": 0,
"lifeTime": 6663880508
},
{
"orderId": "645557101805",
"price": 11227,
"tradeSize": 3,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 3,
"remainedSize": 0,
"lifeTime": 6659504863
},
{
"orderId": "645557101806",
"price": 11227,
"tradeSize": 8,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 8,
"remainedSize": 0,
"lifeTime": 6659418603
},
{
"orderId": "645557101809",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6658736401
},
{
"orderId": "645557101810",
"price": 11227,
"tradeSize": 2,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 2,
"remainedSize": 0,
"lifeTime": 6658707183
},
{
"orderId": "645557101811",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6658664981
},
{
"orderId": "645557101812",
"price": 11227,
"tradeSize": 2,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 2,
"remainedSize": 0,
"lifeTime": 6657991127
},
{
"orderId": "645557101813",
"price": 11227,
"tradeSize": 2,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 2,
"remainedSize": 0,
"lifeTime": 6657969330
},
{
"orderId": "645557101814",
"price": 11227,
"tradeSize": 2,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 2,
"remainedSize": 0,
"lifeTime": 6658602372
},
{
"orderId": "645557101815",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6658582431
},
{
"orderId": "645557101816",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6658561098
},
{
"orderId": "645557101817",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6659428806
},
{
"orderId": "645557101821",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6658584286
},
{
"orderId": "645557101822",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 6658570372
},
{
"orderId": "645557101484",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": true,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 24737767907
},
{
"orderId": "645557101684",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": true,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 9745074560
},
{
"orderId": "645557097906",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": true,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 58952449016
},
{
"orderId": "645557101319",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": true,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 32968388233
},
{
"orderId": "645557101211",
"price": 11227,
"tradeSize": 3,
"isNativeIceberg": true,
"isCustomIceberg": false,
"totalTradedSize": 3,
"remainedSize": 0,
"lifeTime": 38806541808
},
{
"orderId": "645557101511",
"price": 11227,
"tradeSize": 2,
"isNativeIceberg": true,
"isCustomIceberg": false,
"totalTradedSize": 2,
"remainedSize": 0,
"lifeTime": 22761214588
},
{
"orderId": "645557101891",
"price": 11227,
"tradeSize": 1,
"isNativeIceberg": false,
"isCustomIceberg": false,
"totalTradedSize": 1,
"remainedSize": 0,
"lifeTime": 808857398
}
]
},
When a new trade occurs the addon creates such an object and computes some of its properties that are not directly included in the market data, e.g. Iceberg, Stop, the size of the aggressor order, etc. Then it's used to update the values of displayed lines.
The order size filter
Notice that the orders size filter refers to the order size, not the trade size. This is because traders are typically interested to track the larger orders and because the actual order size of all participating orders can be larger than their traded size in a particular transaction. This happens when a Stop-Limit order is only partially executed, when a limit order (especially iceberg order) was already executed earlier.
To summarize, after the trade object is computed, it is used to update the two cumulative-volume-delta (CVD) lines on the chart as following:
Stop orders CVD | Iceberg orders CVD | |
---|---|---|
Affected by | Aggressive orders where isStop is true | Passive orders where isIceberg is true |
Value | The sum of tradeSize of passive orders list | Its own tradeSize field |
Sign | Positive if isBuy is true | Positive if isBuy is false |
Order size filter applies on | orderSize of the aggressor order | totalTradedSize + remainedSize of Iceberg orders |
Accumulation mode
Each event represents the traded volume of that event. The sign of the resulting value is negative for Sell orders and positive for Buy orders. It wouldn't be possible to digest visually every data event. Therefore the indicator line represents some sort of accumulation of past events until the current moment. For convenience, there are several accumulation methods, here are the details:
Accumulation type | The time parameter T means | Accounted time interval | Indicator's value |
---|---|---|---|
SUM | N/A | From data start | Regular sum |
EXPONENTIAL | T - the decay rate (half-life) | From data start | Sum, gradually decaying by 50% every T |
RESET (every T) | T - tells how frequently to reset, e.g. every 1 minute | From last reset point | Regular sum |
SLIDING | T - the width of the sliding window | From T time ago | Regular sum |
SAME_SIDE_SUM | N/A | Accumulates Buy volume until any Sell volume, and vice versa | Regular sum |
Voice and Text alerts
Types of alert triggers
Currently there are 2 types of triggers:
- A burst of Iceberg orders executions
- A burst of Stop orders executions
Both are triggered when the volume traded by corresponding orders is greater or equal V
within time interval T
where V and T are configurable parameters.
Methods of reporting the alerts
Currently there are two methods to receive alerts: as text messages in File->Alerts window, and as a voice synthesized from a text message. Future versions may custom include non-voice sounds. The content (or format) of the message is configurable simply by editing corresponding fields. Variable properties of the alert can be placed anywhere in the message using keywords surrounded by ${}
, for instance:
Stop orders traded ${size} contracts at ${price} within ${time} milliseconds
When an alert is triggered, these variables will be replaced by actual values. The following keywords are supported:
${type}
- the type of the trigger, e.g.Stop
, orIceberg
${symbol}
- Full instrument's name such as ESU0${exchange}
- the exchange, e.g. ES${sym}
- 2 first letters of${symbol}
${size}
- the traded volume which triggered the alert${side}
- eitherBuy
orSell
. Note that the if the event is triggered by Stop order(s) trading against Iceberg(s) orders, theside
of these orders is opposite to each other${time}
- the time interval in milliseconds during which it occurred. If it's caused by a single aggressive order, thistime
is zero${price}
- at which price the${size}
is traded. If there are multiple prices, the${price}
represents VWAP (volume weighted average price)${multi}
- The system aggregates the alerts as long as the audio system is busy (e.g. pronouncing the previous alert). Then multiple alerts are aggregated and reported as a single alert. The${multi}
keyword acts as a separator between the message used for a single alert and the message used for an aggregated alert. If this keyword is absent, the entire message is used regardless of whether the alert is aggregated or not.${N}
- Represents the number of aggregated alerts (appears as1
for a single alert)
Examples:
${type} ${side} alert at ${sym}: ${size} contracts
${type} ${side} alert at ${symbol}.${exchange} (${sym}): ${size} contracts at ${price} within ${time} ms${multi}Miltiple (${N}) ${type} ${side} alerts at ${symbol}.${exchange} (${sym}): ${size} contracts at ${price} within ${time} ms
${sym} ${type} alert: ${side} ${size} in ${time} millis${multi}${sym} ${type} multi alert: ${side} ${size} in ${time} millis by ${N} triggers
${sym} ${type} alert: ${side} ${size}
- a short alert for voice messages${sym} ${type} alert: ${side} ${size}${multi}Multi {sym} ${type} alert: ${side} ${size} by ${N} triggers
- if you want to know which alerts consist of multiple alerts
For voice alerts it's recommended to use very short and simple pattern. For example, ${sym} ${type} alert: ${side} ${size}
will sound like ES Stop alert: Buy 50
. This will reduce time it takes the robot to pronounce it.
Alerts vs Indicator
The latest version allows to align alerts with indicator values by selecting "Apply threshold on indicator..." checkbox.
If not selected, the two are not supposed to be comparable. A simple analogy: when a fire alarm is triggered, it doesn't tell what will be the maximum temperature during the fire. For that it would need to either delay the alert (not acceptable) or to know the future (not possible).
Due to the above, the indicator's values may reach higher magnitude. From the other hand, the indicator accumulates Buy and Sell volume with opposite sign, therefore in theory (because it rarely happens) a consequent Buy Stop 500 and Sell Stop 500 will not change the indicator, but will trigger two alerts.
Note: If orders size filter is enabled, it's similarly used by the indicator and the alerts system
Direct download links
- Latest : download
Versions changelog
3.1.0
Published on 25-Sep-2020.
- TBA
3.0 (alpha/experimental)
Published on 12-Aug-2020.
- Added a new accumulation method: Sliding window
- (Experimental feature) Voice and Text alerts
- Minor changes in user interface (making it more compact)
- Other minor improvements
2.8 (beta/production)
- minor bug fixes
- performance improvements
- update notification system
2.2
Published on 11-June-2020.
- Fix: a false alarm about non-MBO data
- Fix: Default color button
- Improvement: updates notification mechanism (see status in the settings panel)
- Fix: crash when inheriting chart settings from another chart