Provider

A provider defines how to fetch your source data (ticks or candles).

The provider generate method feed data to the estrade.Market object (that will dispatch it to candle sets, indicators, strategies etc.)

Parameters

Name Type Description Default
start_date datetime datetime.datetime start_date: optional start date None
end_date datetime datetime.datetime end_date: optional end date None
requires_login bool set to True if your provider requires login before market run. False
trade_class TradeClassMixin trade class used to open/close trades, if you do not want to override the default trade class, leave this to the default None value. None

Note

if you use the requires_login, you have to implement a login method.

close_trade(self, trade, quantity)

Show source code in estrade/provider.py
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
    def close_trade(self, trade: Trade, quantity: int) -> Trade:
        """
        For a remote provider, use this method to ask your provider to close a trade.

        Arguments:
            trade: trade to be closed
            quantity: quantity to close

        !!! tip

             - You can use the `trade.meta` property to store any necessary data
             for your provider.
             - In case of error it is recommended to raise a
             `estrade.exception.ProviderException`
        """
        return trade

For a remote provider, use this method to ask your provider to close a trade.

Parameters

Name Type Description Default
trade Trade trade to be closed required
quantity int quantity to close required

Tip

  • You can use the trade.meta property to store any necessary data for your provider.
  • In case of error it is recommended to raise a estrade.exception.ProviderException

generate(self)

Show source code in estrade/provider.py
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
    def generate(self) -> None:
        """
        This method must be implemented to fetch ticks or candles from provider.

        If your provider generates ticks, this method must send the tick
        to market calling `estrade.market.Market.on_new_tick` method.

        For most cases you want to run your provider in "Tick mode" meaning that
        your provider feed `estrade.Tick` toi the market.

        !!! example "Example of a provider generating ticks"

            ```python
            from estrade import Provider
            from estrade import Tick

            class MyProvider(Provider):

                def generate(self):
                    '''
                        This method parse all ticks from your database.
                        It assumes that your ticks holds the following attributes:
                        - epic code
                        - bid
                        - ask
                        - datetime
                    '''
                    # eg. query ticks in your database (ordered by datetime)
                    for tick in my_database:
                        # build a tick from your data
                        tick = Tick(
                            epic=self.market.get_epic(tick['epic_code']),
                            bid=tick['bid'],
                            ask=tick['ask'],
                            datetime['datetime'],
                        )
                    # dispatch tick to market
                    self.market.on_new_tick(tick)
            ```

        A provider can also be run in "Candle mode" meaning that the generate method
        feed `estrade.Candle` objects to the market.

        !!! warning
            Using candle mode is not recommended, it should be reserved to exceptional
            cases where you only have candle data.

            In addition, your your candle data must be timed (open, close, high and
            low must be timed).

        !!! example "example of a provider in candle mode"
            ```python
            from estrade import Provider
            from estrade import Candle, Tick

            class MyProvider(Provider):

                def generate(self):
                # eg. query candle in your database (ordered by datetime)
                for candle in my_database:
                    epic = self.market.get_epic(candle['epic_code'])
                    # build an open tick from your data
                    open = Tick(
                        epic=epic,
                        bid=candle['open_bid'],
                        ask=candle['open_ask'],
                        datetime=candle['open_datetime'],
                    )
                    high = Tick(
                        epic=epic,
                        bid=candle['high_bid'],
                        ask=candle['high_ask'],
                        datetime=candle['high_datetime'],
                    )
                    low = Tick(
                        epic=epic,
                        bid=candle['low_bid'],
                        ask=candle['low_ask'],
                        datetime=candle['low_datetime'],
                    )
                    close = Tick(
                        epic=epic,
                        bid=candle['close_bid'],
                        ask=candle['close_ask'],
                        datetime=candle['close_datetime'],
                    )
                    # build a candle with your ticks
                    candle = Candle(
                        timeframe=candle['timeframe'],
                        epic_ref=candle['epic_code'],
                        open_tick=open
                    )
                    # add high, low tick to candle
                    candle.on_new_tick(high)
                    candle.on_new_tick(low)
                    # finally add the close tick to candle
                    candle.on_new_tick(close)

                # dispatch candle to market
                self.market.on_new_candle(candle)
            ```
    """
        pass

This method must be implemented to fetch ticks or candles from provider.

If your provider generates ticks, this method must send the tick to market calling estrade.market.Market.on_new_tick method.

For most cases you want to run your provider in "Tick mode" meaning that your provider feed estrade.Tick toi the market.

Example of a provider generating ticks

from estrade import Provider
from estrade import Tick

class MyProvider(Provider):

    def generate(self):
        '''
            This method parse all ticks from your database.
            It assumes that your ticks holds the following attributes:
            - epic code
            - bid
            - ask
            - datetime
        '''
        # eg. query ticks in your database (ordered by datetime)
        for tick in my_database:
            # build a tick from your data
            tick = Tick(
                epic=self.market.get_epic(tick['epic_code']),
                bid=tick['bid'],
                ask=tick['ask'],
                datetime['datetime'],
            )
        # dispatch tick to market
        self.market.on_new_tick(tick)

A provider can also be run in "Candle mode" meaning that the generate method feed estrade.Candle objects to the market.

Warning

Using candle mode is not recommended, it should be reserved to exceptional cases where you only have candle data.

In addition, your your candle data must be timed (open, close, high and low must be timed).

