Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function egg, 2FA, bidprices #26

Open
korneel69 opened this issue Dec 6, 2020 · 12 comments
Open

Function egg, 2FA, bidprices #26

korneel69 opened this issue Dec 6, 2020 · 12 comments

Comments

@korneel69
Copy link

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
Copy link
Author

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

@korneel69 korneel69 changed the title Function egg Function egg, 2FA, bidprices Dec 6, 2020
@Jakub-CZ
Copy link

Jakub-CZ commented Dec 6, 2020

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
Copy link
Author

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
Copy link

Jakub-CZ commented Dec 7, 2020

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 #6 (comment). 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
Copy link

Jakub-CZ commented Dec 7, 2020

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
Copy link
Author

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
Copy link
Author

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
Copy link

rob1181 commented Dec 31, 2020

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
Copy link

Chavithra commented Jan 3, 2021

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
Copy link

jernejg commented Jan 3, 2021

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
Copy link
Author

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
Copy link

macd2 commented Feb 8, 2021

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants