%global _empty_manifest_terminate_build 0 Name: python-degiro-connector Version: 2.0.23 Release: 1 Summary: This is yet another library to access Degiro's API. License: BSD-3-Clause URL: https://github.com/chavithra/degiro-connector Source0: https://mirrors.nju.edu.cn/pypi/web/packages/59/28/98380ff9e3b8e873e7693a13276f0e3a694333dbd0dd7e19535f1c642301/degiro_connector-2.0.23.tar.gz BuildArch: noarch Requires: python3-grpcio Requires: python3-onetimepass Requires: python3-pandas Requires: python3-protobuf Requires: python3-requests Requires: python3-wrapt %description # 1. **Degiro Connector** This is yet another library to access Degiro's API. Notes : - Migration scripts are available : ```bash python -m degiro_connector.migration.from_0_1_3_to_1_0_0 python -m degiro_connector.migration.from_1_0_4_to_1_0_5 python -m degiro_connector.migration.from_1_0_10_to_2_0_0 python -m degiro_connector.migration.from_2_0_2_to_2_0_3 ``` - `GRPC` services are available to let you consume this library through other languages like Javascript, Java, Go, C++, Rust, etc : ```bash python -m examples.quotecast.relay_server python -m examples.trading.relay_server ``` ## 1.1. Which features ? Here are the features you can access through this library : |**Endpoint**|**Feature(s)**| |:-|:-| |AccountCashReport|Export cash movements in a specific format : CSV, HTML, PDF or XLS.| |AccountInfo|Retrieve a table containing : "clientId" and Currencies.| |AccountOverview|Retrieve all the cash movements between two dates.| |Agenda|Crucial events regarding products : Dividend, Economic, Earnings, Holiday, IPO or Split.| |Bonds
ETFs
Funds
Futures
Leverageds
Lookup
Options
Stocks
Warrants|Search list of products according their name, type and other criterias.
For instance all the stocks from NASDAQ 100.| |Chart|Retrieve chart data.| |ClientDetails|Retrieve a table containing : "clientId", "intAccount" and other account information.| |CompanyProfile|Retrieve a company's profile using its ISIN code.| |CompanyRatios|Retrieve a company's ratios using its ISIN code.| |Config|Retrieve a table containing : "clientId" and URLs which are constitutive of Degiro's API.| |EstimatesSummaries|Retrieve a company's estimates summaries using its ISIN code.| |FavouritesList|Add/Delete/Retrieve favourites lists.| |FavouritesListProducts|Add/Update favourites lists content.| |FinancialStatements|Retrieve a company's financial statements using its ISIN code.| |LatestNews|Retrieve latest news about all the companies.| |LoginQuotecast|Establish a connection for quotecast operations.| |LoginTrading|Establish a connection for trading operations.| |LogoutTrading|Destroy previously established connection for trading operations.| |NewsByCompany|Retrieve news related to a specific company.| |Order|Create, update, delete an Order.| |OrderHistory|Retrieve all Orders created between two dates.| |Orders|List pending Orders.| |Portfolio|List products in your Portfolio.| |ProductsConfig|Retrieve a table containing : useful parameters to filter products.| |ProductsInfo|Search for products using their ids.| |Quotecasts|Fetch real-time data on financial products.
For instance the real-time stock Price.| |TopNewsPreview|Retrieve some news preview about all the companies.| |TotalPorfolio|Retrieve aggregated information about your assets.| |TransactionsHistory|Retrieve all Transactions created between two dates.| ## 1.2. How to install ? ```bash pip install degiro-connector ``` ## 1.3. How to upgrade ? ```bash pip install --no-cache-dir --upgrade degiro-connector ``` ## 1.4. How to uninstall ? ```bash pip uninstall degiro-connector ``` ## 1.5. Table of contents - [1. **Degiro Connector**](#1-degiro-connector) * [1.1. Which features ?](#11-which-features-) * [1.2. How to install ?](#12-how-to-install-) * [1.3. How to upgrade ?](#13-how-to-upgrade-) * [1.4. How to uninstall ?](#14-how-to-uninstall-) * [1.5. Table of contents](#15-table-of-contents) - [2. Real-time data](#2-real-time-data) * [2.1. What are the workflows ?](#21-what-are-the-workflows-) * [2.2. What are the credentials ?](#22-what-are-the-credentials-) * [2.3. How to find your : user_token ?](#23-how-to-find-your--user_token-) * [2.4. How to login ?](#24-how-to-login-) * [2.5. Is there a timeout ?](#25-is-there-a-timeout-) * [2.6. How to subscribe to a data-stream ?](#26-how-to-subscribe-to-a-data-stream-) * [2.7. How to unsubscribe to a data-stream ?](#27-how-to-unsubscribe-to-a-data-stream-) * [2.8. How to fetch the data ?](#28-how-to-fetch-the-data-) * [2.9. How to use this data ?](#29-how-to-use-this-data-) * [2.10. Which are the available data types ?](#210-which-are-the-available-data-types-) * [2.11. What is a Ticker ?](#211-what-is-a-ticker-) * [2.12. What is inside the Dictionary ?](#212-what-is-inside-the-dictionary-) * [2.13. What is inside the DataFrame ?](#213-what-is-inside-the-dataframe-) * [2.14. How to get chart data ?](#214-how-to-get-chart-data-) * [2.15. How to find a : vwd_id ?](#215-how-to-find-a--vwd_id-) - [3. Trading connection](#3-trading-connection) * [3.1. How to login ?](#31-how-to-login-) * [3.2. How to logout ?](#32-how-to-logout-) * [3.3. What are the credentials ?](#33-what-are-the-credentials-) * [3.4. How to find your : int_account ?](#34-how-to-find-your--int_account-) * [3.5. How to use 2FA ?](#35-how-to-use-2fa-) * [3.6. How to find your : totp_secret_key ?](#36-how-to-find-your--totp_secret_key-) * [3.7. How to find your : one_time_password ?](#37-how-to-find-your--one_time_password-) * [3.8. Is there a timeout ?](#38-is-there-a-timeout-) * [3.9. How to manage : TimeoutError ?](#39-how-to-manage--TimeoutError-) - [4. Order](#4-order) * [4.1. How to create an Order ?](#41-how-to-create-an-order-) * [4.1.1. Check Order](#411-check-order) * [4.1.2. Confirm Order](#412-confirm-order) * [4.2. How to update an Order ?](#42-how-to-update-an-order-) * [4.3. How to delete an Order ?](#43-how-to-delete-an-order-) - [5. Portfolio](#5-portfolio) * [5.1. How to retrieve pending Orders ?](#51-how-to-retrieve-pending-orders-) * [5.2. How to get the Portfolio ?](#52-how-to-get-the-portfolio-) * [5.3. How to get the TotalPortfolio ?](#53-how-to-get-the-totalportfolio-) * [5.4. How to retrieve the OrdersHistory ?](#54-how-to-retrieve-the-ordershistory-) * [5.5. How to retrieve the TransactionsHistory ?](#55-how-to-retrieve-the-transactionshistory-) - [6. Account](#6-account) * [6.1. How to retrieve the table : Config ?](#61-how-to-retrieve-the-table--config-) * [6.2. How to retrieve the table : ClientDetails ?](#62-how-to-retrieve-the-table--clientdetails-) * [6.3. How to retrieve the table : AccountInfo ?](#63-how-to-retrieve-the-table--accountinfo-) * [6.4. How to get the table : AccountOverview ?](#64-how-to-get-the-table--accountoverview-) * [6.5. How to export the table : CashAccountReport ?](#65-how-to-export-the-table--cashaccountreport-) * [6.6. How to export the table : PositionReport ?](#66-how-to-export-the-table--positionreport-) - [7. Products](#7-products) * [7.1. How to get the table : ProductsConfig ?](#71-how-to-get-the-table--productsconfig-) * [7.2. How to get my favourite products ?](#72-how-to-get-my-favourite-products-) * [7.3. How to lookup products (search by name) ?](#73-how-to-lookup-products-search-by-name-) * [7.4. How to search bonds ?](#74-how-to-search-bonds-) * [7.5. How to search etfs ?](#75-how-to-search-etfs-) * [7.6. How to search funds ?](#76-how-to-search-funds-) * [7.7. How to search futures ?](#77-how-to-search-futures-) * [7.8. How to search leverageds ?](#78-how-to-search-leverageds-) * [7.9. How to search options ?](#79-how-to-search-options-) * [7.10. How to search stocks ?](#710-how-to-search-stocks-) * [7.11. How to search warrants ?](#711-how-to-search-warrants-) * [7.12. How to search products from ids ?](#712-how-to-search-products-from-ids-) * [7.13. How to create a favourite list ?](#713-how-to-create-a-favourite-list-) * [7.14. How to delete a favourite list ?](#714-how-to-delete-a-favourite-list-) * [7.15. How to put favourite list products ?](#715-how-to-put-favourite-list-products-) * [7.16. How to delete favourite list products ?](#716-how-to-delete-favourite-list-products-) - [8. Companies](#8-companies) * [8.1. How to get : CompanyProfile ?](#81-how-to-get--companyprofile-) * [8.2. How to get : CompanyRatios ?](#82-how-to-get--companyratios-) * [8.3. How to get : FinancialStatements ?](#83-how-to-get--financialstatements-) * [8.4. How to get : LatestNews ?](#84-how-to-get--latestnews-) * [8.5. How to get : TopNewsPreview ?](#85-how-to-get--topnewspreview-) * [8.6. How to get : NewsByCompany ?](#86-how-to-get--newsbycompany-) * [8.7. How to get : Agenda ?](#87-how-to-get--agenda-) * [8.8. How to get : EstimatesSummaries ?](#88-how-to-get--estimatessummaries-) - [9. Contributing](#9-contributing) - [10. License](#10-license) # 2. Real-time data It is possible to fetch a stream of data in real-time from Degiro's API. For instance if one needs the following data from the "AAPL" stock : * LastDate * LastTime * LastPrice * LastVolume You can use this library to retrieve updates like this : LastDate LastTime LastPrice LastVolume 2020-11-13 22:00:00 119.26 4697040 For a list of available metrics, see the example in [section 2.6](#26-how-to-subscribe-to-a-data-stream-). ## 2.1. What are the workflows ? This is the workflow for consuming real-time data-stream : A. Find your "user_token". B. Setup the API object with your "user_token". C. Connect. D. Subscribe to data-stream. E. Fetch data-stream. This is the worflow for consuming charts : A. Find your "user_token". B. Setup the API object with your "user_token". C. Fetch charts. All the details of these steps are explained in the rest of this section. ## 2.2. What are the credentials ? The only credential you need in order to fetch real-time data and charts is the : * user_token Beware, these two identifiers are not the same thing : * user_token : used to fetch real-time data and charts. * int_account : used for some trading operations. ## 2.3. How to find your : user_token ? You can find your "user_token" inside one of these tables : * "Config" : attribute "clientId" * "ClientDetails" : attribute "id" See sections related to ["Config"](#61-how-to-retrieve-the-table--config-) and ["ClientDetails"](#62-how-to-retrieve-the-table--clientdetails-) tables. ## 2.4. How to login ? In order to fetch data you need to establish a connection. You can use the following code to connect : ```python # SETUP QUOTECAST API quotecast_api = API(user_token=YOUR_USER_TOKEN) # CONNECTION quotecast_api.connect() ``` ## 2.5. Is there a timeout ? Connection timeout is around 15 seconds. Which means a connection will cease to work after this timeout. This timeout is reset each time you use this connection to : * Subscribe to a metric (for instance a stock Price) * Fetch the data-stream So if you use it nonstop (in a loop) you won't need to reconnect. ## 2.6. How to subscribe to a data-stream ? To subscribe to a data-stream you need to setup a Request message. A Request has the following parameters : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |subscriptions|MessageMap|List of products and metrics to subscribe to.| |unsubscriptions|MessageMap|List of products and metrics to unsubscribe to.| Here is an example of a request : ```python request = Quotecast.Request() request.subscriptions['360015751'].extend([ 'LastDate', 'LastTime', 'LastPrice', 'LastVolume', 'AskPrice', 'AskVolume', 'LowPrice', 'HighPrice', 'BidPrice', 'BidVolume' ]) request.subscriptions['AAPL.BATS,E'].extend([ 'LastDate', 'LastTime', 'LastPrice', 'LastVolume', 'AskPrice', 'AskVolume', 'LowPrice', 'HighPrice', 'BidPrice', 'BidVolume' ]) ``` In this example these are the `vwd_id` of the products from which you want `Real-time data` : - 360015751 - AAPL.BATS,E See the [section](#215-how-to-find-a--vwd_id-) related to `vwd_id` for more information. Once you have built this Request object you can send it to Degiro's API like this : ```python quotecast_api.subscribe(request=request) ``` For more comprehensive examples : [realtime_poller.py](examples/quotecast/realtime_poller.py) / [realtime_one_shot.py](examples/quotecast/realtime_one_shot.py) ## 2.7. How to unsubscribe to a data-stream ? To remove metrics from the data-stream you need to setup a Request message. If you try to unsubscribe to a metric to which you didn't subscribed previously it will most likely have no impact. A Request has the following parameters : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |subscriptions|MessageMap|List of products and metrics to subscribe to.| |unsubscriptions|MessageMap|List of products and metrics to unsubscribe to.| Here is an example of a request : ```python request = Quotecast.Request() request.unsubscriptions['360015751'].extend([ 'LastDate', 'LastTime', 'LastPrice', 'LastVolume', 'AskPrice', 'AskVolume', 'LowPrice', 'HighPrice', 'BidPrice', 'BidVolume' ]) request.unsubscriptions['AAPL.BATS,E'].extend([ 'LastDate', 'LastTime', 'LastPrice', 'LastVolume', 'AskPrice', 'AskVolume', 'LowPrice', 'HighPrice', 'BidPrice', 'BidVolume' ]) ``` Once you have built this Request object you can send it to Degiro's API like this : ```python quotecast_api.subscribe(request=request) ``` For more comprehensive examples : [realtime_poller.py](examples/quotecast/realtime_poller.py) / [realtime_one_shot.py](examples/quotecast/realtime_one_shot.py) ## 2.8. How to fetch the data ? You can use the following code : ```python quotecast = quotecast_api.fetch_data() ``` For a more comprehensive example : [realtime_poller.py](examples/quotecast/realtime_poller.py) ## 2.9. How to use this data ? Received data is a `Quotecast` object with the following properties : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |json_data|dict|Dictionary representation of what Degiro's API has sent.| |metadata|Metadata|Containing the "response_datetime" and "request_duration".| Here is how to access these properties : ```python json_data = quotecast.json_data response_datetime = quotecast.metadata.response_datetime request_duration= quotecast.metadata.request_duration ``` Notes: * The API sometimes might return an empty Quotecast object. * The API often returns a subset of the requested metrics, e.g. only `'LastPrice'`. Please take this into account when appending consecutive data responses. ## 2.10. Which are the available data types ? This library provides the tools to convert Degiro's JSON data into something more programmer-friendly. Here is the list of available data types : |**Type**|**Description**| |:-|:-| |Ticker|Protobuf message (for GRPC).| |Dictionaries|Standard Python Dictionaries : **dict**.| |DataFrame|DataFrame from the library Pandas.| Here is how to build each type : ```python # UPDATE PARSER quotecast_parser.put_quotecast(quotecast=quotecast) # BUILD TICKER ticker = quotecast_parser.ticker # BUILD DICT ticker_dict = quotecast_parser.ticker_dict # BUILD PANDAS.DATAFRAME ticker_df = quotecast_parser.ticker_df ``` ## 2.11. What is a Ticker ? The generated Ticker contains : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |metadata|Metadata|Containing the "response_datetime" and "request_duration".| |products|MessageMap|Dictionary like object containing the metrics group by "vwd_id".| |product_list|RepeatedScalarFieldContainer|List of available "vwd_id".| Here are some operations available : ```python product = '360015751' metric_name = 'LastPrice' # ACCESS SPECIFIC PRODUCT product = ticker.products[product] # ACCESS SPECIFIC METRIC metric = product[metric_name] # LOOP OVER PRODUCTS for product in ticker.products: product = ticker.products[product] # LOOP OVER METRICS for metric_name in product.metrics: metric = product.metrics[metric_name] ``` A Ticker is a custom Protocol Buffer Message built for this library. It can be transmitted over GRPC framework. ## 2.12. What is inside the Dictionary ? The dictionary representation of a ticker contains the metrics grouped by "vwd_id" (product id), with : * keys : vwd_id * values : another dictionary with the metrics concerning this specific product. Example - Dictionary : ```python { '360114899': { 'vwd_id': 360114899, 'response_datetime': '2020-11-08 12:00:27', 'request_duration': 1.0224891666870117, 'LastDate': '2020-11-06', 'LastTime': '17:36:17', 'LastPrice': '70.0', 'LastVolume': '100' }, '360015751': { 'vwd_id': 360015751, 'response_datetime': '2020-11-08 12:00:27', 'request_duration': 1.0224891666870117, 'LastDate': '2020-11-06', 'LastTime': '17:36:17', 'LastPrice': '22.99', 'LastVolume': '470' } } ``` ## 2.13. What is inside the DataFrame ? In addition to whatever metrics you have chosen to subscribe to (see the example in [section 2.6](#26-how-to-subscribe-to-a-data-stream-)), the DataFrame will contain the following columns : |**Column**|**Description**| |:-|:-| |vwd_id|Product identifier, for instance "AAPL.BATS,E" for APPLE stock.| |response_datetime|Datetime at which the data was received.| |request_duration|Duration of the request used to fetch the data.| Example - DataFrame : vwd_id response_datetime request_duration LastDate LastTime LastPrice LastVolume 0 360114899 2020-11-08 12:00:27 1.022489 2020-11-06 17:39:57 70.0 100 1 360015751 2020-11-08 12:00:27 1.022489 2020-11-06 17:36:17 22.99 470 ## 2.14. How to get chart data ? You can fetch an object containing the same data than in Degiro's website graph. For that you need to prepare a Chart.Request object. Here is a table with the available attributes for Chart.Request. |**Parameter**|**Type**|**Description**| |:-|:-|:-| |requestid|str|It sends you back whatever string you put here, you can set it to : "1".| |resolution|Chart.Resolution|Resolution of the chart like : Chart.Resolution.PT1M.| |culture|str|Country code like : "en-US" or "fr-FR".| |period|Chart.Period|Period of the chart, like : Chart.Period.P1D.| |series|repeated string|Data to get like : ['issueid:36014897', 'price:issueid:360148977'].| |tz|str|Timezone like : "Europe/Paris"| Example of code : ```python request = Chart.Request() request.culture = "fr-FR" request.period = Chart.Interval.PT1H request.requestid = "1" request.resolution = Chart.Interval.P1D # request.series.append("issueid:360148977") # request.series.append("price:issueid:360148977") request.series.append("ohlc:issueid:360148977") # request.series.append("volume:issueid:360148977") # request.series.append("vwdkey:AAPL.BATS,E") # request.series.append("price:vwdkey:AAPL.BATS,E") # request.series.append("ohlc:vwdkey:AAPL.BATS,E") # request.series.append("volume:vwdkey:AAPL.BATS,E") request.tz = "Europe/Paris" # FETCH DATA chart = quotecast_api.get_chart( request=request, override={ "resolution": "P1D", "period": "P1W", }, raw=True, ) ``` The `issueid` parameter is the `vwd_id` of the product from which you want the `Chart` data. See the section related to `vwd_id` for more information. All the options for the enumerations are available in this file : [quotecast.proto](protos/degiro_connector/quotecast/models/quotecast.proto) For a more comprehensive examples : - [chart.py](examples/quotecast/chart.py) - [chart_format.py](examples/quotecast/chart_format.py) ## 2.15. How to find a : vwd_id ? In operations related to `Quotecast`, Degiro uses the `vwd_id` to identify a product. Which means that if you want a `Chart` or `Real-time data` for a specific product : you first need to find this product's `vwd_id`. This two identifiers are not the same : |**Identifier**|**API name(s)**|**Description**| |:-|:-|:-| |id|str|Id used identify a product in `Trading` related endpoints.| |vwd_id|issueid
vwdId
vwdIdSecondary
|Id used identify a product in `Quotecast` (`Chart` and `Real-time data`) related endpoint.| Here are some methods you can use to fetch a product's `vwd_id` : - `product_search` - `get_products_info` The method `product_search` let you use the name or other attributes of a product to fetch it's `vwd_id`. The method `get_products_info` let you use a product's `id` to fetch it's `vwd_id`. # 3. Trading connection This library is divided into two modules : - quotecast : to consume real-time financial data. - trading : to manage your Degiro's account. The module **quotecast** is described in the section related to real-time data. The rest of this document will only refer to the module : **trading**. ## 3.1. How to login ? In order to use the module **trading.api** you need to establish a connection. Check the section related to **int_account** to understand how to get yours. Here is how to connect : ```python # SETUP CREDENTIALS credentials = Credentials( username = YOUR_USERNAME, password = YOUR_PASSWORD, int_account = YOUR_INT_ACCOUNT, # OPTIONAL FOR LOGIN ) # SETUP TRADING API trading_api = API(credentials=credentials) # ESTABLISH CONNECTION trading_api.connect() ``` For a more comprehensive example : [connection.py](examples/trading/connection.py) ## 3.2. How to logout ? Once you no longer need to use the API you can destroy your connection. You can use the following code to disconnect : ```python # DESTROY CONNECTION trading_api.logout() ``` For a more comprehensive example : [logout.py](examples/trading/logout.py) ## 3.3. What are the credentials ? Some credentials are required to use Degiro's trading API. Here are these credentials : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |username|str|Username used to log into Degiro's website.| |password|str|Password used to log into Degiro's website.| |int_account|int|OPTIONAL : unique identifier of the account : used by Degiro's server.| |totp_secret_key|str|OPTIONAL : used for Two-factor Authentication (2FA).| |one_time_password|str|OPTIONAL : used for Two-factor Authentication (2FA).| Check the section related to **int_account** to understand how to get yours. Check the section related to **2FA** if you want to know more about these two parameters : - **totp_secret_key** - **one_time_password** ## 3.4. How to find your : int_account ? To get your **int_acccount** you can run this example : [client_details_table.py](examples/trading/client_details_table.py) See section related to **ClientDetails** table for more details. This **int_acccount** is required to do most of the trading operations available in this connector. Here are some operations for which your **int_acccount** is not required : - Connection - Fetch table : ClientDetails - Fetch table : Config Beware, these two identifiers are not the same thing : - user_token : used to fetch real-time data and charts. - int_account : used for some trading operations. ## 3.5. How to use 2FA ? First I will briefly explain what is : **Two-Factor Authentication (2FA)**. I recommend to skip a few paragraphs if you already know what is **2FA**. In a standard connection you are providing two parameters: - username - password If you use **Two-Factor Authentication (2FA)** you need an extra parameter: - one_time_password This **one_time_password** has a validity of 30 secondes and is generated using a **totp_secret_key** code. Usually you use an app like **‎Google Authenticator** to store this **totp_secret_key** and generate the **one_time_password**. The **totp_secret_key** is stored inside the QRCode which is displayed when you enable 2FA on Degiro's website To use **2FA** with this library you have two solutions. **SOLUTION 1** Provide your **totp_secret_key** : the library will use it to generate a new **one_time_password** at each connection. So you won't have to type your **one_time_password** manually at each connection. This is the proper way. See the section about **totp_secret_key** to understand how to get yours. Here is an example of connection with the **totp_secret_key** : ```python # SETUP CREDENTIALS credentials = Credentials( username=YOUR_USERNAME, password=YOUR_PASSWORD, int_account=YOUR_INT_ACCOUNT, # OPTIONAL FOR LOGIN totp_secret_key=YOUR_2FA_SECRET_KEY, # ONLY IF 2FA IS ENABLED ) # SETUP TRADING API trading_api = API(credentials=credentials) # ESTABLISH CONNECTION trading_api.connect() ``` A complete example here : [connection_2fa.py](examples/trading/connection_2fa.py) **SOLUTION 2** Provide a new **one_time_password** at each connection. Here is an example of connection with the **one_time_password** : ```python # SETUP CREDENTIALS credentials = Credentials( username=YOUR_USERNAME, password=YOUR_PASSWORD, int_account=YOUR_INT_ACCOUNT, # OPTIONAL FOR LOGIN one_time_password=YOUR_2FA_OTP, # ONLY IF 2FA IS ENABLED ) # SETUP TRADING API trading_api = API(credentials=credentials) # ESTABLISH CONNECTION trading_api.connect() ``` A complete example here : [connection_otp.py](examples/trading/connection_otp.py) ## 3.6. How to find your : totp_secret_key ? The parameter **totp_secret_key** is only required if you have enabled `2FA` on Degiro's website. When you try to activate `2FA` on Degiro's website, it displays a `QRCode`. This `QRCode` changes at each activation. A `QRCode` is a picture which can be converted into a text. You can download this `QRCode` and use a tool to extract the text from it. This extracted text will look like this : otpauth://totp/DEGIRO:YOUR_USERNAME?algorithm=SHA1&issuer=DEGIRO&secret=YOUR_TOPT_SECRET_KEY&digits=6&period=30 Has you can guess the "totp_secret_key" is in this part : secret=YOUR_TOPT_SECRET_KEY Here is an example of script that extracts the text from a `QRCode` : [qrcode.py](examples/trading/qrcode.py) ## 3.7. How to find your : one_time_password ? The parameter **one_time_password** is the password you type when you log in the website using **2FA**. Usually you get it through an app like **Google Authenticator**. It is preferable to use the parameter **totp_secret_key** instead of **one_time_password**. ## 3.8. Is there a timeout ? A connection for trading operations has a timeout of 30 minutes. It's [defined](https://github.com/Chavithra/degiro-connector/blob/main/degiro_connector/core/constants/timeouts.py#L2) in seconds as constant `timeouts.TRADING_TIMEOUT`. The timeout period is started when the [`TradingAPI.connect()`](#31-how-to-login-) results successfully. Every time an operation is made to this `TradingAPI` connection, the timeout for this connection will be reset. If a `TradingAPI` connection is left unused during the timeout period, the connection will expire. Every consecutive function call to the `TraderAPI` will then throw a `TimeoutError` exception. A connection timeout might occur when your trading strategy only performs a few trades per day, e.g. once per hour. So when finally a buy opportuntiy occurs, [`check_order()`](#411-check-order): ```python # FETCH CHECKING_RESPONSE checking_response = trading_api.check_order(order=order) ``` Will fail with `TimeoutError`: ``` TimeoutError: Connection has probably expired. ``` ## 3.9. How to manage : TimeoutError ? **HANDLE EXCEPTION** It's recommended to catch the `TimeoutError` on every function call to the `TradingAPI`. When it's detected, it's sufficient to call [`connect()`](#31-how-to-login-) again, followed by repeating the original call that threw the exception. Example for the [`check_order()`](#411-check-order) call: ```python try: checking_response = trading_api.check_order(order=order) except TimeoutError: logging.warning("TradingAPI session did timeout, reconnecting for new session ID...") trading_api.connect() checking_response = trading_api.check_order(order=order) ``` This shows the following in the log, while the order is checked successfully after a successful reconnect: ```python WARNING - TradingAPI session did timeout, reconnecting for new session ID... INFO - get_session_id:response_dict: {'isPassCodeEnabled': False, 'locale': 'nl_NL', 'redirectUrl': 'https://trader.degiro.nl/trader/', 'sessionId': '2BADBBEF3****', 'status': 0, 'statusText': 'success'} INFO - confirmation_id: "053df7cf-****" response_datetime { seconds: 1643801134 nanos: 715765000 } ``` **REFRESH TIMEOUT** As mentioned before, the timeout will be reset after each call to the `TradingAPI`. This provides the opportunity to make a periodic function call, for example every 10 minutes to [`get_update()`](#51-how-to-retrieve-pending-orders-). However, this might interfere with your other logic and might not be robust over time when DeGiro decides to decrease the timeout on their server. Therefor it's strongly recommended to always incorporate the exception handling for `TimeoutError` as indicated in the example above. **CHANGE PERIOD** It's possible to change the timeout period while creating the `TradingAPI`. Just add a `ModelConnection` object for parameter `connection_storage`: ```python # SETUP TRADING API trading_api = TradingAPI( credentials=credentials, connection_storage=ModelConnection( timeout=600, ) ) # Connect: trading_api.connect() ``` The connection will now expire after 10 minutes (10 * 60 s). # 4. Order Creating and updating of orders is done with an `Order` object. Here are the parameters: |**Parameter**|**Type**|**Description**| |:-|:-|:-| |id|str|Optional for [`update_order()`](#42-how-to-update-an-order-). It's the `order_id` of the created `Order` as returned by [`confirm_order()`](#412-confirm-order).| |action|`Order.Action`|Whether you want to : `BUY` or `SELL`.| |order_type|`Order.OrderType`|Type of order : `LIMIT`, `STOP_LIMIT`, `MARKET` or `STOP_LOSS`.| |price|float|Limit price of the order.
Optional for the following `order_type` : `LIMIT` and `STOPLIMIT`.| |product_id|int|Identifier of the product concerned by the order.| |size|float|Size of the order.| |stop_price|float|Stop price of the order.
Optional for the following `order_type` : `STOPLIMIT` and `STOPLOSS`| |time_type|`Order.TimeType`|Duration of the order : `GOOD_TILL_DAY` or `GOOD_TILL_CANCELED`| The full description of an `Order` is available here : [trading.proto](protos/degiro_connector/trading/models/trading.proto) ## 4.1. How to create an Order ? The order creation is done in two steps : 1. Checking : send the `Order` to the API to check if it is valid. 2. Confirmation : confirm the creation of the `Order`. Keeping these two steps (instead of reducing to one single "create" function) provides more options. ## 4.1.1 Check order Use the `check_order()` function of the Trading API: ### **Request parameters** |**Parameter**|**Type**|**Description**| |:-|:-|:-| |order|`Order`|The order to create with all necessary [parameters](#4-order).| ### **Response parameters** On a succesfull request, a `dict` with the following parameters is returned: |**Parameter**|**Type**|**Description**| |:-|:-|:-| |confirmation_id|str|Id necessary to confirm the creation of the Order by the [`confirm_order()`](#412-confirm-order) function.| |response_datetime|[`Timestamp`](https://pythonhosted.org/gax-google-pubsub-v1/google.protobuf.timestamp_pb2.html)|A `Timestamp` represents a point in time independent of any time zone or calendar, represented as seconds (`seconds`) and fractions of seconds at nanosecond resolution (`nanos`) in UTC Epoch time. A `Timestamp` can be converted to a RFC 3339 date string by using `ToJsonString()`.
Note: This `Timestamp` is created by Degiro Connector on reception of the API response, not by DeGiro server.| |free_space_new|float|New free space (balance) if the Order is confirmed.| |transaction_fees|float|Transaction fees that will be applied to the Order.| |show_ex_ante_report_link|bool|?| When the request fails, `None` is returned. ## 4.1.2 Confirm order Use the `confirm_order()` function of the Trading API: ### **Request parameters** |**Parameter**|**Type**|**Description**| |:-|:-|:-| |confirmation_id|str|The confirmtation id from the [`check_order()`](#411-check-order) response.| |order|`Order`|The same order from the [`check_order()`](#411-check-order) request.| ### **Response parameters** On a succesfull request, a `dict` with the following parameters is returned: |**Parameter**|**Type**|**Description**| |:-|:-|:-| |order_id|str|A unique id of the accepted order. This id is required to [update](#42-how-to-update-an-order-) or [delete](#43-how-to-delete-an-order-) the pending order.| |response_datetime|[`Timestamp`](https://pythonhosted.org/gax-google-pubsub-v1/google.protobuf.timestamp_pb2.html)|A `Timestamp` represents a point in time independent of any time zone or calendar, represented as seconds (`seconds`) and fractions of seconds at nanosecond resolution (`nanos`) in UTC Epoch time. A `Timestamp` can be converted to a RFC 3339 date string by using `ToJsonString()`.
Note: This `Timestamp` is created by Degiro Connector on reception of the API response, not by DeGiro server.| When the request fails, `None` is returned. ## 4.1.3 Example of combining these functions ```python # SETUP ORDER order = Order( action=Order.Action.BUY, order_type=Order.OrderType.LIMIT, price=10, product_id=71981, size=1, time_type=Order.TimeType.GOOD_TILL_DAY, ) # FETCH CHECKING_RESPONSE checking_response = trading_api.check_order(order=order) # EXTRACT CONFIRMATION_ID confirmation_id = checking_response.confirmation_id # SEND CONFIRMATION confirmation_response = trading_api.confirm_order( confirmation_id=confirmation_id, order=order, ) ``` For a more comprehensive example : [order.py](examples/trading/order.py) ## 4.2. How to update an Order ? To modify a specific Order, you need to set it up with the `order_id` from the [`confirm_order()`](#412-confirm-order) response and use the `update_order()` function of the Trading API: ### **Request parameters** |**Parameter**|**Type**|**Description**| |:-|:-|:-| |order|`Order`|The order to update with all necessary [parameters](#4-order), including `id` as returned by [`confirm_order()`](#412-confirm-order).| ### **Response parameters** On a succesfull request, a `bool` with the value `True` is returned. When the request fails, `None` is returned. A valid reason is that the pending order has been already executed on the exchange, and this `order_id` no longer exists. Here is an example: ```python # ORDER SETUP order = Order( id=YOUR_ORDER_ID, # `order_id` from `confirm_order()` response action=Order.Action.BUY, order_type=Order.OrderType.LIMIT, price=10.60, product_id=71981, size=1, time_type=Order.TimeType.GOOD_TILL_DAY, ) # UPDATE ORDER succcess = trading_api.update_order(order=order) ``` ## 4.3. How to delete an Order ? To delete a specific Order you just need the `order_id` from the [`confirm_order()`](#412-confirm-order) response and use the `delete_order()` function of the Trading API: ### **Request parameters** |**Parameter**|**Type**|**Description**| |:-|:-|:-| |order_id|str|The unique id of the accepted order as returned by [`confirm_order()`](#412-confirm-order).| ### **Response parameters** On a succesfull request, a `bool` with the value `True` is returned. When the request fails, `None` is returned. A valid reason is that the pending order has been already executed on the exchange, and this `order_id` no longer exists. Here is an example: ```python # DELETE ORDER succcess = trading_api.delete_order(order_id=YOUR_ORDER_ID) # `order_id` from `confirm_order()` response ``` # 5. Portfolio ## 5.1. How to retrieve pending Orders ? This is how to get the list of Orders currently created but not yet executed or deleted : ```python request_list = Update.RequestList() request_list.values.extend([ Update.Request(option=Update.Option.ORDERS, last_updated=0), ]) update = trading_api.get_update(request_list=request_list) update_dict = pb_handler.message_to_dict(message=update) orders_df = pd.DataFrame(update_dict['orders']['values']) ``` Example : Orders product_id time_type price size id ... action order_type stop_price retained_order sent_to_exchange 0 0 GOOD_TILL_DAY 2 3 202cb962-ac59-075b-964b-07152d234b70 ... BUY LIMIT 16 17 18 For a more comprehensive example : [update.py](examples/trading/update.py) ## 5.2. How to get the Portfolio ? This is how to list the stocks/products currently in the portfolio : ```python request_list = Update.RequestList() request_list.values.extend([ Update.Request(option=Update.Option.PORTFOLIO, last_updated=0), ]) update = trading_api.get_update(request_list=request_list) update_dict = pb_handler.message_to_dict(message=update) portfolio_df = pd.DataFrame(update_dict['portfolio']['values']) ``` For a more comprehensive example : [update.py](examples/trading/update.py) Note: In order to resolve product IDs to Human readable names, see [7.12. How to search products from ids ?](#712-how-to-search-products-from-ids-) ## 5.3. How to get the TotalPortfolio ? This is how to get aggregated data about the portfolio : ```python request_list = Update.RequestList() request_list.values.extend([ Update.Request(option=Update.Option.TOTALPORTFOLIO, last_updated=0), ]) update = trading_api.get_update(request_list=request_list) update_dict = pb_handler.message_to_dict(message=update) total_portfolio_df = pd.DataFrame(update_dict['total_portfolio']['values']) ``` Example : DataFrame degiroCash flatexCash totalCash totalDepositWithdrawal todayDepositWithdrawal ... reportNetliq reportOverallMargin reportTotalLongVal reportDeficit marginCallStatus 0 0 1 2 3 4 ... 16 17 18 19 NO_MARGIN_CALL For a more comprehensive example : [update.py](examples/trading/update.py) ## 5.4. How to retrieve the OrdersHistory ? This method returns data about passed orders between two dates. The result contains a list of "Orders" objects with the following attributes : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |created|str|RFC 3339 Datetime, example : "2020-10-06T20:07:18+02:00".| |orderId|str|MD5 HASH, example : "098f6bcd-4621-d373-cade-4e832627b4f6"| |productId|int|Id of the product example : 65156| |size|float|Size of the order, example : 10.0000| |price|float|Price of the order, example : 8.6800| |buysell|str|"B" or "S"| |orderTypeId|int|see 3.Order| |orderTimeTypeId|int|see 3.Order| |stopPrice|float|Price like : 0.0000| |totalTradedSize|int|-| |type|str|"CREATE", "DELETE" or "MODIFY"| |status|str|"CONFIRMED"| |last|str|RFC 3339 Datetime, example : "2020-10-06T20:07:18+02:00".| |isActive|bool|-| Here is how to get this data : ```python # SETUP REQUEST from_date = OrdersHistory.Request.Date(year=2020,month=11,day=15) to_date = OrdersHistory.Request.Date(year=2020,month=10,day=15) request = OrdersHistory.Request(from_date=from_date, to_date=to_date) # FETCH DATA orders_history = trading_api.get_orders_history(request=request) ``` For a more comprehensive example : [orders_history.py](examples/trading/orders_history.py) ## 5.5. How to retrieve the TransactionsHistory ? Here is how to get this data : ```python # SETUP REQUEST from_date = TransactionsHistory.Request.Date(year=2020,month=11,day=15) to_date = TransactionsHistory.Request.Date(year=2020,month=10,day=15) request = TransactionsHistory.Request(from_date=from_date, to_date=to_date) # FETCH DATA transactions_history = trading_api.get_transactions_history(request=request) ``` For a more comprehensive example : [transactions_history.py](examples/trading/transactions_history.py) # 6. Account ## 6.1. How to retrieve the table : Config ? The config table contains the following informations : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |sessionId|str|Current session id.| |clientId|int|Unique Degiro's Account identifier also called "userToken"| |tradingUrl|str|-| |paUrl|str|-| |reportingUrl|str|-| |paymentServiceUrl|str|-| |productSearchUrl|str|-| |dictionaryUrl|str|-| |productTypesUrl|str|-| |companiesServiceUrl|str|-| |i18nUrl|str|-| |vwdQuotecastServiceUrl|str|-| |vwdNewsUrl|str|-| |vwdGossipsUrl|str|-| |taskManagerUrl|str|-| |refinitivNewsUrl|str|-| |refinitivAgendaUrl|str|-| |refinitivCompanyProfileUrl|str|-| |refinitivCompanyRatiosUrl|str|-| |refinitivFinancialStatementsUrl|str|-| |refinitivClipsUrl|str|-| |landingPath|str|-| |betaLandingPath|str|-| |mobileLandingPath|str|-| |loginUrl|str|-| Here is how to get this table : ```python # FETCH DATA config_table = trading_api.get_config() # EXTRACT SOME DATA user_token = config_table['clientId'] session_id = config_table['sessionId'] ``` For a more comprehensive example : [config_table.py](examples/trading/config_table.py) ## 6.2. How to retrieve the table : ClientDetails ? The ClientDetails table contains information about the current Degiro Account. |**Parameter**|**Type**| |:-|:-| |id|int| |intAccount|int| |loggedInPersonId|int| |clientRole|str| |effectiveClientRole|str| |contractType|str| |username|str| |displayName|str| |email|str| |firstContact.firstName|str| |firstContact.lastName|str| |firstContact.displayName|str| |firstContact.nationality|str| |firstContact.gender|str| |firstContact.dateOfBirth|str| |firstContact.placeOfBirth|str| |firstContact.countryOfBirth|str| |address.streetAddress|str| |address.streetAddressNumber|str| |address.zip|str| |address.city|str| |address.country|str| |cellphoneNumber|str| |locale|str| |language|str| |culture|str| |bankAccount.bankAccountId|int| |bankAccount.bic|str| |bankAccount.iban|str| |bankAccount.status|str| |flatexBankAccount.bic|str| |flatexBankAccount.iban|str| |memberCode|str| |isWithdrawalAvailable|bool| |isAllocationAvailable|bool| |isIskClient|bool| |isCollectivePortfolio|bool| |isAmClientActive|bool| |canUpgrade|bool| Here is how to get this table : ```python # FETCH DATA client_details_table = trading_api.get_client_details() # EXTRACT SOME DATA int_account = client_details_table['data']['intAccount'] user_token = client_details_table['data']['id'] ``` For a more comprehensive example : [client_details_table.py](examples/trading/client_details_table.py) ## 6.3. How to retrieve the table : AccountInfo ? The AccountInfo table contains the following information about currencies. |**Parameter**|**Type**| |:-|:-| |clientId|int| |baseCurrency|str| |currencyPairs|dict| |marginType|str| |cashFunds|dict| |compensationCapping|float|-| Here is how to get this table : ```python account_info_table = trading_api.get_account_info() ``` For a more comprehensive example : [account_info_table.py](examples/trading/account_info_table.py) ## 6.4. How to get the table : AccountOverview ? It will provide a list of cash movements. Here is how to get this data : ```python # SETUP REQUEST from_date = AccountOverview.Request.Date(year=2020,month=11,day=15) to_date = AccountOverview.Request.Date(year=2020,month=10,day=15) request = AccountOverview.Request(from_date=from_date, to_date=to_date) # FETCH DATA account_overview = trading_api.get_account_overview(request=request) ``` For a more comprehensive example : [account_overview.py](examples/trading/account_overview.py) Each cash movement contains this kind of parameters : |**Parameter**|**Type**| |:-|:-| |date|str| |valueDate|str| |id|int| |orderId|str| |description|str| |productId|int| |currency|str| |change|float| |balance|dict| |unsettledCash|float| |total|float| ## 6.5. How to export the table : CashAccountReport ? It will export a list of cash movements in a specific format. Available formats : - CSV - HTML - PDF - XLS Here is how to get this content in `CSV` format : ```python # SETUP REQUEST from_date = CashAccountReport.Request.Date(year=2020,month=11,day=15) to_date = CashAccountReport.Request.Date(year=2020,month=10,day=15) request = CashAccountReport.Request( format=CashAccountReport.Format.CSV, country='FR', lang='fr', from_date=from_date, to_date=to_date, ) # FETCH DATA cash_account_report = trading_api.get_cash_account_report( request=request, raw=False, ) ``` Here are the available parameters for `CashAccountReport.Request` : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |format|CashAccountReport.Format|Wanted format :
`CSV`
`HTML`
`PDF`
`XLS`| |country|str|Country name, like : `FR`| |lang|int|Language, like : `fr`| |from_date|CashAccountReport.Request.Date|Events starting after this date.| |to_date|CashAccountReport.Request.Date|Events before this date.| Exact definitions of `CashAccountReport` and `CashAccountReport.Request` are in this file : [trading.proto](protos/degiro_connector/trading/models/trading.proto) For a more comprehensive example : [cash_account_report.py](examples/trading/cash_account_report.py) ## 6.6. How to export the table : PositionReport ? It will export a list of cash movements in a specific format. Available formats : - CSV - HTML - PDF - XLS Here is how to get this content in `CSV` format : ```python # SETUP REQUEST to_date = CashAccountReport.Request.Date(year=2020,month=10,day=15) request = CashAccountReport.Request( format=CashAccountReport.Format.CSV, country='FR', lang='fr', to_date=to_date, ) # FETCH DATA position_report = trading_api.get_position_report( request=request, raw=False, ) ``` Here are the available parameters for `PositionReport.Request` : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |format|PositionReport.Format|Wanted format :
`CSV`
`HTML`
`PDF`
`XLS`| |country|str|Country name, like : `FR`| |lang|int|Language, like : `fr`| |to_date|PositionReport.Request.Date|Events before this date.| Exact definitions of `PositionReport` and `PositionReport.Request` are in this file : [trading.proto](protos/degiro_connector/trading/models/trading.proto) For a more comprehensive example : [position_report.py](examples/trading/position_report.py) # 7. Products ## 7.1. How to get the table : ProductsConfig ? This table contains useful parameters to filter products. Here are the parameters which are inside this table : |**Parameter**|**Type**| |:-|:-| |stockCountries|list| |bondExchanges|list| |bondIssuerTypes|list| |eurexCountries|list| |futureExchanges|list| |optionExchanges|list| |combinationExchanges|list| |cfdExchanges|list| |exchanges|list| |indices|list| |regions|list| |countries|list| |productTypes|list| |etfFeeTypes|list| |investmentFundFeeTypes|list| |optionAggregateTypes|list| |leveragedAggregateTypes|list| |etfAggregateTypes|list| |investmentFundAggregateTypes|list| |lookupSortColumns|list| |stockSortColumns|list| |bondSortColumns|list| |cfdSortColumns|list| |etfSortColumns|list| |futureSortColumns|list| Here is how to get this data : ```python # FETCH DATA products_config = trading_api.get_products_config() ``` For a more comprehensive example : [products_config.py](examples/trading/products_config.py) ## 7.2. How to get my favourite products ? Here is how to get this data : ```python # FETCH DATA favourites_list = trading_api.get_favourites_list() ``` For a more comprehensive example : [favourites_list.py](examples/trading/favourites_list.py) ## 7.3. How to lookup products (search by name) ? Text research on a financial product. Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestLookup( search_text='APPLE', limit=10, offset=0, product_type_id=1, ) # FETCH DATA products_lookup = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_lookup.py](examples/trading/product_lookup.py) ## 7.4. How to search bonds ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestBonds( bond_issuer_type_id=0, bond_exchange_id=710, search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA bond_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.5. How to search etfs ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestETFs( popular_only=False, input_aggregate_types='', input_aggregate_values='', search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA etf_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.6. How to search funds ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestFunds( search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA fund_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.7. How to search futures ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestFutures( future_exchange_id=1, underlying_isin='FR0003500008', search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA fund_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.8. How to search leverageds ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestLeverageds( popular_only=False, input_aggregate_types='', input_aggregate_values='', search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA etf_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.9. How to search options ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestOptions( input_aggregate_types='', input_aggregate_values='', option_exchange_id=3, underlying_isin='FR0003500008', search_text='', offset=0, limit=100, require_total=True, sort_columns='expirationDate,strike', sort_types='asc,asc', ) # FETCH DATA option_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.10. How to search stocks ? It contains information about available stocks. Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestStocks( index_id=122001, # NASDAQ 100 exchange_id=663, # NASDAQ # You can either use `index_id` or `exchange id` # See which one to use in the `ProductsConfig` table is_in_us_green_list=True, stock_country_id=846, # US search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA stock_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.11. How to search warrants ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestWarrants( search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA warrant_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.12. How to search products from ids ? Here is how to get this data : ```python # SETUP REQUEST request = ProductsInfo.Request() request.products.extend([96008, 1153605, 5462588]) # FETCH DATA products_info = trading_api.get_products_info( request=request, raw=True, ) ``` For a more comprehensive example : [products_info.py](examples/trading/products_info.py) ## 7.13. How to create a favourite list ? Example : ```python favorite_list_id = trading_api.create_favourite_list(name="SOME_NAME") ``` For a more comprehensive example : [favourite_list_create.py](examples/trading/favourite_list_create.py) ## 7.14. How to delete a favourite list ? Example : ```python success = trading_api.delete_favourite_list(id=1234567) ``` For a more comprehensive example : [favourite_list_delete.py](examples/trading/favourite_list_delete.py) ## 7.15. How to put favourite list products ? Example : ```python success = trading_api.put_favourite_list_product( id=1234567, product_id=1234567, ) ``` For a more comprehensive example : [favourite_list_put_product.py](examples/trading/favourite_list_put_product.py) ## 7.16. How to delete favourite list products ? Example : ```python success = trading_api.delete_favourite_list_product( id=1234567, product_id=1234567, ) ``` For a more comprehensive example : [favourite_list_delete product.py](examples/trading/favourite_list_delete product.py) # 8. Companies ## 8.1. How to get : CompanyProfile ? Here is how to get this data : ```python # FETCH DATA company_profile = trading_api.get_company_profile( product_isin='FR0000131906', ) ``` For a more comprehensive example : [company_profile.py](examples/trading/company_profile.py) ## 8.2. How to get : CompanyRatios ? This table contains information about the company. Here are the parameters which are inside this table : |**Parameter**|**Type**| |:-|:-| |totalFloat|str| |sharesOut|str| |consRecommendationTrend|dict| |forecastData|dict| |currentRatios|dict| Here is how to get this data : ```python # FETCH DATA company_ratios = trading_api.get_company_ratios( product_isin='FR0000131906', ) ``` For a more comprehensive example : [company_ratios.py](examples/trading/company_ratios.py) ## 8.3. How to get : FinancialStatements ? Here is how to get this data : ```python # FETCH DATA financials_statements = trading_api.get_financials_statements( product_isin='FR0000131906', ) ``` For a more comprehensive example : [financial_statements.py](examples/trading/financial_statements.py) ## 8.4. How to get : LatestNews ? Here is how to get this data : ```python # SETUP REQUEST request = LatestNews.Request( offset=0, languages='en,fr', limit=20, ) # FETCH DATA latest_news = trading_api.get_latest_news( request=request, raw=True, ) ``` For a more comprehensive example : [latest_news.py](examples/trading/latest_news.py) ## 8.5. How to get : TopNewsPreview ? Here is how to get this data : ```python # FETCH DATA top_news_preview = trading_api.get_top_news_preview(raw=True) ``` For a more comprehensive example : [top_news_preview.py](examples/trading/top_news_preview.py) ## 8.6. How to get : NewsByCompany ? Here is how to get this data : ```python # SETUP REQUEST request = NewsByCompany.Request( isin='NL0000235190', limit=10, offset=0, languages='en,fr', ) # FETCH DATA news_by_company = trading_api.get_news_by_company( request=request, raw=True, ) ``` For a more comprehensive example : [news_by_company.py](examples/trading/news_by_company.py) ## 8.7. How to get : Agenda ? Here is how to get this data : ```python # SETUP REQUEST request = Agenda.Request() request.start_date.FromJsonString('2021-06-21T22:00:00Z') request.end_date.FromJsonString('2021-11-28T23:00:00Z') request.calendar_type = Agenda.CalendarType.DIVIDEND_CALENDAR request.offset = 0 request.limit = 25 # FETCH DATA agenda = trading_api.get_agenda( request=request, raw=False, ) ``` Here are the available parameters for `Agenda.Request` : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |calendar_type|Agenda.CalendarType|Type of agenda :
`DIVIDEND_CALENDAR`
`ECONOMIC_CALENDAR`
`EARNINGS_CALENDAR`
`HOLIDAY_CALENDAR`
`IPO_CALENDAR`
`SPLIT_CALENDAR`| |offset|int|-| |limit|int|-| |order_by_desc|bool|-| |start_date|Timestamp|Events starting after this date.| |end_date|Timestamp|Events before this date.| |company_name|str|Filter used on the events description.| |countries|str|Comma separated list of countries like : `FR,US`| |classifications|str|Comma separated list of sectors like : `GovernmentSector,ExternalSector`| |units|str|Comma separated list of units like : `Acre,Barrel`| Exact definitions of `Agenda` and `Agenda.Request` are in this file : [trading.proto](protos/degiro_connector/trading/models/trading.proto) For a more comprehensive example : [agenda.py](examples/trading/agenda.py) ## 8.8. How to get : EstimatesSummaries ? Here is how to get this data : ```python # SETUP REQUEST request = Agenda.Request() request.start_date.FromJsonString('2021-06-21T22:00:00Z') request.end_date.FromJsonString('2021-11-28T23:00:00Z') request.calendar_type = Agenda.CalendarType.DIVIDEND_CALENDAR request.offset = 0 request.limit = 25 # FETCH DATA product_isin = "FR0000131906" estimates_summaries = trading_api.get_estimates_summaries( product_isin=product_isin, raw=False, ) ``` Here are the available parameters for `Agenda.Request` : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |annual|google.protobuf.Struct|Indicators by year.| |currency|str|currency, example `EUR`.| |interim|google.protobuf.Struct|Indicators by quarter.| |lastRetrieved|str|Last Retrieved, example : `2021-12-31T20:07:30.939Z`.| |lastUpdated|str|Last updated,, example : `2021-02-18T01:30:00Z`.| |preferredMeasure|str|Preferred measure, example : `EPS`.| |ric|str|Reuters Instrument Code, example : `BOUY.PA`.| Exact definition of `EstimatesSummaries` is in this file : [trading.proto](protos/degiro_connector/trading/models/trading.proto) For a more comprehensive example : [estimates_summaries.py](examples/trading/estimates_summaries.py) # 9. Contributing Pull requests are welcome. Feel free to open an issue or send me a message if you have a question. # 10. License [BSD-3-Clause License](https://raw.githubusercontent.com/Chavithra/degiro-connector/main/LICENSE) %package -n python3-degiro-connector Summary: This is yet another library to access Degiro's API. Provides: python-degiro-connector BuildRequires: python3-devel BuildRequires: python3-setuptools BuildRequires: python3-pip %description -n python3-degiro-connector # 1. **Degiro Connector** This is yet another library to access Degiro's API. Notes : - Migration scripts are available : ```bash python -m degiro_connector.migration.from_0_1_3_to_1_0_0 python -m degiro_connector.migration.from_1_0_4_to_1_0_5 python -m degiro_connector.migration.from_1_0_10_to_2_0_0 python -m degiro_connector.migration.from_2_0_2_to_2_0_3 ``` - `GRPC` services are available to let you consume this library through other languages like Javascript, Java, Go, C++, Rust, etc : ```bash python -m examples.quotecast.relay_server python -m examples.trading.relay_server ``` ## 1.1. Which features ? Here are the features you can access through this library : |**Endpoint**|**Feature(s)**| |:-|:-| |AccountCashReport|Export cash movements in a specific format : CSV, HTML, PDF or XLS.| |AccountInfo|Retrieve a table containing : "clientId" and Currencies.| |AccountOverview|Retrieve all the cash movements between two dates.| |Agenda|Crucial events regarding products : Dividend, Economic, Earnings, Holiday, IPO or Split.| |Bonds
ETFs
Funds
Futures
Leverageds
Lookup
Options
Stocks
Warrants|Search list of products according their name, type and other criterias.
For instance all the stocks from NASDAQ 100.| |Chart|Retrieve chart data.| |ClientDetails|Retrieve a table containing : "clientId", "intAccount" and other account information.| |CompanyProfile|Retrieve a company's profile using its ISIN code.| |CompanyRatios|Retrieve a company's ratios using its ISIN code.| |Config|Retrieve a table containing : "clientId" and URLs which are constitutive of Degiro's API.| |EstimatesSummaries|Retrieve a company's estimates summaries using its ISIN code.| |FavouritesList|Add/Delete/Retrieve favourites lists.| |FavouritesListProducts|Add/Update favourites lists content.| |FinancialStatements|Retrieve a company's financial statements using its ISIN code.| |LatestNews|Retrieve latest news about all the companies.| |LoginQuotecast|Establish a connection for quotecast operations.| |LoginTrading|Establish a connection for trading operations.| |LogoutTrading|Destroy previously established connection for trading operations.| |NewsByCompany|Retrieve news related to a specific company.| |Order|Create, update, delete an Order.| |OrderHistory|Retrieve all Orders created between two dates.| |Orders|List pending Orders.| |Portfolio|List products in your Portfolio.| |ProductsConfig|Retrieve a table containing : useful parameters to filter products.| |ProductsInfo|Search for products using their ids.| |Quotecasts|Fetch real-time data on financial products.
For instance the real-time stock Price.| |TopNewsPreview|Retrieve some news preview about all the companies.| |TotalPorfolio|Retrieve aggregated information about your assets.| |TransactionsHistory|Retrieve all Transactions created between two dates.| ## 1.2. How to install ? ```bash pip install degiro-connector ``` ## 1.3. How to upgrade ? ```bash pip install --no-cache-dir --upgrade degiro-connector ``` ## 1.4. How to uninstall ? ```bash pip uninstall degiro-connector ``` ## 1.5. Table of contents - [1. **Degiro Connector**](#1-degiro-connector) * [1.1. Which features ?](#11-which-features-) * [1.2. How to install ?](#12-how-to-install-) * [1.3. How to upgrade ?](#13-how-to-upgrade-) * [1.4. How to uninstall ?](#14-how-to-uninstall-) * [1.5. Table of contents](#15-table-of-contents) - [2. Real-time data](#2-real-time-data) * [2.1. What are the workflows ?](#21-what-are-the-workflows-) * [2.2. What are the credentials ?](#22-what-are-the-credentials-) * [2.3. How to find your : user_token ?](#23-how-to-find-your--user_token-) * [2.4. How to login ?](#24-how-to-login-) * [2.5. Is there a timeout ?](#25-is-there-a-timeout-) * [2.6. How to subscribe to a data-stream ?](#26-how-to-subscribe-to-a-data-stream-) * [2.7. How to unsubscribe to a data-stream ?](#27-how-to-unsubscribe-to-a-data-stream-) * [2.8. How to fetch the data ?](#28-how-to-fetch-the-data-) * [2.9. How to use this data ?](#29-how-to-use-this-data-) * [2.10. Which are the available data types ?](#210-which-are-the-available-data-types-) * [2.11. What is a Ticker ?](#211-what-is-a-ticker-) * [2.12. What is inside the Dictionary ?](#212-what-is-inside-the-dictionary-) * [2.13. What is inside the DataFrame ?](#213-what-is-inside-the-dataframe-) * [2.14. How to get chart data ?](#214-how-to-get-chart-data-) * [2.15. How to find a : vwd_id ?](#215-how-to-find-a--vwd_id-) - [3. Trading connection](#3-trading-connection) * [3.1. How to login ?](#31-how-to-login-) * [3.2. How to logout ?](#32-how-to-logout-) * [3.3. What are the credentials ?](#33-what-are-the-credentials-) * [3.4. How to find your : int_account ?](#34-how-to-find-your--int_account-) * [3.5. How to use 2FA ?](#35-how-to-use-2fa-) * [3.6. How to find your : totp_secret_key ?](#36-how-to-find-your--totp_secret_key-) * [3.7. How to find your : one_time_password ?](#37-how-to-find-your--one_time_password-) * [3.8. Is there a timeout ?](#38-is-there-a-timeout-) * [3.9. How to manage : TimeoutError ?](#39-how-to-manage--TimeoutError-) - [4. Order](#4-order) * [4.1. How to create an Order ?](#41-how-to-create-an-order-) * [4.1.1. Check Order](#411-check-order) * [4.1.2. Confirm Order](#412-confirm-order) * [4.2. How to update an Order ?](#42-how-to-update-an-order-) * [4.3. How to delete an Order ?](#43-how-to-delete-an-order-) - [5. Portfolio](#5-portfolio) * [5.1. How to retrieve pending Orders ?](#51-how-to-retrieve-pending-orders-) * [5.2. How to get the Portfolio ?](#52-how-to-get-the-portfolio-) * [5.3. How to get the TotalPortfolio ?](#53-how-to-get-the-totalportfolio-) * [5.4. How to retrieve the OrdersHistory ?](#54-how-to-retrieve-the-ordershistory-) * [5.5. How to retrieve the TransactionsHistory ?](#55-how-to-retrieve-the-transactionshistory-) - [6. Account](#6-account) * [6.1. How to retrieve the table : Config ?](#61-how-to-retrieve-the-table--config-) * [6.2. How to retrieve the table : ClientDetails ?](#62-how-to-retrieve-the-table--clientdetails-) * [6.3. How to retrieve the table : AccountInfo ?](#63-how-to-retrieve-the-table--accountinfo-) * [6.4. How to get the table : AccountOverview ?](#64-how-to-get-the-table--accountoverview-) * [6.5. How to export the table : CashAccountReport ?](#65-how-to-export-the-table--cashaccountreport-) * [6.6. How to export the table : PositionReport ?](#66-how-to-export-the-table--positionreport-) - [7. Products](#7-products) * [7.1. How to get the table : ProductsConfig ?](#71-how-to-get-the-table--productsconfig-) * [7.2. How to get my favourite products ?](#72-how-to-get-my-favourite-products-) * [7.3. How to lookup products (search by name) ?](#73-how-to-lookup-products-search-by-name-) * [7.4. How to search bonds ?](#74-how-to-search-bonds-) * [7.5. How to search etfs ?](#75-how-to-search-etfs-) * [7.6. How to search funds ?](#76-how-to-search-funds-) * [7.7. How to search futures ?](#77-how-to-search-futures-) * [7.8. How to search leverageds ?](#78-how-to-search-leverageds-) * [7.9. How to search options ?](#79-how-to-search-options-) * [7.10. How to search stocks ?](#710-how-to-search-stocks-) * [7.11. How to search warrants ?](#711-how-to-search-warrants-) * [7.12. How to search products from ids ?](#712-how-to-search-products-from-ids-) * [7.13. How to create a favourite list ?](#713-how-to-create-a-favourite-list-) * [7.14. How to delete a favourite list ?](#714-how-to-delete-a-favourite-list-) * [7.15. How to put favourite list products ?](#715-how-to-put-favourite-list-products-) * [7.16. How to delete favourite list products ?](#716-how-to-delete-favourite-list-products-) - [8. Companies](#8-companies) * [8.1. How to get : CompanyProfile ?](#81-how-to-get--companyprofile-) * [8.2. How to get : CompanyRatios ?](#82-how-to-get--companyratios-) * [8.3. How to get : FinancialStatements ?](#83-how-to-get--financialstatements-) * [8.4. How to get : LatestNews ?](#84-how-to-get--latestnews-) * [8.5. How to get : TopNewsPreview ?](#85-how-to-get--topnewspreview-) * [8.6. How to get : NewsByCompany ?](#86-how-to-get--newsbycompany-) * [8.7. How to get : Agenda ?](#87-how-to-get--agenda-) * [8.8. How to get : EstimatesSummaries ?](#88-how-to-get--estimatessummaries-) - [9. Contributing](#9-contributing) - [10. License](#10-license) # 2. Real-time data It is possible to fetch a stream of data in real-time from Degiro's API. For instance if one needs the following data from the "AAPL" stock : * LastDate * LastTime * LastPrice * LastVolume You can use this library to retrieve updates like this : LastDate LastTime LastPrice LastVolume 2020-11-13 22:00:00 119.26 4697040 For a list of available metrics, see the example in [section 2.6](#26-how-to-subscribe-to-a-data-stream-). ## 2.1. What are the workflows ? This is the workflow for consuming real-time data-stream : A. Find your "user_token". B. Setup the API object with your "user_token". C. Connect. D. Subscribe to data-stream. E. Fetch data-stream. This is the worflow for consuming charts : A. Find your "user_token". B. Setup the API object with your "user_token". C. Fetch charts. All the details of these steps are explained in the rest of this section. ## 2.2. What are the credentials ? The only credential you need in order to fetch real-time data and charts is the : * user_token Beware, these two identifiers are not the same thing : * user_token : used to fetch real-time data and charts. * int_account : used for some trading operations. ## 2.3. How to find your : user_token ? You can find your "user_token" inside one of these tables : * "Config" : attribute "clientId" * "ClientDetails" : attribute "id" See sections related to ["Config"](#61-how-to-retrieve-the-table--config-) and ["ClientDetails"](#62-how-to-retrieve-the-table--clientdetails-) tables. ## 2.4. How to login ? In order to fetch data you need to establish a connection. You can use the following code to connect : ```python # SETUP QUOTECAST API quotecast_api = API(user_token=YOUR_USER_TOKEN) # CONNECTION quotecast_api.connect() ``` ## 2.5. Is there a timeout ? Connection timeout is around 15 seconds. Which means a connection will cease to work after this timeout. This timeout is reset each time you use this connection to : * Subscribe to a metric (for instance a stock Price) * Fetch the data-stream So if you use it nonstop (in a loop) you won't need to reconnect. ## 2.6. How to subscribe to a data-stream ? To subscribe to a data-stream you need to setup a Request message. A Request has the following parameters : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |subscriptions|MessageMap|List of products and metrics to subscribe to.| |unsubscriptions|MessageMap|List of products and metrics to unsubscribe to.| Here is an example of a request : ```python request = Quotecast.Request() request.subscriptions['360015751'].extend([ 'LastDate', 'LastTime', 'LastPrice', 'LastVolume', 'AskPrice', 'AskVolume', 'LowPrice', 'HighPrice', 'BidPrice', 'BidVolume' ]) request.subscriptions['AAPL.BATS,E'].extend([ 'LastDate', 'LastTime', 'LastPrice', 'LastVolume', 'AskPrice', 'AskVolume', 'LowPrice', 'HighPrice', 'BidPrice', 'BidVolume' ]) ``` In this example these are the `vwd_id` of the products from which you want `Real-time data` : - 360015751 - AAPL.BATS,E See the [section](#215-how-to-find-a--vwd_id-) related to `vwd_id` for more information. Once you have built this Request object you can send it to Degiro's API like this : ```python quotecast_api.subscribe(request=request) ``` For more comprehensive examples : [realtime_poller.py](examples/quotecast/realtime_poller.py) / [realtime_one_shot.py](examples/quotecast/realtime_one_shot.py) ## 2.7. How to unsubscribe to a data-stream ? To remove metrics from the data-stream you need to setup a Request message. If you try to unsubscribe to a metric to which you didn't subscribed previously it will most likely have no impact. A Request has the following parameters : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |subscriptions|MessageMap|List of products and metrics to subscribe to.| |unsubscriptions|MessageMap|List of products and metrics to unsubscribe to.| Here is an example of a request : ```python request = Quotecast.Request() request.unsubscriptions['360015751'].extend([ 'LastDate', 'LastTime', 'LastPrice', 'LastVolume', 'AskPrice', 'AskVolume', 'LowPrice', 'HighPrice', 'BidPrice', 'BidVolume' ]) request.unsubscriptions['AAPL.BATS,E'].extend([ 'LastDate', 'LastTime', 'LastPrice', 'LastVolume', 'AskPrice', 'AskVolume', 'LowPrice', 'HighPrice', 'BidPrice', 'BidVolume' ]) ``` Once you have built this Request object you can send it to Degiro's API like this : ```python quotecast_api.subscribe(request=request) ``` For more comprehensive examples : [realtime_poller.py](examples/quotecast/realtime_poller.py) / [realtime_one_shot.py](examples/quotecast/realtime_one_shot.py) ## 2.8. How to fetch the data ? You can use the following code : ```python quotecast = quotecast_api.fetch_data() ``` For a more comprehensive example : [realtime_poller.py](examples/quotecast/realtime_poller.py) ## 2.9. How to use this data ? Received data is a `Quotecast` object with the following properties : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |json_data|dict|Dictionary representation of what Degiro's API has sent.| |metadata|Metadata|Containing the "response_datetime" and "request_duration".| Here is how to access these properties : ```python json_data = quotecast.json_data response_datetime = quotecast.metadata.response_datetime request_duration= quotecast.metadata.request_duration ``` Notes: * The API sometimes might return an empty Quotecast object. * The API often returns a subset of the requested metrics, e.g. only `'LastPrice'`. Please take this into account when appending consecutive data responses. ## 2.10. Which are the available data types ? This library provides the tools to convert Degiro's JSON data into something more programmer-friendly. Here is the list of available data types : |**Type**|**Description**| |:-|:-| |Ticker|Protobuf message (for GRPC).| |Dictionaries|Standard Python Dictionaries : **dict**.| |DataFrame|DataFrame from the library Pandas.| Here is how to build each type : ```python # UPDATE PARSER quotecast_parser.put_quotecast(quotecast=quotecast) # BUILD TICKER ticker = quotecast_parser.ticker # BUILD DICT ticker_dict = quotecast_parser.ticker_dict # BUILD PANDAS.DATAFRAME ticker_df = quotecast_parser.ticker_df ``` ## 2.11. What is a Ticker ? The generated Ticker contains : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |metadata|Metadata|Containing the "response_datetime" and "request_duration".| |products|MessageMap|Dictionary like object containing the metrics group by "vwd_id".| |product_list|RepeatedScalarFieldContainer|List of available "vwd_id".| Here are some operations available : ```python product = '360015751' metric_name = 'LastPrice' # ACCESS SPECIFIC PRODUCT product = ticker.products[product] # ACCESS SPECIFIC METRIC metric = product[metric_name] # LOOP OVER PRODUCTS for product in ticker.products: product = ticker.products[product] # LOOP OVER METRICS for metric_name in product.metrics: metric = product.metrics[metric_name] ``` A Ticker is a custom Protocol Buffer Message built for this library. It can be transmitted over GRPC framework. ## 2.12. What is inside the Dictionary ? The dictionary representation of a ticker contains the metrics grouped by "vwd_id" (product id), with : * keys : vwd_id * values : another dictionary with the metrics concerning this specific product. Example - Dictionary : ```python { '360114899': { 'vwd_id': 360114899, 'response_datetime': '2020-11-08 12:00:27', 'request_duration': 1.0224891666870117, 'LastDate': '2020-11-06', 'LastTime': '17:36:17', 'LastPrice': '70.0', 'LastVolume': '100' }, '360015751': { 'vwd_id': 360015751, 'response_datetime': '2020-11-08 12:00:27', 'request_duration': 1.0224891666870117, 'LastDate': '2020-11-06', 'LastTime': '17:36:17', 'LastPrice': '22.99', 'LastVolume': '470' } } ``` ## 2.13. What is inside the DataFrame ? In addition to whatever metrics you have chosen to subscribe to (see the example in [section 2.6](#26-how-to-subscribe-to-a-data-stream-)), the DataFrame will contain the following columns : |**Column**|**Description**| |:-|:-| |vwd_id|Product identifier, for instance "AAPL.BATS,E" for APPLE stock.| |response_datetime|Datetime at which the data was received.| |request_duration|Duration of the request used to fetch the data.| Example - DataFrame : vwd_id response_datetime request_duration LastDate LastTime LastPrice LastVolume 0 360114899 2020-11-08 12:00:27 1.022489 2020-11-06 17:39:57 70.0 100 1 360015751 2020-11-08 12:00:27 1.022489 2020-11-06 17:36:17 22.99 470 ## 2.14. How to get chart data ? You can fetch an object containing the same data than in Degiro's website graph. For that you need to prepare a Chart.Request object. Here is a table with the available attributes for Chart.Request. |**Parameter**|**Type**|**Description**| |:-|:-|:-| |requestid|str|It sends you back whatever string you put here, you can set it to : "1".| |resolution|Chart.Resolution|Resolution of the chart like : Chart.Resolution.PT1M.| |culture|str|Country code like : "en-US" or "fr-FR".| |period|Chart.Period|Period of the chart, like : Chart.Period.P1D.| |series|repeated string|Data to get like : ['issueid:36014897', 'price:issueid:360148977'].| |tz|str|Timezone like : "Europe/Paris"| Example of code : ```python request = Chart.Request() request.culture = "fr-FR" request.period = Chart.Interval.PT1H request.requestid = "1" request.resolution = Chart.Interval.P1D # request.series.append("issueid:360148977") # request.series.append("price:issueid:360148977") request.series.append("ohlc:issueid:360148977") # request.series.append("volume:issueid:360148977") # request.series.append("vwdkey:AAPL.BATS,E") # request.series.append("price:vwdkey:AAPL.BATS,E") # request.series.append("ohlc:vwdkey:AAPL.BATS,E") # request.series.append("volume:vwdkey:AAPL.BATS,E") request.tz = "Europe/Paris" # FETCH DATA chart = quotecast_api.get_chart( request=request, override={ "resolution": "P1D", "period": "P1W", }, raw=True, ) ``` The `issueid` parameter is the `vwd_id` of the product from which you want the `Chart` data. See the section related to `vwd_id` for more information. All the options for the enumerations are available in this file : [quotecast.proto](protos/degiro_connector/quotecast/models/quotecast.proto) For a more comprehensive examples : - [chart.py](examples/quotecast/chart.py) - [chart_format.py](examples/quotecast/chart_format.py) ## 2.15. How to find a : vwd_id ? In operations related to `Quotecast`, Degiro uses the `vwd_id` to identify a product. Which means that if you want a `Chart` or `Real-time data` for a specific product : you first need to find this product's `vwd_id`. This two identifiers are not the same : |**Identifier**|**API name(s)**|**Description**| |:-|:-|:-| |id|str|Id used identify a product in `Trading` related endpoints.| |vwd_id|issueid
vwdId
vwdIdSecondary
|Id used identify a product in `Quotecast` (`Chart` and `Real-time data`) related endpoint.| Here are some methods you can use to fetch a product's `vwd_id` : - `product_search` - `get_products_info` The method `product_search` let you use the name or other attributes of a product to fetch it's `vwd_id`. The method `get_products_info` let you use a product's `id` to fetch it's `vwd_id`. # 3. Trading connection This library is divided into two modules : - quotecast : to consume real-time financial data. - trading : to manage your Degiro's account. The module **quotecast** is described in the section related to real-time data. The rest of this document will only refer to the module : **trading**. ## 3.1. How to login ? In order to use the module **trading.api** you need to establish a connection. Check the section related to **int_account** to understand how to get yours. Here is how to connect : ```python # SETUP CREDENTIALS credentials = Credentials( username = YOUR_USERNAME, password = YOUR_PASSWORD, int_account = YOUR_INT_ACCOUNT, # OPTIONAL FOR LOGIN ) # SETUP TRADING API trading_api = API(credentials=credentials) # ESTABLISH CONNECTION trading_api.connect() ``` For a more comprehensive example : [connection.py](examples/trading/connection.py) ## 3.2. How to logout ? Once you no longer need to use the API you can destroy your connection. You can use the following code to disconnect : ```python # DESTROY CONNECTION trading_api.logout() ``` For a more comprehensive example : [logout.py](examples/trading/logout.py) ## 3.3. What are the credentials ? Some credentials are required to use Degiro's trading API. Here are these credentials : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |username|str|Username used to log into Degiro's website.| |password|str|Password used to log into Degiro's website.| |int_account|int|OPTIONAL : unique identifier of the account : used by Degiro's server.| |totp_secret_key|str|OPTIONAL : used for Two-factor Authentication (2FA).| |one_time_password|str|OPTIONAL : used for Two-factor Authentication (2FA).| Check the section related to **int_account** to understand how to get yours. Check the section related to **2FA** if you want to know more about these two parameters : - **totp_secret_key** - **one_time_password** ## 3.4. How to find your : int_account ? To get your **int_acccount** you can run this example : [client_details_table.py](examples/trading/client_details_table.py) See section related to **ClientDetails** table for more details. This **int_acccount** is required to do most of the trading operations available in this connector. Here are some operations for which your **int_acccount** is not required : - Connection - Fetch table : ClientDetails - Fetch table : Config Beware, these two identifiers are not the same thing : - user_token : used to fetch real-time data and charts. - int_account : used for some trading operations. ## 3.5. How to use 2FA ? First I will briefly explain what is : **Two-Factor Authentication (2FA)**. I recommend to skip a few paragraphs if you already know what is **2FA**. In a standard connection you are providing two parameters: - username - password If you use **Two-Factor Authentication (2FA)** you need an extra parameter: - one_time_password This **one_time_password** has a validity of 30 secondes and is generated using a **totp_secret_key** code. Usually you use an app like **‎Google Authenticator** to store this **totp_secret_key** and generate the **one_time_password**. The **totp_secret_key** is stored inside the QRCode which is displayed when you enable 2FA on Degiro's website To use **2FA** with this library you have two solutions. **SOLUTION 1** Provide your **totp_secret_key** : the library will use it to generate a new **one_time_password** at each connection. So you won't have to type your **one_time_password** manually at each connection. This is the proper way. See the section about **totp_secret_key** to understand how to get yours. Here is an example of connection with the **totp_secret_key** : ```python # SETUP CREDENTIALS credentials = Credentials( username=YOUR_USERNAME, password=YOUR_PASSWORD, int_account=YOUR_INT_ACCOUNT, # OPTIONAL FOR LOGIN totp_secret_key=YOUR_2FA_SECRET_KEY, # ONLY IF 2FA IS ENABLED ) # SETUP TRADING API trading_api = API(credentials=credentials) # ESTABLISH CONNECTION trading_api.connect() ``` A complete example here : [connection_2fa.py](examples/trading/connection_2fa.py) **SOLUTION 2** Provide a new **one_time_password** at each connection. Here is an example of connection with the **one_time_password** : ```python # SETUP CREDENTIALS credentials = Credentials( username=YOUR_USERNAME, password=YOUR_PASSWORD, int_account=YOUR_INT_ACCOUNT, # OPTIONAL FOR LOGIN one_time_password=YOUR_2FA_OTP, # ONLY IF 2FA IS ENABLED ) # SETUP TRADING API trading_api = API(credentials=credentials) # ESTABLISH CONNECTION trading_api.connect() ``` A complete example here : [connection_otp.py](examples/trading/connection_otp.py) ## 3.6. How to find your : totp_secret_key ? The parameter **totp_secret_key** is only required if you have enabled `2FA` on Degiro's website. When you try to activate `2FA` on Degiro's website, it displays a `QRCode`. This `QRCode` changes at each activation. A `QRCode` is a picture which can be converted into a text. You can download this `QRCode` and use a tool to extract the text from it. This extracted text will look like this : otpauth://totp/DEGIRO:YOUR_USERNAME?algorithm=SHA1&issuer=DEGIRO&secret=YOUR_TOPT_SECRET_KEY&digits=6&period=30 Has you can guess the "totp_secret_key" is in this part : secret=YOUR_TOPT_SECRET_KEY Here is an example of script that extracts the text from a `QRCode` : [qrcode.py](examples/trading/qrcode.py) ## 3.7. How to find your : one_time_password ? The parameter **one_time_password** is the password you type when you log in the website using **2FA**. Usually you get it through an app like **Google Authenticator**. It is preferable to use the parameter **totp_secret_key** instead of **one_time_password**. ## 3.8. Is there a timeout ? A connection for trading operations has a timeout of 30 minutes. It's [defined](https://github.com/Chavithra/degiro-connector/blob/main/degiro_connector/core/constants/timeouts.py#L2) in seconds as constant `timeouts.TRADING_TIMEOUT`. The timeout period is started when the [`TradingAPI.connect()`](#31-how-to-login-) results successfully. Every time an operation is made to this `TradingAPI` connection, the timeout for this connection will be reset. If a `TradingAPI` connection is left unused during the timeout period, the connection will expire. Every consecutive function call to the `TraderAPI` will then throw a `TimeoutError` exception. A connection timeout might occur when your trading strategy only performs a few trades per day, e.g. once per hour. So when finally a buy opportuntiy occurs, [`check_order()`](#411-check-order): ```python # FETCH CHECKING_RESPONSE checking_response = trading_api.check_order(order=order) ``` Will fail with `TimeoutError`: ``` TimeoutError: Connection has probably expired. ``` ## 3.9. How to manage : TimeoutError ? **HANDLE EXCEPTION** It's recommended to catch the `TimeoutError` on every function call to the `TradingAPI`. When it's detected, it's sufficient to call [`connect()`](#31-how-to-login-) again, followed by repeating the original call that threw the exception. Example for the [`check_order()`](#411-check-order) call: ```python try: checking_response = trading_api.check_order(order=order) except TimeoutError: logging.warning("TradingAPI session did timeout, reconnecting for new session ID...") trading_api.connect() checking_response = trading_api.check_order(order=order) ``` This shows the following in the log, while the order is checked successfully after a successful reconnect: ```python WARNING - TradingAPI session did timeout, reconnecting for new session ID... INFO - get_session_id:response_dict: {'isPassCodeEnabled': False, 'locale': 'nl_NL', 'redirectUrl': 'https://trader.degiro.nl/trader/', 'sessionId': '2BADBBEF3****', 'status': 0, 'statusText': 'success'} INFO - confirmation_id: "053df7cf-****" response_datetime { seconds: 1643801134 nanos: 715765000 } ``` **REFRESH TIMEOUT** As mentioned before, the timeout will be reset after each call to the `TradingAPI`. This provides the opportunity to make a periodic function call, for example every 10 minutes to [`get_update()`](#51-how-to-retrieve-pending-orders-). However, this might interfere with your other logic and might not be robust over time when DeGiro decides to decrease the timeout on their server. Therefor it's strongly recommended to always incorporate the exception handling for `TimeoutError` as indicated in the example above. **CHANGE PERIOD** It's possible to change the timeout period while creating the `TradingAPI`. Just add a `ModelConnection` object for parameter `connection_storage`: ```python # SETUP TRADING API trading_api = TradingAPI( credentials=credentials, connection_storage=ModelConnection( timeout=600, ) ) # Connect: trading_api.connect() ``` The connection will now expire after 10 minutes (10 * 60 s). # 4. Order Creating and updating of orders is done with an `Order` object. Here are the parameters: |**Parameter**|**Type**|**Description**| |:-|:-|:-| |id|str|Optional for [`update_order()`](#42-how-to-update-an-order-). It's the `order_id` of the created `Order` as returned by [`confirm_order()`](#412-confirm-order).| |action|`Order.Action`|Whether you want to : `BUY` or `SELL`.| |order_type|`Order.OrderType`|Type of order : `LIMIT`, `STOP_LIMIT`, `MARKET` or `STOP_LOSS`.| |price|float|Limit price of the order.
Optional for the following `order_type` : `LIMIT` and `STOPLIMIT`.| |product_id|int|Identifier of the product concerned by the order.| |size|float|Size of the order.| |stop_price|float|Stop price of the order.
Optional for the following `order_type` : `STOPLIMIT` and `STOPLOSS`| |time_type|`Order.TimeType`|Duration of the order : `GOOD_TILL_DAY` or `GOOD_TILL_CANCELED`| The full description of an `Order` is available here : [trading.proto](protos/degiro_connector/trading/models/trading.proto) ## 4.1. How to create an Order ? The order creation is done in two steps : 1. Checking : send the `Order` to the API to check if it is valid. 2. Confirmation : confirm the creation of the `Order`. Keeping these two steps (instead of reducing to one single "create" function) provides more options. ## 4.1.1 Check order Use the `check_order()` function of the Trading API: ### **Request parameters** |**Parameter**|**Type**|**Description**| |:-|:-|:-| |order|`Order`|The order to create with all necessary [parameters](#4-order).| ### **Response parameters** On a succesfull request, a `dict` with the following parameters is returned: |**Parameter**|**Type**|**Description**| |:-|:-|:-| |confirmation_id|str|Id necessary to confirm the creation of the Order by the [`confirm_order()`](#412-confirm-order) function.| |response_datetime|[`Timestamp`](https://pythonhosted.org/gax-google-pubsub-v1/google.protobuf.timestamp_pb2.html)|A `Timestamp` represents a point in time independent of any time zone or calendar, represented as seconds (`seconds`) and fractions of seconds at nanosecond resolution (`nanos`) in UTC Epoch time. A `Timestamp` can be converted to a RFC 3339 date string by using `ToJsonString()`.
Note: This `Timestamp` is created by Degiro Connector on reception of the API response, not by DeGiro server.| |free_space_new|float|New free space (balance) if the Order is confirmed.| |transaction_fees|float|Transaction fees that will be applied to the Order.| |show_ex_ante_report_link|bool|?| When the request fails, `None` is returned. ## 4.1.2 Confirm order Use the `confirm_order()` function of the Trading API: ### **Request parameters** |**Parameter**|**Type**|**Description**| |:-|:-|:-| |confirmation_id|str|The confirmtation id from the [`check_order()`](#411-check-order) response.| |order|`Order`|The same order from the [`check_order()`](#411-check-order) request.| ### **Response parameters** On a succesfull request, a `dict` with the following parameters is returned: |**Parameter**|**Type**|**Description**| |:-|:-|:-| |order_id|str|A unique id of the accepted order. This id is required to [update](#42-how-to-update-an-order-) or [delete](#43-how-to-delete-an-order-) the pending order.| |response_datetime|[`Timestamp`](https://pythonhosted.org/gax-google-pubsub-v1/google.protobuf.timestamp_pb2.html)|A `Timestamp` represents a point in time independent of any time zone or calendar, represented as seconds (`seconds`) and fractions of seconds at nanosecond resolution (`nanos`) in UTC Epoch time. A `Timestamp` can be converted to a RFC 3339 date string by using `ToJsonString()`.
Note: This `Timestamp` is created by Degiro Connector on reception of the API response, not by DeGiro server.| When the request fails, `None` is returned. ## 4.1.3 Example of combining these functions ```python # SETUP ORDER order = Order( action=Order.Action.BUY, order_type=Order.OrderType.LIMIT, price=10, product_id=71981, size=1, time_type=Order.TimeType.GOOD_TILL_DAY, ) # FETCH CHECKING_RESPONSE checking_response = trading_api.check_order(order=order) # EXTRACT CONFIRMATION_ID confirmation_id = checking_response.confirmation_id # SEND CONFIRMATION confirmation_response = trading_api.confirm_order( confirmation_id=confirmation_id, order=order, ) ``` For a more comprehensive example : [order.py](examples/trading/order.py) ## 4.2. How to update an Order ? To modify a specific Order, you need to set it up with the `order_id` from the [`confirm_order()`](#412-confirm-order) response and use the `update_order()` function of the Trading API: ### **Request parameters** |**Parameter**|**Type**|**Description**| |:-|:-|:-| |order|`Order`|The order to update with all necessary [parameters](#4-order), including `id` as returned by [`confirm_order()`](#412-confirm-order).| ### **Response parameters** On a succesfull request, a `bool` with the value `True` is returned. When the request fails, `None` is returned. A valid reason is that the pending order has been already executed on the exchange, and this `order_id` no longer exists. Here is an example: ```python # ORDER SETUP order = Order( id=YOUR_ORDER_ID, # `order_id` from `confirm_order()` response action=Order.Action.BUY, order_type=Order.OrderType.LIMIT, price=10.60, product_id=71981, size=1, time_type=Order.TimeType.GOOD_TILL_DAY, ) # UPDATE ORDER succcess = trading_api.update_order(order=order) ``` ## 4.3. How to delete an Order ? To delete a specific Order you just need the `order_id` from the [`confirm_order()`](#412-confirm-order) response and use the `delete_order()` function of the Trading API: ### **Request parameters** |**Parameter**|**Type**|**Description**| |:-|:-|:-| |order_id|str|The unique id of the accepted order as returned by [`confirm_order()`](#412-confirm-order).| ### **Response parameters** On a succesfull request, a `bool` with the value `True` is returned. When the request fails, `None` is returned. A valid reason is that the pending order has been already executed on the exchange, and this `order_id` no longer exists. Here is an example: ```python # DELETE ORDER succcess = trading_api.delete_order(order_id=YOUR_ORDER_ID) # `order_id` from `confirm_order()` response ``` # 5. Portfolio ## 5.1. How to retrieve pending Orders ? This is how to get the list of Orders currently created but not yet executed or deleted : ```python request_list = Update.RequestList() request_list.values.extend([ Update.Request(option=Update.Option.ORDERS, last_updated=0), ]) update = trading_api.get_update(request_list=request_list) update_dict = pb_handler.message_to_dict(message=update) orders_df = pd.DataFrame(update_dict['orders']['values']) ``` Example : Orders product_id time_type price size id ... action order_type stop_price retained_order sent_to_exchange 0 0 GOOD_TILL_DAY 2 3 202cb962-ac59-075b-964b-07152d234b70 ... BUY LIMIT 16 17 18 For a more comprehensive example : [update.py](examples/trading/update.py) ## 5.2. How to get the Portfolio ? This is how to list the stocks/products currently in the portfolio : ```python request_list = Update.RequestList() request_list.values.extend([ Update.Request(option=Update.Option.PORTFOLIO, last_updated=0), ]) update = trading_api.get_update(request_list=request_list) update_dict = pb_handler.message_to_dict(message=update) portfolio_df = pd.DataFrame(update_dict['portfolio']['values']) ``` For a more comprehensive example : [update.py](examples/trading/update.py) Note: In order to resolve product IDs to Human readable names, see [7.12. How to search products from ids ?](#712-how-to-search-products-from-ids-) ## 5.3. How to get the TotalPortfolio ? This is how to get aggregated data about the portfolio : ```python request_list = Update.RequestList() request_list.values.extend([ Update.Request(option=Update.Option.TOTALPORTFOLIO, last_updated=0), ]) update = trading_api.get_update(request_list=request_list) update_dict = pb_handler.message_to_dict(message=update) total_portfolio_df = pd.DataFrame(update_dict['total_portfolio']['values']) ``` Example : DataFrame degiroCash flatexCash totalCash totalDepositWithdrawal todayDepositWithdrawal ... reportNetliq reportOverallMargin reportTotalLongVal reportDeficit marginCallStatus 0 0 1 2 3 4 ... 16 17 18 19 NO_MARGIN_CALL For a more comprehensive example : [update.py](examples/trading/update.py) ## 5.4. How to retrieve the OrdersHistory ? This method returns data about passed orders between two dates. The result contains a list of "Orders" objects with the following attributes : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |created|str|RFC 3339 Datetime, example : "2020-10-06T20:07:18+02:00".| |orderId|str|MD5 HASH, example : "098f6bcd-4621-d373-cade-4e832627b4f6"| |productId|int|Id of the product example : 65156| |size|float|Size of the order, example : 10.0000| |price|float|Price of the order, example : 8.6800| |buysell|str|"B" or "S"| |orderTypeId|int|see 3.Order| |orderTimeTypeId|int|see 3.Order| |stopPrice|float|Price like : 0.0000| |totalTradedSize|int|-| |type|str|"CREATE", "DELETE" or "MODIFY"| |status|str|"CONFIRMED"| |last|str|RFC 3339 Datetime, example : "2020-10-06T20:07:18+02:00".| |isActive|bool|-| Here is how to get this data : ```python # SETUP REQUEST from_date = OrdersHistory.Request.Date(year=2020,month=11,day=15) to_date = OrdersHistory.Request.Date(year=2020,month=10,day=15) request = OrdersHistory.Request(from_date=from_date, to_date=to_date) # FETCH DATA orders_history = trading_api.get_orders_history(request=request) ``` For a more comprehensive example : [orders_history.py](examples/trading/orders_history.py) ## 5.5. How to retrieve the TransactionsHistory ? Here is how to get this data : ```python # SETUP REQUEST from_date = TransactionsHistory.Request.Date(year=2020,month=11,day=15) to_date = TransactionsHistory.Request.Date(year=2020,month=10,day=15) request = TransactionsHistory.Request(from_date=from_date, to_date=to_date) # FETCH DATA transactions_history = trading_api.get_transactions_history(request=request) ``` For a more comprehensive example : [transactions_history.py](examples/trading/transactions_history.py) # 6. Account ## 6.1. How to retrieve the table : Config ? The config table contains the following informations : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |sessionId|str|Current session id.| |clientId|int|Unique Degiro's Account identifier also called "userToken"| |tradingUrl|str|-| |paUrl|str|-| |reportingUrl|str|-| |paymentServiceUrl|str|-| |productSearchUrl|str|-| |dictionaryUrl|str|-| |productTypesUrl|str|-| |companiesServiceUrl|str|-| |i18nUrl|str|-| |vwdQuotecastServiceUrl|str|-| |vwdNewsUrl|str|-| |vwdGossipsUrl|str|-| |taskManagerUrl|str|-| |refinitivNewsUrl|str|-| |refinitivAgendaUrl|str|-| |refinitivCompanyProfileUrl|str|-| |refinitivCompanyRatiosUrl|str|-| |refinitivFinancialStatementsUrl|str|-| |refinitivClipsUrl|str|-| |landingPath|str|-| |betaLandingPath|str|-| |mobileLandingPath|str|-| |loginUrl|str|-| Here is how to get this table : ```python # FETCH DATA config_table = trading_api.get_config() # EXTRACT SOME DATA user_token = config_table['clientId'] session_id = config_table['sessionId'] ``` For a more comprehensive example : [config_table.py](examples/trading/config_table.py) ## 6.2. How to retrieve the table : ClientDetails ? The ClientDetails table contains information about the current Degiro Account. |**Parameter**|**Type**| |:-|:-| |id|int| |intAccount|int| |loggedInPersonId|int| |clientRole|str| |effectiveClientRole|str| |contractType|str| |username|str| |displayName|str| |email|str| |firstContact.firstName|str| |firstContact.lastName|str| |firstContact.displayName|str| |firstContact.nationality|str| |firstContact.gender|str| |firstContact.dateOfBirth|str| |firstContact.placeOfBirth|str| |firstContact.countryOfBirth|str| |address.streetAddress|str| |address.streetAddressNumber|str| |address.zip|str| |address.city|str| |address.country|str| |cellphoneNumber|str| |locale|str| |language|str| |culture|str| |bankAccount.bankAccountId|int| |bankAccount.bic|str| |bankAccount.iban|str| |bankAccount.status|str| |flatexBankAccount.bic|str| |flatexBankAccount.iban|str| |memberCode|str| |isWithdrawalAvailable|bool| |isAllocationAvailable|bool| |isIskClient|bool| |isCollectivePortfolio|bool| |isAmClientActive|bool| |canUpgrade|bool| Here is how to get this table : ```python # FETCH DATA client_details_table = trading_api.get_client_details() # EXTRACT SOME DATA int_account = client_details_table['data']['intAccount'] user_token = client_details_table['data']['id'] ``` For a more comprehensive example : [client_details_table.py](examples/trading/client_details_table.py) ## 6.3. How to retrieve the table : AccountInfo ? The AccountInfo table contains the following information about currencies. |**Parameter**|**Type**| |:-|:-| |clientId|int| |baseCurrency|str| |currencyPairs|dict| |marginType|str| |cashFunds|dict| |compensationCapping|float|-| Here is how to get this table : ```python account_info_table = trading_api.get_account_info() ``` For a more comprehensive example : [account_info_table.py](examples/trading/account_info_table.py) ## 6.4. How to get the table : AccountOverview ? It will provide a list of cash movements. Here is how to get this data : ```python # SETUP REQUEST from_date = AccountOverview.Request.Date(year=2020,month=11,day=15) to_date = AccountOverview.Request.Date(year=2020,month=10,day=15) request = AccountOverview.Request(from_date=from_date, to_date=to_date) # FETCH DATA account_overview = trading_api.get_account_overview(request=request) ``` For a more comprehensive example : [account_overview.py](examples/trading/account_overview.py) Each cash movement contains this kind of parameters : |**Parameter**|**Type**| |:-|:-| |date|str| |valueDate|str| |id|int| |orderId|str| |description|str| |productId|int| |currency|str| |change|float| |balance|dict| |unsettledCash|float| |total|float| ## 6.5. How to export the table : CashAccountReport ? It will export a list of cash movements in a specific format. Available formats : - CSV - HTML - PDF - XLS Here is how to get this content in `CSV` format : ```python # SETUP REQUEST from_date = CashAccountReport.Request.Date(year=2020,month=11,day=15) to_date = CashAccountReport.Request.Date(year=2020,month=10,day=15) request = CashAccountReport.Request( format=CashAccountReport.Format.CSV, country='FR', lang='fr', from_date=from_date, to_date=to_date, ) # FETCH DATA cash_account_report = trading_api.get_cash_account_report( request=request, raw=False, ) ``` Here are the available parameters for `CashAccountReport.Request` : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |format|CashAccountReport.Format|Wanted format :
`CSV`
`HTML`
`PDF`
`XLS`| |country|str|Country name, like : `FR`| |lang|int|Language, like : `fr`| |from_date|CashAccountReport.Request.Date|Events starting after this date.| |to_date|CashAccountReport.Request.Date|Events before this date.| Exact definitions of `CashAccountReport` and `CashAccountReport.Request` are in this file : [trading.proto](protos/degiro_connector/trading/models/trading.proto) For a more comprehensive example : [cash_account_report.py](examples/trading/cash_account_report.py) ## 6.6. How to export the table : PositionReport ? It will export a list of cash movements in a specific format. Available formats : - CSV - HTML - PDF - XLS Here is how to get this content in `CSV` format : ```python # SETUP REQUEST to_date = CashAccountReport.Request.Date(year=2020,month=10,day=15) request = CashAccountReport.Request( format=CashAccountReport.Format.CSV, country='FR', lang='fr', to_date=to_date, ) # FETCH DATA position_report = trading_api.get_position_report( request=request, raw=False, ) ``` Here are the available parameters for `PositionReport.Request` : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |format|PositionReport.Format|Wanted format :
`CSV`
`HTML`
`PDF`
`XLS`| |country|str|Country name, like : `FR`| |lang|int|Language, like : `fr`| |to_date|PositionReport.Request.Date|Events before this date.| Exact definitions of `PositionReport` and `PositionReport.Request` are in this file : [trading.proto](protos/degiro_connector/trading/models/trading.proto) For a more comprehensive example : [position_report.py](examples/trading/position_report.py) # 7. Products ## 7.1. How to get the table : ProductsConfig ? This table contains useful parameters to filter products. Here are the parameters which are inside this table : |**Parameter**|**Type**| |:-|:-| |stockCountries|list| |bondExchanges|list| |bondIssuerTypes|list| |eurexCountries|list| |futureExchanges|list| |optionExchanges|list| |combinationExchanges|list| |cfdExchanges|list| |exchanges|list| |indices|list| |regions|list| |countries|list| |productTypes|list| |etfFeeTypes|list| |investmentFundFeeTypes|list| |optionAggregateTypes|list| |leveragedAggregateTypes|list| |etfAggregateTypes|list| |investmentFundAggregateTypes|list| |lookupSortColumns|list| |stockSortColumns|list| |bondSortColumns|list| |cfdSortColumns|list| |etfSortColumns|list| |futureSortColumns|list| Here is how to get this data : ```python # FETCH DATA products_config = trading_api.get_products_config() ``` For a more comprehensive example : [products_config.py](examples/trading/products_config.py) ## 7.2. How to get my favourite products ? Here is how to get this data : ```python # FETCH DATA favourites_list = trading_api.get_favourites_list() ``` For a more comprehensive example : [favourites_list.py](examples/trading/favourites_list.py) ## 7.3. How to lookup products (search by name) ? Text research on a financial product. Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestLookup( search_text='APPLE', limit=10, offset=0, product_type_id=1, ) # FETCH DATA products_lookup = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_lookup.py](examples/trading/product_lookup.py) ## 7.4. How to search bonds ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestBonds( bond_issuer_type_id=0, bond_exchange_id=710, search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA bond_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.5. How to search etfs ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestETFs( popular_only=False, input_aggregate_types='', input_aggregate_values='', search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA etf_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.6. How to search funds ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestFunds( search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA fund_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.7. How to search futures ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestFutures( future_exchange_id=1, underlying_isin='FR0003500008', search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA fund_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.8. How to search leverageds ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestLeverageds( popular_only=False, input_aggregate_types='', input_aggregate_values='', search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA etf_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.9. How to search options ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestOptions( input_aggregate_types='', input_aggregate_values='', option_exchange_id=3, underlying_isin='FR0003500008', search_text='', offset=0, limit=100, require_total=True, sort_columns='expirationDate,strike', sort_types='asc,asc', ) # FETCH DATA option_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.10. How to search stocks ? It contains information about available stocks. Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestStocks( index_id=122001, # NASDAQ 100 exchange_id=663, # NASDAQ # You can either use `index_id` or `exchange id` # See which one to use in the `ProductsConfig` table is_in_us_green_list=True, stock_country_id=846, # US search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA stock_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.11. How to search warrants ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestWarrants( search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA warrant_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.12. How to search products from ids ? Here is how to get this data : ```python # SETUP REQUEST request = ProductsInfo.Request() request.products.extend([96008, 1153605, 5462588]) # FETCH DATA products_info = trading_api.get_products_info( request=request, raw=True, ) ``` For a more comprehensive example : [products_info.py](examples/trading/products_info.py) ## 7.13. How to create a favourite list ? Example : ```python favorite_list_id = trading_api.create_favourite_list(name="SOME_NAME") ``` For a more comprehensive example : [favourite_list_create.py](examples/trading/favourite_list_create.py) ## 7.14. How to delete a favourite list ? Example : ```python success = trading_api.delete_favourite_list(id=1234567) ``` For a more comprehensive example : [favourite_list_delete.py](examples/trading/favourite_list_delete.py) ## 7.15. How to put favourite list products ? Example : ```python success = trading_api.put_favourite_list_product( id=1234567, product_id=1234567, ) ``` For a more comprehensive example : [favourite_list_put_product.py](examples/trading/favourite_list_put_product.py) ## 7.16. How to delete favourite list products ? Example : ```python success = trading_api.delete_favourite_list_product( id=1234567, product_id=1234567, ) ``` For a more comprehensive example : [favourite_list_delete product.py](examples/trading/favourite_list_delete product.py) # 8. Companies ## 8.1. How to get : CompanyProfile ? Here is how to get this data : ```python # FETCH DATA company_profile = trading_api.get_company_profile( product_isin='FR0000131906', ) ``` For a more comprehensive example : [company_profile.py](examples/trading/company_profile.py) ## 8.2. How to get : CompanyRatios ? This table contains information about the company. Here are the parameters which are inside this table : |**Parameter**|**Type**| |:-|:-| |totalFloat|str| |sharesOut|str| |consRecommendationTrend|dict| |forecastData|dict| |currentRatios|dict| Here is how to get this data : ```python # FETCH DATA company_ratios = trading_api.get_company_ratios( product_isin='FR0000131906', ) ``` For a more comprehensive example : [company_ratios.py](examples/trading/company_ratios.py) ## 8.3. How to get : FinancialStatements ? Here is how to get this data : ```python # FETCH DATA financials_statements = trading_api.get_financials_statements( product_isin='FR0000131906', ) ``` For a more comprehensive example : [financial_statements.py](examples/trading/financial_statements.py) ## 8.4. How to get : LatestNews ? Here is how to get this data : ```python # SETUP REQUEST request = LatestNews.Request( offset=0, languages='en,fr', limit=20, ) # FETCH DATA latest_news = trading_api.get_latest_news( request=request, raw=True, ) ``` For a more comprehensive example : [latest_news.py](examples/trading/latest_news.py) ## 8.5. How to get : TopNewsPreview ? Here is how to get this data : ```python # FETCH DATA top_news_preview = trading_api.get_top_news_preview(raw=True) ``` For a more comprehensive example : [top_news_preview.py](examples/trading/top_news_preview.py) ## 8.6. How to get : NewsByCompany ? Here is how to get this data : ```python # SETUP REQUEST request = NewsByCompany.Request( isin='NL0000235190', limit=10, offset=0, languages='en,fr', ) # FETCH DATA news_by_company = trading_api.get_news_by_company( request=request, raw=True, ) ``` For a more comprehensive example : [news_by_company.py](examples/trading/news_by_company.py) ## 8.7. How to get : Agenda ? Here is how to get this data : ```python # SETUP REQUEST request = Agenda.Request() request.start_date.FromJsonString('2021-06-21T22:00:00Z') request.end_date.FromJsonString('2021-11-28T23:00:00Z') request.calendar_type = Agenda.CalendarType.DIVIDEND_CALENDAR request.offset = 0 request.limit = 25 # FETCH DATA agenda = trading_api.get_agenda( request=request, raw=False, ) ``` Here are the available parameters for `Agenda.Request` : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |calendar_type|Agenda.CalendarType|Type of agenda :
`DIVIDEND_CALENDAR`
`ECONOMIC_CALENDAR`
`EARNINGS_CALENDAR`
`HOLIDAY_CALENDAR`
`IPO_CALENDAR`
`SPLIT_CALENDAR`| |offset|int|-| |limit|int|-| |order_by_desc|bool|-| |start_date|Timestamp|Events starting after this date.| |end_date|Timestamp|Events before this date.| |company_name|str|Filter used on the events description.| |countries|str|Comma separated list of countries like : `FR,US`| |classifications|str|Comma separated list of sectors like : `GovernmentSector,ExternalSector`| |units|str|Comma separated list of units like : `Acre,Barrel`| Exact definitions of `Agenda` and `Agenda.Request` are in this file : [trading.proto](protos/degiro_connector/trading/models/trading.proto) For a more comprehensive example : [agenda.py](examples/trading/agenda.py) ## 8.8. How to get : EstimatesSummaries ? Here is how to get this data : ```python # SETUP REQUEST request = Agenda.Request() request.start_date.FromJsonString('2021-06-21T22:00:00Z') request.end_date.FromJsonString('2021-11-28T23:00:00Z') request.calendar_type = Agenda.CalendarType.DIVIDEND_CALENDAR request.offset = 0 request.limit = 25 # FETCH DATA product_isin = "FR0000131906" estimates_summaries = trading_api.get_estimates_summaries( product_isin=product_isin, raw=False, ) ``` Here are the available parameters for `Agenda.Request` : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |annual|google.protobuf.Struct|Indicators by year.| |currency|str|currency, example `EUR`.| |interim|google.protobuf.Struct|Indicators by quarter.| |lastRetrieved|str|Last Retrieved, example : `2021-12-31T20:07:30.939Z`.| |lastUpdated|str|Last updated,, example : `2021-02-18T01:30:00Z`.| |preferredMeasure|str|Preferred measure, example : `EPS`.| |ric|str|Reuters Instrument Code, example : `BOUY.PA`.| Exact definition of `EstimatesSummaries` is in this file : [trading.proto](protos/degiro_connector/trading/models/trading.proto) For a more comprehensive example : [estimates_summaries.py](examples/trading/estimates_summaries.py) # 9. Contributing Pull requests are welcome. Feel free to open an issue or send me a message if you have a question. # 10. License [BSD-3-Clause License](https://raw.githubusercontent.com/Chavithra/degiro-connector/main/LICENSE) %package help Summary: Development documents and examples for degiro-connector Provides: python3-degiro-connector-doc %description help # 1. **Degiro Connector** This is yet another library to access Degiro's API. Notes : - Migration scripts are available : ```bash python -m degiro_connector.migration.from_0_1_3_to_1_0_0 python -m degiro_connector.migration.from_1_0_4_to_1_0_5 python -m degiro_connector.migration.from_1_0_10_to_2_0_0 python -m degiro_connector.migration.from_2_0_2_to_2_0_3 ``` - `GRPC` services are available to let you consume this library through other languages like Javascript, Java, Go, C++, Rust, etc : ```bash python -m examples.quotecast.relay_server python -m examples.trading.relay_server ``` ## 1.1. Which features ? Here are the features you can access through this library : |**Endpoint**|**Feature(s)**| |:-|:-| |AccountCashReport|Export cash movements in a specific format : CSV, HTML, PDF or XLS.| |AccountInfo|Retrieve a table containing : "clientId" and Currencies.| |AccountOverview|Retrieve all the cash movements between two dates.| |Agenda|Crucial events regarding products : Dividend, Economic, Earnings, Holiday, IPO or Split.| |Bonds
ETFs
Funds
Futures
Leverageds
Lookup
Options
Stocks
Warrants|Search list of products according their name, type and other criterias.
For instance all the stocks from NASDAQ 100.| |Chart|Retrieve chart data.| |ClientDetails|Retrieve a table containing : "clientId", "intAccount" and other account information.| |CompanyProfile|Retrieve a company's profile using its ISIN code.| |CompanyRatios|Retrieve a company's ratios using its ISIN code.| |Config|Retrieve a table containing : "clientId" and URLs which are constitutive of Degiro's API.| |EstimatesSummaries|Retrieve a company's estimates summaries using its ISIN code.| |FavouritesList|Add/Delete/Retrieve favourites lists.| |FavouritesListProducts|Add/Update favourites lists content.| |FinancialStatements|Retrieve a company's financial statements using its ISIN code.| |LatestNews|Retrieve latest news about all the companies.| |LoginQuotecast|Establish a connection for quotecast operations.| |LoginTrading|Establish a connection for trading operations.| |LogoutTrading|Destroy previously established connection for trading operations.| |NewsByCompany|Retrieve news related to a specific company.| |Order|Create, update, delete an Order.| |OrderHistory|Retrieve all Orders created between two dates.| |Orders|List pending Orders.| |Portfolio|List products in your Portfolio.| |ProductsConfig|Retrieve a table containing : useful parameters to filter products.| |ProductsInfo|Search for products using their ids.| |Quotecasts|Fetch real-time data on financial products.
For instance the real-time stock Price.| |TopNewsPreview|Retrieve some news preview about all the companies.| |TotalPorfolio|Retrieve aggregated information about your assets.| |TransactionsHistory|Retrieve all Transactions created between two dates.| ## 1.2. How to install ? ```bash pip install degiro-connector ``` ## 1.3. How to upgrade ? ```bash pip install --no-cache-dir --upgrade degiro-connector ``` ## 1.4. How to uninstall ? ```bash pip uninstall degiro-connector ``` ## 1.5. Table of contents - [1. **Degiro Connector**](#1-degiro-connector) * [1.1. Which features ?](#11-which-features-) * [1.2. How to install ?](#12-how-to-install-) * [1.3. How to upgrade ?](#13-how-to-upgrade-) * [1.4. How to uninstall ?](#14-how-to-uninstall-) * [1.5. Table of contents](#15-table-of-contents) - [2. Real-time data](#2-real-time-data) * [2.1. What are the workflows ?](#21-what-are-the-workflows-) * [2.2. What are the credentials ?](#22-what-are-the-credentials-) * [2.3. How to find your : user_token ?](#23-how-to-find-your--user_token-) * [2.4. How to login ?](#24-how-to-login-) * [2.5. Is there a timeout ?](#25-is-there-a-timeout-) * [2.6. How to subscribe to a data-stream ?](#26-how-to-subscribe-to-a-data-stream-) * [2.7. How to unsubscribe to a data-stream ?](#27-how-to-unsubscribe-to-a-data-stream-) * [2.8. How to fetch the data ?](#28-how-to-fetch-the-data-) * [2.9. How to use this data ?](#29-how-to-use-this-data-) * [2.10. Which are the available data types ?](#210-which-are-the-available-data-types-) * [2.11. What is a Ticker ?](#211-what-is-a-ticker-) * [2.12. What is inside the Dictionary ?](#212-what-is-inside-the-dictionary-) * [2.13. What is inside the DataFrame ?](#213-what-is-inside-the-dataframe-) * [2.14. How to get chart data ?](#214-how-to-get-chart-data-) * [2.15. How to find a : vwd_id ?](#215-how-to-find-a--vwd_id-) - [3. Trading connection](#3-trading-connection) * [3.1. How to login ?](#31-how-to-login-) * [3.2. How to logout ?](#32-how-to-logout-) * [3.3. What are the credentials ?](#33-what-are-the-credentials-) * [3.4. How to find your : int_account ?](#34-how-to-find-your--int_account-) * [3.5. How to use 2FA ?](#35-how-to-use-2fa-) * [3.6. How to find your : totp_secret_key ?](#36-how-to-find-your--totp_secret_key-) * [3.7. How to find your : one_time_password ?](#37-how-to-find-your--one_time_password-) * [3.8. Is there a timeout ?](#38-is-there-a-timeout-) * [3.9. How to manage : TimeoutError ?](#39-how-to-manage--TimeoutError-) - [4. Order](#4-order) * [4.1. How to create an Order ?](#41-how-to-create-an-order-) * [4.1.1. Check Order](#411-check-order) * [4.1.2. Confirm Order](#412-confirm-order) * [4.2. How to update an Order ?](#42-how-to-update-an-order-) * [4.3. How to delete an Order ?](#43-how-to-delete-an-order-) - [5. Portfolio](#5-portfolio) * [5.1. How to retrieve pending Orders ?](#51-how-to-retrieve-pending-orders-) * [5.2. How to get the Portfolio ?](#52-how-to-get-the-portfolio-) * [5.3. How to get the TotalPortfolio ?](#53-how-to-get-the-totalportfolio-) * [5.4. How to retrieve the OrdersHistory ?](#54-how-to-retrieve-the-ordershistory-) * [5.5. How to retrieve the TransactionsHistory ?](#55-how-to-retrieve-the-transactionshistory-) - [6. Account](#6-account) * [6.1. How to retrieve the table : Config ?](#61-how-to-retrieve-the-table--config-) * [6.2. How to retrieve the table : ClientDetails ?](#62-how-to-retrieve-the-table--clientdetails-) * [6.3. How to retrieve the table : AccountInfo ?](#63-how-to-retrieve-the-table--accountinfo-) * [6.4. How to get the table : AccountOverview ?](#64-how-to-get-the-table--accountoverview-) * [6.5. How to export the table : CashAccountReport ?](#65-how-to-export-the-table--cashaccountreport-) * [6.6. How to export the table : PositionReport ?](#66-how-to-export-the-table--positionreport-) - [7. Products](#7-products) * [7.1. How to get the table : ProductsConfig ?](#71-how-to-get-the-table--productsconfig-) * [7.2. How to get my favourite products ?](#72-how-to-get-my-favourite-products-) * [7.3. How to lookup products (search by name) ?](#73-how-to-lookup-products-search-by-name-) * [7.4. How to search bonds ?](#74-how-to-search-bonds-) * [7.5. How to search etfs ?](#75-how-to-search-etfs-) * [7.6. How to search funds ?](#76-how-to-search-funds-) * [7.7. How to search futures ?](#77-how-to-search-futures-) * [7.8. How to search leverageds ?](#78-how-to-search-leverageds-) * [7.9. How to search options ?](#79-how-to-search-options-) * [7.10. How to search stocks ?](#710-how-to-search-stocks-) * [7.11. How to search warrants ?](#711-how-to-search-warrants-) * [7.12. How to search products from ids ?](#712-how-to-search-products-from-ids-) * [7.13. How to create a favourite list ?](#713-how-to-create-a-favourite-list-) * [7.14. How to delete a favourite list ?](#714-how-to-delete-a-favourite-list-) * [7.15. How to put favourite list products ?](#715-how-to-put-favourite-list-products-) * [7.16. How to delete favourite list products ?](#716-how-to-delete-favourite-list-products-) - [8. Companies](#8-companies) * [8.1. How to get : CompanyProfile ?](#81-how-to-get--companyprofile-) * [8.2. How to get : CompanyRatios ?](#82-how-to-get--companyratios-) * [8.3. How to get : FinancialStatements ?](#83-how-to-get--financialstatements-) * [8.4. How to get : LatestNews ?](#84-how-to-get--latestnews-) * [8.5. How to get : TopNewsPreview ?](#85-how-to-get--topnewspreview-) * [8.6. How to get : NewsByCompany ?](#86-how-to-get--newsbycompany-) * [8.7. How to get : Agenda ?](#87-how-to-get--agenda-) * [8.8. How to get : EstimatesSummaries ?](#88-how-to-get--estimatessummaries-) - [9. Contributing](#9-contributing) - [10. License](#10-license) # 2. Real-time data It is possible to fetch a stream of data in real-time from Degiro's API. For instance if one needs the following data from the "AAPL" stock : * LastDate * LastTime * LastPrice * LastVolume You can use this library to retrieve updates like this : LastDate LastTime LastPrice LastVolume 2020-11-13 22:00:00 119.26 4697040 For a list of available metrics, see the example in [section 2.6](#26-how-to-subscribe-to-a-data-stream-). ## 2.1. What are the workflows ? This is the workflow for consuming real-time data-stream : A. Find your "user_token". B. Setup the API object with your "user_token". C. Connect. D. Subscribe to data-stream. E. Fetch data-stream. This is the worflow for consuming charts : A. Find your "user_token". B. Setup the API object with your "user_token". C. Fetch charts. All the details of these steps are explained in the rest of this section. ## 2.2. What are the credentials ? The only credential you need in order to fetch real-time data and charts is the : * user_token Beware, these two identifiers are not the same thing : * user_token : used to fetch real-time data and charts. * int_account : used for some trading operations. ## 2.3. How to find your : user_token ? You can find your "user_token" inside one of these tables : * "Config" : attribute "clientId" * "ClientDetails" : attribute "id" See sections related to ["Config"](#61-how-to-retrieve-the-table--config-) and ["ClientDetails"](#62-how-to-retrieve-the-table--clientdetails-) tables. ## 2.4. How to login ? In order to fetch data you need to establish a connection. You can use the following code to connect : ```python # SETUP QUOTECAST API quotecast_api = API(user_token=YOUR_USER_TOKEN) # CONNECTION quotecast_api.connect() ``` ## 2.5. Is there a timeout ? Connection timeout is around 15 seconds. Which means a connection will cease to work after this timeout. This timeout is reset each time you use this connection to : * Subscribe to a metric (for instance a stock Price) * Fetch the data-stream So if you use it nonstop (in a loop) you won't need to reconnect. ## 2.6. How to subscribe to a data-stream ? To subscribe to a data-stream you need to setup a Request message. A Request has the following parameters : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |subscriptions|MessageMap|List of products and metrics to subscribe to.| |unsubscriptions|MessageMap|List of products and metrics to unsubscribe to.| Here is an example of a request : ```python request = Quotecast.Request() request.subscriptions['360015751'].extend([ 'LastDate', 'LastTime', 'LastPrice', 'LastVolume', 'AskPrice', 'AskVolume', 'LowPrice', 'HighPrice', 'BidPrice', 'BidVolume' ]) request.subscriptions['AAPL.BATS,E'].extend([ 'LastDate', 'LastTime', 'LastPrice', 'LastVolume', 'AskPrice', 'AskVolume', 'LowPrice', 'HighPrice', 'BidPrice', 'BidVolume' ]) ``` In this example these are the `vwd_id` of the products from which you want `Real-time data` : - 360015751 - AAPL.BATS,E See the [section](#215-how-to-find-a--vwd_id-) related to `vwd_id` for more information. Once you have built this Request object you can send it to Degiro's API like this : ```python quotecast_api.subscribe(request=request) ``` For more comprehensive examples : [realtime_poller.py](examples/quotecast/realtime_poller.py) / [realtime_one_shot.py](examples/quotecast/realtime_one_shot.py) ## 2.7. How to unsubscribe to a data-stream ? To remove metrics from the data-stream you need to setup a Request message. If you try to unsubscribe to a metric to which you didn't subscribed previously it will most likely have no impact. A Request has the following parameters : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |subscriptions|MessageMap|List of products and metrics to subscribe to.| |unsubscriptions|MessageMap|List of products and metrics to unsubscribe to.| Here is an example of a request : ```python request = Quotecast.Request() request.unsubscriptions['360015751'].extend([ 'LastDate', 'LastTime', 'LastPrice', 'LastVolume', 'AskPrice', 'AskVolume', 'LowPrice', 'HighPrice', 'BidPrice', 'BidVolume' ]) request.unsubscriptions['AAPL.BATS,E'].extend([ 'LastDate', 'LastTime', 'LastPrice', 'LastVolume', 'AskPrice', 'AskVolume', 'LowPrice', 'HighPrice', 'BidPrice', 'BidVolume' ]) ``` Once you have built this Request object you can send it to Degiro's API like this : ```python quotecast_api.subscribe(request=request) ``` For more comprehensive examples : [realtime_poller.py](examples/quotecast/realtime_poller.py) / [realtime_one_shot.py](examples/quotecast/realtime_one_shot.py) ## 2.8. How to fetch the data ? You can use the following code : ```python quotecast = quotecast_api.fetch_data() ``` For a more comprehensive example : [realtime_poller.py](examples/quotecast/realtime_poller.py) ## 2.9. How to use this data ? Received data is a `Quotecast` object with the following properties : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |json_data|dict|Dictionary representation of what Degiro's API has sent.| |metadata|Metadata|Containing the "response_datetime" and "request_duration".| Here is how to access these properties : ```python json_data = quotecast.json_data response_datetime = quotecast.metadata.response_datetime request_duration= quotecast.metadata.request_duration ``` Notes: * The API sometimes might return an empty Quotecast object. * The API often returns a subset of the requested metrics, e.g. only `'LastPrice'`. Please take this into account when appending consecutive data responses. ## 2.10. Which are the available data types ? This library provides the tools to convert Degiro's JSON data into something more programmer-friendly. Here is the list of available data types : |**Type**|**Description**| |:-|:-| |Ticker|Protobuf message (for GRPC).| |Dictionaries|Standard Python Dictionaries : **dict**.| |DataFrame|DataFrame from the library Pandas.| Here is how to build each type : ```python # UPDATE PARSER quotecast_parser.put_quotecast(quotecast=quotecast) # BUILD TICKER ticker = quotecast_parser.ticker # BUILD DICT ticker_dict = quotecast_parser.ticker_dict # BUILD PANDAS.DATAFRAME ticker_df = quotecast_parser.ticker_df ``` ## 2.11. What is a Ticker ? The generated Ticker contains : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |metadata|Metadata|Containing the "response_datetime" and "request_duration".| |products|MessageMap|Dictionary like object containing the metrics group by "vwd_id".| |product_list|RepeatedScalarFieldContainer|List of available "vwd_id".| Here are some operations available : ```python product = '360015751' metric_name = 'LastPrice' # ACCESS SPECIFIC PRODUCT product = ticker.products[product] # ACCESS SPECIFIC METRIC metric = product[metric_name] # LOOP OVER PRODUCTS for product in ticker.products: product = ticker.products[product] # LOOP OVER METRICS for metric_name in product.metrics: metric = product.metrics[metric_name] ``` A Ticker is a custom Protocol Buffer Message built for this library. It can be transmitted over GRPC framework. ## 2.12. What is inside the Dictionary ? The dictionary representation of a ticker contains the metrics grouped by "vwd_id" (product id), with : * keys : vwd_id * values : another dictionary with the metrics concerning this specific product. Example - Dictionary : ```python { '360114899': { 'vwd_id': 360114899, 'response_datetime': '2020-11-08 12:00:27', 'request_duration': 1.0224891666870117, 'LastDate': '2020-11-06', 'LastTime': '17:36:17', 'LastPrice': '70.0', 'LastVolume': '100' }, '360015751': { 'vwd_id': 360015751, 'response_datetime': '2020-11-08 12:00:27', 'request_duration': 1.0224891666870117, 'LastDate': '2020-11-06', 'LastTime': '17:36:17', 'LastPrice': '22.99', 'LastVolume': '470' } } ``` ## 2.13. What is inside the DataFrame ? In addition to whatever metrics you have chosen to subscribe to (see the example in [section 2.6](#26-how-to-subscribe-to-a-data-stream-)), the DataFrame will contain the following columns : |**Column**|**Description**| |:-|:-| |vwd_id|Product identifier, for instance "AAPL.BATS,E" for APPLE stock.| |response_datetime|Datetime at which the data was received.| |request_duration|Duration of the request used to fetch the data.| Example - DataFrame : vwd_id response_datetime request_duration LastDate LastTime LastPrice LastVolume 0 360114899 2020-11-08 12:00:27 1.022489 2020-11-06 17:39:57 70.0 100 1 360015751 2020-11-08 12:00:27 1.022489 2020-11-06 17:36:17 22.99 470 ## 2.14. How to get chart data ? You can fetch an object containing the same data than in Degiro's website graph. For that you need to prepare a Chart.Request object. Here is a table with the available attributes for Chart.Request. |**Parameter**|**Type**|**Description**| |:-|:-|:-| |requestid|str|It sends you back whatever string you put here, you can set it to : "1".| |resolution|Chart.Resolution|Resolution of the chart like : Chart.Resolution.PT1M.| |culture|str|Country code like : "en-US" or "fr-FR".| |period|Chart.Period|Period of the chart, like : Chart.Period.P1D.| |series|repeated string|Data to get like : ['issueid:36014897', 'price:issueid:360148977'].| |tz|str|Timezone like : "Europe/Paris"| Example of code : ```python request = Chart.Request() request.culture = "fr-FR" request.period = Chart.Interval.PT1H request.requestid = "1" request.resolution = Chart.Interval.P1D # request.series.append("issueid:360148977") # request.series.append("price:issueid:360148977") request.series.append("ohlc:issueid:360148977") # request.series.append("volume:issueid:360148977") # request.series.append("vwdkey:AAPL.BATS,E") # request.series.append("price:vwdkey:AAPL.BATS,E") # request.series.append("ohlc:vwdkey:AAPL.BATS,E") # request.series.append("volume:vwdkey:AAPL.BATS,E") request.tz = "Europe/Paris" # FETCH DATA chart = quotecast_api.get_chart( request=request, override={ "resolution": "P1D", "period": "P1W", }, raw=True, ) ``` The `issueid` parameter is the `vwd_id` of the product from which you want the `Chart` data. See the section related to `vwd_id` for more information. All the options for the enumerations are available in this file : [quotecast.proto](protos/degiro_connector/quotecast/models/quotecast.proto) For a more comprehensive examples : - [chart.py](examples/quotecast/chart.py) - [chart_format.py](examples/quotecast/chart_format.py) ## 2.15. How to find a : vwd_id ? In operations related to `Quotecast`, Degiro uses the `vwd_id` to identify a product. Which means that if you want a `Chart` or `Real-time data` for a specific product : you first need to find this product's `vwd_id`. This two identifiers are not the same : |**Identifier**|**API name(s)**|**Description**| |:-|:-|:-| |id|str|Id used identify a product in `Trading` related endpoints.| |vwd_id|issueid
vwdId
vwdIdSecondary
|Id used identify a product in `Quotecast` (`Chart` and `Real-time data`) related endpoint.| Here are some methods you can use to fetch a product's `vwd_id` : - `product_search` - `get_products_info` The method `product_search` let you use the name or other attributes of a product to fetch it's `vwd_id`. The method `get_products_info` let you use a product's `id` to fetch it's `vwd_id`. # 3. Trading connection This library is divided into two modules : - quotecast : to consume real-time financial data. - trading : to manage your Degiro's account. The module **quotecast** is described in the section related to real-time data. The rest of this document will only refer to the module : **trading**. ## 3.1. How to login ? In order to use the module **trading.api** you need to establish a connection. Check the section related to **int_account** to understand how to get yours. Here is how to connect : ```python # SETUP CREDENTIALS credentials = Credentials( username = YOUR_USERNAME, password = YOUR_PASSWORD, int_account = YOUR_INT_ACCOUNT, # OPTIONAL FOR LOGIN ) # SETUP TRADING API trading_api = API(credentials=credentials) # ESTABLISH CONNECTION trading_api.connect() ``` For a more comprehensive example : [connection.py](examples/trading/connection.py) ## 3.2. How to logout ? Once you no longer need to use the API you can destroy your connection. You can use the following code to disconnect : ```python # DESTROY CONNECTION trading_api.logout() ``` For a more comprehensive example : [logout.py](examples/trading/logout.py) ## 3.3. What are the credentials ? Some credentials are required to use Degiro's trading API. Here are these credentials : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |username|str|Username used to log into Degiro's website.| |password|str|Password used to log into Degiro's website.| |int_account|int|OPTIONAL : unique identifier of the account : used by Degiro's server.| |totp_secret_key|str|OPTIONAL : used for Two-factor Authentication (2FA).| |one_time_password|str|OPTIONAL : used for Two-factor Authentication (2FA).| Check the section related to **int_account** to understand how to get yours. Check the section related to **2FA** if you want to know more about these two parameters : - **totp_secret_key** - **one_time_password** ## 3.4. How to find your : int_account ? To get your **int_acccount** you can run this example : [client_details_table.py](examples/trading/client_details_table.py) See section related to **ClientDetails** table for more details. This **int_acccount** is required to do most of the trading operations available in this connector. Here are some operations for which your **int_acccount** is not required : - Connection - Fetch table : ClientDetails - Fetch table : Config Beware, these two identifiers are not the same thing : - user_token : used to fetch real-time data and charts. - int_account : used for some trading operations. ## 3.5. How to use 2FA ? First I will briefly explain what is : **Two-Factor Authentication (2FA)**. I recommend to skip a few paragraphs if you already know what is **2FA**. In a standard connection you are providing two parameters: - username - password If you use **Two-Factor Authentication (2FA)** you need an extra parameter: - one_time_password This **one_time_password** has a validity of 30 secondes and is generated using a **totp_secret_key** code. Usually you use an app like **‎Google Authenticator** to store this **totp_secret_key** and generate the **one_time_password**. The **totp_secret_key** is stored inside the QRCode which is displayed when you enable 2FA on Degiro's website To use **2FA** with this library you have two solutions. **SOLUTION 1** Provide your **totp_secret_key** : the library will use it to generate a new **one_time_password** at each connection. So you won't have to type your **one_time_password** manually at each connection. This is the proper way. See the section about **totp_secret_key** to understand how to get yours. Here is an example of connection with the **totp_secret_key** : ```python # SETUP CREDENTIALS credentials = Credentials( username=YOUR_USERNAME, password=YOUR_PASSWORD, int_account=YOUR_INT_ACCOUNT, # OPTIONAL FOR LOGIN totp_secret_key=YOUR_2FA_SECRET_KEY, # ONLY IF 2FA IS ENABLED ) # SETUP TRADING API trading_api = API(credentials=credentials) # ESTABLISH CONNECTION trading_api.connect() ``` A complete example here : [connection_2fa.py](examples/trading/connection_2fa.py) **SOLUTION 2** Provide a new **one_time_password** at each connection. Here is an example of connection with the **one_time_password** : ```python # SETUP CREDENTIALS credentials = Credentials( username=YOUR_USERNAME, password=YOUR_PASSWORD, int_account=YOUR_INT_ACCOUNT, # OPTIONAL FOR LOGIN one_time_password=YOUR_2FA_OTP, # ONLY IF 2FA IS ENABLED ) # SETUP TRADING API trading_api = API(credentials=credentials) # ESTABLISH CONNECTION trading_api.connect() ``` A complete example here : [connection_otp.py](examples/trading/connection_otp.py) ## 3.6. How to find your : totp_secret_key ? The parameter **totp_secret_key** is only required if you have enabled `2FA` on Degiro's website. When you try to activate `2FA` on Degiro's website, it displays a `QRCode`. This `QRCode` changes at each activation. A `QRCode` is a picture which can be converted into a text. You can download this `QRCode` and use a tool to extract the text from it. This extracted text will look like this : otpauth://totp/DEGIRO:YOUR_USERNAME?algorithm=SHA1&issuer=DEGIRO&secret=YOUR_TOPT_SECRET_KEY&digits=6&period=30 Has you can guess the "totp_secret_key" is in this part : secret=YOUR_TOPT_SECRET_KEY Here is an example of script that extracts the text from a `QRCode` : [qrcode.py](examples/trading/qrcode.py) ## 3.7. How to find your : one_time_password ? The parameter **one_time_password** is the password you type when you log in the website using **2FA**. Usually you get it through an app like **Google Authenticator**. It is preferable to use the parameter **totp_secret_key** instead of **one_time_password**. ## 3.8. Is there a timeout ? A connection for trading operations has a timeout of 30 minutes. It's [defined](https://github.com/Chavithra/degiro-connector/blob/main/degiro_connector/core/constants/timeouts.py#L2) in seconds as constant `timeouts.TRADING_TIMEOUT`. The timeout period is started when the [`TradingAPI.connect()`](#31-how-to-login-) results successfully. Every time an operation is made to this `TradingAPI` connection, the timeout for this connection will be reset. If a `TradingAPI` connection is left unused during the timeout period, the connection will expire. Every consecutive function call to the `TraderAPI` will then throw a `TimeoutError` exception. A connection timeout might occur when your trading strategy only performs a few trades per day, e.g. once per hour. So when finally a buy opportuntiy occurs, [`check_order()`](#411-check-order): ```python # FETCH CHECKING_RESPONSE checking_response = trading_api.check_order(order=order) ``` Will fail with `TimeoutError`: ``` TimeoutError: Connection has probably expired. ``` ## 3.9. How to manage : TimeoutError ? **HANDLE EXCEPTION** It's recommended to catch the `TimeoutError` on every function call to the `TradingAPI`. When it's detected, it's sufficient to call [`connect()`](#31-how-to-login-) again, followed by repeating the original call that threw the exception. Example for the [`check_order()`](#411-check-order) call: ```python try: checking_response = trading_api.check_order(order=order) except TimeoutError: logging.warning("TradingAPI session did timeout, reconnecting for new session ID...") trading_api.connect() checking_response = trading_api.check_order(order=order) ``` This shows the following in the log, while the order is checked successfully after a successful reconnect: ```python WARNING - TradingAPI session did timeout, reconnecting for new session ID... INFO - get_session_id:response_dict: {'isPassCodeEnabled': False, 'locale': 'nl_NL', 'redirectUrl': 'https://trader.degiro.nl/trader/', 'sessionId': '2BADBBEF3****', 'status': 0, 'statusText': 'success'} INFO - confirmation_id: "053df7cf-****" response_datetime { seconds: 1643801134 nanos: 715765000 } ``` **REFRESH TIMEOUT** As mentioned before, the timeout will be reset after each call to the `TradingAPI`. This provides the opportunity to make a periodic function call, for example every 10 minutes to [`get_update()`](#51-how-to-retrieve-pending-orders-). However, this might interfere with your other logic and might not be robust over time when DeGiro decides to decrease the timeout on their server. Therefor it's strongly recommended to always incorporate the exception handling for `TimeoutError` as indicated in the example above. **CHANGE PERIOD** It's possible to change the timeout period while creating the `TradingAPI`. Just add a `ModelConnection` object for parameter `connection_storage`: ```python # SETUP TRADING API trading_api = TradingAPI( credentials=credentials, connection_storage=ModelConnection( timeout=600, ) ) # Connect: trading_api.connect() ``` The connection will now expire after 10 minutes (10 * 60 s). # 4. Order Creating and updating of orders is done with an `Order` object. Here are the parameters: |**Parameter**|**Type**|**Description**| |:-|:-|:-| |id|str|Optional for [`update_order()`](#42-how-to-update-an-order-). It's the `order_id` of the created `Order` as returned by [`confirm_order()`](#412-confirm-order).| |action|`Order.Action`|Whether you want to : `BUY` or `SELL`.| |order_type|`Order.OrderType`|Type of order : `LIMIT`, `STOP_LIMIT`, `MARKET` or `STOP_LOSS`.| |price|float|Limit price of the order.
Optional for the following `order_type` : `LIMIT` and `STOPLIMIT`.| |product_id|int|Identifier of the product concerned by the order.| |size|float|Size of the order.| |stop_price|float|Stop price of the order.
Optional for the following `order_type` : `STOPLIMIT` and `STOPLOSS`| |time_type|`Order.TimeType`|Duration of the order : `GOOD_TILL_DAY` or `GOOD_TILL_CANCELED`| The full description of an `Order` is available here : [trading.proto](protos/degiro_connector/trading/models/trading.proto) ## 4.1. How to create an Order ? The order creation is done in two steps : 1. Checking : send the `Order` to the API to check if it is valid. 2. Confirmation : confirm the creation of the `Order`. Keeping these two steps (instead of reducing to one single "create" function) provides more options. ## 4.1.1 Check order Use the `check_order()` function of the Trading API: ### **Request parameters** |**Parameter**|**Type**|**Description**| |:-|:-|:-| |order|`Order`|The order to create with all necessary [parameters](#4-order).| ### **Response parameters** On a succesfull request, a `dict` with the following parameters is returned: |**Parameter**|**Type**|**Description**| |:-|:-|:-| |confirmation_id|str|Id necessary to confirm the creation of the Order by the [`confirm_order()`](#412-confirm-order) function.| |response_datetime|[`Timestamp`](https://pythonhosted.org/gax-google-pubsub-v1/google.protobuf.timestamp_pb2.html)|A `Timestamp` represents a point in time independent of any time zone or calendar, represented as seconds (`seconds`) and fractions of seconds at nanosecond resolution (`nanos`) in UTC Epoch time. A `Timestamp` can be converted to a RFC 3339 date string by using `ToJsonString()`.
Note: This `Timestamp` is created by Degiro Connector on reception of the API response, not by DeGiro server.| |free_space_new|float|New free space (balance) if the Order is confirmed.| |transaction_fees|float|Transaction fees that will be applied to the Order.| |show_ex_ante_report_link|bool|?| When the request fails, `None` is returned. ## 4.1.2 Confirm order Use the `confirm_order()` function of the Trading API: ### **Request parameters** |**Parameter**|**Type**|**Description**| |:-|:-|:-| |confirmation_id|str|The confirmtation id from the [`check_order()`](#411-check-order) response.| |order|`Order`|The same order from the [`check_order()`](#411-check-order) request.| ### **Response parameters** On a succesfull request, a `dict` with the following parameters is returned: |**Parameter**|**Type**|**Description**| |:-|:-|:-| |order_id|str|A unique id of the accepted order. This id is required to [update](#42-how-to-update-an-order-) or [delete](#43-how-to-delete-an-order-) the pending order.| |response_datetime|[`Timestamp`](https://pythonhosted.org/gax-google-pubsub-v1/google.protobuf.timestamp_pb2.html)|A `Timestamp` represents a point in time independent of any time zone or calendar, represented as seconds (`seconds`) and fractions of seconds at nanosecond resolution (`nanos`) in UTC Epoch time. A `Timestamp` can be converted to a RFC 3339 date string by using `ToJsonString()`.
Note: This `Timestamp` is created by Degiro Connector on reception of the API response, not by DeGiro server.| When the request fails, `None` is returned. ## 4.1.3 Example of combining these functions ```python # SETUP ORDER order = Order( action=Order.Action.BUY, order_type=Order.OrderType.LIMIT, price=10, product_id=71981, size=1, time_type=Order.TimeType.GOOD_TILL_DAY, ) # FETCH CHECKING_RESPONSE checking_response = trading_api.check_order(order=order) # EXTRACT CONFIRMATION_ID confirmation_id = checking_response.confirmation_id # SEND CONFIRMATION confirmation_response = trading_api.confirm_order( confirmation_id=confirmation_id, order=order, ) ``` For a more comprehensive example : [order.py](examples/trading/order.py) ## 4.2. How to update an Order ? To modify a specific Order, you need to set it up with the `order_id` from the [`confirm_order()`](#412-confirm-order) response and use the `update_order()` function of the Trading API: ### **Request parameters** |**Parameter**|**Type**|**Description**| |:-|:-|:-| |order|`Order`|The order to update with all necessary [parameters](#4-order), including `id` as returned by [`confirm_order()`](#412-confirm-order).| ### **Response parameters** On a succesfull request, a `bool` with the value `True` is returned. When the request fails, `None` is returned. A valid reason is that the pending order has been already executed on the exchange, and this `order_id` no longer exists. Here is an example: ```python # ORDER SETUP order = Order( id=YOUR_ORDER_ID, # `order_id` from `confirm_order()` response action=Order.Action.BUY, order_type=Order.OrderType.LIMIT, price=10.60, product_id=71981, size=1, time_type=Order.TimeType.GOOD_TILL_DAY, ) # UPDATE ORDER succcess = trading_api.update_order(order=order) ``` ## 4.3. How to delete an Order ? To delete a specific Order you just need the `order_id` from the [`confirm_order()`](#412-confirm-order) response and use the `delete_order()` function of the Trading API: ### **Request parameters** |**Parameter**|**Type**|**Description**| |:-|:-|:-| |order_id|str|The unique id of the accepted order as returned by [`confirm_order()`](#412-confirm-order).| ### **Response parameters** On a succesfull request, a `bool` with the value `True` is returned. When the request fails, `None` is returned. A valid reason is that the pending order has been already executed on the exchange, and this `order_id` no longer exists. Here is an example: ```python # DELETE ORDER succcess = trading_api.delete_order(order_id=YOUR_ORDER_ID) # `order_id` from `confirm_order()` response ``` # 5. Portfolio ## 5.1. How to retrieve pending Orders ? This is how to get the list of Orders currently created but not yet executed or deleted : ```python request_list = Update.RequestList() request_list.values.extend([ Update.Request(option=Update.Option.ORDERS, last_updated=0), ]) update = trading_api.get_update(request_list=request_list) update_dict = pb_handler.message_to_dict(message=update) orders_df = pd.DataFrame(update_dict['orders']['values']) ``` Example : Orders product_id time_type price size id ... action order_type stop_price retained_order sent_to_exchange 0 0 GOOD_TILL_DAY 2 3 202cb962-ac59-075b-964b-07152d234b70 ... BUY LIMIT 16 17 18 For a more comprehensive example : [update.py](examples/trading/update.py) ## 5.2. How to get the Portfolio ? This is how to list the stocks/products currently in the portfolio : ```python request_list = Update.RequestList() request_list.values.extend([ Update.Request(option=Update.Option.PORTFOLIO, last_updated=0), ]) update = trading_api.get_update(request_list=request_list) update_dict = pb_handler.message_to_dict(message=update) portfolio_df = pd.DataFrame(update_dict['portfolio']['values']) ``` For a more comprehensive example : [update.py](examples/trading/update.py) Note: In order to resolve product IDs to Human readable names, see [7.12. How to search products from ids ?](#712-how-to-search-products-from-ids-) ## 5.3. How to get the TotalPortfolio ? This is how to get aggregated data about the portfolio : ```python request_list = Update.RequestList() request_list.values.extend([ Update.Request(option=Update.Option.TOTALPORTFOLIO, last_updated=0), ]) update = trading_api.get_update(request_list=request_list) update_dict = pb_handler.message_to_dict(message=update) total_portfolio_df = pd.DataFrame(update_dict['total_portfolio']['values']) ``` Example : DataFrame degiroCash flatexCash totalCash totalDepositWithdrawal todayDepositWithdrawal ... reportNetliq reportOverallMargin reportTotalLongVal reportDeficit marginCallStatus 0 0 1 2 3 4 ... 16 17 18 19 NO_MARGIN_CALL For a more comprehensive example : [update.py](examples/trading/update.py) ## 5.4. How to retrieve the OrdersHistory ? This method returns data about passed orders between two dates. The result contains a list of "Orders" objects with the following attributes : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |created|str|RFC 3339 Datetime, example : "2020-10-06T20:07:18+02:00".| |orderId|str|MD5 HASH, example : "098f6bcd-4621-d373-cade-4e832627b4f6"| |productId|int|Id of the product example : 65156| |size|float|Size of the order, example : 10.0000| |price|float|Price of the order, example : 8.6800| |buysell|str|"B" or "S"| |orderTypeId|int|see 3.Order| |orderTimeTypeId|int|see 3.Order| |stopPrice|float|Price like : 0.0000| |totalTradedSize|int|-| |type|str|"CREATE", "DELETE" or "MODIFY"| |status|str|"CONFIRMED"| |last|str|RFC 3339 Datetime, example : "2020-10-06T20:07:18+02:00".| |isActive|bool|-| Here is how to get this data : ```python # SETUP REQUEST from_date = OrdersHistory.Request.Date(year=2020,month=11,day=15) to_date = OrdersHistory.Request.Date(year=2020,month=10,day=15) request = OrdersHistory.Request(from_date=from_date, to_date=to_date) # FETCH DATA orders_history = trading_api.get_orders_history(request=request) ``` For a more comprehensive example : [orders_history.py](examples/trading/orders_history.py) ## 5.5. How to retrieve the TransactionsHistory ? Here is how to get this data : ```python # SETUP REQUEST from_date = TransactionsHistory.Request.Date(year=2020,month=11,day=15) to_date = TransactionsHistory.Request.Date(year=2020,month=10,day=15) request = TransactionsHistory.Request(from_date=from_date, to_date=to_date) # FETCH DATA transactions_history = trading_api.get_transactions_history(request=request) ``` For a more comprehensive example : [transactions_history.py](examples/trading/transactions_history.py) # 6. Account ## 6.1. How to retrieve the table : Config ? The config table contains the following informations : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |sessionId|str|Current session id.| |clientId|int|Unique Degiro's Account identifier also called "userToken"| |tradingUrl|str|-| |paUrl|str|-| |reportingUrl|str|-| |paymentServiceUrl|str|-| |productSearchUrl|str|-| |dictionaryUrl|str|-| |productTypesUrl|str|-| |companiesServiceUrl|str|-| |i18nUrl|str|-| |vwdQuotecastServiceUrl|str|-| |vwdNewsUrl|str|-| |vwdGossipsUrl|str|-| |taskManagerUrl|str|-| |refinitivNewsUrl|str|-| |refinitivAgendaUrl|str|-| |refinitivCompanyProfileUrl|str|-| |refinitivCompanyRatiosUrl|str|-| |refinitivFinancialStatementsUrl|str|-| |refinitivClipsUrl|str|-| |landingPath|str|-| |betaLandingPath|str|-| |mobileLandingPath|str|-| |loginUrl|str|-| Here is how to get this table : ```python # FETCH DATA config_table = trading_api.get_config() # EXTRACT SOME DATA user_token = config_table['clientId'] session_id = config_table['sessionId'] ``` For a more comprehensive example : [config_table.py](examples/trading/config_table.py) ## 6.2. How to retrieve the table : ClientDetails ? The ClientDetails table contains information about the current Degiro Account. |**Parameter**|**Type**| |:-|:-| |id|int| |intAccount|int| |loggedInPersonId|int| |clientRole|str| |effectiveClientRole|str| |contractType|str| |username|str| |displayName|str| |email|str| |firstContact.firstName|str| |firstContact.lastName|str| |firstContact.displayName|str| |firstContact.nationality|str| |firstContact.gender|str| |firstContact.dateOfBirth|str| |firstContact.placeOfBirth|str| |firstContact.countryOfBirth|str| |address.streetAddress|str| |address.streetAddressNumber|str| |address.zip|str| |address.city|str| |address.country|str| |cellphoneNumber|str| |locale|str| |language|str| |culture|str| |bankAccount.bankAccountId|int| |bankAccount.bic|str| |bankAccount.iban|str| |bankAccount.status|str| |flatexBankAccount.bic|str| |flatexBankAccount.iban|str| |memberCode|str| |isWithdrawalAvailable|bool| |isAllocationAvailable|bool| |isIskClient|bool| |isCollectivePortfolio|bool| |isAmClientActive|bool| |canUpgrade|bool| Here is how to get this table : ```python # FETCH DATA client_details_table = trading_api.get_client_details() # EXTRACT SOME DATA int_account = client_details_table['data']['intAccount'] user_token = client_details_table['data']['id'] ``` For a more comprehensive example : [client_details_table.py](examples/trading/client_details_table.py) ## 6.3. How to retrieve the table : AccountInfo ? The AccountInfo table contains the following information about currencies. |**Parameter**|**Type**| |:-|:-| |clientId|int| |baseCurrency|str| |currencyPairs|dict| |marginType|str| |cashFunds|dict| |compensationCapping|float|-| Here is how to get this table : ```python account_info_table = trading_api.get_account_info() ``` For a more comprehensive example : [account_info_table.py](examples/trading/account_info_table.py) ## 6.4. How to get the table : AccountOverview ? It will provide a list of cash movements. Here is how to get this data : ```python # SETUP REQUEST from_date = AccountOverview.Request.Date(year=2020,month=11,day=15) to_date = AccountOverview.Request.Date(year=2020,month=10,day=15) request = AccountOverview.Request(from_date=from_date, to_date=to_date) # FETCH DATA account_overview = trading_api.get_account_overview(request=request) ``` For a more comprehensive example : [account_overview.py](examples/trading/account_overview.py) Each cash movement contains this kind of parameters : |**Parameter**|**Type**| |:-|:-| |date|str| |valueDate|str| |id|int| |orderId|str| |description|str| |productId|int| |currency|str| |change|float| |balance|dict| |unsettledCash|float| |total|float| ## 6.5. How to export the table : CashAccountReport ? It will export a list of cash movements in a specific format. Available formats : - CSV - HTML - PDF - XLS Here is how to get this content in `CSV` format : ```python # SETUP REQUEST from_date = CashAccountReport.Request.Date(year=2020,month=11,day=15) to_date = CashAccountReport.Request.Date(year=2020,month=10,day=15) request = CashAccountReport.Request( format=CashAccountReport.Format.CSV, country='FR', lang='fr', from_date=from_date, to_date=to_date, ) # FETCH DATA cash_account_report = trading_api.get_cash_account_report( request=request, raw=False, ) ``` Here are the available parameters for `CashAccountReport.Request` : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |format|CashAccountReport.Format|Wanted format :
`CSV`
`HTML`
`PDF`
`XLS`| |country|str|Country name, like : `FR`| |lang|int|Language, like : `fr`| |from_date|CashAccountReport.Request.Date|Events starting after this date.| |to_date|CashAccountReport.Request.Date|Events before this date.| Exact definitions of `CashAccountReport` and `CashAccountReport.Request` are in this file : [trading.proto](protos/degiro_connector/trading/models/trading.proto) For a more comprehensive example : [cash_account_report.py](examples/trading/cash_account_report.py) ## 6.6. How to export the table : PositionReport ? It will export a list of cash movements in a specific format. Available formats : - CSV - HTML - PDF - XLS Here is how to get this content in `CSV` format : ```python # SETUP REQUEST to_date = CashAccountReport.Request.Date(year=2020,month=10,day=15) request = CashAccountReport.Request( format=CashAccountReport.Format.CSV, country='FR', lang='fr', to_date=to_date, ) # FETCH DATA position_report = trading_api.get_position_report( request=request, raw=False, ) ``` Here are the available parameters for `PositionReport.Request` : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |format|PositionReport.Format|Wanted format :
`CSV`
`HTML`
`PDF`
`XLS`| |country|str|Country name, like : `FR`| |lang|int|Language, like : `fr`| |to_date|PositionReport.Request.Date|Events before this date.| Exact definitions of `PositionReport` and `PositionReport.Request` are in this file : [trading.proto](protos/degiro_connector/trading/models/trading.proto) For a more comprehensive example : [position_report.py](examples/trading/position_report.py) # 7. Products ## 7.1. How to get the table : ProductsConfig ? This table contains useful parameters to filter products. Here are the parameters which are inside this table : |**Parameter**|**Type**| |:-|:-| |stockCountries|list| |bondExchanges|list| |bondIssuerTypes|list| |eurexCountries|list| |futureExchanges|list| |optionExchanges|list| |combinationExchanges|list| |cfdExchanges|list| |exchanges|list| |indices|list| |regions|list| |countries|list| |productTypes|list| |etfFeeTypes|list| |investmentFundFeeTypes|list| |optionAggregateTypes|list| |leveragedAggregateTypes|list| |etfAggregateTypes|list| |investmentFundAggregateTypes|list| |lookupSortColumns|list| |stockSortColumns|list| |bondSortColumns|list| |cfdSortColumns|list| |etfSortColumns|list| |futureSortColumns|list| Here is how to get this data : ```python # FETCH DATA products_config = trading_api.get_products_config() ``` For a more comprehensive example : [products_config.py](examples/trading/products_config.py) ## 7.2. How to get my favourite products ? Here is how to get this data : ```python # FETCH DATA favourites_list = trading_api.get_favourites_list() ``` For a more comprehensive example : [favourites_list.py](examples/trading/favourites_list.py) ## 7.3. How to lookup products (search by name) ? Text research on a financial product. Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestLookup( search_text='APPLE', limit=10, offset=0, product_type_id=1, ) # FETCH DATA products_lookup = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_lookup.py](examples/trading/product_lookup.py) ## 7.4. How to search bonds ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestBonds( bond_issuer_type_id=0, bond_exchange_id=710, search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA bond_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.5. How to search etfs ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestETFs( popular_only=False, input_aggregate_types='', input_aggregate_values='', search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA etf_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.6. How to search funds ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestFunds( search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA fund_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.7. How to search futures ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestFutures( future_exchange_id=1, underlying_isin='FR0003500008', search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA fund_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.8. How to search leverageds ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestLeverageds( popular_only=False, input_aggregate_types='', input_aggregate_values='', search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA etf_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.9. How to search options ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestOptions( input_aggregate_types='', input_aggregate_values='', option_exchange_id=3, underlying_isin='FR0003500008', search_text='', offset=0, limit=100, require_total=True, sort_columns='expirationDate,strike', sort_types='asc,asc', ) # FETCH DATA option_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.10. How to search stocks ? It contains information about available stocks. Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestStocks( index_id=122001, # NASDAQ 100 exchange_id=663, # NASDAQ # You can either use `index_id` or `exchange id` # See which one to use in the `ProductsConfig` table is_in_us_green_list=True, stock_country_id=846, # US search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA stock_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.11. How to search warrants ? Here is how to get this data : ```python # SETUP REQUEST request = ProductSearch.RequestWarrants( search_text='', offset=0, limit=100, require_total=True, sort_columns='name', sort_types='asc', ) # FETCH DATA warrant_list = trading_api.product_search(request=request) ``` For a more comprehensive example : [product_search.py](examples/trading/product_search.py) ## 7.12. How to search products from ids ? Here is how to get this data : ```python # SETUP REQUEST request = ProductsInfo.Request() request.products.extend([96008, 1153605, 5462588]) # FETCH DATA products_info = trading_api.get_products_info( request=request, raw=True, ) ``` For a more comprehensive example : [products_info.py](examples/trading/products_info.py) ## 7.13. How to create a favourite list ? Example : ```python favorite_list_id = trading_api.create_favourite_list(name="SOME_NAME") ``` For a more comprehensive example : [favourite_list_create.py](examples/trading/favourite_list_create.py) ## 7.14. How to delete a favourite list ? Example : ```python success = trading_api.delete_favourite_list(id=1234567) ``` For a more comprehensive example : [favourite_list_delete.py](examples/trading/favourite_list_delete.py) ## 7.15. How to put favourite list products ? Example : ```python success = trading_api.put_favourite_list_product( id=1234567, product_id=1234567, ) ``` For a more comprehensive example : [favourite_list_put_product.py](examples/trading/favourite_list_put_product.py) ## 7.16. How to delete favourite list products ? Example : ```python success = trading_api.delete_favourite_list_product( id=1234567, product_id=1234567, ) ``` For a more comprehensive example : [favourite_list_delete product.py](examples/trading/favourite_list_delete product.py) # 8. Companies ## 8.1. How to get : CompanyProfile ? Here is how to get this data : ```python # FETCH DATA company_profile = trading_api.get_company_profile( product_isin='FR0000131906', ) ``` For a more comprehensive example : [company_profile.py](examples/trading/company_profile.py) ## 8.2. How to get : CompanyRatios ? This table contains information about the company. Here are the parameters which are inside this table : |**Parameter**|**Type**| |:-|:-| |totalFloat|str| |sharesOut|str| |consRecommendationTrend|dict| |forecastData|dict| |currentRatios|dict| Here is how to get this data : ```python # FETCH DATA company_ratios = trading_api.get_company_ratios( product_isin='FR0000131906', ) ``` For a more comprehensive example : [company_ratios.py](examples/trading/company_ratios.py) ## 8.3. How to get : FinancialStatements ? Here is how to get this data : ```python # FETCH DATA financials_statements = trading_api.get_financials_statements( product_isin='FR0000131906', ) ``` For a more comprehensive example : [financial_statements.py](examples/trading/financial_statements.py) ## 8.4. How to get : LatestNews ? Here is how to get this data : ```python # SETUP REQUEST request = LatestNews.Request( offset=0, languages='en,fr', limit=20, ) # FETCH DATA latest_news = trading_api.get_latest_news( request=request, raw=True, ) ``` For a more comprehensive example : [latest_news.py](examples/trading/latest_news.py) ## 8.5. How to get : TopNewsPreview ? Here is how to get this data : ```python # FETCH DATA top_news_preview = trading_api.get_top_news_preview(raw=True) ``` For a more comprehensive example : [top_news_preview.py](examples/trading/top_news_preview.py) ## 8.6. How to get : NewsByCompany ? Here is how to get this data : ```python # SETUP REQUEST request = NewsByCompany.Request( isin='NL0000235190', limit=10, offset=0, languages='en,fr', ) # FETCH DATA news_by_company = trading_api.get_news_by_company( request=request, raw=True, ) ``` For a more comprehensive example : [news_by_company.py](examples/trading/news_by_company.py) ## 8.7. How to get : Agenda ? Here is how to get this data : ```python # SETUP REQUEST request = Agenda.Request() request.start_date.FromJsonString('2021-06-21T22:00:00Z') request.end_date.FromJsonString('2021-11-28T23:00:00Z') request.calendar_type = Agenda.CalendarType.DIVIDEND_CALENDAR request.offset = 0 request.limit = 25 # FETCH DATA agenda = trading_api.get_agenda( request=request, raw=False, ) ``` Here are the available parameters for `Agenda.Request` : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |calendar_type|Agenda.CalendarType|Type of agenda :
`DIVIDEND_CALENDAR`
`ECONOMIC_CALENDAR`
`EARNINGS_CALENDAR`
`HOLIDAY_CALENDAR`
`IPO_CALENDAR`
`SPLIT_CALENDAR`| |offset|int|-| |limit|int|-| |order_by_desc|bool|-| |start_date|Timestamp|Events starting after this date.| |end_date|Timestamp|Events before this date.| |company_name|str|Filter used on the events description.| |countries|str|Comma separated list of countries like : `FR,US`| |classifications|str|Comma separated list of sectors like : `GovernmentSector,ExternalSector`| |units|str|Comma separated list of units like : `Acre,Barrel`| Exact definitions of `Agenda` and `Agenda.Request` are in this file : [trading.proto](protos/degiro_connector/trading/models/trading.proto) For a more comprehensive example : [agenda.py](examples/trading/agenda.py) ## 8.8. How to get : EstimatesSummaries ? Here is how to get this data : ```python # SETUP REQUEST request = Agenda.Request() request.start_date.FromJsonString('2021-06-21T22:00:00Z') request.end_date.FromJsonString('2021-11-28T23:00:00Z') request.calendar_type = Agenda.CalendarType.DIVIDEND_CALENDAR request.offset = 0 request.limit = 25 # FETCH DATA product_isin = "FR0000131906" estimates_summaries = trading_api.get_estimates_summaries( product_isin=product_isin, raw=False, ) ``` Here are the available parameters for `Agenda.Request` : |**Parameter**|**Type**|**Description**| |:-|:-|:-| |annual|google.protobuf.Struct|Indicators by year.| |currency|str|currency, example `EUR`.| |interim|google.protobuf.Struct|Indicators by quarter.| |lastRetrieved|str|Last Retrieved, example : `2021-12-31T20:07:30.939Z`.| |lastUpdated|str|Last updated,, example : `2021-02-18T01:30:00Z`.| |preferredMeasure|str|Preferred measure, example : `EPS`.| |ric|str|Reuters Instrument Code, example : `BOUY.PA`.| Exact definition of `EstimatesSummaries` is in this file : [trading.proto](protos/degiro_connector/trading/models/trading.proto) For a more comprehensive example : [estimates_summaries.py](examples/trading/estimates_summaries.py) # 9. Contributing Pull requests are welcome. Feel free to open an issue or send me a message if you have a question. # 10. License [BSD-3-Clause License](https://raw.githubusercontent.com/Chavithra/degiro-connector/main/LICENSE) %prep %autosetup -n degiro-connector-2.0.23 %build %py3_build %install %py3_install install -d -m755 %{buildroot}/%{_pkgdocdir} if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi pushd %{buildroot} if [ -d usr/lib ]; then find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst fi if [ -d usr/lib64 ]; then find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst fi if [ -d usr/bin ]; then find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst fi if [ -d usr/sbin ]; then find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst fi touch doclist.lst if [ -d usr/share/man ]; then find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst fi popd mv %{buildroot}/filelist.lst . mv %{buildroot}/doclist.lst . %files -n python3-degiro-connector -f filelist.lst %dir %{python3_sitelib}/* %files help -f doclist.lst %{_docdir}/* %changelog * Fri May 05 2023 Python_Bot - 2.0.23-1 - Package Spec generated