example of a provider in candle mode

from estrade import Provider
from estrade import Candle, Tick

class MyProvider(Provider):

    def generate(self):
    # eg. query candle in your database (ordered by datetime)
    for candle in my_database:
        epic = self.market.get_epic(candle['epic_code'])
        # build an open tick from your data
        open = Tick(
            epic=epic,
            bid=candle['open_bid'],
            ask=candle['open_ask'],
            datetime=candle['open_datetime'],
        )
        high = Tick(
            epic=epic,
            bid=candle['high_bid'],
            ask=candle['high_ask'],
            datetime=candle['high_datetime'],
        )
        low = Tick(
            epic=epic,
            bid=candle['low_bid'],
            ask=candle['low_ask'],
            datetime=candle['low_datetime'],
        )
        close = Tick(
            epic=epic,
            bid=candle['close_bid'],
            ask=candle['close_ask'],
            datetime=candle['close_datetime'],
        )
        # build a candle with your ticks
        candle = Candle(
            timeframe=candle['timeframe'],
            epic_ref=candle['epic_code'],
            open_tick=open
        )
        # add high, low tick to candle
        candle.on_new_tick(high)
        candle.on_new_tick(low)
        # finally add the close tick to candle
        candle.on_new_tick(close)

    # dispatch candle to market
    self.market.on_new_candle(candle)

get_open_trades(self)

Show source code in estrade/provider.py
207
208
209
210
211
212
213
214
215
216
    def get_open_trades(self) -> List[Trade]:
        """
        Implement this method to fetch list of open trades from your provider.

        This method is called before market run to load existing opened trades.

        Returns:
            List of existing trades to load before Market run
        """
        return []

Implement this method to fetch list of open trades from your provider.

This method is called before market run to load existing opened trades.

Returns

Type Description
List[estrade.trade.Trade] List of existing trades to load before Market run

login(self)

Show source code in estrade/provider.py
218
219
220
221
222
223
224
225
226
227
    def login(self) -> bool:
        """
        This method must perform login process with your provider.

        Returns:
            - True if login to provider was successful successfully
            - False if login to provider failed

        """
        return True

This method must perform login process with your provider.

Returns

Type Description
bool - True if login to provider was successful successfully - False if login to provider failed

open_trade(self, trade)

Show source code in estrade/provider.py
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
    def open_trade(self, trade: Trade) -> Trade:
        """
        For a remote provider, use this method to ask your provider to create
        a new trade.

        Arguments:
            trade: trade to be opened

        !!! tip

            - You can use the `trade.meta` property to store any necessary data for
            your provider.
            - In case of error it is recommended to raise a
            `estrade.exception.ProviderException`

        """
        return trade

For a remote provider, use this method to ask your provider to create a new trade.

Parameters

Name Type Description Default
trade Trade trade to be opened required

Tip

  • You can use the trade.meta property to store any necessary data for your provider.
  • In case of error it is recommended to raise a estrade.exception.ProviderException

update_epic_status(self, epic_ref, tradeable_status)

Show source code in estrade/provider.py
229
230
231
232
233
234
235
236
237
238
239
    def update_epic_status(self, epic_ref: str, tradeable_status: bool) -> None:
        """
        This method allow to set epic as (not) tradeable.
        When an epic is not tradeable, no open/close trade will be attempted.

        Arguments:
            epic_ref: epic code
            tradeable_status: Is trading allowed on this epic
        """
        epic = self.market.get_epic(epic_ref)
        epic.tradeable = tradeable_status

This method allow to set epic as (not) tradeable. When an epic is not tradeable, no open/close trade will be attempted.

Parameters

Name Type Description Default
epic_ref str epic code required
tradeable_status bool Is trading allowed on this epic required

update_trade(self, *args, **kwargs)

Show source code in estrade/provider.py
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
    def update_trade(self, *args, **kwargs):
        """
        For a remote provider, use this method to update a trade in case your provider
        notifies an update.

        !!! example

            ```python
            from estrade import Provider


            class MyProvider(Provider):
                # ...
                def update_trade(self, remote_update):
                    # search for existing trade by its ref if your provider
                    # update contains it.
                    trade = self.market.trade_manager.get_trade_by_ref(
                        ref=remote_update['ref']
                    )
                    trade.set_stop(value=remote_update['stop'], relative=False)
                    return trade

                    # search in all existing trades if you stored reconciliation data
                    # in trades meta
                    for trade in self.market.trade_manager.trades:
                        if trade.meta['remote_id'] == remote_update['id']:
                            # update your trade
                            trade.set_stop(value=remote_update['stop'], relative=False)
                            return trade
            ```
        """

For a remote provider, use this method to update a trade in case your provider notifies an update.

Example

from estrade import Provider


class MyProvider(Provider):
    # ...
    def update_trade(self, remote_update):
        # search for existing trade by its ref if your provider
        # update contains it.
        trade = self.market.trade_manager.get_trade_by_ref(
            ref=remote_update['ref']
        )
        trade.set_stop(value=remote_update['stop'], relative=False)
        return trade

        # search in all existing trades if you stored reconciliation data
        # in trades meta
        for trade in self.market.trade_manager.trades:
            if trade.meta['remote_id'] == remote_update['id']:
                # update your trade
                trade.set_stop(value=remote_update['stop'], relative=False)
                return trade