start_historical_data_subscription – ShinyBroker

# start_historical_data_subscription

`start_historical_data_subscription(historical_data=None, hd_socket=None, subscription_id=None, contract=Contract({}), endDateTime='', durationStr='1 D', barSizeSetting='1 hour', whatToShow='Trades', useRTH=1, formatDate=1, keepUpToDate=0)`

Reactively get historical data

Creates a subscription for historical data using the parameters supplied. Results will appear in the `sb_rvs['historical_data']` object, where they are accessible by other functions in your app.

## Parameters

Name | Type | Description | Default
--- | --- | --- | ---
`historical_data` |  | You probably want to pass `sb_rvs['historical_data']` to this parameter unless you have declared a different reactive variable for storing your historical data queries. Unless you have a very specific use case to do otherwise, use `sb_rvs['historical_data']`. | `None`
`hd_socket` |  | The socket on which you want to make the historical data subscription. You almost certainly want to pass `ib_socket` as this parameter unless you have constructed an app that uses different sockets for different tasks. This is not recommended except for advanced use cases. | `None`
`subscription_id` |  | Identifier of the request. You may use your own system, such as using contract `symbol` as your ID if you wish. If not supplied, then ShinyBroker will assign the smallest number that isn’t already in use as a historical data subscription ID. | `None`
`contract` |  | The Contract object for which you want data | `Contract({})`
`endDateTime` |  | Ending datetime string formatted as “YYYYMMDD HH:mm:ss TMZ” specifying the end of the time period for which you want historical data. Leave it as the default “” to get historical data up to the current present moment. | `''`
`durationStr` |  | A Duration String that specifies how far back in time you want to fetch data. | `'1 D'`
`barSizeSetting` |  | A Bar Size that specifies how fine-grained you want your historical data to be (daily, weekly, every 30 seconds, etc). | `'1 hour'`
`whatToShow` |  | You may select from any of the Historical Data Types but for most cases you’ll probably be happy with one of “BID_ASK”, “MIDPOINT”, or “TRADES”. | `'Trades'`
`useRTH` |  | “Use Regular Trading Hours”. Set to `False` if you want the historical data to include after-hours/pre-market trading | `1`
`formatDate` |  | Numeric code from the Format Date Received table that specifies how you want your dates formatted in the data. | `1`
`keepUpToDate` |  | Set to `True` if you want to keep receiving new bar data as it becomes available. For a `barSizeSetting` of `5 min`, that would mean you receive new data every 5 minutes. | `0`

## Example

