henrydatei / wikifolio-api

A Python API-Wrapper for the unofficial wikifolio API
GNU General Public License v3.0
17 stars 4 forks source link

Wikifolio API - Portfolio #16

Closed JoeGithub53 closed 9 months ago

JoeGithub53 commented 9 months ago

Hi, is there a way to read the content of portfolio from a wikifolio ?. In the wikifolio.py I can't find any function which do this. Do you think to implement this ? thank you in advance! regards Josef

henrydatei commented 9 months ago

Currently there is no such way, but @apunkt made a pull requests (https://github.com/henrydatei/wikifolio-api/pull/15) for that. The PR has some problems with return types, so I didn't merge it. But since nothing has changed on that front and you asked I'll merge it and fix the return type by myself

henrydatei commented 9 months ago

Ok fixed it. You can now use it with

wf = Wikifolio("username", "password", "wikifolioID")
print(wf.get_portfolio_details())
JoeGithub53 commented 9 months ago

have tried it as follows:

from classes.wikifolio import Wikifolio

def main():

Replace with your actual email, password, and wikifolio ID

username = "myuserid"
password = "mypassword"
wikifolioID = "WF0HRO2015"

wf = Wikifolio("username", "password", "wikifolioID")
print(wf.get_portfolio_details())

if name == "main": main()

the results are following: S D:\Python_script_depot> python main.py Traceback (most recent call last): File "D:\Python_script_depot\main.py", line 19, in main() File "D:\Python_script_depot\main.py", line 10, in main wf = Wikifolio("username", "password", "wikifolioID") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\Python_script_depot\classes\wikifolio.py", line 38, in init r.raise_for_status() File "C:\Users\J-KBe\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\requests\models.py", line 1021, in raise_for_status raise HTTPError(http_error_msg, response=self) requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://www.wikifolio.com/api/login?country=de&language=de PS D:\Python_script_depot>

any ideas what could be wrong. is username the correct variable ? on my tests befor I used email and logon was successful.

apunkt commented 9 months ago

Hm, as username I also use email. I submit wikifolioID all lowercase. Have you tried wf0hro2015 ?

JoeGithub53 commented 9 months ago

from classes.wikifolio import Wikifolio

def main():

Replace with your actual email, password, and wikifolio ID

email = "myeMail@provider.de"
password = "mypassword"
wikifolio_id = "WF0HRO2015"

wf = Wikifolio(email, password, wikifolio_id)
print(wf.get_portfolio_details())

if name == "main": main() results now ok (you did a very good job!) [PortfolioDetail(name='UFP Technologies', isin='US9026731029', quantity=250.0, averagePurchasePrice=145.525904761905, ask=153.0, bid=148.0, close=150.0, percentage=0.06379077075071292, link='/de/de/s/us9026731029?wikifolio=wf0hro2015', openLinkInSameTab=True, issuer=None, mid=150.5, isLeveraged=False, isTicking=True, partnerName='aktienguide', isLtsuActive=False), PortfolioDetail(name='adesso', isin='DE000A0Z23Q5', quantity=260.0, averagePurchasePrice=119.243076923077, ask=102.8, bid=102.2, close=101.4, percentage=0.04581211784832281, link='/de/de/s/de000a0z23q5?wikifolio=wf0hro2015', openLinkInSameTab=True, issuer=None, mid=102.5, isLeveraged=False, isTicking=True, partnerName='aktienguide', isLtsuActive=False), ....

JoeGithub53 commented 9 months ago

currently(30.9.2023, 16:59h) I get following error: HTTPError: 400 Client Error: Bad Request for url: https://www.wikifolio.com/api/login?country=de&language=de when I try to signon (wf = Wikifolio(email, password, wikifolio_id) can you also try it, to findout if currently a server problem exists.

henrydatei commented 9 months ago

For me it works

JoeGithub53 commented 9 months ago

the problem was the variables email, password, wikfolio_id has to be changed to global variables. following I've created a script which formats the output from wf.get_portfolio_details() to my needs. If someone have also a need, please put it to your Wikifolio API members. Currently it has a little problem. Concatinate a pattern to output from {portfolio_details_str} first element would be printed double: provided_string = ("[PortfolioDetail(name='UFP Technologies', isin='US9026731029', " "quantity=250.0, averagePurchasePrice=145.525904761905, ask=153.0, " "bid=148.0, close=150.0, percentage=0.06379077075071292, " "link='/de/de/s/us9026731029?wikifolio=wf0hro2015', " f"PortfolioDetailDetails: {portfolio_details_str})]") if you have any idea to eliminate the first element from provided_string, please change my script. for me it is no problem, because I have also to delete duplicates in my excel sheet. thank you very much for your excellent work! regards Josef

import ast
import re
from classes.wikifolio import Wikifolio

# Define global variables
email = "my_eMail_id"
password = "my_password"
wikifolio_id = " "

# Auszuwertende Wikifolios in Liste
tabsels = [
    ("wf0hro2015", "wf00818181", "wfdmtrades", "wf00200775", "wf00hack42"),
    ("wfumbrella", "wf000mai05", "wf25061981", "wf0stwtech", "wf00smylel"),
]

def extract_portfolio_details(provided_string):
    # Define a regular expression pattern to extract the desired fields
    pattern = r"name='([^']+)', isin='([^']+)', .*?bid=([^,]+), .*?link='([^']+)'"

    # Find all matches of the pattern in the string
    matches = re.findall(pattern, provided_string)

    # Print the extracted information
    for match in matches:
        name, isin, bid, link = match
        print(f"Name:; {name} ISIN:; {isin}; Bid:; {bid}; https://www.wikifolio.com{link}")

if __name__ == "__main__":

    print("Start main for wikifolio_id", wikifolio_id)

for group in tabsels:
    print("Processing group:")

    for wikifolio_id in group:
        #print(f"  Processing Wikifolio ID: {wikifolio_id}")

        # Speichere die Wikifolio-ID in einer Variable
        current_wikifolio_id = wikifolio_id

        # Hier ein einfaches Beispiel: Drucken der aktuellen Wikifolio-ID
        #print(f"  Current Wikifolio ID: {current_wikifolio_id}")

        # Assuming you have a Wikifolio instance created, replace this with your actual object creation
        # For example:
        wf = Wikifolio(email, password, wikifolio_id)

        # Get the portfolio details and convert them to a string
        portfolio_details_str = str(wf.get_portfolio_details())

        # Corrected provided_string to match the format
        provided_string = ("[PortfolioDetail(name='UFP Technologies', isin='US9026731029', "
                          "quantity=250.0, averagePurchasePrice=145.525904761905, ask=153.0, "
                          "bid=148.0, close=150.0, percentage=0.06379077075071292, "
                          "link='/de/de/s/us9026731029?wikifolio=wf0hro2015', "
                          f"PortfolioDetailDetails: {portfolio_details_str})]")

        # Extract portfolio details
        extract_portfolio_details(provided_string)

Output: Name:; UFP Technologies ISIN:; US9026731029; Bid:; 148.0; https://www.wikifolio.com/de/de/s/us9026731029?wikifolio=wf0hro2015 Name:; UFP Technologies ISIN:; US9026731029; Bid:; 151.0; https://www.wikifolio.com/de/de/s/us9026731029?wikifolio=wf0hro2015 .......

henrydatei commented 9 months ago

The key thing when working with classes is to make it easy to interact with them and not doing complex Regex matching. For example your code could be (not tested, just written here):

from wikifolio import Wikifolio

email = "my_eMail_id"
password = "my_password"

# Auszuwertende Wikifolios in Liste
tabsels = ["wf0hro2015", "wf00818181", "wfdmtrades", "wf00200775", "wf00hack42", "wfumbrella", "wf000mai05", "wf25061981", "wf0stwtech", "wf00smylel"]

for wikifolioID in tabsels:
    wf = Wikifolio(email, password, wikifolioID)
    portfolio_details = wf.get_portfolio_details()
    for detail in portfolio_details:
        print(f"Name:; {detail.name} ISIN:; {detail.isin}; Bid:; {detail.bid}; https://www.wikifolio.com{detail.link}")

And two remarks: You can format code and make it better readable by using tripple backticks

```python
code

And for new questons please make a new issue every time so that nothing gets mixed. This issue started with a feature request, than some questions about login problems and now about coding questions. Making 3 issues out of that would be better I think.
JoeGithub53 commented 9 months ago

thank you very much for this excellent solution! I've tried it and it works very fine. Next I'll try to by and sell share with your wikifolio-Api. Can you give me please a sample for buy, sell ?.

henrydatei commented 9 months ago

I assume you want to make a limit order (technically you can also make a quote order with buy_quote and sell_quote but this type of order is somehow unstable and is not executed via this API). This code is not tested too, I'm writing this on my smartphone right now:

wf = Wikifolio("email", "password", "wikifolioID")
wf.buy_limit(amount=1, isin="US0378331005", limit_price=170) # buy 1 apple share, order is valid for 1 day
# You should wait until your order is executed before selling the share again
wf.sell_limit(amount=1, isin="US0378331005", limit_price=160) # sell 1 apple share, order is valid for 1 day