lolokraus / DegiroAPI

An unofficial API for the trading platform Degiro, with the ability to get real time data and historical data
MIT License
215 stars 86 forks source link

Function egg, 2FA, bidprices #26

Open korneel69 opened 3 years ago

korneel69 commented 3 years ago

Hey Guys,

Thanks a lot for developing this API, it really is a gift from above. You are an angel! To further improve the security, I was thinking to implement 2FA (à la: https://github.com/pladaria/degiro) and some way of pulling bid prices (ideas?). However the egg thingy prevents me from doing so... Relatively new to python, but why did you use an egg structure in this context?

korneel69 commented 3 years ago

Bid prices are not given when calling the API but maybe a work-around with beautiful soup could somewhat solve the issue, donno

Jakub-CZ commented 3 years ago

Unfortunately, the original author is unresponsive, so they are not accepting Pull Requests with additional features. Somebody may have to take over, fork this project and start publishing it under a different name in PyPI.

2FA

You could notice that 2FA has been contributed by @pforero here: #12

If you want, you can very easily install his version that has 2FA using this command:

pip install -U git+https://github.com/pforero/DegiroAPI.git@totp

egg

As of the "egg", I'm not sure what you're talking about. You need to explain what your problem with the "egg" is.

My wild guess would be that you installed this package from PyPI (Python repository) and then you attempted to edit the files in ...\Lib\site-packages\degiroapi.

If you want to make your own edits in this project, you should instead:

  1. Clone this project, or download and extract the source
  2. In the folder that contains "setup.py", run pip install -U -e .
  3. Now, when you make changes in your source code, they take an immediate effect, no need to rerun pip install again.

Bid prices

What do you mean exactly? Price of share in the last trade? Or actually the current best Bid and best Ask?

korneel69 commented 3 years ago

Wow! Great response! Thanks man!

I will definitely check the 2FA version out! As for the egg, I meant a Python Egg (first time seeing it), and I did indeed try to make some changes to the init file to achieve 2FA. But I couldn't, so it bothered me. But that's not an issue anymore with the 2FA version you referenced. Need to look into the Egg thingy a bit deeper tho...

I do indeed mean the current best bid and best ask. At the moment I'm using the last trade price, since its the only price we can consult via the API. However best bid and best ask price would be more useful. When looking at the Degiro UI the best bid and ask prices are provided. So I was wondering if it was possible to scrape them from the UI and use them that way. Probably not the pentacle of efficiency, so ideas for a more elegant solution are greatly appreciated :)

Jakub-CZ commented 3 years ago

https://packaging.python.org/discussions/wheel-vs-egg/

Wheel is superior. But you don't need to get into that too much. Both are just packaging standards. All you need to do is to install each package using pip - either from PyPI, or directly from source as I described.

If you do the editable/debug install (parameter -e) you can forget about wheels and eggs. It will just work.

As for the bid/ask data: I highly discourage you from trying to scrape the data from the UI. The UI is very dynamic, so Beautiful Soup will only see an almost empty page. You'd have to automate a full-blown browser instance with something like Selenium, and that's an overkill.

Our best bet is to find which API end-points Degiro uses to get the data. But that seems to be quite a challenge; see https://github.com/lolokraus/DegiroAPI/issues/6#issuecomment-653456750. I tried to find the source using Chrome DevTools, with no success. Apparently, it could be seen using tools like Wireshark but I haven't tried that myself.

BTW, are you sure the bid/ask data is so important to you? Aren't they delayed by 15-30 minutes anyway?

Jakub-CZ commented 3 years ago

P.S.: Do you know if retrieving the bid/ask works in the library that you linked (https://github.com/pladaria/degiro)? If is does, then we may be able to ~steal~ borrow the solution from here: https://github.com/pladaria/degiro/blob/b3fcb2ab12f02e5c74ac3db917c344806ba22ff9/src/index.js#L80-L162

korneel69 commented 3 years ago

Yep I installed the 2FA version. Works just perfect!

The bid and ask prices are real prices you can get for buying and selling a stock. The last trade price is just indicative in terms of the current bid and ask price. The current best bid or ask could be laying way above or below this price. btw they are real time.

Consider the liquidity of the stock. For liquid stocks (take Amazon) with tight spreads (0.09%), you can go off the last trade price and most of the time you will find a buyer/seller for your order. However, for less liquid stocks, with a bigger spread and not a deep orderbook you might overpay/get underpaid substantially. These profits go out of your pocket, into a market maker's.

Same occurs with big market events like covid and the vaccines (even liquid stocks become illiquid). So, if you want the BEST prices at ALL times, you should use current bid and ask prices.

It also allows you to easily develop your own market making or liquidity provider bot. Be it a naïve one :)

korneel69 commented 3 years ago

P.S.: Do you know if retrieving the bid/ask works in the library that you linked (https://github.com/pladaria/degiro)? If is does, then we may be able to ~steal~ borrow the solution from here: https://github.com/pladaria/degiro/blob/b3fcb2ab12f02e5c74ac3db917c344806ba22ff9/src/index.js#L80-L162

I dont know if it works. Looks fine. I kept away from Java for as long as I could. Seems the time has come to face the beast. Will look into it when i find the time

rob1181 commented 3 years ago

Getting Bid-/Ask-Data (on a near realtime basis), can be done. I did it the following way: First, collect all vwdIDs for the securities of interest (with the product_info() function of degiroapi) and put them into a list. Then I call the following method of my trader-class to subscribe for the Bid/Ask/Last-Data:

def get_vwd_session_and_initialise_data_request(self, listOfvwdIds):
        self.https_session = requests.Session()

        response = self.https_session.post(self.__VWD_SESSION_REQUEST_URL, params=self.vwd_parameters, data=self.vwd_payload, headers=self.vwd_headers)
        logger.info(response.text)
        self.vwd_session_id = response.json()['sessionId']

        request_string = ''
        for vwdId in listOfvwdIds:
            request_string = request_string + 'req({0}.LastPrice);req({0}.BidPrice);req({0}.AskPrice);req({0}.ClosePrice);req({0}.LastTime);req({0}.BidVolume);req({0}.AskVolume);req({0}.LastDate);'.format(vwdId)
        self.vwd_payload2 = '{{"controlData":"{0}"}}'.format(request_string)

        return self.https_session.post(self.__LATEST_PRICE_DATA_URL + self.vwd_session_id, data=self.vwd_payload2, headers=self.vwd_headers), self.vwd_session_id, self.vwd_payload2

After this call you can poll the requested information in an infinite loop with this code:

def get_exchange_data(self, vwdIds):
        new_tape_entry = {}

        try:
            response = self.https_session.get(self.__LATEST_PRICE_DATA_URL + self.vwd_session_id, headers=self.vwd_headers)

            for i in response.json():
                if i['m'] == 'a_req':
                    # save id for priceKey
                    self.data_keys[i['v'][1]] = [i['v'][0].split(".")[-1], vwdIds[i['v'][0].split(".")[0]]]
                if i['m'] == 'us' or i['m'] == 'un':
                    new_tape_entry[(self.data_keys[i['v'][0]][1], self.data_keys[i['v'][0]][0])] = i['v'][1]
        except:
            logger.warning('https_session.get() failed inside get_exchange_data')

        return new_tape_entry

This method was "borrowed" from the Degiro-website. They use a similar approach. There is no push-API available, but you can pull every second. For my trading strategies that's more than fast enough.

In general, I support the suggestion from Jakub-CZ to fork the project as the author is pretty unresponsive...

Chavithra commented 3 years ago

Hi, nice reverse engineering job,

If you are looking for a python library which handles real-time data, I have made one : https://github.com/Chavithra/degiro-connector

It is documented and I plan to maintain it for a while.

jernejg commented 3 years ago

There is now a new Degiro library every day :)

Stay safe guys, do a proper code base analysis before you pass your Degiro credentials to any library that is not your own.

korneel69 commented 3 years ago

Awesome! I have some troubles configuring @rob1181's solution for my own (I'm not that savvy). I'll definitely give @Chavithra's library a go.

Thanks for the contributions guys! :)

macd2 commented 3 years ago

There is now a new Degiro library every day :)

Stay safe guys, do a proper code base analysis before you pass your Degiro credentials to any library that is not your own.

what's your recommendation right now including 2FA and live Bid and ask?