Run the app below for an informative exploration of this function and related objects.

    import shinybroker as sb
    from shiny import Inputs, Outputs, Session, ui, render, reactive, req

    shdss_ui = ui.page_fluid(
        ui.h2("Historical Data Fetcher"),
        ui.p(
            'When you click the "Fetch Historical Data" button, this app ' +
            'feeds each of the labelled inputs to ',
            ui.code("start_historical_data_subscription"),
            "which assigns an ID to each query and makes the data request. " +
            "ShinyBroker then reactively receives the data as it comes in and " +
            "stores it in the reactive variable ",
            ui.code("sb_rvs['historical_data']"),
            ", which this app uses to populate the output fields."
        ),
        ui.p(
            "For simplicity, the contract object is defined here using ",
            ui.code("conId"),
            " only. Feel free to experiment with other IDs such as '76792991' " +
            "(Tesla), '43645865' (IBKR), '36285627' (GameStop), or use the " +
            "tools from the \"Inspect\" tab of ShinyBroker to look up more."
        ),
        ui.br(),
        ui.row(
            ui.column(
                3,
                ui.input_text(
                    id='con_id',
                    label='conId',
                    value='265598'
                )
            ),
            ui.column(6),
            ui.column(
                3,
                ui.input_action_button(
                    id='fetch_data',
                    label='Fetch Historical Data'
                )
            )
        ),
        ui.row(
            ui.column(
                3,
                ui.input_text(
                    id='endDateTime',
                    label='endDateTime',
                    value=''
                )
            ),
            ui.column(
                3,
                ui.input_text(
                    id='durationStr',
                    label='durationStr',
                    value='1 W'
                )
            ),
            ui.column(
                3,
                ui.input_text(
                    id='barSizeSetting',
                    label='barSizeSetting',
                    value='1 day'
                )
            ),
            ui.column(
                3,
                ui.input_text(
                    id='whatToShow',
                    label='whatToShow',
                    value='Trades'
                )
            )
        ),
        ui.row(
            ui.column(
                3,
                ui.input_switch(id="useRTH", label="useRTH", value=True)
            ),
            ui.column(
                3,
                ui.input_radio_buttons(
                    "formatDate",
                    "formatDate",
                    {
                        "1": "String Time Zone Date",
                        "2": "Epoch Date",
                        "3": "Day & Time Date"
                    }
                )
            ),
            ui.column(
                3,
                ui.input_switch(
                    id="keepUpToDate", label="keepUpToDate", value=False
                )
            ),
            ui.column(3)
        ),
        ui.output_ui('hd_selector'),
        ui.output_ui('hd_output')
    )

    # Server to support the new UI
    # Signature must always contain the following five parameters:
    #   input, output, session, ib_socket, and sb_rvs
    def shdss_server(
            input: Inputs, output: Outputs, session: Session, ib_socket, sb_rvs
    ):

        @reactive.effect
        @reactive.event(input.fetch_data, ignore_init=True)
        def fetch_historical_data():
            sb.start_historical_data_subscription(
                historical_data=sb_rvs['historical_data'],
                hd_socket=ib_socket,
                contract=sb.Contract({'conId': input.con_id()}),
                endDateTime=input.endDateTime(),
                durationStr=input.durationStr(),
                barSizeSetting=input.barSizeSetting(),
                useRTH=input.useRTH(),
                formatDate=input.formatDate(),
                keepUpToDate=input.keepUpToDate()
            )

        @render.ui
        def hd_selector():
            if len(sb_rvs['historical_data']().keys()) > 0:
                return ui.TagList(
                    ui.input_radio_buttons(
                        id='selected_hd_id',
                        label='Select an ID to display historical data',
                        choices=dict(
                            zip(
                                sb_rvs['historical_data']().keys(),
                                sb_rvs['historical_data']().keys()
                            )
                        )
                    ),
                    ui.output_ui('hd_description'),
                    ui.output_data_frame('selected_hd_data')
                )
            else:
                return ui.TagList(
                    ui.p(
                        'Please make a historical data request and the results ' +
                        'will appear here.'
                    )
                )

        @render.data_frame
        def selected_hd_data():
            selected_hd = sb_rvs['historical_data']().get(
                input.selected_hd_id(), {}
            ).get('hst_dta', False)
            req(selected_hd is not False, cancel_output=True)
            return render.DataTable(selected_hd)

        @render.ui
        def hd_description():
            return ui.TagList(
                ui.br(),
                ui.h5(
                    "Here is the output of all the elements of ",
                    ui.code("sb_rvs['historical_data']"),
                    " except for ",
                    ui.code('\'hst_dta\''),
                    ":"
                ),
                ui.code(str({
                    key: value for (key, value) in
                    sb_rvs['historical_data']().get(
                        input.selected_hd_id()).items() if
                    key != 'hst_dta'
                })),
                ui.br(),
                ui.br(),
                ui.h5(
                    '...and here are the contents of ',
                    ui.code(
                        "sb_rvs['historical_data']().get(input.selected_hd_id)" +
                        ".get('hst_dta')"
                    ),
                    ", rendered as a data table output:"
                )
            )

    # Create a ShinyBroker app with the new ui and server
    app = sb.sb_app(
        shdss_ui,
        shdss_server,
        host='127.0.0.1',
        port=7497,
        client_id=10742
    )

    app.run()