graph_data_request

Description

Subscribe to a continuously updating chart bar data. Chart bar data refers to chart base data and subgraph data

~11 Min Overview Video

https://youtu.be/jKcwLcKrsF4

Request Lifecycle

The general approach to the lifecycle is that when the client first subscribes, some historical data is initially sent. This initial historical data would normally be used to warm up indicators. Once that is done the server sends continuous updates. The user can control how many bars are sent in each phase.

In more detail, the client sends a request to subscribe with X historical_bars and Y realtime_update_bars

The server then goes through to 2 phases:

  • Init phase - the server responds by sending back Y bars. This is a one time event, allowing the client to initialize itself with enough historical data.

  • Realtime update phase - the server sends Y bars on each update. So more below on the update frequency.

In other words, the server first sends back X bars, this is a one time thing. After that the server continuously sends Y bars on each update.

X is dependent on the historical_bars parameter sent in the request.

Y is dependent on the realtime_update_bars send in the request.

If Y is zero, phase2, realtime updates, will not happen. The server will simply send the historical bars and end there

When done the client sends an unsubscribe message.

Request Parameters

Param

Description

Type

Valid Values

Example

Param

Description

Type

Valid Values

Example

Header params

 

 

 

 

base_data

List of base data elements. Base data refers to open, high, low, last, volume, etc. The values in the list correspond with the Sierra Chart base data numbering

string

List of base data

See SC Base Data Constants

Elements are separated by semicolon

 

 

“1;3;4;12;13”

refers to open, low, last, up vol and down vol

sg_data

Defines the list of subgraphs to retrieve

string

Follows the SG Data format

ID1.[SG1-SG3]

subscribes to updates on study ID1, subgraphs 1-3

include_timestamp

 

boolean

1 or 0

 

historical_bars

 

int

integer

500 - 500 historical bars are sent during the init subcription phase

see below for more

realtime_update_bars

 

int

integer

5 - 5 bars are sent on each real time update

on_bar_close

True - real time updates are sent only when a bar closes

False - real time updates are sent continuously based on the update_frequency_ms

boolean

True or False

 

update_frequency_ms

 

int

integer

5000, updates are sent every 5000 milliseconds

include_bar_ closed_status

 

boolean

True or False

 

include_bar_index

 

boolean

True or False

 

include_vbp

 

boolean

True or False

 

vbp_include_empty_price_levels

 

boolean

True or False

 

block

blocking call (should the call be async or sync, see more here)

boolean

 

 

 

sg_data=”ID2.[SG1-SG3]”

The SG Data parameter is used to specify a list of subgraphs to subscribe to. The parameter syntax generally looks like this: study_id.[subgraphs]

A simple example of this is something like "ID0.[SG4]” which translates to study 0 (the main price graph) and subgraph 4 (which happens to be the last price in the main price graph)

In more detail

study_id - formatted like it appears in SC. ID1, ID2, ID3 etc. ID0 is the main price graph.

subgraphs - subgraphs are denoted similar to how they appear in SC. SG1, SG2. SG3 etc. The field supports single values, range and list

  • Single - [SG3]

  • Range - [SG3-SG5]

  • List - [SG3, SG4, SG5]

  • Mixed list and range [SG3-SG5, SG8, SG9]

Subscribing to multiple studies at the same time

The description above demonstrates subscribing to data from a single study.

It’s possible to subscribe to multiple studies in one subscription. To that simply separate each study description by a semicolon

For example, assume you have a chart with a simple moving average on it at ID1.

To receive both the last price and the ma, the syntax would look like this: "ID0.[SG4];ID1.[SG1]”

update_frequency

The client uses on_bar_close and update_frequency to specify how often it wishes to receive updates from the server.

If on_bar_close is 1, the server will send updates only when a bar is closed - no updates will be sent while the bar is still forming.

If on_bar_close is 0, the server will use update_frequency to determine how often it sends messages to clients. The update_frequency param is tied with Sierra Chart own chart update frequency settings.

If the update_fequency is used when it is greater than the chart update frequency.

For example, if the chart update frequency is 800ms and the client sent update_frequency 5000, the server will update the client every 5000ms (5 seconds).

If the update_frequency is set to 0, the server will default to the chart update frequency set in Sierra Chart

If the update_fequency is less than the chart update frequency, again, the server will fall back to the chart update frequency.

historical_init=x

Sends x number of bars when a request is first made.

Use cases:

  • Reducing real time resource usage

  • One time data retrievals (while in a research workflow or live)

This setting is impacted by on_bar_close:

  • if on_bar_close is set to False, the last (live) bar on the chart will not be sent

  • if on_bar_close is set to True, the last (live) bar on the chart, will be sent

 

2 Approaches for retrieving data for realtime processing

The method graph_data_request has 2 settings that control how many bars are sent

  • historical_init_bars - when you send a request, the first response is that many bars. it will send that many bars once at the start

  • realtime_update_bars - on each update this many bars will be sent

The python library does not cache or store any history. If you set realtime_update_bars=10, effectively what that means is that 10 bars are sent from SC to your code on every update. In your example, where you need 10 bars of history to do your calculations, you could achieve that as you did in your code which would work fine. 

But there are other strategies to do that. For example, you could get hisotrical_init_bars of 10 which you would use to initialize your raw DataFrame with 10 bars. You could then set the realtime_update_bars to 1. Then, on each update you would receive a new bar of data. You could then take the raw dataframe and append the new bar you just received and drop the oldest one.

Why do we need these two approaches? In many cases, you only need 10-100 bars of data which is not a lot. So the approach of setting realtime_update_bars to a value in that range is simple and easy. You always get the number of bars you need to calculate from SC and you don't have to worry about it. In some cases you need a lot more history and it becomes resource intensive and laggy to send too many bars. In that case the 2nd approach would work well.

block - blocking vs. non-blocking

By default graph_data_request is asynchronous and non-blocking.

In the async mode, the usage looks like this:

  1. Make a call to grapg_data_request, receive the request_id

  2. Get a hold of the response queue

  3. Using the response queue, get the response

Code snipper looks like this:

from trade29.sc.bridge import SCBridge bridge = SCBridge() bridge.graph_data_request(key='xx', base_data='4', historical_init_bars = 1000, realtime_update_bars=0, block=False) response_q = bridge.get_response_queue() while True: msg = response_q.get() print(msg.df)

graph_data_request supports blocking mode. In blocking mode, which is sync and not async, the usage would look like this:

  1. Make a call to graph_data_request and receive the response

All in one step, no need to use the queue as a middle man to retrieve the result.

This type of call is similar to the standard way of calling functions where you make the function call and the function returns the desired result directly.

Code snippet looks like this:

from src.trade29.sc.bridge import SCBridge from src.trade29.sc.constants import * bridge = SCBridge() response = bridge.graph_data_request(key='xx', base_data='4', historical_init_bars=1000, realtime_update_bars=0, block=True) print(response.df)

The two snippets are similar but for two differences:

  1. The 1st snippet has block=False, the 2nd snippet has blocl=True

  2. The 1st snippet uses the queue to receive the response. The 2nd snippet receive the data directly from graph_data_request

block=True only makes sense when realtime_update_bars=0. In other words, it only makes sense when retrieving historical data. When using subscribing to realtime updates, block should be False

Return Message Format

Graph data is returned in a pandas DataFrame.

The order of the fields

  1. bar timestamp - single column

  2. bar closed flag - single column

  3. bar index - single column

  4. base data - multiple columns

  5. subgraph data - multiple columns

Whether a field appears or not depends on what was requested. For example, if include_bar_closed_status was set to False, the returned DataFrame will not include this field.

Graph data DataFrame field descriptions and examples

 

Description

Example

 

Description

Example

bar_timestamp

Bar timestamp

This field will appear only if the user has set include_bar_timestamp to 1

2023-04-27 22:25:00

bar_is_closed_flag

A flag signaling if this bar is closed

This field will appear only if the user has set include_bar_closed_status to 1

 

bar_index

The index of the bar on the chart.

This field will appear only if the user has set include_bar_closed_status to 1

374 would be bar number 375 on the chart (the count starts from 0)

base_data

A list of values.
The list is based on the base_data field
The order of the list aligns with the order passed in by the user when making the request

User has set the base_data list to SC_OPEN, SC_LAST

4034.25, 4044.50 would mean that the open of the bar is 4034.25 and the last price is 4044.50

 

bar_sg_data

A list of values.
The list is based on the sg_data field
The order of the list aligns with the order passed in by the user when making the request

User has set sg_data to ID1.[SG1-SG3], ID1 is the BB on the chart

The record will include 3 fields for SG1, SG2, SG3

In other words, we would have the 3 BB values separated by commas

 

vbp_data

Volume by Price (footprint) data

List of tuples, each tuple includes price, bid volume, ask volume,number of trades